In eclipse project explorer, copy lab01b_aspect_ratio, and call new project lab01c_simple_animation
rename reshape.cpp to bounce.cpp
verify that project builds and runs successfully.
We need access to the window "world" co-ordinates - so create two global variables
int windowWidth;
int windowHeight;
if (w <= h)
{
windowWidth = 100;
windowHeight = 100 / aspectRatio;
glOrtho(-100.0, 100.0, -windowHeight, windowHeight, 1.0, -1.0);
}
else
{
windowWidth = 100 * aspectRatio;
windowHeight = 100;
glOrtho(-windowWidth, windowWidth, -100.0, 100.0, 1.0, -1.0);
}
Build and test.
In addition, we will store the actual location of the rectangle in x, and y globals:
float x = -25.0f;
float y = 25.0f;
glRectf(x, y, x+50, y-50);
//glRectf(-25.0f, 25.0f, 25.0f, -25.0f);
Read the documentation on the following
Introduce a new function to act as the timer callback:
void timerFunction(int value)
{
}
glutTimerFunc(33, timerFunction, 1);
Using the debugger, verify that this method is called //once only//
We would like to redraw the box in a different position on each triggering of the timer. This version of the timerFunc here is a start:
static float xstep = 1.0f;
static float ystep = 1.0f;
if (x > windowWidth - 50 || x < -windowWidth)
xstep = -xstep;
if (y > windowHeight || y < -windowHeight + 50)
ystep = -ystep;
x += xstep;
y += ystep;
cout << "x:" << x << " y:" << y << endl;
Build and execute. Note that it seems to be called only once, outputting "x:-24 y:26"
This is because the timer is not iterative - it sets up a single call. To have this called every 33 ns, we need to set it at the end of each call:
glutTimerFunc(33, timerFunction, 1);
Build and test. This time, debug is showing x,y being updated - but no chance on screen.
Have a look at this glut method:
Incorporate a call to this method at the end of timerFunc.
Build and test. Resize the window during execution to get more interesting behaviour.
The timerFunc should refactored, decoupling the updating of the "world" (i.e. moving the co-ordinates of the square) into a separate method.
Call this method "update" and have the timers method call it on every timer "tick".
Experiment with different values for the timer callback - particular observer the behavior for smaller values.
Also experiment with the step size.
Experiment with different dimensions for the rectangle. Devise a simple way of having the rectangle dimensions specified in a single const.
There is a glut function which allows an "idle" funcion to be registered"
Refactor the current implementation to use this for the animation, instead of the timer.
First step would be to write and register an idle callback:
void idleFunction()
{
}
int main(int argc, char* argv[])
{
//...
glutIdleFunc(idleFunction);
//...
}
void idleFunction()
{
update();
glutPostRedisplay();
}
Try it - clearly not very satisfactory.
One simple technique would be to read the system clock in each idle loop and, if a given time has elapsed (say 25 milliseconds), then do an update. This should more or less mimic the behavour of the timer version.
First step would be to introduce static variable to remember time of the last call, and make sure this is initialised the first time the idle loop is called:
static clock_t lastTime = 0;
if (lastTime == 0)
lastTime = clock();
clock_t currTime = clock();
clock_t deltaTime = currTime - lastTime;
float secondsDelta = (float)deltaTime/CLOCKS_PER_SEC;
if (secondsDelta >= 0.025)
{
update();
lastTime = currTime;
glutPostRedisplay();
}
Execute and experiment with different intervals.
Is there any noticeable difference between the operation of this technique and the timers?
Create another rectangle - green this time.
Place it below the red rectangle, and have it move in the opposite direction.