how to aim correctly at first person shooter

Started by manji, October 30, 2010, 19:26:28

Previous topic - Next topic

manji

I have the follow problem. The character of my fps game, can shoot bullets, towards where the corsair points. I want the bullets to be rendered. This works well when the gun is at the center of the window, and you can see the bullets heading to the target. Now, when I try to place the camera higher, near the head of the character, the bullets are also going higher, missing the target. This of course makes sense, and it wouldn't be a problem if did not want to render the bullets. But how can I efficiently make it work? It must be a common issue in most fps and other games, sorry for my noob question.
toyWars game blog: http://toywars.wordpress.com/

CodeBunny

I'm not sure, but I think you can use a ray to discover where the "centered" camera bullets would first intersect an object, and then you just fire a bullet from your offset gun towards those coordinates.

manji

Thank you for your answer CodeBunny. I searched this issue a little more, and yes, ray tracing (AABB) seems to be the way. I have implemented an algorithm found at the book Real-Time Collision Detection, Christer Ericson, 2005. But I still have a problem. The algorithm works fine, it does detect if and where intersections occur. But, it gives me a wrong y coordinate when I am aiming at the 2 sides parallel to the xy plane. With all the other sides, there seems to be no problem. I place the algorithm I use here:
private boolean intersects(Box b){

    final float EPSILON = 0.00000001f;
    float tmin = 0.0f;
    float tmax = Float.MAX_VALUE;          
    // Camera position
    float[] cameraPos = {xWorld, yWorld, zWorld};
    // Camera direction
    float[] dir = {xDir, yDir, zDir};

    // For all three slabs
    for (int i=0; i<3; i++){
    // Avoid division by zero later
        if (Math.abs(dir[i]) < EPSILON){
            // Ray is parallel to slab. No hit if origin not within slab
            if (cameraPos[i] < b.min[i] || cameraPos[i] > b.max[i]){
                return false;
            }
        }
        else{
            // Compute intersection t value of ray with near and far plane of slab
            float odd = 1.0f/dir[i];			
            float t1 = (b.min[i] - cameraPos[i])*odd;
            float t2 = (b.max[i] - cameraPos[i])*odd;                   

            // Make t1 be intersection with near plane, t2 with far plane
            if (t1 > t2){
                float t = t1;
                t1 = t2;
                t2 = t;
            }

            // Compute the intersection of slab intersection intervals
            if (t1 > tmin){
                tmin = t1;
            }
            if (t2 < tmax){
                tmax = t2;			  
            }

            // Exit with no collision as soon as slab intersection becomes empty
            if (tmin > tmax){			
                return false;
            }
        }
        // Ray intersects the slab. Return point and intersection t value (tmin)
        intersectionPos[i] = cameraPos[i] + dir[i]*tmin; // Declared as member variable
    }
    return true;
}

Any thoughts?
toyWars game blog: http://toywars.wordpress.com/

CodeBunny

I'm not the best person to ask, I've never used RayTracing algorithms before.

What do you mean by "wrong y coordinate"? The xy-plane of a bounding box would be the top and bottom of the box - do you mean the reported value is the center of the box, or 0, or something else?

I do know that JME has built-in support for this. It's a great 3D engine, if you're not opposed to using a pre-made setup I'd suggest using that. Plus, you wouldn't have to stick with bounding boxes for raytracing - I believe their method works for any geometric shape.

manji

QuoteWhat do you mean by "wrong y coordinate"?
For now, I test my algorithm by placing my character looking at a box, and print the location on the box he is looking at. The strange thing is that when he is looking at the sides parallel to the xy plane, the y coordinate on the box he is looking at(according to the ray intersection code) is wrong. For example when he is looking at the bottom of the side, I get 0,3 when the right one i 0.0. Or when looking at the top of the side I get 0.8 then the right one is 1.0. And when he changes his view only parallel to the local x axis of the box(hope that makes sense), the y coordinate also changes. For all the other sides, I seem to have the right coordinates for any position on the sides.

Just now, I noticed something very interesting and helpful. What influences this difference in the output, is the order of the planes being checked. The slab that is checked in the middle, will return false results! For example if the loop goes xzy, the z coordinates will be wrong when looking at a pair of sides (don't know which ones for sure). So I guess there is something wrong in the logic of the algorithm... But I cannot find it two days now!

QuoteI do know that JME has built-in support for this.
Yes, I know about JME. I had begun studying it, but the support on the new revision, JME3, was lacking documentation so I gave up. I also tried jBullet but I couldn't even install it. I think it is for the best, because this way I get to learn stuff, which I find interesting.
toyWars game blog: http://toywars.wordpress.com/

manji

Solution Found!!!
Ok, guys, it was a very silly mistake of mine, sorry  ;D
intersectionPos must be calculated outside of the loop, because where it is now, tmin is not final of course.
I believe though that this piece of code can be useful for anyone searching for a simple, clever and maybe efficient way of checking ray-box intersection.
toyWars game blog: http://toywars.wordpress.com/