|
|||
|
Last things Term Project Specs PLP Team Assignments Key control code Including Blackjack Including game prototype How to Lingo Sample How to Lingo Summary Blackjack project How to Lingo midterm Fallout Game, Part 1 Walker-scroller project Lingo Walker project Unique random selection Case assignment Scripted animation Hints for Part 3 Term project Timeline vs. scripting Materials from UB Course "How To Lingo" Project Syllabus |
Fallout Game, Part 1Today we'll transform a version of the walker-scroller game prototype into an actual game. Games require several basic elements: a situation or problem; a means of play or control; a way of keeping score; and at least one outcome (winning or losing). Our prototype has some but not all these elements. In one version, for instance, you can maneuver the walker left and right across the screen--the element of control. But there's no particular purpose to his movements. In this revision we'll throw in some positive reinforcement (magic, score-increasing orbs) as well as some negative (cinderblocks falling from a great height). 1. Download the file falloutStart.dir from the usual class directory. Be SURE you download this file before opening it! Once you have it on your local hard drive, open the file. 2. Look in the Cast for a PNG depicting a red sphere. Drag this sprite to the first frame of channel 10 of your movie. Use the Property Inspector to extend this sprite to two frames. 3. In the Cast, right-click on the red sphere ("smallOrb") and open its Cast Member Script. Replace the default mouseUp handler with an enterFrame handler. Inside that handler enter the following:
global theScore
--vertical movement of orb
if sprite(10).locV < 450 then
sprite(10).locV = sprite(10).locV + 20
else -- fallen sprite moves with background
sprite(10).locH = sprite(10).locH - 20
end if
--when sprite goes offstage left, reset
if sprite(10).locH < -45 then
sprite(10).locH = random(640)
sprite(10).locV = 0 - random(300)
end if
4. Test your movie. The red ball should drop to a point somewhere below the walker's feet, at which point it should move horizontally offstage, synchronized with the scenery, as if it had hit the ground. If your movie works properly, save it. 5. We want the walker to be able to intercept the magic orb and be rewarded for so doing. So we need to add some code that tests for contact between the walker and the orb. Within the Cast Member Script for the orb (which you should still have open), and below the last line you added in Step 3, add the following lines:
--collision check
if sprite(10).intersects(sprite(3)) then
theScore = theScore + 500
Member("scoreField").text = string(theScore)
orbReset()
end if
The expression sprite(x) intersects(sprite(y)) resolves to TRUE or 1 if the rectangles of the two sprites overlap at any point. Otherwise it is FALSE or 0. We're using a variable called theScore. I saved you a step by including code in the main Movie Script to declare this variable as global and initialize it to zero. Note that you can never call your scoring variable simply score -- that word is reserved in Lingo, since the structure of your frames is built in something called a Score (!). Also note that we can't just plug theScore into our display field scoreField, because fields in Director want to display text, not numbers. So we apply the string() method which does the conversion from number to text or string. Now we come to a part of the script that won't work yet -- that line orbReset(). As you can tell from those parentheses, this line invokes what in Lingo is called a custom handler (or in other languages, a function). We'll write that handler in the next step. 6. AFTER the end enterFrame statement enter the following handler: on orbReset() sprite(10).locH = random(640) sprite(10).locV = 0 - random(300) end orbReset These lines should look familiar. They're the same lines we typed above to reset the orb once it drifted offscreen. We could simply have echoed these lines in the collision test part of the enterFrame handler, but we save a few keystrokes by pulling them out into their own custom handler since they're needed by two different parts of the main script. Take note of what we've done here, streamlining our code by allowing certain lines to work in multiple contexts. This is called multipurposing or abstracting code function. It's enormously important to scripters. Now that we've abstracted the reset function for the orb, we can cut out those lines that randomize locH and locV back up in the enterFrame handler. Replace them with the single line orbReset(). Test your movie (or game) by trying to make the walker bump into the orb. When you succeed your score should increase by 500 points and the orb should vanish, shortly to reappear somewhere up above. 7. Now for the negative reinforcements. In the Cast, find the image of a cinderblock and create a sprite for this cast member in frame 1 of channel 11. Use the Property Inspector to stretch this sprite to 2 frames. 8. Check in your Score to be sure both frames of the sprite in channel 11 (the cinderblock) are selected. If they are, then make your Stage visible and right-click on the cinderblock image. Open its Sprite Script by selecting Script from the menu. 9. Remove the default mouseUp handler and substitute an enterFrame. Within this handler, insert the following line of code: dropBlock(the spriteNum of me) As you'll see directly, this one little line of code will end up doing a lot of work. Technically speaking it connects the sprite in channel 11 with a custom handler called drobBlock(). This is another chunk of multi-purpose code, which we're about to create. 10. Find the main Movie Script in the Cast (member 24; or look for the script featuring "startMovie"). Open this script. Below the startMovie handler, add the following lines:
on dropBlock(whichSprite)
global theScore
--vertical movement
if sprite(whichSprite).locV < 450 then
sprite(whichSprite).locV = sprite(whichSprite).locV + 25
else -- if sprite has fallen, it moves with background
sprite(whichSprite).locH = sprite(whichSprite).locH - 20
end if
--when block goes offstage left, reset its position offstage above
if sprite(whichSprite).locH < -45 then
sprite(whichSprite).locH = random(640)
sprite(whichSprite).locV = 0 - random(300)
--score increases when a block leaves the stage
theScore = theScore+50
Member("scoreField").text = string(theScore)
end if
--collision check
if sprite(whichSprite).intersects(sprite(3)) then
theScore = theScore - 100
Member("scoreField").text = string(theScore)
if theScore < 0 then
theScore = 0
go to "ouch"
end if
end if
end dropBlock
You should recognize most of this code as a slight variation on the code we wrote for the falling orb. One thing is different, though -- instead of referring to a particular sprite number we keep typing sprite(whichSprite). The variable whichSprite is called an argument that is passed to this handler from the sprite that invokes it. That is, the cinderblock sprite in channel 11 calls up this custom handler from the main movie script and tells it to use the number 11 wherever the variable whichSprite appears. While it may seem a bit confusing, this procedure lets us use the drobBlock() custom handler with a sprite IN ANY CHANNEL -- and with AS MANY SPRITES AS WE LIKE. To test this proposition, create new sprites of the cinderblock image in channels 12 and 13. Repeat Steps 8 and 9 for each of the new sprites, adding the script that links the sprites to the custom handler. Now test your movie. There should be three cinderblocks in action as well as the magic orb -- and all without having to change a single line in the custom handler. 11. Finally I'll point out a deliberate flaw in the project and challenge you to work out a solution. If you watch the score window closely, you'll see that the score goes down by more than 100 points when a cinderblock collides with the poor walker. Actually the score goes down continually so long as the block is passing through our miserable hero. Can you think of a way to correct this problem? | ||
|
|||