|
-
M.D.
Hitest And Basic Collision
hopefully this will stop all the hitTest questions. If you have something helpful to post please do.
THINGS YOU SHOULD KNOW ABOUT HITEST
- hitest can find a collision between two movieclips or a point against a movieclip
- hit testing uses global coordinates
- the two methods of hit testing are: movieclip : movieclip or movieclip : point
- movieclip to point can accept a thrid parameter, called a shape flag, if this parameter is set to true, it will test the actual shape of a movieclip (this can be anything) if it's set to false it will check the bounding box of a movieclip, this is a bounding box is always a square or rectangle
- hit testing will return a boolean value, meaning: true or false, which also means you can store a hitTest in a variable
- hit testing does not position objects, it use is for checking a hit
- hit testing should be avoided with complex mathematical collisions such as Rigid body's
- hit testing is a good simple way to check a hit without slowing your game down
if you remember the above rules, then hitTesting will be a breeze
SIMPLE HITEST
MOVIECLIP : MOVIECLIP HIT TESTING
to perform a simple hit test between two movieclips:
Code:
if (player.hitTest(enemy)) {
trace("hit");
}
MOVIECLIP : POINT HIT TESTING
to perform a hit test on an objects actual shape and a point:
Code:
if (player.hitTest(enemy._x, enemy._y, true)) {
trace("hit");
}
the first two parameters are numbers, they don't have to be the enemy's position, they could be any number you want, the third parameter is the shapeflag, when set to true it checks the numbers against the players shape
to perform a hit test on an objects bounding box and a point:
Code:
if (player.hitTest(enemy._x, enemy._y, false)) {
trace("hit");
}
COLLISION RESPONSE
before any additional checking, nothing is known about the hitTest, we only know that it is true or false, so we need to use other methods to respond to the collision
IF STATEMENT
the "if statement" can be very limited, since we know nothing about the intersection of the hitTest, we can only guess, a common solution is:
Code:
var speed = 10
if (!landscape.hitTest(player._x, player._y+speed, true)) {
player._y += speed;
}
WHILE LOOP
this works by running a loop while an object has detected a collision, a loop is needed so that the object moves in the correct direction the exact amount of pixels required. A while loop is used here because we are not sure how far the movieclip has intersected another movieclip, so we do some operations "while" the condition is true
Code:
while (landscape.hitTest(player._x, player._y, true)) {
player._y--;
}
the above code checks the x and y coordinates of the player and moves it up 1 pixel every time a hitest is found. The drawback to this solution is that it can be slow with the more directions you are checking for.
ADVANCED COLLISION DETECTION
HIGH SPEEDS
sometimes an object will be moving very fast and needs to check collision between an object which is thinner than the movieclips current speed, odds are that the movieclip will miss the detection of a hit because its moving too fast. An easy way to overcome this is use a loop to check the positions between the current movieclips position and its next position, so that anything in between will be detected. This method uses the shapeflag hitest again.
Code:
//players inital velocity's
player.vx = 300;
player.vy = 300;
//code run on every frame
onEnterFrame = function () {
//grab the players actual speed
var speed = Math.sqrt(player.vx*player.vx+player.vy*player.vy);
var vx = player.vx/speed;
var vy = player.vy/speed;
//loop through the coordinates from the player's current position to its next position
for (var i = 0; i<speed; i++) {
var x = player._x+(i*vx);
var y = player._y+(i*vy);
//perform a shape based collision on the landscape based on the current coordinate
if (landscape.hitTest(x, y, true)) {
//position the player at the correct coordinate
player._x = x;
player._y = y;
//stop the movement of the player
player.vx = 0;
player.vy = 0;
//no need to continue checking additional points, so we break from the loop
break;
}
}
//update the players position
player._x += player.vx;
player._y += player.vy;
};
this code assumes the player and landscape are in one movieclip, and this code is put on frame 1 of that movieclip. You can easily change it to your needs by changing the names.
OPTIMISED HIGH SPEEDS
the majority of the above code is used here as well. Except we need to change how many pixels are checked in the loop, if we make this number smaller the collision checking will be faster and less strain on the CPU. But the accuracy of the checking will be smaller. By simply adding and changing the next lines we can optimise the checking:
Code:
//to lessen the strain of the loop, we want to only check a few points
//the higher the step, the less checking we have to do, but the less accurate the check will be.
//if our speed is 70 and the step divisor is 10, that means every that every 7 pixels between the start and end point will be checked
//always keep the step smaller than any part of the movieclip to be hitTested, this will stop anything from missing a collision
var step = speed/10;
var vx = player.vx/step;
var vy = player.vy/step;
//loop through the coordinates from the player's current position to its next position
for (var i = 0; i<step; i++) {
MULTIPLE OBJECTS
using loops again we can check collision between multiple objects.
If you wish to check collision between all movieclips within another movieclip (common scenario: “enemies” within an “enemy’s” movieclip) you use a “for in” loop to check. The same code can be used to check an array or an object. I recommend the object method: var myObjects = {} as the checking is much faster. Using the typeof command eliminates checking of anything in the enemyParent movieclip that is not a movieclip, like objects or variables. Using the "typeof" command is optional.
Code:
function checkHit(player, ob) {
return player.hitTest(ob);
}
for (var i in enemyParent) {
var enemy = enemyParent[i];
if (typeof enemy == "movieclip") {
if (checkHit(player, enemy)) {
trace("hit");
//this is where you can run your collision response function
}
}
}
By creating an additional function we can pass two movie clips, (which don’t have to be player and enemy) and perform a hitest between them, you could also run a collision response script from the returned Boolean
BASIC MATHEMATICAL COLLISION
CIRCLE : CIRCLE COLLISION
Circle to circle collision is actauly quite easy, all we need to do is get the distance between two objects and compare that distance to the sum of both the movieclips radius (since a circle is round we half its width to get the radius)
Code:
function checkCircleCollision(c1, c2) {
//get the radius
var radius = (c1._width/2)+(c2._width/2);
//get the x distance
var dx = c1._x-c2._x;
//get the y distance
var dy = c1._y-c2._y;
//get the overall distance
var distance = Math.sqrt(dx*dx+dy*dy);
//return a boolean indicating whether the distance is less than the radius
return distance<radius;
}
onEnterFrame = function () {
circle1._x += 2;
circle2._x -= 2;
//check the collision between both circles
if (checkCircleCollision(circle1, circle2)) {
trace("hit");
}
};
The above code assumes two movieclips have the names “circle1” and “circle2”. And both movieclips are centered around their origin's
Hopefully this has helped you, I’ve only covered some basic collision detection and responses, there are many ways to do them. These methods are generally not suited to tile based games and games which require realistic reaction. If your looking for such things, I suggest you try these links:
Mathematical: http://www.moor47.fsnet.co.uk/gamephysics.htm
Tile Based: http://www.tonypa.pri.ee/tbw/index.html
More HitTest: http://board.flashkit.com/board/show...Test+explained
Last edited by mr_malee; 09-10-2006 at 08:02 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|