Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Chapter 11: Ballistics simulation This chapter builds on the previous one to describe ballistics simulation, namely, the simulation of the firing of a projectile into the air. When studying this chapter, you will learn the basic mathematics and physics of projectile motion, including simulation of the effects of gravity practice building an application involving collision checking understand the benefits of dividing a project into steps gain experience using the Flash features for Clipevents, the hitTest method, adding audio effects, and providing drop and drag operations Motivating Example The cannonball application featured in this chapter can serve as a basis for a shooting type of game. The initial screen is Figure 1. Opening screen of cannonball. The player clicks on the FIRE button. The cannonball travels in an arc and either hits the ground or the target. The player can change the angle of the cannon by entering a new amount in the field next to the static text field Degrees, initially set at 45, or can change the speed out of the mouth of the cannon by changing the text field next to the static text field Speed, initially set to 10. The player also can drag the target using the mouse buttons. If the ball hits the target, it turns red and tilts, with a sound played. Figure 2 shows the screen after a successful firing of the cannon. Figure 2. Screen after the cannonball hits the target and it tilts. The critical features required by this application include the features described for the bouncing ball application: the ability to re-position objects on the screen and to produce animation by doing the re-positioning at intervals of time calculating vertical and horizontal components of velocity calculating the effects of [simulated] gravity to produce the characteristic arc of projectile motion determining collisions calculating the orientation of a tilting object changing the color of a Flash movie clip producing a sound TIP: This application requires some basic mathematics. Do not be frightened. The equations are all supplied and you will not need to consult any tables or do any calculations. What you need to do is understand the use of built-in Math methods. Seeing the mathematical functions in use should help your understanding. Introduction to concepts When someone throws a ball or shoots an arrow or fires a missile, the projectile travels in an arc in the shape of a parabola. This is because the force of gravity acts on the object. In the previous chapter, it was noted that the requirements of most computer systems made it necessary to separate the horizontal and vertical components of velocity. Ballistics simulation provides another reason for this separation. Gravity acts to change the vertical component, not the horizontal component. The horizontal component is changed by forces such as the drag from the air, but we assume a more idealized situation. The horizontal velocity remains constant and the vertical velocity changes. EXAMPLE: The simulation is to move (animate) the cannonball through the air using calculations based on the initial velocity out of the cannon, the resolution of that vector into horizontal and vertical components, and the effects of gravity to change the vertical vector. In simulations involving virtual worlds, the program often must check if the position of one object overlays the position of another. A generic term for these checks is collision detection. The checks are to determine if the virtual objects collide. EXAMPLE: Checks are made to see if the cannonball hits the ground or hits a target. These checks are set up to be done throughout the flight using different programming techniques. The simulation is enhanced by allowing the player to change the angle of the cannon and the velocity out of the cannon. The player also can move the target by dragging and then dropping it using the mouse. Lastly, the simulation produces a sound and makes the target slowly rotate when the hit is detected. These all involve various coding techniques, some specific to Flash, and others applicable to other programming languages. A lesson for all programming is to divide implementation into steps. This will be demonstrated by dividing the implementation of the cannonball application into multiple steps. This is an important principle to keep in mind for all projects. Description: simulation of projectile motion In the bouncing ball simulation, the ball is re-positioned horizontally and vertically over and over again to produce the look of animation. For the cannonball simulation, it is necessary to determine the horizontal and vertical components of the velocity. The initial information is the speed of the cannonball out of the cannon and the angle of the cannon. Figure 3 shows how the vector v representing the cannonball departing the cannon oriented at angle a can be decomposed (resolved) into horizontal and vertical vectors, vx and vy. velocity v out of cannon vertical component vy a horizontal component vx Figure 3. Initial speed as sum of component parts. The magnitude of the two vectors turns out to be easy to calculate using the built-in trigonometric functions. Look at the triangle shown in Figure 3. It is a right triangle, meaning that two of the sides are perpendicular. The side opposite the right angle is called the hypotenuse. The angle at the left is of size a. In any triangle of this shape, meaning any right triangle with one of the other angles of size a, the ratio of the side next to angle a, vx, to the hypotenuse, v, is the same known value called the cosine of the angle a. Similarly, the ratio of the side opposite, vy, to the hypotenuse, v, is the same known value, called the sine of the angle a. These ratios are definitions of the trigonometric functions sine and cosine. Using pseudo-code and the common abbreviations of the functions: vx = v * cos(a) vy = v * sin(a) Most programming languages have built-in functions or methods for producing the trigonometric functions and this is the case with ActionScript: vx = v * Math.cos(a); vy = v * Math.sin(a); Math.cos and Math.sin are class methods. The parameter a is the angle. Stating this in practical terms, once the value v, the velocity of the cannonball out of the cannon, and the angle a, the rotation of the cannon, are known, you can write the code to calculate the horizontal and vertical velocities for moving the cannonball. TECHNICAL NOTE: What are the units for the angle? This question may not have occurred to you because you assume that degrees, 360 indicating a full circle, are the only way of measuring angles. We all are familiar with degrees--90 degrees to a right angle; making a u-turn is "doing a 180"--but this measurement is totally arbitrary and it is not the only possibility. Many computer programming languages use radians in place of degrees. Imagine taking the radius of a circle and using it as the ruler to measure the arcs around the circle. There are 2 * pi radians to go all the way around. One radian is a little less than 60 degrees. This unit may seem strange to us, but calculations are easier. Consequently, radian is the standard unit for many programming languages. You need to determine what units the built-in trigonometric functions expect and adjust accordingly. The cannonball application expects the player to input the angle in the familiar degrees. The built-in functions expect angles to be expressed in radians. The program, therefore, must make the conversion. Fortunately, ActionScript provides a Math class variable Math.PI. The code for the conversion is angle_radians = angle_degrees * Math.PI/180 Now that is clear how to determine the initial values to use to animate the cannonball, it is time to move on to describe how to include the effects of gravity. The vertical velocity must change. Exploring this requires a return to the equations of motion. Velocity changes position: it causes displacement. The displacement is calculated using the formula new_position = old_position + velocity * time Gravity is a force that brings about acceleration. Acceleration changes velocity. The technical term acceleration means any change in velocity, not just getting faster by pushing on the car gas pedal. Acceleration can mean going faster or slower and it also can refer to changes in direction. The relevant formula is new_velocity = old_velocity + acceleration * time Assuming constant acceleration, the velocity at the end of the time interval chosen for the simulation is the velocity at the start of the interval plus the value of the acceleration. Note that the sign (positive or negative) of the acceleration does not matter for these equations to be valid. What is the velocity to be used for re-positioning the object? The answer is to take the average of the starting and ending values. average_velocity = (old_velocity + new_velocity)/2 Combining the last two equations, average_velocity = (old velocity + old_velocity+acceleration*time)/2 Now putting this value into the displacement equation, new_position = old_position + ((old_velocity+old_velocity+acceleration*time)/2)*time Simplifying this new_position = old_position + old_velocity*time + .5 *acceleration*time2 The simplification is done to show that the value assigned for the new position is a quadratic expression in terms of the time variable. This is the reason that the path is a parabolic arc. The horizontal component of the velocity remains constant so the object keeps moving horizontally as it started. The horizontal movement is proportional to the time elapsed. The vertical component undergoes the changes corresponding to the quadratic expression. For the ballistics simulation, assuming the cannon is pointing up and to the right, the vertical velocity begins moving the projectile upward, changes to moving upward slower and slower, then changes to moving downwards, then moving downwards faster and faster. Figure 4 is an attempt to convey this. Figure 4. Arc (may not be perfect parabola!) When you get to the coding, you will learn about the signs of the relevant variables and how this produces the desired effect, but this mathematics and physics lesson is over. If you work on action games or simulation of many phenomena of nature, you will need to explore more equations such as these involving forces and vectors. Description: collision detection The ballistics simulation featured in this chapter requires two calculations involving collisions: the ball hitting the ground and the ball hitting the target. The object nature of Flash and ActionScript provide features that makes the programming more-or-less intuitive but in this and other programming environments, it is important to understand that you, the programmer, need to check explicitly for the conditions that indicate a collision. There are no cannonballs, targets and ground inside the computer. Graphical objects are characterized by their positions on the screen or in the virtual world and numbers or formulas defining their shapes. The position generally is the location of the registration point or nominal origin of the object so it is critical to know what the registration point is. In Flash, the registration point would be indicated by a + sign on the Stage. You draw the graphics keeping this registration point in mind. However, if it turns out that you need to re-position the graphics in terms of the registration point, you can select everything using the arrow selection tool and move the material. Alternatively, you can change the coordinates given in the Properties panel directly. Figure 5 shows 4 rectangles with circles representing the registration points. (A filled-in circle is used here to indicate the registration point.) The first rectangle has the registration point in the middle. The next two on the top row have the registration point in or near corners. The rectangle on the bottom row has the registration point away from the rectangle itself. When these items are positioned, the value of the position coordinates is the location for the registration points. Figure 5. Examples of registration points. Figure 6 shows stars positioned 'near' the rectangles, that is, near the rectangle registration points. Notice the very different effects. Figure 6. Rectangles positioned. TIP: The registration point or origin may or may not be under your control. For example, images in HTML are positioned in terms of the upper left corner. In Flash, you can define the registration point to be anywhere you want, including making it away from the actual graphical material. If you know the registration point and the shape of an object, you can write code to determine if a point is within the boundaries of an object. The Flash system has a method that performs such tests, which will be explained next. However, just in case your language does not have it, and to increase your understanding, consider the following situation involving a rectangle. If a rectangle's origin is the upper left corner and origin at rx, ry width rwidth height rheight and the question is whether or not the point mx, my is within the rectangle, the check is the compound if test if ((mx>=rx) && (my >= ry) && (mx <=(rx+rwidth)) && (my<=(ry+rheight))) rx, ry rheight mx, my mx, my rwidth Figure 7. Point (mx, my) inside and outside of rectangle. Figure 7 shows one point inside the rectangle and one outside. Which of the conditions fails for the point outside? Imagine other points outside the rectangle and see if you can identify which of the 4 conditions fail. A rectangle is a relatively simple shape. You have seen the coding for the expression for determining if a point lies within a rectangle. The coding for other graphical shapes may be more complex. For this reason, the bounding rectangle, also called the bounding box, for a graphical object is defined as the smallest rectangle that encloses all the material of the object. Examples of bounding are shown in Figure 8. Figure 8. Examples of bounding rectangles ActionScript supports a method for movie clips, hitTest, that can check for a point being in the same position as any graphical content of the movie clip: any pixel that has had color added to it, any non-transparent point. The coding is if (clip.hitTest(x, y, true)) This test will return true only if the point x,y indicates a pixel in the movie clip that is not transparent. If the point x,y corresponds to any white pixel in the objects shown in Figure 8, for example, the area in the center of the doughnut, the method will return false. If the third parameter in the call to hitTest is false, the check will be the point against the bounding rectangle of the movie clip. You also can use the hitTest method to compare one movie clip to another. if (clip1.hitTest(clip2)) However, in this situation, the comparison is between the bounding rectangles of the clips. The test is fairly fast and if it satisfies the requirements for the application, it should be used. However, if the movie clips hold irregular shapes and it is important to have an exact determination, you may want to consider other strategies. For example, to check if a movie clip, circleclip, that is a circle shape and has origin in the center has collided with a movie clip, wavyclip, you may want to use if (wavyclip.hitTest(circleclip._x, circleclip._y, true)) rather than if (wavyclip.hitTest(circleclip) The first expression checks if the center of circleclip is on any occupied pixel of wavyclip. The second checks if the bounding box of circleclip intersects with the bounding box of wavyclip. This will return true for many more situations. Figure 9 shows two configurations of circleclip and wavyclip. The bounding rectangles overlap in both cases. However, the hitTest that checks a point would return false for the configuration on the left and true for the configuration on the right. Figure 9. circleclip and wavyclip. TECHNICAL NOTE: The two variations of the hitTest method, movie clip versus movie clip and movie clip versus point, demonstrate overloading. The Flash system distinguishes between the two based on the parameters. Sometimes it is possible to use a relatively simple test to determine a critical condition. For example, in the cannonball application, the code checking if the ball has hit the ground actually checks if the vertical coordinate of the ball is equal or greater than the vertical coordinate of the ground object. This is just one comparison operation. Remember that vertical values increase moving down the screen. TIP: You do need to make sure that the registration point for the ground movie clip is on the ground and not way above or below. You also need to be wary of imposing too strict a test for collisions, especially if you are requiring a player to use the mouse to position something. Often, it is necessary to define a level of tolerance. For example, if the requirement is for the point x,y to be 'at' x0, y0, you may want the condition to be if ((Math.abs(x-x0)<tolerance) && (Math.abs(y-y0)<tolerance)) where tolerance has been set to a value such as 50. The Math method abs stands for absolute value. Math.abs(f) is f if f>=0 and –f is f<0 The absolute value function returns the magnitude of the argument independent of the sign. In the if condition checking of a point x,y was near enough to the point x0,y0, this means that you do not care if the point was to the left or the right of the target, if x>=x0 or x<x0 The code checks that regardless of what side, the difference is less than the tolerance amount. You can experiment. EXAMPLE: The cannonball application uses the Flash hitTest method to determine if and when the cannonball hits the target. Description: dragging and dropping of objects A typical operation in modern interactive computer applications is dragging and dropping. Dragging begins by pressing down on the standard mouse button when the cursor controlled by the mouse is over a certain area of the screen. This indicates that dragging is to start. The user then moves the mouse. The item in question is now moved across the screen as long as the mouse button stays down. When the mouse button is released, the item stays put. Different programming languages provide different types of support for dragging and dropping. The mechanisms in Flash work as follows. It is possible to specify a handler for the mousedown event for any movie clip. This event is triggered if and when the mouse button is pressed down anywhere on the screen. The event handler then can check if the mouse is over the material of the movie clip by using the hitTest described earlier. If this is the case, the movie clip can be set to be dragged by invoking a movie clip method. Because it is sometimes the case that you may want to let the user/player click anywhere on the movie clip to start the dragging, but you want the dragging to be from the registration point, an argument to the startdrag method indicates true if you want dragging to be from the movie clip origin and false otherwise. The code to start dragging a movie clip is: onClipEvent (mouseDown) { if (this.hitTest(_root._xmouse, _root._ymouse,true)) { this.startdrag(false); } } The _root._xmouse and _root._ymouse give the coordinates of the mouse. The this indicates this movie clip. The startdrag is a method applicable to all movie clips. TECHNICAL NOTE: The false is a parameter indicating dragging is to take place from the initial point of contact. Setting this parameter to true would indicate that you wanted dragging to be done in terms of the registration point (origin) of the movie clip. The effect would be that the cursor would jump to origin. Stopping dragging is simpler than starting dragging. There is an event for monitoring the mouse button being released. When this happens, the event handler can include a call to the function stopdrag. This stops all dragging. onClipEvent(mouseUp) { stopdrag(); } TECHNICAL NOTE: Some programming languages provide less support for dragging. You may need to write code to monitor the mouse move event and then move the item explicitly by saving old and new coordinates and computing the changes. EXAMPLE: The cannonball application allows the player to re-position the target using the mouse. Description: audio (sound) The addition of audio to a computer application can increase the target audience to include people with visual impairments, improve usability in busy environments through the use of attention-getting signals, or simply make an application more dramatic. A feature of an audio clip is that it takes up a certain amount of time. You, the programmer, must coordinate the playing of the audio clip with whatever else is happening in the application. The statement that starts the audio clip does just that: starts it. The sound probably goes on while other statements are being executed. EXAMPLE: The cannonball application makes a sound when the target is hit. This is really just for fun, but it does illustrate an important concept in interactive applications: provide feedback to your user. TECHNICAL NOTE: There are different file formats for audio just as there are different file formats for images. The wav format actually is a family of formats corresponding to different sample rates (frequencies) and different amounts of data recorded at each instance of sampling. The mpeg family of formats represents a highly efficient way of compressing audio files. You need to understand the specifications for the programming language you are using in order to incorporate audio files. Description: iterative development Programs can be complex. A way to deal with the complexity is to divide the work into small[er] parts. It is easy to make the general statement, but more challenging in practice. One rule of thumb is that if it is possible to program a small part of an application and test it independently, do so. The application featured here will be described in several steps. No claims are made that these steps are the only ones possible or the best ones, but they do serve to divide the work. NOTE ON TERMINOLOGY: To avoid confusion with the Stage of Flash, the term 'step' is used in place of 'stage'. EXAMPLE: The cannonball application is excellent for practicing iterative development. Do the basics first and then add the bells-and-whistles. Reading checks 1. How are the trigonometric functions, sine and cosine, used for ballistics simulation? 2. What is the formula relating radians to degrees? 3. Why is it necessary to convert from degrees to radians? 4. What are the mouse events that are significant for performing a drag-and-drop operation? Application Review of previous examples The application featured in Chapter 10 made use of the playing of frames to simulate the behavior of a ball bouncing in a 2-dimensional box. This application will build on that methodology to simulate the shooting of a cannonball out of a cannon. Plan of attack for cannonball The strategy for cannonball is to use the same 3 frame scheme demonstrated in the bouncing ball application to do the simulation. See Figure 10. The first frame will contain function definitions and global variables, including any initializing of values. The second frame, named continue, will contain free-standing code to animate the cannonball. The third frame will contain free-standing code that will send play back to frame 2 if the cannonball is in flight. Figure 10. Timeline for cannonball. The graphical material of the application includes 4 movie clips: cannon, ball, target and ground. You need to create these movie clip symbols and move instances to the Stage. The instance name for the target movie clip was made target1 to hint that it is possible to have multiple targets. Because the plan is to have target1 appear to sink into the ground, the ground movie clip is in its own layer, also named ground, above the board layer holding everything else. This means that the ground remains in front of the target1. See Figure 10. It is recommended that you begin with simple graphics as shown here. When you have the application working, you can enhance the graphics. See the What can go wrong section for a common error concerning the cannon. The material also includes a button showing the word FIRE, and text fields: two static ones holding Speed and Degrees and next to each of these input text fields with var names speed and anglein. Figure 11 shows the material in all 3 frames. Note the registration point of the cannon and note also that it is oriented horizontally—flat on the ground. The initial setting of the text field anglein is 45. The code in the firecannon function to be described later will rotate the cannon to its specified angle. Figure 11. Material for cannonball. The implementation will be done in steps, starting with implementing the cannonball traveling in a parabolic arc based on the speed and angles specified in the input text fields. When working properly, application at this first iteration does not stop! You need to close the window. The next step will add the collision testing and subsequent steps will add other features. Use of concepts in implementation Implementing a program in steps is an example of the adage "make haste slowly". Working on one thing at a time makes the work go faster. Step 1: parabolic arc, no stopping The first step of implementation is to rotate the cannon as designated by the angle, position the cannonball at the mouth of the cannon and move the cannonball according to the equations of motion. Since this step does not have anything to stop the flight, it will be necessary to close the window showing the movie. This may feel silly but once this much of the program works, you have the most difficult part completed. Frame 1 ActionScript contains the global variable declarations and the definition of the function firecannon. The coding for the global variables and their purpose is indicated in the following table. var inflight; var then; Boolean indicating whether flight is to continue or not Used to store start of time interval var var var var now; elapsed; hspeed; vspeed1; var vspeed2; var gravity = 9.8/12; var angle; Used to store end of time interval Used to hold elapsed time Horizontal component of the velocity Vertical component of velocity at the start of the time interval Vertical component of the velocity at the end of the time interval A made up number representing the magnitude of the change in velocity due to gravity The angle in radians, converted from the degrees input by the player The on(release) for the button is to invoke firecannon. The function definition is: function firecannon() { inflight = true; cannon._rotation = - anglein; ball._x = cannon._x +cannon._width +(.5* ball._width); ball._y = cannon._y cannon._height -(.5*ball._height); angle = anglein * Math.PI/180; ball._visible = true; hspeed = Math.cos(angle)*speed; vspeed1 = -Math.sin(angle)*speed; vspeed2 = vspeed1; then = getTimer(); gotoAndPlay("continue"); function header set inflight to true indicating the ball is in flight Rotate the cannon the designated amount, sign changed to be counter clockwise. Position ball horizontally next to right end of cannon Position ball vertically in middle of cannon Convert from degrees to radians Make ball visible Calculate horizontal component Calculate vertical component. Negative sign due to screen coordinates having origin at the top To start with, starting and ending velocities are the same Get time Go to continue frame (frame 2) } The Frame 2 ActionScript is free-standing code. This frame is labeled "continue". It moves the ball horizontally using the fixed horizontal speed and vertically according to the average of the vertical speeds at the start and the end of the time interval. if (inflight) { Still in flight? now = getTimer(); elapsed = 12*(now - then)/1000; ball._x += hspeed * elapsed; vspeed1 = vspeed2; vspeed2 = vspeed1 + gravity* elapsed; ball._y += elapsed * (vspeed1 + vspeed2)*.5; then = now; } Get the time Calculate the elapsed time Move ball over horizontally Set the vertical speed for the start what it was at the end of the last time interval Calculate the vertical speed at the end using the formula for acceleration Move the ball over vertically using the average Set the starting time for the next iteration End of true clause The Frame 3 ActionScript sends play back to the continue frame or stops depending on the value of the inflight variable. For this step, nothing changes inflight, so the ball keeps going. if (inflight) { gotoAndPlay("continue");} else { stop(); } Try to get this working. You need to check the program with different values for the speed out of the cannon and for the angle. The cannon should rotate corresponding to the different angles. (See the exercises for a challenge regarding the angle.) Step 2: checking for ground and checking for the target The next step is to put in code to stop the flight, either when the cannonball hits the target or hits the ground. You could do this symmetrically, but here is another approach. The check for hitting the target will be placed in a ClipEvent of the target1 instance. You need to select the target1 instance in each of frame 2 and frame 3 and enter the code onClipEvent (enterFrame) { if (this.hitTest(_root.ball)) { _root.ball._visible = false; _root.inflight = false; } } The qualifier _root means to use the ball and the inflight defined in the main movie. Otherwise, the language processor looks for variables defined locally, say in the target1 movie clip. If the variable or instance is defined in the main movie, it is never incorrect to use the _root qualifier, so when in doubt, use it. Putting the code in the onClipEvent (enterframe) means that it gets executed over and over because the one frame of the target1 instance is played over and over. Checking for the ball hitting the ground is done by placing code in frame 2. In the true clause of the if (inflight) statement, insert if ((ball._y + ball._height) > ground._y) { inflight = false; ball._y = ground._y - ball._height; } This is an example of using a simple test to determine if there is a collision. In this case, the test is essentially: has the ball gone beyond the level of the ground. Remember that further down the screen is a greater y value. If this is the case, the line ball._y = ground._y - ball._height; makes the ball lie on the ground. Think of it as correcting the fact that the check is done at discrete intervals so the ball may have below ground level. Now test the program. Sometimes students believe testing is complete when they make the cannonball hit the target. This is thinking like a game player and not the game builder. You must check different combinations. An amusing situation is when the cannonball flies over the target. Assuming the programming is correct, it will stop when it reaches the vertical level of the ground even if it is off-screen. Step 3: making the target turn red This next enhancement to the project does not add any significant functionality, but is more of a 'bells and whistles'. See the exercises for an alternative. Flash and ActionScript provide a way to associate colors with movie clips. A Color object variable is created as associated with a movie clip instance. Add the following statement to Frame 1, with the other global variables. var zap = new Color(target1); In the firecannon function definition, add the statement zap.setRGB(0x000000); The setRGB method of Color objects sets the color using red-green-blue hexadecimal coding. A hexadecimal character is 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, or F. Think of it as 0 to 15. The 0x indicates an hexadecimal string. There are 3 times 2 = 6 hexadecimal characters hold 2 for red, 2 for green and 2 for blue. The two values used for this application are easy enough to understand: all zeroes represents the absence of color, black. Red is represented by 0xFF0000. To find out the hexadecimal pattern for other numbers, you can consult books on HTML or use a drawing program such as JASC Paint Shop Pro or Adobe Photo Shop. Assuming that the original movie clip is all black, this statement does not do anything the very first time. However, you do want the target to turn back to black when you hit the FIRE button again. To make the target change color, select the target1 instance and add the following statement in the onClipEvent(enterframe) code, in the true clause indicating ball has hit the target _root.zap.setRGB(0xFF0000); You do need to add the _root here to get the global variable zap changed. You make this addition to both frames 2 and 3. Try it! Again, make sure the program works for different settings of speed and angle. This means you need to check that the target does not change color if it is not hit by the ball. You also need to check that the target changes back to black when you, acting as the player, hit the FIRE button again after the target has turned red. Step 4: adding sound Adding sound is another 'bells-and-whistles' enhancement. The first step is to acquire a sound from the Common Library/Sound. My choice was Bucket Sound. Select it and drag to the Library. Figure 12 shows panels from both the Common Library and the Library for the cannonball application. The two wave patterns represent the signals sent to the two speakers. You can use the setPan and setVolume methods to control the sounds from the left and right speakers. Figure 12. Sounds Library and Library for project shown. The next step is to 1. Select the Bucket Hit in the Library 2. Right click and click on Linkage 3. Click on the check box for Export for ActionScript. The Export in first frame will be checked, also. Type in an identifier: buckethit is what is used in the code. This is shown in Figure 13. Click OK. Figure 13. Linkage Properties for sounds. The coding now is somewhat like that for the color change, but there is a difference. You need to make sure that the sound is just started once. In Frame 1, add the following to the global variables: var soundc = new Sound(); soundc.attachSound("buckethit"); var okforsound; The soundc object is a sound controller to which you need to attach a sound. The okforsound is a variable used in this program to determine if it is okay to start playing the sound. In the firecannon function definition, add the statement okforsound = true; Now, just as you did for the color change, select target1 instance in frame 2 and add to the onClipEvent(enterframe) code, to the true clause, the following: if (_root.okforsound) { _root.soundc.start(0, 1); _root.okforsound = false; } Repeat for frame 3. This starts the sound. The first parameter to the start method, 0 here, indicates that the sound is to start from the beginning. You can signal the sound to start a specified number of seconds into the sound clip. The second parameter indicates the number of times the sound clip is to repeat, to loop. The code here indicates the sound is to play just one time. The last statement in the clause sets the variable okforsound to false. This means that the sound will not be started again. Step 5: hit target tilts The next enhancement is to make the target appear to tilt and sink into the ground. This is accomplished over the playing of several frames of the target1 instance. The first step is, again, additions to the global variables in frame 1. var oktofall; var origrotation = target1._rotation; The oktofall is not Boolean, but will hold a number, initialized in firecannon to be zero and incremented until it is 10. The tilting will take place if the target1 instance is hit and if oktofall is under 10. The origrotation holds the original rotation for the target1 instance. It is needed to reset the rotation after hitting. In the firecannon function definition, add oktofall = 0; target1._rotation = origrotation; Now, moving again to the onClipEvent(enterframe) coding as in steps 3 and 4, the code is shown in full. The addition is the if statement checking if oktofall is less than 10. onClipEvent (enterFrame) { if (this.hitTest(_root.ball)) { _root.zap.setRGB(0xFF0000); _root.ball._visible = false; _root.inflight = false; if (_root.okforsound) { _root.soundc.start(0, 1); _root.okforsound = false; } if (_root.oktofall<10) { _root.oktofall += 1; _root.target1._rotation += 1; _root.target1._y += .3; } } } The if statement checks if it is still ok to fall. If this is the case, the oktofall variable is incremented. The target1 instance is rotated by 1 degree and its vertical (y) coordinate is increased by 3 pixels. Because the ground layer is above the board layer that holds target1 instance, this has the effect of the target1 sinking and tilting. The three enhancements could be added in any order, but it certainly makes sense to add them one at a time. Step 6: dragging and dropping The last enhancement is to add the facility to move the target (target1 instance). The Flash/ActionScript product makes this very simple to do. Select the target1 instance and add the following to all 3 frames: onClipEvent (mouseDown) { if (this.hitTest(_root._xmouse, _root._ymouse)) { this.startdrag(false); } } onClipEvent(mouseUp) { stopdrag(); } This coding has been explained already. Test the program. Move the target by pressing the mouse button down and dragging. You can move the target up above the ground and then click on the FIRE button. See if you can 'catch' the cannonball in flight. What happens? If you do not want the target to be up in the air and look rather silly tilting over as shown in Figure 14, you need to do some more programming! Figure 14. Target up in the 'air' when hit. Add one more global variable in frame 1: var origy = target1._y; This stores the original vertical location of the target1 instance so it can be restored once the FIRE button is pressed. In the firecannon definition, add target1._y = origy; This will 'bring the target down to earth' if it has been moved. To test the program properly, you need to check if it still works if you do not move the target and if you do. Remember that working means doing the appropriate action when the cannonball hits the target and when it does not hit the target. Reading checks 1. Review each step to check that you know what will the application is to do at that step. 2. At what step will you see the parabolic arc? 3. At what step is there a check if the target has been hit? 4. What would be the effects of changing the value for gravity? How is that done? 5. Why must there be a check that the sound has started? 6. How is the tilting done and why must there be a check to stop the tilting? 7. Why is the ground instance put in a layer on top of everything else? 8. What happens in the first frame? The second frame? The third frame? Give your answer in words, not code. What can go wrong This application is meant to inspire readers to build an improved version. However, the recommendations already mentioned deserve repetition: start with simple graphics and work in steps. One common error is to design an elaborate cannon or find a picture of one on-line (this would be theft of someone else's work, so don't do it). At rest, the cannon appears to be fine. However, the coding rotates the movie clip instance named cannon with the rotation done at the registration point. You don't want the base and the wheels of the cannon to be rotated off the ground. Be sure your cannon movie clip is essentially a rectangle with the registration point at the left end. After you have the basic application working, you may decide to design a cannon assembly consisting of two or more separate movie clips. One will have instance named cannon and be the one that is referenced in the code. This application has code in each of the 3 frames, code associated with the button and code associated with the target1 instance. If the code is not in the correct place, the program will not work. For example, if the mouse event handlers for the target1 instance are placed as Actions in the Frame, you will see a little a in the ground layer as indicated in Figure 15. Figure 15. Putting instance code in the wrong place. When you test the program, an error message will appear as shown in Figure 16. Figure 16. Error message. This is a signal that you need to move the coding so that it is associated with a movie clip instance. Chapter Summary and Reflection This chapter covered programming features necessary to simulate projectile motion. The basics for the computed animation were addressed in the previous chapter. This chapter focused on the mathematical operations necessary to represent (resolve) a vector into vertical and horizontal components and calculate the changing vertical velocity. These would be similar in any programming language. The application also required implementation of accepting player input, collision detection, drag-and-drop operations and playing a sound. The cannonball application, along with the bouncing ball of the previous chapter, shows the power of computed animation. The program, based on inputs and actions by the player/user, produces a complex display. You can begin to appreciate that a computer program can produce results that were not specifically predicted by the designers/programmers, but still under their control. The radians versus degrees issue brings up an important point for interface design. Build an interface for the user, not for the programming language. People use degrees. It is the programmer's job to code any conversions to satisfy the internal system requirements . The application shows event-driven, interactive programming. The events include the passage of time, the player entering information into text fields and the player clicking a button. Review the 3 enhancements to the project: color change, sound and tilting. Their implementations had features that were similar: each required global variables and the main code was all in the same place in the onClipEvent(enterframe) for the target1 instance. However, there also were differences, mainly relating to time. The color change was instantaneous. The sound was not instantaneous; that is, it had a duration more than an instant. However, in terms of the ActionScript programming, it was critical to just invoke the sound once. Lastly, the tilting also lasted a certain amount of time and it was under the control of the ActionScript programming. If you were a programmer Ballistics simulation was one of the earliest applications of computers. Simulation and control of missiles and rockets still are important applications. A question to ask is how much of the material in this chapter applies to programming languages other than Flash and ActionScript. The answer is most of it: the laws of physics are the same. The equations of motion are the same. Setting up events and event handlers varies, but the general design considerations would apply to any programming system. Of course, if you were working on an application to simulate, track or control real phenomena, you would need to pay closer attention to values and units. For the cannonball application, the value for gravity, 9.8 pixels/sec/sec, was chosen because of its closeness to a constant the author remembered and because it produces a nice-looking arc on the screen. Programs created to help scientists, engineers and planners better visualize and understand situations may require that the simulation run at variable rates, slower and/or faster than the real thing. The general lessons of this chapter on dividing implementation into steps and testing all situations apply even more to work in industry than to projects found in books. Organizations may even have groups of professionals whose main assignments are to plan the steps of work or perform system testing. What's next The next chapter presents a different kind of simulation, the virtual dog. It represents the class of applications characterized as finite-state, stochastic processes. The implementation language will be HTML and JavaScript. Exercises 1. Math/physics problem: a toy moves 5 inches/second. How far does it go in 30 seconds? 10 seconds? 2 minutes? 3 and ½ minutes? three-quarters of an hour? 2. Math/physics problem: a toy is not moving. It accelerates at the rate of 10inch/sec/sec. How fast is it going after 5 seconds? 3. Do research (this can include personal experience, but be careful): what are typical rates of acceleration when driving a car: starting from rest? Driving at 55 miles/hour? How quickly can you decelerate from 55miles/hour to 30 miles/hour? 4. The cannonball application as presented does no checking on the angle entered by the player. See what happens when the player puts in 90 for 90 degrees. Fix this bug by checking the value to make sure it is a positive integer and to not accept a value over 89 degrees. 5. What is the ActionScript to initiate dragging for the movie clip house? 6. What is the ActionScript to stop all dragging? 7. True or False: the event onClipEvent(mousedown) for a specific movie clip will be triggered by the mouse being down anywhere on the screen, not just on top of material in the movie clip. 8. Recalling the formula for the area of a circle (Area = pi * the square of the radius), write the expression in ActionScript that calculates the area of a circle with radius r. Projects 9. Add scoring and a scoreboard to the cannonball game. 10. Improve the graphics of the game. Make the cannon look like a cannon as hinted at in the chapter. You will create a cannon assembly consisting of more than one movie clip. Consider making the target smaller. See next two exercises. 11. Turn this into a shooting rockets in space game by taking out gravity: the vertical velocity remains the same. 12. Produce a more general ballistics simulation by making it possible to change gravity. You can provide the player choices, such as Earth, Moon, Mars for 3 set values. Consider changing the background graphics to correspond with each choice. 13. Change the target to something other than a rectangle. Now change the collision detection code to use the point versus clip hitTest . Define the point to be the center of cannonball. 14. The cannonball application as presented changes the color of the target when it is hit, makes a sound, and tilts the target into the ground. Instead, create a new movie clip representing a target that has been hit. Bring an instance to the Stage, off-stage, and name it hit_target. When the target is deemed to have been hit, set target1 to be invisible, move hit_target to the same location and make it visible. 15. Create a moving target. There are at least two ways to do this. You can move the target using computed animation. Think of combining bouncing ball and cannonball. Alternatively, you can create a movie clip that itself has multiple frames producing cel animation for the target. 16. Investigate what happens if an over-eager player clicks on the FIRE button while the cannonball is in flight. Fix this by adding code to check the inflight variable in the firebutton function. 17. The cannonball is a ball, or, more specifically, a circle. Think about what is necessary to implement an arrow shot at a target. You want the arrow to rotate so that the tip leads as it moves up, levels and then moves down. You will need to use trigonometry to rotate the arrow. What is necessary is to calculate the angle using arctangent: the angle whose tangent is the argument of the function. The code would be (substituting arrow for ball, though you certainly could keep ball as the instance name): vspeeda = (vspeed1+vspeed2)*.5; arrow._y += elapsed * vspeeda; var anga = Math.atan(vspeeda/hspeed); var angad = anga*(180)/Math.PI; arrow._rotation = angad; For an arrow as opposed to a ball, you also want to determine hitting the target based on the tip of the arrow hitting the target. Set alength to be the length of the arrow. Then the coordinates of the tip are calculated as follows: aangr = arrow._rotation*Math.PI/180; apx = arrow._x+Math.cos(aangr)*alength; apy = arrow._y+Math.sin(aangr)*alength; if (this.hitTest(apx, apy, true)) { For teachers only: Tips for Teachers Most students enjoy doing cannonball, though it is a challenge. The main problem is that students' ambitions exceed their abilities. You need to slow them down and force them to do the project in steps, and, initially, with simple graphics. A common problem is that students draw elaborate cannons. They will need to separate the cannon housing from the part of the cannon that rotates. Set up distinct due dates for the different steps, or at least steps 1 and 2, and do not accept later steps until the first ones are complete. This also is a way to make sure that they have done the work. Many students will groan if and when you talk about trigonometry. A tactic is to say the following: in the past, you learned or maybe did not learn some terminology. Here is a chance to use it. You do not have to figure out the coding. It is provided to you. You do not have to look up values in tables. The built-in methods provide the coding. Once you understand the workings of vectors, you can build very complex applications.