如何移动多个矩形作为碰撞响应?

时间:2010-07-28 15:00:22

标签: c++ response collision irrlicht

我正在尝试制作游戏(使用带有c ++的irrlicht引擎),你可以使用盒子捕获你的敌人。但是,当我检测到用户与一个或多个盒子之间的碰撞时,我只是不知道如何检测应该移动的内容。另一件事是,还会有一些叫砖的物体能够阻挡运动。

由于我不太善于解释事物,所以我添加了一张图片,因此希望澄清我的意思:alt text http://jrahmati.info/images/collision.gif

我用我的代码尝试了几件事但没有成功。所以我真的希望有人会努力回答这个问题。提前致谢。 顺便说一句,我不需要c ++,java或.Net语言中的答案也可以。

对于对代码感兴趣的人:

bool Game :: tryMove(用户,dir)的内容,试图远离播放器

bool thereIsCollision = false;
bool undoMovements = false;
bool userCollision = false;
do{
    thereIsCollision = false;
    for (int i = 0; i < totalObjects; i++) {
        //First check if object hits the user
        if(gameObjects[i].hits(user)){
            if (gameObjects[i]->isMovable()) {
                MovableObject* mObject = (MovableObject*) gameObjects[i];
                mObject->move(dir);
                mObject->setPushVector(dir);
                userCollision = true;
                //thereIsCollision = true;
            }
            else{
                undoMovements = true;
                thereIsCollision = false; //To break do-while loop
                userCollision = true;
                break;
            }
        }
    }
    if(undoMovements)
        break;
    for (int i = 0; i < totalObjects; i++) {
        //Then check if objects hit each other
        for (int i2 = 0; i2 < totalObjects; i2++) {
            if(i == i2)
                continue;
            if (gameObjects[i2].hits(gameObjects[i])){
               //thereIsCollision = true;
               if(gameObjects[i]->isMovable() && gameObjects[i2]->isMovable()){
                   MovableObject* mObject = (MovableObject*) gameObjects[i];
                   MovableObject* mObject2 = (MovableObject*) gameObjects[i2];
                   if(mObject->getPushVector().X > 0 
                           || mObject->getPushVector().Y > 0 
                           || mObject->getPushVector().Z > 0){
                       mObject2->move(mObject->getPushVector());
                       mObject2->setPushVector(mObject->getPushVector());
                       mObject->setPushVector(irr::core::vector3df(0, 0, 0));
                   }
                   else if(mObject2->getPushVector().X > 0 
                           || mObject2->getPushVector().Y > 0 
                           || mObject2->getPushVector().Z > 0){
                       mObject->move(mObject2->getPushVector());
                       mObject->setPushVector(mObject2->getPushVector());
                       mObject2->setPushVector(irr::core::vector3df(0, 0, 0));
                   }
               }
               else{
                   undoMovements = true;
                   thereIsCollision = false; //To break do-while loop
                   break;
               }
           }
        }
    }
}while(thereIsCollision);

for (int i = 0; i < totalObjects; i++) {
    if (gameObjects[i]->isMovable()) {
        MovableObject* mObject = (MovableObject*) gameObjects[i];
        if(undoMovements){
            // Resets position of gameObject to its previous one
            mObject->undoMovement();
        }
        else{
            // confirms movement(i.e. prevPosition=curPosition)
            mObject->confirmMovement();
        }
    }
}
return !(userCollision);

2 个答案:

答案 0 :(得分:0)

据我了解,你使用的是2d或3d空间,而你的对象并没有放在某种网格上(即坐标是浮点数)。在这种情况下,有两种解决方案:

解决方案#1:

使用物理引擎,例如PhysX。

解决方案#2:

  1. 重复10或20次或直到不再发生碰撞:
    1.1查找所有重叠(碰撞)对象。这包括玩家和盒子。箱子也与其他箱子相撞。
    1.2对于每个对象创建“移动”向量(响应碰撞应移动多少对象)m并将其初始化为全零(x:0,y:0,z:0)。
    1.3对于每对碰撞(重叠)对象A和B,计算将它们彼此推开的向量(比如“pushAwayVector”)。将该向量添加到A.move和B.move。请记住,物体彼此被推开,所以你应该注意标志和大小。即A.move += pushAway*0.5f; B.move += -0.5f*pushAway;。不要替换 .move与pushAway向量,但添加pushAway移动。否则结果将不太可靠。您还可以考虑物体的质量,如下所示:A.move += (B.mass/(A.mass + B.mass))*pushAway; B.move += -(A.mass/(A.mass+B.mass))*pushAway;,在这种情况下,较轻的物体更难以推动较重的物体;
    1.4处理完所有重叠对象后,对所有对象执行obj.position += obj.move;
  2. 请注意,在每种情况下,都不能保证盒子保持精确的相对位置。但是当玩家移动时,它们会被推开,并且会阻挡玩家的移动。

    请注意,使用物理引擎会产生更接近您想要的结果。

    另一种解决方案是,一旦玩家触摸一个盒子,找到彼此碰撞的一组盒子和一个玩家,然后移除不受当前玩家移动影响的盒子。但是,我不喜欢这种解决方案 - 它很杂乱,缺乏优雅,虽然它会保持相对的对象位置(这也看起来不切实际)。

    我建议使用物理引擎。

答案 1 :(得分:0)

这是一种推箱子游戏,玩家可以在8个方向移动,并且能够一次移动几个盒子吗?从Sokoban的鸟瞰视角观看比赛场地,还是他们在示例中看到的落下的箱子(侧视图,如俄罗斯方块)?盒子和玩家之间的摩擦力是无限的(换句话说,当玩家正在移动的方向,当它对角移动时,是否禁止玩家正在触摸的盒子滑动)?两个盒子之间的摩擦是无限的吗?

我无法专注于你的代码,但这是我的2cents算法。该算法意味着任何两个对象之间的摩擦是无限的。

当玩家移动时,您需要确定哪些可移动物体可能受到影响。将播放器在移动方向上触摸的那些放入某些搜索堆栈,然后对于搜索堆栈中的每个项目,通过将更多对象放入其中来重复搜索过程。最后,你将耗尽可移动的物体。如果你在任何时候偶然发现一个不可移动的物体,那么玩家也不能移动(因为无限的摩擦规则),所以没有任何动作。如果没有涉及不可移动的对象,则将堆栈中的所有对象移动一个网格单元。