Rem Zombie Attack
Rem Cory Thornsberry
Rem 8/31/07
 
` Notes:  I've included Obese's Move_Player Function
` I updated it to include foreward and backward movement
 
` Feel free to play around with the option variables
` I've included many to help you customize the game
` By default the game is easy but you can make it harder
 
Rem Startup------------------------------------------------
Sync On
Sync Rate 40
Backdrop On
Color Backdrop 0
Always Active Off
Autocam Off
Hide Mouse
 
Rem Main Variables-----------------------------------------
` Adjustable Options Block
BulletSpd=10         : ` Adjust projectile speed
StartDist=150        : ` Adjust starting distance
PDamage=5            : ` Adjust Player Damage
EDamage=1            : ` Adjust Enemy Damage
Radius=10            : ` Adjust player radius
PSpd=10              : ` Adjust player speed
ESpd=2               : ` Adjust enemy speed
Life=100             : ` Adjust starting health
 
MaxEnemies=3         : ` Maximum number of enemies
 
` Main Arrays
Dim PPos#(MaxEnemies,4)
Dim Proj#(3)
 
Rem Setup-World--------------------------------------------
INK RGB(168,168,168),0
GoSub Info_Screen : CLS 0
GoSub Setup_World
 
Rem Main Loop----------------------------------------------
do
   ` Sync loop timer
   time1=timer()
 
   ` Print Data
   Set Cursor 1,1
   INK RGB(168,168,168),0
   Print Screen FPS()," FPS at ",time2," ms" : Print
   Print "Health: ",PPos#(0,4)
   Print "Score : ",scr
 
   ` GoSubs
   GoSub Control_Player
   GoSub Control_Enemies
   If firing=1 then GoSub Projectile_Control
 
   ` Retrieve loop time
   time2=timer()-time1
 
   Sync
Loop
 
Rem Sub-Routines-------------------------------------------
Info_Screen:
   Repeat
      Set Cursor 1,1
      Print "ZOMBIE ATTACK!" : Print
      Print "     You're walking through the park and suddenly you see"
      Print "  multiple zombies in front of you.  Luckily you happen to"
      Print "  be carrying your trusty ML-251A Anti-Zombie Gun.  I think"
      Print "  you've played enough games to know what to do next."
      Print
      Print "Instructions---"
      Print
      Print "  [KeyBrd] Control: Use UP/DOWN to move and LEFT/RIGHT to Turn"
      Print "  [Mouse-] Control: Turn with the mouse and Move with LMB and RMB"
      Print "  Press [CTRL] to switch Control Schemes"
      Print "  Press [SPACE] to fire your zombie gun"
      Print "  Don't let the zombies touch you"
      Print "  Survive! And kill all zombies"
      Print
      Print "  Press any Key to Start"
      Sync
   Until ScanCode() > 0
Return
 
Setup_World:
   ` Use trig to spread enemies evenly
   PPos#(0,1)=320 : PPos#(0,2)=240
   PPos#(0,3)=0 : PPos#(0,4)=Life
   For n=1 to MaxEnemies
      ` Evaluate using "law of sines"
      PPos#(n,4)=Life
      PPos#(n,3)=(360/MaxEnemies)*(n-1)
      PPos#(n,2)=PPos#(0,2)+((Sin(PPos#(n,3)))/(Sin(90)/startdist))
      PPos#(n,1)=PPos#(0,1)+SQRT(startdist^2-(PPos#(0,2)-PPos#(n,2))^2)
   next n
 
   ` Draw Cursor
   INK RGB(255,0,255),0
   Line 12,0,12,24
   Line 0,12,24,12
   Get Image 1,0,0,24,24
Return
 
Control_Player:
   If PPos#(0,4) <= 0 then Game_Over("lose",0)
 
   ` Rotation
   If ROTctrl = 1
      ` Rotation using keyboard
      If LeftKey()=1 then PPos#(0,3)=Wrapvalue(PPos#(0,3)+4)
      If RightKey()=1 then PPos#(0,3)=Wrapvalue(PPos#(0,3)-4)
      ` Movement using keyboard
      If UpKey()=1 then OBESE_Move_Player(0,1,PSpd)
      If DownKey()=1 then OBESE_Move_Player(0,-1,PSpd)
   Else
      ` Rotation using mouse
      Sprite 1,MouseX()-12,MouseY()-12,1
      Show Sprite 1
      PPos#(0,3)=CT_Mouse_Control()
      If MouseClick() > 0
         If MouseClick()=1 then OBESE_Move_Player(0,1,PSpd)
         If MouseClick()=2 then OBESE_Move_Player(0,-1,PSpd)
      EndIf
   EndIf
 
   ` Zombie Gun
   If firing=0 and SpaceKey()=1
      firing=1
      Fire_Zombie_Gun()
   EndIf
 
   ` Input Control
   If ControlKey()=1
      If rest=0
         If ROTCtrl=0 then ROTCtrl=1 else ROTCtrl=0 : Hide Sprite 1
         rest=25
      EndIf
   EndIf
 
   If rest > 0 then DEC rest
Return
 
Control_Enemies:
   If scr < MaxEnemies
      For n=0 to MaxEnemies
         ` Dumb AI (Chase)
         If n > 0 and PPos#(n,4) > 0
            INK RGB(168,168,168),0
            Center Text PPos#(n,1),PPos#(n,2)+(Radius+2),STR$(PPos#(n,4))
            DeltaX#=PPos#(0,1)-PPos#(n,1)
            DeltaY#=PPos#(0,2)-PPos#(n,2)
            PPos#(n,3)=CT_ATAN_Full(DeltaX#,DeltaY#)
            dist#=CT_Get_Dist(0,DeltaX#,DeltaY#,0,0)
            OBESE_Move_Player(n,1,ESpd)
 
            ` Projectile checking
            If firing=1
               proj_DeltaX#=Proj#(1)-PPos#(n,1)
               proj_DeltaY#=Proj#(2)-PPos#(n,2)
               If CT_Get_Dist(0,proj_DeltaX#,proj_DeltaY#,0,0) < Radius
                  PPos#(n,4)=PPos#(n,4)-PDamage
                  If PPos#(n,4) <= 0 then INC scr
                  firing=0
               EndIf
            EndIf
         EndIf
 
         ` Re-Draw Players
         If PPos#(n,4) > 0
            If n = 0 then INK RGB(0,0,255),0 else INK RGB(0,168,0),0
            Circle PPos#(n,1),PPos#(n,2),Radius
            NewX#=PPos#(n,1)+SIN(PPos#(n,3))*20
            NewY#=PPos#(n,2)+COS(PPos#(n,3))*20
            Line PPos#(n,1),PPos#(n,2),NewX#,NewY#
         EndIf
         CT_Control_Boundaries(n,Radius,MaxEnemies,PSpd,ESpd,EDamage)
      next n
   Else
      Game_Over("win",scr)
   EndIf
Return
 
Projectile_Control:
   If firing=1
      Oldx#=Proj#(1)
      Oldy#=Proj#(2)
 
      ` Kill projectile if out of bounds
      If Oldx# < 0 or Oldx# > 640 then firing=0
      If Oldy# < 0 or Oldy# > 480 then firing=0
 
      ` Move projectile foreward
      Proj#(1)=Oldx#+SIN(Proj#(3))*BulletSpd
      Proj#(2)=Oldy#+COS(Proj#(3))*BulletSpd
 
      INK RGB(255,0,0),0
      Line Oldx#,Oldy#,Proj#(1),Proj#(2)
   else
      ` Kill projectile
      firing=0
   EndIf
Return
 
Rem Functions----------------------------------------------
Function CT_Mouse_Control()
   DeltaX#=MouseX()-PPos#(0,1)
   DeltaY#=MouseY()-PPos#(0,2)
   theta#=CT_ATAN_Full(DeltaX#,DeltaY#)
EndFunction theta#
 
Function CT_ATAN_Full(deltax#,deltay#)
   If deltay# > 0
      ` If Below player object
      If ABS(deltay#)>0
         theta#=ATAN(deltax#/deltay#)
      Else
         theta#=0
      EndIf
   else
      ` If above player object then invert
      If ABS(deltay#)>0
         theta#=ATAN(deltax#/deltay#)
         theta#=Wrapvalue(theta#-180)
      Else
         theta#=0
      EndIf
   EndIf
 
   ` Fixes negative angle glitch
   If theta# < 0 then theta#=Wrapvalue(theta#)
EndFunction theta#
 
Function CT_Get_Dist(t,distx#,disty#,p1,p2)
   If t=0
      dist#=SQRT((distX#^2)+(disty#^2))
   Else
      DeltaX#=PPos#(p1,1)-PPos#(p2,1)
      DeltaY#=PPos#(p1,2)-PPos#(p2,2)
      dist#=SQRT((DeltaX#^2)+(DeltaY#^2))
   EndIf
EndFunction dist#
 
Function CT_Control_Boundaries(p,radius,max,spd1,spd2,edam)
   If PPos#(p,1) < Radius then PPos#(p,1)=Radius
   If PPos#(p,2) < Radius then PPos#(p,2)=Radius
   If PPos#(p,1) > 640-Radius then PPos#(p,1)=640-Radius
   If PPos#(p,2) > 480-Radius then PPos#(p,2)=480-Radius
   If PPos#(p,4) > 0
      For x=0 to max
         If PPos#(x,4) > 0
            If x < p or x > p
               dist#=CT_Get_Dist(1,0.0,0.0,p,x)
               If dist# < radius*2
                  If p=0
                     PPos#(0,4)=PPos#(0,4)-edam
                     OBESE_Move_Player(p,-1,spd1)
                  Else
                     If x=0 then PPos#(0,4)=PPos#(0,4)-edam
                     OBESE_Move_Player(p,-1,spd2)
                  EndIf
               EndIf
            EndIf
         EndIf
      next x
   EndIf
EndFunction
 
` Modified Move_Player Function
` Original Version by Obese
` New Version by Roddman
Function OBESE_Move_Player(p,d,v)
   ` Now supports foreward and backward movement
   ` d of 1 = Foreward, d of -1 = Backward
   PPos#(p,1)=(PPos#(p,1)+(0.25*(sin(PPos#(p,3))*(d*v))))
   PPos#(p,2)=(PPos#(p,2)+(0.25*(cos(PPos#(p,3))*(d*v))))
EndFunction
 
Function Fire_Zombie_Gun()
   Proj#(3)=PPos#(0,3)
   Proj#(2)=PPos#(0,2)
   Proj#(1)=PPos#(0,1)
EndFunction
 
Function Game_Over(string$,score)
   If Lower$(string$)="win"
      INK RGB(0,255,0),0
      string$="You Win! Final Score: "+STR$(score)
      Center Text 320,240,string$
   Else
      INK RGB(255,0,0),0
      Center Text 320,240,"You Lose, Please Play Again!"
   EndIf
EndFunction