A Flash Developer Resource Site

# Thread: What's the best method for hitTesting ground and shapes in a platform game?

1. ## What's the best method for hitTesting ground and shapes in a platform game?

I will redo the whole code for my balloon game. But before that I will make (or start on) a new platformer so that I can get a better understanding of the platform collision detection.

My question is: what is the best method to check collision with various objects?.

The 2 methods I know are the one where you paint the whole stage and put it in a MC and check the shapes like (_x, _y, true).

The other way is to instead of having one giant painted stage, have hidden MCs and check collision with them instead:
Originally Posted by UnknownGuy
Ironclaw, to fix the collision problems you really need to go away from just point vs landscape collision and move into individual movieclips/rectangles.
Originally Posted by UnknownGuy
Well, theoretically if you went all math you wouldn't need mcs, but you would need to create an "object" with the x,y,width and height of each platform.

But if you split it into mc's, you can just use a normal rectangle vs rectangle hittest, not using points.
So, what should I do? as my previous attempt kinda worked, but very glitchy .

2. This may just may things worse for you, as it's another alternative.

In my BombJack game I get all the cords of the platforms ( x,y, width height ), and split them into arrays depending on which part of the screen their in ( ie, split the screen into quarters ).

From there I do a maths based check, so if the players jumping I check his head to the platforms base, if falling check his feet to the top of the platform etc.
I also do a loop checking pixel by pixel, 'cause it's important for the main sprite to be pixel perfect ( Whereas it doesn't matter a great deal about the baddies ). It's a bit slow, but 'cause I'm only checking a quarter of the screen ( Most of the time anyway ) I can get away with it.

Now this is for a static screen, and I guess you want scrolling, but it's another method to think about. Also tiles of course ( You can even just use tiles for your collision detection and keep the map fairly art based ).

Squize.

3. I like to use a for-loop that check's every pixel on the border of your hero with pixel-hitTest. So if you'd move right, it would loop from the top-right to the botton-right corners and check every pixel on a hitTest. The advantage of this is that you can have an almost pixel-perfect hitTest and that the ground can still be one big MC.

~Sph

4. Originally Posted by Squize
This may just may things worse for you, as it's another alternative.

In my BombJack game I get all the cords of the platforms ( x,y, width height ), and split them into arrays depending on which part of the screen their in ( ie, split the screen into quarters )....
Yeah, sound too complicated .

Originally Posted by SaphuA
I like to use a for-loop that check's every pixel on the border of your hero with pixel-hitTest. So if you'd move right, it would loop from the top-right to the botton-right corners and check every pixel on a hitTest. The advantage of this is that you can have an almost pixel-perfect hitTest and that the ground can still be one big MC.
Isn't that kinda the way I did it (if checking the code in the link below). That method didn't require any math and was fairly easy for me to work with, but still, after a while everything became unstable and dodgy/glitchy... ie the character jumped and landed, then moved up and down a bit before finally came to a stop asnd stuff...

http://www.flashkit.com/board/showth...hlight=balloon

What I was thinking of trying was to make lots of hidden MCs represent the shape of the stage and of course add them all in a for loop and then........ well.... are abit uncertain when to execute the collision detection code.. ie when the player moves right and then only check for the right stuff he might collide with... or just make one single collision code checking everything... well.... will play around with some stuff and see what happen ...

5. Squize: I know a lot of people like to split up the screen like that but I still don't
really get it. I understand the reasons, but it seems like a lot of work since a lot of
new problems follows with it.

For example: what if the player is falling and the player's
registration point is within the upperleft quarter. In that frame he will loop against all
objects in that area, but what if he's moving so fast that he will end up in the quarter beneth
it? There may be objects there that the player isn't checking for collision with until the following
frame when it's already to late.

How do you solve this? Do you check for collision with objects within both (or all four) areas in
cases like this?

6. It's not that tricky at all on a static screen ( Don't think I've ever tried on a scrolling one ).

You just pre-calculate what goes in your sectors. If a platform crosses over two or more sectors ( Which is highly likely ) then you just put the same platform into both arrays.
You always know which sector the player sprites in, so choosing the correct arrays to test against is pretty straight forward. Worse case ( player in the center of the screen ) then you do have to run more checks, but it's still not overly painful and as a whole you gain more than you lose.

Speed wise it holds up pretty well. I used it ages ago on my X game for the player bullets to asteroids check, and it worked fine even with fast moving objects.

Squize.

7. I still have the same problem as with the other hitTest thingy I did.

When doing it like this, the first jump will make the player land inside the ground covering the player to 50%. When pressing jump again, he will land ontop of the ground (good). When pressing space again, the player will land 2 pixels inside the ground.... and when jumping again he will land 5 pixels.... etc.... 10pixels till he is half way inside again, and after that he will land ontop of the ground and it will the loop over again... why is that??????

Code:
```	if (jumping == true) {
player.gotoAndStop("jump");
velY += 0.7;
player._y += velY;
}
for (i=0; i<10; i++) {
if (world["objects"+i].hitTest(player._x, player._y+21.5, true)) {
trace("hit");
jumping = false;
velY = -15;
}
}
};```

If I add a falling speed limit like this:

Code:
```	if (jumping == true) {
player.gotoAndStop("jump");
velY += 0.7;
player._y += velY;
if (velY>=0.7) {
velY = 1;
}
}
for (i=0; i<10; i++) {
if (world["objects"+i].hitTest(player._x, player._y+21.5, true)) {
trace("hit");
jumping = false;
velY = -15;
}
}
};```
He will of course fall very slowly, but he will land pixel perfect. If changing the fall speed to 2, he will land at random depths like in the fist code problem... if keep jumping... and at fall speed 5, he will at the first jump land 2 pixels in, then at the next jump pixel perfect, then the next jump 1 pixel in, then 2.. looping..

omg.. the very same problem as with my balloon hittest engine... I use framerate 30 and of course by changing it to like 60 it will make fall speed of 2 pixel perfect while in fps 30 make fall speed of 2 +-1 pixel off...

I don't want to use fall speed limit as I want the player to accellerate while falling.

this is oooo difficuly and frustrating.... I could easily solve my problem bu taking one of those free tutorial platforms flas that are available... but I wont.. I really need to do this myself and from the ground.... as I get the same result with this type of checking as with just checking one big drawed area.. I'm better of with a drawn area as no for loops is needed.... i need several for this type....

Oh well...... will fiddle around with it some more....

It's reallt annoying that so many people makes good platform engines and posts them everywhere.. there are alot of them on newgrounds, made by KIDS... well... seems like it anyway... maybe they steal already made flas? .....

I WILL PREVAIL!!

arghh arghh arghhh...and on top of all this, I doesn't get any better speed than 5kb/sec when downloading torrents..... the agony never ends! :P

(lots of code and text removed under this text cuz I got bored of explaining......)

8. Yep torrents blow

For a start, get rid of +21.5 < The .5, you're a coder not a designer mate, work in integers.

Also after the velY = -15; have you tried

player._y-=int(velY);

? That will round it down which may help with the velocity being a floating point. I can't actually see where you reset the player _y when you land, you just subtract 15 from the velocity.

As another alternative you can just force the value in there, eg

player._y=world["objects"+i]._y-player._height;

( Assuming that all the objects have a y registration point of 0 ).

Squize.

9. I use 21.5 as the box I drew is 43x43.

The player._y-=int(velY); didn't do any difference, still random falling-through-the-ground depths.

...

I have made some changes... so here's the fla and a swf. Had problem with the falling code (as commented in the fla), so didn't add that piece.

http://www.retrogaming4ever.com/Misc/Arghh.html

ps: Why isn't swf accepted as a valid attachment extension?

Valid file extensions: ai bmp doc fla fun gif jpe jpeg jpg pdf png psd swi t3d txt zip

10. Here's a very quick and dirty fix. You're still going to get the odd jump where it restores the _y position, but that should be hidden by the landing animation.

Also, if you're not going to use vectors, avoid centering your mc like you have.
Code:
```	// if the player has passed through the ground, move him up:
for (i=0; i<10; i++) {
if (world["objects"+i].hitTest(player._x+21.5, player._y+21.5, true) or world["objects"+i].hitTest(player._x-20.5, player._y+21.5, true)) {
trace("move up");
var mc=world["objects"+i];
var cnt=-1;
while(++cnt!=10){
if (mc.hitTest(player._x+21.5, player._y+21.5, true) or mc.hitTest(player._x-20.5, player._y+21.5, true)) {
player._y--;
} else {
break;
}
}
}
}```
Squize.

11. Thanks for clearing that up : ) When might we expect to see the X game up and running? Those screenshots were really sexy

12. np olli's killing himself doing the security stuff for sN, so hopefully sooner rather than later. Thanks for the interest though mate

Squize.

13. Originally Posted by Squize
Here's a very quick and dirty fix. You're still going to get the odd jump where it restores the _y position, but that should be hidden by the landing animation.
Yep, and it's alot better now, thanks . Trying to undertand exactly what it's doing:

Code:
```		var mc = world;
var cnt = -1;
while (++cnt != 10) {
if (mc.hitTest(player._x+21.5, player._y+21.5, true) or mc.hitTest(player._x-20.5, player._y+21.5, true)) {
player._y--;
} else {
break;
}
}```
I can see what it is doing, but don't understand how it could work . Also seen several platform engines using the while thingy but never understood what it's for, reading the reference for while doesn't make it clearer .

You made a copy of the hitTest line and added the above code so tha the "if" function now have two of those lines which looks odd, is it really necessary to have those 2?.. can't they be merged?

Code:
```if (world.hitTest(player._x+21.5, player._y+21.5, true) or world.hitTest(player._x-20.5, player._y+21.5, true)) {
velYx = -10;
trace("move up");
var mc = world;
var cnt = -1;
while (++cnt != 10) {
if (mc.hitTest(player._x+21.5, player._y+21.5, true) or mc.hitTest(player._x-20.5, player._y+21.5, true)) {
player._y--;
} else {
break;
}
}
}```
Originally Posted by Squize
Also, if you're not going to use vectors, avoid centering your mc like you have..
I kinda know what a vector is, but what vectors are you referring to? and why should the mc not be centered?.. and do you mean the player mc? (guess you do as you said mc and not mcs)

Anyway, I couldn't get my fall code to work. For some reason it doesn't hitTest.
Code:
```	for (o=0; o<10; o++) {
if (!world["objects"+o].hitTest(player._x, player._y+22.5, true)) {
trace("in air");
}
}```
So I changed things to work like in my balloon game; hitTesting against a painted area inside a MC. Then the fall code instantly worked and all those for loops aren't needed.

fla attached if someone wanna have a look... and here's the swf:
http://www.retrogaming4ever.com/Misc/Arghh2.html

Now I will try to add a scroller to it..... and it will probably screw things around. My goal is to have a working platform engine that I understand fully and that I then can use for all my games suited in that category. This engine will be alot less complicated than the balloon one, as in this one the player wont be able to land on platforms or if hitting a roof with the head; then fall down and stuff.. this will be a simple one and I already know what game to make out of it.

14. "Also seen several platform engines using the while thingy but never understood what it's for"

while is pretty much like a for loop, just ever so slightly different syntax and runs a bit quicker. To be honest I don't have a clue about for syntax, I never use it, and if I ever need to I always have to look at help.

"You made a copy of the hitTest line and added the above code so tha the "if" function now have two of those lines which looks odd, is it really necessary to have those 2?.. can't they be merged?"

Kinda lost me there sorry ?

"why should the mc not be centered?.. and do you mean the player mc? (guess you do as you said mc and not mcs)"

If you're not going to zoom on a sprite ( ie, change it's _xscale or even use _rotation ) then it shouldn't be centered, there's no need for it. Also Flash sometimes distorts bitmap images if they've got a minus position within a mc.
I mentioned vectors ( Meaning in a graphical sense, not in a maths sense ) 'cause if you do need zooming or rotation you're better off using vectors 'cause it looks like poo with bitmaps.

Squize.

15. while is pretty much like a for loop, just ever so slightly different syntax and runs a bit quicker. To be honest I don't have a clue about for syntax, I never use it, and if I ever need to I always have to look at help.

Yeah, that's what I thought. Looked like a loop thingy when reading the help.

If you're not going to zoom on a sprite ( ie, change it's _xscale or even use _rotation ) then it shouldn't be centered, there's no need for it.

Yes, of course, if I want to zoom an object, it's better if the point is in the middle or it will zoom in on where the point is. (I think)

In my game it doesn't have to be in the middle on anything, except the player cuz I never know if I want to be able to zoom in on him (for cool close up effect because I got some ideas for cool stuff).

Also Flash sometimes distorts bitmap images if they've got a minus position within a mc.

Ahh, good to know, thanks.... Don't think I have seen any distortions yet though.

I mentioned vectors ( Meaning in a graphical sense, not in a maths sense ) 'cause if you do need zooming or rotation you're better off using vectors 'cause it looks like poo with bitmaps.[/QUOTE]

Vectors which is things drawn i.e Flash?... if so, yep... they are much better for zooming in as no pixels are shown, but they also require more cpu power. But I always use bitmaps only, never anything less (gifs preferred). I like that "retro" look . So the more and bigger pixels, the better :P.

Kinda lost me there sorry ?

Yeah well... hmm.. you see I had this code for making the player move up if he passed through the ground:
Code:
```	for (i=0; i<10; i++) {
if (world["objects"+i].hitTest(player._x+21.5, player._y+21.5, true) or world["objects"+i].hitTest(player._x-20.5, player._y+21.5, true)) {
trace("move up");
player._y--;
}
}```
It was a big buggy as you would move through the ground and then slowly upwards and also everytime you jumped you would land at different hights. You fixed this by by adding some more code and in that code you used the "if" again, but changed the world to mc... Anyway, could this code:
Code:
```	if (world.hitTest(player._x+21.5, player._y+21.5, true) or world.hitTest(player._x-20.5, player._y+21.5, true)) {
velYx = -10;
trace("move up");
var mc = world;
var cnt = -1;
while (++cnt != 10) {
if (mc.hitTest(player._x+21.5, player._y+21.5, true) or mc.hitTest(player._x-20.5, player._y+21.5, true)) {
player._y--;
} else {
break;
}
}
}```
be changed to just have one "if" line?... right now it has 2. I was also wondering what was happening with the new part you added.... I noticed that the "10" is the speed in which the player moves in place if he fell into the ground... if chaning to 99, you almost doesn't notice the "bump".

It's no biggie .....

I have made some more changes and have added a scrolling and by using this code (in bold):

Code:
```var velY = -15;
var velYx = -10;
var jumping = false;
var falling = false;
var worldXSpeed = 4;
var playerXSpeed = 4;
this.onEnterFrame = function() {
// if the player isn't holding left or right and is not jumping, then stand.
if (!Key.isDown(Key.RIGHT) and !Key.isDown(Key.LEFT) and jumping == false) {
player.gotoAndStop("stand");
}
if (Key.isDown(Key.RIGHT)) {
world._x -= worldXSpeed;
player._xscale = +100;
player.gotoAndStop("walk");
if (world.hitTest(player._x+21.5, player._y+21.5, true) or world.hitTest(player._x+21.5, player._y-21.5, true)) {
world._x += worldXSpeed;
}
}
if (Key.isDown(Key.LEFT)) {
world._x += worldXSpeed;
player._xscale = -100;
player.gotoAndStop("walk");
if (world.hitTest(player._x-21.5, player._y+21.5, true) or world.hitTest(player._x-21.5, player._y-21.5, true)) {
world._x -= worldXSpeed;
}
}
if (Key.isDown(Key.SPACE)) {
jumping = true;
}
if (jumping == true) {
player.gotoAndStop("jump");
velY += 0.7;
player._y += velY;
// ground checking code when falling:
// will check for the bottom left, bottom and bottom right courner of the player.
if (world.hitTest(player._x-21.5, player._y+21.5, true) or world.hitTest(player._x+21.5, player._y+21.5, true)) {
trace("ground stop");
player._y--;
// changes the veolicty back to -15, as originaly stated on top of
// this page (var velY = -15), it handles the height the player jumps.
velY = -15;
jumping = false;
}
}
// if the player has passed through the ground, move him up:
if (world.hitTest(player._x+21.5, player._y+21.5, true) or world.hitTest(player._x-21.5, player._y+21.5, true)) {
velYx = -10;
trace("move up");
var mc = world;
var cnt = -1;
// 10 seems to be the speed in which it moves up to the right place.
while (++cnt != 10) {
if (mc.hitTest(player._x+21.5, player._y+21.5, true) or mc.hitTest(player._x-21.5, player._y+21.5, true)) {
player._y--;
} else {
break;
}
}
}
// if the player is not touching the ground and are not jumping, FALL!
if (!world.hitTest(player._x+22.5, player._y+22.5, true) and !world.hitTest(player._x-22.5, player._y+22.5, true) and jumping == false) {
falling = true;
} else {
falling = false;
}
if (falling == true) {
trace("falling");
velYx -= 0.7;
player._y -= velYx;
}
};```
when walking to the right or left and touches an obstacle, the player moves up... caused by the "move up" code of course. (see example here) So I changed the x values to 23 instead so the player wouldn't get too close and thus not move up, which works (example here). But the problem I then have is that the player gets different distances in which he stops:

Walking to the right:

the distance difference is different on each step.

But when walking to the left, the distance is greater:

Also, as the player get different distances, sometimes depending on floor hight, he gets too deep and the "move up" code executes... so I ended up using 25.5 instead of standard 21.5 to get faaar away.....

How can this be fixed then??.. only fix I could come up with was using 25.5, but then there's a big gap between the player and the.. wall.

I will make this to a fighting game with combos! ... yes.... so many people are making fighting games, so I thought I would try it.... the special thing will be the combos.. and I'm almost positive that making the combo system and stuff is alot easier than making this platform collision engine.

16. The fla if needed .

17. As I will probably want to zoom in and stuff I have moved both the player and the world mc inside a MC. To make things work now I knew I needed localToGlobal... it took some tries till I got it to work . But unfortunately the landing part is a bit buggy now.. when landing the player quickly bounces several times before stopping.

The swf if you want to see what I mean: swf
The new fla is attached and here is the new code:

Code:
```var velY = -15;
var velYx = -10;
var jumping = false;
var falling = false;
var worldXSpeed = 4;
var playerXSpeed = 4;
this.onEnterFrame = function() {
//---------------------------
var point = {x:0, y:0};
var x = point.x;
var y = point.y;
player.localToGlobal(point);
//---------------------------
// if the player isn't holding left or right and is not jumping, then stand.
if (!Key.isDown(Key.RIGHT) and !Key.isDown(Key.LEFT) and jumping == false) {
player.gotoAndStop("stand");
}
if (Key.isDown(Key.RIGHT)) {
world._x -= worldXSpeed;
player._xscale = +100;
player.gotoAndStop("walk");
// using 23.5 instead of 21.5 so the player doesn't get too deep, or he will move up
// by the "move up" code further down.
if (world.hitTest(point.x+23.5, point.y+21.5, true) or world.hitTest(point.x+23.5, point.y-21.5, true)) {
world._x += worldXSpeed;
}
}
if (Key.isDown(Key.LEFT)) {
world._x += worldXSpeed;
player._xscale = -100;
player.gotoAndStop("walk");
// using 25.5 instead of 23.5 as with walking to the right because for some
// reason, the player gets deeper into the wall when walking left than right.
if (world.hitTest(point.x-25.5, point.y+21.5, true) or world.hitTest(point.x-25.5, point.y-21.5, true)) {
world._x -= worldXSpeed;
}
}
if (Key.isDown(Key.SPACE)) {
jumping = true;
}
if (jumping == true) {
player.gotoAndStop("jump");
velY += 0.7;
player._y += velY;
// ground checking code when falling:
// will check for the bottom left, bottom and bottom right courner of the player.
if (world.hitTest(point.x-21.5, point.y+21.5, true) or world.hitTest(point.x+21.5, point.y+21.5, true)) {
trace("ground stop");
player._y--;
// changes the veolicty back to -15, as originaly stated on top of
// this page (var velY = -15), it handles the height the player jumps.
velY = -15;
jumping = false;
}
}
// if the player has passed through the ground, move him up:
if (world.hitTest(point.x+21.5, point.y+21.5, true) or world.hitTest(point.x-21.5, point.y+21.5, true)) {
velYx = -10;
trace("move up");
var mc = world;
var cnt = -1;
while (++cnt != 10) {
if (mc.hitTest(point.x+21.5, point.y+21.5, true) or mc.hitTest(point.x-21.5, point.y+21.5, true)) {
player._y--;
} else {
break;
}
}
}
// if the player is not touching the ground and are not jumping, FALL!
if (!world.hitTest(point.x+22.5, point.y+22.5, true) and !world.hitTest(point.x-22.5, point.y+22.5, true) and jumping == false) {
falling = true;
} else {
falling = false;
}
if (falling == true) {
trace("falling");
velYx -= 0.7;
player._y -= velYx;
}
};```

18. I can't get the player to stop bouncing, but when removing your code:

Code:
```	var mc = world;
var cnt = -1;
while (++cnt != 10) {
if (mc.hitTest(point.x+21.5, point.y+21.5, true) or mc.hitTest(point.x-21.5, point.y+21.5, true)) {
player._y--;
} else {
break;
}
}```
he stops bouncing but goes a bit into the ground and then slowly moves back up (which is what the code is made to fix, but doesn't now as I have added localToGlobal). I have tried all kind of changes but he bounces anyway.

19. Hey,

I'm new to game programming- prism is my first attempt at making a game, so I haven't got a lot of experience with different ways of achieving collision detection with hitTesting, and I couldn't get my head around the separating axis method used in N either. I spent about three months trying to get line/circle collision working too, but it kept failing for reasons still unknown to me.

So what's the point of this post?

Vectors!

I strongly recommend you look at using vectors for detecting collisions with your platforms. Following some very straightforward tutorials found on Tonypa's site, you can implement vectors into your collision checking, and have a world of power for creating perfect collision with very complex shapes. I've used vector based collision, combined with bitmap collision and the standard hitTest method in combination together to get the desired results. It runs very fast too! Have a look at those tutorials, and if you can't work out how to implement vectors in your code after following them, give me a shout and I'll share some code with you.

Hope that helps!

20. The way to code these "vectors" looks very complicated and are nothing close to the way I code now. I guess intregating the vector coding technique could improve the accuracy of my hitTest... but looks like it's a whole new way to code.

Many platformers don't use this vector coding technique and still have good collision detection.... and I'll keep on trying to code this way.

Thanks though.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•

 » Home » Movies » Tutorials » Submissions » Board » Links » Reviews » Feedback » Gallery » Fonts » The Lounge » Sound Loops » Sound FX » About FK » Sitemap