Ich entwickle gerade einen Breakout-Klon und habe eine Straßensperre getroffen, um die Kollisionserkennung zwischen einer Kugel (Kreis) und einem Stein (konvexes Polygon) zu erhalten, die korrekt funktioniert. Ich verwende einen Kreis-Linien-Kollisionserkennungstest, bei dem jede Linie den konvexen Polygonstein darstellt und kantet.
Die meiste Zeit funktioniert der Circle-Line-Test ordnungsgemäß und die Kollisionspunkte werden korrekt aufgelöst.
Kollisionserkennung funktioniert korrekt.
Gelegentlich gibt mein Kollisionserkennungscode jedoch aufgrund einer negativen Diskriminante falsch zurück, wenn der Ball tatsächlich den Stein schneidet.
Kollisionserkennung fehlgeschlagen.
Ich bin mir der Ineffizienz dieser Methode bewusst und verwende achsenausgerichtete Begrenzungsrahmen, um die Anzahl der getesteten Steine zu verringern. Mein Hauptanliegen ist, ob mein Code unten mathematische Fehler enthält.
/*
* from and to are points at the start and end of the convex polygons edge.
* This function is called for every edge in the convex polygon until a
* collision is detected.
*/
bool circleLineCollision(Vec2f from, Vec2f to)
{
Vec2f lFrom, lTo, lLine;
Vec2f line, normal;
Vec2f intersectPt1, intersectPt2;
float a, b, c, disc, sqrt_disc, u, v, nn, vn;
bool one = false, two = false;
// set line vectors
lFrom = from - ball.circle.centre; // localised
lTo = to - ball.circle.centre; // localised
lLine = lFrom - lTo; // localised
line = from - to;
// calculate a, b & c values
a = lLine.dot(lLine);
b = 2 * (lLine.dot(lFrom));
c = (lFrom.dot(lFrom)) - (ball.circle.radius * ball.circle.radius);
// discriminant
disc = (b * b) - (4 * a * c);
if (disc < 0.0f)
{
// no intersections
return false;
}
else if (disc == 0.0f)
{
// one intersection
u = -b / (2 * a);
intersectPt1 = from + (lLine.scale(u));
one = pointOnLine(intersectPt1, from, to);
if (!one)
return false;
return true;
}
else
{
// two intersections
sqrt_disc = sqrt(disc);
u = (-b + sqrt_disc) / (2 * a);
v = (-b - sqrt_disc) / (2 * a);
intersectPt1 = from + (lLine.scale(u));
intersectPt2 = from + (lLine.scale(v));
one = pointOnLine(intersectPt1, from, to);
two = pointOnLine(intersectPt2, from, to);
if (!one && !two)
return false;
return true;
}
}
bool pointOnLine(Vec2f p, Vec2f from, Vec2f to)
{
if (p.x >= min(from.x, to.x) && p.x <= max(from.x, to.x) &&
p.y >= min(from.y, to.y) && p.y <= max(from.y, to.y))
return true;
return false;
}
sqrt_disc = sqrt(disc);
wieder einzutragen . Vielen Dank für Ihre Antwort unten, die mir sehr geholfen hat.