Collision detection with a tilemap- raping the walls

Started by
12 comments, last by Trienco 12 years, 10 months ago

int tileX = static_cast<int>(entity.x / tileSize);
int tileY = static_cast<int>(entity.y / tileSize);


I see trouble unless you limit it to positive numbers. -1 should always be in tile -1 but ends up 0 unless you add special handling for negative coordinates.

Shouldn't the left side be:
insideX = (temp.x + 32) - getX(); (the right block edge minus the objects left edge
setX(temp.x + insideX); (the right block edge plus the amount you have to bounce back)

The numbers in your code confuse me. Where did 24 come from? Why the additional -32 after colliding to the right?

Wait, I noticed one bug in my code. You need to
setX(temp.x - 2*insideX)
(once to move "out" of the block, twice to where you should be after bouncing back)

So the fixed collision to the left would be:
setX(temp.x + 2*insideX)

And to exploit the neatness of math


if (hspeed > 0)
insideX = (getX() + 32) - temp.x;
else
insideX = getX() - (temp.x + 32);

//or more compact and confusing: insideX = getX() - temp.x + (hSpeed * 32);

setX(getX() - 2*insideX);



edit: damn non-descriptive names. getX, not temp.x
f@dzhttp://festini.device-zero.de
Advertisement
Yes, that was what I had done originally (with the exception of multiplying the insideX by 2), but for some reason the enemy would then start flickering left and right, without moving, when he touched a wall. After much trial and error, this is what I got. Not entirely sure why it works, but it does. And as for subtracting 32, it made for smoother looking animation. Same for adding 24, but if I added 32 on that side it would end up on the other opposite of the block.

[quote name='Sirisian' timestamp='1306262975' post='4815243']
int tileX = static_cast<int>(entity.x / tileSize);
int tileY = static_cast<int>(entity.y / tileSize);


I see trouble unless you limit it to positive numbers. -1 should always be in tile -1 but ends up 0 unless you add special handling for negative coordinates.
[/quote]
Indexes into an array are normally restricted to positive numbers. You see in a tile based game the tile map is normally represented by a multidimensional array either indexed with y * width + x or using jagged arrays so the restriction of only positive numbers is there.

Indexes into an array are normally restricted to positive numbers.


Yes, but entity positions aren't tile indices and you add implicit limitations to one level of abstraction (object positions) based on a much lower level (layout in memory). I'll not bring up languages where negative indices are perfectly normal and common, since we're talking Java here. Still, you should point out that your code requires positions to be limited to values >tileSize and <worldsize - tileSize not only to prevent "falling into the void", but because any position on or beyond the first or last tile will cause access violations.


Yes, that was what I had done originally (with the exception of multiplying the insideX by 2), but for some reason the enemy would then start flickering left and right, without moving, when he touched a wall. After much trial and error, this is what I got.[/quote]

You should avoid the "trial and error shortcut", it will only result in stuff that looks like a working solution, but blows up every 100th time (which is the most annoying kind of bug to find). What if your randomly chosen value of 24 only works for 75% of cases, because for the remaining situations it should have been 25 or 29? What if in two weeks you suddenly see objects flickering twice and then pop out on the wrong side of a wall?

Programming means analyse and understand the problem, create an informed plan to solve it and then implement that plan. Seriously, you are currently dealing with the most trivial kind of collision you will ever get. It's only 1 dimensions and you're not even checking for actual collision, but for intersection (which can easily fail with fast moving objects and/or variable time steps). If you decide you can't be bothered to wrap your head around the problem while it's simple, how do you expect to get anything done when you add a second dimensions or want objects that move more than 32 pixels per frame or add thinner blocks as walls?

Look at how you calculate insideX for collisions to the left and right: Notice something? It's the exact same thing. You add 32 and subtract temp.x. The whole point is to determine how much you overlap the block and how much to bounce back. While you _could_ still exploit the fact that apparently everything is 32 wide, but that's not going to make the code any easier to understand.

You can of course ignore the idea of "how close was the object to the block before colliding and how much of it's movement should have already happened in the other direction", in that case you don't need any calculation except for placing the object to the left (temp.x - 32) or to the right (temp.x + 32) and change the direction (hspeed *= -1). Just make sure to use a method you actually understand and could explain (nothing more embarassing than answering "that's cool, how does it work" with "uhm... no idea, I just randomly put some stuff there until it kind of worked most of the time").
f@dzhttp://festini.device-zero.de

This topic is closed to new replies.

Advertisement