Sign in to follow this  
cozzie

"Shocking" movement

Recommended Posts

Hi, After digging back into math, I think I've got my movement in my 3d engine working fine, mathematically. Although, my free mouselook looks a bit "shocking", it's not really smooth. Is there someone willing to take a look at my "movement"-code, and/or maybe check this little demo: http://www.sierracosworth.nl/engine-tst2.zip (mouselook, W/S/A/D, T/G, F1=fullscreen, F2 and more = effects on/off) All suggestions and help is welcome. Here's the source-code (parts related to movement/mouselook). "main" input checking:
			if(input->buffer[DIK_W] || input->buffer[DIK_UP] & 0x80)				{
				scene->cam->pos.x += (float)sin(scene->cam->rot.y*piover180) * moveSpeed;
				scene->cam->pos.z -= (float)cos(scene->cam->rot.y*piover180) * moveSpeed;
			}
			if(input->buffer[DIK_S] || input->buffer[DIK_DOWN] & 0x80)				{
				scene->cam->pos.x -= (float)sin(scene->cam->rot.y*piover180) * moveSpeed;
				scene->cam->pos.z += (float)cos(scene->cam->rot.y*piover180) * moveSpeed;
			}

			if(input->buffer[DIK_A] || input->buffer[DIK_LEFT] & 0x80)				{
				scene->cam->pos.x -= (float)sin((scene->cam->rot.y+90.0f)*piover180) * moveSpeed;
				scene->cam->pos.z += (float)cos((scene->cam->rot.y+90.0f)*piover180) * moveSpeed;
			}
			if(input->buffer[DIK_D] || input->buffer[DIK_RIGHT] & 0x80)				{
				scene->cam->pos.x -= (float)sin((scene->cam->rot.y-90.0f)*piover180) * moveSpeed;
				scene->cam->pos.z += (float)cos((scene->cam->rot.y-90.0f)*piover180) * moveSpeed;
			}
			input->CheckMouseState(turnAngle, &scene->cam->rot.x, &scene->cam->rot.y);


Specific mouselook function:
void GLdinput::CheckMouseState(float angle, float *camXrot, float *camYrot)
{
	GetCursorPos(&mpos);	
	*camYrot -= ((float)((screenWidth/2 - mpos.x)) * angle); // / (screenwidth / 5.2);
	*camXrot += (float)(mpos.y - screenHeight/2) * angle;

//	if(mpos.x < (float)screenWidth/2) *camYrot-=angle;
//	else if(mpos.x > (float)screenWidth/2) *camYrot+=angle;

//	if(mpos.y < (float)screenHeight/2) *camXrot-=angle;
//	else if(mpos.y > (float)screenHeight/2) *camXrot+=angle;

//	if(*camXrot > 360) *camXrot = 0;
//	if(*camXrot < 0) *camXrot = 360;

//	if(*camYrot > 360) *camYrot = 0;
//	if(*camYrot < 0) *camYrot = 360;

	SetCursorPos(screenWidth/2, screenHeight/2);	
}


Rendering the 3d scene:
int GLscene::Render(int width, int height)
{
	static int mc, oc;
	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();						

	glRotatef(cam->rot.x, 1, 0, 0);
	glRotatef(cam->rot.y, 0, 1, 0);

	glTranslatef(-cam->pos.x, -cam->pos.y, -cam->pos.z);

	frustum.CalculateFrustum();
      
        ...position lightsources
        ...draw all objects if they're in the frustum


Share this post


Link to post
Share on other sites
I dont see any problems with your mouselook
it didn't seem jerky or anything strange to me.

Maybe you have some kind of framerate issues that don't show up for me?
if your movement calculation is framerate dependant and your screen is getting choppy you might need to measure the change and compensate for your motions
(have a time factor in those calculations)

Your mouselook seems pretty standard for most fps games, perhaps your complaint is that motion is directly linked to the mouse? -jerky mouse motion translates to jerky screen, with no smoothing out?

a quick way to add this is have a separate camera rotation varible from the mouse rotation variables
and instead of having them match all the time make the camera only move 90%(adjustable) of the way to where the mouse is
a more complicated way to do it is the have your camera be physically simulated with angular momentum and whatnot, so that instead of turning instantly it takes time for it to change direction...

P.S.
zomg! I can walk through the walls

and your skybox, should probably be rendered before all the camera translations, this way it stays as if it was an infinite distance in the sky...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Same anonymous.

I'm running a 2GHz P4 HP Laptop (I know, don't laugh, it's 'cause it has a numeric keypad), and anyway, it looks fine to me, just a tiny bit of shudder.

I think your code is working, using GetMousePos() and SetMousePos()
isn't quite what you want, race condition and all.
(it would be nicer if windows let you do both at once).

You might try to smooth out the input somehow, but anything you try
will cause movement to be less responsive in some sense.

I'd suggest reverse engineering something like Counter Strike's mouselook behavior, see if that gives you any ideas. I don't play games with
mouselook myself, so that's all I've got for you.

Share this post


Link to post
Share on other sites
Thanks guys, for testing.
I think I'll try something with the separate mouse camera-rotation variable.

I think walking trough the walls is because I don't have any collision detection yet ;-)

And timebased movement is my next step...
I thought it would be something like this:

- before everything is rendered in the renderloop: get the current time (1)
- after everything's rendered: get the current time (2)
- time2 - time1 = frametime
- say tat I want the movement speed allways to be 1.0 undependent of system performance, I could measure every 5 frametimes and say that:
totalFrameTime / 5 is the average time that's needed per frame.

So then I know 2 variables: averagetime needed per frame, and the static 1.0 units I want to move per second.

I can't figure it out how to calculatie the moveSpeed from those 2 variables.
Anyone?
(probably a simple answer, but it just not coming to me)

Share this post


Link to post
Share on other sites
It is not the movement speed that should be adapted. The velocity (i.e. scalar speed multiplied by movement direction vector) should be given e.g. by user input. I also suggest not to measure the time before and after rendering, but at one defined point in the loop: At the beginning of updating the game's state. So you get the elapsed time independent also of rendering duration.

Assuming that the velocity is constant during the next frame (or frames, how long ever the rendering would take) the updated position of a figure would be
new_pos := current_pos + velocity * duration
where duration is the time elapsed since the last recent time picking (see above). After doing some collision detection and such, the new_pos is finally calculated. Then
current_pos := new_pos
This is in fact an integration of the velocity over time, naturally yielding in a position. However, you are able to change the velocity in magnitude and direction at each run through the loop, of course, dependent on user input or so.

EDIT: Going the other way, i.e. _interpolating_ the position at a given moment, is needed only if you want the figure reach a defined location at a defined moment. That is less often needed. If you have such an requirement let us know.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I just tried it out on my GF's comp (2.6 ghz Celeron, 256 megs ram, onboard video, windows xp) your mouselook seems fine. Maybe a touch sensative for most people, but just about right where i like it. However, none of the keys you listed other than wasd did -anything-, and if you alt tabbed out of the window it still retained control over your mouse, which was very annoying.

Share this post


Link to post
Share on other sites
Sorry about the mouselook, when alt-tabbing ;-)

Haphazardlynamed: sounds like a really big issue, I don't know if my problem is the same as your explanation solves.
I have one float variable moveSpeed, which says how many units the position of the camera's should change when the user moves the player/camera.

What I'm trying to do is change that float variable moveSpeed in relation to the number of fps, to achieve the same movement speed on every system/pc.

Share this post


Link to post
Share on other sites
Quote:
Original post by cozzie
What I'm trying to do is change that float variable moveSpeed in relation to the number of fps, to achieve the same movement speed on every system/pc.

Please notice my post above!

If your figure goes 1 meter per second, and you render 50 frames per second, how fast does your figure go if you render only 25 frames per second? It still has a speed of 1 meter per second. Why do you want to define the speed in dependence of an uncontrollable unit like frame duration? On each computer a second is a second (more or less ;-), so I strongly suggest you to define the speed w.r.t. seconds as a good example for a _fixed_ time duration.

You could not say "0.1 meters per frame" since the frame duration is artificial and unknown. You could say "0.1 meters per frame at a framerate of 50 frames per second", but if you multiply that out you will see that you actually would have said: "5 meters per second".

What you actually want to achieve is a smooth movement, much as independent of the computer's power as possible, and that means the gone way distance during the frame-to-frame duration. The speed is automatically hold constant since it is the quotient of distance and duration.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this