Game design : Smooth movement of an object

Hey guys,
I was coding brick breaker game and i have written code so as to move the paddle when the user presses LEFT/RIGHT arrow key.but it doesnt move smoothly… please help me to code it so as to move smoothly and one more thing - whenever i move the paddle, the ball in the game gets redrawn. I guess bricks also gets redrawn. I dont want that to happen is there any way i could bypass it??

/*Re-post
one more thing, if you observe the output, some bricks tend a bit offside(though x cordinates are same for every row) example, just see the red-row . Do you know why this happens?? are there any corrections ??
Here is the code
*/


#include<stdlib.h>
#include<dos.h>
#include<time.h>
#include<windows.h>
#include<stdio.h>
#include <cmath>
#include<GL/glut.h>
float fx1=46,ex1=114.9,fx2=115.9,ex2=184.8,fx3=185.8,ex3=254.7,fx4=255.7,ex4=324.6,fx5=325.6,ex5=394.5,fx6=395.5,ex6=464.4,fx7=465.4,ex7=534.3,fx8=535.3,ex8=604.2,fx9=605.2,ex9=674.1,fx10=675.1,ex10=744;

float fy1=700,ey1=670,fy2=668,ey2=638,fy3=636,ey3=606,fy4=604,ey4=574,fy5=572,ey5=542,fy6=540,ey6=510;

float bx=395,by=53;
float px=325,py=10,pz=0;
float move_unit = 1;
float dx=1;
float cx=3;
void keyboardown(int key, int x, int y)
{
    switch (key){
        case GLUT_KEY_RIGHT:
			for(int i=0;i<25;i++)
            px+=move_unit*dx*cx;;
            break;

        case GLUT_KEY_LEFT:
           for(int i=0;i<25;i++)
            px-=move_unit*dx*cx;;
        break;

       default:
         break;
    }
    glutPostRedisplay();
}

void border()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glLineWidth(30);
	glColor3f(0.4,0.4,0.4);
	glBegin(GL_LINE_STRIP);
	glVertex2f(30,5);
	glVertex2f(30,770);
	glVertex2f(760,770);
	glVertex2f(760,5);
	glEnd();
	glColor3f(1,1,1);
	glLineWidth(2);
	glBegin(GL_LINES);
	glVertex2f(20,5);
	glVertex2f(20,765);
	glEnd();
	glBegin(GL_LINES);
	glVertex2f(30,780);
	glVertex2f(750,780);
	glEnd();
	glBegin(GL_LINES);
	glVertex2f(750,5);
	glVertex2f(750,730);
	glEnd();
	glPointSize(2);
	glBegin(GL_POINTS);
	glVertex2f(750,735);
	glVertex2f(750,740);
	glEnd();
	glutSwapBuffers();
	glFlush();
}
void outtext(char *string,float x,float y) 
{ 
char *c;
glRasterPos2f(x,y);
for (c=string; *c != '\0'; c++) 
{
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *c);
}
}
void waitFor(unsigned int secs) {
    int retTime = time(0) + secs;     
    while (time(0) < retTime);    
}
void scoreboard()
{
	glColor3f(1,0,0);
	outtext("Score:",820,700);
	glutSwapBuffers();
	waitFor(5);
	glColor3f(0,0,0);
	outtext("Score:",820,700);
	glColor3f(1,0,0);
	outtext("Test",820,700);
	glutSwapBuffers();
}
void bricks()
{
	{
		glLineWidth(30);
		glColor3f(0.5,0.5,0.5);
		glBegin(GL_LINES);
		glVertex2f(fx1,fy1);
		glVertex2f(ex1,fy1);
		glVertex2f(fx2,fy1);
		glVertex2f(ex2,fy1);
		glVertex2f(fx3,fy1);
		glVertex2f(ex3,fy1);
		glVertex2f(fx4,fy1);
		glVertex2f(ex4,fy1);
		glVertex2f(fx5,fy1);
		glVertex2f(ex5,fy1);
		glVertex2f(fx6,fy1);
		glVertex2f(ex6,fy1);
		glVertex2f(fx7,fy1);
		glVertex2f(ex7,fy1);
		glVertex2f(fx8,fy1);
		glVertex2f(ex8,fy1);
		glVertex2f(fx9,fy1);
		glVertex2f(ex9,fy1);
		glVertex2f(fx10,fy1);
		glVertex2f(ex10,fy1);
		glEnd();
		
		glColor3f(0.8,0.2,0);
		glBegin(GL_LINES);
		glVertex2f(fx1,fy2);
		glVertex2f(ex1,fy2);
		glVertex2f(fx2,fy2);
		glVertex2f(ex2,fy2);
		glVertex2f(fx3,fy2);
		glVertex2f(ex3,fy2);
		glVertex2f(fx4,fy2);
		glVertex2f(ex4,fy2);
		glVertex2f(fx5,fy2);
		glVertex2f(ex5,fy2);
		glVertex2f(fx6,fy2);
		glVertex2f(ex6,fy2);
		glVertex2f(fx7,fy2);
		glVertex2f(ex7,fy2);
		glVertex2f(fx8,fy2);
		glVertex2f(ex8,fy2);
		glVertex2f(fx9,fy2);
		glVertex2f(ex9,fy2);
		glVertex2f(fx10,fy2);
		glVertex2f(ex10,fy2);
		glEnd();
		
		glColor3f(0,0.5,0.8);
		glBegin(GL_LINES);
		glVertex2f(fx1,fy3);
		glVertex2f(ex1,fy3);
		glVertex2f(fx2,fy3);
		glVertex2f(ex2,fy3);
		glVertex2f(fx3,fy3);
		glVertex2f(ex3,fy3);
		glVertex2f(fx4,fy3);
		glVertex2f(ex4,fy3);
		glVertex2f(fx5,fy3);
		glVertex2f(ex5,fy3);
		glVertex2f(fx6,fy3);
		glVertex2f(ex6,fy3);
		glVertex2f(fx7,fy3);
		glVertex2f(ex7,fy3);
		glVertex2f(fx8,fy3);
		glVertex2f(ex8,fy3);
		glVertex2f(fx9,fy3);
		glVertex2f(ex9,fy3);
		glVertex2f(fx10,fy3);
		glVertex2f(ex10,fy3);
		glEnd();
		
		glColor3f(1.0, 0.45, 0.00);
		glBegin(GL_LINES);
		glVertex2f(fx1,fy4);
		glVertex2f(ex1,fy4);
		glVertex2f(fx2,fy4);
		glVertex2f(ex2,fy4);
		glVertex2f(fx3,fy4);
		glVertex2f(ex3,fy4);
		glVertex2f(fx4,fy4);
		glVertex2f(ex4,fy4);
		glVertex2f(fx5,fy4);
		glVertex2f(ex5,fy4);
		glVertex2f(fx6,fy4);
		glVertex2f(ex6,fy4);
		glVertex2f(fx7,fy4);
		glVertex2f(ex7,fy4);
		glVertex2f(fx8,fy4);
		glVertex2f(ex8,fy4);
		glVertex2f(fx9,fy4);
		glVertex2f(ex9,fy4);
		glVertex2f(fx10,fy4);
		glVertex2f(ex10,fy4);
		glEnd();

		glColor3f(0.9,0,0.7);
		glBegin(GL_LINES);
		glVertex2f(fx1,fy5);
		glVertex2f(ex1,fy5);
		glVertex2f(fx2,fy5);
		glVertex2f(ex2,fy5);
		glVertex2f(fx3,fy5);
		glVertex2f(ex3,fy5);
		glVertex2f(fx4,fy5);
		glVertex2f(ex4,fy5);
		glVertex2f(fx5,fy5);
		glVertex2f(ex5,fy5);
		glVertex2f(fx6,fy5);
		glVertex2f(ex6,fy5);
		glVertex2f(fx7,fy5);
		glVertex2f(ex7,fy5);
		glVertex2f(fx8,fy5);
		glVertex2f(ex8,fy5);
		glVertex2f(fx9,fy5);
		glVertex2f(ex9,fy5);
		glVertex2f(fx10,fy5);
		glVertex2f(ex10,fy5);
		glEnd();

		glColor3f(0,0.9,0);
		glBegin(GL_LINES);
		glVertex2f(fx1,fy6);
		glVertex2f(ex1,fy6);
		glVertex2f(fx2,fy6);
		glVertex2f(ex2,fy6);
		glVertex2f(fx3,fy6);
		glVertex2f(ex3,fy6);
		glVertex2f(fx4,fy6);
		glVertex2f(ex4,fy6);
		glVertex2f(fx5,fy6);
		glVertex2f(ex5,fy6);
		glVertex2f(fx6,fy6);
		glVertex2f(ex6,fy6);
		glVertex2f(fx7,fy6);
		glVertex2f(ex7,fy6);
		glVertex2f(fx8,fy6);
		glVertex2f(ex8,fy6);
		glVertex2f(fx9,fy6);
		glVertex2f(ex9,fy6);
		glVertex2f(fx10,fy6);
		glVertex2f(ex10,fy6);
		glEnd();
	}
	glutSwapBuffers();
}
void draw(float x,float y)
{
	glColor3f(0.7,0.3,0.1);
	
	glBegin(GL_POINTS);
	glVertex2f(x,y);
	glEnd();
	glutSwapBuffers();
}
void plot(int h,int k,int x,int y)
{
	draw(x+h,y+k);
	draw(-x+h,y+k);
	draw(x+h,-y+k);
	draw(-x+h,-y+k);
	draw(y+h,x+k);
	draw(-y+h,x+k);
	draw(y+h,-x+k);
	draw(-y+h,-x+k);
}
void ball(int h,int k,int r)
{
	int x=0,d=1-r,y=r;
	
	{
	while(y>x)
	{
		plot(h,k,x,y);
		if(d<0)
			d+=2*x+3;
		else
		{
			d+=2*(x-y)+5;
			--y;
		}
		++x;
	}
	plot(h,k,x,y);
	glutSwapBuffers();
	}
}
void paddle()
{
	glLineWidth(4);
	glColor3f(0.7,0.7,0.7);
	if (px>=46&&px<=604)
	{
	glBegin(GL_LINE_LOOP);
	glVertex2f(px,py);
	glVertex2f(px,py+40);
	glVertex2f(px+20,py+40);
	glVertex2f(px+30,py+30);
	glVertex2f(px+110,py+30);
	glVertex2f(px+120,py+40);
	glVertex2f(px+140,py+40);
	glVertex2f(px+140,py);
	glVertex2f(px+120,py);
	glVertex2f(px+110,py+10);
	glVertex2f(px+30,py+10);
	glVertex2f(px+20,py);
	glEnd();
	glutSwapBuffers();
	}
	else if(px<46)
	{
	px=48,py=10;
	glBegin(GL_LINE_LOOP);
	glVertex2f(px,py);
	glVertex2f(px,py+40);
	glVertex2f(px+20,py+40);
	glVertex2f(px+30,py+30);
	glVertex2f(px+110,py+30);
	glVertex2f(px+120,py+40);
	glVertex2f(px+140,py+40);
	glVertex2f(px+140,py);
	glVertex2f(px+120,py);
	glVertex2f(px+110,py+10);
	glVertex2f(px+30,py+10);
	glVertex2f(px+20,py);
	glEnd();
	glutSwapBuffers();
	}
	else if(px>604)
	{
	px=602,py=10;
	glBegin(GL_LINE_LOOP);
	glVertex2f(px,py);
	glVertex2f(px,py+40);
	glVertex2f(px+20,py+40);
	glVertex2f(px+30,py+30);
	glVertex2f(px+110,py+30);
	glVertex2f(px+120,py+40);
	glVertex2f(px+140,py+40);
	glVertex2f(px+140,py);
	glVertex2f(px+120,py);
	glVertex2f(px+110,py+10);
	glVertex2f(px+30,py+10);
	glVertex2f(px+20,py);
	glEnd();
	glutSwapBuffers();
	}
}
void display()
{
	glClear(GL_COLOR_BUFFER_BIT);
	border();
	bricks();
	glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
	glPushMatrix();
    paddle();
	glTranslatef(px,py,pz);
	glPopMatrix();
	ball(bx,by,10);
	glutSwapBuffers();
}

void init()
{
	glClearColor(0,0,0,0);
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(0,1199,0,799);
}
void main(int argc,char **argv)
{
	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
	glutInitWindowSize(1200,800);
	glutCreateWindow("Arkanoid");
	glutDisplayFunc(display);
	init();
	glutSpecialFunc(keyboardown);
	glutMainLoop();
}

void keyboardown(int key, int x, int y)
{
    switch (key){
        case GLUT_KEY_RIGHT:
			for(int i=0;i<25;i++)
            px+=move_unit*dx*cx;;
            break;
 
        case GLUT_KEY_LEFT:
           for(int i=0;i<25;i++)
            px-=move_unit*dx*cx;;
        break;
 
       default:
         break;
    }
    glutPostRedisplay();
}

the loops in the case statements are useless, you will only see the result of the final px += 25 * move_unit * dx * cx; because there are never any images drawn with any of the intermediate values. Similarly, you don’t want to call glutSwapBuffers() in the functions that draw pieces of your scene (e.g. paddle() or ball()). Instead, draw a full frame of your scene, then call glutSwapBuffers().

To move objects smoothly you could keep track of which keys are currently pressed and each frame move the paddle by a small amount based on which keys are down. You get even smoother motion if you apply some simple form of acceleration to the paddle so that in the first few frames a key is pressed the movement distance is smaller and slowly increases up to a max. You probably also want to make the movement speed independent of your framerate (search the forums, there are threads with more details on this). For that keep track of how much time has elapsed since the last frame and use that to scale the movement distance.

Many applications redraw the whole scene for each frame, that is quite a common approach as there is often not much/anything that is static between frames (especially if the camera moved). Your application probably has some static elements, so you could draw those into a texture using a FBO and then just draw the texture to restore the static elements. I would only recommend that if profiling shows it’s worth the effort - your program has plenty of optimization potential before that, e.g. get rid of immediate mode rendering (glBegin/glEnd) and use buffer objects (keyword: VBO).

[QUOTE=carsten neumann;1250434]


void keyboardown(int key, int x, int y)
{
    switch (key){
        case GLUT_KEY_RIGHT:
			for(int i=0;i<25;i++)
            px+=move_unit*dx*cx;;
            break;
 
        case GLUT_KEY_LEFT:
           for(int i=0;i<25;i++)
            px-=move_unit*dx*cx;;
        break;
 
       default:
         break;
    }
    glutPostRedisplay();
}

the loops in the case statements are useless, you will only see the result of the final px += 25 * move_unit * dx * cx; because there are never any images drawn with any of the intermediate values. Similarly, you don’t want to call glutSwapBuffers() in the functions that draw pieces of your scene (e.g. paddle() or ball()). Instead, draw a full frame of your scene, then call glutSwapBuffers().

To move objects smoothly you could keep track of which keys are currently pressed and each frame move the paddle by a small amount based on which keys are down. You get even smoother motion if you apply some simple form of acceleration to the paddle so that in the first few frames a key is pressed the movement distance is smaller and slowly increases up to a max. You probably also want to make the movement speed independent of your framerate (search the forums, there are threads with more details on this). For that keep track of how much time has elapsed since the last frame and use that to scale the movement distance.

Many applications redraw the whole scene for each frame, that is quite a common approach as there is often not much/anything that is static between frames (especially if the camera moved). Your application probably has some static elements, so you could draw those into a texture using a FBO and then just draw the texture to restore the static elements. I would only recommend that if profiling shows it’s worth the effort - your program has plenty of optimization potential before that, e.g. get rid of immediate mode rendering (glBegin/glEnd) and use buffer objects (keyword: VBO).[/QUOTE]

Hey, Thanks for your reply…
i was trying to make it smooth so i introduced for() which was of no use…
anyhow … thanks for clearing me with glutSwapBuffers().(So, if i call glutSwapBuffers once at end of display() its ok right??. :confused: )currently, my ball getting redrawn has stopped since i removed glutSwapBuffers() everywhere else except display(). i will try to make it smooth as you said by modifying its code tomorrow :slight_smile: Thanks bro :slight_smile: :slight_smile: