Sprites
As probably most people know, a sprite is a collection of 2D images (called frames), shown in sequence with a delay between each frame. Sprites are used for a lot of game objects, i.e. moving people, spaceships, chairs, powerups, missiles, animated mouse cursors, etc.
If you need more advanced features, sprites can be rotated and made semi-translucent, you can tweak the animation speed for individual frames, set frame offsets, set drawing and rotation alignment, you can play them in a backward looping pattern, a ping-pong loop, forward just-once, etc. Short said, CL_Sprite can do most things you'll ever need for basic 2d sprites.
Constructing sprites
CL_Sprite can be constructed in two ways - either using ClanLib resources, or manually through a CL_SpriteDescription.
Creating sprites using resources
Please read the Sprites Resources Overview for a description on the resource options for sprites.
After you have created your sprite resource, you can easily create a
CL_ResourceManager resources("resources.xml"); CL_Sprite sprite1(gc, "my_simple_sprite", &resources); CL_Sprite sprite2(gc, "my_advanced_sprite", &resources);
Creating sprites manually
If you for some reason don't want to use resource files, you can manually create
the same sprite setup using the
You add, just like in the resource file, a series of cutters which will extract the frames to be used in the sprite.
CL_SpriteDescription desc_simple; desc_simple.add_frame(CL_ImageProviderFactory::load("image_single1.tga")); desc_simple.add_frame(CL_ImageProviderFactory::load("image_single2.tga")); desc_simple.add_frame(CL_ImageProviderFactory::load("image_single2.tga")); CL_SpriteDescription desc_advanced; desc_advanced.add_frame(CL_ImageProviderFactory::load("image1.tga")); desc_advanced.add_gridclipped_frames(CL_ImageProviderFactory::load("gridframes.tga"), 0, 0, 32, 32, 10, 2, 0, 0); desc_advanced.add_alphaclipped_frames(CL_ImageProviderFactory::load("alphaframes.tga"), 0, 0, 0.05f); desc_advanced.add_frame(CL_ImageProviderFactory::load("image2.tga")); desc_advanced.add_gridclipped_frames(CL_ImageProviderFactory::load("image3.tga"), 0, 0, 32, 32, 1, 1, 0, 0); CL_Sprite sprite1(gc, desc_simple); CL_Sprite sprite2(gc, desc_advanced); sprite2.set_alpha(0.5f); sprite2.set_base_angle(CL_Angle::from_degrees(90.0f)); sprite2.set_frame_delay(20, 100); sprite2.set_frame_offset(20, CL_Point(1, 1));
If you read the Sprites Resources Overview, you will see this code creates the exact same setup, only now using code instead of a resourcefile.
Using sprites
Example usage code:
// Make sure sprites are animated sprite1.update(); sprite2.update(); // Rotate sprite sprite1.rotate(CL_Angle::from_degrees(0.5f)); // Draw sprites sprite1.draw(gc, 10, 10); sprite2.draw(gc, 100, 100);
Changing look of a sprite
If you want to change the look of your sprite, use CL_Sprite::set_image_data(). This will keep the current attributes (rotation, alpha, etc), except the animation status (current frame etc).
class Man { ... CL_Sprite sprite_man_walk; CL_Sprite sprite_man_still; CL_Sprite sprite_man; } void Man::init() { sprite_man_walk = CL_Sprite(gc, "man_walk", resources); sprite_man_still = CL_Sprite(gc, "man_still", resources); set_walking(true); } void Man::set_walking(bool walking) { if(walking) sprite_man.set_image_data(sprite_man_walk); else sprite_man.set_image_data(sprite_man_still); } void Man::draw() { sprite_man.update(); sprite_man.rotate(CL_Angle::from_degrees(1.0f)); sprite_man.draw(gc, x, y); }
Playback control
TODO
Alignment and hotspot
TODO
Advanced: Frame-independent update
There are different ways of having a frame-independent game. One way is to calculate the time elapsed since last frame. This is how the update() function in CL_Sprite works. Between every call to update(), it calculates the amount of time lapsed, and uses this to decide which frame in the animation it should display. In most cases, this is good enough, and you won't have to bother with the second option described below.
Some games works in a fixed-tick-mode, where updates are called X numbers of times during one second, instead of calculating a variable time between each update. It is possible to use this approach with CL_Sprite as well; you just call CL_Sprite::update(float time) with the time between each tick. So, if you have a constant tick of 30 per second, you would call sprite.update(1000.0f/30);