我一直在尝试用C / X11 / OpenGL编写FPS,但我遇到的问题是计算子弹击中的位置。我使用了可怕的技术,它有时只能起作用:
pos size, p;
size.x = 0.1;
size.z = 0.1; // Since the game is technically top-down (but in a 3D perspective)
// Positions are in X/Z, no Y
float f; // Counter
float d = FIRE_MAX + 1 /* Shortest Distance */, d1 /* Distance being calculated */;
x = 0; // Index of object to hit
for (f = 0.0; f < FIRE_MAX; f += .01) {
// Go forwards
p.x = player->pos.x + f * sin(toRadians(player->rot.x));
p.z = player->pos.z - f * cos(toRadians(player->rot.x));
// Get all objects that collide with the current position of the bullet
short* objs = _colDetectGetObjects(p, size, objects);
for (i = 0; i < MAX_OBJECTS; i++) {
if (objs[i] == -1) {
continue;
}
// Check the distance between the object and the player
d1 = sqrt(
pow((objects[i].pos.x - player->pos.x), 2)
+ pow((objects[i].pos.z - player->pos.z),
2));
// If it's closer, set it as the object to hit
if (d1 < d) {
x = i;
d = d1;
}
}
// If there was an object, hit it
if (x > 0) {
hit(&objects[x], FIRE_DAMAGE, explosions, currtime);
break;
}
}
它只是通过制作for循环并计算可能与子弹当前位置发生碰撞的任何对象来工作。当然,这非常慢,有时甚至无法正常工作。
计算子弹击中位置的首选方法是什么?我想过制作一条线,看看是否有任何物体与该线相撞,但我不知道如何进行这种碰撞检测。
编辑:我想我的问题是这样的:我如何计算一条直线上碰撞的最近物体(可能不是45/90度的直角)?或者有没有更简单的计算子弹击中位置的方法?子弹有点像激光,在某种意义上重力不影响它(写一个老派游戏,所以我不希望它过于逼真)
答案 0 :(得分:3)
对于您想要命中的每个对象,定义一个边界对象。 简单的例子是球体或盒子。 然后,您必须实现光线球体或光线盒交叉点。
对于exaple,请查看line-sphere intersection。 对于框,您可以测试四个边界线,但是有一些算法优化了axis aligned boxes。
有了这个,就像你已经做的那样继续。对于场景中的每个对象,检查交叉点,如果相交,则比较与先前相交的对象的距离,取出先前击中的对象。
交叉算法为您提供了射线参数(值{t hit_position = ray_origin + t * ray_direction
),您可以使用它来比较距离。
答案 1 :(得分:1)
您可以在BSP tree中组织所有场景对象,然后点击\碰撞检测将非常容易实现。您还可以使用BSP检测不可见对象,并在渲染之前将其丢弃。