8. Projectiles

Whether you want to launch plasma, magic or fruit, a projectile algorithm is what you are looking for. It might sound simple enough but when you start to break it down and think it through it is quite an involved process. Not necessarily complicated, just a lot of little things to keep track of.

  1. Setup collisions between projectiles and the targets
  2. Create a new projectile every time the "fire key" is pressed
  3. Update the location of each new projectile
  4. Check for collisions
  5. Switch to an explosion animation if collided
  6. Remove the object the projectile collided with

Phew! This might seem like the toughest of all 12 lessons but most of it involves code you've already used. You don't have to understand it all at once and the important parts you will understand.


If you haven't already downloaded the tutorial files do so now, unzip to your desktop and OPEN up lesson8.bb, functions8.bb, and loadworld8.bb (below) and RUN / LANUCH the lesson8.bb program by pressing the ROCKET ICON

and you should see this...

NEW CODE is BOLD.

Here's the CODE!
lesson8.bb

Include "functions8.bb"

Global escape_key = 1
Global screen_width = 640, screen_height = 480

Graphics3D screen_width, screen_height, 16, 2
SetBuffer BackBuffer()


; Add projectile type
Global coll_player = 1, coll_characters = 2, coll_objects = 3, coll_projectile = 4

; Add projectiles to the collision list
Collisions coll_projectile, coll_characters, 1,1
Collisions coll_characters, coll_player, 1, 2
Collisions coll_player, coll_characters, 1, 2
Collisions coll_player, coll_objects, 1, 2
Collisions coll_characters, coll_characters, 1, 2
Collisions coll_characters, coll_objects, 1, 2

AmbientLight 200, 200, 200

light1 = CreateLight(2)

cam1 = CreateCamera()
CameraViewport cam1, 0, 0, screen_width, screen_height

Include "loadworld8.bb"

LoadMusic()
LoadSFX()

MoveMouse screen_width/2, screen_height/2

While Not KeyHit( escape_key )

   ; Keep any projectiles and explosions going
    UpdateProjectiles()

    MoveCharacters( player )
    If run_vol# > 0 Then AnimSprite( player, anim_tex, 200, 4 )
    object_key_control( player )
    ChannelVolume runchannel, run_vol#
    PositionEntity sky, EntityX( player ), EntityY( player ), EntityZ( player )

    UpdateWorld
    RenderWorld

    ; 2D here


Flip
Wend

End


loadworld8.bb

; Add projectile Type
Type Projectile
   Field sprite, time_out
End Type


; Add Explosion Type
Type Explosion
   Field sprite, scale#
End Type
. . .
; Load Projectile Sprites
explosion_sprite = LoadSprite( "explosion.bmp" )
HideEntity explosion_sprite

projectile_sprite = LoadSprite( "heart.bmp" )
EntityRadius projectile_sprite, 2
EntityType projectile_sprite, coll_projectile
HideEntity projectile_sprite
. . .


functions8.bb

. . .
; Add projectile variables
Global player, projectile_sprite, explosion_sprite, hit, shoot, boom

Function LoadSFX()
   ; Load projectile sounds
   shoot = LoadSound( "shoot.wav" )
   SoundVolume shoot, .9
   boom = LoadSound( "boom.wav" )
   SoundVolume boom, .5

   . . .
End Function

Function object_key_control( obj )
   ; Add spacebar = fire
   If KeyHit(57) Then CreateProjectile( player )
   . . .
End Function

Function UpdateProjectiles()
   For P.Projectile = Each Projectile
      UpdateProjectile( P )
   Next
   For E.Explosion = Each Explosion
      UpdateExplosion( E )
   Next
End Function

Function CreateProjectile.Projectile( source )
   P.Projectile = New Projectile
   P\time_out = 150
   P\sprite = CopyEntity( projectile_sprite, source )

   ; Don't want projectiles coming out of player's feet :)
   MoveEntity P\sprite, 0, 2, 0
   EntityParent P\sprite, 0
   shootChannel = PlaySound ( shoot )
   Return P
End Function

Function UpdateProjectile( P.Projectile )
   If CountCollisions( P\sprite )
      If EntityCollided( P\sprite, coll_characters )
         For k = 1 To CountCollisions( P\sprite )
            hit = CollisionEntity( P\sprite, k )
            If GetEntityType( hit ) = coll_characters
               Exit
            EndIf
         Next
         boomChannel = PlaySound (boom)
         CreateExplosion( P )
         FreeEntity P\sprite
         Delete P
         Return
      EndIf
   EndIf
   P\time_out = P\time_out - 1
   If P\time_out = 0
      FreeEntity P\sprite
      Delete P
      Return
   EndIf
   MoveEntity P\sprite, 0, 0, 1
End Function

Function CreateExplosion.Explosion( P.Projectile )
   E.Explosion = New Explosion
   E\scale = 1
   E\sprite = CopyEntity( explosion_sprite, P\sprite )
   EntityParent E\sprite, 0
   Return E
End Function

Function UpdateExplosion( E.Explosion )
   If E\scale < 5
      E\scale = E\scale + .2
      ScaleSprite E\sprite, E\scale, E\scale
   Else
      FreeEntity E\sprite
      Delete E
      For Character.Sprite = Each Sprite
         If Character\ID = hit Then Delete Character : FreeEntity hit
      Next
   EndIf
End Function
. . .


NEW COMMANDS
lesson8.bb

. . .
; Add projectile type
Global coll_player = 1, coll_characters = 2, coll_objects = 3, coll_projectile = 4

; Add projectiles to the collision list
Collisions coll_projectile, coll_characters, 1,1
. . .
While Not KeyHit( escape_key )

   ; Keep any projectiles and explosions going
    UpdateProjectiles()
. . .

asdasdasd

loadworld8.bb

; Add projectile Type
Type Projectile
   Field sprite, time_out
End Type


; Add Explosion Type
Type Explosion
   Field sprite, scale#
End Type
. . .
; Load Projectile Sprites
explosion_sprite = LoadSprite( "explosion.bmp" )
HideEntity explosion_sprite

projectile_sprite = LoadSprite( "heart.bmp" )
EntityRadius projectile_sprite, 2
EntityType projectile_sprite, coll_projectile
HideEntity projectile_sprite
. . .

asdasd

functions8.bb

. . .
; Add projectile variables
Global player, projectile_sprite, explosion_sprite, hit, shoot, boom

Function LoadSFX()
   ; Load projectile sounds
   shoot = LoadSound( "shoot.wav" )
   SoundVolume shoot, .9
   boom = LoadSound( "boom.wav" )
   SoundVolume boom, .5

   . . .
End Function

Function object_key_control( obj )
   ; Add spacebar = fire
   If KeyHit(57) Then CreateProjectile( player )
   . . .
End Function

Function UpdateProjectiles()
   For P.Projectile = Each Projectile
      UpdateProjectile( P )
   Next
   For E.Explosion = Each Explosion
      UpdateExplosion( E )
   Next
End Function

Function CreateProjectile.Projectile( source )
   P.Projectile = New Projectile
   P\time_out = 150
   P\sprite = CopyEntity( projectile_sprite, source )

   ; Don't want projectiles coming out of player's feet :)
   MoveEntity P\sprite, 0, 2, 0
   EntityParent P\sprite, 0
   shootChannel = PlaySound ( shoot )
   Return P
End Function

Function UpdateProjectile( P.Projectile )
   If CountCollisions( P\sprite )
      If EntityCollided( P\sprite, coll_characters )
         For k = 1 To CountCollisions( P\sprite )
            hit = CollisionEntity( P\sprite, k )
            If GetEntityType( hit ) = coll_characters
               Exit
            EndIf
         Next
         boomChannel = PlaySound (boom)
         CreateExplosion( P )
         FreeEntity P\sprite
         Delete P
         Return
      EndIf
   EndIf
   P\time_out = P\time_out - 1
   If P\time_out = 0
      FreeEntity P\sprite
      Delete P
      Return
   EndIf
   MoveEntity P\sprite, 0, 0, 1
End Function

Function CreateExplosion.Explosion( P.Projectile )
   E.Explosion = New Explosion
   E\scale = 1
   E\sprite = CopyEntity( explosion_sprite, P\sprite )
   EntityParent E\sprite, 0
   Return E
End Function

Function UpdateExplosion( E.Explosion )
   If E\scale < 5
      ScaleSprite E\sprite, E\scale, E\scale
      E\scale = E\scale + .2
   Else
      FreeEntity E\sprite
      Delete E
      For Character.Sprite = Each Sprite
         If Character\ID = hit Then Delete Character : FreeEntity hit
      Next
   EndIf
End Function

asdasdasd
EXPERIMENT !
asdasd

THE CHALLENGE!!!
Add sdfsdfsdsdf

NEXT : Lesson 9 - HUD / MousePick