Let's suppose you want to begin working on Assignment 3 by adapting the code from the Virtual Fishtank demo (fishtankDemo1.0.fla, available on Crow). You don't have to start from this basis, but if you're new to scripting it's a relatively easy way in.
Step 1: Set Up File
Download the fishtankDemo1.0.fla file and use Save As to save it under another name.
Step 2: Add Layers
Add a layer to the timeline for each sprite that will be in the movie. There are currently two layers occupied by sprites. You'll need at least six. Each sprite must have its own layer. Name the layers appropriately.
Step 3: Create a New Sprite (Movie Clip)
In the Library, create a new Movie Clip symbol to represent an additional sprite. Add any graphics you like. Drag this Movie Clip into the single frame in one of your new layers; this will create an instance of the Movie Clip. Using the Property Inspector, set the instance name of this instance to something you can remember (e.g., "fish3"). Don't use spaces or slashes (/) in the instance name.
Step 4: Set Up a Script for the Sprite
Right-click or click-and-hold (Mac) on the new instance to bring up its scripting window. Write an onClipEvent(enterFrame) handler, or paste in a copy of the handler from one of the original sprites (fish1, fish2).
Step 5: Animation
The first demonstration example allows sprites to move only in one direction--left-to-right or right-to-left. You can give your sprites more complex options for movement but only if you're ready to write somewhat more ambitious scripts, as in the fishtank1.4 example. One-way movement is perfectly acceptable for this assignment. If this is what you want, decide which way you want your new sprite to move. In the enterFrame handler, include a line that increments the _x property (e.g., "fish3._x +=8") or one that decrements this property (e.g., "fish3._x -=8"). Incrementing means rightward movement, decrementing means leftward movement. Also include the code to reset the sprite position when it goes offscreen. If you're doing one-way movement you can leave this unchanged from the example.
Step 6: Sprite Interaction
Here you have some decisions to make. The code in the first example makes each sprite sensitive to contact with only one other sprite. Using this code unmodified, you could design a system in which each sprite can interact with only one other sprite. But let's say you want any given fish to have multiple possibilities for interaction. Here's a solution for a three-sprite system (fish1, fish2, fish3). The code shown here goes within the onClipEvent(enterFrame) handler of the "fish1" sprite. You'd need to place slightly different versions of the same code in the relevant handlers of the other two sprites as well.
if(this.hitTest(_root.fish2) && _root.bumpus == false){
_root.bumpus = true;
_root.fish2._visible = false;
this.width +=50;
this.height +=50;
}
if(this.hitTest(_root.fish3) && _root.bumpus == false){
_root.bumpus = true;
_root.fish3._visible = false;
this.width +=50;
this.height +=50;
}
Now the "fish1" sprite will respond to collisions with either of the other two sprites. As you can see, the additional If condition is just a slightly modified copy of the first. In this inefficient but relatively clear design a separate If test is required for each sprite with which the current sprite might potentially collide.
Step 7: Build Your Project to Full Scope
Add more sprites to your movie, following the steps described above. Note that each time you add a sprite you need to modify the scripts for all the other sprites if you want to allow any sprite to collide with any other.
Additional: Streamlining the Method
If all this strikes you as terribly inefficient, congratulations. Experienced designers would never use such cumbersome and repetitive structures. Here's a slightly streamlined improvement--but don't worry about it unless you feel pretty confident about scripting. Efficient code is almost always harder to understand, and the cumbersome method works just fine.
this.hitSomething = false;
if(this.hitTest(_root.fish2) && _root.bumpus == false){
this.hitSomething = true;
_root.fish2.visible = false;
}
if(this.hitTest(_root.fish3) && _root.bumpus == false){
this.hitSomething = true;
_root.fish3._visible = false;
}
//add the other four IF conditions here
if(this.hitSomething == true){
this.hitSomething = false;
_root.bumpus = true;
this.width +=50;
this.height +=50;
}
This modification pulls out three standard statements:
_root.bumpus = true; this.width +=50; this.height +=50;
and attaches them to an additional If condition that depends on yet another flag variable called this.hitSomething. That variable becomes true when any of the collision hit tests proves out--an arrangement that lets us attach the three common statements to any one of several possible preconditions. Thus we don't have to type those three statements more than once.
Unlike _root.bumpus, this.hitSomething is a local variable attached only to the current Movie Clip. We set it up this way because we want to store information only about the current Movie Clip.
Note that we reset this.hitSomething to false whenever we find it to be true. You must always reset a flag variable if you want it to operate more than once.
Note also that this modified code still requires us to reset the visibility of the Movie Clip that receives the collision within a particular If condition. Can you think of a way to streamline the code even further?
