FPS design questions.[solved I think?]

So I’m mainly working on an RPG, but it can get tedious and aggitating to only having one project(IMO). So in attempts to keep interest in my little RPG I decided I want to make a little FPS. I have a couple questions on two of the problems I’m not sure (yet) how to solve.

Here are the two “problems”:

  1. a 3-D shooting algorithm. The way I’d want to do this is to find the center of my screen in any 3-D environment. I know how to do this if the with no camera rotations. I don’t want to use unProject I want to learn the math. If anyone knows what type of algorithm I might need to use, please lemme know :).(Screen 2-D to world 3-D) , the problem I see is if you rotate your camera on it’s Y-axis there’s no real way to tell if your looking towards the Z Plane or the X Plane…

  2. Bullet holes and blood splatter on walls. I saw how TUER did it it looked like he just put a new plane object where the collision was. I find that method kind of cheesey(if that’s what he did). I was wondering if there was a way to actively change the texture of a quad smoothly at run-time? Would this be through the use of a shader(if so that’s gonna be complex)?

Any input, ideas, comments, concerns I may have would be excellent. The goal for this isn’t to have some immaculate FPS just a cheesey cube shooter or something haha.

this should not be too hard.

let say your camera is set with
px,py,pz (pos)
rx,ry,rz (rot)
FOV=70

create three Vector that will represent a 3D space axis (unit matrix)
ax(1,0,0) =>for axis X
ay(0,1,0) =>for axis Y
az(0,0,1) =>for axis Z

apply to this vector the same tranformation than your camera rot (rx,ry,rz) then trans(px,py,pz)

you now have the local axis of your cam set in world space.

you can use it to translate camera space to world space or world space to camera space (you only have to use scalar product to do that).

world to camera space (world pos is wx,wy,wz & camera pos is cx,cy,cz):
wx-=px;
wy-=py;
wz-=pz;
cx=wxaxx+wyaxy+wzaxz.
cy=wx
ayx+wyayy+wzayz.
cz=wxazx+wyazy+wz*azz.

camera to world space :
wx=px+cxaxx+cyayx+czazx;
wy=py+cx
axy+cyayy+czazy;
wz=pz+cxaxz+cyayz+cz*azz;

now we need to convert a screen pos to a camera space ray :
if your screen bounds ar -100,-100 to 100,100 (size 200*200 and origin at the center)

you can compute two rotation that should be applied to a vector starting from the cam and going along Z axis (forward)

rotY=(mouseXFOV0.5)/screenWith;
rotX=(mouseYFOV0.5)/screenHeight;

if mouse pos is 50,50 you get
rotx=5035/100 17.5°
roty=50
35/100 17.5°

apply those two rotations to the bullet vector BV(0,0,1);

convert it from camera to world space (and substract camera pos) and then ?!
you get the bullet vector in world space.

NB: double check if i dont make error on equation as this was written in a raw

Looks pretty sensible to me! I was thinking about that I wasnt exactly sure how to use vectors in Java though. I guess I best look into it :). Thanks for taking the time and writing that out for me!

better with a draw, you welcome nothing to do today :slight_smile:

Okay I just got the basic stuff done to get the screen moving with the arrow keys, etc.

Now for the maths. I am starting out just by trying to figure this out without the mouse. My goal is so once I press the spacebar a little plane appears in the center of my screen.

I’ve never used vectors in Java, or programming for that matter. Only math class(not a java class haha).
What information do I pass to these vectors exactly?
did I set them up correctly?


	private Vector xAxis = new Vector(3);
	private Vector yAxis = new Vector(3);
	private Vector zAxis = new Vector(3);

What advantages does a vector have over just using the camera variables? Man I feel so noob, but I guess this is how you learn! It’s just like an arraylist kinda… right?

what you were saying was?
ax(1,0,0) =>for axis X POSITION?
ay(0,1,0) =>for axis Y POSITION?
az(0,0,1) =>for axis Z POSITION?

Then I apply the rotation to this vector…How? and what does a rotation angle have to do with a location/how do they work together? then this transformation should be new vectors : PX, PY, PZ?

hmm…

Couldn’t I get the position of each screen coordinate(as it’s a plane in itself) TopLeft, TopRight, BottomLeft, BottomRight? then multiply it by the ratio used in the screen to mouse pose ratio(- the left most and bottommost co-ords)? Or is that what your doing? I’m lost a bit but I’m thinking I promise haha

Vector are not what you are looking for, Vector is more Collection/Enumeration.

from javadoc :

[quote]The Vector class implements a growable array of objects
[/quote]
below is a class that enable you to set a 3d point/vector and rotate, feel free to upgrade it.

the advantage can be that you will find a lot of usefull class to perform operations on your vector/point/axis/matrix and it will make the code smaller.

public class Point3D
{

public double x,y,z;

public Point3D rotate(double angle,double x,double y,double z)
{
		
	//normalize axis in case of
	double n=Math.sqrt(x*x+y*y+z*z);
	if(n==0.0) return this;
	double in=1.0/n;
	x*=in;
	y*=in;
	z*=in;
		
	double nzx=Math.sqrt(x*x+z*z);

	double rx=Math.asin(y);
	double ry=0;
	if(nzx!=0.0)
		{
		ry=-Math.acos(z/nzx);
		if(x<0)
		ry=-ry;
	}
	else
	{	if(y>0)
			rx=Math.PI*0.5;
		else
			rx=-Math.PI*0.5;
		ry=0;
	}
	//add here the -T translation for arbitrary axis (not starting at 0,0,0)
	this.rotateY(-ry);
	this.rotateX(-rx);
	this.rotateZ(angle);
	this.rotateX(rx);
	this.rotateY(ry);
	//add here the +T translation for arbitrary axis (not starting at 0,0,0)
	return this;
	
}

//rotate around world x axis
public Point3D rotateX(double angle)
{
	double tY=y,tZ=z;
	double cosa=Math.cos(angle);
	double sina=Math.sin(angle);
	y=tY*cosa + tZ*sina;
	z=-tY*sina + tZ*cosa;
	return this;
}
	
//rotate around world y axis
public Point3D rotateY(double angle)
{
	double tX=x,tZ=z;
	double cosa=Math.cos(angle);
	double sina=Math.sin(angle);
	x=tX*cosa - tZ*sina;
	z=tX*sina + tZ*cosa;
	return this;
}
	
//rotate around world z axis	
public Point3D rotateZ(double angle)
{
	double tY=y,tX=x;
	double cosa=Math.cos(angle);
	double sina=Math.sin(angle);
	x=tX*cosa + tY*sina;
	y=-tX*sina + tY*cosa;
	return this;
}
}

Ahhhh now I get it! Haha I was gonna say how on Earth would I do that with the Vector Class? haha, Thanks a bunch. I will most likely post next once it’s finished!

Well I got your algorithms to work perfectly! You obviously got your Algo’s down :smiley:

The only thing that is confusing me is how do I get say a point 25(units) away from this newly localized camera coord?

It should be fairly simple…
here’s what I have so far


		double SHOOT_DIST = 10;
		xAxis.rotateX(viewAngle);
		yAxis.rotateY(yAngle);
		zAxis.rotateZ(viewAngle);

		double wX = CameraX + (CameraX * xAxis.x) + (CameraY * yAxis.x) + (CameraZ * zAxis.x);
		double wY = CameraY + (CameraX * xAxis.y) + (CameraY * yAxis.y) + (CameraZ * zAxis.y);
		double wZ = CameraZ + (CameraX * xAxis.z) + (CameraY * yAxis.z) + (CameraZ * zAxis.z);
		double farX = wX + (Math.cos( Math.toRadians(viewAngle)) * SHOOT_DIST);
		double farZ = wZ + (Math.sin( Math.toRadians(viewAngle)) * SHOOT_DIST);
                //I don't understand how to get the NEW Y value

edit: but then I just realized I see no point in doing any of this? if the center of the screen is always where your firing from and you already know the angle your screen is at…then why do any of this? I am just confused in general.

[quote]edit: but then I just realized I see no point in doing any of this? if the center of the screen is always where your firing from and you already know the angle your screen is at…then why do any of this? I am just confused in general.
[/quote]
true if you always fire at the center of the screen, this method explain how to fire to an arbitrary screen pos. for example if you have a shootgun it is interresting to fire a cupple of bullet in different direction near the center but not liying on it.

that’s seems wrong :

probably something like :

xAxis.rotateX(xAngle);
xAxis.rotateY(yAngle);
yAxis.rotateX(xAngle);
yAxis.rotateY(yAngle);
zAxis.rotateX(xAngle);
zAxis.rotateY(yAngle);

that’s weird, cuz it’s pretty much working some how with just this…


		double SHOOT_DIST = 30;
		xAxis.rotateX(viewAngle);
		yAxis.rotateY(yAngle);
		zAxis.rotateZ(viewAngle);

		double wX = CameraX + (CameraX * xAxis.x) + (CameraY * yAxis.x) + (CameraZ * zAxis.x);
		double wY = CameraY + (CameraX * xAxis.y) + (CameraY * yAxis.y) + (CameraZ * zAxis.y);
		double wZ = CameraZ + (CameraX * xAxis.z) + (CameraY * yAxis.z) + (CameraZ * zAxis.z);
		double farX = wX + (Math.cos( Math.toRadians(viewAngle)) * SHOOT_DIST);
		double farZ = wZ + (Math.sin( Math.toRadians(viewAngle)) * SHOOT_DIST);
		double farY = wY + (Math.sin( Math.toRadians(yAngle)) * SHOOT_DIST);
		
		olinex = farX;oliney = farY;olinez = farZ;
		linex = wX;liney = wY;linez = wZ;

Yeah I see what you mean I just got reallly confused when all those calculations where done and it pretty much was my camera variables haha. I like it though, and I’m sure it’d be useful for AI aim as well. I’m gonna need to toy with this some more because I’m not sure if this is right but it looks pretty good.

Actually it’s not working yet haha. I’ll try it the way you suggested!

if you simply want to shoot from the center of the screen just do that to get your direction vector :


Point3D playerpos; (or cam...)
double ry,rx; (player rotation rx up/down ry left/right )
Point3D shootVector;
shootVector.x=0;
shootVector.y=0;
shootVector.z=1; //or distance depending on how you will use it

shootVector.rotateX(rx);
shootVector.rotateY(ry);
shootVector.x+=playerpos.x;
shootVector.y+=playerpos.y;
shootVector.z+=playerpos.z;

you bullet must start at playerpos and go toward shootVector

I thought I got your code to work, but then I realized I didn’t comment out my old code. I am still struggling and I don’t know why. Here’s what I’m trying now:


public void shoot(){
		double SHOOT_DIST = 30;
		shootVector.x = 0;
		shootVector.y = 0;
		shootVector.z = SHOOT_DIST;
		
		shootVector.rotateY(leftRightAngle);
		shootVector.rotateX(upDownAngle);
		
		shootVector.x += CameraX;
		shootVector.y += CameraY;
		shootVector.z += CameraZ;
		
		
		linex = CameraX;liney = CameraY;linez = CameraZ;
	}

I think the problem is with my rotations… Got any ideas?
ps linex, liney, and linez are just the co-ords I’m using to draw a GL_LINE object from the center of the screen to the new destination…

Nevermind I found out an easy way to do it. Just had to bust out my moms calc book.


		double SHOOT_DIST = 20;
		shootVector.x = CameraX + (Math.cos(Math.toRadians(leftRightAngle)) * SHOOT_DIST);
		shootVector.y = CameraY + ((Math.atan(upDownAngle/100)) * SHOOT_DIST);
		shootVector.z = CameraZ + (Math.sin(Math.toRadians(leftRightAngle)) * SHOOT_DIST);

I’m glad to see that opening my source code is sometimes useful for some people :smiley: The method to compute the impacts is not very accurate but it was enough when TUER supported only strictly orthogonal levels. Maybe you can use multi-pass rendering or multi-texturing and blending to change the appearance of a texture at run-time, it would be faster to precompute a finite set of textures that would represent the different steps of the impact and use alpha blending to use them anywhere and maybe modify the texture coordinates to avoid an ugly effect that is in TUER (the impacts go outside the walls).

I didn’t even know you are the writer of tuer! That’s so cool. That game is ace and an inspiration. Also I played DzzzD’s FPS demo on his web-site a little too.

Yes I did notice that sometimes it went into the wall, and sometimes over a corner marginally(but better than what I can come up with right now :D).

I know nothing of the methods you just mentioned. I can’t imagine it being easy to re-texture an object at run-time in retrospect. The game is going to be VERY simple meaning that the “textures” used at this point are going to be one solid color. I’m not sure if that makes this problem any easier to solve or not . Do you think Graphics2D would be too slow for this(if I had preloaded a splatter texture then just created an empty bufferedimage then created a tex while the bullet was still calculating)?

It would be so cool to have the blood/cube juice(lol) run down the wall, but I’m going to say that I’m getting ahead of myself, and dreaming further into a region I am more clueless about haha(perhaps a particle engine???).

I also need to find a fast (CLEAN)Ray + Cube/Box intersection algorithm which to my surprise is a bit harder to come by then I thought.

Don’t use Graphics2D, you don’t need it especially if you use JOGL.

Use JOPS for the particles. It is quite easy to implement blood juice by using precomputed animations as I do for the explosions but you have to resize them and USE POLYGON OFFSET. When I have more time, in some months, I will implement it in TUER.

You can find it on the web or adapt existing source code in C++ in the Nehe’s tutorial. Maybe I have what you’re looking for.