我的瓷磚地圖有衝突解決問題。我有一個撞在瓦片上的球。碰撞工作正常,除了當兩個瓦片之間發生碰撞時。然後我的碰撞解決方法變得很糟糕,而且球飛向錯誤的方向。我的球是長方形的,而方塊是長方形的。兩塊瓷磚之間的Tilemap衝突解決方案
這裏是演示了這個問題一個.gif:
球應該反映斷磚一次一個。
的算法是這樣的:
- 應用運動,之後檢查和解決衝突。
- 找出球重疊的方塊。
- 如果瓷磚被檢查是不是差強人意:
- 找出球是多少重疊瓦的X和Y軸。
- 僅通過在淺軸上將球移出瓦片來解決碰撞。 (無論哪個軸最少穿透)。
- 繼續前進到下一個圖塊。
- 如果被檢查的磁貼是可通過的,則什麼也不做。
我已經讀過這個最小位移技術的問題是在解決碰撞後,可能會將球移動到另一個碰撞。修復應該是,那只是第二次運行算法。我試過這個,但它沒有幫助。這裏是我的衝突處理的代碼,在C++:
void PlayState::handleCollisions() {
// Get ball bounding box.
sf::FloatRect ballBounds = ball.sprite.getGlobalBounds();
// Find out the nearby tiles.
int leftTile = (int)floor((float)ballBounds.left/level1.TILE_WIDTH);
int rightTile = (int)ceil(((float)(ballBounds.left + ballBounds.width)/level1.TILE_WIDTH)) - 1;
int topTile = (int)floor((float)ballBounds.top/level1.TILE_HEIGHT);
int bottomTile = (int)ceil(((float)(ballBounds.top + ballBounds.height)/level1.TILE_HEIGHT)) - 1;
// For each potentially colliding tile,
for(int y = topTile; y <= bottomTile; ++y) {
for(int x = leftTile; x <= rightTile; ++x) {
// If this tile is collidable,
TileCollision collision = getCollision(x, y);
if(collision == Impassable) {
// Determine collision depth (with direction) and magnitude.
sf::FloatRect tileBounds = getTileBounds(x, y);
sf::Vector2f depth = Collision::getIntersectionDepth(ballBounds, tileBounds);
if(depth != sf::Vector2f(0, 0)) {
float absDepthX = std::abs(depth.x);
float absDepthY = std::abs(depth.y);
// Resolve the collision along the shallow axis.
if(absDepthY < absDepthX) {
// Resolve the collision along the Y axis.
ball.sprite.setPosition(ball.sprite.getPosition().x, ball.sprite.getPosition().y + depth.y);
// Perform further collisions with the new bounds.
sf::FloatRect ballBounds = ball.sprite.getGlobalBounds();
// Y-distance to the tile center.
if(distanceY < 0) {
std::cout << "Collided from TOP." << std::endl;
ball.velocity.y = -ball.velocity.y;
}
else {
std::cout << "Collided from BOTTOM." << std::endl;
ball.velocity.y = -ball.velocity.y;
}
}
else {
// Resolve the collision along the X axis.
ball.sprite.setPosition(ball.sprite.getPosition().x + depth.x, ball.sprite.getPosition().y);
// Perform further collisions with the new bounds.
sf::FloatRect ballBounds = ball.sprite.getGlobalBounds();
// X-distance to the tile center.
if(distanceX < 0) {
std::cout << "Collided from LEFT." << std::endl;
ball.velocity.x = -ball.velocity.x;
}
else {
std::cout << "Collided from RIGHT." << std::endl;
ball.velocity.x = -ball.velocity.x;
}
}
}
}
}
}
}
我試圖運行算法第二次,就像這樣:
void PlayState::update(sf::Time deltaTime) {
ball.update(deltaTime);
handleCollisions();
handleCollisions();
}
有什麼事解決這個問題?
我將如何計算可能的碰撞點的座標? – lefti
我已經更新瞭解答這個問題的答案 – Vovanium
注意@mfa答案,最好把球當作點。 – Vovanium