Resolution independent 2D graphics engine
02 Animation
Picture of earth and moon aplication

This tutorial shows how animation can be created in Quad-Ren, the result of this tutorial is a pseudo 3D animation of the moon orbiting the Earth. You should read the hello world tutorial before diving into this one.

Like the hello world tutorial, we include the Quad-Ren header file, math.h is also needed for cos and sin. #include <quad-ren/quad-ren.h>
#include <math.h>

int main()
{

Here we create a renderer, get the resource manager from it and set the window title.     qr::renderer *renderer_ob = new qr::renderer(qr::vector2d_i(16, 9),
        10.0 ,false ,qr::vector2d_i(0, 0), false, 0);

    qr::scene_manager *scene_man = renderer_ob ->
        get_scene_manager();

    renderer_ob -> set_window_title("Animation - Quad-Ren");

Next we load a space image for the background from a PNG image and attach it to the background quad.     qr::sprite *background = new qr::sprite(scene_man, 1);

    background -> load_png_frame(
        "../media/star_background.png", 1);

    background -> convert_data();

    renderer_ob -> set_bg_sprite(background);

We need to create 2 more sprites for the Earth and Moon. While the frames could be loaded from separate PNG images, Quad-Ren includes a much easier and cleaner way to store animation sequences, the QRDD, or Quad-Ren Data Dump file format. This enables entire animation sequences to be dumped to disk, and then re-loaded with only a single function call.     qr::sprite *Earth;
    qr::sprite *Moon;

    Earth = qr::qrdd_file_handler::load_sprite(scene_man, "../media/earth.QRDD");
    Moon =  qr::qrdd_file_handler::load_sprite(scene_man, "../media/moon.QRDD");

To display a sprite in the scene it must be attached to a scene node, You already know about the always present background quad, but this can only display one sprite. Displaying more sprites is done using the qr::quad scene node, Which can be rotated, translated and resized however you wish.

We create 2 quads, one for the earth and one for the moon.     qr::scene_node *Earth_quad = new qr::quad(scene_man);
    qr::scene_node *Moon_quad  = new qr::quad(scene_man);

Scene nodes can be resized using the set_size method.     Earth_quad -> set_size(qr::vector2d_f(2.5,2.5));

To create the illusion of a 3D scene, we make the Moon pass behind the Earth as it goes about its orbit, this is done using layers. The Earth is placed on layer 2, and the Moon will dynamically switch between layers 1 and 3.     Earth_quad -> set_layer(2);

For the sprites of the earth and moon to show, we need to apply them to there respective scene node, this is done with the set_sprite() method.     Earth_quad -> set_sprite(Earth);
    Moon_quad -> set_sprite(Moon);

To make the planets loop through there sprite frames a sprite_loop_animator is attached to them, this object takes the animation frame rate as a parameter. The next tutorial shows how you can implement your own animators.     qr::animator *sprite_anim = new qr::sprite_loop_animator(25);
    Earth_quad->set_animator(sprite_anim);
    Moon_quad->set_animator(sprite_anim);

Thats it for set up, we define some variables, then its on to the animation. Unlike in the hello world example, where the internal event loop was used, here we run the renderer inside a while loop.     float orbit_angle = 0;
    qr::vector2d_f orbit;

    while(renderer_ob -> run())
    {

Now we get the time delta (time difference between the current and previous frame) from the renderer. This will be used to create frame-rate independent animation.         float time_delta = renderer_ob -> get_time_delta() / 10;

Increment the orbit angle, this is multiplied by the time delta to make the animation speed frame rate independent.         orbit_angle += 0.01 * time_delta;

Next we calculate moon orbit location using cos() and sin(). The hight variation of the orbit is substantially less than the width variation to aid the 3D effect.         orbit.X = 4 * cos(orbit_angle);
        orbit.Y = 0.5 * sin(orbit_angle);
        Moon_quad -> set_location(orbit);

Dynamically change the layer the moon is on so that it passes behind the earth.         if(orbit.Y < 0)
            Moon_quad -> set_layer(3);
        else
            Moon_quad -> set_layer(1);

Finally, to complete the 3D effect the moon is scaled down in the distance. The moon size is calculated from the inverse of its Y co-ordinate.         float moon_size = ((0 - (orbit.Y * 2)) /3) + 0.7;
        Moon_quad -> set_size(qr::vector2d_f(moon_size, moon_size));
    }

Like before, drop the renderer on application exit, animators are not managed currently so we also need to delete the sprite animator object.     renderer_ob -> drop();
    delete sprite_anim;
}