2017-04-03 8 views
0

私はちょうど私の基本的なボクセルの物理学にちょっと固執しています。それは非常に、非常に途切れ途切れだと私は数学がどこか壊れているかなり確信している、しかし、あなたが言っているか見てみましょう:ボクセルの世界での衝突の検出

// SOMEWHERE AT CLASS LEVEL (so not being reinstantiated every frame, but persisted instead!) 
glm::vec3 oldPos; 

// ACTUAL IMPL 
glm::vec3 distanceToGravityCenter = 
     this->entity->getPosition() - 
     ((this->entity->getPosition() - gravityCenter) * 0.005d); // TODO multiply by time 

if (!entity->grounded) { 
    glm::vec3 entityPosition = entity->getPosition(); 

    if (getBlock(floorf(entityPosition.x), floorf(entityPosition.y), floorf(entityPosition.z))) { 
     glm::vec3 dir = entityPosition - oldPos; // Actually no need to normalize as we check for lesser, bigger or equal to 0 

     std::cout << "falling dir: " << glm::to_string(dir) << std::endl; 

     // Calculate offset (where to put after hit) 
     int x = dir.x; 
     int y = dir.y; 
     int z = dir.z; 

     if (dir.x >= 0) { 
      x = -1; 
     } else if (dir.x < 0) { 
      x = 1; 
     } 

     if (dir.y >= 0) { 
      y = -1; 
     } else if (dir.y < 0) { 
      y = 1; 
     } 

     if (dir.z >= 0) { 
      z = -1; 
     } else if (dir.z < 0) { 
      z = 1; 
     } 

     glm::vec3 newPos = oldPos + glm::vec3(x, y, z); 
     this->entity->setPosition(newPos); 
     entity->grounded = true; // If some update happens, grounded needs to be changed 
    } else { 
     oldPos = entity->getPosition(); 
     this->entity->setPosition(distanceToGravityCenter); 
    } 
} 

基本的な考え方は、表面を打つことになる方向entitytから決定することであったし、次にそれを配置します1つの「ユニット」をその方向に戻します。しかし、明らかに、エンティティを常に元の位置に戻し、効果的にスポーンポイントに保持するので、私は間違ったことをしています。

また、これはおそらくもっと簡単だろうと私はそれを考えすぎています。

+1

'if(dir.x> = 0){x = -1; } if(dir.x <0){x = 1; } ' - それは私にはかなり役に立たないようです...' x'は常に '1'に終わるでしょう。あなたは 'else if'を意味しましたか?これは記述した振る舞いを引き起こすので、私はそれを答えにします。 – CompuChip

+0

@CompuChipもちろん、ある馬鹿馬鹿しいエラーが消えました。そこには他に何が潜んでいますか?しかしそれは唯一の問題ではなく、それはまだ非常に不安定です。 – Sorona

答えて

1

に、凝縮させることができる

if (dir.x >= 0) { 
    x = -1; 
} else if (dir.x < 0) { 
    x = 1; 
} 

あなたのifsをさらに簡素化できると指摘しました。

:あなたが投稿コードから

しかし、何より重要なのは、あなたが(残念ながらあなたが任意の映像を提供していないので、これは私の最高の推測です)説明「途切れ」を説明するだろう一つの論理的な問題である

まず、エンティティが接地されているかどうかを確認します。もしそうなら、あなたは衝突があるかどうかをチェックし続け、最後に衝突がなければ、あなたはその位置を設定します。

これを少し反転させる必要があります。古い位置

  • チェック保存

    1. 新しいものにすでに位置を設定し
    2. を接地した場合!
    3. 衝突検出を行う
    4. 衝突を登録した場合!そこで、基本的

    glm::vec3 distanceToGravityCenter = 
         this->entity->getPosition() - 
         ((this->entity->getPosition() - gravityCenter) * 0.005d); // TODO multiply by time 
    
    oldPos = entity->getPosition(); // 1. 
    
    if (!entity->grounded) { // 2. 
        this->fallingStar->setPosition(distanceToGravityPoint); // 3 
    
        glm::vec3 entityPosition = entity->getPosition(); 
    
        if (getBlock(floorf(entityPosition.x), floorf(entityPosition.y), floorf(entityPosition.z))) { // 4, 5 
         this->entity->setPosition(oldPos); 
         entity->grounded = true; // If some update happens, grounded needs to be changed 
        } 
    } 
    

    これは、取得する必要が私はもう少し詳しく説明したい:)

    開始:

    をあなたが最初の衝突をチェックした場合、その後、あなたの位置を設定します最初の衝突/ヒット時に「無限ループ」を作成して衝突すると、衝突があった場合は元の位置に戻ります。基本的に数学的な不正確さは、あなたが元の位置に戻される毎回のチェックと同じように、あなたを動かすでしょう。

  • 1

    は、あなたの座標のいずれかのif -statementsを考えてみましょう:

    if (dir.x >= 0) { 
        x = -1; 
    } 
    
    if (dir.x < 0) { 
        x = 1; 
    } 
    

    dir.x < 0と仮定します。次に、最初のifをスキップし、2番目を入力して、xを1に設定します。 dir.x >= 0の場合、最初にifを入力し、x-1に設定します。今度はx < 0が真であるため、2番目のifも入力し、xは再び1に設定されます。

    dir.xに応じて、xを1に設定するか、-1に設定します。最初の1が入力されていなかったときに必要なので、あなただけの、二ifを実行する必要がありelse if:もしあなたそうしてください、すでに@CompuChipとして

    x = (dir.x >= 0) ? -1 : 1; 
    
    +0

    ありがとう、非常に良いキャッチ!まだ非常に、非常に不安定! – Sorona

    +0

    私の「フロアリング」も間違っているのでしょうか? – Sorona