Code: Select all
Type int2d
Dim As Integer x,y
Declare Constructor
Declare Constructor(x As Integer, y As Integer)
Declare Operator Cast () As String
End Type
Constructor int2d
End Constructor
Constructor int2d(x As Integer, y As Integer)
This.x = x : This.y = y
End Constructor
' "x, y"
Operator int2d.cast () As String
Return Str(x) & "," & Str(y)
End Operator
Operator + (a As int2d, b As int2d) As int2d
Return Type(a.x + b.x, a.y + b.y)
End Operator
'===============================================================================
#Include "fbgfx.bi"
#IfNDef int2d
Type int2d
Dim As Integer x, y
End Type
#EndIf
'triangle drawing routing, single color
'modified & stolen from D.J.Peters?
#Define SHIFTS 8 ' 24:8 fixed point format
Sub triangle(p() As int2d, c As ULong, pImg As ULong Ptr = 0)
Dim As Integer t = Any, b = Any, l = Any, r = Any
Dim As Integer d1 = Any, d2 = Any, s1 = Any, s2 = Any, cl = Any, cr = Any
Dim As ULong Ptr pPix, pRow = Any, pCstart = Any, pCend = Any
Dim As int2d v0 = Any, v1 = Any, v2 = Any
Dim As Integer w, h
If pImg = 0 Then
pPix = ScreenPtr()
ScreenInfo w, h
Else
'todo: ImageInfo( image [, [width] [, [height] [, [bypp] [, [pitch] [, [pixdata] [, size]]]]]] )
'imageInfo w, h, , pitch, pPix
End If
v0 = p(0) : v1 = p(1) : v2 = p(2)
If (v1.y > v2.y) Then Swap v1, v2
If (v0.y > v2.y) Then Swap v0, v2
If (v0.y > v1.y) Then Swap v0, v1
If (v2.y = v0.y) Then Return
s1 = ((v2.x - v0.x) ShL SHIFTS) / (v2.y - v0.y)
d1 = v0.x ShL SHIFTS
For i As Integer = 0 To 1
s2 = ((v1.x - v0.x) ShL SHIFTS) / (v1.y - v0.y)
d2 = v0.x ShL SHIFTS
t = v0.y 'top
'begin in first row
If t < 0 Then
d1 -= s1 * t
d2 -= s2 * t
t = 0
End If
b = v1.y 'bottom
'end in last row
If b >= h Then b = h - 1
If b <= t Then GoTo next_triangle
pRow = pPix + t * w 'first row
b -= t 'how many scanlines
'from top to bottom
While b
l = d1 ShR SHIFTS : r = d2 ShR SHIFTS
If l > r Then Swap l, r
If l >= w Then GoTo next_scanline
If r < 1 Then GoTo next_scanline
cl = 0 : cr = 0 'reset clipflag
If l < 0 Then l = 0 : cl = 1
If r >= w Then r = w : cr = 1
pCstart = pRow + l 'first pixel
pCend = pRow + r 'last pixel
While pCstart < pCend
*pCstart = c
pCstart += 1
Wend
next_scanline:
d1 += s1 : d2 += s2 : pRow += w : b-=1
Wend
next_triangle:
d1 = (v0.x ShL SHIFTS) + ((v1.y - v0.y) * s1)
v0 = v1 : v1 = v2
Next
End Sub
Sub quad(p() As int2d, c As ULong, pImg As ULong Ptr = 0)
Static As int2d t1(2), t2(2)
t1(0) = p(0) : t1(1) = p(1) : t1(2) = p(2)
t2(0) = p(3) : t2(1) = p(1) : t2(2) = p(2)
triangle(t1(), c, pImg)
triangle(t2(), c, pImg)
End Sub
'===============================================================================
Const As Single M_PI = Atn(1) * 4
Const As Single M_PI_2 = M_PI * 2
Const As Single M_PI_HALF = M_PI / 2
Const As Single M_RAD = 180 / M_PI
#Define rndrange(a, b) ( Rnd() * (b - a) + a )
Const SW = 800, SH = 600
'-------------------------------------------------------------------------------
Function rotate(v1 As int2d, angle As Single) As int2d
Dim As int2d v2 = Any
v2.x = v1.x * Cos(angle)
v2.x += v1.y * Cos(angle - M_PI_HALF)
v2.y = v1.x * Sin(angle)
v2.y += v1.y * Sin(angle - M_PI_HALF)
Return v2
End Function
Sub drawRect(x As Integer, y As Integer, w As Integer, h As Integer, angle As Single, c As ULong)
Dim As int2d q(0 To 3)
q(0).x = -w \ 2 : q(0).y = -h \ 2
q(1).x = w \ 2 : q(1).y = -h \ 2
q(2).x = -w \ 2 : q(2).y = h \ 2
q(3).x = w \ 2 : q(3).y = h \ 2
For i As Integer = 0 To 3
q(i) = rotate(q(i), angle)
q(i).x += x
q(i).y += y
Next
quad(q(), c)
End Sub
Sub drawScene()
'draw grass
Line(0, SH * 0.75)-(SW - 1, SH - 1), &h00A000, bf
'draw fence pole grass
Circle(SW * 0.49, SH * 0.78), 20, &h209000,,,0.25, f
Circle(SW * 0.60, SH * 0.795), 20, &h209030,,,0.25, f
Circle(SW * 0.70, SH * 0.805), 20, &h209020,,,0.25, f
Circle(SW * 0.805, SH * 0.78), 20, &h209000,,,0.25, f
'draw fence poles
drawRect(SW * 0.50, SH * 0.72, 15, 75, +0.07, &h705000)
drawRect(SW * 0.60, SH * 0.73, 15, 80, 0.05, &h805000)
drawRect(SW * 0.70, SH * 0.74, 15, 80, -0.02, &h906000)
drawRect(SW * 0.80, SH * 0.72, 15, 70, -0.13, &h906030)
'draw fence planks
drawRect(SW * 0.55, SH * 0.69, 100, 20, 0.15, &h703000)
drawRect(SW * 0.65, SH * 0.69, 100, 20, 0.1, &h804000)
drawRect(SW * 0.75, SH * 0.70, 100, 20, -0.18, &h704030)
'draw house grass
Circle(SW * 0.25, SH * 0.82), 120, &h209000,,,0.25, f
'draw house chimney
drawRect(SW * 0.20, SH * 0.58, 40, 40, 0, &h800020)
'draw house roof
drawRect(SW * 0.25, SH * 0.66, 130, 130, 45 / M_RAD, &h900020)
'draw house base
drawRect(SW * 0.25, SH * 0.75, 160, 100, 0, &hA00020)
drawRect(SW * 0.25, SH * 0.665, 170, 4, 0, &h702020)
'draw house lower window
drawRect(SW * 0.29, SH * 0.75, 42, 52, 0, &h603010)
drawRect(SW * 0.29, SH * 0.75, 30, 40, 0, &hC0a000)
drawRect(SW * 0.29, SH * 0.75, 30, 6, 0, &h603000)
drawRect(SW * 0.29, SH * 0.75, 6, 40, 0, &h603000)
'draw house upper window
' circle(SW * 0.25, SH * 0.60), 15, &h603000,,,, f
' circle(SW * 0.25, SH * 0.60), 10, &hC0a000,,,, f
'draw house door
drawRect(SW * 0.21, SH * 0.77, 38, 66, 0, &h603020)
drawRect(SW * 0.21, SH * 0.77, 28, 56, 0, &h804030)
'draw snow man (base, body, head, nose, hat)
'draw trees
'draw mountains
'draw pond
End Sub
'-------------------------------------------------------------------------------
Type simple_list_type
'private:
Dim As int2d item(Any)
Dim As Integer numItems
'public:
Declare Constructor(size As Integer)
Declare Destructor()
Declare Function Add(newItem As int2d) As boolean
Declare Sub del(index As Integer)
End Type
Constructor simple_list_type(size As Integer)
ReDim item(size - 1)
numItems = 0
End Constructor
Destructor simple_list_type()
Erase(item)
numItems = 0
End Destructor
Function simple_list_type.add(newItem As int2d) As boolean
Dim As Integer ub = UBound(item)
If numItems > ub Then
Return false 'list is full
Else
item(numItems) = newItem
numItems += 1
Return true 'ok
End If
End Function
Sub simple_list_type.del(index As Integer)
item(index) = item(numItems - 1) 'move last items into place
numItems -= 1
End Sub
'-------------------------------------------------------------------------------
Sub addFlakes(snowflakes As simple_list_type, maxAdd As Integer)
Dim As Integer x, y
For i As Integer = 0 To maxAdd - 1
x = Int(rndRange(-0.5 * SW, +1.5 * SW))
y = Int(rndRange(-100, 0))
If snowflakes.add(int2d(x, y)) = false Then Exit For
Next
End Sub
ScreenRes SW, SH, 32, 1
Width SW \ 8, SH \ 16
Var snowflakes = simple_list_type(10000)
Dim As String key
Dim As Integer loopCount = 0, incFlakes = 1
Dim As fb.image Ptr pScene = ImageCreate(SW, SH)
drawScene()
Get(0, 0)-(SW - 1, SH - 1), pScene
While key = ""
ScreenLock()
Put (0, 0), pScene, PSet
'draw snowflakes
For i As Integer = 0 To snowflakes.numItems - 1
PSet(snowflakes.item(i).x, snowflakes.item(i).y), &hffffff
Next
Draw String(0, 0), Str(snowflakes.numItems), &hb0b000
ScreenUnLock()
Sleep(10)
key = InKey()
'update snowflakes
For i As Integer = 0 To snowflakes.numItems - 1
snowflakes.item(i).y += 2
If snowflakes.item(i).y > SH Then
snowflakes.del(i)
Continue For
End If
snowflakes.item(i).x += CInt(Rnd * 3 - 0.7)
Next
loopCount += 1
If incFlakes < 10 Then
If loopCount Mod 200 = 0 Then incFlakes += 1
End If
addFlakes(snowFlakes, incFlakes)
Wend
'get background screen