I'm writing my very first 2D game engine in C++ and SDL2. I wrote a very simplistic RigidBody
class that computes the resultant force, applies forces and simulates gravity. I also wrote a BoxCollider
class and a QuadTree
class which as any game dev would know manages collisions. Every thing seems to be working fine, however I'm facing a pit stop I can't wrap my head around. How do I stop a GameObject
when it collides with a static wall or ground. I tried setting the velocity
to zero but that literally freezes the object and I can't move it using my controls. Also setting the gravity
to zero doesn't stop the object since it still has a non zero velocity
and it sort of digs it's way through the ground. How can I implement this and if there are any decent tutorials regarding my question please do share them. Thanks!
How to stop a moving object when colliding with a static wall or ground
None
fudgeracoon said:
I tried setting the velocity to zero but
Zero out velocity.x for walls and velocity.y for floors.
Also, gravity isn't something to be changing willy nilly.
Try Box2D if you need decent 2D physics interactions. It gets pretty involved once you get beyond simple horizontal/vertical/circle geo interactions.
🙂🙂🙂🙂🙂<←The tone posse, ready for action.
@fleabay Zeroing out the velocity was initially what I did as I specified in my post, which came with an issue than once collision happened it caused the object to freeze in place. Also, I'm writing my own physics engine I have no interest in using physics libraries.
None
fudgeracoon said:
Zeroing out the velocity was initially what I did
I didn't say zero out velocity.
fudgeracoon said:
I'm writing my own physics engine I have no interest in using physics libraries.
Good luck.
🙂🙂🙂🙂🙂<←The tone posse, ready for action.
fudgeracoon said:
I'm writing my very first 2D game engine in C++ and SDL2. I wrote a very simplistic
RigidBody
class that computes the resultant force, applies forces and simulates gravity. I also wrote aBoxCollider
class and aQuadTree
class which as any game dev would know manages collisions. Every thing seems to be working fine, however I'm facing a pit stop I can't wrap my head around. How do I stop aGameObject
when it collides with a static wall or ground. I tried setting thevelocity
to zero but that literally freezes the object and I can't move it using my controls. Also setting thegravity
to zero doesn't stop the object since it still has a non zerovelocity
and it sort of digs it's way through the ground. How can I implement this and if there are any decent tutorials regarding my question please do share them. Thanks!
Check out the standard “Newtonian impulse-based kinematic energy preserving collision response model”: e.g. Chris Hecker has good classic articles about it: http://www.chrishecker.com/Rigid_Body_Dynamics . This wikipedia page has a treatise on the same computational model: https://en.wikipedia.org/wiki/Collision_response#Impulse-based_contact_model
To answer your specific questions:
fudgeracoon said:
How do I stop a
GameObject
when it collides with a static wall or ground. I tried setting thevelocity
to zero but that literally freezes the object and I can't move it using my controls.
In your code, if you set velocity to zero on collision, and it causes you being unable to later apply velocity to move the object, then it possibly means that your detection of what constitutes a collision was not taking relative velocities of the objects into account. A robust way is to mark a collision between two objects A and B if and only if 1) the two objects are overlapping, but also 2) their relative velocities would be moving them to overlap even further on the next frame.
With this model, two objects that are overlapping, but have velocities that are moving the objects away from each other, would not considered to be colliding. This has the benefit that you can actually apply a velocity to an object towards the opposite direction of an object it is in overlap with, without having the collision response system null out the velocity, which is what your description sounds like is happening for you.
Or if your collision response is to flip/mirror the velocity (think of arkanoid/breakout “ball hits a brick” style of mirroring velocities), then after the velocity x/y coordinate has been flipped, the ball and brick, even if they are overlapping, should no longer be considered to be colliding, since their relative velocities are taking the objects apart, and not closer together.
In the Impulse-based collision response model, collisions are modeled either as fully elastic (superballs, coefficient of restitution = 1.0), or fully energy-absorbing (coefficient of restitution=0.0). Under that model, the way to stop an object when it hits a wall is to set the coefficient of restitution of the wall, or the player, to 0.0 when computing the j
collision response factor. That way the collision will fully absorb the collision energy when the player hits it - or if you want the player to bounce off the wall a little, you could use a coefficient 0.3
for example.
fudgeracoon said:
Also setting the
gravity
to zero doesn't stop the object since it still has a non zerovelocity
and it sort of digs it's way through the ground. How can I implement this and if there are any decent tutorials regarding my question please do share them. Thanks!
Stable resting contacts are a pain when implementing any physics systems. The absolute “proper” way to implement stacking objects under gravity is to separate impulse gathering and collision response solving to two different phases, and then solve the collision responses as a group of objects. That will produce stable stacking contacts, but the implementation gets really complex really fast, so for simpler code, heuristics and hacks that are “good enough” to work for your particular game physics simulations are in order.
A common hack is to implement a nonphysical forced separation of overlapping objects when their velocities are detected to be at rest. That is, when you have two objects colliding, but their relative velocities are really small, what you can do is instead of resolving the collision, you just move the objects back along the collision normal so that they do not overlap, and set their relative velocities along the normal to zero. This can help objects from “burrowing” through ground and other walls they should instead stack on top of. However it will result in really wild artifacts, or dampened collision responses in other cases.
Definitely recommend taking a look at the above Newtonian impulse-based collision response model, it is the gold standard for simple 2D physics responses and quite manageable to implement after a little bit of familiarizing with the topic, and it will give you nice separation of collisions causing rotation or linear velocity on the collided objects. And if you don't care about rotational velocity but objects should always stay upright, you can use the same formula, but greatly simplify by treating each object to have a rotational mass of inertia = infinity
, which will null out parts of the formula.