Lab (3) - Simple Animation Using MOUSE and idle()

Lab Goals We can use the idle callback function to implement animation. The following program registers idle() as the function to be called whenever there is free cpu time. This function changes the coordinates of a point at which display() will draw a square, then forces display() to be called by executing glutPostRedisplay(). If we call the coordinates x and y, then e.g. x += 0.2,  y += 0.2 will march the square across the screen and gets out of the screen.  Here is the program that draws a square on different locations of the display by continuously changing the coordinates. 

#include <GL/glut.h>

GLfloat x=10,y=20;
GLfloat xinc=.2,yinc=.2;
const GLfloat size=5;
const GLfloat max=50;
void myinit(void)
{
        /* attributes */
        glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */
        glColor3f(1.0, 0.0, 0.0); /* draw in red */
        /* set up viewing */
        /* 50 x 50 window with origin lower left */
        glPolygonMode(GL_FILL,GL_FRONT);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluOrtho2D(0.0, max, 0.0, max);
        glMatrixMode(GL_MODELVIEW);
}

void display( void )
{
        glClear(GL_COLOR_BUFFER_BIT);  /*clear the window */
        glBegin(GL_POLYGON);
                glVertex2f(x,y);
                glVertex2f(x+size,y);
                glVertex2f(x+size,y-size);
                glVertex2f(x,y-size);
        glEnd();
        glFlush(); /* clear buffers */
}

void idle()
{
        x += xinc;
        y += yinc;
        glutPostRedisplay();
}

void main(int argc, char** argv)
{
        /* Standard GLUT initialization */
        glutInit(&argc,argv);
        glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); /* default, not needed */
        glutInitWindowSize(500,500); /* 500 x 500 pixel window */
        glutInitWindowPosition(0,0); /* place window top left on display */
        glutCreateWindow("Test"); /* window title */
        glutDisplayFunc(display); /* display callback invoked when window opened */

        glutIdleFunc(idle);

        myinit(); /* set attributes */
        glutMainLoop(); /* enter event loop */
}

Answer this question for yourself
What does each line in the following code segment do?
void idle()
{
        x  + = 2;   //x and y are global variables for x,y coordinates of a vertex
        y  += 2;
        glutPostRedisplay();
}

Flicker Free Display using Double Buffer
As you have noticed the above program gives lots of flickers. The screen repeatedly gets refreshed while the square is only partially drawn. The solution is to use double buffering. We draw to an offscreen buffer, then switch buffers all at once. This requires changing only two lines of code. We add

        glutSwapBuffers();
to our display function (after the glFlush call, which flushes output to the buffer). We also change a flag in our call to glutInitDisplayMode:
        glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
Activity (1)  - Flicker Free Square
Make the required changes in your program so that it is flicker free.  Once you are done, run the program and let me see the result.

Activity (2)  - Keeping the Square in the Frame
You noticed that square appeared from one side of the screen and got out from the other side.  Make changes in the program to prevent the square from going out of the screen and instead bounces back when reaches one of the boundaries (all 4 sides must be considered).  In order to do this, you need to track the square and once reached the boundary reverse its path.  One easy way to do this, is to change the sign for the increment for the appropriate coordinate once you hit any of the boundaries.   Once you made the change, compile and run the program.  Show me the result during the lab before moving to the next step.

Submit this program as an attachment.  On the Subject line please write Lab3-Activity2.

Adding the Mouse Function

One last thing to do in this lab.  In class, we talked about the interaction of mouse with your graphics program.  We will use the mouse callback for this purpose. The mouse callback function looks like this:

glutMouseFunc(mouse_callback_func)

void mouse_callback_func(int button, int state, int x, int y)

Here is an example for a mouse function:

void mouse_callback_function(int button, int state, int x, int y)
{
     if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
          exit( 1);
     if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
    {      
            x += 2.0;
             RedrawWhatever();
    }
    else
            
RedrawWhatever();

}

Activity (3)  - Mouse in Control of the Square
Now, add to your program the mouse function such that by pressing:

Submit this program as an attachment.  On the Subject line please write Lab3-Activity3.

An example output screen:
sq

If you didn't finish this in the lab, finish it by next Wednesday.

A Good program for you to look at The Rotating Square

Post-Lab - Simulating a Game (Due Wednesday Feb 21)
For the post-lab you will simulate a game that looks like the Squash Game, but I have invented it :-).  For now, we work on a 2-D model.  The dimensions are given in units instead of a distance unit such as feet or meter. 

The player starts the game by hitting the ball to the wall in front.  The ball bounces back from the wall (knowing the laws of physics) in some direction.  You need to compute that direction assuming elastic motion in physics.  The player will hit the bouncing ball back with a racket and will wait for the next hit when the ball is bounced back.  There are three ranges for the racket depending on the level of difficulty.  If you were able to hit the ball 5 times, you will score points based on the difficulty level.  If you fail to hit a bouncing ball, you will lose points.  Here are some rules, I may add more:
          That score will  go up with the same increment for each level of difficulty if the same  ball is still in play. Basically your earn 10 point for every 5 hits of the
          same
bouncing ball.  Thus, if you get a new ball, counts will reset to 0. You can hit the bounced ball to the sides.  Only the starting ball cannot be hit to the side           wall.
There is a scoreboard that keeps track of the level of difficulty, total number of balls you have started, and the score.   Here is an example of a possible view for the game board. 
MySqGame