I have a problem with top-down racing game I'm working on. I need to implement AABB collision with other cars and objects. But when going fast enough, the car can go through thin objects when hitting top and left sides or bottom right corner if the surface is limited with colliders on each side. Here's da codez of collision response:
private void OnCollision(BoundsCollider sender, BoundsCollider collider)
{
// TODO: question stackexchange gamedev what's wrong with left and top
// maybe i should compare the center point...
if (sender.Rect.Left < collider.Rect.Right) // right
{
sender.GameObject.Transform.Position += new Vector2(1, 0);
if (GameObject.IsAI)
{
if (collider.GameObject != null)
{
Velocity = new Vector2(-collider.GameObject.Rigidbody.Velocity.X, Velocity.Y);
}
else
{
Velocity = new Vector2(-Velocity.X, Velocity.Y);
}
AngularVelocity = 0.01f;
}
else
{
Velocity = new Vector2(-Velocity.X, Velocity.Y);
}
}
else if (sender.Rect.Right >= collider.Rect.Left) // left (working wrong)
{
sender.GameObject.Transform.Position += new Vector2(-1, 0);
if (GameObject.IsAI)
{
if (collider.GameObject != null)
{
Velocity = new Vector2(-collider.GameObject.Rigidbody.Velocity.X, Velocity.Y);
}
else
{
Velocity = new Vector2(-Velocity.X, Velocity.Y);
}
AngularVelocity = -0.01f;
}
else
{
Velocity = new Vector2(-Velocity.X, Velocity.Y);
}
}
if (sender.Rect.Top < collider.Rect.Bottom) // bottom
{
sender.GameObject.Transform.Position += new Vector2(0, 1);
if (GameObject.IsAI)
{
if (collider.GameObject != null)
{
Velocity = new Vector2(Velocity.X, -collider.GameObject.Rigidbody.Velocity.Y);
}
else
{
Velocity = new Vector2(Velocity.X, -Velocity.Y);
}
}
else
{
Velocity = new Vector2(Velocity.X, -Velocity.Y);
}
}
else if (sender.Rect.Bottom >= collider.Rect.Top) // top (working wrong)
{
sender.GameObject.Transform.Position += new Vector2(0, -1);
if (GameObject.IsAI)
{
if (collider.GameObject != null)
{
Velocity = new Vector2(Velocity.X, -collider.GameObject.Rigidbody.Velocity.Y);
}
else
{
Velocity = new Vector2(Velocity.X, -Velocity.Y);
}
}
else
{
Velocity = new Vector2(Velocity.X, -Velocity.Y);
}
}
}
How do I do it right? If you'll need the whole project, I'll share one with you.
BTW I also use MonoGame.Extended for RectangleF and other stuff
UPD: I've partually fixed it but now you can get out from the corners. How do I fix this? Don't suggest intersection, it doesn't work right (when colliding the wall from left/right, it sends you up and down)
private void OnCollision(BoundsCollider sender, BoundsCollider collider)
{
if (sender.Rect.Center.X > collider.Rect.Center.X) // right
{
sender.GameObject.Transform.Position += new Vector2(1, 0);
if (GameObject.IsAI)
{
if (collider.GameObject != null)
{
Velocity = new Vector2(-collider.GameObject.Rigidbody.Velocity.X, Velocity.Y);
}
else
{
Velocity = new Vector2(-Velocity.X, Velocity.Y);
}
AngularVelocity = 0.01f;
}
else
{
Velocity = new Vector2(-Velocity.X, Velocity.Y);
}
}
else if (sender.Rect.Center.X < collider.Rect.Center.X) // left
{
sender.GameObject.Transform.Position += new Vector2(-1, 0);
if (GameObject.IsAI)
{
if (collider.GameObject != null)
{
Velocity = new Vector2(-collider.GameObject.Rigidbody.Velocity.X, Velocity.Y);
}
else
{
Velocity = new Vector2(-Velocity.X, Velocity.Y);
}
AngularVelocity = -0.01f;
}
else
{
Velocity = new Vector2(-Velocity.X, Velocity.Y);
}
}
if (sender.Rect.Center.Y > collider.Rect.Center.Y) // bottom
{
sender.GameObject.Transform.Position += new Vector2(0, 1);
if (GameObject.IsAI)
{
if (collider.GameObject != null)
{
Velocity = new Vector2(Velocity.X, -collider.GameObject.Rigidbody.Velocity.Y);
}
else
{
Velocity = new Vector2(Velocity.X, -Velocity.Y);
}
}
else
{
Velocity = new Vector2(Velocity.X, -Velocity.Y);
}
}
else if (sender.Rect.Center.Y < collider.Rect.Center.Y) // top
{
sender.GameObject.Transform.Position += new Vector2(0, -1);
if (GameObject.IsAI)
{
if (collider.GameObject != null)
{
Velocity = new Vector2(Velocity.X, -collider.GameObject.Rigidbody.Velocity.Y);
}
else
{
Velocity = new Vector2(Velocity.X, -Velocity.Y);
}
}
else
{
Velocity = new Vector2(Velocity.X, -Velocity.Y);
}
}
}