smooth keyboard movement

Started by
15 comments, last by littlekid 17 years, 11 months ago
hi i am making a 2d rpg game in opengl. the game works fine, except the keyboard function. when my character moves in one direction for a while, it looks ok. as soon as i change the direction, there is a sudden jerk then it continues to be smooth. my question is how do i make it completely smooth. my keyboard code is: switch(key) { case GLUT_KEY_RIGHT : hero_addx=-hero.speed; hero_addy=0; hero.drawy =1; if (!collision_check(tx+1.0f,ty)) { for (u=0;u<10;u++) { Sleep(15); // slow to show the animation hero.x += hero.speed; hero.motion(); // change sprite animation display_gamemode(); // re-render scene } } break; i think the sleep function is messing up the smoothness. is there any better method of moving the character smoothly? Is it possible to move the character in my code without the whole "for loop"? hope this is clear :)
Advertisement
What do you mean by sudden jerk?

I also like to add that having any rendering code in your input is general bad design. I n general you would want you game game loop to be in distinct steps, check input, process data (Such as animation, collision) and render to the screen.

Steven Yau
[Blog] [Portfolio]

Not really a jerk but as soon as I press another button, the character stops in a tile for a quick second then moves. I don’t’ want him to have that small freeze. As soon as I press a another button he should move RIGHT away, with no small freeze
In that case I would guess that it is your for loop inside the case statement causing you grief. I cant tell until I see the rest of the game loop.

Eg.you press right, the game hits the for loop. While it is still processing the for statement (10 loops), you press left but since it still is in the eight keypresses for loop, it looks like the game is non responsive.

Steven Yau
[Blog] [Portfolio]

is there any way to do this without the "for loop"? i read something about QueryPerformanceCounter and GetTickCount and those in a game loop. can i apply those somehow? also is there a way to read information from keyabord and not register it until a certain condition is met?
Ignoring the timer questions (dont want to start introducing more problems and not needed at this stage), in a nutshell:

Start of game loop If condition is met then  Process game input else do nothing Process animation for next frame Render to scene Sleep(15)End Game loop


Althougth depending on what that condition is, it might be better if it was in the object's class/function call if it is directly related to the object rather then the general game code.

Steven Yau
[Blog] [Portfolio]

Make the animation move a certain speed in pixels/second or grid/second.
Don't tie it in with the framerate.
Seconds are the same on all the computers..

For example, make the key only toggle a "Direction" variable,
and then make the Move routine be called aways once per frame.

Then do this:

Move(){  switch(Player->Direction)  {    case DIR_LEFT:      Player.MoveX(Player.Speed);      break;    case DIR_RIGHT:      Player.MoveX(Player.Speed);      break;    [...]    case DIR_DOWN:      Player.MoveY(Player.Speed);      break;    default:      //no processing;      break;  }}


In the MoveX/Y function you move the player depending on his speed
AND how much time has actually passed till last frame:
distance = time * speed;

Hope this helps.
[edit reason: not too helpful the first time]
ttdeath, can u elaborate how to move a pixel by pixel/sec or gird/sec. all i do is
herox = herox +1; and the render like draw(herox,heroy);

what do u mean by don't tie it in with framerate?

u said "each frame rate", how do i know each frame rate in a game loop?
using a Sleep() in a game loop pauses the game for a certain amount out time, say 7 sec. but then sometimes i need to update different sprites at differnt speed. like change water tile every 5 sec while the chracter animation moves every 2 sec. these two things need to be updated at differnt time, but the sleep() in the loop pauses for the 1 sec, so it does update the character animation or water tile in time. is there a method to keep updating everything differnt sprites at different time or am i just understaing this whole concept rong?
I see you are using glut. You may be relying on your operating system key repeat speed. This would cause a "jerk" when you change directions, if I understand you correctly. You press 'd' for example to start smoothly going right. It moves one space right, pauses, and then smoothly scrolls right. Is this what you are experiencing?

If so, you may be interested in this code. Try it out and see for yourself. You will see nice smooth camera movements using the keyboard although key repeat is turned off in glut.

#include <math.h>#include <GL/glut.h>#include <stdlib.h>float angle=0.0,deltaAngle = 0.0,ratio;float x=0.0f,y=1.75f,z=5.0f;float lx=0.0f,ly=0.0f,lz=-1.0f;GLint snowman_display_list;int deltaMove = 0;void changeSize(int w, int h)	{	// Prevent a divide by zero, when window is too short	// (you cant make a window of zero width).	if(h == 0)		h = 1;	ratio = 1.0f * w / h;	// Reset the coordinate system before modifying	glMatrixMode(GL_PROJECTION);	glLoadIdentity();		// Set the viewport to be the entire window    glViewport(0, 0, w, h);	// Set the clipping volume	gluPerspective(45,ratio,1,1000);	glMatrixMode(GL_MODELVIEW);	glLoadIdentity();	gluLookAt(x, y, z, 		      x + lx,y + ly,z + lz,			  0.0f,1.0f,0.0f);	}void drawSnowMan() {	glColor3f(1.0f, 1.0f, 1.0f);// Draw Body		glTranslatef(0.0f ,0.75f, 0.0f);	glutSolidSphere(0.75f,20,20);// Draw Head	glTranslatef(0.0f, 1.0f, 0.0f);	glutSolidSphere(0.25f,20,20);// Draw Eyes	glPushMatrix();	glColor3f(0.0f,0.0f,0.0f);	glTranslatef(0.05f, 0.10f, 0.18f);	glutSolidSphere(0.05f,10,10);	glTranslatef(-0.1f, 0.0f, 0.0f);	glutSolidSphere(0.05f,10,10);	glPopMatrix();// Draw Nose	glColor3f(1.0f, 0.5f , 0.5f);	glRotatef(0.0f,1.0f, 0.0f, 0.0f);	glutSolidCone(0.08f,0.5f,10,2);}GLuint createDL() {	GLuint snowManDL;	// Create the id for the list	snowManDL = glGenLists(1);	// start list	glNewList(snowManDL,GL_COMPILE);	// call the function that contains the rendering commands		drawSnowMan();	// endList	glEndList();	return(snowManDL);}void initScene() {	glEnable(GL_DEPTH_TEST);	snowman_display_list = createDL();}void orientMe(float ang) {	lx = sin(ang);	lz = -cos(ang);	glLoadIdentity();	gluLookAt(x, y, z, 		      x + lx,y + ly,z + lz,			  0.0f,1.0f,0.0f);}void moveMeFlat(int i) {	x = x + i*(lx)*0.1;	z = z + i*(lz)*0.1;	glLoadIdentity();	gluLookAt(x, y, z, 		      x + lx,y + ly,z + lz,			  0.0f,1.0f,0.0f);}void renderScene(void) {	if (deltaMove)		moveMeFlat(deltaMove);	if (deltaAngle) {		angle += deltaAngle;		orientMe(angle);	}	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Draw ground	glColor3f(0.9f, 0.9f, 0.9f);	glBegin(GL_QUADS);		glVertex3f(-100.0f, 0.0f, -100.0f);		glVertex3f(-100.0f, 0.0f,  100.0f);		glVertex3f( 100.0f, 0.0f,  100.0f);		glVertex3f( 100.0f, 0.0f, -100.0f);	glEnd();// Draw 36 SnowMen	for(int i = -3; i < 3; i++)		for(int j=-3; j < 3; j++) {			glPushMatrix();			glTranslatef(i*10.0,0,j * 10.0);			glCallList(snowman_display_list);;			glPopMatrix();		}	glutSwapBuffers();}void pressKey(int key, int x, int y) {	switch (key) {		case GLUT_KEY_LEFT : deltaAngle = -0.01f;break;		case GLUT_KEY_RIGHT : deltaAngle = 0.01f;break;		case GLUT_KEY_UP : deltaMove = 1;break;		case GLUT_KEY_DOWN : deltaMove = -1;break;	}}void releaseKey(int key, int x, int y) {	switch (key) {		case GLUT_KEY_LEFT : 		case GLUT_KEY_RIGHT : deltaAngle = 0.0f;break;		case GLUT_KEY_UP : 		case GLUT_KEY_DOWN : deltaMove = 0;break;	}}void processNormalKeys(unsigned char key, int x, int y) {	if (key == 27) 		exit(0);}int main(int argc, char **argv){	glutInit(&argc, argv);	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);	glutInitWindowPosition(100,100);	glutInitWindowSize(640,360);	glutCreateWindow("SnowMen from Lighthouse 3D");	initScene();	glutIgnoreKeyRepeat(1);	glutKeyboardFunc(processNormalKeys);	glutSpecialFunc(pressKey);	glutSpecialUpFunc(releaseKey);	glutDisplayFunc(renderScene);	glutIdleFunc(renderScene);	glutReshapeFunc(changeSize);	glutMainLoop();	return(0);}
btw, this is tile based 2d rpg game like pokemon, or zelda ,so i want a constant moving speed.

This topic is closed to new replies.

Advertisement