Jump to content
  • Advertisement
Sign in to follow this  
tomba

smooth keyboard movement

This topic is 4430 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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 :)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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);
}


Share this post


Link to post
Share on other sites
btw, this is tile based 2d rpg game like pokemon, or zelda ,so i want a constant moving speed.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!