asteroids

Hi. I’m just starting my OpenGL adventure. Could someone help me with the code of how to make an object fly across the screen (i.e. a flying bullet). I have my spaceship flying around nicely but when I fire a bullet it only appears at its original location and then its ending location. I don’t see it animate (or fly) through the screen. I mean shouldn’t the glutPostRedisplay() function call in my keyboard() function render the bullet at each point? Here’s some of my code:


void display(void)
{
	int i=0;
	glClear (GL_COLOR_BUFFER_BIT);
 	init();
	glColor3f(1.0,1.0,1.0);
	
	glLoadIdentity();
	glPushMatrix();

        //translate and rotate spaceship
	glTranslatef(speedX, speedY, 0.0);
	glRotatef(angle, 0.0, 0.0, 1.0);

        //draw spaceship
	glColor3f(1.0,1.0,1.0);
	glBegin(GL_POLYGON);
		glVertex2f(-1.0, 0.0);
		glVertex2f(1.0, 1.0);
		glVertex2f(1.0, -1.0);
	glEnd();
	glPopMatrix();

	glPointSize(4.0);
	glColor3f(1.0,0.0,0.0);	

        //translate and draw bullet
	glTranslatef(bulletX, bulletY, 0.0);
	glBegin(GL_POINTS);
		glVertex2f(0.0,0.0);
	glEnd();
		
	}
	glutSwapBuffers();
}

...

void specialKeys (int key, int x, int y)
{
   switch (key) {
      case GLUT_KEY_UP: 
         speedX -= .05*cos(angle*PI/180);
	 speedY -= .05*sin(angle*PI/180);
         glutPostRedisplay();
         break;

...

void keyboard(unsigned char key, int x, int y)
{
	int i;
	switch(key)
	{
		case ' ':
			for(i=0; i<10; i++)
			{
			bulletX -= 0.5*cos(angle*PI/180);
			bulletY -= 0.5*sin(angle*PI/180);
			glutPostRedisplay();
			}
		break;

...

when I fire a bullet it only appears at its original location and then its ending location.

I don’t see anything in the code that defines an ending location. You’re simply adding a vector to the bullet’s position indefinitely.

Or rather, just once:

I mean shouldn’t the glutPostRedisplay() function call in my keyboard() function render the bullet at each point?

Why would it?

display() only gets called as needed. The same goes with keyboard() and specialKeys(). In these cases, they get called only when the user presses a key. So unless you actually press a key, the object won’t move.

If you want to do animation in FreeGLUT, the right way to do it is to just call “glutPostRedisplay()” at the end of the “display()” function. Of course, you’ll also need to use FreeGLUT to check the time difference between the last display call, so that you can scale the speed properly.

Bullet if flying across the screen in <= 10 frames (10 loops in your ‘keyboard’ function).
You have very little amount of geometry, so You are probably getting high framerate (I assume You are calling glutPostRedisplay somewhere in main loop).
I suppose that your bullet is there, but it flies so fast that You are unable to see it (~0.17s on 60fps)

btw. You should not block in keyboard function (set some flag, and move bullet in display function)

The frame rate isn’t the problem as I added this j loop to my code and when I fire, the bullet waits for about a second and then appears at the end (10 translations down):


case ' ':
for(i=0; i<10; i++)	
{
  for(j=0; j<10000000;j++);
  bulletX -= 0.5*cos(angle*PI/180);
  bulletY -= 0.5*sin(angle*PI/180);
  glutPostRedisplay();
}

The bullet’s position should be incremented 10 times by .5cos(anglePI/180) and drawn every time because of glutPostRedisplay(). However it only appears in the beginning and then when I fire it it appears 10 translations down. It doesn’t draw each translation in between.

Use glutTimerFunc for timing, or simple sleep(), busy loop is bad idea for at least 3 reasons:

  1. Wastes precious cpu time
  2. Speed will be different on various cpus
  3. Can be optimized out by compiler

edit: (my previous explaination was totally wrong)

this should work:
I don’t use glut, but it’s probably one-threaded library.
glutPostRedisplay doesn’t call display function, it just adds redisplay command to the queue.
If You are sitting in keyboard function, and callinng glutPostRedisplay x times, it does not redraw anything, it accumulates redraw commands in queue.
The actual redraw occurs when main glut thread returns to processing commands (after exiting keyboard func).

To achieve simple effect of animation in glut do something like that:


static GLboolean flag = false; /*global variable*/


void timer( int t )
{
   if(flag)
   {
      moveBullet();
      if(bullet reached it's destination)
         flag = false;
   }
   glutPostRedisplay()
   glutTimerFunc( timeout_in_milliseconds, timer, t );
}

void keyboard(...)
{
   switch(key)
   {
      case ' ':
         flag = true;
         break;
(...)

/* somewhere in Your initialization code*/
glutTimerFunc( delay_in_milliseconds, timer, some_value );