2

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

由于我不太擅长解释事情,所以我附上了一张图片,所以希望它能澄清我的意思:(来源:jrahmati.info替代文字

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

对于任何对代码感兴趣的人:

bool Game::tryMove(user, 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);
4

2 回答 2

0

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

解决方案#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;

请注意,在每种情况下,框都不能保证保持精确的相对位置。但是当玩家移动时它们会被推开,并且会阻挡玩家的移动。

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

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

我建议使用物理引擎。

于 2010-07-29T06:26:27.663 回答
0

这是一种推箱子游戏,玩家可以向 8 个方向移动,并且可以同时移动多个盒子吗?是从鸟瞰视图中看到的游戏场,就像在推箱子中一样,还是我们在示例中看到的掉落的盒子(侧视图,就像在俄罗斯方块中一样)?盒子和玩家之间的摩擦力是否无限(换句话说,当玩家触摸的盒子斜向移动时,是否禁止玩家触摸的盒子滑离玩家移动的方向)?两个盒子之间的摩擦力是无穷大吗?

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

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

于 2010-07-31T16:57:36.763 回答