Sub LightOn
For i = 8 To 12
shape[i]["bc"] = "#FFFF66"
EndFor
EndSub
Sub OnButtonClicked
If sbd Or silverlight Then
buttonClicked = "True"
Else
TrickOrTreat()
EndIf
EndSub
Sub OnTick
Timer.Pause()
For i = 1 To 9
bat[i]["cycle"] = bat[i]["cycle"] + 1
If 8 < bat[i]["cycle"] Then
bat[i]["cycle"] = 1
EndIf
bat[i]["x"] = bat[i]["x"] + Math.GetRandomNumber(7) - 4
If bat[i]["x"] < 0 Then
bat[i]["x"] = 0
ElseIf (gw - ow) < bat[i]["x"] Then
bat[i]["x"] = gw - ow
EndIf
bat[i]["y"] = bat[i]["y"] + Math.GetRandomNumber(17) - 9
If bat[i]["y"] < 0 Then
bat[i]["y"] = 0
ElseIf (gh - 110 - oh) < bat[i]["y"] Then
bat[i]["y"] = gh - 110 - oh
EndIf
bat[i]["angle"] = bat[i]["angle"] + Math.GetRandomNumber(7) - 4
If bat[i]["angle"] < -10 Then
bat[i]["angle"] = -10
ElseIf 10 < bat[i]["angle"] Then
bat[i]["angle"] = 10
EndIf
If bat[i]["cycle"] < 4 Then
Shapes.HideShape(bat[i]["close"])
Shapes.Move(bat[i]["open"], bat[i]["x"], bat[i]["y"])
Shapes.Rotate(bat[i]["open"], bat[i]["angle"])
Shapes.ShowShape(bat[i]["open"])
Else
Shapes.HideShape(bat[i]["open"])
Shapes.Move(bat[i]["close"], bat[i]["x"], bat[i]["y"])
Shapes.Rotate(bat[i]["close"], bat[i]["angle"])
Shapes.ShowShape(bat[i]["close"])
EndIf
EndFor
Timer.Resume()
EndSub
Sub TrickOrTreat
i = nSprite
Sprite_Remove()
Controls.Remove(trick)
Shapes.Remove(orText)
Controls.Remove(treat)
GraphicsWindow.FontSize = 40
If Controls.LastClickedButton = trick Then
GraphicsWindow.BackgroundColor = "Indigo"
' draw moon
GraphicsWindow.BrushColor = "White"
size = 100
x = gw - size - 10
y = 10
GraphicsWindow.FillEllipse(x, y, size, size)
' draw ground
GraphicsWindow.BrushColor = "Black"
GraphicsWindow.FillRectangle(0, gh * 0.6, gw, gh * 0.4)
' draw tree
DrawTree()
' draw Jack-o'-lanterns
LightOn()
scale = (gw / 6) * 0.6 / spr["width"]
xl = spr["width"] * scale * 0.2
dx = gw / 6
y = gh * 0.6 - spr["height"] * scale / 2
For i = 1 To 6
name = "Jack" + i
Sprite_Add()
x = xl + (i - 1) * dx
Sprite_Move()
EndFor
' draw caption
GraphicsWindow.BrushColor = "Orange"
halloween = Shapes.AddText("Happy Halloween " + year)
x = 10
y = 10
Shapes.Move(halloween, x, y)
' draw bats
oImg = "http://www.nonkit.com/smallbasic.files/OpenBat.png"
If silverlight Then
Program.Delay(msWait)
EndIf
ow = 63
oh = 30
cImg = "http://www.nonkit.com/smallbasic.files/CloseBat.png"
cw = 26
ch = 26
For i = 1 To 9
bat[i]["open"] = Shapes.AddImage(oImg)
bat[i]["close"] = Shapes.AddImage(cImg)
bat[i]["cycle"] = Math.GetRandomNumber(4)
bat[i]["x"] = Math.GetRandomNumber(gw - ow)
bat[i]["y"] = Math.GetRandomNumber(gh * 0.6 - oh)
bat[i]["angle"] = Math.GetRandomNumber(21) - 11
EndFor
Program.Delay(500)
Timer.Interval = 1000 / 20
Timer.Tick = OnTick
Else
GraphicsWindow.BackgroundColor = "Orange"
url = "http://www.nonkit.com/smallbasic.files/Candy1.png"
candy1 = Shapes.AddImage(url)
If silverlight Then
Program.Delay(msWait)
EndIf
cw = 197
ch = 376
x = (gw - cw) / 2 - 200
y = (gh - ch) / 2
Shapes.Move(candy1, x, y)
Shapes.Rotate(candy1, -10)
url = "http://www.nonkit.com/smallbasic.files/Candy2.png"
candy2 = Shapes.AddImage(url)
x = (gw - cw) / 2
Shapes.Move(candy2, x, y)
x = (gw - cw) / 2 + 200
url = "http://www.nonkit.com/smallbasic.files/Candy3.png"
candy3 = Shapes.AddImage(url)
If silverlight Then
Program.Delay(msWait)
EndIf
Shapes.Move(candy3, x, y)
Shapes.Rotate(candy3, 10)
GraphicsWindow.BrushColor = "Black"
halloween = Shapes.AddText("Happy Halloween " + year)
x = 10
y = 10
Shapes.Move(halloween, x, y)
EndIf
If "False" Then
OnTick = 1
EndIf
EndSub
Sub Math_CartesianToPolar
' Math | convert cartesian coodinate to polar coordinate
' param x, y - cartesian coordinate
' return r, a - polar coordinate
r = Math.SquareRoot(x * x + y * y)
If x = 0 And y > 0 Then
a = 90 ' [degree]
ElseIf x = 0 And y < 0 Then
a = -90
Else
a = Math.ArcTan(y / x) * 180 / Math.Pi
EndIf
If x < 0 Then
a = a + 180
ElseIf x > 0 And y < 0 Then
a = a + 360
EndIf
EndSub
Sub SB_LineWorkaround
' Small Basic | line rotate workaround for SBD
' param x, y - coordinate of the position of the line
' param x1, y1 - coordinate of the first point
' param x2, y2 - coordinate of the second point
' param pw - pen width
' param alpha - to rotate [degree]
' return x, y - workaround value for the coordinate
Stack.PushValue("local", x)
Stack.PushValue("local", y)
x = x1 - x2
y = y1 - y2
Math_CartesianToPolar()
y = Stack.PopValue("local")
x = Stack.PopValue("local")
_a = Math.GetRadians(a)
_alpha = Math.GetRadians(a - alpha)
Δx = pw / 4 * (Math.Sin(_alpha) - Math.Sin(_a))
Δy = pw / 4 * (Math.Cos(_alpha) - Math.Cos(_a))
x = x - Δx
y = y - Δy
EndSub
Sub SB_RotateWorkaround
' Small Basic | rotate workaround for Silverlight
' param shp - current shape
' param x, y - original coordinate
' param _alpha - angle [radian]
' returns x, y - workaround coordinate
If shp["func"] = "tri" Then
x1 = -Math.Floor(shp["x3"] / 2)
y1 = -Math.Floor(shp["y3"] / 2)
ElseIf shp["func"] = "line" Then
x1 = -Math.Floor(Math.Abs(shp["x1"] - shp["x2"]) / 2)
y1 = -Math.Floor(Math.Abs(shp["y1"] - shp["y2"]) / 2)
EndIf
ox = x - x1
oy = y - y1
x = x1 * Math.Cos(_alpha) - y1 * Math.Sin(_alpha) + ox
y = x1 * Math.Sin(_alpha) + y1 * Math.Cos(_alpha) + oy
EndSub
Sub SB_Workaround
' Small Basic | workaround for Silverlight / SBD
' return silverlight - "True" if in remote
' return sbd - "True" if Small Basic Desktop
_gw = GraphicsWindow.Width
_gh = GraphicsWindow.Height
silverlight = "False"
sbd = "False"
If (_gw = 640) And (_gh = 480) Then
silverlight = "True"
msWait = 300
ElseIf (_gw = 624) And (_gh = 441) Then
sbd = "True"
EndIf
EndSub
Sub SBO_SplitParam
' Small Basic Online | split "index=value;" format as an array param
' param param[] - to split
' return param[] - split
_param = ""
p = 1
len = Text.GetLength(param)
While p <= len
eq = Text.GetIndexOf(Text.GetSubTextToEnd(param, p), "=")
sc = Text.GetIndexOf(Text.GetSubTextToEnd(param, p), ";")
name = Text.GetSubText(param, p, eq - 1)
value = Text.GetSubText(param, p + eq, sc - eq - 1)
_param[name] = value
p = p + sc
EndWhile
param = _param
EndSub
Sub SBO_SplitShape
' Small Basic Online | split "index=value;" format as a jagged array shape
' param shape[] - to split
' return shape[] - split
arry = shape
n = Array.GetItemCount(arry)
For i = 1 To n
param = arry[i]
SBO_SplitParam()
arry[i] = param
EndFor
shape = arry
EndSub
Sub Shapes_CalcRotateZoomPos
' Shapes | calculate position for rotated and zoomed shape
' param["x"], param["y"] - position of a shape
' param["width"], param["height"] - size of a shape
' param ["cx"], param["cy"] - center of rotation
' param ["angle"] - rotate angle
' param ["scale"] - zoom scale
' return x, y - rotated position of a shape
_cx = param["x"] + param["width"] / 2
_cy = param["y"] + param["height"] / 2
x = _cx - param["cx"]
y = _cy - param["cy"]
Math_CartesianToPolar()
a = a + param["angle"]
x = r * Math.Cos(a * Math.Pi / 180) * param["scale"]
y = r * Math.Sin(a * Math.Pi / 180) * param["scale"]
_cx = x + param["cx"]
_cy = y + param["cy"]
x = _cx - param["width"] / 2
y = _cy - param["height"] / 2
EndSub
Sub Shapes_CalcWidthAndHeight
' Shapes | calculate total width and height of shapes
' param shape[] - shape array
' return shWidth, shHeight - total size of shapes
For i = 1 To Array.GetItemCount(shape)
shp = shape[i]
If shp["func"] = "tri" Or shp["func"] = "line" Then
xmin = shp["x1"]
xmax = shp["x1"]
ymin = shp["y1"]
ymax = shp["y1"]
If shp["x2"] < xmin Then
xmin = shp["x2"]
EndIf
If xmax < shp["x2"] Then
xmax = shp["x2"]
EndIf
If shp["y2"] < ymin Then
ymin = shp["y2"]
EndIf
If ymax < shp["y2"] Then
ymax = shp["y2"]
EndIf
If shp["func"] = "tri" Then
If shp["x3"] < xmin Then
xmin = shp["x3"]
EndIf
If xmax < shp["x3"] Then
xmax = shp["x3"]
EndIf
If shp["y3"] < ymin Then
ymin = shp["y3"]
EndIf
If ymax < shp["y3"] Then
ymax = shp["y3"]
EndIf
EndIf
shp["width"] = xmax - xmin
shp["height"] = ymax - ymin
EndIf
If i = 1 Then
shWidth = shp["x"] + shp["width"]
shHeight = shp["y"] + shp["height"]
Else
If shWidth < shp["x"] + shp["width"] Then
shWidth = shp["x"] + shp["width"]
EndIf
If shHeight < shp["y"] + shp["height"] Then
shHeight = shp["y"] + shp["height"]
EndIf
EndIf
shape[i] = shp
EndFor
EndSub
Sub Sprite_Add
' Sprite | add shapes to a sprite
' param name - sprite name
' param shX, shY - origin of shape array
' param scale - to resize
' param shape[] - shape array
' param nSprite - number of sprite
' return nSprite - updated number of sprite
' return sprite[] - sprite array
Stack.PushValue("local", i)
Stack.PushValue("local", x)
Stack.PushValue("local", y)
nSprite = nSprite + 1
spr = ""
spr["name"] = name
spr["x"] = shX
spr["y"] = shY
spr["angle"] = 0
spr["dir"] = 1
Shapes_CalcWidthAndHeight()
spr["width"] = shWidth
spr["height"] = shHeight
spr["cx"] = shWidth / 2
spr["cy"] = shHeight / 2
If scale = "" Then
scale = 1
EndIf
s = scale
spr["scale"] = s
For i = 1 To Array.GetItemCount(shape)
shp = shape[i]
GraphicsWindow.PenWidth = shp["pw"] * s
If shp["pw"] > 0 Then
GraphicsWindow.PenColor = shp["pc"]
EndIf
If Text.IsSubText("rect|ell|tri|text|btn", shp["func"]) Then
GraphicsWindow.BrushColor = shp["bc"]
EndIf
If Text.IsSubText("text|btn", shp["func"]) Then
If silverlight Then
fs = Math.Floor(shp["fs"] * 0.9)
Else
fs = shp["fs"]
EndIf
GraphicsWindow.FontSize = fs * s
GraphicsWindow.FontName = shp["fn"]
If shp["fb"] = "False" Then
GraphicsWindow.FontBold = "False"
Else
GraphicsWindow.FontBold = "True"
EndIf
EndIf
If shp["func"] = "rect" Then
shp["obj"] = Shapes.AddRectangle(shp["width"] * s, shp["height"] * s)
ElseIf shp["func"] = "ell" Then
shp["obj"] = Shapes.AddEllipse(shp["width"] * s, shp["height"] * s)
ElseIf shp["func"] = "tri" Then
shp["obj"] = Shapes.AddTriangle(shp["x1"] * s, shp["y1"] * s, shp["x2"] * s, shp["y2"] * s, shp["x3"] * s, shp["y3"] * s)
ElseIf shp["func"] = "line" Then
shp["obj"] = Shapes.AddLine(shp["x1"] * s, shp["y1"] * s, shp["x2"] * s, shp["y2"] * s)
ElseIf shp["func"] = "text" Then
shp["obj"] = Shapes.AddText(shp["text"])
EndIf
x = shp["x"]
y = shp["y"]
shp["rx"] = x
shp["ry"] = y
If sbd And (shp["func"] = "line") Then
shp["wx"] = x
shp["wy"] = y
ElseIf silverlight And Text.IsSubText("tri|line", shp["func"]) Then
_alpha = Math.GetRadians(shp["angle"])
SB_RotateWorkaround()
shp["wx"] = x
shp["wy"] = y
EndIf
If shp["func"] = "btn" Then
shp["obj"] = Controls.AddButton(shp["caption"], shX + x * s, shY + y * s)
Else
Shapes.Move(shp["obj"], shX + x * s, shY + y * s)
EndIf
If Text.IsSubText("rect|ell|tri|text", shp["func"]) And (shp["angle"] <> 0) And (shp["angle"] <> "") Then
Shapes.Rotate(shp["obj"], shp["angle"])
EndIf
shape[i] = shp
EndFor
spr["shape"] = shape
sprite[nSprite] = spr
y = Stack.PopValue("local")
x = Stack.PopValue("local")
i = Stack.PopValue("local")
EndSub
Sub Sprite_Move
' Sprite | move a sprite
' param sprite[i] - sprite to move
' param x, y - position to move
' return sprite[i] - updated sprite
Stack.PushValue("local", j)
spr = sprite[i]
s = spr["scale"]
spr["x"] = x
spr["y"] = y
shape = spr["shape"]
n = Array.GetItemCount(shape)
For j = 1 To n
shp = shape[j]
If sbd And (shp["func"] = "line") Then
_x = shp["wx"]
_y = shp["wy"]
ElseIf silverlight And Text.IsSubText("tri|line", shp["func"]) Then
_x = shp["wx"]
_y = shp["wy"]
Else
_x = shp["rx"]
_y = shp["ry"]
EndIf
Shapes.Move(shp["obj"], spr["x"] + _x * s, spr["y"] + _y * s)
EndFor
sprite[i] = spr
j = Stack.PopValue("local")
EndSub
Sub Sprite_Remove
' Sprite | remove a sprite
' param sprite[i] - sprite to remove
' return nSprite - updated number of sprites
If (0 < i) And (i <= nSprite) Then
spr = sprite[i]
shape = spr["shape"]
For _i = 1 To Array.GetItemCount(shape)
Shapes.Remove(shape[_i]["obj"])
EndFor
For _i = i + 1 To nSprite
sprite[_i - 1] = sprite[_i]
EndFor
nSprite = nSprite - 1
EndIf
EndSub
Sub Sprite_Rotate
' Sprite | rotate a sprite
' param sprite[i] - sprite to rotate
' param cx, cy - rotation center (if given)
' param angle - to rotate
Stack.PushValue("local", x)
Stack.PushValue("local", y)
Stack.PushValue("local", n)
spr = sprite[i]
shape = spr["shape"]
moved = "False"
If cx <> "" Then
moved = "True"
Else
cx = "" ' to avoid syntax error
EndIf
If cy <> "" Then
moved = "True"
Else
cy = "" ' to avoid syntax error
EndIf
s = spr["scale"]
If moved Then
param["cx"] = (cx - spr["x"]) / s
param["cy"] = (cy - spr["y"]) / s
Else
param["cx"] = spr["width"] / 2
param["cy"] = spr["height"] / 2
EndIf
param["scale"] = 1
spr["angle"] = angle
param["angle"] = spr["angle"]
n = Array.GetItemCount(shape)
Stack.PushValue("local", i)
For i = 1 To n
shp = shape[i]
param["x"] = shp["x"]
param["y"] = shp["y"]
param["width"] = shp["width"]
param["height"] = shp["height"]
Shapes_CalcRotateZoomPos()
shp["rx"] = x
shp["ry"] = y
alpha = shp["angle"] + spr["angle"]
If sbd And (shp["func"] = "line") And (alpha <> 0) Then
x1 = shp["x1"]
y1 = shp["y1"]
x2 = shp["x2"]
y2 = shp["y2"]
pw = shp["pw"]
SB_LineWorkaround()
shp["wx"] = x
shp["wy"] = y
ElseIf silverlight And Text.IsSubText("tri|line", shp["func"]) Then
_alpha = Math.GetRadians(alpha)
SB_RotateWorkaround()
shp["wx"] = x
shp["wy"] = y
EndIf
Shapes.Move(shp["obj"], spr["x"] + x * s, spr["y"] + y * s)
Shapes.Rotate(shp["obj"], shp["angle"] + spr["angle"])
shape[i] = shp
EndFor
i = Stack.PopValue("local")
spr["shape"] = shape
sprite[i] = spr
n = Stack.PopValue("local")
y = Stack.PopValue("local")
x = Stack.PopValue("local")
EndSub