Foundation Game Design with ActionScript 3.0, Second Edition (60 page)

BOOK: Foundation Game Design with ActionScript 3.0, Second Edition
6.19Mb size Format: txt, pdf, ePub

Figure 6-18.
Draw a square and center it inside the character object.

This has been a quick introduction to AS3.0's drawing package, which allows you to draw all sorts of simple shapes with AS3.0 code. You won't be using it again in this book, but it's covered in detail in
Advanced Game Design with Flash
. You'll also find very detailed information on how to use it in Adobe's AS3.0 documentation at
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Graphics.html
.

To make the white square invisible so that it's not blocking the character's face, just add this line to the last bit of code:

square.visible = false;

Now that the character is carrying around this square subobject, you can use it in the
enterFrameHandler
to check it for a collision with the star. The code is very straightforward.

if (square.hitTestObject(star))
{
  output.text = "Collision!"
}
else
{
  output.text = "No collision"
}

Of course, this collision detection still isn't perfect. It will avoid the problem of a collision being detected when the cat's ear intersects with the empty corner of the star's bounding box. But it's still not precise collision detection between the image of the character and the star. Is that important? In all likelihood, it won't be.

Take a good look at the collision detection going on in some of your favorite 2D games, and you'll notice that you can often touch an enemy just slightly and get away with it without a collision being registered. I can't count the number of times I've been saved by this fuzzy collision detection when jumping over barrels in
Donkey Kong
or evading Koopa shells in
Super Mario Bros.
, and it never seemed like there was something wrong with the game.

This boils down to very carefully thinking about the collision detection in your game and deciding which kinds of collisions are important and which aren't. Let's have another look at the cat and star problem. Would it really make sense to have the cat pick the star up if its ears were touching the empty corner of its bounding box? It definitely wouldn't, and if it did happen it would certainly look wrong. Is it okay for the star to overlap with the cat's body a bit and not register a collision? Probably'because as soon as the cat touches the star with the part of its body that includes its paws, the collision will occur. This would make sense to the player. The slight overlap would be accounted for as the shallow depth (or maybe the cat's fur), and the player wouldn't notice there was anything wrong with it.

However, if you tested this and discovered that it actually did look really awkward, you could start adding more rectangular subobjects in areas of the cat to improve or fine-tune the collision accuracy. You could add as many of these additional subobjects as you need. The only drawback is that you'll have to write more code to check for these collisions. And if you have a huge number of them, they might start to slow down your game. Still, it's a good solution, and there are very few collision detection problems you won't be able to solve by doing this judiciously.

All this is an art, not a science. If you get the balance right, you'll have an amazingly comfortable and natural collision detection system. Hooray for
hitTestObject
!

Advanced collision detection strategies

HitTestObject
is going to keep you busy for most of this book, but eventually your games will need more precise ways of detecting collisions. The following are some techniques you can look into:

  • hitTestPoint
    . This is a related method to
    hitTestObject
    . It tests whether a single point is intersecting the shape of an object. However, it only works with vector shapes, which you can make with code using AS3.0's
    Shape
    class or draw with Flash Professional software. Here's the format for using the
    hitTestPoint
    method:
    if(vectorShape.hitTestPoint(pointX, pointY, true))
    {
      //Collision directives…
    }

    If
    pointX
    and
    PointY
    are touching the vector shape, the collision will register as
    true
    , and the collision directives will run.
    hitTestPoint
    actually tells you if the point is touching the actual shape of the object, not just its bounding box.

    This seems like it could be useful, but it's almost never used for games. That's not because it doesn't work well for what it does, but it turns out that there are better, more useful, and more precise ways of checking for collisions between shapes. Most game designers thus step over it on the way to greater things. Don't discount it completely, however; you may find some innovative uses for it in some of your games. You can find out more about
    hitTestPoint
    at
    http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html?filter_flash=cs5&filter_flashplayer=10.2&filter_air=2.6#hitTestPoint()
    .

  • BitmapData.hitTest.
    This AS3.0 method, if properly used, will lead you to the holy grail of collision detection: pixel-perfect collision between shapes. It requires an advanced understanding of AS3.0 and programming to use, but you'll have all those skills by the time you've finished this book. You'll find out everything you need to use
    BitmapData.hitTest
    for very sophisticated collision detection in
    Advanced Game Design with Flash
    .
  • Use math. Perhaps surprisingly, the best way of figuring out whether two objects are colliding is to ditch AS3.0's built-in methods like
    hitTestObject
    completely and figure it out for yourself. Not only does this give you a lot of precision, but if you use math to work out collisions, your games will run much faster. At an advanced level, you can use
    vector math
    to do extremely precise collision detection between objects of all shapes and sizes (you'll find all about how to do this in
    Advanced Game Design with Flash
    .) However, you can use much simpler math to do very precise collision detection between rectangular shapes, which is perfect for 95% of the games you're likely to write.

So let's take a look at another way of doing collision detection that you'll find great uses for in your games.

Working with vector based collision detection

So far, the collision detection code you've looked at has told you when two objects are touching, and you've been able to use that information to change the values of variables and object properties. However, for most games you need to go one step further. You need the objects to be able to react in some physical way to the collision. For example, if a game character bumps into a box, the box should block its movement. Or, if a game character finds a rock, perhaps it should be able to push that rock around stage.

There are no features built in to AS3.0 that let you do these things. You can certainly make these things happen, but you'll have to write all the code to do it from scratch. That means learning a little easy math, and taking the time to see how the code works. Don't let this put you off'the skills you'll learn along the way will be invaluable to your developing career as a game designer, and you'll be able to directly apply all these same techniques to any other game design technologies or programming languages.

Vector based collision detection
is one of the great black arts of video game design. Learn how to do it and you'll have precision control over all the collision detection and reaction in your games. You're going to use it to prevent two objects from overlapping, so that one object blocks the movement of the other.

Preventing objects from overlapping

If you want a game object, like a box, to block the movement of a game character, you have to find a way of preventing the character and box from overlapping. But you can only do this if you know by how much the objects are overlapping when they collide.
hitTestObject
won't help you with this at all because it doesn't give you any information about the amount of overlap between objects in a collision.
Figure 6-19
illustrates this problem.

Figure 6-19.
You can separate objects in a collision if you know by how much they're overlapping. But how can you figure that out?

If you know the amount of overlap between the objects, then you can separate them by exactly that amount. How can you figure that out? The solution is to use
vectors
.

You can think of vectors as imaginary lines that connect objects together. By “imaginary” I mean they just exist as numbers; you can't see them on the stage. But if you draw these imaginary lines between the centers of your game objects, you can find out if the objects are touching and also by exactly how much they're overlapping. If you know by how much they overlap, you can separate them with knife-edge precision. It's all done using some simple math. Here's how it works:

First, you need to calculate a vector between the center of the first object and the center of the second object. You can describe this vector using two variables.

  • vx
    : tells you how wide the vector is. “vx” stands for “vector along the x axis.”
  • vy
    : tells you how high the vector is. “vy” stands for “vector along the y axis.”

If you have
vx
and
vy
variables that store this information, then you've created a vector that you can use in your game.
Figure 6-20
shows how to use the
vx
and
vy
variables to describe the distance between two game objects.

Figure 6-20.
The vx and vy variables describe the vector's width and height.

The distance vector that you see in
Figure 6-20
is the imaginary line I was talking about. You can't see it on the stage. It only exists because the
vx
and
vy
variables are describing its height and width.

You can easily see in
Figure 6-20
that the objects are 5 units apart on the x axis and 5 units apart on the y axis. That's all the
vx
and
vy
variables are telling you. Easy stuff!

If you ever need to know exactly how long the distance vector is, you can use the Pythagorean theorem. The Pythagorean theorem is a very common, well-worn formula for working this out. Here's how to use it with the
vx
and
vy
variables to calculate the exact distance between the objects:

distance = Math.sqrt(vx * vx + vy * vy);

Math.sqrt
is a built-in AS3.0 method that tells you the square root of whatever value is in its argument.

In
Figure 6-20
, the
vx
and
vy
variables have the values 5 and 5. If you substitute these in the formula above, it will look like this:

distance = Math.sqrt(5 * 5 + 5 * 5);

If you run this code in AS3.0, you'll end up with the following result:

distance = 5.9

That's exactly the length of the distance vector between the objects that you see in
Figure 6-20
.

Being able to figure out the exact distance between objects like this is extremely useful for games. If you know which objects are closer to others, your game characters could make decisions about where to go or what they should be avoiding based on how close or far they are to other objects. You don't need to use the Pythagorean theorem in this chapter, but you'll revisit it in
Chapter 10
.

Now that you have a vector that tells you the distance between two objects, how can you use it to find out if they are touching? First, you have to calculate the combined half-widths and half-heights of the two objects. What do I mean by that? Take the width of the first object, and divide it by half. Then take the width of the second object, and divide it by half also. Add these two numbers together, and you end up with a number that tells you what the combined half-widths of the objects are. Here's an example:

Other books

Wasted by Nicola Morgan
Trouble's Child by Walter, Mildred Pitts;
The Fourth Star by Greg Jaffe
Gaslight in Page Street by Harry Bowling
What the Duke Wants by Kristin Vayden
Switch by Janelle Stalder
Meltdown by Andy McNab
A Southern Star by Forest, Anya