AppEasy Core SDK
1.5.0
Cross platform mobile and desktop app and game development SDK - The easy way to make apps
|
A collection of animation frames. More...
#include <CzAnim.h>
Public Types | |
enum | eAnimStatus { AS_Stopped, AS_Playing, AS_Paused } |
Values that represent the current state of the animation. More... | |
typedef CzVector< CzAnimFrame * > ::iterator | _Iterator |
Public Member Functions | |
_Iterator | begin () |
_Iterator | end () |
void | setType (CzAnimFrame::eAnimType type) |
CzAnimFrame::eAnimType | getType () const |
float | getDuration () const |
void | setDuration (float duration) |
void | addFrame (CzAnimFrame *frame) |
Adds an animation frame to the animation. | |
bool | getCurrentFrame (CzAnimFrame **current, CzAnimFrame **next, float current_time) |
Gets current frame. | |
void | CalculateCurrentData (float current_time, CzAnimFrame *current_data, bool interpolate=true) |
Calculates the current frame data. | |
int | getFrameCount () |
CzAnimFrame * | getFrame (int index) |
void | setCategory (int category) |
int | getCategory () const |
void | setAutoDelete (bool enable) |
bool | isAutoDelete () const |
CzAnim () | |
virtual | ~CzAnim () |
void | GenerateAtlasFrames (int count, int frame_w, int frame_h, int start_x, int start_y, int pitch_x, int pitch_y, int image_width, float frame_speed) |
Generates a group of rect image atlas frames. | |
int | LoadFromXoml (IzXomlResource *parebt, bool load_children, CzXmlNode *node) |
Creates an instance of this class from XOML. | |
Protected Attributes | |
CzAnimFrame::eAnimType | Type |
Type of animation. | |
float | Duration |
Duration of animation. | |
CzVector< CzAnimFrame * > | Frames |
Animation frames. | |
int | Category |
User defined category. | |
bool | AutoDelete |
If set to true thenm timeline will be deleted when finished. |
A collection of animation frames.
There are plenty of great games and apps out there that do not feature any form of animation. However, most modern games do feature animations to enhance their look and feel. Lets take "Angry Birds" as an example, Angry Birds uses animations all over the place, such as the animating birds and pigs, even the menus contain flashing and sweeping animations.
When we initially decided to implement an animation system we decided that it had to be very flexible and support any type of animation, be it animating the position of an actor, animating the graphical frames of an actor or even animating a list of commands for an actor. From AppEasy's point of view, animation refers to any variable or set of variables that can change over time.
The AppEasy animation system currently supports the following features:
The animation system is split into the following classes:
Animation frame data is the backbone of all animations, it represents the actual discrete state of a variable at a given point in time (called a key frame). An animation frame consists of two components:
The base class for all animation frame data types is the CzAnimFrame. This class provides a means for the developer to implement their own custom animation frame data types. The following animation frame data types are already implemented:
The resource manager is used to manage a group of resources (animations). The idea is that you create a group of animations then add them to the resource manager and then forget about them. The resource manager will take care of cleaning them up when the scene or main app is destroyed. The main app object contains its own global resource manager whilst all scenes contain their own local resource manager.
Note that when animations are created via XOML mark-up they are added to the resource manager. Animations that are created inside a scene will be added to the scenes resource manager, whilst animations created outside of the scene will be added to the global resource manager.
To find an animation within a scenes resource manager you would use could such as:
CzAnim* anim = (CzAnim*)scene->getResourceManager()->findResource("Player1Anim", CzHashes::Animation_Hash);
Note that if the animation is not found within the scene then the system will automatically search the global resource manager for the animation. You can prevent this global search by passing false as the third parameter to findResource().
Timelines are stored in the timelines manager of a scene, actor or the global time lines manager, depending on where they are declared.
CzAnim is basically used as a means to store the animation data in a convenient place. With this in mind you do not play a CzAnim directly, instead you create an instance of it using CzAnimInstance:
// Create and set up an animation CzAnimInstance* face_anim = new CzAnimInstance(); face_anim->setAnimation(anim); face_anim->setTarget(actor, "SrcRect");
Note the following line of code:
face_anim->setTarget(actor, "SrcRect");
This line of code tells the animation to modify the "SrcRect" (the actors image atlas position) property of the actor object, causing the image to change.
Animation instances can be played, paused, resumed, stopped and restarted. You can also tell an animation to delay playing for a finite period of time.
AppEasy Core uses the concept of animation targets and animation target properties. An animation target is basically a class that contains a variable or group of variables that can be targeted for modification by an animation. The actual variable or variables that are targeted are called target properties. An example target would be an actor and example target property would be the actors position. When you create an instance of an animation you set the target and target property that the animation will modify using code similar to that shown below:
face_anim->setTarget(actor, "SrcRect");
Any class can be used as a target for animation as long as it derives from the IzAnimTarget interface and implements the the following pure virtual method:
virtual bool UpdateFromAnimation(CzAnimInstance *animation) = 0;
When the animation updates it will call back this method passing in its data asking the method to update the state of the object. Both scene and actor classes already have this functionality implemented.
Lets take a quick look at a small section of CzScene::UpdateFromAnimation() to see how the CzScene class has implemented this method:
bool CzScene::UpdateFromAnimation(CzAnimInstance *animation) { unsigned int property_name = animation->getTargetPropertyHash(); bool delta = animation->isDelta(); if (Camera != NULL) { if (property_name == CzHashes::Position_Hash) { CzAnimFrameVec2* frame = (CzAnimFrameVec2*)animation->getCurrentData(); if (delta) { CzVec2 pos = Camera->getPosition(); pos.x += frame->data.x; pos.y += frame->data.y; Camera->setPosition(pos.x, pos.y); } else Camera->setPosition(frame->data.x, frame->data.y); return true; } else if (property_name == CzHashes::Angle_Hash) { CzAnimFrameFloat* frame = (CzAnimFrameFloat*)animation->getCurrentData(); if (delta) Camera->setAngle(Camera->getAngle() + frame->data); else Camera->setAngle(frame->data); return true; } else if (property_name == CzHashes::Scale_Hash) { CzAnimFrameFloat* frame = (CzAnimFrameFloat*)animation->getCurrentData(); if (delta) Camera->setScale(Camera->getScale() + frame->data); else Camera->setScale(frame->data); return true; } } return false; }
The logic is quite simple, we check the name of the property that was passed in by the animation instance then check that against known property names of the class. If it matches then we move the animation data from the animation instance into our classes local variable.
As you can see implementing your own custom animation targets is a simple case of:
An animation time line is basically a way to group together multiple animation instances and play, pause, stop and resume them all together. The general idea is that you create an animation time line then create animation instances and add them to the time line. You then attach the time line to your destination object, be that a scene or an actor. The animation system will then take care of the rest for you. Here is an example showing how to create and use a time line:
// Find our face animation CzAnim* face_anim = (CzAnim*)scene->getResourceManager()->findResource("FaceAnim", CzHashes::Animation_Hash); // Create and set up our animation instance CzAnimInstance* instance = new CzAnimInstance(); instance->setAnimation(face_anim); instance->setTarget(actor, "SrcRect"); timeline->addAnimation(instance); timeline->play(); // Create an animation timeline to hold our image animation CzAnimTimeline* timeline = new CzAnimTimeline(); timeline->addAnimation(instance); // Attach timeline to the actor actor->setTimeline(timeline);
Defining and attaching animations is much easier and more intuitive if done declaratively using XOML mark-up. More on this this later
Note that when you attach an animation time line to a scene or an actor, the scene / actor will automatically take over updating it for you.
Time lines can be played, paused, resumed and stopped. All animation instances within the animation time line will be affected.
The resource manager is generally responsible for managing the lifetimes of animations and animation time lines, in particular those created from XOML mark-up.
Each scene has its own local resource manager as well as a global resource manager.
The general work flow when working with the animation system has two potential paths:
The first method is more difficult as it does require creatng and setting up animation classes yourself. Heres the basic flow for manual animation setup:
The second method using XOML is much simpler:
AppEasy supports a number of different types of animation as previously explained. In our example we are going to create a basic floating point animation that animates the rotation property of an actor object.
// Create an animation CzAnim* anim = new CzAnim(); anim->setName("TestAnim"); anim->setDuration(3); anim->setType(CzAnimFrame::FT_Float); // Create and add frames CzAnimFrameFloat* frame = new CzAnimFrameFloat(); frame->Time = 0; frame->data = 0; anim->addFrame(frame); frame = new CzAnimFrameFloat(); frame->Time = 1; frame->data = 45; anim->addFrame(frame); frame = new CzAnimFrameFloat(); frame->Time = 2; frame->data = 90; anim->addFrame(frame); // Create animation instance CzAnimInstance* instance = new CzAnimInstance(); instance->setAnimation(anim); instance->setDelay(0); instance->setRepeatCount(0); instance->setTarget(actor, "Angle"); // Creata a time line CzAnimTimeline* timeline = new CzAnimTimeline(); timeline->setName("Timeline1"); timeline->addAnimation(instance); // Play the timeline timeline->play(); // Attach timeline to the actor actor->setTimeline(timeline);
As you can see it is a little verbose, which is why we recommend using XOML mark-up for defining animations in particular.
XOML is AppEasy's mark-up language that can be used to define and set-up actors, scenes, resource, animations and other game elements. Here is an example showing how to set up the previous example using XOML syntax:
<xml> <Animation Name="TestAnim" Type="float" Duration="3" > <Frame Value="0" Time="0.0" /> <Frame Value="45" Time="1.0" /> <Frame Value="90" Time="2.0" /> </Animation> <Timeline Name="Timeline1" AutoPlay="true"> <Animation Anim="TestAnim" Target="Angle" Repeat="0" StartAtTime="0"/> </Timeline> </xml>
As you can see it is incredibly easy to set up animations and time line's using XOML syntax.
XOML Anim tag properties
Type and Duration are required properties
XOML Anim Frame tag properties
Time and Value are required properties
XOML Timeline tag properties
Timelines also contain child Animation tags which define which animations will appear in the timeline. Lets take a look at the properties of this inner tag:
Anim and Target are required properties
Note that a time line can be assigned to as many objects you like but the time line will be played back the same on all objects. This is very useful if you have a group of actors that need to run the same animations synchronously.
We are now going to take a look at creating an image based animation that we can attach to an actor:
// Create an animation CzAnim* anim = new CzAnim(); anim->setName("TestAnim"); anim->setDuration(0.8f); anim->GenerateAtlasFrames(8, 36, 40, 0, 0, 512, 40, 512, 0.1f); // Create animation instance CzAnimInstance* instance = new CzAnimInstance(); instance->setAnimation(anim); instance->setDelay(0); instance->setRepeatCount(0); instance->setTarget(actor, "SrcRect"); // Creata a time line CzAnimTimeline* timeline = new CzAnimTimeline(); timeline->setName("Timeline1"); timeline->addAnimation(instance); // Play the timeline timeline->play(); // Attach timeline to actor actor->setTimeline(timeline);
Setting up an image based animation is a little simpler because the CzAnim::GenerateAtlasFrames() method() automates the generation of frames for us.
Although the same can also be done in XOML which is even simpler, e.g:
<Animation Name="TestAnim" Type="rect" Duration="0.8" > <Atlas Count="8" Duration="0.1" Pitch="36, 40" Size="36, 40" Width="36" /> </Animation> <Timeline Name="Timeline1" AutoPlay="true"> <Animation Anim="TestAnim" Target="SrcRect" Repeat="0" StartAtTime="0"/> </Timeline>
The properties for the Atlas tag are as follows:
typedef CzVector<CzAnimFrame*>::iterator CzAnim::_Iterator |
enum CzAnim::eAnimStatus |
CzAnim::CzAnim | ( | ) | [inline] |
virtual CzAnim::~CzAnim | ( | ) | [inline, virtual] |
void CzAnim::addFrame | ( | CzAnimFrame * | frame | ) |
Adds an animation frame to the animation.
[in,out] | frame | If non-null, the frame. |
_Iterator CzAnim::begin | ( | ) | [inline] |
void CzAnim::CalculateCurrentData | ( | float | current_Time, |
CzAnimFrame * | current_data, | ||
bool | interpolate = true |
||
) |
Calculates the current frame data.
This method is called internally by the animation systen to calculate the animations current frame data from its current and next animation frames, taking into account the elapsed time, interpolation and tweening effect.
current_Time | The current time. | |
[in,out] | current_data | If non-null, current anim frame. |
interpolate | true to interpolate animation frames. |
_Iterator CzAnim::end | ( | ) | [inline] |
void CzAnim::GenerateAtlasFrames | ( | int | count, |
int | frame_w, | ||
int | frame_h, | ||
int | start_x, | ||
int | start_y, | ||
int | pitch_x, | ||
int | pitch_y, | ||
int | image_width, | ||
float | frame_duration | ||
) |
Generates a group of rect image atlas frames.
count | Number of frames to generate. |
frame_w | The frame width. |
frame_h | The frame height. |
start_x | The start x coordinate. |
start_y | The start y coordinate. |
pitch_x | The x pitch. |
pitch_y | The y pitch. |
image_width | Width of the image. |
frame_duration | Duration of each frame. |
int CzAnim::getCategory | ( | ) | const [inline] |
bool CzAnim::getCurrentFrame | ( | CzAnimFrame ** | current, |
CzAnimFrame ** | next, | ||
float | current_Time | ||
) |
Gets current frame.
[in,out] | current | If non-null, the current. |
[in,out] | next | If non-null, the next. |
current_Time | The current time. |
float CzAnim::getDuration | ( | ) | const [inline] |
CzAnimFrame* CzAnim::getFrame | ( | int | index | ) | [inline] |
int CzAnim::getFrameCount | ( | ) | [inline] |
CzAnimFrame::eAnimType CzAnim::getType | ( | ) | const [inline] |
bool CzAnim::isAutoDelete | ( | ) | const [inline] |
int CzAnim::LoadFromXoml | ( | IzXomlResource * | parent, |
bool | load_children, | ||
CzXmlNode * | node | ||
) | [virtual] |
Creates an instance of this class from XOML.
LoadFromXoml is the main method used by all classes that can be instantiated from XOML mark-up. This method creates an instance of this class from the supplied XML node structure specified by node.
[in] | parent | If non-null, the parent. |
load_children | true to load child nodes. | |
[in] | node | If non-null, the XOML markup node that defines this object |
Implements IzXomlResource.
void CzAnim::setAutoDelete | ( | bool | enable | ) | [inline] |
void CzAnim::setCategory | ( | int | category | ) | [inline] |
void CzAnim::setDuration | ( | float | duration | ) | [inline] |
void CzAnim::setType | ( | CzAnimFrame::eAnimType | type | ) | [inline] |
bool CzAnim::AutoDelete [protected] |
If set to true thenm timeline will be deleted when finished.
int CzAnim::Category [protected] |
User defined category.
float CzAnim::Duration [protected] |
Duration of animation.
CzVector<CzAnimFrame*> CzAnim::Frames [protected] |
Animation frames.
CzAnimFrame::eAnimType CzAnim::Type [protected] |
Type of animation.