I try to calculate the angle between two points, but my calculation isn't 100% correct. I have a playable character which walks over a set of different tiles. I gave the tiles a fixed angle, but I search for a way to get that angle, if I don't know it.

I make a raycast from the character to the ground and catch the normal vector. After that I try to calculate the angle between the raycast and the normal vector. At small angles my calculation is quite accurate, but it becomes less accurate as the angles grow.

Example:

Tile = 0°, calculated angle = 0.04082203282543162

Tile = -12°, calculated angle = -12.107372514693608

Tile = -24°, calculated angle = -24.326980801092944

But now...

Tile = -36°, calculated angle = -40.01937287049262 (difference of 4°)

Tile = -40°, calculated angle = -47.358631842930436 (difference of 7°)

Tile = -42°, calculated angle = -51.53428808461311 (difference of 9°)

That's my code:

Code: Select all

`var p1:b2Vec2 = body.GetWorldPoint(new b2Vec2(0, 0));`

var p2:b2Vec2 = body.GetWorldPoint(new b2Vec2(0, (height / 2 + 0.3) * Box2DConfig.PIXEL_IN_METER));

var f:b2Fixture = Box2DConfig.world.RayCastOne(p1, p2);

if (f)

{

var rayInput:b2RayCastInput = new b2RayCastInput(p1, p2);

var rayOutput:b2RayCastOutput = new b2RayCastOutput();

f.RayCast(rayOutput, rayInput);

//calculate angle

var v1:b2Vec2 = new b2Vec2(p2.x-p1.x, p2.y-p1.y);

var n1:b2Vec2 = body.GetWorldPoint(new b2Vec2(0, 0));

var n2:b2Vec2 = body.GetWorldPoint(new b2Vec2(rayOutput.normal.x, rayOutput.normal.y));

var v2:b2Vec2 = new b2Vec2(n2.x-n1.x, n2.y-n1.y);

var angle = (Math.atan2(v1.y - v2.y, v1.x + v2.x) * 180 / Math.PI - 90)*-1;

}

Any solutions? Maybe my points aren't accurate enough. If my raycast is exactly vertical "p2.x-p1.x" isn't 0 like it should be, but +/-0.00000xxxx.

EDIT:

Hours later...

Have it now. If anybody is interest, here is the code:

Code: Select all

`var r1:b2Vec2 = body.GetWorldPoint(new b2Vec2(0, 0));`

var r2:b2Vec2 = body.GetWorldPoint(new b2Vec2(0, (height / 2 + 0.3) * Box2DConfig.PIXEL_IN_METER));

var f:b2Fixture = Box2DConfig.world.RayCastOne(r1, r2);

if (f)

{

var rayInput:b2RayCastInput = new b2RayCastInput(r1, r2);

var rayOutput:b2RayCastOutput = new b2RayCastOutput();

f.RayCast(rayOutput, rayInput);

var v1:b2Vec2 = new b2Vec2(r2.x-r1.x, r2.y-r1.y);

var n1:b2Vec2 = body.GetWorldPoint(new b2Vec2(0, 0));

var n2:b2Vec2 = body.GetWorldPoint(new b2Vec2(rayOutput.normal.x, rayOutput.normal.y));

var v2:b2Vec2 = new b2Vec2(n2.x - n1.x, n2.y - n1.y);

var v1Magnitude = Math.sqrt(v1.x * v1.x + v1.y * v1.y);

var v2Magnitude = Math.sqrt(v2.x * v2.x + v2.y * v2.y);

var s = (v1.x * v2.x + v1.y * v2.y) / (v1Magnitude * v2Magnitude);

if (s < -1)

{

s = -1;

}

var exactAngle = Math.acos(s) * 180 / Math.PI - 180;

if (v1.x < 0 && v2.x > 0)

{

exactAngle *= -1;

}

var angle = Math.round(exactAngle);

}