Flash 5/Flash MX: Bouncing ball lab CHANGES FOR FLASH 8
Flash provides many facilities for animation: moving (and transforming) graphics on the screen. For example, you can put different content into each of a sequence of frames. You can also use tweening: you specify contents of two frames as well as other information and the Flash system derives the 'in-between' frame content. This lab is different. You will write code (ActionScript) to be executed during run-time to move a ball. The ball is its own movie clip resident as an instance on the main movie clip. The ball will bounce against [images of] walls, stop and re-start under the control of a button, and also change speed, under the control of an input text field.
You can (and should) change the graphics.
The critical features needed for this application are:
- A way to cause a ball [any shape] to be moved incrementally. This will be done using frame actions. The frame action code changes the _x and _y properties of the ball instance according to current settings for speed, horizontal (left-right) and vertical (up-down) directions.
- A way to determine if the ball hits a wall. More specifically, the direction of motion will be changed depending on which wall was hit. This will be done using the hitTest method of the ball instance 4 times, with parameters naming the 4 different instances representing the walls.
- A provision for the player to vary the speed of the ball. To do this, you will place an Input Text field on the screen named speed.
- A way to allow the player to stop and re-start the bouncing of the ball. This is done using a button with text on it that is a Dynamic Text field. Dynamic text fields can be changed by ActionScript. The button release event handler calls a function we name toggle. The toggle function checks caption (our name for the Dynamic Text field), either stops or re-starts the motion and changes the caption.
Start with a new project and get the Info Panel (Window/Panels/Info)on screen. Positions on screen in Flash (and most other computer applications) are given in terms of an x-y coordinate system in which the upper left corner is 0,0; x values increase moving from left to right and y values increase going down the screen. Move the mouse and notice the changes in the X Y fields on the Info Panel.
Write down what happens when you do the following, starting from the center of the stage:
- move the mouse to the right about an inch. Ans: x increases around 80
- move the mouse to the left
- move the mouse up higher on the screen
- move the mouse down lower on the screen.
- move the mouse to the upper left corner.
- move the mouse to the lower left corner.
- move the mouse to the upper right corner.
- move the mouse to the lower right corner.
Now begin your project. You will create 3 symbols in the library.
- a movie clip, called ball, containing one round shape.
- a movie clip, called wall, containing a long, flat rectangle: say 300 pixels wide and 10 pixels high.
- a button, called stopgo.
You can make your own button or use one from the common library. If you use a button from the common library, you will need to add a dynamic text box. As part of the button, click on the text tool (the A in the toolbox), using the Property panel, put in a field of type Dynamic text with the var field set tocaption.
FOR FLASH 8: keep this the var name. You will do something different for the text field that holds the speed of the button. This will be an Input text field and you will give it an instance name.
Type in the (initial) text: Stop Ball. The meaning of Dynamic is that your code can and will change the value of this text field.
Start simple, but at some point, do try to change the graphics and other aspects of the project to make it your own.
In the main movie (scene 1): add a new layer. Your project will have 3 frames and two layers. Name the first layer: board and the second (upper) layer: actions. All the graphics (that is, instances of symbols and other graphics you may choose to create) will be in the board layer. All the ActionScript code will be in the actions layer. Make sure both layers have 3 keyframes.
In the first frame of the board layer, make the following instances using the symbols you have made by dragging the symbols from the Library to the stage:
- an instance of the ball movie clip. Name it ball.
- an instance of the button. It does not need a name.
- 4 instances of the wall. Position them to make 4 sides of a box. You will need to do some rotation: Modify/Transform/Rotate. Name these instances lowerwall, upperwall, leftwall and rightwall to correspond with their positions on the stage. The screen shot below shows a stage in the middle of this process. I have created two instances of the wall and positioned them. I have just dragged a third instance of the wall to the stage and not yet named it or re-positioned it.
The re-positioning is done using Modify/Transform/Rotate 90◦CW.
The next screen shot shows the Property Panel in which you enter the name of the instance.
To reinforce your understanding of the coordinate system, click on the ball. Notice its x and y values. Move the ball and examine the values again. Your code will move the ball by assigning new values to ball._x and ball._y. The code will detect if the ball has hit a wall, by invoking what is called a built-in method of a movie clip, the hitTest method. The following fragment of code (which you will write later) checks if the ball instance overlaps with the rightwall instance. If this is the case, then a variable named lrdir changes sign. You will see that lrdir controls left versus right on the motion of the ball.
if (ball.hitTest(rightwall)) {
lrdir = -lrdir;
}
Add one more thing to the stage: an Input text field that you will name speed. Do this by clicking on the text tool, and in Property window, make it Input Text and name it speed. Put in an initial value of 100. The meaning of Input is that your player can change this value. The screen show shows the text field with 100 in it and the Properties panel indicating Input Text as the type of text field and the Var: field set to speed.
FOR FLASH 8: instead, set the instance name to speed.
Flash 8: It is necessary to re-set the speed instance of the input text field. The variable speedt is used for this. It will be used in the 2nd and 3rd frame. In the toggle function (see below), speedt is assigned the value of speed.text whenever motion is resumed. You need to use a variable such as speedt in the way described here to keep the 100 from re-appearing.
By the way, if you forget to put in a value or forget the Input Text altogether or forget to initialize variables, Flash will assume the values are zero and interpret your code accordingly. In this situation, the ball will not move. Some programming languages are fussier about such things and you will appreciate the error messages they provide.
Next, you need the Actions panel. If it is minimized (as it is in the screen shot above), click on the small arrow next to Actions. You need to have the mode for creating ActionScript be Expert mode to type in code directly. For Flash 8, the default corresponds to the Expert mode (the other mode is Script Assist). To confirm this or to change to Expert mode, click on the icon at the right of the Actions panel (pointed to by the red arrow)
Click on the stopgo button. There should be a blue box around the button. Go to the Actions panel. Type in the following:
on (release) {
_root.toggle();
}
This means: when the player uses the mouse and presses and then releases the mouse button over this button, the function _root.toggle will be invoked. You have not written toggle yet! When programming, you need to be patient with yourself. You cannot do everything at once.
Click off the button. On the timeline, click in the actions layer, add 3 keyframes. Here is an explanation of what you are trying to do. READ IT and think about it before typing in the code shown.
The first frame contains variable declarations (var statements) and the toggle function. The toggle function starts or stops action. The term 'toggle' implies something that goes back and forth between two states. The toggle function uses the value of captionto determine what to do.
Here is the code that goes in the first frame, and in the Actions panel. Read it over and then you can go back and type it into the first frame.
var continueflag = true; / This variable starts off as true: the ball is bouncing when you start the movie.var now = getTimer(); / Set to current time
var then = 0; / The variable will be re-set.
var elapsed; / Used in calculation
var numSec; / Used in calculation
var speedt = 100; / Used for input text field FLASH 8
var moveAmount; / Used in calculation
if (lrdir == undefined) {var lrdir = 1;} / The action here is different, depending on whether this is the very, very first time for this frame, or after resuming.
if (uddir == undefined) {var uddir = 1;} / See above
function toggle() { / Definition of toggle function
if (caption=="Stop ball") { / If the caption says "Stop ball", it means the ball was in motion and the code needs to stop it.
continueflag = false; / Switch the continueflag to false
caption = "Resume"; / Make the caption now say Resume.
}
else { / Start clause for the ball NOT being in motion.
speedt = speed.text; / Just in case player has changed speed FLASH 8
caption = "Stop ball"; / Change the caption to say Stop ball.
now = getTimer(); / Set now so it will give a good result in the (now – then) calculation
continueflag = true; / Set flag to get ball to move
gotoAndPlay(2); / Go to next frame. (Avoids re-setting the speedt variable.
} / End the else clause
} / End the function definition.
The first set of lines are var statements. These set up variables to be used by the project. Their use will become clearer as you see the rest of the script.
continueflag / controls whether the ball is moving or at rest. We start it off by being truenow / set to the current number of milliseconds since the project began. GetTimer() is a built-in function.
then / used with now
elapsed / will hold elapsed time (now – then)
numSec / will hold elapsed/1000
moveAmount / will hold speed times numSec, the amount we want to move the ball based on elapsed time and the speed.
The next two lines set up and initialize lrdir and uddir. It is done in this way to preserve the direction of motion after stopping and re-starting the ball moving. Remember that for motion on a computer screen, you need to handle left and right (horizontal motion) and up and down (vertical motion) separately.
The next part of the script defines the togglefunction. You have already set up the on (release) action to call this function. The on (release) is called an event handler. The code says: when the on-screen button is clicked and released, call thetoggle function. The captionis what you set up when defining the button symbol. Your code uses it to toggle (English meaning of the term) back and forth by changing the value of continueflag, the value of the caption, and either allow the normal progression of Flash to go to frame 2 or use the gotoAndPlay method to re-start the movie at frame 1. While the button is in motion, the action is from frame 2 to frame 3 to frame 2 to frame 3 and so on.
Now we move to explain the code for the second frame in the actions layer. You have previously made this a keyframe. If you have not done so, do it now. In the Actions panel (in Expert mode), write the following:
then = now;
now = getTimer();
elapsed = now - then;
numSec = elapsed/1000;
moveAmount = speed * numSec; // see below
FLASH 8 replace previous line with the next 2 lines:
speed.text = speedt;
moveAmount = speed.text * numSec;
ball._x += (lrdir * moveAmount);
ball._y += (uddir * moveAmount);
if (ball.hitTest(rightwall)) {
lrdir = -lrdir;
}
if (ball.hitTest(leftwall)) {
lrdir = -lrdir;
}
if (ball.hitTest(upperwall)) {
uddir = -uddir;
}
if (ball.hitTest(lowerwall)) {
uddir =-uddir;
}
Follow this explanation by looking at the code. Make sure you understand what line or lines do the indicated action:
- Set the variable then to the value of now and make now the current time.
- Calculate the elapsed time (in milliseconds).
- Calculate the elapsed time in seconds.
- Use the formula, distance equals speed times time to calculate the amount to move the ball.
- Move the ball horizontally the indicated amount in the appropriate direction!
- Move the ball vertically the indicated amount in the appropriate direction.
- Apply 4 tests, using 4 ifstatements. In each of the specific cases, if the hitTest is true, the direction changes. Note: you could combine these into 2 statements, such as
if ((ball.hitTest(rightwall) || (ball.hitTest(leftwall)) {lrdir = - lrdir;}
if ((ball.hitTest(upperwall) || (ball.hitTest(lowerwall)) {uddir = - uddir;}
The lrdir term or the uddir term are each changing from 1 to -1 or -1 to 1.
This frame is where the movement occurs. Flash movies cycle through the frames unless code directs them to do otherwise. The next, the third, which is also, the last frame, checks if movement is to continue. Click on the third frame in the actions layer and type in the following:
speed.text = speedt; //Flash 8
if (continueflag) {
gotoAndPlay(2);
}
else {stop();}
The if test checks the continueflag. If this is true, we want to continue the animation. This is done by going to the second frame (not the first). If continueflag has been set to be false (which would have been done if the toggle function was called), then everything stops. To be more accurate: changing from frame to frame of the main movie stops. However, the Flash system still 'listens' for the release event of the button. This will re-start the animation. The Flash system also allows the player to change the value in the speed text field. Your code in frame 2 of the actions layer uses whatever is there. Now go back and enter in the code for the 3 frames. Experiment. You will notice that if you make the speed high enough, the ball will go outside the walls before turning around.
HINT: In Flash, the order in which you do things is important. For example, if you find that you have forgotten to name the caption field in the stopgo button, you need to change it in all 4 frames, not just one frame. Similarly, if you forgot to name the speed Input field (or perhaps you did not make it an Input field, but left it as Dynamic or Static), you will need to make sure that that change is in all 3 frames.
You can click on Windows/Movie Explorer and set a listing of everything you have placed in the movie. This is a good way to review what you have done systematically and, often, find things to correct.
Summary: This application is made up of a main movie with two layers, three frames:
- The first layer is called board. It holds a movie clip instance named ball, a button with a Dynamic Text field named caption, an Input text field named speed, and 4 movie clips representing the walls, all instances of the same Library movie clip symbol.
- The second layer is called actions. The first frame has the var statements for the variables and the definition of the toggle function called by the on(release) of the button. When the ball is moving, play cycles between the second and the third frame. The amount of horizontal and vertical motion is dependent on calculations involving the speed and the elapsed time. The elapsed time is calculated using variables named now and then.