0

I have a Player class that contains a physics body represented by a sphere, and I want to be able to tell if the player is on the ground, on a wall, or in the air. So far I have a bool IsOnGround that I set with these event handlers for the physics body:

void PhysicsBody_OnSeparation(Fixture fixtureA, Fixture fixtureB)
{
    IsOnGround = false;
    PhysicsBody_OnCollision(fixtureA, fixtureB, null);
}

bool PhysicsBody_OnCollision(Fixture fixtureA, Fixture fixtureB,
    FarseerPhysics.Dynamics.Contacts.Contact contact)
{
    if (fixtureB.UserData is JumpableFixtureData &&
        fixtureB.Body.Position.Y > fixtureA.Body.Position.Y)
    {
        IsOnGround = true;
    }
    else
    {
        IsOnGround = false;
    }

    return true;
}

I have my level so that each level object sets the user data of their physics body to be a JumpableFixtureData (just an empty class), and though most of the objects are rectangular, there are a few shapes with cave-like openings, such that the player is 'inside' the shape.

My problem is that sometimes the IsOnGround bool is set to true when the object is still in the air, and sometimes it remains false after touching the ground. This setup clearly isn't working. What should I do instead? I found this tutorial in the Box2D tutorials, but I haven't used C++ in forever and I can't find any way to create a separate instance of a fixture so I can make it a 'foot'.

CubeJockey
  • 2,209
  • 8
  • 24
  • 31
einsteinsci
  • 1,137
  • 1
  • 8
  • 22
  • 1
    The problem probably has something to do with the fact that a body can collide with multiple walls at the same time. For example, if your sphere touches the floor, then touches a wall OnCollision will be called twice. When it moves away from the wall OnSeparation will be called, but the sphere will still be touching the floor. In other words, a simple true / false flag is not enough to determine contact. Sorry, I don't actually have a solution off the top of my head but perhaps this will help you. – craftworkgames May 12 '14 at 23:31
  • 1
    I think @craftworkgames might be on to something. How about an int that increments every time it gets a 'true' and decrements when it gets 'false'? That way you can quickly determine if what craftworkgames explained, is actually the case. – Falgantil May 13 '14 at 06:50
  • Thanks! I still need to figure out how to determine what's colliding on the bottom and what's colliding on the side or top. Do you have any idea how to implement the "foot" idea from the Box2D tutorial? – einsteinsci May 13 '14 at 14:33
  • I have another problem now: I have a one-way platform, and whenever I go upward through the platform, the collision count is increasing continually (1 per frame). This is a problem since it only decreases by one when it exits the collision. – einsteinsci May 13 '14 at 18:51
  • How do you determine if the platform you've hit is one-way? Maybe you can simply not increment the count if the character is travelling upward through a one-way platform. – craftworkgames May 14 '14 at 06:20
  • That wouldn't work. If the character jumps and just barely misses the platform (which is a rectangle, not an edge, since I couldn't get edges to work), as it is falling down through it the jump increases. I figured it out though. I made it so it only increments the count if the collision is enabled (if the player is going up and above it). – einsteinsci May 14 '14 at 15:23

1 Answers1

1
  • I think there is a property somewhere called "slop" which might help. I am not sure if it is at system, body, or fixture level. Slop is a threshold to allow for overlap and to smooth the collision of bodies against each other.
  • Or you could have second smaller collision volume (sphere or circle) within the larger one that sticks out below it. It could be a sensor and so the larger volume will deal with collision resolutions and then this sensor can modify your 'on_ground' boolean.
quin
  • 276
  • 1
  • 9