Microsoft Small Basic

Program Listing: SPR072
' SBace-Invaders-25 (v2) - A space invader game in under 25 lines by Davey~Wavey, Nov.2009, for Small Basic Forum.
' ===================================================================================
'
' Alien has increasing speed as it descends to increase difficulty, but you also get more score the faster they are!
' Aliens have different personalities (!) and drop further depending on their agression (i.e. a random number)
' You are rated on your score and your hit accuracy. You have 3 lives. Use your mouse to move your rocket and left mousebutton to fire.
' When an alien gets through your defences, they kill you off, then immediately regroup for another assault.
'
' See below game code for notes. Good Luck, civilization is depending on you!!!!!

' initialise game array
gamearry = "1=-1;-1=1;moveables=7;lives=3;ammo=0;score=0;aspeed=2;mx1=0;my1=0;mxo1=-3;myo1=0;m1=" + Shapes.AddEllipse(5,10) + ";mx2="+(GraphicsWindow.MouseX-25)+";my2="+(GraphicsWindow.Height-50)+";m2=" + Shapes.AddImage("http://www.tutorialized.com/upload/(2006.06.21-09:12:44)rocket50x50.jpg") + ";mxo3=-25;myo3=-25;mx3=" + ((GraphicsWindow.Width/2)-160) + ";my3=20;md3=-1;m3=" + shapes.AddImage("http://www.adiumxtras.com/images/thumbs/space_invaders_1_17601_6150_thumb.png") + ";mxo4=-25;myo4=-25;mx4=" + ((GraphicsWindow.Width/2)-80) + ";my4=20;md4=-1;m4=" + shapes.AddImage("http://www.adiumxtras.com/images/thumbs/space_invaders_1_17601_6150_thumb.png") + ";mxo5=-25;myo5=-25;mx5=" + (GraphicsWindow.Width/2) + ";my5=20;md5=-1;m5=" + shapes.AddImage("http://www.adiumxtras.com/images/thumbs/space_invaders_1_17601_6150_thumb.png") + ";mxo6=-25;myo6=-25;mx6=" + ((GraphicsWindow.Width/2)+80) + ";my6=20;md6=-1;m6=" + shapes.AddImage("http://www.adiumxtras.com/images/thumbs/space_invaders_1_17601_6150_thumb.png") + ";mxo7=-25;myo7=-25;mx7=" + ((GraphicsWindow.Width/2)+160) + ";my7=20;md7=-1;m7=" + shapes.AddImage("http://www.adiumxtras.com/images/thumbs/space_invaders_1_17601_6150_thumb.png")

While gamearry["lives"] > 0

' update alien and bullet positions
gamearry = "1=-1;-1=1;moveables=" + gamearry["moveables"] + ";lives=" + gamearry["lives"] +";ammo=" + gamearry["ammo"] +";score=" + gamearry["score"] +";aspeed=" + gamearry["aspeed"] +";mx1=" + gamearry["mx1"] + ";my1=" + (gamearry["my1"] - gamearry["aspeed"]) +";mxo1=" + gamearry["mxo1"] + ";myo1=" + gamearry["myo1"] + ";m1=" + gamearry["m1"] +";mx2="+(GraphicsWindow.MouseX-25)+";my2="+(GraphicsWindow.Height-50)+";m2=" + gamearry["m2"] +";mxo3=" + gamearry["mxo3"] +";myo3=" + gamearry["myo3"] +";mx3=" + (gamearry["mx3"] + (gamearry[ gamearry["md3"] ] * gamearry["aspeed"] )) +";my3=" + gamearry["my3"] +";md3=" + gamearry["md3"] + ";m3=" + gamearry["m3"] + ";mxo4=" + gamearry["mxo4"] + ";myo4=" + gamearry["myo4"] + ";mx4=" + (gamearry["mx4"] + (gamearry[ gamearry["md4"] ] * gamearry["aspeed"] )) + ";my4=" + gamearry["my4"] + ";md4=" + gamearry["md4"] + ";m4=" + gamearry["m4"] + ";mxo5=" + gamearry["mxo5"] + ";myo5=" + gamearry["myo5"] + ";mx5=" + (gamearry["mx5"] + (gamearry[ gamearry["md5"] ] * gamearry["aspeed"] )) + ";my5=" + gamearry["my5"] + ";md5=" + gamearry["md5"] + ";m5=" + gamearry["m5"] + ";mxo6=" + gamearry["mxo6"] + ";myo6=" + gamearry["myo6"] + ";mx6=" + (gamearry["mx6"] + (gamearry[ gamearry["md6"] ] * gamearry["aspeed"] )) + ";my6=" + gamearry["my6"] + ";md6=" + gamearry["md6"] + ";m6=" + gamearry["m6"] + ";mxo7=" + gamearry["mxo7"] + ";myo7=" + gamearry["myo7"] + ";mx7=" + (gamearry["mx7"] + (gamearry[ gamearry["md7"] ] * gamearry["aspeed"] )) + ";my7=" + gamearry["my7"] + ";md7=" + gamearry["md7"] + ";m7=" + gamearry["m7"]

' move the bullet (m1), gun (m2) and aliens (m3+)
For m=1 To gamearry["moveables"]

' put the shapes where they're supposed to be
Shapes.Move(gamearry["m"+m], gamearry["mx"+m]+gamearry["mxo"+m], gamearry["my"+m]+gamearry["myo"+m])

If m > 2 And ( math.abs( math.Floor(gamearry["mx1"]-(gamearry["mx"+m])) ) <25 ) And ( math.Abs( Math.Floor( gamearry["my1"]-gamearry["my"+m] ) ) < 10 ) Then
' bullet has collided with alien - increase score and reset alien
gamearry = "1=-1;-1=1;moveables=" + gamearry["moveables"] + ";lives=" + gamearry["lives"] +";ammo=" + gamearry["ammo"] +";score=" + (gamearry["score"]+10) +";aspeed=" + gamearry["aspeed"] +";mx1=" + gamearry["mx1"] + ";my1=-200;mxo1=" + gamearry["mxo1"] + ";myo1=" + gamearry["myo1"] + ";m1=" + gamearry["m1"] +";mx2="+(GraphicsWindow.MouseX-25)+";my2="+(GraphicsWindow.Height-50)+";m2=" + gamearry["m2"] +";mxo3=" + gamearry["mxo3"] +";myo3=" + gamearry["myo3"] +";mx3=" + gamearry["mx3"] +";my3=" + (gamearry["my3"]-(((gamearry["my3"]+80)*(math.Max(0,0-(Math.Remainder(m+10,3+10)*2)+1))))) +";md3=" + gamearry["md3"] + ";m3=" + gamearry["m3"] + ";mxo4=" + gamearry["mxo4"] + ";myo4=" + gamearry["myo4"] + ";mx4=" + gamearry["mx4"] + ";my4=" + (gamearry["my4"]-((gamearry["my4"]+80)*(math.Max(0,0-(Math.Remainder(m,4)*2)+1)))) + ";md4=" + gamearry["md4"] + ";m4=" + gamearry["m4"] + ";mxo5=" + gamearry["mxo5"] + ";myo5=" + gamearry["myo5"] + ";mx5=" + gamearry["mx5"] + ";my5=" + (gamearry["my5"]-((gamearry["my5"]+80)*(math.Max(0,0-(Math.Remainder(m,5)*2)+1)))) + ";md5=" + gamearry["md5"] + ";m5=" + gamearry["m5"] + ";mxo6=" + gamearry["mxo6"] + ";myo6=" + gamearry["myo6"] + ";mx6=" + gamearry["mx6"] + ";my6=" + (gamearry["my6"]-((gamearry["my6"]+80)*(math.Max(0,0-(Math.Remainder(m,6)*2)+1)))) + ";md6=" + gamearry["md6"] + ";m6=" + gamearry["m6"] + ";mxo7=" + gamearry["mxo7"] + ";myo7=" + gamearry["myo7"] + ";mx7=" + gamearry["mx7"] + ";my7=" + (gamearry["my7"]-((gamearry["my7"]+80)*(math.Max(0,0-(Math.Remainder(m,7)*2)+1)))) + ";md7=" + gamearry["md7"] + ";m7=" + gamearry["m7"]


ElseIf m > 2 AND ( (gamearry["mx"+m] < 35) Or (gamearry["mx"+m] > GraphicsWindow.Width-55) ) Then
' alien has hit edge of screen, so bounce it and increase speed
gamearry = "1=-1;-1=1;moveables=" + gamearry["moveables"] + ";lives=" + gamearry["lives"] +";ammo=" + gamearry["ammo"] +";score=" + gamearry["score"] +";aspeed=" + (gamearry["aspeed"]+0.01) +";mx1=" + gamearry["mx1"] + ";my1=" + gamearry["my1"] +";mxo1=" + gamearry["mxo1"] + ";myo1=" + gamearry["myo1"] + ";m1=" + gamearry["m1"] +";mx2="+(GraphicsWindow.MouseX-25)+";my2="+(GraphicsWindow.Height-50)+";m2=" + gamearry["m2"] +";mxo3=" + gamearry["mxo3"] +";myo3=" + gamearry["myo3"] +";mx3=" + gamearry["mx3"] +";my3=" + (gamearry["my3"]+((math.Max(0,0-(Math.Remainder(m+10,3+10)*4)+1))*(10+Math.GetRandomNumber(20)))) +";md3=" + gamearry[(gamearry["md3"]*(math.Max(-1,0-(Math.Remainder(m+10,3+10)*4)+1)))] + ";m3=" + gamearry["m3"] + ";mxo4=" + gamearry["mxo4"] + ";myo4=" + gamearry["myo4"] + ";mx4=" + gamearry["mx4"] + ";my4=" + (gamearry["my4"]+((math.Max(0,0-(Math.Remainder(m,4)*4)+1))*(10+Math.GetRandomNumber(20)))) + ";md4=" + gamearry[(gamearry["md4"]*(math.Max(-1,0-(Math.Remainder(m,4)*4)+1)))] + ";m4=" + gamearry["m4"] + ";mxo5=" + gamearry["mxo5"] + ";myo5=" + gamearry["myo5"] + ";mx5=" + gamearry["mx5"] + ";my5=" + (gamearry["my5"]+((math.Max(0,0-(Math.Remainder(m,5)*4)+1))*(10+Math.GetRandomNumber(20)))) + ";md5=" + gamearry[(gamearry["md5"]*(math.Max(-1,0-(Math.Remainder(m,5)*4)+1)))] + ";m5=" + gamearry["m5"] + ";mxo6=" + gamearry["mxo6"] + ";myo6=" + gamearry["myo6"] + ";mx6=" + gamearry["mx6"] + ";my6=" + (gamearry["my6"]+((math.Max(0,0-(Math.Remainder(m,6)*4)+1))*(10+Math.GetRandomNumber(20)))) + ";md6=" + gamearry[(gamearry["md6"]*(math.Max(-1,0-(Math.Remainder(m,6)*4)+1)))] + ";m6=" + gamearry["m6"] + ";mxo7=" + gamearry["mxo7"] + ";myo7=" + gamearry["myo7"] + ";mx7=" + gamearry["mx7"] + ";my7=" + (gamearry["my7"]+((math.Max(0,0-(Math.Remainder(m,7)*4)+1))*(10+Math.GetRandomNumber(20)))) + ";md7=" + gamearry[(gamearry["md7"]*(math.Max(-1,0-(Math.Remainder(m,7)*4)+1)))] + ";m7=" + gamearry["m7"]


ElseIf (gamearry["my"+m] >= GraphicsWindow.Height-15) Then
' alien has reached the bottom - decrease life and reset alien.
gamearry = "1=-1;-1=1;moveables=" + gamearry["moveables"] + ";lives=" + (gamearry["lives"]-1) +";ammo=" + gamearry["ammo"] +";score=" + gamearry["score"] +";aspeed=" + (gamearry["aspeed"]-0.5) +";mx1=" + gamearry["mx1"] + ";my1=" + gamearry["my1"] +";mxo1=" + gamearry["mxo1"] + ";myo1=" + gamearry["myo1"] + ";m1=" + gamearry["m1"] +";mx2="+(GraphicsWindow.MouseX-25)+";my2="+(GraphicsWindow.Height-50)+";m2=" + gamearry["m2"] +";mxo3=" + gamearry["mxo3"] +";myo3=" + gamearry["myo3"] +";mx3=" + ((GraphicsWindow.Width/2)-160) + ";my3=20;md3=" + gamearry["md3"] + ";m3=" + gamearry["m3"] + ";mxo4=" + gamearry["mxo4"] + ";myo4=" + gamearry["myo4"] + ";mx4=" + ((GraphicsWindow.Width/2)-80) + ";my4=20;md4=" + gamearry["md4"] + ";m4=" + gamearry["m4"] + ";mxo5=" + gamearry["mxo5"] + ";myo5=" + gamearry["myo5"] + ";mx5=" + (GraphicsWindow.Width/2) + ";my5=20;md5=" + gamearry["md5"] + ";m5=" + gamearry["m5"] + ";mxo6=" + gamearry["mxo6"] + ";myo6=" + gamearry["myo6"] + ";mx6=" + ((GraphicsWindow.Width/2)+80) + ";my6=20;md6=" + gamearry["md6"] + ";m6=" + gamearry["m6"] + ";mxo7=" + gamearry["mxo7"] + ";myo7=" + gamearry["myo7"] + ";mx7=" + ((GraphicsWindow.Width/2)+160) + ";my7=20;md7=" + gamearry["md7"] + ";m7=" + gamearry["m7"]


ElseIf Mouse.IsLeftButtonDown Then
' fire button pressed
gamearry = "1=-1;-1=1;moveables=" + gamearry["moveables"] + ";lives=" + gamearry["lives"] +";ammo=" + (gamearry["ammo"]+1) +";score=" + gamearry["score"] +";aspeed=" + gamearry["aspeed"] +";mx1=" + (GraphicsWindow.mousex) + ";my1=" + (GraphicsWindow.Height-45) +";mxo1=" + gamearry["mxo1"] + ";myo1=" + gamearry["myo1"] + ";m1=" + gamearry["m1"] +";mx2="+(GraphicsWindow.MouseX-25)+";my2="+(GraphicsWindow.Height-50)+";m2=" + gamearry["m2"] +";mxo3=" + gamearry["mxo3"] +";myo3=" + gamearry["myo3"] +";mx3=" + gamearry["mx3"] +";my3=" + gamearry["my3"] +";md3=" + gamearry["md3"] + ";m3=" + gamearry["m3"] + ";mxo4=" + gamearry["mxo4"] + ";myo4=" + gamearry["myo4"] + ";mx4=" + gamearry["mx4"] + ";my4=" + gamearry["my4"] + ";md4=" + gamearry["md4"] + ";m4=" + gamearry["m4"] + ";mxo5=" + gamearry["mxo5"] + ";myo5=" + gamearry["myo5"] + ";mx5=" + gamearry["mx5"] + ";my5=" + gamearry["my5"] + ";md5=" + gamearry["md5"] + ";m5=" + gamearry["m5"] + ";mxo6=" + gamearry["mxo6"] + ";myo6=" + gamearry["myo6"] + ";mx6=" + gamearry["mx6"] + ";my6=" + gamearry["my6"] + ";md6=" + gamearry["md6"] + ";m6=" + gamearry["m6"] + ";mxo7=" + gamearry["mxo7"] + ";myo7=" + gamearry["myo7"] + ";mx7=" + gamearry["mx7"] + ";my7=" + gamearry["my7"] + ";md7=" + gamearry["md7"] + ";m7=" + gamearry["m7"]
EndIf
EndFor

' show status in titlebar
GraphicsWindow.Title = "SBace-Invaders-25: SCORE=" + gamearry["score"] + " LIVES=" + gamearry["lives"]

EndWhile

' Game Over!
GraphicsWindow.ShowMessage ("Well Done, you scored: " + gamearry["score"] + " and your Skill = " + Math.Floor((gamearry["score"]/gamearry["ammo"])*100) + "%", "<<< G-A-M-E O-V-E-R >>> ")



' =========================================================================================================
'
' NOTES: This looks more complex than it really is. Instead of defining any variables, I am using the array to handle everything.
' Unfortunately this means that every time I change a variable, I have to completely rebuild the array, hence the long 'gamearry' lines (yeah, they're LONG!)
' If you compare them though, you'll see that only one, or maybe two, values change each time.
' To cut down on lines, I'm also using the ElseIf's to handle the various checks, which means I only need one endif.
'
' moveables = number of sprites to be moved (processed) each mainloop cycle
' The strange '1=-1;-1=1' elements, along with 'md3,4,etc', allow me to simulate a logical 'NOT' type function when I need to bounce the alien. (i.e. md3=NOT md3)
' mxo, myo are the offsets for each object (to centre object over its x,y)
' md3,4,5,etc. are the direction of individual aliens (-1,+1)
'
' Note that the calculations for collisions with alien 1 (m3) are slightly different in the arrays, due to 3 dividing into 3 and 6 without remainders.
' If adding more aliens, the same issue will be found with alien 2 (m4) and new alien 6 (m8), etc.
'
' CALCULATION TO RESET ALIEN WHEN HIT BY BULLET = (gamearry["my3"]-(gamearry["my3"]*(math.Max(0,0-(Math.Remainder(m,3)*2)+1))))
' which 1) calculates the remainder of the alien number being checked divided by the loop number = No remainder for alien being processed!
' then 2) multiplies the remainder by 2. Alien being processed stays as zero (as zero remainder times 2 still = zero)!
' then 3) make value negative, then add one to the result. Alien being processed gets a value of 1, all others remain negative.
' then 4) gets the highest (max) value comparing zero and the above result. Negatives give us zero, while alien being processed gives us 1.
' then 5) multiply the y position of the alien by the above result. Gives us zero if this is not the alien being processed.
' then 6) subtract the result above from the alien y position. If this is the alien being processed, it gets returned to the top of the screen. Yay!
'
' (c) Dave~Wavey, 2009. Please use this code only to produce further examples for the Small Basic forum to help others learn.