
I'm having a slight issue detecting the ground angle of my player. I am using the popular square/circle/motor joint character and am using an OnCollision event to check the angle. to find the contact angle, I am using the contact.Manifold.LocalNormal.
This is basically jsut an update of Elsch's method I found
here. At first, it really looked to be working perfectly, but when I changed the angle of the slope, it broke.
Here is my pertinent character code:
private bool OnWheelCollision(Fixture f1, Fixture f2, Contact contact)
{
float angle = Vector2.Dot(contact.Manifold.LocalNormal, Vector2.UnitY);
if (Math.Abs(angle) >= .1)
{
_activity = Activity.None;
_groundCache.Add(f2);
}
if (Math.Abs(angle) < .1f)
{
_onWall = true;
_wallCache.Add(f2);
}
return true;
}
Here is a picture of the two scenarios.
PICTURE
The scenarion on the left produces a contact normal of (0, 1) and angle of 1.0, while the scenario on the right produces a contact normal of (1, 0) and angle of 0.0. It seems like the normal should be a unit vector in a wide variety of directions, but I can't seem to get it to work.
Any thoughts? Am I implementing this wrong? Is there a better way?
Thanks in advance for the reply!


Developer
Jan 25, 2011 at 2:34 AM

My method was copy pasted from a tilebased engine using only square tiles. Vector2.Dot calculates the angle between the contact normal and the yaxis and i just check if it is near zero or one e.g. whether the angle is 0° or 90°. This only works
for horizontal floors and vertical walls.
You need to check if the angle is within a range from 45° to 45° for example. First of all you have to decide at which angle you want to classify a slope as wall or ground.



Well, from what I've been reading, it is better to use dot product to get an approximation of angle because it saves processor time over hefty trig functions. In my code I am using .1 ("angle") as the cutoff because I want to be able
to jump from all slope angles except for the steepest ones. The problem seems to be with the contact.Manifold.LocalNormal. It doesn't give me an angle that I would expect. It is giving me either Vector2.UnitY or Vector2.UnitX as the LocalNormal. On
a 45 degree slope I would expect a normal similar to Vector2.Normalize(1, 1), so that when I calculate the dot product against the Vector2.UnitY, I would get an "angle" close to .5.
I'm wondering how to calculate that angle correctly.
Thanks for your help!



May have figured it out... I used contact.GetWorldManifold instead and it seems to be outputing more reasonable results. Can anyone verify that this is the proper method? Thanks!


Developer
Jan 25, 2011 at 9:18 AM

You're right. I just had a look at my own code and i use contact.GetWorldManifold myself ;)

