2

ボックスを使用して敵をトラップできるゲーム(c ++でirrlichtエンジンを使用)を作成しようとしています。しかし、ユーザーと1つ以上のボックスとの衝突が検出されたときに、何を移動する必要があるかを検出する方法がわかりません。もう1つは、動きをブロックできるレンガと呼ばれるオブジェクトもいくつかあるということです。

私は物事を説明するのがあまり得意ではないので、画像を含めました。それで、私が何を意味するのかが明確になることを願っています:(出典:jrahmati.info代替テキスト

私は自分のコードでいくつかのことを試しましたが、成功しませんでした。ですから、誰かがこの問題に答える努力をしてくれることを本当に望んでいます。前もって感謝します。ちなみに、私は必ずしもc ++で答えを必要としません、javaまたは.Net言語も大丈夫です。

コードに興味のある人のために:

プレイヤーからすべてを遠ざけようとするboolGame :: 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;交換しないでください.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方向に移動でき、一度に複数のボックスを移動できる倉庫番ゲームの一種ですか?倉庫番のように鳥の目で見たプレイフィールドですか、それとも例のように落下箱(テトリスのように側面図)ですか?ボックスとプレーヤーの間の摩擦は無限ですか(言い換えると、プレーヤーが触れているボックスが、斜めに移動するときに、プレーヤーが移動している方向からスライドすることは禁止されています)?2つのボックス間の摩擦は無限ですか?

私はあなたのコードに集中することができませんでした、しかしこれが私の2centsアルゴリズムです。このアルゴリズムは、任意の2つのオブジェクト間の摩擦が無限であることを意味します。

プレイヤーが移動するとき、影響を受ける可能性のある可動オブジェクトを確立する必要があります。プレイヤーが移動方向に触れているものを検索スタックに入れ、検索スタック内の各アイテムについて、さらにオブジェクトを入れて検索プロセスを繰り返します。最後に、可動オブジェクトが不足します。移動できないオブジェクトに遭遇した場合、プレーヤーも移動できず(摩擦のルールが無限であるため)、何も移動しません。移動できないオブジェクトが含まれていない場合は、スタック内のすべてのオブジェクトを1グリッド単位で移動します。

于 2010-07-31T16:57:36.763 に答える