我正在尝试创建一个2D平台游戏(类似马里奥),但在处理碰撞时遇到了一些问题。我使用C++编写此游戏,使用SDL进行输入、图像加载、字体加载等操作。我还使用FreeGLUT库结合SDL使用OpenGL显示图形。
我的碰撞检测方法是AABB (轴对齐边界框),这基本上就是我需要的。我需要一种简单的方法来检测发生碰撞的那一侧,并正确地处理碰撞。所以,如果玩家与平台顶部发生碰撞,则将其重新定位到顶部;如果有侧面碰撞,则将玩家重新定位回对象的侧面;如果底部发生碰撞,则将玩家重新定位到平台下方。
我尝试过很多不同的方法,例如尝试找到渗透深度并向后重新定位玩家。可惜的是,我尝试的所有方法都不能正常工作。玩家的移动变得非常卡顿,而且会在我不想要的时候重新定位玩家。可能部分原因是因为我觉得这是一件非常简单的事情,但我却想复杂了。
如果有人认为他们可以帮助,请查看下面的代码,并在可能的情况下帮我改进。如果可能,我希望避免使用库来处理此问题(因为我想自己学习),或者像SAT(分离轴定理)这样的东西。提前感谢你的帮助!
void world1Level1CollisionDetection()
{
for(int i; i < blocks; i++)
{
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==true)
{
de2dObj ballPrev;
ballPrev.coords[0] = ball.coords[0];
ballPrev.coords[1] = ball.coords[1];
ballPrev.coords[2] = ball.coords[2];
ballPrev.coords[3] = ball.coords[3];
ballPrev.coords[0] -= ball.xspeed;
ballPrev.coords[1] -= ball.yspeed;
ballPrev.coords[2] -= ball.xspeed;
ballPrev.coords[3] -= ball.yspeed;
int up = 0;
int left = 0;
int right = 0;
int down = 0;
if (ballPrev.coords[0] < block[i].coords[0] && ballPrev.coords[2] < block[i].coords[0] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || ball.coords[3] < block[i].coords[3])))
{
left = 1;
}
if (ballPrev.coords[0] > block[i].coords[2] && ballPrev.coords[2] > block[i].coords[2] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || (ball.coords[3] < block[i].coords[3]))))
{
right = 1;
}
if(ballPrev.coords[1] < block[i].coords[1] && block[i].coords[1] < ballPrev.coords[3] && ballPrev.coords[3] < block[i].coords[3])
{
up = 1;
}
if(block[i].coords[1] < ballPrev.coords[1] && ballPrev.coords[1] < block[i].coords[3] && block[i].coords[3] < ballPrev.coords[3])
{
down = 1;
}
cout << left << ", " << right << ", " << up << ", " << down << ", " << endl;
if (left == 1)
{
ball.coords[0] = block[i].coords[0] - 18.0f;
ball.coords[2] = block[i].coords[0] - 2.0f;
}
else if (right == 1)
{
ball.coords[0] = block[i].coords[2] + 2.0f;
ball.coords[2] = block[i].coords[2] + 18.0f;
}
else if (down == 1)
{
ball.coords[1] = block[i].coords[3] + 4.0f;
ball.coords[3] = block[i].coords[3] + 20.0f;
}
else if (up == 1)
{
ball.yspeed = 0.0f;
ball.gravity = 0.0f;
ball.coords[1] = block[i].coords[1] - 17.0f;
ball.coords[3] = block[i].coords[1] - 1.0f;
}
}
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==false)
{
ball.gravity = -0.5f;
}
}
}
为了解释这段代码的含义:
变量blocks基本上是存储块或平台数量的整数。我使用for循环检查所有块,循环当前正在进行的数字由整数i表示。 坐标系可能看起来有点奇怪,因此值得解释。 coords [0]表示对象的x位置(左侧)(在x轴上开始的位置)。 coords [1]表示对象的y位置(顶部)(在y轴上开始的位置)。 coords [2]表示对象的宽度加上coords [0](右侧)。 coords [3]表示对象的高度加上coords [1](底部)。 de2dCheckCollision执行AABB碰撞检测。 向上为负y,向下为正y,这在大多数游戏中都是如此。
希望我提供的信息足够帮助你成功。如果我漏掉了什么可能至关重要的内容,请让我知道,我会提供必要的信息。最后,对于任何可以帮助的人,提供代码将非常有帮助并且非常感激。
感谢您的帮助!
编辑2:我已经使用新算法更新了我的代码,该算法检查球在碰撞之前所在的位置。角落案例现在在单个平台上可以正确工作,当我有一堵墙的物体时,我可以正确地沿着它滑动。唯一剩下的问题是当我在地面上时会出现小的抖动效果,球似乎不断上下移动,就像被重力拉扯然后球重新掉进物体里。
编辑:这里是一个URL,尝试显示我遇到的问题类型的图像: http://img8.imageshack.us/img8/4603/collisionproblem.png 如果图片中的解释不太清楚,请问我,我会尽力澄清更多。