【发布时间】:2012-03-27 20:22:30
【问题描述】:
我正在尝试在我的游戏中实现碰撞检测,但一开始看起来很容易的东西已经变成了一个怪物,我在没有帮助的情况下无法完全解决。
游戏将在某个时候成为 RTS,但现在只有一堆单位可以被告知移动到屏幕上的特定位置。但是,单位不断消失,只剩下一个单位,所以我为每个单位定义了边界框,并在游戏循环中移动它们后测试了单位之间的碰撞,以便将它们分开。
这不起作用,因为我没有实施一种方法来知道我正在移动的特定单元不会取代其他单元的位置(我已经迭代过)。
我试图保持已经占据的位置(或区域),以便在没有单位的地方转移。但这在某些情况下也不起作用,例如当一个单元在屏幕的四个角中的任何一个上移动时,它不能超出屏幕的边界,也不能占据它所碰撞的单元所占据的区域。
我仍然很确定我过于复杂化了可以通过不同方法轻松完成的事情。
每个单元都有自己的边界球体、位置、方向矢量和速度矢量。
class Unit {
friend class Party;
protected:
float xPos, yPos;
float destX, destY;
float detectionRange;
Vector *vel;
Vector *dest;
int dir;
int offset;
int width, height;
Circle *circle; //Bounding Circle
...
public:
...
};
//Collision Checking
void Party::checkCollisions() {
bool noCol;
float dx, dy;
Circle *mCircle = NULL;
Circle *sCircle = NULL;
do {
noCol = true;
for(int i=0; i<numUnits; i++) {
mCircle = units[i]->getCircle();
for(int j=0; j<numUnits; j++) {
if(j==i) {
continue;
}
sCircle = units[j]->getCircle();
if(mCircle->isColliding(sCircle)) {
noCol = false;
mCircle->getShifts(sCircle, &dx, &dy);
units[i]->shift(dx, dy);
units[j]->shift(-dx, -dy);
}
}
}
} while(noCol == false);
}
//IsColliding. This is overriden for isColliding(Circle *circle), but here
//you see the actual algorithm.
bool Circle::isColliding(float X, float Y, int rad) {
float mag = sqrt((X-x)*(X-x) + (Y-y)*(Y-y));
if(mag <= (radius + rad)){
return true;
}
return false;
}
//Get Shifts
void Circle::getShifts(Circle *c, float *dx, float *dy) {
float x1 = x - c->x;
float y1 = y - c->y;
if(x1 > -1 && x1 < 1) {
x1 = 1;
}
if(y1 > -1 && y1 < 1) {
y1 = 1;
}
*dx = x1/fabs(x1);
*dy = y1/fabs(y1);
}
This video 显示了我目前所得到的结果,但很明显它出现了极大的故障并且有不必要的单位移动。
我想要的是,当两个或更多单位聚集在一起时,它们会自然聚集。但并非所有单位在任何时候都形成一个群体。由于每个单元具有不同的检测范围,因此可以从群中分离出一个或多个单元。我想要这个,以便以后我可以选择和移动不同的单位组。
【问题讨论】: