প্রথমে চিত্রটি দেখুন:
আমার এএবিবি পদার্থবিজ্ঞানের ইঞ্জিন যখন কোনও ছেদটি সমাধান করে, অনুপ্রবেশ ছোট যেখানে অক্ষটি সন্ধান করে এটি করা হয়, তারপরে সেই অক্ষের সত্তাকে "ধাক্কা দিয়ে" ফেলে।
"জাম্পিং মুভিং বাম" উদাহরণ বিবেচনা করে:
- যদি বেগ Y এর চেয়ে বড় হয় তবে এএবিবি কার্যকরভাবে লাফটি থামিয়ে ওয়াই অক্ষের উপরে সত্তাকে ঠেলে দেয় (ফলস্বরূপ: প্লেয়ার মধ্য-বাতাসে থামে)।
- যদি বেগটি এক্স বেগের চেয়ে ছোট হয় (ডায়াগ্রামে দেখানো হয়নি), প্রোগ্রামটি উদ্দেশ্য হিসাবে কাজ করে, কারণ এএবিবি সত্ত্বাকে এক্স অক্ষের বাইরে ঠেলে দেয়।
কিভাবে আমি এই সমস্যার সমাধান করতে পারে?
সোর্স কোড:
public void Update()
{
Position += Velocity;
Velocity += World.Gravity;
List<SSSPBody> 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;
}