Back to Lesson 6
Forward to Lesson 8

Lesson 7 - Messages between Objects

Great going so far, although we really want the shoot message to come from somewhere other than the message window. Remember the message window will not be there in the finished product. We also need something easy for the user so that they can shoot quickly. We could use the mouse button, but I'd rather not because if you click outside Director accidentally the movie will stop running and you'll bring some other application to the front. This is irritating (believe me) so it might be better to use the keyboard.

We could get the bullet to check the keyboard when it is not shooting but it might be conceptually better for the cannon to do this and for the shoot message to come from the cannon. We also want the invader to be able to shoot bullets. We can now apply what we now know about properties and the beginsprite message to the cannon script:

property mySprite, bullet

on beginsprite me

  set mySprite to the spritenum of me
  set bullet to 2

end

on exitFrame me

  set stagewidth to the width of the rect of the stage

  if the mouseH > 0 and the mouseH < stagewidth then

    set the locH of sprite mySprite to the mouseH

  end if

  if the shiftDown then

    shoot sprite bullet

  end if

end

When you run the movie you will find that pressing the shift key on the keyboard launches a bullet from the cannon. When the bullet disappears from the screen it is ready to be shot again. Notice that it is the cannon which monitors the state of the shift key (use of non 'modifier' keys is more complicated) and sends a message to the sprite specified by its bullet property. Now we have to turn out attention to collisions between the bullet and its targets so that the invaders can be hit by the bullet.

Director provides several convenient features for collisions and intersections. We are going to use the easiest and most accurate. Let's look again at the exitframe handler of the bullet script.

on exitFrame me

  if shooting then

    set myV to the locV of sprite mySprite

    if myV < 0 then

      set shooting to false
      set the locV of sprite mysprite to -999
      return

    end if

    set the locV of sprite mySprite to myV - 1

  end if

end

After the first test (shooting) has proved true, we therefore know that the bullet is moving. It is at this moment that we test whether the bullet has moved offstage, and it is therefore at this moment that we test for collisions. For now we'll test for collisions with only the first of our invaders, the one in channel 3.

on exitFrame me

  if shooting then

    set myV to the locV of sprite mySprite

    if myV < 0 then

      set shooting to false
      set the locV of sprite mysprite to -999
      return

    end if


    if sprite mysprite intersects 3 then

      hit sprite 3

    end if

    set the locV of sprite mySprite to myV - 1

  end if

end

Once again, we are using a custom message, hit , addressed to sprite 3, but if we run the movie now, a collision between the bullet and the invader in sprite channel 3 will produce an error, 'handler not defined'. This is because the script attached to sprite 3 has no way of handling the message.

There are ways of avoiding the error without adding an extra handler to the invader script, but in this case the error message indicates our next step. We need to get the invader to respond to the hit message by adding the necessary handler. Here is how the invader script will look just after we have added the skeleton for the new hit handler:

property mySprite, hdirection, stagewidth

on beginsprite me

  set mySprite to the spritenum of me
  set hdirection to 1
  set stagewidth to the width of the rect of the stage

end

on exitFrame me

  set myH to the locH of sprite mySprite

  if myH < 0 then

    set hdirection to 1

  end if

  if myH > stagewidth then

    set hdirection to -1

  end if

  set the locH of sprite mySprite to myH + hdirection

end

on hit me

   
end

...and if all we wanted was to avoid the 'handler not defined' error, this would do just fine, only we want the invader to stop doing what it was doing and die. This requires something similar to the state variable shooting in the bullet script. We could add a property called alive so that the invader only moved from side to side if alive were true. This is how the script would look if we did this.

property mySprite, hdirection, stagewidth, alive

on beginsprite me

  set mySprite to the spritenum of me
  set hdirection to 1
  set stagewidth to the width of the rect of the stage
  set alive to true

end

on exitFrame me

  if not alive then 

    return 

  end if 

  set myH to the locH of sprite mySprite 

  if myH < 0 then 

    set hdirection to 1 

  end if 

  if myH > stagewidth then 
    set hdirection to -1 
  end if 

  set the locH of sprite mySprite to myH + hdirection 
end 

on hit me 
  set alive to false 
  set the locH of sprite mySprite to -999 
end

Later we will modify this so that the invader will run a little animation while it is dying. This means that simple alive and not alive will not be adequate to describe the different kinds of behevior we want from the invader.

Now at last we have some gameplay. Run the movie and try and shoot at sprite 3. If you are successful, sprite 3 should disappear. This is fine, but what about the other invaders?

 

Forward to Lesson 8