所以,谷歌搜索和阅读小时后碰撞检测的帮助,我发现,检测使用SAT碰撞的基本过程是:需要与实施使用分离轴定理
for each edge of poly A
project A and B onto the normal for this edge
if intervals do not overlap, return false
end for
for each edge of poly B
project A and B onto the normal for this edge
if intervals do not overlap, return false
end for
不过,由于很多我尝试在代码中实现这一点,我无法通过它来检测碰撞。我的当前代码如下:
for (unsigned int i = 0; i < asteroids.size(); i++) {
if (asteroids.valid(i)) {
asteroids[i]->Update();
// Player-Asteroid collision detection
bool collision = true;
SDL_Rect asteroidBox = asteroids[i]->boundingBox;
// Bullet-Asteroid collision detection
for (unsigned int j = 0; j < player.bullets.size(); j++) {
if (player.bullets.valid(j)) {
Bullet b = player.bullets[j];
collision = true;
if (b.x + (b.w/2.0f) < asteroidBox.x - (asteroidBox.w/2.0f)) collision = false;
if (b.x - (b.w/2.0f) > asteroidBox.x + (asteroidBox.w/2.0f)) collision = false;
if (b.y - (b.h/2.0f) > asteroidBox.y + (asteroidBox.h/2.0f)) collision = false;
if (b.y + (b.h/2.0f) < asteroidBox.y - (asteroidBox.h/2.0f)) collision = false;
if (collision) {
bool realCollision = false;
float min1, max1, min2, max2;
// Create a list of vertices for the bullet
CrissCross::Data::LList<Vector2D *> bullVerts;
bullVerts.insert(new Vector2D(b.x - b.w/2.0f, b.y + b.h/2.0f));
bullVerts.insert(new Vector2D(b.x - b.w/2.0f, b.y - b.h/2.0f));
bullVerts.insert(new Vector2D(b.x + b.w/2.0f, b.y - b.h/2.0f));
bullVerts.insert(new Vector2D(b.x + b.w/2.0f, b.y + b.h/2.0f));
// Create a list of vectors of the edges of the bullet and the asteroid
CrissCross::Data::LList<Vector2D *> bullEdges;
CrissCross::Data::LList<Vector2D *> asteroidEdges;
for (int k = 0; k < 4; k++) {
int n = (k == 3) ? 0 : k + 1;
bullEdges.insert(new Vector2D(bullVerts[k]->x - bullVerts[n]->x,
bullVerts[k]->y - bullVerts[n]->y));
asteroidEdges.insert(new Vector2D(asteroids[i]->vertices[k]->x - asteroids[i]->vertices[n]->x,
asteroids[i]->vertices[k]->y - asteroids[i]->vertices[n]->y));
}
Vector2D *vectOffset = new Vector2D(asteroids[i]->center.x - b.x, asteroids[i]->center.y - b.y);
for (unsigned int k = 0; k < asteroidEdges.size(); k++) {
Vector2D *axis = asteroidEdges[k]->getPerpendicular();
axis->normalize();
min1 = max1 = axis->dotProduct(asteroids[i]->vertices[0]);
for (unsigned int l = 1; l < asteroids[i]->vertices.size(); l++) {
float test = axis->dotProduct(asteroids[i]->vertices[l]);
min1 = (test < min1) ? test : min1;
max1 = (test > max1) ? test : max1;
}
min2 = max2 = axis->dotProduct(bullVerts[0]);
for (unsigned int l = 1; l < bullVerts.size(); l++) {
float test = axis->dotProduct(bullVerts[l]);
min2 = (test < min2) ? test : min2;
max2 = (test > max2) ? test : max2;
}
float offset = axis->dotProduct(vectOffset);
min1 += offset;
max1 += offset;
delete axis; axis = NULL;
float d0 = min1 - max2;
float d1 = min2 - max1;
if (d0 > 0 || d1 > 0) {
realCollision = false;
break;
} else {
realCollision = true;
}
}
if (realCollision) {
for (unsigned int k = 0; k < bullEdges.size(); k++) {
Vector2D *axis = bullEdges[k]->getPerpendicular();
axis->normalize();
min1 = max1 = axis->dotProduct(asteroids[i]->vertices[0]);
for (unsigned int l = 1; l < asteroids[i]->vertices.size(); l++) {
float test = axis->dotProduct(asteroids[i]->vertices[l]);
min1 = (test < min1) ? test : min1;
max1 = (test > max1) ? test : max1;
}
min2 = max2 = axis->dotProduct(bullVerts[0]);
for (unsigned int l = 1; l < bullVerts.size(); l++) {
float test = axis->dotProduct(bullVerts[l]);
min2 = (test < min2) ? test : min2;
max2 = (test > max2) ? test : max2;
}
float offset = axis->dotProduct(vectOffset);
min1 += offset;
max1 += offset;
delete axis; axis = NULL;
float d0 = min1 - max2;
float d1 = min2 - max1;
if (d0 > 0 || d1 > 0) {
realCollision = false;
break;
} else {
realCollision = true;
}
}
}
if (realCollision) {
player.bullets.remove(j);
int numAsteroids;
float newDegree;
srand (j + asteroidBox.x);
if (asteroids[i]->degree == 90.0f) {
if (rand() % 2 == 1) {
numAsteroids = 3;
newDegree = 30.0f;
} else {
numAsteroids = 2;
newDegree = 45.0f;
}
for (int k = 0; k < numAsteroids; k++)
asteroids.insert(new Asteroid(asteroidBox.x + (10 * k), asteroidBox.y + (10 * k), newDegree));
}
delete asteroids[i];
asteroids.remove(i);
}
while (bullVerts.size()) {
delete bullVerts[0];
bullVerts.remove(0);
}
while (bullEdges.size()) {
delete bullEdges[0];
bullEdges.remove(0);
}
while (asteroidEdges.size()) {
delete asteroidEdges[0];
asteroidEdges.remove(0);
}
delete vectOffset; vectOffset = NULL;
}
}
}
}
}
bullEdges是子弹的边缘向量的列表,asteroidEdges是类似的,并且bullVerts和小行星[I] .vertices是,很明显,每个顶点的向量的列表为各自的子弹或小行星。
老实说,我不是在寻找代码修正,只是一个新的眼睛。
究竟是什么问题? realCollision总是出错?您的包围盒测试是否正常工作?我没有看到任何明显的东西,你应该将碰撞检测分成单独的方法,以便你可以对它进行单元测试。 – 2010-06-01 02:31:40
边界框碰撞的作品,但realCollision几乎总是以假结束。 – Eddie 2010-06-01 02:34:22
用最新的代码更新,阅读另一篇文章,并遵循它的要点。 – Eddie 2010-06-01 02:38:09