Advertisement

A very VERY bad int.

Started by February 11, 2012 06:58 PM
2 comments, last by LorenzoGatti 12 years, 9 months ago
So i almost completed my a* smoothing algorithm a couple of hours ago. But sometimes it went through walls somehow, some way.

After debugging very long, and letting all the colision rectangles show up i noticed i was moving my rectangle by (int)0.96 since multiplied normalized X vector of 0.16 with 6(1/5 of my tiles). So it never bumped into the wall and figured the next straight path should be above the wall.

Now i am just multiplying my normals with 1/2 of my tile size, and i should not foresee any problems with what i currently have, it does ocasionally go slightly across a non walkable tile but it's not very noticable. But what if i have really long straight walls so my normalized vector times the full tile size would be below 0. I can 't simply increase the normal since it's used for direction.

I should probably tell how i am doing my smoothing.

I get the path list from a regular A*.

I then "for" loop through it and see what the first path is i can not reach straight.

I check the distance and direction of both tiles and let a test rectangle test the path until it reaches the destination.

testrec.X += (int)(direction.X * velocity);
testrec.Y += (int)(direction.Y * velocity);
// a rectangle only excepts ints, hence the cast so if the direction*velocity of testing rectangle is not above 1 it won't move that direction and thinks the path is ok. I really like this velocity as low as possible so my paths are not intersecting.


I put the tile [i - 1(since i is not reachable)] as a vector in a new list.

Repeat until the list is done.
If you are using tiles, your speeds and positions (at least the ones you use for pathfinding and physics) should be integers.

Fractions can be used to break an "official" move into several interpolated frames of animation: the worst that can happen is a practically invisible error in sprite position.

On the other hand, when you use floating point for equality comparison (like in your tests for touching walls) slight errors are amplified.

Omae Wa Mou Shindeiru

Advertisement
Not sure what your saying....

It's like this

My character hugs a wall to the right and clicks 20 tiles above player and 1 tile to the right (where the wall ended after 20 tiles up).

Now i calculate the direction by:
direction.normalize(tileclicked - playerlocation);

Now the normalized vector has a X value of .05 (don't get me on my math please :D), so i let this collision rectangle traverse the path rectangle by doing:
rectangleX += direction * 15pixels;

Now since the rectangle only excepts int's i have to vast a int on it. and since .05 * 15 == .75 that rectangle will never move into the wall and detect colision. And 15 pixels are pretty long steps to check for colision on 32*32 tiles. I rather use something like 5 or 6 so things never move through walls.

One way to solve it is to make for each angle a sepperate statement but this feels like overkill.
Sorry for misunderstanding your code, I didn't notice you rounded coordinates to integer values. This is, however, as wrong as using fractional positions: your integer positions have a random perturbation of up to 1 unit, which can cause all sorts of biased and incorrect pathfinding (errors can accumulate arbitrarily along the steps of the path) and unpredictable collision detection.

Correct and predictable tile-based movement requires moving from tile A to tile B in a whole number of turns, altering actual movement speed (for example, adjacent tiles in 2 turns and diagonally adjacent tiles in 3 turns rather than the "natural" 2.828... turns); you might need to break down tiles or turns into smaller units to reduce error, but the cost of a move should be a whole number of turns.

Omae Wa Mou Shindeiru

This topic is closed to new replies.

Advertisement