开发一个基本的比武(一种古老的街机游戏)克隆,达到碰撞检测,一开始似乎可以工作。 但我发现,当我在平台上保持静止时,或者即使我在平台上移动时,经过短暂时间(~5sc)后,我会夹住平台
我首先进行了一些清理、测试、移动、测试和小型重构,以简化检测和测试,并使其整体更干净,但检测似乎还可以;毕竟它可以工作〜5sc。
之后,我想到了重力;因为即使在地面上,它也会影响玩家并可能迫使拍摄对象发生剪辑。所以我可能是一个 isGrounded 变量。所以操作顺序应该是:(玩家稍微在空中开始)
handleCollision 说确定没有碰撞 -> isGrounded=false
使用有效重力更新玩家
玩家摔倒
然后玩家与平台相撞
handleCollision 说哦,你在平台上 -> isGrounded=true
玩家更新应该不受重力影响
#include "game.h"
Game::Game() : window(sf::VideoMode(windowWidth, windowHeight), "App")
{
// stuff //
isGrounded = true;
}
void Game::handleCollision(sf::RectangleShape &A, const sf::RectangleShape &B)
{
sf::FloatRect BoxA = A.getGlobalBounds();
sf::FloatRect BoxB = B.getGlobalBounds();
// Check collision from above
if (BoxA.intersects(BoxB) && BoxA.top + BoxA.height < BoxB.top + BoxB.height)
{
A.setPosition(A.getPosition().x, B.getPosition().y - BoxA.height); // A.getSize().y);
isGrounded = true;
std::cout << "Grounded: " << std::endl;
}
else
{
isGrounded = false;
std::cout << "In The Air: " << std::endl;
}
}
void Game::handleCollisions()
{
handleCollision(player1, platformGround);
}
void Game::update()
{
float deltaTime = frameTime.asSeconds();
// Player 1 movement control using keyboard input
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
player1.move(-playerSpeed * deltaTime, 0);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
player1.move(playerSpeed * deltaTime, 0);
}
// Player 1 flapping control using spacebar
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
{
player1Velocity = flapVelocity;
}
// Apply gravity only when player is not grounded
if (!isGrounded)
{
player1Velocity += gravity * deltaTime;
}
else
{
player1Velocity = 0.0f;
}
// Update position
player1.move(0, player1Velocity * deltaTime);
handleCollisions();
}
这确实是一件愚蠢而明显的事情,它(几乎)总是这样;但预先感谢您提供任何形式的帮助。
好的
一周后,我找到了解决方案。问题是,这段代码只适用于两个对象,这就是问题所在,因为我进行了 6 次碰撞检查:当接触地面时,标志 isGrounded 被正确设置为 true,但在下一次检查中立即重置(因为当时条件为 false,所以去到 else 部分并将 isGrounded 设置回 false)
所以在我这边做了其他最小的例子之后,我开始用以下内容替换原始支票:
if (BoxA.intersects(BoxB) && player1Velocity >= 0.0f)
{
// isGrounded = true;
A.setPosition(A.getPosition().x, BoxB.top - BoxA.height);
player1Velocity = 0.0f;
std::cout << "Grounded: " << BoxA.height << std::endl;
}
else
{
isGrounded = false;
std::cout << "In The Air: " << std::endl;
}
现在可以与其他碰撞检查一起使用,即使现在我不知道为什么,因为 isGrounded 仍然设置为 false,因此应该在更新函数中激活重力效果。
但那是另一回事,不再链接到最初的问题。