2017-04-03 106 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

'if(dir.x> = 0){x = -1; } if(dir.x <0){x = 1; }' - 對我來說這似乎很無用......'''''''''''''''''''''''''''''''''''''你的意思是「如果」呢?這將導致你描述的行爲,所以我會讓它成爲一個答案。 – CompuChip

+0

@CompuChip當然,一個愚蠢的錯誤消失了,還有多少潛伏在那裏?這不是唯一的問題,但它仍然非常非常波濤洶涌。 – Sorona

回答

1

由於@CompuChip已經指出,你的ifs可以進一步簡化。

但更重要的是可以解釋的「振盪格局」你形容一個邏輯問題(可悲的是你沒有提供任何鏡頭,所以這是我最好的猜測)

從您發佈的代碼:

首先檢查實體是否接地。如果是這樣,你繼續檢查是否有碰撞,最後如果沒有,你設置位置。

你要反轉這一點。

  1. 保存舊的位置
  2. 檢查接地
  3. 已經設置的位置到新的!
  4. 是否碰撞檢測
  5. 重置爲舊位置如果您註冊了碰撞!

所以基本上:

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,進入第二,和x將被設置爲1。 如果dir.x >= 0,您將進入第一ifx將被設置爲-1。現在x < 0是真實的,所以你將進入第二if的歡迎,並得到x再次設置爲1。

可能你想要的是將x設置爲1或-1,這取決於dir.x。您應該只執行第二if時未進入第一個,所以你需要一個else if

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

可凝結,如果你願意請,到

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

謝謝,非常好的趕上!儘管如此,仍然非常非常不穩定! – Sorona

+0

也許我的'地板'也是錯的? – Sorona