Microsoft Small Basic

Program Listing: XXV038-3
' Car Graphics 1.0b
' Copyright © 2014-2016 Filipe Cardoso Martins and Nonki Takahashi. The MIT Lisence.
'
' History:
' 1.0 2016-07-06 Change roads as a quiz. (XXV038-3)
' 0.9 2016-06-17 Added roads. (XXV038-2)
' 0.8 2015-12-07 Design changed by Filipe. Command shortened. (XXV038-1)
' 0.7 2015-08-15 Bug fixed. (XXV038-0)
' 0.6 2015-08-12 Created from Turtle Graphics 0.5b. (XXV038)
' 0.5 2015-04-13 Supported skip opening and nested REPEAT. (XVK119-3)
' 0.4 2015-04-09 Added REPEAT command. (XVK119-2)
' 0.3 2015-04-06 Changed for Challenge of the Month - April 2014. (XVK119-1)
' 0.2 2014-03-21 Adopted to remote. (XVK119-0)
' 0.1 2014-03-20 Created. (XVK119)
'
GraphicsWindow.Title = "Car Graphics 1.0b"
Init()
Opening()
onRoad = "False"
Main()
hE = 100
wE = 100
Sub Main
Config()
GraphicsWindow.BrushColor = "Chartreuse"
GraphicsWindow.FontSize = 20
pgm = Controls.AddMultiLineTextBox(20, 20)
Controls.SetSize(pgm, 180, gh - 80)
src = sample
Controls.SetTextBoxText(pgm, src)
GraphicsWindow.BrushColor = "DarkOrange"
Controls.AddButton("RUN", 20, gh - 55)
clicked = "False"
Controls.ButtonClicked = OnButtonClicked
AT_Init()
GraphicsWindow.PenWidth = 0
GraphicsWindow.BrushColor = "Black"
mask = Shapes.AddRectangle(gw, gh)
Shapes.SetOpacity(mask, 0)
Shapes.HideShape(mask)
AT_Show()
x = 250
y = 275
AT_MoveTo()
angle = 90
AT_SetAngle()
DrawRoads()
onRoad = "True"
GraphicsWindow.PenColor = "DeepSkyBlue"
GraphicsWindow.PenWidth = 2
While "True"
If clicked Then
src = Controls.GetTextBoxText(pgm)
Run()
clicked = "False"
Else
Program.Delay(500)
EndIf
EndWhile
EndSub
Sub Config
gw = 800
gh = 550
GraphicsWindow.Height = gh
GraphicsWindow.Width = gw

GraphicsWindow.BackgroundColor= "DodgerBlue"
GraphicsWindow.BrushColor= GraphicsWindow.GetColorFromRGB (255, 255, 255)
GraphicsWindow.FillRectangle (10, 10, 780, 530)
GraphicsWindow.BrushColor= GraphicsWindow.GetColorFromRGB (0, 0, 0)
GraphicsWindow.FillRectangle (15, 15, 770, 520)
GraphicsWindow.BrushColor= GraphicsWindow.GetColorFromRGB (255, 255, 255)
GraphicsWindow.FillRectangle (10, 10, 200, 530)
GraphicsWindow.BrushColor= GraphicsWindow.GetColorFromRGB (0, 0, 0)
GraphicsWindow.FillRectangle (15, 15, 190, 520)
EndSub
Sub CONFIG2
GraphicsWindow.Height = hE
GraphicsWindow.Width = wE
EndSub
Sub criarEspaço
GraphicsWindow.Show()
CONFIG2()
EndSub
Sub CheckCrash
crash = "False"
If onRoad Then
color = GraphicsWindow.GetPixel(Math.Round(x), Math.Round(y))
If color <> "#333333" And color <> "#00BFFF" Then
crash = "True"
EndIf
EndIf
EndSub
Sub DrawBlow
' param x, y - position of the car
GraphicsWindow.BrushColor = "DarkOrange"
n = 7
For i = 1 To n
θ = Math.GetRadians((i - 1) * (360 / n))
x1 = x + 40 * Math.Cos(θ)
y1 = y - 40 * Math.Sin(θ)
x2 = x + 10 * Math.Cos(θ - Math.Pi / 2)
y2 = y - 10 * Math.Sin(θ - Math.Pi / 2)
x3 = x + 10 * Math.Cos(θ + Math.Pi / 2)
y3 = y - 10 * Math.Sin(θ + Math.Pi / 2)
GraphicsWindow.FillTriangle(x1, y1, x2, y2, x3, y3)
EndFor
EndSub
Sub DrawCross
' param x, y - position for the cross
GraphicsWindow.PenWidth = 4
GraphicsWindow.PenColor = "DarkOrange"
GraphicsWindow.DrawLine(x - 14, y - 14, x + 14, y + 14)
GraphicsWindow.DrawLine(x - 14, y + 14, x + 14, y - 14)
EndSub
Sub DrawRoads
' param AT_x, AT_y - position of the car
GraphicsWindow.PenColor = "#333333"
GraphicsWindow.PenWidth = 20
GraphicsWindow.DrawLine(AT_x - 10, AT_y, AT_x + 200, AT_y)
GraphicsWindow.DrawLine(AT_x + 300, AT_y, AT_x + 510, AT_y)
For x = AT_x + 100 To AT_x + 400 Step 100
GraphicsWindow.DrawLine(x, AT_y - 210, x, AT_y + 210)
EndFor
For y = AT_y - 200 To AT_y + 200 Step 100
If y <> AT_y Then
GraphicsWindow.DrawLine(AT_x + 100, y, AT_x + 410, y)
EndIf
EndFor
x = AT_x + 100
y = AT_y - 150
DrawCross()
x = AT_x + 150
y = AT_y + 100
DrawCross()
x = AT_x + 350
y = AT_y - 100
DrawCross()
x = AT_x + 350
y = AT_y + 200
DrawCross()
xGoal = Math.Round(AT_x) + 500
yGoal = Math.Round(AT_y)
EndSub
Sub OnButtonClicked
clicked = "True"
EndSub
Sub Run
SrcToLines()
l = 1 ' level
For i = 1 To nLines
DoLine()
If crash Then
Shapes.ShowShape(mask)
For op = 0 To 80 Step 4
Shapes.SetOpacity(mask, op)
Program.Delay(100)
EndFor
GraphicsWindow.BrushColor = "White"
GraphicsWindow.FontSize = 80
txtMsg = Shapes.AddText("GAME OVER")
Shapes.Move(txtMsg, 190, 220)
i = nLines ' exit For
EndIf
EndFor
If Math.Round(AT_x) = xGoal And Math.Round(AT_y) = yGoal Then
Sound.PlayBellRing()
Shapes.ShowShape(mask)
Shapes.SetOpacity(mask, 80)
GraphicsWindow.BrushColor = "White"
GraphicsWindow.FontSize = 80
txtMsg = Shapes.AddText("GOAL")
Shapes.Move(txtMsg, 310, 220)
ShowTickerTape()
Shapes.Remove(txtMsg)
Shapes.HideShape(mask)
EndIf
EndSub
Sub SrcToLines
p = 1
nLines = 0
pNewLine = Text.GetIndexOf(src, CR)
While 0 < pNewLine
nLines = nLines + 1
line[nLines] = Text.ConvertToUpperCase(Text.GetSubText(src, p, pNewLine - 1))
p = p + pNewLine
If Text.GetSubText(src, p, 1) = LF Then
p = p + 1
EndIf
pNewLine = Text.GetIndexOf(Text.GetSubTextToEnd(src, p), CR)
EndWhile
If p <= Text.GetLength(src) Then
nLines = nLines + 1
line[nLines] = Text.ConvertToUpperCase(Text.GetSubTextToEnd(src, p))
EndIf
EndSub
Sub DoLine
' param line - array of command lines
' param i - index to do for the line
If Text.StartsWith(line[i], "FD") Then
distance = Text.GetSubTextToEnd(line[i], 3)
AT_Move()
ElseIf Text.StartsWith(line[i], "PU") Then
AT_PenUp()
ElseIf Text.StartsWith(line[i], "PD") Then
AT_PenDown()
ElseIf Text.StartsWith(line[i], "RT") Then
angle = Text.GetSubTextToEnd(line[i], 3)
AT_Turn()
ElseIf Text.StartsWith(line[i], "LT") Then
angle = -Text.GetSubTextToEnd(line[i], 3)
AT_Turn()
ElseIf Text.StartsWith(line[i], "REPEAT") Then
b = Text.GetIndexOf(line[i], "[")
count[l] = Text.GetSubText(line[i], 7, b - 7)
iStart[l] = i + 1
iEnd[l] = nLines
nest = 0
For k = iStart[l] To nLines
If Text.StartsWith(line[k], "REPEAT") Then
nest = nest + 1
ElseIf Text.StartsWith(line[k], "]") Then
If nest = 0 Then
iEnd[l] = k - 1
k = nLines
Else
nest = nest - 1
EndIf
EndIf
EndFor
l = l + 1
For j = 1 To count[l - 1]
Stack.PushValue("local", j)
For i = iStart[l - 1] To iEnd[l - 1]
DoLine()
EndFor
j = Stack.PopValue("local")
EndFor
l = l - 1
i = iEnd[l] + 1
EndIf
EndSub
Sub Init
int = 500 ' interval time to synchronize with Silverlight
gw = 598
gh = 435
colors = "1=DarkOrange;2=Chartreuse;3=DeepSkyBlue;"
GraphicsWindow.BackgroundColor = "Black"
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh
CR = Text.GetCharacter(13)
LF = Text.GetCharacter(10)
src = "FD 100" + CR + "RT 90" + CR + "FD 200"
SrcToLines()
sample = "FD 200" + CR + "LT 90" + CR + "FD 100" + CR + "RT 90" + CR
sample = sample + "FD 100" + CR + "RT 90" + CR + "FD 100" + CR + "LT 90" + CR
sample = sample + "FD 200"
EndSub
Sub Opening
ms = "TITLE=2000;FORWARD=5;RIGHT=20;CLEAR=400;HELP=7000;"
GraphicsWindow.KeyDown = OnkeyDown
url = Program.Directory + "/image"
url = "http://www.nonkit.com/smallbasic.files"
obj = Shapes.AddImage(url + "/Car240.png")
GraphicsWindow.BrushColor = "DarkOrange"
GraphicsWindow.FontSize = 60
GraphicsWindow.FontName = "Trebuchet MS"
txt[0] = Shapes.AddText("CAR GRAPHICS")
Shapes.Move(txt[0], 10, 0)
x = 100
y = 440
Shapes.Move(obj, 10, 440)
Program.Delay(ms["TITLE"])
GraphicsWindow.BrushColor = "#333333"
GraphicsWindow.FillRectangle(x - 20, 100 - 20, x + 160, gh)
GraphicsWindow.FillRectangle(x + 160, 100 - 20, gw, 100 + 160)
GraphicsWindow.FontSize = 40
GraphicsWindow.BrushColor = "Chartreuse"
txt[1] = Shapes.AddText(line[1])
Shapes.Move(txt[1], 10, 80)
For y = y To 100 Step -1
Shapes.Move(obj, x, y)
Program.Delay(ms["FORWARD"])
EndFor
txt[2] = Shapes.AddText(line[2])
Shapes.Move(txt[2], 10, 120)
For a = 0 To 90
Shapes.Rotate(obj, a)
Program.Delay(ms["RIGHT"])
EndFor
txt[3] = Shapes.AddText(line[3])
Shapes.Move(txt[3], 10, 160)
For x = x To 700
Shapes.Move(obj, x, y)
Program.Delay(ms["FORWARD"])
EndFor
GraphicsWindow.BrushColor = "Black"
For i = 0 To 3
Shapes.Remove(txt[i])
Program.Delay(ms["CLEAR"])
EndFor
GraphicsWindow.BrushColor = "Chartreuse"
GraphicsWindow.DrawText(10, 10, "COMMANDS:")
GraphicsWindow.DrawText(10, 70, "FD distance")
GraphicsWindow.DrawText(10, 110, "LT|RT angle")
GraphicsWindow.DrawText(10, 150, "PD|PU")
GraphicsWindow.DrawText(10, 190, "REPEAT count [commands]")
GraphicsWindow.BrushColor = "DarkOrange"
GraphicsWindow.DrawText(10, 250, "HAVE FUN!")
Program.Delay(ms["HELP"])
GraphicsWindow.Clear()
EndSub
Sub ShowTickerTape
GraphicsWindow.PenWidth = 0
nMin = 1
nMax = 0
AddTickerTape()
Timer.Interval = 1000 / 24
Timer.Tick = OnTick
msStart = Clock.ElapsedMilliseconds
While 0 < Array.GetItemCount(tt)
If tick Then
If (Math.GetRandomNumber(10) = 1) And (Clock.ElapsedMilliseconds < msStart + 15000) Then
AddTickerTape()
EndIf
For i = nMin To nMax
x[i] = x[i] + Math.GetRandomNumber(4) - 2
y[i] = y[i] + Math.GetRandomNumber(4)
If gh + 60 < y[i] Then
nMin = i + 1
While tt[i] <> ""
Shapes.Remove(tt[i])
tt[i] = ""
i = i - 1
EndWhile
EndIf
Shapes.Move(tt[i], x[i], y[i])
a[i] = a[i] + 45
If 360 <= a[i] Then
a[i] = a[i] - 360
EndIf
Shapes.Zoom(tt[i], 1, Math.Sin(Math.GetRadians(a[i])))
EndFor
tick = "False"
Else
Program.Delay(1000 / 24)
EndIf
EndWhile
RemoveTickerTape()
EndSub
Sub RemoveTickerTape
For i = nMin To nMax
Shapes.Remove(tt[i])
EndFor
EndSub
Sub AddTickerTape
nMax = nMax + 1
GraphicsWindow.BrushColor = colors[Math.GetRandomNumber(3)]
tt[nMax] = Shapes.AddRectangle(20, 12)
x[nMax] = Math.GetRandomNumber(gw - 20) + 10
y[nMax] = -10
a[nMax] = Math.GetRandomNumber(360) - 1
Shapes.Rotate(tt[nMax], a[nMax])
Shapes.Move(tt[nMax], x[nMax], y[nMax])
EndSub
Sub OnTick
tick = "True"
EndSub
Sub OnKeyDown
If GraphicsWindow.LastKey = "Space" Then
ms = ""
EndIf
EndSub
Sub AT_Init
' Another Turtle | Initialize
' param x, y - initial position
AT_SIZE = 16
AT_OFFSET = AT_SIZE / 2
AT_speed = 5
AT_obj = Shapes.AddImage(url + "/Car.png")
Program.Delay(int) ' to synchronize with Silverlight
AT_x = Turtle.X
AT_y = Turtle.Y
Shapes.Move(AT_obj, AT_x - AT_OFFSET, AT_y - AT_OFFSET)
Shapes.HideShape(AT_obj)
EndSub
Sub AT_SetAngle
' Another Turtle | Set Angle
Shapes.Rotate(AT_obj, angle)
AT_angle = angle
EndSub
Sub AT_Show
' Another Turtle | Show
Shapes.ShowShape(AT_obj)
EndSub
Sub AT_Move
' Another Turtle | Move
' param distance
xStart = AT_x
yStart = AT_y
AT_x = AT_x + distance * Math.Sin(Math.GetRadians(AT_angle))
AT_y = AT_y - distance * Math.Cos(Math.GetRadians(AT_angle))
Shapes.Animate(AT_obj, AT_x - AT_OFFSET, AT_y - AT_OFFSET, distance * 50 / AT_speed)
If AT_penUp Then
Program.Delay(distance * 50 / AT_speed)
Else
xLast = xStart
yLast = yStart
For d = distance / 10 To distance Step distance / 10
x = xStart + d * Math.Sin(Math.GetRadians(AT_angle))
y = yStart - d * Math.Cos(Math.GetRadians(AT_angle))
Stack.PushValue("local", x)
Stack.PushValue("local", y)
xEnd = x
yEnd = y
For Δ = 0 To 1 Step 0.02
x = xLast + Δ * (xEnd - xLast)
y = yLast + Δ * (yEnd - yLast)
CheckCrash()
If crash Then
Δ = 1 ' exit For
EndIf
EndFor
y = Stack.PopValue("local")
x = Stack.PopValue("local")
GraphicsWindow.DrawLine(xLast, yLast, x, y)
If crash Then
DrawBlow()
Shapes.Move(AT_obj, x - AT_OFFSET, y - AT_OFFSET)
d = distance ' exit For
Else
xLast = x
yLast = y
Program.Delay(distance * 5 / AT_speed)
EndIf
EndFor
EndIf
EndSub
Sub AT_MoveTo
' Another Turtle | Move to given position
' param x
' param y
Stack.PushValue("local", x)
Stack.PushValue("local", y)
x = x - AT_x
y = y - AT_y
Math_CartesianToPolar()
angle = a + 90 - AT_angle
distance = r
AT_Turn()
AT_Move()
y = Stack.PopValue("local")
x = Stack.PopValue("local")
EndSub
Sub AT_PenUp
AT_penUp = "True"
EndSub
Sub AT_PenDown
AT_penUp = "False"
EndSub
Sub AT_Turn
' Another Turtle | Turn given angle
' param angle
Stack.PushValue("local", angle)
sa = angle / Math.Abs(angle)
angle = AT_angle + angle
For _a = AT_angle To angle Step sa
Shapes.Rotate(AT_obj, _a)
Program.Delay(2)
EndFor
Math_AdjustAngle()
AT_angle = angle
angle = Stack.PopValue("local")
EndSub
Sub AT_TurnRight
' Another Turtle | Turn Right
For angle = AT_angle To AT_angle + 90
Shapes.Rotate(AT_obj, a)
Program.Delay(2)
EndFor
AT_angle = angle - 1
EndSub
Sub Math_AdjustAngle
' Math | adjust angle [0, 360) degree
' param angle
' return angle
angle = Math.Remainder(angle, 360)
If angle < 0 Then
angle = angle + 360
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