Thursday, June 28, 2018

c# - Platform jumping problems with AABB collisions


See the diagram first:



When my AABB physics engine resolves an intersection, it does so by finding the axis where the penetration is smaller, then "push out" the entity on that axis.


Considering the "jumping moving left" example:




  • If velocityX is bigger than velocityY, AABB pushes the entity out on the Y axis, effectively stopping the jump (result: the player stops in mid-air).

  • If velocityX is smaller than velocitY (not shown in diagram), the program works as intended, because AABB pushes the entity out on the X axis.


How can I solve this problem?


Source code:


public void Update()
{
Position += Velocity;
Velocity += World.Gravity;


List toCheck = World.SpatialHash.GetNearbyItems(this);

for (int i = 0; i < toCheck.Count; i++)
{
SSSPBody body = toCheck[i];
body.Test.Color = Color.White;

if (body != this && body.Static)
{
float left = (body.CornerMin.X - CornerMax.X);

float right = (body.CornerMax.X - CornerMin.X);
float top = (body.CornerMin.Y - CornerMax.Y);
float bottom = (body.CornerMax.Y - CornerMin.Y);

if (SSSPUtils.AABBIsOverlapping(this, body))
{
body.Test.Color = Color.Yellow;

Vector2 overlapVector = SSSPUtils.AABBGetOverlapVector(left, right, top, bottom);


Position += overlapVector;
}

if (SSSPUtils.AABBIsCollidingTop(this, body))
{
if ((Position.X >= body.CornerMin.X && Position.X <= body.CornerMax.X) &&
(Position.Y + Height/2f == body.Position.Y - body.Height/2f))
{
body.Test.Color = Color.Red;
Velocity = new Vector2(Velocity.X, 0);


}
}
}
}
}



public static bool AABBIsOverlapping(SSSPBody mBody1, SSSPBody mBody2)
{

if(mBody1.CornerMax.X <= mBody2.CornerMin.X || mBody1.CornerMin.X >= mBody2.CornerMax.X)
return false;
if (mBody1.CornerMax.Y <= mBody2.CornerMin.Y || mBody1.CornerMin.Y >= mBody2.CornerMax.Y)
return false;

return true;
}
public static bool AABBIsColliding(SSSPBody mBody1, SSSPBody mBody2)
{
if (mBody1.CornerMax.X < mBody2.CornerMin.X || mBody1.CornerMin.X > mBody2.CornerMax.X)

return false;
if (mBody1.CornerMax.Y < mBody2.CornerMin.Y || mBody1.CornerMin.Y > mBody2.CornerMax.Y)
return false;

return true;
}
public static bool AABBIsCollidingTop(SSSPBody mBody1, SSSPBody mBody2)
{
if (mBody1.CornerMax.X < mBody2.CornerMin.X || mBody1.CornerMin.X > mBody2.CornerMax.X)
return false;

if (mBody1.CornerMax.Y < mBody2.CornerMin.Y || mBody1.CornerMin.Y > mBody2.CornerMax.Y)
return false;

if(mBody1.CornerMax.Y == mBody2.CornerMin.Y)
return true;

return false;
}
public static Vector2 AABBGetOverlapVector(float mLeft, float mRight, float mTop, float mBottom)
{

Vector2 result = new Vector2(0, 0);

if ((mLeft > 0 || mRight < 0) || (mTop > 0 || mBottom < 0))
return result;

if (Math.Abs(mLeft) < mRight)
result.X = mLeft;
else
result.X = mRight;


if (Math.Abs(mTop) < mBottom)
result.Y = mTop;
else
result.Y = mBottom;

if (Math.Abs(result.X) < Math.Abs(result.Y))
result.Y = 0;
else
result.X = 0;


return result;
}

Answer




I just looked at the code I have not tried to prove where it is wrong.


I looked at the code and these 2 lines seemed strange:


if ((Position.X >= body.CornerMin.X && Position.X <= body.CornerMax.X) &&
(Position.Y + Height/2f == body.Position.Y - body.Height/2f))

You check for interval and then You check for euquality? I may be wrong, (there might be som rounding going on) but it seems it might cause a trouble.



No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...