Microsoft Small Basic

Program Listing:
Embed this in your website
' 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"


' 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

  LevelCheck()

   GraphicsWindow.PenColor = playerColor
   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 Array.GetItemCount(rock)
    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 Array.GetItemCount(ammo)
    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 Array.GetItemCount(rock)
    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 Array.GetItemCount(ammo)
      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
  Array.SetValue(rock, (Array.GetItemCount(rock) + 1), Shapes.AddEllipse(size, size))
  Shapes.Move(Array.GetValue(rock, Array.GetItemCount(rock)), x, y)
  Array.SetValue(rockAngle, Array.GetItemCount(rock), Math.GetRandomNumber(360))
  Array.SetValue(rockSize, Array.GetItemCount(rock), 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 (Array.GetItemCount(rock) - 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, Array.GetItemCount(rock))
  Array.RemoveValue(rockAngle, Array.GetItemCount(rockAngle))
  Array.RemoveValue(rockSize, Array.GetItemCount(rockSize))
EndSub

' Check if the player has completed the level, if so, level up
Sub LevelCheck
  If(Array.GetItemCount(rock) < 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(Array.GetItemCount(ammo) > (ammoMax - 1))
    nextRemove = 1
    RemoveAmmo()
  EndWhile

  ' Add the ammo
  GraphicsWindow.PenColor = ammoColor
  Array.SetValue(ammo, (Array.GetItemCount(ammo) + 1), Shapes.AddEllipse(ammoSize, ammoSize))
  Shapes.Move(Array.GetValue(ammo, Array.GetItemCount(ammo)), (px1 + px2 - ammoSize) / 2, (py1 + py2 - ammoSize) / 2)
  Array.SetValue(ammoAngle, Array.GetItemCount(ammo), 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 (Array.GetItemCount(ammo) - 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, Array.GetItemCount(ammo))
  Array.RemoveValue(ammoAngle, Array.GetItemCount(ammoAngle))
  Array.RemoveValue(ammoAge, Array.GetItemCount(ammoAge))
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.