Microsoft Small Basic
Program Listing:
Embed this in your website
<object id='sbapp' data='data:application/x-silverlight-2,' type='application/x-silverlight-2' width='640' height='480'> <param name='source' value='http://smallbasic.com/program/ClientBin/SBWeb.xap'/> <param name='onError' value='onSilverlightError' /> <param name='background' value='white' /> <param name='minRuntimeVersion' value='3.0.40624.0' /> <param name='autoUpgrade' value='true' /> <param name='initParams' value='programId=ASTEROIDS' /> </object>
' Asteroids Game
' Copyright (C) 2009, Jason T. Jacques
' License: MIT license http://www.opensource.org/licenses/mit-license.php
' Game area controls
gameWidth
=
640
gameHeight
=
480
backColor
=
"black"
' Window title
gameTitle
=
"Asteroids, Score: "
' Target frames per second
fps
=
25
' Key controls
leftKey
=
"Left"
rightKey
=
"Right"
forwardKey
=
"Up"
backKey
=
"Down"
fireKey
=
"Space"
pauseKey
=
"P"
' Asteroid (rock) settings
rockSpeed
=
1
rockColor
=
"white"
rockMin
=
20
' small size rock
rockTypes
=
3
' number of rock sizes (multiples of small rock size)
initRocks
=
5
' Ammo settings
ammoSpeed
=
5
ammoColor
=
"white"
ammoLife
=
60
' moves before auto destruct
ammoMax
=
10
ammoSize
=
5
' Player settings
playerColor
=
"white"
playerHeight
=
30
playerWidth
=
20
safeTime
=
100
' time player has to get out of the way on level up
' Point multiplier
pointsMultiply
=
10
' Array name initialisation
rock
=
"rockArray"
rockAngle
=
"rockAngle"
rockSize
=
"rockSize"
ammo
=
"ammoArray"
ammoAngle
=
"ammoAngle"
ammoAge
=
"ammoAge"
rockCount
=
0
ammoCount
=
0
bigRock
=
ImageList
.
LoadImage
(
"http://smallbasic.com/drop/Asteroids_BigRock.png"
)
medRock
=
ImageList
.
LoadImage
(
"http://smallbasic.com/drop/Asteroids_MediumRock.png"
)
smlRock
=
ImageList
.
LoadImage
(
"http://smallbasic.com/drop/Asteroids_SmallRock.png"
)
background
=
ImageList
.
LoadImage
(
"http://smallbasic.com/drop/Asteroids_Sky.png"
)
' Start game
Init
(
)
Play
(
)
' Setup world
Sub
Init
GraphicsWindow
.
Hide
(
)
GraphicsWindow
.
Title
=
gameTitle
+
"0"
GraphicsWindow
.
CanResize
=
"False"
GraphicsWindow
.
Width
=
gameWidth
GraphicsWindow
.
Height
=
gameHeight
GraphicsWindow
.
BackgroundColor
=
backColor
GraphicsWindow
.
BrushColor
=
backColor
GraphicsWindow
.
DrawImage
(
background
,
0
,
0
)
LevelCheck
(
)
GraphicsWindow
.
PenColor
=
playerColor
player
=
Shapes
.
AddImage
(
"http://smallbasic.com/drop/Asteroids_Ship.png"
)
' player = Shapes.AddTriangle(playerWidth/2, 0, 0, playerHeight, playerWidth, playerHeight)
Shapes
.
Move
(
player
,
(
gameWidth
-
playerWidth
)
/
2
,
(
gameHeight
-
playerHeight
)
/
2
)
playerAngle
=
0
EndSub
' Main gane routine
Sub
Play
GraphicsWindow
.
Show
(
)
GraphicsWindow
.
KeyDown
=
ChangeDirection
' Main loop
play
=
1
pause
=
0
While
(
play
=
1
)
Program
.
Delay
(
1000
/
fps
)
If
(
pause
=
0
)
Then
Move
(
)
CollisionCheck
(
)
AgeAmmo
(
)
LevelCheck
(
)
EndIf
EndWhile
EndSub
' Read key event and act
Sub
ChangeDirection
If
(
GraphicsWindow
.
LastKey
=
rightKey
)
Then
playerAngle
=
Math
.
Remainder
(
playerAngle
+
10
,
360
)
ElseIf
(
GraphicsWindow
.
LastKey
=
leftKey
)
Then
playerAngle
=
Math
.
Remainder
(
playerAngle
-
10
,
360
)
ElseIf
(
GraphicsWindow
.
LastKey
=
forwardKey
)
Then
playerSpeed
=
playerSpeed
+
1
ElseIf
(
GraphicsWindow
.
LastKey
=
backKey
)
Then
playerSpeed
=
playerSpeed
-
1
ElseIf
(
GraphicsWindow
.
LastKey
=
fireKey
)
Then
Fire
(
)
ElseIf
(
GraphicsWindow
.
LastKey
=
pauseKey
)
Then
pause
=
Math
.
Remainder
(
pause
+
1
,
2
)
EndIf
Shapes
.
Rotate
(
player
,
playerAngle
)
EndSub
' Move all on screen items
Sub
Move
' Move player
x
=
Math
.
Remainder
(
Shapes
.
GetLeft
(
player
)
+
(
Math
.
Cos
(
Math
.
GetRadians
(
playerAngle
-
90
)
)
*
playerSpeed
)
+
gameWidth
,
gameWidth
)
y
=
Math
.
Remainder
(
Shapes
.
GetTop
(
player
)
+
(
Math
.
Sin
(
Math
.
GetRadians
(
playerAngle
-
90
)
)
*
playerSpeed
)
+
gameHeight
,
gameHeight
)
Shapes
.
Move
(
player
,
x
,
y
)
' Move rocks
For
i
=
1
To
rockCount
x
=
Math
.
Remainder
(
Shapes
.
GetLeft
(
Array
.
GetValue
(
rock
,
i
)
)
+
(
Math
.
Cos
(
Math
.
GetRadians
(
Array
.
GetValue
(
rockAngle
,
i
)
-
90
)
)
*
rockSpeed
)
+
gameWidth
,
gameWidth
)
y
=
Math
.
Remainder
(
Shapes
.
GetTop
(
Array
.
GetValue
(
rock
,
i
)
)
+
(
Math
.
Sin
(
Math
.
GetRadians
(
Array
.
GetValue
(
rockAngle
,
i
)
-
90
)
)
*
rockSpeed
)
+
gameHeight
,
gameHeight
)
Shapes
.
Move
(
Array
.
GetValue
(
rock
,
i
)
,
x
,
y
)
EndFor
' Move ammo
For
i
=
1
To
ammoCount
x
=
Math
.
Remainder
(
Shapes
.
GetLeft
(
Array
.
GetValue
(
ammo
,
i
)
)
+
(
Math
.
Cos
(
Math
.
GetRadians
(
Array
.
GetValue
(
ammoAngle
,
i
)
-
90
)
)
*
ammoSpeed
)
+
gameWidth
,
gameWidth
)
y
=
Math
.
Remainder
(
Shapes
.
GetTop
(
Array
.
GetValue
(
ammo
,
i
)
)
+
(
Math
.
Sin
(
Math
.
GetRadians
(
Array
.
GetValue
(
ammoAngle
,
i
)
-
90
)
)
*
ammoSpeed
)
+
gameHeight
,
gameHeight
)
Shapes
.
Move
(
Array
.
GetValue
(
ammo
,
i
)
,
x
,
y
)
Array
.
SetValue
(
ammoAge
,
i
,
Array
.
GetValue
(
ammoAge
,
i
)
+
1
)
EndFor
EndSub
' Check for collisions between onscreen items
Sub
CollisionCheck
' Calculate player bounding box.
px1
=
Shapes
.
GetLeft
(
player
)
-
(
(
Math
.
Abs
(
playerWidth
*
Math
.
Cos
(
Math
.
GetRadians
(
playerAngle
)
)
+
playerHeight
*
Math
.
Sin
(
Math
.
GetRadians
(
playerAngle
)
)
)
-
playerWidth
)
/
2
)
py1
=
Shapes
.
GetTop
(
player
)
-
(
(
Math
.
Abs
(
playerWidth
*
Math
.
Sin
(
Math
.
GetRadians
(
playerAngle
)
)
+
playerHeight
*
Math
.
Cos
(
Math
.
GetRadians
(
playerAngle
)
)
)
-
playerHeight
)
/
2
)
px2
=
px1
+
Math
.
Abs
(
playerWidth
*
Math
.
Cos
(
Math
.
GetRadians
(
playerAngle
)
)
+
playerHeight
*
Math
.
Sin
(
Math
.
GetRadians
(
playerAngle
)
)
)
py2
=
py1
+
Math
.
Abs
(
playerWidth
*
Math
.
Sin
(
Math
.
GetRadians
(
playerAngle
)
)
+
playerHeight
*
Math
.
Cos
(
Math
.
GetRadians
(
playerAngle
)
)
)
' Re-order co-oridinates if they are the wrong way arround
If
(
px1
>
px2
)
Then
tmp
=
px1
px1
=
px2
px2
=
tmp
EndIf
If
(
py1
>
py2
)
Then
tmp
=
py1
py1
=
py2
py2
=
tmp
EndIf
' Check if each rock has hit something
For
i
=
1
To
rockCount
ax1
=
Shapes
.
Getleft
(
Array
.
GetValue
(
rock
,
i
)
)
ay1
=
Shapes
.
GetTop
(
Array
.
GetValue
(
rock
,
i
)
)
ax2
=
ax1
+
Array
.
GetValue
(
rockSize
,
i
)
ay2
=
ay1
+
Array
.
GetValue
(
rockSize
,
i
)
' Player collison
If
(
playerSafe
<
1
)
Then
If
(
(
ax1
<
px1
And
ax2
>
px1
)
Or
(
ax1
<
px2
And
ax2
>
px2
)
)
Then
If
(
(
ay1
<
py1
And
ay2
>
py1
)
Or
(
ay1
<
py2
And
ay2
>
py2
)
)
Then
EndGame
(
)
EndIf
EndIf
EndIf
' Ammo collison
For
j
=
1
to
ammoCount
bx1
=
Shapes
.
Getleft
(
Array
.
GetValue
(
ammo
,
j
)
)
by1
=
Shapes
.
GetTop
(
Array
.
GetValue
(
ammo
,
j
)
)
bx2
=
bx1
+
ammoSize
by2
=
by1
+
ammoSize
If
(
(
ax1
<
bx1
And
ax2
>
bx1
)
Or
(
ax1
<
bx2
And
ax2
>
bx2
)
)
Then
If
(
(
ay1
<
by1
And
ay2
>
by1
)
Or
(
ay1
<
by2
And
ay2
>
by2
)
)
Then
nextRemove
=
i
RemoveRock
(
)
nextRemove
=
j
RemoveAmmo
(
)
EndIf
EndIf
EndFor
EndFor
' Decrease the time player is safe
If
(
playerSafe
>
0
)
Then
playerSafe
=
playerSafe
-
1
EndIf
EndSub
' Add a new rock to the world
Sub
AddRock
' Check if the next rock size/position has been specified
If
(
nextSize
<>
0
)
Then
size
=
rockMin
*
nextSize
x
=
Shapes
.
GetLeft
(
nextPosition
)
y
=
Shapes
.
GetTop
(
nextPosition
)
nextSize
=
0
Else
' Choose a random size and position
size
=
rockMin
*
Math
.
GetRandomNumber
(
rockTypes
)
x
=
Math
.
GetRandomNumber
(
gameWidth
-
size
)
y
=
Math
.
GetRandomNumber
(
gameHeight
-
size
)
EndIf
' Draw the rock
GraphicsWindow
.
PenColor
=
rockColor
If
size
=
60
Then
Array
.
SetValue
(
rock
,
rockCount
+
1
,
Shapes
.
AddImage
(
bigRock
)
)
ElseIf
size
=
40
Then
Array
.
SetValue
(
rock
,
rockCount
+
1
,
Shapes
.
AddImage
(
medRock
)
)
Else
Array
.
SetValue
(
rock
,
rockCount
+
1
,
Shapes
.
AddImage
(
smlRock
)
)
EndIf
rockCount
=
rockCount
+
1
Shapes
.
Move
(
Array
.
GetValue
(
rock
,
rockCount
)
,
x
,
y
)
Array
.
SetValue
(
rockAngle
,
rockCount
,
Math
.
GetRandomNumber
(
360
)
)
Array
.
SetValue
(
rockSize
,
rockCount
,
size
)
EndSub
' Remove a rock from the world and update score
Sub
RemoveRock
removeSize
=
Array
.
GetValue
(
rockSize
,
nextRemove
)
/
rockMin
' If not a mini rock
If
(
removeSize
>
1
)
Then
' ... add new rocks until we have made up for it being broken apart...
While
(
removeSize
>
0
)
nextSize
=
Math
.
GetRandomNumber
(
removeSize
-
1
)
nextPosition
=
Array
.
GetValue
(
rock
,
nextRemove
)
removeSize
=
removeSize
-
nextSize
AddRock
(
)
EndWhile
' And give a point for a 'hit'
score
=
score
+
1
Else
' We've destroyed it - give some extra points and
score
=
score
+
5
EndIf
' Show updated score
GraphicsWindow
.
Title
=
gameTitle
+
(
score
*
pointsMultiply
)
' Remove all references from the arrays
Shapes
.
Remove
(
Array
.
GetValue
(
rock
,
nextRemove
)
)
For
i
=
nextRemove
To
rockCount
-
1
Array
.
SetValue
(
rock
,
i
,
Array
.
GetValue
(
rock
,
i
+
1
)
)
Array
.
SetValue
(
rockAngle
,
i
,
Array
.
GetValue
(
rockAngle
,
i
+
1
)
)
Array
.
SetValue
(
rockSize
,
i
,
Array
.
GetValue
(
rockSize
,
i
+
1
)
)
EndFor
Array
.
RemoveValue
(
rock
,
rockCount
)
Array
.
RemoveValue
(
rockAngle
,
rockCount
)
Array
.
RemoveValue
(
rockSize
,
rockCount
)
rockCount
=
rockCount
-
1
EndSub
' Check if the player has completed the level, if so, level up
Sub
LevelCheck
If
(
rockCount
<
1
)
Then
nextSize
=
0
For
i
=
1
To
initRocks
AddRock
(
)
EndFor
initRocks
=
initRocks
+
1
' Give players some time to move out of the way
playerSafe
=
safeTime
EndIf
EndSub
' Add ammo to game
Sub
Fire
' Remove additional ammo
While
(
ammoCount
>
(
ammoMax
-
1
)
)
nextRemove
=
1
RemoveAmmo
(
)
EndWhile
' Add the ammo
GraphicsWindow
.
PenColor
=
ammoColor
ammoCount
=
ammoCount
+
1
Array
.
SetValue
(
ammo
,
ammoCount
,
Shapes
.
AddEllipse
(
ammoSize
,
ammoSize
)
)
Shapes
.
Move
(
Array
.
GetValue
(
ammo
,
ammoCount
)
,
(
px1
+
px2
-
ammoSize
)
/
2
,
(
py1
+
py2
-
ammoSize
)
/
2
)
Array
.
SetValue
(
ammoAngle
,
ammoCount
,
playerAngle
)
EndSub
' Check ammo age
Sub
AgeAmmo
While
(
Array
.
GetValue
(
ammoAge
,
1
)
>
ammoLife
)
nextRemove
=
1
RemoveAmmo
(
)
EndWhile
EndSub
' Remove top Ammo
Sub
RemoveAmmo
Shapes
.
Remove
(
Array
.
GetValue
(
ammo
,
nextRemove
)
)
For
i
=
nextRemove
To
ammoCount
-
1
Array
.
SetValue
(
ammo
,
i
,
Array
.
GetValue
(
ammo
,
i
+
1
)
)
Array
.
SetValue
(
ammoAngle
,
i
,
Array
.
GetValue
(
ammoAngle
,
i
+
1
)
)
Array
.
SetValue
(
ammoAge
,
i
,
Array
.
GetValue
(
ammoAge
,
i
+
1
)
)
EndFor
Array
.
RemoveValue
(
ammo
,
ammoCount
)
Array
.
RemoveValue
(
ammoAngle
,
ammoCount
)
Array
.
RemoveValue
(
ammoAge
,
ammoCount
)
ammoCount
=
ammoCount
-
1
EndSub
' Display simple end game message box
Sub
EndGame
play
=
0
Shapes
.
Remove
(
player
)
GraphicsWindow
.
ShowMessage
(
"You scored "
+
(
score
*
pointsMultiply
)
+
" points. Thanks for Playing."
,
"Game Over!"
)
EndSub
Copyright (c) Microsoft Corporation. All rights reserved.