REM ***********************************************
REM Title: Parachute
REM Author: Phaelax
REM Downloaded from: http://dbcc.zimnox.com/
REM ***********************************************
 
REM ===========================
REM === PARA-TROOPER ATTACK ===
REM === Coded by: Phaelax =====
REM ===========================
 
set display mode 640,480,32
sync on
sync rate 60
backdrop on
color backdrop 0
 
 
#CONSTANT TRUE = 1
#CONSTANT FALSE = 0
 
Global ScreenWidth
Global ScreenHeight
ScreenWidth = screen width()
ScreenHeight = screen height()
rem radius of cannon's base
Global CannonRadius = 20
rem length of cannon's gun
Global CannonLength = 15
rem rate of fire (lower = faster)
Global CannonRoF = 100
rem how often a baddy tries to drop a parachute man (in milliseconds)
Global baddyDropRate = 1000
 
REM score values
pts_plane = 10
pts_trooper = 15
 
rem a bullet consists of an angle of direction,
rem speed, the state of whether it's moving or not,
rem and a position
 
type bullet
   angle as float
   speed as float
   isActive as boolean
   x as float
   y as float
endtype
 
 
maxBullets = 40
dim bullets(maxBullets) as bullet
 
rem set bullets' default speed
for t = 1 to maxBullets
   bullets(t).speed = 4
next t
 
rem direction, 1 means plane coming from left side of screen
rem and a -1 means plane coming from right side of screen
rem lastdrop, time index of when the plane last dropped a para-trooper
type baddy
   x as float
   y as float
   speed as float
   isActive as boolean
   direction as integer
   lastDrop as integer
endtype
rem enemey planes
dim baddies(20) as baddy
 
rem state, 0=not active, 1=falling, 2=on ground
rem direction, when on ground is walking left or right
type paratrooper
   x as float
   y as float
   state as integer
   direction as integer
endtype
dim troopers(20) as paratrooper
 
 
rem starting angle of gun (straight up)
cAngle# = 270
rem starting player score
playerScore = 0
rem how many para-troopers are on the ground
troopersOnGround = 0
 
 
DO
 
   gosub _keys
   gosub _check_gun_boundaries
 
   gosub _handle_bullets
 
   gosub _handle_baddies
 
   gosub _handle_troopers
 
 
   drawCannon(cAngle#)
 
 
   set cursor 0,0
   print "Score: ", playerScore
   print "Troopers on ground: ", troopersOnGround
 
   sync
LOOP
 
 
 
 
rem player controls
_keys:
   if rightkey() then inc cAngle#, 3
   if leftkey() then dec cAngle#, 3
   if spacekey() and lastShot + CannonRoF < timer()
      createBullet(cAngle#)
      lastShot = timer()
   endif
RETURN
 
 
 
rem keep from rotating the gun too far
_check_gun_boundaries:
   cAngle# = wrapvalue(cAngle#)
   if cAngle# < 200 then cAngle# = 200
   if cAngle# > 340 then cAngle# = 340
RETURN
 
 
 
rem handles active bullets (movement and calling the bullet drawing function)
_handle_bullets:
   max = array count(bullets(0))
   rem update position of all bullets
   for t = 1 to max
      rem if bullet is active
      if bullets(t).isActive = TRUE
         rem update bullet's position
         bullets(t).x = bullets(t).x + cos(bullets(t).angle)*bullets(t).speed
         bullets(t).y = bullets(t).y + sin(bullets(t).angle)*bullets(t).speed
         rem check to see if bullet is outside of screen boundaries
         if bullets(t).x < 0 or bullets(t).x > ScreenWidth or bullets(t).y < 0
            rem kill the bullet
            bullets(t).isActive = FALSE
         endif
         rem draw the bullet
         drawBullet(bullets(t).x,bullets(t).y)
      endif
   next t
RETURN
 
 
 
rem controls enemy planes and creation of para-troopers and collision with bullets
_handle_baddies:
   enemyFrequency = 3000
 
   if lastEnemy + enemyFrequency < timer()
      createNewBaddy()
      lastEnemy = timer()
   endif
 
   max = array count(baddies(0))
   bMax = array count(bullets(0))
 
   rem loop through all baddies
   for t = 1 to max
      rem if baddy is active
      if baddies(t).isActive = TRUE
         isAlive = TRUE
         rem loop through all bullets to check for collision with baddies
         for b = 1 to bMax
            rem if bullet is active
            if bullets(b).isActive = TRUE
               bx# = bullets(b).x
               by# = bullets(b).y
               ex# = baddies(t).x
               ey# = baddies(t).y
               rem if X distance between bullet and baddy is less than 20
               rem and Y distance is less than 10
               if abs(bx#-ex#) < 20 and abs(by#-ey#) < 10
                  isAlive = FALSE
                  bullets(b).isActive = FALSE
                  baddies(t).isActive = FALSE
                  inc playerScore, pts_plane
               endif
            endif
         next b
         if isAlive = TRUE
            baddies(t).x = baddies(t).x + (baddies(t).speed * baddies(t).direction)
            rem control rate of dropping para-troopers
            if baddies(t).lastDrop+baddyDropRate < timer()
               baddies(t).lastDrop = timer()
               rem make sure baddy is on screen before dropping a trooper
               if baddies(t).x > 50 and baddies(t).x < ScreenWidth-50
                  rem 50% of dropping a man
                  if rnd(1) = 1
                     createNewParatrooper(baddies(t).x, baddies(t).y)
                  endif
               endif
            endif
            rem kill baddy if flies outside of screen boundaries
            if baddies(t).direction = 1 and baddies(t).x > ScreenWidth+50
               baddies(t).isActive = FALSE
            endif
            if baddies(t).direction = -1 and baddies(t).x < -50
               baddies(t).isActive = FALSE
            endif
            rem draw the baddy
            drawBaddy(baddies(t).x, baddies(t).y, baddies(t).direction)
         endif
      endif
   next t
 
RETURN
 
 
 
 
rem handles trooper falling and walking and collision with cannon and bullets
_handle_troopers:
   rem reinitialize variable
   troopersOnGround = 0
   rem middle of screen
   mid = ScreenWidth/2
   rem max trooper count to check
   max = array count(troopers(0))
   bMax = array count(bullets(0))
   rem loop through all troopers
   for t = 1 to max
      if troopers(t).state > 0
         rem if trooper is in a falling state
         if troopers(t).state = 1
            isAlive = TRUE
            rem loop through all bullets
            for b = 1 to bMax
               rem if bullet is active
               if bullets(b).isActive = TRUE
                  bx# = bullets(b).x
                  by# = bullets(b).y
                  px# = troopers(t).x
                  py# = troopers(t).y
                  rem if bullet is within the bounding box of the trooper
                  rem if you change the trooper's dimensions, you need to change this line
                  rem to accomodate it
                  if bx#>px#-3 and bx#<px#+3 and by#<py# and by#>py#-14
                     bullets(b).isActive = FALSE
                     troopers(t).state = 0
                     isAlive = FALSE
                     inc playerScore, pts_trooper
                  endif
               endif
            next b
            rem if trooper is still alive after checking collision with bullets
            if isAlive = TRUE
               troopers(t).y = troopers(t).y + 1
               rem if trooper falls onto cannon, kill trooper
               if (troopers(t).x - mid)^2 + (troopers(t).y - ScreenHeight)^2 < CannonRadius^2
                  troopers(t).state = 0
               endif
               rem if trooper falls to ground, change its state
               if troopers(t).y >= ScreenHeight
                  troopers(t).state = 2
               endif
            endif
         endif
         rem if troop is walking on ground
         if troopers(t).state = 2
            inc troopersOnGround, 1
            troopers(t).x = troopers(t).x + troopers(t).direction
            x# = troopers(t).x
            rem change walking direction if trooper reaches either side of screen or the cannon
            if x# < 2 or x# > ScreenWidth or abs(x# - mid) < CannonRadius
               troopers(t).direction = troopers(t).direction * -1
            endif
         endif
         rem draw trooper
         drawTrooper(troopers(t).x,troopers(t).y)
      endif
   next t
RETURN
 
 
 
 
rem creates a new para-trooper
function createNewParatrooper(x as float, y as float)
   max = array count(troopers(0))
   for t = 1 to max
      if troopers(t).state = 0
         troopers(t).state = 1
         troopers(t).x = x
         troopers(t).y = y
         troopers(t).direction = 1
         rem stop searching for next available trooper
         exitfunction
      endif
   next t
 
endfunction
 
 
 
rem creates a new airplane baddy, starting with a random position and speed
function createNewBaddy()
   max = array count(baddies(0))
   rem find next available baddy in array
   for t = 1 to max
      if baddies(t).isActive = FALSE
         baddies(t).isActive = TRUE
         rem randomly start from either right or left side of screen
         side = rnd(1)
         rem start on left side
         if side = 0
            baddies(t).x = -50
            baddies(t).direction = 1
         endif
         rem start on right side
         if side = 1
            baddies(t).x = ScreenWidth + 50
            baddies(t).direction = -1
         endif
         rem start at a random height between the top of the screen (0) and 100pixels from the bottom
         baddies(t).y = rnd(ScreenHeight-100)
         rem random speed between 1-3
         baddies(t).speed = rnd(2)+1
         exitfunction
      endif
   next t
endfunction
 
 
 
rem activates a new bullet
function createBullet(angle as float)
   max = array count(bullets(0))
   rem find next available bullet, if any
   for t = 1 to max
      rem if this bullet isn't moving
      if bullets(t).isActive = FALSE
         bullets(t).isActive = TRUE
         bullets(t).angle = angle
         rem find the tip of the gun barrel
         bullets(t).x = ScreenWidth/2 + cos(angle)*(CannonRadius+CannonLength)
         bullets(t).y = ScreenHeight + sin(angle)*(CannonRadius+CannonLength)
         rem exit funtion early because we found a bullet
         exitfunction
      endif
   next t
endfunction
 
 
 
rem draws the cannon
function drawCannon(angle as float)
   s2 = ScreenWidth/2
   circle s2,ScreenHeight,CannonRadius
   sx# = s2 + cos(angle)*CannonRadius
   sy# = ScreenHeight + sin(angle)*CannonRadius
   ex# = sx# + cos(angle)*CannonLength
   ey# = sy# + sin(angle)*CannonLength
   line sx#,sy#,ex#,ey#
endfunction
 
 
 
rem draws a bullet
function drawBullet(x as float, y as float)
   dot x, y
endfunction
 
 
 
rem draw a funny looking airplane
function drawBaddy(x as float, y as float, d as integer)
   rem body
   ellipse x, y, 20,10
   rem wing
   line x-3,y,x+3,y
   line x-3,y,x-1,y+20
   line x+3,y,x+1,y+20
   line x-1,y+20,x+1,y+20
endfunction
 
 
 
 
rem draw a para-trooper
rem x,y = bottom coordinates of trooper(at its feet)
function drawTrooper(x as float, y as float)
   rem head
   circle x, y-11, 2
   rem body
   line x,y-9,x, y-4
   rem left leg
   line x,y-4,x-2,y
   rem right leg
   line x,y-4,x+2,y
   rem arms
   line x-2,y-7,x+2,y-7
endfunction