Detection Using hitTest()


As you probably know, Flash's MovieClip object contains many methods and properties that assist in working with movie clips. When a movie clip is created, either in the authoring environment or with ActionScript, it inherits all the methods and properties of the MovieClip object. These methods and properties are then available to this new movie-clip instance.

We can use the hitTest() method of the MovieClip object to detect collisions in three simple scenarios. But before we discuss these three types of collisions, I'll introduce you to a new term, bounding box. Bounding box refers to the imaginary box that encloses everything in a movie clip. If you have a movie clip with a circle in it, then the bounding box for this movie clip is a square that is exactly big enough to fit the circle, with each side of the box touching the circle. Likewise, if you have an irregular shape or multiple shapes within a movie clip, then the bounding box will be made up of a rectangle that touches the uppermost piece in the movie clip, the leftmost piece in the movie clip, the rightmost piece in the movie clip, and the lowest piece in the movie clip.

graphics/05fig03.gif

Now that you have an understanding of the bounding box of a movie clip, we can mention the three types of collision detection that are possible using hitTest().

Movie Clip-Movie Clip Collisions

This type of collision detection determines if the bounding boxes of two movie clips are overlapping. The shapes within the movie clips may or may not be touching, but as long as the two bounding boxes are, then a collision has occurred.

graphics/05fig04.gif

Now let's delve into the ActionScript involved. Since hitTest() is a method of the MovieClip object, it can be applied only to a movie clip (as opposed to any other kind of object, such as a graphic or a text field). Following is the syntax for using hitTest() to determine if two movie clips are colliding:

 myMovieClip.hitTest(target_MovieClip)  

This line of ActionScript starts with the instance name of a movie clip. After the instance name, the hitTest() method is invoked by passing in a parameter. The value of that parameter is the instance name of another movie clip. Translated into English, this line of ActionScript would become a question that would read something like this: "Is the bounding box of myMovieClip colliding with the bounding box of target_MovieClip?"

When this line of ActionScript is executed, Flash gives you an answer to that question. In English you would expect the answer to be "yes" or "no"; in ActionScript, the answer is true (yes) or false (no).

graphics/cd_icon.gif

Open movieclip_movieclip.fla in the Chapter05 directory on the CD to see an example. In this FLA file we have two movie clips shape1 and shape2. This file has been programmed so that shape1 will move to the right, and during every frame it checks to see if there is a collision occurring between shape1 and shape2. If a collision is happening, then we simply execute a trace action to indicate that the collision is happening. Here is the ActionScript used.

graphics/tip_icon.gif

The trace action is purely for testing and debugging purposes. If you type trace("My name is Jobe and I'm a physics major") in the Flash MX Actions panel and then test the movie, you'll see that message appear in the Output window. Trace actions are only displayed in test-movie mode in the Flash environment, never in a Web page or in the stand-alone SWF file.

 1   xmov = 3;  2   _root.onEnterFrame = function () { 3      shape1._x += xmov; 4      if (shape1.hitTest(shape2)) { 5         trace("They are colliding!!"); 6      } 7   } 

graphics/05fig05.gif

You can see that we start out moving shape1 in the same way we introduced in Chapter 4, "Basic Physics"; first a speed variable, xmov, is set, and then the position is updated in every frame. Where we start introducing new ActionScript is on the fourth line. This is a conditional statement: If the hitTest() method returns a value of true, then the condition is fulfilled and the trace action is executed; otherwise nothing happens.

Here is that same conditional statement converted to words: "If the bounding box of shape1 collides with the bounding box of shape2, then put 'They are colliding!!' in the output window."

graphics/cd_icon.gif

For a more practical example, you can check out ball_falling.fla in the Chapter05 directory on the CD. There are two movie clips in this file ball and floor. Using gravity (as covered in Chapter 4), the ball falls. In every frame, we check for a collision between it and the floor. If hitTest() returns a value of true, then the velocity of the ball is reversed and the ball goes back up. Generate a SWF to test the file. (The quickest way to do this is to press Ctrl-Enter in Windows or Command-Return on the Mac.) Note that if you run the file for 30 seconds or so, the ball gets stuck in the floor. This is due to one of the limitations of hitTest(), which we'll discuss in the "Detection Using Math" section of this chapter.

Movie Clip-Point Collisions

The hitTest() method lets you determine if a point (x, y) is within the bounding box of a movie clip. This can be handy in specific game situations. Usually these are times when the mouse is involved. Simple click-and-destroy style games make use of this type of collision detection. For example, let's take a balloon game. If the user clicks the mouse when it's positioned over a balloon, then the balloon pops. This is the easiest way to find out if the mouse is over a movie clip without using a button. However, most click-and-destroy games are created with buttons. For that reason, in my opinion, the movie-clip point method of detection doesn't have many effective uses in games.

graphics/05fig06.gif

Here is the syntax for using the hitTest() method to determine if a point is colliding with the bounding box of a movie clip:

 myMovieClip.hitTest(x, y)  

And here's the English translation: "Does the point with coordinates of x and y fall within the bounding box of myMovieClip?"

As in the previous section, the answer to this question that is, the result of the line of ActionScript is going to be true or false.

graphics/cd_icon.gif

To see this in action, open the file balloon_pop.fla from the Chapter05 directory on the CD. You'll see a movie clip containing an image of a balloon on the stage. This movie clip has an instance name of balloon. There is ActionScript on frame 1 in the Actions layer that executes when the mouse is clicked. This script then determines if the mouse is over the balloon clip, and if so, then the balloon is "told" to explode. Here is the ActionScript used to accomplish this.

 1   _root.onMouseDown = function () { 2      mx = _xmouse; 3      my = _ymouse; 4      if (balloon.hitTest(mx, my)) { 5         balloon.play(); 6      } 7   } 

In line 1 of this script we define a function that will be called when the mouse button is pressed down (and not yet released). When this happens, two variables are set mx and my to store the x and y positions of the mouse. Then, in line 4, we use an if statement to determine if the mouse is within the bounding box of the balloon clip. To satisfy this conditional statement, the statement balloon.hitTest(mx, my) must return a result of true, confirming the "collision" of the pointer and the balloon. If the condition is satisfied, then line 5 is executed, and the movie clip called balloon plays a popping animation.

graphics/tip_icon.gif

The popping animation was created inside of the balloon movie clip. The first frame of that movie clip shows the balloon in its un-popped state. The frames after that show the balloon popping. The final frame in the animation is blank.

graphics/cd_icon.gif

The idea used in balloon_pop.fla can be extended easily to apply to any number of movie clips. To see such an expanded example, open balloon_pop_many.fla from the Chapter05 folder on the CD. In this file, the number of balloons that will be displayed is controlled by a variable. There's a movie clip in the library, again called balloon, whose linkage identifier is also named balloon (see the sidebar "ActionScript Review: attachMovie() and Linkage Identifiers" if this is new to you). With the linkage specified, we can attach the balloon clip to the stage (that is, create new copies of it) as many times as we want. When the mouse button is clicked, we can loop through all of the balloons on the screen using ActionScript, performing a hitTest() on each balloon, to determine if there are any collisions between the mouse and the balloon. Here is the ActionScript used in this example.

 1   //Number of balloons to be created  2   totalBalloons = 10; 3   //Set the dimensions of the screen so that we can randomly      place the balloons 4   screenWidth = 700; 5   screenHeight = 400; 6   //Create and place the balloon instances on the stage 7   for (var i = 0; i<totalBalloons; ++i) { 8      var name = "balloon"+i; 9      _root.attachMovie("balloon", name, i); 10     var x = random(screenWidth); 11     var y = random(screenHeight); 12     _root[name]._x = x; 13     _root[name]._y = y; 14  } 15  _root.onMouseDown = function() { 16     mx = _xmouse; 17     my = _ymouse; 18     //Loop through all of the balloons looking for collisions 19     for (var i = 0; i<totalBalloons; ++i) { 20        var name = "balloon"+i; 21        if (_root[name].hitTest(mx,my)) { 22           _root[name].play(); 23        } 24     } 25  }; 

The second line of code above sets a variable called totalBalloons. The value of this variable determines how many balloons will be created and placed on the stage. Lines 4 14 create and place the balloons on the stage. Lines 19-24 contain an ActionScript loop that checks for a collision with each balloon. The balloons that are created (from lines 4 14) are named sequentially (balloon0, balloon1, balloon2, and so on). In this loop, we dynamically re-create the name of each of these balloons and use these names to reference the movie clips, checking to see if a movie clip of the same name has a hitTest() of true with the position of the mouse. For instance, if the loop is on iteration 12, then the name created is balloon12. Since the value of name is "balloon12" then the action _root[name] is equivalent to writing _root.balloon12. This is how the references to the movie clips are created dynamically in these loops.

graphics/05fig07.gif

ActionScript Review: attachMovie() and Linkage Identifiers

With ActionScript you can create a new instance on the stage of a movie clip that is in the Flash file's library. Many effects are accomplished this way, such as creating an endless supply of bullets from a gun. In order for ActionScript to pull a movie clip from the library, the clip must be configured to do so. This is very easy. Open the Library panel, find the movie clip you wish to make available, right-click (Windows) or Control-click (Mac) on it, and select Linkage from the contextual menu. In the Linkage Properties dialog box, make sure the box next to Export for ActionScript is checked, and then type in an identifier name. The identifier is how you tell Flash which movie clip you want to attach. To then attach a movie clip, simply use the following action:

 path.attachMovie(linkage_identifier, new_instance_name, depth)  

For instance,

 _root.attachMovie("balloon", "balloon2", 2);  

ActionScript Review: for Loops

Loops are an immeasurably helpful ActionScript feature. With them you can perform the same actions as many times as you wish. This is particularly useful for doing the same thing to many movie clips. For instance, if you have pictures on the stage named picture1 through picture30 and you want to make them all invisible, you can create a simple for loop to do so:

 for (var i=1; i<=30; ++i) {    var name = "picture"+i;    this[name]._visible = false; } 

The for loop accepts three parameters. The first parameter (in this case, var i=1) specifies a starting place. The second parameter (i<=30) is a condition that must be fulfilled to continue looping. If this condition is no longer fulfilled, then the loop ends. The third parameter (++i) increments the variable so that the loop will at some time end. If the loop variable is not incremented, then the condition will always be satisfied, and the loop will never end.

Shape-Point Collisions

With the previous two types of collision detection, we saw that a collision happens with the actual bounding box of a movie clip. There is one other way to use the hitTest() method, and that is to detect a collision between a point and the contents of the movie clip not just the bounding box. Imagine a movie clip that contains several separate graphics or shapes. Using the hitTest() method, we can tell if a point is colliding with any one of the shapes in this movie clip.

graphics/05fig08.gif

Here is the syntax used to invoke this type of collision detection:

 myMovieClip.hitTest(x, y, true)  

You might immediately notice that this is identical to the syntax for the movie-clip point collision detection, with one change: the addition of the true parameter. When that parameter is set to true, the hitTest() method checks for a collision between the point and the contents of the movie clip. If that parameter does not exist or if it is set to false, then the hitTest() method checks for a collision between the point and the bounding box of the movie clip.

graphics/cd_icon.gif

To see an example of this, open puzzle_piece.fla in the Chapter05 directory. On the stage you will see a movie clip with an instance name of piece, containing the shape of a puzzle piece, which happens to be a candid shot of my cat. The ActionScript in this movie simply checks for a collision between the mouse and the shape when the mouse is clicked.

 1   _root.onMouseDown = function () { 2      mx =_xmouse; 3      my =_ymouse; 4      if (piece.hitTest(mx, my, true)) { 5         trace("Meow!"); 6      } 7   } 

The first line of this code defines a function to be called when the mouse button is pressed. When this function is called, it sets two variables, as in our previous examples, to store the position of the mouse cursor. Then, on line 4, comes a conditional statement that checks to see if the hitTest() of the mouse position with the movie clip called piece is true. If it is true, then a trace action is executed to show you that a collision was detected.

graphics/05fig09.gif

graphics/cd_icon.gif

You can see a more practical application of this technique in the file puzzle_piece_drag.fla in the Chapter05 folder on the CD. In that file, the collision detection is coded exactly as it is here; the difference is that instead of giving a trace result when the puzzle piece is clicked, the piece gets dragged until the mouse button is released.



Macromedia Flash MX Game Design Demystified(c) The Official Guide to Creating Games with Flash
Macromedia Flash MX Game Design Demystified: The Official Guide to Creating Games with Flash -- First 1st Printing -- CD Included
ISBN: B003HP4RW2
EAN: N/A
Year: 2005
Pages: 163
Authors: Jobe Makar

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net