2
\$\begingroup\$

I'm having some issues with jump detection due to begincontact. I have a player entity made of 2 bodies, and it looks something like this:

player model

Note how the circle below (a body connected via a revolute joint) is not quite as wide as the rectangle. This means that when the player is up against a wall, there is no contact between the circle and the wall.

However, if the player collides with a wall at high velocity, begincontact registers a contact between the circle and the wall. Is there any way around this?

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

There are a number of ways you can get around this depending on your situation.

If all the walls are vertical and it is never the intention for the circle to hit the wall then you can set up contact filtering using the catergoryBits and maskBits on the FixtureDef.filter to filter out any collisions between the circle and walls.

If the circle should be able to sometimes hit the wall except for when it hits it side-on then you can manually filter the contact in beginContact by measuring the delta between the center of the circle and the contact point. If this delta is small, then ignore the contact (which you can do by calling setEnabled(false)).

And example of the latter may look something like this (this is in Java, I don't know what language you're using but it should be trivial to port);

world.setContactListener(new ContactListener() { private Body tryGet(Body body, String bodyUserData) { return body.getUserData() != null && body.getUserData().equals(bodyUserData) ? body : null; } private Body tryGet(Contact contact, String bodyUserData) { Body body = tryGet(contact.getFixtureA().getBody(), bodyUserData); return body != null ? body : tryGet(contact.getFixtureB().getBody(), bodyUserData); } @Override public void beginContact(Contact contact) { torsoCollided |= tryGet(contact, "torso") != null; Body feetBody = tryGet(contact, "feet"); if (feetBody != null) { WorldManifold manifold = contact.getWorldManifold(); // Should really check numPoints here to see how many contact points float contactY = manifold.getPoints()[0].y; float bodyY = feetBody.getWorldCenter().y; // If difference in the vertical is small then the circle (feet) hit the wall // side on, which is impossible if the torso is wider and the torso can't rotate boolean isValidCircleContact = Math.abs(contactY - bodyY) > 0.001f; feetCollided |= isValidCircleContact; contact.setEnabled(isValidCircleContact); } } @Override public void endContact(Contact contact) { contact.setEnabled(true); } @Override public void preSolve(Contact contact, Manifold oldManifold) { } @Override public void postSolve(Contact contact, ContactImpulse impulse) { } }); 

The above assumes there being user data on the box set to "torso" and to "feet" on the circle, torsoCollided and bodyCollided are fields cleared to false before calling world.step on every iteration which you may or may not have any use for.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for the help! The first solution would work if I didn't have to account for circular walls/objects that rotate. There's also the issue of colliding with the same fixture in multiple spots at different angles (e.g. a valley in a concave polygon) that prevents me from just keeping track of the manifold's normal vector and a set of colliding fixtures. Should I just avoid using nonconvex polygons altogether? \$\endgroup\$ Commented Jul 9, 2017 at 20:29
  • \$\begingroup\$ Using convex only geometry usually make things simpler but if it is required for the game-play you should keep non-convex geometry. If you have the CPU cycles to spare you could lower the timestep to combat the issue you're seeing, but it won't help with the many contact points. \$\endgroup\$ Commented Jul 12, 2017 at 22:30
0
\$\begingroup\$

When you get over a certain speed, you can try to increase red rectangle width proportionaly(?) to object speed. May be also usefull to define a max object speed.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.