Invadir 13 - Caught in the Crossfire
|
IF YOU HAVE NOT TIDIED UP YOUR SCRIPTS AND MADE PREPARATIONS FOR THE NEXT STEPS AS SUGGESTED IN THE PREVIOUS LESSON, PLEASE GO BACK AND DO SO NOW! |
Sorry to shout, but we're about to introduce some extra complexity into the game and if you are to retain your sanity and sense of self worth it is important that as many loose ends are tied up as possible before the new stuff throws the whole thing out of control.
The next step is to refine the bullet script so that it can be fired from both the cannon and the invaders. We'd also like to have more than one bullet. It has taken me some time to put my thoughts in order about presenting this next part of the tutorial. Those of you who have watched the tutorial appear lesson by lesson may already have attempted to implement multiple bullets yourself in the interim. You will probably have found it quite complicated.
Do not be afraid of complexity.
One of the main reasons for choosing an object-oriented approach
is that it formalises the process of managing complex systems.
You have already seen this in action with the invaders. Before
you started this tutorial you might have imagined that a space
invader game would require long complicated handlers which 'keep
track of' all the necessary information, the speed and direction
of each invader for example. As it happens we've let Director's
existing abstraction of multiple sprite channels (a list) deal
with that so that we only need to think about one invader to program
all of them.
Encapsulation removes 'keeping track' from the equation, indeed if you are having trouble keeping track of what is going on, you have probably not encapsulated things optimally.
Now, we know that the bullet will need to be moving in two directions, depending on which sprite shoots it. What we'll do is vary the bullet's new vdirection property, then use a parameter to specify where the bullet is coming from, thus:
-- new shoot handler for the bullet script
on shoot me, whosShooting
if shooting then
return
end if
set shooting to true
set the loc of sprite mysprite to the loc of sprite whosShooting
if whosShooting = cannon then
set vdirection to -1 -- shooting upwards
else
set vdirection to 1 -- shooting downwards
end if
puppetsound soundChan, shootsound
end
Notice the whosShooting parameter which is expected along with the shoot message. This provides the starting location for the bullet and also specifies the direction.then when it comes to testing for collisions, it will be necessary to test different sprite channels depending on the direction. In the previous lesson I mysteriously changed the property name 'possibleTargets' to 'invaders' and added an extra line to the exitframe handler to set the local variable possibleTargets to the invaders list. Now you are going to see why I did that. Look at this;
-- new exitframe handler for the bullet script
on exitFrame me
if not shooting then
return
end if
set myV to the locV of sprite mySprite
if myV < 0 or myv > the height of the rect of the stage then
set shooting to false
set the locV of sprite mysprite to offstage
return
end if
if vdirection = 1 then
set possibleTargets to [cannon]
else
set possibleTargets to invaders
end if
repeat with target in possibleTargets
if sprite mysprite intersects target then
hit sprite target
if target = cannon then
-- End of life
else
deleteOne invaders, target
if invaders = [] then
-- End of level
end if
end if
set shooting to false
set the locV of sprite mysprite to offstage
return
end if
end repeat
set the locV of sprite mySprite to myV + (vdirection * speed)
end
So now, it is important to specify where the bullets are coming from. Go back to your cannon script and provide the extra parameter:
if the shiftDown then
shoot sprite bullet, mysprite -- sends own sprite channel as extra parameter
end if
If you run the movie now you should find that everything works exactly as before. This might be a bit disheartening after all our efforts, but I also hope you are beginning to see why we took the trouble to tidy up. Don't worry, we'll soon reap a rich harvest from all this.
For some immediate lollipops, we can get the invaders to shoot downwards without too much trouble. This is a quick fix for those impatient souls who want to see something new happening after this difficult and slightly anal exercise in order:
In true 'quick and dirty' style I'm going to use hardcoded values for this. I'll clean up in the next lesson:
-- very temporary exitframe handler for the invader script
on exitFrame me
if not alive then
return -- leave here, do nothing
end if
set myH to the locH of sprite mySprite -- current horizontal pos
if myH < 0 then -- hit left edge
set hdirection to 1
end if
if myH > stagewidth then -- hit right edge
set hdirection to -1
end if
set the locH of sprite mySprite to myH + (hdirection * speed) -- move sprite
set cannonLeft to the left of sprite 1 -- YIKES! HARDCODED!
set cannonRight to the right of sprite 1 -- WORSE, THE SAME VALUE AGAIN!
if myH > cannonLeft and myH < cannonRight then -- directly above cannon
shoot sprite 2, mysprite -- Urrgh. But it works!
end if
end
This should ensure that the bullet drops down from the invader when it is in line with the cannon. If you're lucky, you can 'steal' the bullet if you are lucky by holding down the shift key. When a baddies bullet hits the cannon there will be an error message:
Script Error: Handler not defined hit sprite target #hit |
This is a nerdy way of telling you that everything is going ok. The cannon does not understand the #hit message, but at least it has recieved it.
I hope that is gratifying enough to feel like we have not been totally wasting our time! Now read on...