Animation trouble

I am having trouble with the animation in my simple pong game. It seems that i doesn’t clear the screen completly before painting the next frame. This causes the ball to appear at two places at once.

The display code looks like this:

//can’t move objects when this is true
displayCalled=true;

GL gl = drawable.getGL();
GLU glu = drawable.getGLU();

  /** Clear the colour buffer */ 
  gl.glClear( GL.GL_COLOR_BUFFER_BIT ); //why?

  ball.display( gl, glu );
  leftPadd.display( gl, glu );
  rightPadd.display( gl, glu );
  upperWall.display( gl, glu );
  lowerWall.display( gl, glu );

displayCalled=false;

Another thread controlls the moving of the objects and if my code is correct it can’t update the objects while painting is done. All the objects have a nearly identical display method:

public void display( GL gl, GLU gl ){

  gl.glColor3f( 1.0f, 1.0f, 1.0f );

  gl.glBegin( GL.GL_QUADS );
  gl.glVertex2i( xpos, ypos );
  gl.glVertex2i( xpos+xsize, ypos );
  gl.glVertex2i( xpos+xsize, ypos+ysize );
  gl.glVertex2i( xpos, ypos+ysize );
  gl.glEnd();

}

I don’t have a clue of what is wrong( a good indication that there is something I have misunderstood ). Any help is appreciated.

oyse

I forgot to mention that I use the Animator class to handle the rendering loop

Hi oyse,

at a first glance, your code appears to be correct, but I wonder why you use two threads if you don’t allow them to run at the same time anyway?

You could try (if your applications structure allows it):


public void display(GLDrawable drawable) {

if(somethingChanged) {
updatePositions();
}

GL gl = drawable.getGL();
gl.glClear(GL.GL_COLOR_BUFFER_BIT);

drawStuff(gl);

}

That way you don’t have to care about thread overhead or untimely modifications of the elements positions.

Regards
musashi

At first I didn’t use two threads, and I had almost the exact same code as you suggested. The only difference is that I updateded positions in each display call.


public void display(GLDrawable drawable) { 
 
updatePositions(); 
 
GL gl = drawable.getGL(); 
gl.glClear(GL.GL_COLOR_BUFFER_BIT); 
 
drawStuff(gl); 
 
}

This almost works, but each time the an elements changes direction the square is painted in two different places at once.

I thought this problem could have something to do with double buffering, but isn’t double buffering automatic in jogl or have I misunderstood?

A problem with the one thread solutions is that the elements moves faster on a fast machine than a slow one since the rendering thread calls display as fast as it can.

I think I found a bug in the old code i posted. It was not possible to update positions while it was rendering, but it was possible to render while it updated position. Correcting this bug didn’t help though.

oyse

Still haven’t found the source of the error, but I have constructed a smaller and simpler program with the same error. If someone actually bothers to read this code and find my error I will be ecstatic with joy. The error is driving me crazy!


import java.awt.*; 
import java.awt.event.*; 
import net.java.games.jogl.*;
 
public class GraphicTest extends Frame implements GLEventListener{ 

private Animator animator; //loops the painting

  int xdirection=1, ydirection=1;
  int xpos=100, ypos=100;
  int relativeWidth, relativeHeight;

  public GraphicTest( int width, int height ) {

    relativeWidth=width;
    relativeHeight=height;

    GLCapabilities caps=new GLCapabilities(); 
    GLCanvas canvas=GLDrawableFactory.getFactory().createGLCanvas(caps);
    animator=new Animator(canvas);
    canvas.addGLEventListener(this); 
    add( "Center", canvas ); 
    setSize( width, height ); 
    show(); //frame metode. Gjør vinduet synlig
    animator.start();
    canvas.requestFocus();
  } 

  public static void main( String args[]) { 
    final GraphicTest frame = new GraphicTest( 300, 250 );
   
    //exit if frame's close box is clicked 
    frame.addWindowListener( new WindowAdapter() { 
    public void windowClosed(WindowEvent e){ 
      System.exit(0); 
    } 
    public void windowClosing(WindowEvent e) { 
     frame.cleanUp();
     windowClosed(e); 
    } 
  } 
                                         ); 
  } 
 
  /* This method handles the painting of the GLDrawable */ 
  public void display(GLDrawable drawable) { 
 
    GL gl = drawable.getGL(); 
    GLU glu = drawable.getGLU(); 
 
    gl.glClear( GL.GL_COLOR_BUFFER_BIT );
 
    xpos=xpos+(3*xdirection); //update position
    ypos=ypos+(3*ydirection); //update position

    gl.glColor3f( 1.0f, 1.0f, 1.0f );
      
    gl.glBegin( GL.GL_QUADS ); 
     gl.glVertex2i( xpos, ypos );
     gl.glVertex2i( xpos+5, ypos );
     gl.glVertex2i( xpos+5, ypos+5 );
     gl.glVertex2i( xpos, ypos+5 );
    gl.glEnd();

    if( xpos>200 || xpos < 10 ){ //change direction before it is outside the viewport
     xdirection=xdirection*(-1);
    }
    if( ypos>200 || ypos < 10 ){
     ydirection=ydirection*(-1);
    }
  } 
 
  /** This method handles things if display depth changes */ 
  public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged){ 
  } 

  /* Executed exactly once to initialize the associated GLDrawable */  
  public void init(GLDrawable drawable) { 
 
    GL gl = drawable.getGL(); 
    GLU glu = drawable.getGLU(); 
    gl.glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); //black 
    gl.glColor3f( 1.0f, 1.0f, 1.0f ); 
  } 

  public void reshape(GLDrawable drawable, int x, int y, int width, int height) { 

    GL gl = drawable.getGL(); 
    GLU glu = drawable.getGLU(); 
    gl.glViewport( 0, 0, width, height ); 
    gl.glMatrixMode( GL.GL_PROJECTION );  
    gl.glLoadIdentity(); 
    glu.gluOrtho2D( 0.0, relativeWidth, 0.0, relativeHeight); 
}

  public void cleanUp(){
    animator.stop();
  }
}

oyse

don’t really know the problem, but if you change all your ints to floats and call glVertex2f then it works just fine here …

Thanks for the tip about the floats. Using floats didn’t help directly, but if I used smaller increments when I update variables the animation finally became smooth.

Using 0.5f instead of 3 did the trick at my computer. The only problem is that the Pong game got slower and if possible, more boring.

I don’t know why this works, but I am happy it works at all.

oyse

Hi oyse,

I ran your code and it looked like being “a bit out of sync”. So I switched on vertical synchronization in my graphics driver and the artifacts disappeared.
It should work without having to force synchronization, though.
hrmmm, will think about that…

In my first post I assumed you would calculate the balls position by interpolating between start and destination of its path.
Using a method, which calculates the balls position for any given time, would make the game speed independent from the number of rendered frames and thus independent from the machines processing power.

Regards
musashi