3
\$\begingroup\$

I'm writing a simple 2d physics system using a circle colliding with edges. When the user presses a key the circle's velocity is incremented by some amount in the direction they pressed. There is currently no friction, although that shouldn't be relevant (for example if a character is jumping there's often no friction until landing but walls should still work correctly). There is also a limit to the magnitude of the velocity vector.

When the circle collides with an edge its velocity is projected along the surface of the edge. This allows the circle to slide along the walls, however it causes the circle to accelerate along the surface instead of move at the expected constant speed. Here's a diagram to demonstrate this:

enter image description here

On the left is the first iteration where the red vector represents the velocity and the green vector represents the amount added to the velocity from user input. This combined vector is projected on the wall to produce the blue vector.

On the right is the second iteration where the same green vector as before is added to the current velocity (the same projected velocity from the first iteration), and this resultant vector is projected along the surface to produce the new purple velocity vector.

As you can see the purple vector is larger than the blue one meaning that the circle is moving faster on the second iteration than the first and therefore is accelerating along the wall. The character will continue to accelerate on consecutive iterations along the wall until reaching the maximum speed.

I understand why this happens, however I'm struggling to figure out how to change the logic so that it'll behave in the way games typically handle this. Typically characters accelerate more slowly and have a smaller apparent speed cap the more perpendicular they are moving relative to the wall's surface.

\$\endgroup\$
  • 1
    \$\begingroup\$ I don't understand, following your diagrams it already should be moving more slowly and accelerate more slowly while moving along the wall, simply due to the fact the vectors get smaller when projected on the wall. \$\endgroup\$ – Christer Dec 3 '15 at 15:56
  • 1
    \$\begingroup\$ Not sure if I'm misunderstanding something, but shouldn't this behaviour be expected without friction? If you were to remove the wall and simply press forward, then you'd also just be adding green vectors to blue vectors, creating larger, un-damped blue vectors, that you in turn add more green vectors to, no? \$\endgroup\$ – Yousef Amar Dec 3 '15 at 16:20
1
\$\begingroup\$

I believe this occurs in your example because the user input is used to define the acceleration of the object. (As in your example you show that the velocity is increased based on user input).

Limiting the Maximum Velocity

What you could do is have a maximum velocity which scales depending on the angle with which the player attempts to move 'into' the wall,

vel_max = vel_max0 * abs(dot(player_input, wall_vector))

where player_input is the vector for the acceleration added by the player,wall vector is the vector parallel to the wall and dot is the dot product of the two vectors.

This would mean that a player who tries to go directly into the wall will have a maximum speed of zero and only players who move along the wall will reach the maximum speed vel_max0. Note you need to normalise the player_input before inserting into the dot product.

Limiting the acceleration

In similar way you could limit the acceleration of the player by multiplying by dot(player_input, wall_vector) achieving the result you desire.

Edit: As the comments have mentioned this behaviour is not entirely physical but it will 'appear' to behaviour better as per your requests.

\$\endgroup\$
  • \$\begingroup\$ Limiting the velocity as you suggested works if I don't change directions while hitting the wall. If for example I'm moving parallel to the wall and I suddenly change directions to move perpendicular to the wall, the character will stop immediately because the dot product of the wall and input normal becomes zero making the max velocity zero. \$\endgroup\$ – user3124047 Dec 4 '15 at 20:13
  • \$\begingroup\$ Hmm, I see what you mean. I guess you could impose a deceleration in the opposite direction of the velocity if the velocity is above the minimum (instead of just limiting it). This will have an effect similar to static friction when pressing against a wall (but not exactly the same). \$\endgroup\$ – Malrig Dec 6 '15 at 18:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.