3

I have been trying to write an FPS in C/X11/OpenGL, but the issue that I have encountered is with calculating where the bullet hits. I have used a horrible technique, and it only sometimes works:

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;
    }
}

It just works by making a for-loop and calculating any objects that might collide with where the bullet currently is. This, of course, is very slow, and sometimes doesn't even work.

What would be the preferred way to calculate where the bullet hits? I have thought of making a line and seeing if any objects collide with that line, but I have no idea how to do that kind of collision detection.


EDIT: I guess my question is this: How do I calculate the nearest object colliding in a line (that might not be a straight 45/90 degree angle)? Or are there any simpler methods of calculating where the bullet hits? The bullet is sort of like a laser, in the sense that gravity does not affect it (writing an old-school game, so I don't want it to be too realistic)

mad_manny
  • 1,081
  • 16
  • 28
MiJyn
  • 5,327
  • 4
  • 37
  • 64
  • Can't you just solve that quadratic equation manually and hardcode the solution formula? –  Nov 23 '12 at 19:23
  • Add more information, and make a resume of the variables – Alberto Bonsanto Nov 23 '12 at 19:34
  • @H2CO3, I'm a newbie when it comes to quadratic equations... could you give an example? – MiJyn Nov 23 '12 at 19:55
  • @AlbertoBonsanto, sure, will do – MiJyn Nov 23 '12 at 19:55
  • @lkjoel an example for a quadratic equation is *ax^2 + bx + c = 0,* and you should have learnt about them during your highschool maths and physics lessons. They describe the movement of free-falling objects. –  Nov 23 '12 at 19:56
  • Oh right, yeah, I thought you were talking about quaternions (keep on confusing them :/) – MiJyn Nov 23 '12 at 20:13
  • I edited my question for clarity – MiJyn Nov 23 '12 at 20:21
  • `float d = FIRE_MAX + 1 /* Shortest Distance */, d1 /* Distance being calculated */; x = 0;` Now: make up your mind: what do you want it to be? Note: don't use a float as an index- or a loop-variable. You might look silly, and it will hurt you in the end. – wildplasser Nov 23 '12 at 23:30
  • @wildplasser, I'm not exactly sure what you mean... and yeah, that's half the reason I posted this question (I know how horrible it looks and it already hurts me :P) – MiJyn Nov 24 '12 at 00:09

2 Answers2

3

For every object you want to be hit-able, define a bounding object. Simple examples would be a sphere or a box. Then you have to implement a ray-sphere or ray-box intersection.

For exaple have a look at line-sphere intersection. For boxes, you can either test aginast the four bounding lines, but there are algorithms optimsed for axis aligned boxes.

With this, proceed as you already do. For every object in the scene, check for intersection, if intersects, compare distance to previous intersected objects, take the one that is hit first. The intersection algorithems give you the ray parameter as a result (the value t for which hit_position = ray_origin + t * ray_direction) which you can use to compare the distances.

kakTuZ
  • 562
  • 2
  • 11
  • Thanks a lot! It works! I used this code as a base: http://tog.acm.org/resources/GraphicsGems/gemsii/xlines.c, and I went the lazy way and used 4 lines for rectangles. – MiJyn Nov 24 '12 at 00:35
1

You can organise all scene objects in the BSP tree then hit\collide detection will be pretty easy to implement. Also you can use BSP to detect invisible objects and discard them before rendering.

JAre
  • 4,666
  • 3
  • 27
  • 45
  • Are there any basic examples of how to do that? – MiJyn Nov 23 '12 at 23:22
  • @lkjoel you can start with this [FAQ](http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/bsp-tree-faq-r657) and [this](http://www.gamedev.net/page/resources/_/technical/game-programming/practical-collision-detection-r736) – JAre Nov 23 '12 at 23:35
  • 1
    Thanks for the links. Sadly, the examples are horribly formatted, no idea why. Though kakTuZ has helped me solve the question, I will look into the other method in my spare time :) – MiJyn Nov 24 '12 at 00:36