Ich arbeite gerade an einigen grundlegenden 2D RigidBody Physik und habe ein Problem festgestellt. Ich habe eine Funktion, die auf Kollision zwischen einem Kreis und einem AABB prüft, aber manchmal kollidiert der Kreis (in diesem Fall der Spieler) und verschwindet dann. Wenn ich die Position ausdruck, wenn dies passiert, setze ich einfach "nan".C++ Collision Detection verursacht das Verschwinden von Objekten
bool Game::Physics::RigidBody2D::CircleAABB(RigidBody2D& body)
{
sf::Vector2f diff = m_Position - body.m_Position;
sf::Vector2f halfExtents = sf::Vector2f(body.m_Size.x/2.0f, body.m_Size.y/2.0f);
sf::Vector2f diffContrained = diff;
if (diff.x > halfExtents.x)
{
diffContrained.x = halfExtents.x;
}
else if (diff.x < -halfExtents.x)
{
diffContrained.x = -halfExtents.x;
}
if (diff.y > halfExtents.y)
{
diffContrained.y = halfExtents.y;
}
else if (diff.y < -halfExtents.y)
{
diffContrained.y = -halfExtents.y;
}
sf::Vector2f colCheck = diff - diffContrained;
sf::Vector2f VDirNorm = NormVector(colCheck);
sf::Vector2f colToPlayer = NormVector(m_Position - (diffContrained + body.m_Position));
float dist = getMagnitude(colCheck) - m_fRadius;
//std::cout << dist << std::endl;
if (dist < 0)
{
OnCollision((diffContrained + body.m_Position) - m_Position);
m_Position += (VDirNorm * abs(dist));
body.m_Position -= (VDirNorm * abs(dist))* (1.0f - body.m_fMass);
return true; //Collision has happened
}
return false;
}
Dies geschieht zufällig und fast ohne ersichtlichen Grund, obwohl es häufiger zu passieren scheint, wenn der Kreis schnell bewegt, kann aber auch passieren, wenn es langsam oder ein oder zwei Mal bewegt, wenn es überhaupt nicht bewegt alle.
Ein weiterer Hinweis ist, dass ich die Schwerkraft auf die Y-Geschwindigkeit und auf Kollision stellen Sie die Geschwindigkeit der koordinierenden Achse auf 0
Also meine Frage anzuwenden ist, ist etwas eindeutig falsch hier, um diejenigen mit mehr Physik Erfahrung als mich?
Hinweis: Die Verwendung von SFML zum Zeichnen und Vector2 Klassen Physik Code ist alles meins.
EDIT: Die OnCollision-Funktion prüft die Seite der Kollision, so dass Objekte, die erben, diese verwenden können (z. B. prüfen, ob die Kollision unterhalb war, um einen "isGrounded" -Boolean auszulösen). In diesem Fall überprüft der Spieler die Seite und setzt dann die Geschwindigkeit auf dieser Achse auf 0 und löst auch einen isGrounded-Boolean aus, wenn er darunter ist.
void Game::GamePlay::PlayerController::OnCollision(sf::Vector2f vDir)
{
if (abs(vDir.x) > abs(vDir.y))
{
if (vDir.x > 0.0f)
{
//std::cout << "Right" << std::endl;
//Collision on the right
m_Velocity.x = 0.0f;
}
if (vDir.x < 0.0f)
{
//std::cout << "Left" << std::endl;
//Collision on the left
m_Velocity.x = 0.0f;
}
return;
}
else
{
if (vDir.y > 0.0f)
{
//std::cout << "Below" << std::endl;
//Collision below
m_Velocity.y = 0.0f;
if (!m_bCanJump && m_RecentlyCollidedNode != nullptr)
{
m_RecentlyCollidedNode->ys += 3.f;
}
m_bCanJump = true;
}
if (vDir.y < 0.0f)
{
//std::cout << "Above" << std::endl;
//Collision above
m_Velocity.y = 0.0f;
}
}
}
Aus dem Debugging von Geschwindigkeit und Position ist kein wirklicher Grund an die Oberfläche gekommen.
inline sf::Vector2f NormVector(sf::Vector2f vec)
{
float mag = getMagnitude(vec);
return vec/mag;
}
Lösung:
if (colCheck.x == 0 && colCheck.y == 0)
{
std::cout << "Zero Vector" << std::endl;
float impulse = m_Velocity.x + m_Velocity.y;
m_Velocity.x = 0;
m_Velocity.y = 0;
m_Velocity += NormVector(diff)*impulse;
}
else
{
VDirNorm = NormVector(colCheck);
dist = getMagnitude(colCheck) - m_fRadius;
}
Sie sollten einige Debugging und melden Sie zurück mit dem, was Sie finden. –
Sie müssen eine ordnungsgemäße [MCVE] bereitstellen. Insbesondere müssen wir wissen, was "NormVector" auf Code-Ebene macht und was "OnCollision" tut. Bis jetzt sehen diese wie die wahrscheinlichsten Täter aus. – Xirema
Entschuldigung! Wird mehr Details hinzufügen. –