Microsoft Small Basic

Program Listing: BFN681
'***************************************************
' Small Basic Chomper (SBC) v 1.0
' Pacman-style game (BETA)
'Version 1.3.7.13 (online version)
'
' Software designed & written in BASIC by Anthony Yarrell (QBasicLover in the SB forums)
' Designed for Microsoft Small Basic 1.0
' March 2013
'
'Sprites created using Microsoft Paint
'Maze designed using Microsoft Excel
'
'My Research Sources:
'===============
'Sprite Management & Animation: "Visual Basic Game Programming for Teens", Jonathan S. Harbour;
'"Video Game Programming for Teens", Jonathan S. Harbour; Microsoft Small Basic Forums.
'Pacman Sprite Behavior: "The Pacman Dossier" http://home.comcast.net/~jpittman2/pacman/pacmandossier.html;
'Creating a Pacman Maze: http://stackoverflow.com/questions/622471/pacman-maze-in-java;
'
'***************************************************

'These variables control game play:
BRAND_NEW_GAME = 0
PLAY_LEVEL = 1
ADVANCE_LEVEL = 2
REPLAY_LEVEL = 3
GAME_OVER = 4
gameState = BRAND_NEW_GAME

'Initialization:
mazeScale = 8 'Size of maze and distance between tiles. The game runs better when
'the mazeScale is 2 x the number of animation frames. I set the total animation frames
'to 4 because it gave the best performance while making the math easier.
gameScreenHeight = 375
gamescreenWidth = 225
monsterEatenCtr = 0 'Counts the number of monsters eaten in succession per energizer (4= bonus)
monsterBonusPts = 1000 'Pts given to player for eating 4 monsters in succession.
monsterPts = 200 'Points player gets when he/she eats a monster.
monsterPtsMuliplier = 2 'Causes player to get bonus points when monsters are eaten in succession.
monstersEatenPerLevel = 0'Counts the number of mosters eaten per level. SBC gets a life if he eats 16 monsters per level.
gameSpeed = 20'<-- Decrease if game runs too slowly
gameScore = 0
gameLevel = 0
pelletScore = 25
energizerScore = 100
hasReached50K = "False" 'Flag to track if score reaches 50,000. Player gets extra life.
initialCountDownTime = 80 'Amount of time (cycles) the monsters stay "frightened"
globalCycleCtr = 0 'Used for syncronization and scheduling.

'**********************************
'Game loop
'***********************************
While (gameState <> GAME_OVER)
keyPressed = GraphicsWindow.LastKey

start = Clock.ElapsedMilliseconds
globalCycleCtr = globalCycleCtr + 1

If (gameState = BRAND_NEW_GAME) Then

InitializeLookupTables()
SetupGraphicsWindow()
LoadBitmaps()
InitializeSprites()
SpriteArray[SBC][Lives] = 3
gameState = ADVANCE_LEVEL

ElseIf (gameState = ADVANCE_LEVEL) Then
globalCycleCtr = 0
monstersEatenPerLevel = 0
selectedRotation = 0 ' SBC goes through 4 max rotations.
sbcDirection = Dir_R ' SBC moves to the right when level starts.
SmallDelay()
UpdateLevelState()
ConstructGameElements()
splashText = "L E V E L : "+ gameLevel
DisplayLevelSplash()
gameState = PLAY_LEVEL

ElseIf (gameState = PLAY_LEVEL) Then
LeaveMonsterPenOneByOne()

'Each sprite has a counter that it uses to track when it reaches a tile when moving though the maze.
'When this counter reaches mazeScale, the sprite updates it info and draws.
'Each sprite also has a spritespeed variable that it uses to set its movement speed. For example,
'if spritespeed = 1 then updates will be done on each tick of the global counter. If spritespeed = 2 then
'updates will be done on every 2nd tick, which will slow down that sprite, etc.

For Sprites = firstSprite to lastSprite
IF Math.Remainder(globalCycleCtr,SpriteArray[Sprites][spriteSpeed])=0 Then
Update()
Draw()
EndIf
Endfor

ElseIf (gameState = REPLAY_LEVEL) Then
sbcDirection = Dir_R
Sprites=1
SpriteArray[SBC][Lives] = SpriteArray[sbc][Lives] - 1
SpriteArray[SBC][State] = NORMAL
globalCycleCtr = 0
SmallDelay()
ClearSpritesFromaze()
InitializeSprites()
PositionSpritesInMaze()
DrawSprites() '<---BUG FIX. A call to DrawSprites( ) fixes an issue where SBC dissapears when level restarts.
SmallDelay()
gameState = PLAY_LEVEL


If (SpriteArray[SBC][Lives] = 0) Then
gameState = GAME_OVER
splashText = "Game Over"
DisplayLevelSplash()
Endif

Endif

delay = gameSpeed - (Clock.ElapsedMilliseconds-start)
If (delay > 0) Then
Program.Delay(delay)
EndIf

KeyboardHandler()
EndWhile 'End of main state machine
'***********************************************************************************
Sub SmallDelay
Program.Delay(500)
EndSub
'*******************************************************************************************
'Updates various games elements (eg maze color, game speed, etc) as the player advances to a new level:
'- gameSpeed: Overall speed of game. Game gets faster on each level.
'- initialCountDownTime: amount of time that monsters stay afraid. Decreases on each level.

Sub UpdateLevelState
If math.Remainder(gameLevel,4) = 1 Then
mazeBorderColor = "Cyan"
ElseIf math.Remainder(gameLevel,4) = 2 then
mazeBorderColor = "Red"
Elseif math.Remainder(gameLevel,4) = 3 then
mazeBorderColor = "midnightblue"
Elseif math.Remainder(gameLevel,4) = 0 then
mazeBorderColor = "magenta"
EndIf

gameLevel = gameLevel + 1
gameSpeed = gameSpeed - 2

If (gameSpeed <= 0) Then
gameSpeed = 0
EndIf

'Give the player a new life on levels 4 and 8:
If (gameLevel = 4 Or gameLevel = 8) Then
SpriteArray[sbc][Lives]=SpriteArray[sbc][Lives] + 1
EndIf

'Reduce the amount of time that the monsters stay "Frightened" as game progresses.
'At much higher levels, the monsters won't stay frighened at all:
initialCountDownTime = initialCountDownTime - 2
If initialCountDownTime <= 0 Then
initialCountDownTime = 0
EndIf
EndSub
'*******************************************************************************************
'Dsplays a splash screen at the start of each level:

Sub DisplayLevelSplash
GraphicsWindow.FontSize=14
GraphicsWindow.BrushColor="white"
l=Shapes.AddText(splashText)
Shapes.Move(l,-200,205)
Shapes.Animate(l,80,205,1000)
SmallDelay()
SmallDelay()
SmallDelay()
Shapes.Animate(l,-200,205,1000)
EndSub
'*******************************************************************************************
'The variables Dir_L, Dir_U, Dir_R, Dir_D are used as indexes into the xModifier and yModifier lookup tables.
'For example, xModifier[L] & yModifier[L] produces -1 and 0 respectively. When added to XY or RC values this will cause
'the sprite to go left, etc:

Sub KeyboardHandler

Dir_L = 1
Dir_U = 2
Dir_R = 3
Dir_D = 4

If (keyPressed = "Left") Then
sbcDirection = Dir_L
Elseif (keyPressed = "Right") Then
sbcDirection = Dir_R
Elseif (keyPressed = "Up") Then
sbcDirection = Dir_U
Elseif (keyPressed = "Down") Then
sbcDirection = Dir_D
Elseif (keyPressed = "Escape") Then
gameState = GAME_OVER
Endif

EndSub
'*******************************************************************************************
Sub MoveSBC
'This routine moves SBC around the screen and causes SBC to stop at borders.It checks the maze
'locations adjacent to SBC's current location aganist the direction chosen by an arrow key press.
'If the new direction is possible (eg no borders in the way) SBC will go in the new direction. If
'the new direction is not possible, but the previous direction is, SBC will continue traveling in the
'direction it was moving in prior to the arrow key press. If neither direction is possible, SBC
'will stop moving:

If Sprites=SBC Then
canMoveInOldDirection = "False"
canMoveInNewDirection = "False"

'Get maze data ahead of SBC:
aheadDirX = SpriteArray[SBC][mazeCol] + SpriteArray[SBC][DX]
aheadDirY = SpriteArray[SBC][mazeRow] + SpriteArray[SBC][DY]
aheadDirData = Maze[aheadDirY][aheadDirX]

'Get maze data at location based on arrow key press:
newDirX = SpriteArray[SBC][mazeCol] + xModifier[SbcDirection]
newDirY = SpriteArray[SBC][mazeRow] + yModifier[SbcDirection]
newDirData = Maze[newDirY][newDirX]

'The mazeTokens array holds data that represent ares that are NOT blocked by borders.

For a = firstToken To lastToken
If (mazeTokens[a] = newDirData) Then
canMoveInNewDirection = "True"
Goto _XIT_4Loop_Early
EndIf
If (mazeTokens[a] = aheadDirData) Then
canMoveInOldDirection = "True"
EndIf
EndFor
_XIT_4Loop_Early:

'If the new direction is possible, go in new direction:
If (canMoveInNewDirection = "True") Then
SpriteArray[SBC][DX] = xModifier[sbcDirection]
SpriteArray[SBC][DY] = yModifier[sbcDirection]
selectedRotation = rotationLookupTable[sbcDirection]
EndIf

'If neither old nor new directions are possible, come to a stop:
If (canMoveInNewDirection = "False" And canMoveInOldDirection = "False") Then
SpriteArray[SBC][DX] = 0
SpriteArray[SBC][DY] = 0
EndIf

SpriteArray[SBC][mazeCol] = SpriteArray[SBC][mazeCol] + SpriteArray[SBC][DX]
SpriteArray[SBC][mazeRow] = SpriteArray[SBC][mazeRow] + SpriteArray[SBC][DY]

EatPellet()
EndIf

EndSub
'*******************************************************************************************
Sub MoveMonstersTowardTarget
'This routine moves the monsters toward a target while allowing them to navigate around the maze
'borders. LL is a temporary array:

INVALID = 9999 '9999 is used as an invalid flag because the total distance across the maze is
'much lower than 9999 pixels. Later, when the code calculates the distance
'between source to target, anything marked 9999 won't be considered.

If (Sprites <> SBC) Then '<--SBC has his own movement routine (see MoveSBC)

For a = 1 To 4 'step through XY/RC modifier table:
SourceX = SpriteArray[Sprites][mazeCol] + xModifier[a]
SourceY = SpriteArray[Sprites][mazeRow] + yModifier[a]
targetX = SpriteArray[Sprites][targetCol]
targetY = SpriteArray[Sprites][targetRow]

For b = firstToken To lastToken

'If the maze area being examined is not a border then calculate the distance from that maze area
' to the target using the Manhattan Distance formula (SourceX-targetCol)+(SourceY-targetRow)...
If mazeTokens[b]=Maze[SpriteArray[Sprites][mazeRow] + yModifier[a]][SpriteArray[Sprites][mazeCol]+ xModifier[a]] Then
LL[a] = 1+(math.Abs(Sourcex-targetx) + math.Abs(Sourcey-targety))
Goto _XIT4

'...otherwise mark it as invalid because it's a border :
Else
LL[a] = INVALID
EndIf

EndFor
_XIT4:
EndFor

'For each maze area stored in the LL array, check to see if that was visited by the monster during previous
'game loop cycle. If so mark it INVALID, then save the monster's current maze location
'in VX, VY. These two steps will force the monster to travel in forward directions only (no reversing direction):
For c = 1 To 4
If SpriteArray[Sprites][mazeCol] + xModifier[c] = SpriteArray[Sprites][VX] Then
If SpriteArray[Sprites][mazeRow] + yModifier[c] = SpriteArray[Sprites][VY] Then
LL[c] = INVALID
EndIf
EndIf
EndFor

SpriteArray[Sprites][VX] = SpriteArray[Sprites][mazeCol]
SpriteArray[Sprites][VY] = SpriteArray[Sprites][mazeRow]

'Get the smallest number in temporary LL array, which will represent the direction to move in
'1 = go left, 2 = go up, 3 = to right, 4 = go down:
initialValue = LL[1]
For ictr = 1 TO 4
If initialValue >= LL[ictr] THEN
initialValue = LL[ictr]
elementfound = ictr
EndIf
EndFor
'Set the movement direction. The xModifier/yModifier lookup tables eliminate the need for If/Then tests here:
SpriteArray[Sprites][DX] = xModifier[elementfound]
SpriteArray[Sprites][DY] = yModifier[elementfound]

'** There is at least one circumstance where the monster finds a dead end - when the monster is in the
'monster pen at level start. In this instance, the monster's L, D, & R adjacent areas will be invalid
'due to being blocked by visible and invisible borders, and U is blocked because it will be added to the
'VX/VY variables after the first game cycle. When this happens the VX/VY variables must be deleted
'and on the next game cycle the monster will move out of dead end.
'
if LL[elementfound] = INVALID Then
SpriteArray[Sprites][DX] = 0
SpriteArray[Sprites][DY] = 0
SpriteArray[Sprites][VX] = 0
SpriteArray[Sprites][VY] = 0
EndIf

'Finally, move toward target:
SpriteArray[Sprites][mazeCol] = (SpriteArray[Sprites][mazeCol] + SpriteArray[Sprites][dx])
SpriteArray[Sprites][mazeRow] = (SpriteArray[Sprites][mazeRow] + SpriteArray[Sprites][dy])

EndIf

Endsub
'*******************************************************************************************
'Detects when sprites touch each other and when sprites enter special areas of the maze:
Sub CollisionDetect

If Sprites <> SBC Then
CheckRectangles()

If isTouching = "True" Then
isTouching = "False"
'Monster dies if touching SBC while fightened and then monster returns to the monster pen:
If SpriteArray[Sprites][State] = FRIGHT then
ShowEatSplash()
SpriteArray[Sprites][State] = DIE
hasEatenMonster = "True"
ScoreAndBonusManager()

'SBC dies if touching monster when energizer is not active:
ElseIf SpriteArray[Sprites][State] = CHASE then
SpriteArray[SBC][State] = DIE
gameState = REPLAY_LEVEL
EndIf

hasEatenMonster = "False"
EndIf

'When monster reaches monster pen, get body back and leave:
If SpriteArray[Sprites][mazeCol] = MonsterPenX and SpriteArray[Sprites][mazeRow]= MonsterPenY Then
If SpriteArray[Sprites][State] = DIE then
SpriteArray[Sprites][State] = EMERGE
EndIf
EndIf
'When monster has left monster pen, go back to chasing SBC:
If SpriteArray[Sprites][mazeCol] = emergeX and SpriteArray[Sprites][mazeRow] = emergeY Then
If SpriteArray[Sprites][State] = EMERGE then
SpriteArray[Sprites][State] = CHASE
EndIf
EndIf
EndIf

'***BUG FIX: If a monster is in the monster pen when an energizer is eaten it will switch from whatever mode its in to
'FRIGHT mode. However, FRIGHT mode closes to doors when causes the monster to get trapped. This is a side effect -
'my intention was to keep the monsters from re-entering the pen prematurely. The fix below checks to see if a monster
'is in the pen and is the wrong mode. If so, it is switched to EMERGE mode so that it can properly emerge from the pen:
If (SpriteArray[Sprites][mazeCol] = MonsterPenX) and (SpriteArray[Sprites][mazeRow] = MonsterPenY) Then
If (SpriteArray[Sprites][State] <> DIE) Or (SpriteArray[Sprites][State] <> EMERGE) then
SpriteArray[Sprites][State] = EMERGE
EndIf
EndIf
EndSub
'*******************************************************************************************
'Sets the targets that the monsters will move towards:
Sub SetupMonsterTargets

IF (Sprites <>SBC) then

'Sets ghosts to meander around the screen after SBC eats a power pellet:
If SpriteArray[Sprites][State] = FRIGHT Then
SpriteArray[Sprites][targetRow] = math.GetRandomNumber(maxMazeRows)
SpriteArray[Sprites][targetCol] = math.GetRandomNumber(maxMazeCols)

'Sends the monsters back to monster pen after being eaten by SBC:
ElseIf SpriteArray[Sprites][State] = DIE Then
SpriteArray[Sprites][targetCol] = MonsterPenX
SpriteArray[Sprites][targetRow] = MonsterPenY

'Makes the monsters leave home base:
ElseIf SpriteArray[Sprites][State] = EMERGE Then
SpriteArray[Sprites][targetCol] = emergeX
SpriteArray[Sprites][targetRow] = emergeY

Elseif SpriteArray[Sprites][State] = CHASE Then

If Sprites = RedMonster Then
'Red monster pursues directly:
SpriteArray[RedMonster][targetCol] = SpriteArray[SBC][mazeCol]
SpriteArray[RedMonster][targetRow] = SpriteArray[SBC][mazeRow]

ElseIf Sprites = PinkMonster Then
'Pink monster tries to ambush (***TO DO: needs to be fixed***):
SpriteArray[PinkMonster][targetCol] = SpriteArray[SBC][mazeCol] + (SpriteArray[SBC][DX]-1)
SpriteArray[PinkMonster][targetRow] = SpriteArray[SBC][mazeRow] + (SpriteArray[SBC][DY]-1)

ElseIf Sprites = OrangeMonster Then
'Orange monster wanders around
SpriteArray[OrangeMonster][targetCol] = math.GetRandomNumber(maxMazeCols)
SpriteArray[OrangeMonster][targetRow] = math.GetRandomNumber(maxMazeRows)

ElseIf Sprites = BlueMonster Then
'Blue monster considers red monster's coordinates and SBC's coordinates wheb determining how to move:
SpriteArray[BlueMonster][targetCol] = math.abs(SpriteArray[SBC][mazeCol] + SpriteArray[RedMonster][mazeCol])
SpriteArray[BlueMonster][targetRow] = math.abs(SpriteArray[SBC][mazeRow] + SpriteArray[RedMonster][mazeRow])
EndIf

EndIf

ENDIF

EndSub
'*******************************************************************************************
'Animation manager. The animation frames are stored in the ImageArray 2D array. This routine
'sets the indexes into that array. FrameCtr + Offset is used as the index into ImageArray.
'When Offset = zero all sprites go through the normal 4-cycle animation sequence. When
'offset = 5, the monsters turn purple (Fright Mode), and when the offset = 6 the monsters turn dark gray
'(Die Mode).

Sub SetupAnimationSequence

SpriteArray[SBC][LastFrame] = 4
SpriteArray[SBC][FirstFrame] = 1
SpriteArray[SBC][offset] = 0

If (Sprites <> SBC) Then
If SpriteArray[Sprites][State] = CHASE Then
SpriteArray[Sprites][offset] = 0
SpriteArray[Sprites][LastFrame] = 4
SpriteArray[Sprites][FirstFrame] = 1

ElseIf SpriteArray[Sprites][State] = FRIGHT Then
SpriteArray[Sprites][offset] = 5
SpriteArray[Sprites][LastFrame] = 5
SpriteArray[Sprites][FirstFrame] = 5

ElseIf SpriteArray[Sprites][State] = DIE Then
SpriteArray[Sprites][offset] = 6
SpriteArray[Sprites][LastFrame] = 6
SpriteArray[Sprites][FirstFrame] = 6

ElseIf SpriteArray[Sprites][State] = EMERGE Then
SpriteArray[Sprites][offset] = 0
SpriteArray[Sprites][LastFrame] = 4
SpriteArray[Sprites][FirstFrame] = 1
Endif
EndIf
FlashMonsters()
EndSub
'*******************************************************************************************
Sub EatPellet

erasePelletFromScreen = "FALSE"
mazeData = Maze[(SpriteArray[SBC][mazeRow])][(SpriteArray[SBC][mazeCol])]

'Pellet = mazeToken[1]. Energizer = mazeToken[2]:
If (mazeData = mazeTokens[1] Or mazeData = mazeTokens[2]) Then
Maze[(SpriteArray[SBC][mazeRow])][(SpriteArray[SBC][mazeCol])]=mazeTokens[0] 'empty this maze location
pelletCount = pelletCount - 1
erasePelletFromScreen = "True"
gameScore = gameScore + pelletScore

If (mazeData = mazeTokens[1]) Then
gameScore = gameScore + pelletScore
ElseIf (mazeData = mazeTokens[2]) then
monsterEatenCtr=0
SetMonstersToFrightState()
gameScore = gameScore + energizerScore
energizerTimer = ACTIVE
energizerTime = initialCountDownTime
EndIf

If pelletCount <= 0 Then
gameState = ADVANCE_LEVEL
EndIf

EndIf

DoEnergizerTimer()
EndSub
'*******************************************************************************************
'Sets all monsters to FRIGHT state. VY & VX are zeroed out so that the monsters can switch
'directions. (MoveMonstersTowardTarget( ) normally restricts the monsters to forward-only movements):
Sub SetMonstersToFrightState
For ee = firstMonster to lastMonster
if SpriteArray[ee][State] <> DIE then
SpriteArray[ee][State] = FRIGHT
shapes.SetOpacity(ImageArray[ee][5],100)
SpriteArray[ee][VY] = 0
SpriteArray[ee][VX] = 0
EndIf
Endfor
EndSub
'*******************************************************************************************
'Sets all monsters to CHASE state. This is a bug fix to keep the monsters from switching out of DIE
'mode prematurely:
Sub MakeMonstersChase
For mc = firstMonster to lastMonster
If SpriteArray[mc][State] <> DIE then
SpriteArray[mc][State] = CHASE
EndIf
Endfor
EndSub
'*******************************************************************************************
'Manages the count down timer that determines how long an energizer lasts.
Sub DoEnergizerTimer
If (energizerTimer = ACTIVE) Then
If (energizerTime <> 0) Then
energizerTime = energizerTime -1
Else
energizerTimer = INACTIVE
monsterEatenCtr=0
MakeMonstersChase()
Endif
Endif

EndSub
'*******************************************************************************************
'Dispatch routine for erasing pellets/energizers from the screen:
Sub ErasePellet
pelletColor = "black"
pelletX = SpriteArray[SBC][screenX] + sWidth - mazeScale
pelletY = SpriteArray[SBC][screenY] + sHeight - mazeScale
DrawEnergizer()
EndSub
'*******************************************************************************************
'Draws/erases an energizer
Sub DrawEnergizer
pelletSize = 6
xOffset = -6
yOffset = -6
DP()
Endsub
'*******************************************************************************************
'Draws/erases a pellet
Sub DrawPellet
pelletSize = 3
xOffset = -3
yOffset = -3
DP()
EndSub
'*******************************************************************************************
Sub DP
GraphicsWindow.BrushColor = pelletColor
GraphicsWindow.FillEllipse(pelletX+xOffset, pelletY+yOffset, pelletSize, pelletSize)
EndSub
'*******************************************************************************************
'Removes sprites from the maze
Sub ClearSpritesFromaze
For r=firstSprite To lastSprite
For t = 1 To 6
Shapes.move(ImageArray[r][t],-100,-100)
EndFor
EndFor

EndSub
'*******************************************************************************************
'Draws sprites on screen while advancing through the animation sequence setup by SetupAnimationSequence().

Sub DrawSprites

'To reduce flicker only draw sprites that are moving (SBC sometimes stops)
If SpriteArray[Sprites][dx]<>0 Or SpriteArray[Sprites][dy]<>0 Then

'Get a reference to the current animation frame. We will hide it later:
oldFrameCtr=SpriteArray[Sprites][FrameCtr]
SpriteArray[Sprites][frameCtr]=SpriteArray[Sprites][frameCtr]+1+SpriteArray[Sprites][offset]

'Advance to next frame and check to see if all frames have been displayed:
If SpriteArray[Sprites][frameCtr]>SpriteArray[Sprites][lastFrame] then
SpriteArray[Sprites][frameCtr]=SpriteArray[Sprites][firstFrame]
Endif

'Update screen coordinates:
SpriteArray[Sprites][screenX]= SpriteArray[Sprites][screenX]+ SpriteArray[Sprites][DX] * 1
SpriteArray[Sprites][screenY]= SpriteArray[Sprites][screenY]+ SpriteArray[Sprites][DY] * 1.5

'Get reference to new animation frame and apply rotation (for SBC):
newFrameCtr=SpriteArray[Sprites][frameCtr]
if Sprites = SBC Then
Shapes.Rotate(ImageArray[Sprites][newFrameCtr], selectedRotation)
EndIf

'Finally, hide previous frame and show new animation frame:
shapes.Move(ImageArray[Sprites][oldFrameCtr],-20,-20)
Shapes.Move(ImageArray[Sprites][newFrameCtr], SpriteArray[Sprites][screenX], SpriteArray[Sprites][screenY])

EndIf

If erasePelletFromScreen = "True" Then
ErasePellet()
EndIf

EndSub
'*******************************************************************************************
'This routine intializes general purpose global lookup tables.

Sub InitializeLookupTables

'The xModifier & yModifier arrays are used to modify the XY screen coordinates and RC maze coordinates:
xModifier[0] = 0 'Stop moving
xModifier[1] =-1 'Move Left (when added to X)
xModifier[2] = 0 '
xModifier[3] = 1 'Move Right (when added to X)
xModifier[4] = 0

yModifier[0] = 0 'Stop moving
yModifier[1] = 0 '
yModifier[2] =-1 'Move Up (when added to Y)
yModifier[3] = 0 '
yModifier[4] = 1 'Move Down (when added to Y)

'rotationLookupTable holds the rotation angles for SBC. SbcDirection is used as an index:
rotationLookupTable[1] = 180
rotationLookupTable[2] = 270
rotationLookupTable[3] = 0
rotationLookupTable[4] = 90

EndSub
'*******************************************************************************************
'Sets up sprite data structure and establishes related variables:

Sub InitializeSprites

'State variables for sprites:
DIE = 0
NORMAL = 1
CHASE = 2
SCATTER = 3 '<--not implemented yet
FRIGHT = 4
EMERGE = 5

'State variables for energizer timer:
ACTIVE = 1
INACTIVE = 0

'The sprite data structure is a 2D array. These variables are indexes into the 2nd dimension of that array.
'(Dimension#1 slects the sprite, dimension #2 sets/gets properties of the particular sprite:

firstSprite = SBC
lastSprite = PinkMonster
firstMonster = RedMonster
lastMonster = PinkMonster

'Variables for dimension #2:
screenX = 1 'screen x coordinate
screenY = 2 'screen y coordinate
mazeCol = 3 'maze col
mazeRow = 4 'maze row
DX = 5 'x/col modifier
DY = 6 'y/row modifier
targetCol= 7 'maze target col
targetRow= 8 'maze target row
VX = 9 'visited maze col
VY = 10 'visited maze row
State = 11
Lives = 12
FrameCtr = 13 'Index into ImageArray[ ][ ]
Offset = 14
FirstFrame = 15
LastFrame = 16
cycleCounter= 17
spriteSpeed= 18

'Initialize:
For spriteCtr = firstSprite To lastSprite
SpriteArray[spriteCtr][FirstFrame] = 1
SpriteArray[spriteCtr][LastFrame] = 4
SpriteArray[spriteCtr][FrameCtr] = 4
SpriteArray[spriteCtr][offset] = 4
SpriteArray[spriteCtr][DX] = 0
SpriteArray[spriteCtr][DY] = 0
SpriteArray[spriteCtr][VX] = 0
SpriteArray[spriteCtr][VY] = 0
SpriteArray[spriteCtr][targetCol] = 0
SpriteArray[spriteCtr][targetRow] = 0
SpriteArray[spriteCtr][State] = CHASE
SpriteArray[spriteCtr][spriteSpeed] = 1
SpriteArray[spriteCtr][cycleCounter] = 1
Endfor
SpriteArray[SBC][State] = NORMAL
sbcDirection = Dir_R

EndSub
'*******************************************************************************************
Sub PositionSpritesInMaze

'Used for alignment hacks:
xxOffset= 0
yyOffset= 0

'Position SBC two tiles underneath Monster pen:
SpriteArray[SBC][mazeCol] = 15
SpriteArray[SBC][mazeRow] = 24

'Position Red Monster outside & above Monster pen:
SpriteArray[RedMonster][mazeCol] = 12
SpriteArray[RedMonster][mazeRow] = 12

'Blue, Orange and Pink Monsters inside Monster pen:
SpriteArray[BlueMonster][mazeCol] = 12
SpriteArray[BlueMonster][mazeRow] = 16
SpriteArray[OrangeMonster][mazeCol] = 17
SpriteArray[OrangeMonster][mazeRow] = 16
SpriteArray[PinkMonster][mazeCol] = 14
SpriteArray[PinkMonster][mazeRow] = 15

'Set correct screen positions:
For Sprites = firstSprite to lastSprite
AdjustScreenCoords()
EndFor

EndSub
'*******************************************************************************************
'Using maze RC values, calculate screen XYs:
Sub AdjustScreenCoords
SpriteArray[Sprites][screenX] = (SpriteArray[Sprites][mazeCol]) * mazeScale - mazeScale
SpriteArray[Sprites][screenY] = (SpriteArray[Sprites][mazeRow]) * mazeScale * 1.5 - mazeScale
EndSub
'*******************************************************************************************
Sub LoadBitmaps
'The sprite data structure is a 2D array. These variables are indexes into the 2nd dimension of that array.
'(Dimension#1 slects the sprite, dimension #2 sets/gets properties of the particular sprite.

'Variables to select the sprites (dimension #1 of SpriteArray):
SBC = 1
RedMonster = 2
BlueMonster = 3
OrangeMonster = 4
PinkMonster = 5

sWidth = mazeScale * 2
sHeight = mazeScale * 2

'ImageArray is a 2D array that holds references to the bitmaps used by the sprites. Dimension #1 is used
'to select the sprite, dimension #2 is used to select the bitmap.

'Load bitmaps for normal animation sequence:
filePath = Program.Directory +"\"
'SBC animation frames
ImageArray[SBC][1]=shapes.addimage("http://farm9.staticflickr.com/8240/8528887960_413fda8a5a_t.jpg")
ImageArray[SBC][2]=shapes.addimage("http://farm9.staticflickr.com/8379/8528887958_f8f6d3e534_t.jpg")
ImageArray[SBC][3]=shapes.addimage("http://farm9.staticflickr.com/8520/8527774169_b73baef828_t.jpg")
ImageArray[SBC][4]=shapes.addimage("http://farm9.staticflickr.com/8379/8528887958_f8f6d3e534_t.jpg")

'Red Monster animation frames
ImageArray[RedMonster][1]=shapes.addimage("http://farm9.staticflickr.com/8388/8528887972_d45aa82d69_t.jpg")
ImageArray[RedMonster][2]=shapes.addimage("http://farm9.staticflickr.com/8388/8528887972_d45aa82d69_t.jpg")
ImageArray[RedMonster][3]=shapes.addimage("http://farm9.staticflickr.com/8388/8528887972_d45aa82d69_t.jpg")
ImageArray[RedMonster][4]=shapes.addimage("http://farm9.staticflickr.com/8388/8528887972_d45aa82d69_t.jpg")

'Blue Monster animation frames
ImageArray[BlueMonster][1]=shapes.addimage("http://farm9.staticflickr.com/8378/8527774263_5f7d6e6aac_t.jpg")
ImageArray[BlueMonster][2]=shapes.addimage("http://farm9.staticflickr.com/8378/8527774263_5f7d6e6aac_t.jpg")
ImageArray[BlueMonster][3]=shapes.addimage("http://farm9.staticflickr.com/8378/8527774263_5f7d6e6aac_t.jpg")
ImageArray[BlueMonster][4]=shapes.addimage("http://farm9.staticflickr.com/8378/8527774263_5f7d6e6aac_t.jpg")

'Orange Monster animation frames
ImageArray[OrangeMonster][1]=shapes.addimage("http://farm9.staticflickr.com/8377/8527774201_6fced83ebf_t.jpg")
ImageArray[OrangeMonster][2]=shapes.addimage("http://farm9.staticflickr.com/8377/8527774201_6fced83ebf_t.jpg")
ImageArray[OrangeMonster][3]=shapes.addimage("http://farm9.staticflickr.com/8377/8527774201_6fced83ebf_t.jpg")
ImageArray[OrangeMonster][4]=shapes.addimage("http://farm9.staticflickr.com/8377/8527774201_6fced83ebf_t.jpg")

'Pink Monster animation frames
ImageArray[PinkMonster][1]=shapes.addimage("http://farm9.staticflickr.com/8523/8527774181_5fa1ebe6bb_t.jpg")
ImageArray[PinkMonster][2]=shapes.addimage("http://farm9.staticflickr.com/8523/8527774181_5fa1ebe6bb_t.jpg")
ImageArray[PinkMonster][3]=shapes.addimage("http://farm9.staticflickr.com/8523/8527774181_5fa1ebe6bb_t.jpg")
ImageArray[PinkMonster][4]=shapes.addimage("http://farm9.staticflickr.com/8523/8527774181_5fa1ebe6bb_t.jpg")

For s= 1 to 5

'Load bitmaps for FRIGHT Mode:
ImageArray[s][5]=shapes.addimage("http://farm9.staticflickr.com/8102/8528933134_d80645e3cc_t.jpg")

'Load bitmaps for DIE mode:
ImageArray[s][6]=shapes.addimage("http://farm9.staticflickr.com/8532/8528888036_85d4b2906d_t.jpg")
Shapes.SetOpacity(ImageArray[s][6],50)

Endfor

ClearSpritesFromaze()

EndSub

''*******************************************************************************************
'Loads maze pattern into maze array, counts the number of pellets added to maze, and gets the
'maze XY coordinates for special areas. Also creates and populates the mazeToken[ ] lookup table:
'
Sub LoadMaze

M[1] = "/------\/----------\/------\"
M[2] = "|......||..........||......|"
M[3] = "|*/--\.||./------\.||./--\*|"
M[4] = "|.(--).().(------).().(--).|"
M[5] = "|..........................|"
M[6] = "(-\./\./---\./\./---\./\./-)"
M[7] = "oo|.||.| |.||.| |.||.|oo"
M[8] = "oo|.||.(---).||.(---).||.|oo"
M[9] = "oo|.||.......||.......||.|oo"
M[10] = "oo|.|(--\+/--)(--\+/--)|.|oo"
M[11] = "--).(---)+(------)+(---).(--"
M[12] = "LT+.+++++++E++++++++++++.+SR"
M[13] = "--\./---\+/AAAAAAo+/---\./--"
M[14] = "oo|.|/--)+|+Co+B+|+(--\|.|oo"
M[15] = "oo|.||++++|+oo+o+|++++||.|oo"
M[16] = "oo|.||+/\+|MCo+B+|+/\+||.|oo"
M[17] = "oo|.()+||+(------)+||+().|oo"
M[18] = "oo|.+++||++++++++++||+++.|oo"
M[19] = "oo|./--)(--\+/\+/--)(--\.|oo"
M[20] = "oo|.(------)+||+(------).|oo"
M[21] = "oo|.......+++||+++.......|oo"
M[22] = "oo|./---\./--)(--\./---\.|oo"
M[23] = "/-).(---).(------).(---).(-\"
M[24] = "|............++............|"
M[25] = "|./--\./---\./\./---\./--\.|"
M[26] = "|.|oo|.|/--).||.(--\|.|oo|.|"
M[27] = "|.|oo|.||....||....||.|oo|.|"
M[28] = "|*|oo|.||./--)(--\.||.|oo|*|"
M[29] = "|.(--).().(------).().(--).|"
M[30] = "|..........................|"
M[31] = "(--------------------------)"
maxMazeRows = Array.GetItemCount(M)
maxMazeCols = Text.GetLength(M[1])

'mazeTokens[ ] hold tokens that represent walkable space in the maze:
firstToken = 0
lastToken = 2

mazeTokens[0]= "+"
mazeTokens[1]= "."
mazeTokens[2]= "*"

'Load the maze pattern into the maze[ ] [ ] array:
For rows = 1 To maxMazeRows
For cols = 1 To maxMazeCols
maze[rows][cols] = Text.GetSubText(M[rows], cols, 1)
If maze[rows][cols] = mazeTokens[1] Or maze[rows][cols] = mazeTokens[2] Then
pelletCount = pelletCount + 1
EndIf

'Special areas:
If Maze[rows][cols] ="M" Then 'DIE mode target Monster Pen tile
Maze[rows][cols] = mazeTokens[0]
monsterpenX = cols
MonsterPenY = rows
ElseIf Maze[rows][cols] ="E" Then 'Emerge mode target tile
Maze[rows][cols] = mazeTokens[0]
emergeX = cols
emergeY = rows
ElseIf Maze[rows][cols] ="L" Then 'Left tunnel tile
Maze[rows][cols] = mazeTokens[0]
leftTunnelX = cols
leftTunnelY = rows
ElseIf Maze[rows][cols] ="R" Then 'Right tunnel tile
Maze[rows][cols] = mazeTokens[0]
rightTunnelX = cols
rightTunnelY = rows
ElseIf Maze[rows][cols] ="S" Then 'Right slow-down tunnel tile
Maze[rows][cols] = mazeTokens[0]
sld1X = cols
sld1Y = rows
ElseIf Maze[rows][cols] ="T" Then 'Right slow-down tunnel tile
Maze[rows][cols] = mazeTokens[0]
sld2X = cols
sld2Y = rows
EndIf

EndFor
EndFor

'Delete the temporary array holding the maze structure:
M=""
EndSub
'*******************************************************************************************
'Steps through maze[ ] [ ] and draws the pattern on screen:
Sub DrawMaze

mazeBackgroundColor = "black"
GraphicsWindow.BackgroundColor= mazeBackgroundColor
x = 0
y = 0
mWidth = mazeScale
mHeight = mazeScale
MMX = (X + 1 * mWidth)
MMY = (Y + 1.5 * mHeight)
MMH = (1.5 * mHeight)
MMW = (1 * mWidth)

For rows = 1 To maxMazeRows
tempMMYrows = MMY*rows 'helps speed up draw operations a bit.
For cols = 1 To maxMazeCols
mazeData = Maze[rows][cols]

GraphicsWindow.PenColor = mazeBorderColor
GraphicsWindow.PenWidth = 2
' Upper Left corner:
if mazeData = "/" then
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, mazeCol+MMW*cols, TempMMYrows)
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols, MMY+MMH*rows)

'Upper Right corner:
elseif mazeData = "\" then
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols-MMW, TempMMYrows)
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols, TempMMYrows+MMH)

'Lower Left corner:
elseif mazeData = "(" then
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols, TempMMYrows-MMH)
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols+MMW, TempMMYrows)

'Lower right corner:
elseif mazeData = ")" then
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols, TempMMYrows-MMH)
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols-MMW, TempMMYrows)
'
'Vertical line:
elseif mazeData = "-" then
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols-MMW, TempMMYrows)
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols+MMW, TempMMYrows)
'
'Vertical line for top door
elseif mazeData = "A" then
GraphicsWindow.PenColor="white"
GraphicsWindow.PenWidth="1"
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols-MMW, TempMMYrows)
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols+MMW, TempMMYrows)
'
'Horizontal line:
elseif mazeData = "|" then
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols, TempMMYrows-MMH)
GraphicsWindow.DrawLine(MMX*cols,TempMMYrows, MMX*cols, TempMMYrows+MMH)

'Pellet:
elseif mazeData = "." then
pelletColor = "white"
pelletX=(cols * MMW)
pelletY=(rows * MMY)
DrawPellet()

'Energizer:
elseif mazeData = "*" then
pelletColor = "white"
pelletX=(cols * MMW)
pelletY=(rows * MMY)
DrawEnergizer()

Endif
EndFor
EndFor
EndSub
'*******************************************************************************************
'There are three invisible borders that keep the blue, pink and orange ghosts in the monster pen
'and also keeps the monsters from getting back in unless they are in EMERGE or DIE modes.
'The doors are "opened" by adding their tokens to the mazeToken[ ] array and extending the lastToken pointer.
'The doors are "closed" by resetting the lastToken pointer:
Sub CloseDoors
lastToken = 2
EndSub
'*******************************************************************************************
Sub OpenLeftDoor
mazeTokens[3] = "B"
lastToken = lastToken + 1
EndSub
'*******************************************************************************************
Sub OpenRightDoor
mazeTokens[3] = "C"
lastToken = lastToken + 1
EndSub
'*******************************************************************************************
Sub OpenTopDoor
mazeTokens[3] = "A"
lastToken = lastToken + 1
EndSub
'*******************************************************************************************
'This routines causes the monsters to leave the monster pen one-by-one after a certain number of
'cycles have past. This done at game start, on each new level and when a level is replayed . The
'invisible "doors" open whenever the monsters are in EMERGE or DIE modes:
Sub LeaveMonsterPenOneByOne

If globalCycleCtr = 100 then
SpriteArray[PinkMonster][state] = EMERGE
ElseIf globalCycleCtr = 200 Then
SpriteArray[OrangeMonster][state] = EMERGE
Elseif globalCycleCtr = 400 Then
SpriteArray[BlueMonster][state] = EMERGE
EndIf
EndSub
'*******************************************************************************************
'Dispatches update-related routines:
Sub Update
SpriteArray[Sprites][cycleCounter]=SpriteArray[Sprites][cycleCounter]+1

'Do updates when a sprite reaches a new tile. Distance between tiles is set by MazeScale:
if (SpriteArray[Sprites][cycleCounter] > mazeScale) Then
MoveSBC()
SetupMonsterTargets()
SetupSpriteSpeed()
OpenCloseDoors()
MoveMonstersTowardTarget()
CheckGoThroughTunnels()
SpriteArray[Sprites][cycleCounter]=1
DisplayScore()
DisplayLevel()
EndIf

Endsub
'*******************************************************************************************
'Displaches draw-related routines:
Sub Draw
SetupAnimationSequence()
DrawSprites()
CollisionDetect()
CheckGoThroughTunnels()
Endsub
'*******************************************************************************************
'Ensures that sprites are moving at correct speed:
Sub SetupSpriteSpeed

If SpriteArray[Sprites][state] = CHASE Then
SpriteArray[Sprites][spriteSpeed] = 1
ElseIf SpriteArray[Sprites][state] = FRIGHT Then
SpriteArray[Sprites][spriteSpeed] = 2
ElseIf SpriteArray[Sprites][state] = NORMAL Then
SpriteArray[Sprites][spriteSpeed] = 1
ElseIf SpriteArray[Sprites][state] = DIE Then
SpriteArray[Sprites][spriteSpeed] = 1
EndIf

EndSub
'*******************************************************************************************
'Can't speed up maze drawing, so black out the game screen and then construct maze and position
'bitmaps underneath the black cover:
Sub ConstructGameElements
BlackOutGameScreen()
LoadMaze()
DrawMaze()
DisplayLevel()
DisplayLives()
ClearSpritesFromaze()
InitializeSprites()
PositionSpritesInMaze()
RemoveBlackScreen()
EndSub
'*******************************************************************************************
'Causes the monsters to flash briefly as a warning to the player that the monsters are about
'to swtich from Fright to Chase states:
'***BUG ??: This routine doesn't work well with Silverlight***

Sub FlashMonsters

If (energizerTimer = ACTIVE) And (SpriteArray[Sprites][State] = FRIGHT) Then
If (energizerTime < 20) Then
If (Math.Remainder(energizerTime,3)=0) Then
shapes.SetOpacity(ImageArray[sprites][5],100) 'Visible
Else
shapes.SetOpacity(ImageArray[sprites][5],10) 'Faint
EndIf
EndIf
EndIf
EndSub
'*********************************************************************************
'Allows game to cage in or release monsters from monster pen:

Sub OpenCloseDoors
If SpriteArray[Sprites][State] = CHASE Then
CloseDoors()
ElseIf SpriteArray[Sprites][State] = FRIGHT Then
CloseDoors()
ElseIf SpriteArray[Sprites][State] = NORMAL Then
CloseDoors()
ElseIf SpriteArray[Sprites][State] = DIE Then
OpenLeftDoor()
OpenRightDoor()
OpenTopDoor()
ElseIf SpriteArray[Sprites][State] = EMERGE Then
OpenLeftDoor()
OpenRightDoor()
OpenTopDoor()
EndIf
EndSub
'**************************************************************************
Sub ScoreAndBonusManager

If (hasEatenMonster = "True") Then
monsterEatenCtr = monsterEatenCtr + 1
gameScore = gameScore + monsterPts +(monsterEatenCtr * monsterPts)

'Give player a bonus when all 4 monsters are eaten in succession:
If monsterEatenCtr = 4 Then
gameScore = gameScore + monsterBonusPts
splashText=monsterBonusPts + "PT BONUS!"
DisplayLevelSplash()
monsterEatenCtr=0
EndIf

monstersEatenPerLevel = monstersEatenPerLevel + 1

'Give player an extra life whenever 16 monsters are eaten per level:
If monstersEatenPerLevel = 16 Then
SpriteArray[sbc][lives] = SpriteArray[sbc][lives] + 1
splashText="EXTRA LIFE ADDED!"
monstersEatenPerLevel=0
DisplayLevelSplash()
EndIf
hasEatenMonster="False"
EndIf

If hasReached50K="False" Then
If gameScore > 50000 Then
hasReached50K="True"
SpriteArray[sbc][lives] = SpriteArray[sbc][lives] + 1
splashText="EXTRA LIFE ADDED!"
DisplayLevelSplash()
DisplayLives()
EndIf
EndIf
EndSub
'*******************************************************************************
'Bounding Box collision detection routine from "Beginning Microsoft Small Basic", 9-30
Sub CheckRectangles

isTouching = "False"

Object1X=SpriteArray[sbc][screenX]
Object1Y=SpriteArray[sbc][screenY]
Object2X=SpriteArray[Sprites][screenX]
Object2Y=SpriteArray[Sprites][screenY]

If ((Object1X + 6 +sWidth - 6) > Object2X +6) Then 
If (Object1X +6 < (Object2X+6 + sWidth - 6)) Then 
If ((Object1Y+6 + sHeight - 6) > Object2Y+6) Then 
If (Object1Y+6 < (Object2Y+6 + sHeight - 6)) Then 
isTouching = "True"
EndIf 
EndIf
EndIf
EndIf

EndSub
'************************************************************************
'Allows sprites to travel through tunnels and causes the monsters to slow down at tunnel entrances:
sub CheckGoThroughTunnels

If Sprites <> SBC Then
if (SpriteArray[Sprites][mazecol]=sld1X And SpriteArray[Sprites][mazeRow]=sld2Y) or (SpriteArray[Sprites][mazecol]=sld2X And SpriteArray[Sprites][mazeRow]=sld2Y) Then
SpriteArray[Sprites][spriteSpeed]=4
EndIf
endif

If SpriteArray[Sprites][mazeCol] = rightTunnelX and SpriteArray[Sprites][mazeRow] = rightTunnelY Then
SpriteArray[Sprites][mazeCol] = leftTunnelX
SpriteArray[Sprites][mazeRow] = leftTunnelY
AdjustScreenCoords()

ElseIf SpriteArray[Sprites][mazeCol] = leftTunnelX and SpriteArray[Sprites][mazeRow] = leftTunnelY Then
SpriteArray[Sprites][mazeCol] = rightTunnelX
SpriteArray[Sprites][mazeRow] = rightTunnelY
AdjustScreenCoords()

EndIf
EndSub
'********************************************************************
'Shows the per-monster points at the location where the monster was eaten:
Sub ShowEatSplash
GraphicsWindow.BrushColor="white"
GraphicsWindow.FontName="Arial"
o=shapes.AddText(monsterPts +(monsterEatenCtr * monsterPts))
osx = SpriteArray[Sprites][screenX] - sWidth
osy = SpriteArray[Sprites][screenY] + sHeight
Shapes.Move(o,osx,osy)
SmallDelay()
Shapes.Remove(o)
EndSub
'*******************************************************************************************
sub SetupGraphicsWindow
GraphicsWindow.Title="Small Basic Chomper"
GraphicsWindow.Width= gamescreenWidth
GraphicsWindow.Height=gameScreenHeight
GraphicsWindow.CanResize="false"
GraphicsWindow.BrushColor="white"
GraphicsWindow.FontSize = 10
GraphicsWindow.FontBold = "False"
GraphicsWindow.DrawText(10,0,"SCORE: ")
GraphicsWindow.DrawText(100,0,"LEVEL: ")
GraphicsWindow.DrawText(180,0,"LIVES: ")
scoreShape=Shapes.AddText(gameScore)
livesShape=Shapes.AddText(SpriteArray[sbc][Lives])
levelShape=Shapes.AddText(gameLevel)
Shapes.Move(scoreShape,50,0)
Shapes.Move(levelShape,135,0)
Shapes.Move(livesShape,220,0)
endsub
'*******************************************************************************************
Sub DisplayScore
Shapes.SetText(scoreShape,gamescore)
EndSub
'*******************************************************************************************
Sub DisplayLives
Shapes.SetText(livesShape,SpriteArray[sbc][lives])
EndSub
'*******************************************************************************************
Sub DisplayLevel
Shapes.SetText(levelShape,gameLevel)
EndSub
'*******************************************************************************************
Sub BlackoutGameScreen
GraphicsWindow.BrushColor="black"
blkScreen = Shapes.AddRectangle(gamescreenWidth, gameScreenHeight)
Endsub
'*******************************************************************************************
Sub RemoveBlackScreen
Shapes.Remove(blkScreen)
EndSub