HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Animation using function pointers

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
animationfunctionusingpointers

Problem

So I've been thinking alot about simple/convenient ways to implement simple 2D animation using a bare-bones graphics library I'm using for school (Animation is way out of the scope of the class, I'm just experimenting.)

I thought of using a custom function passed to the class to allow the "user" of the code to just write their own code to do whatever they want to the sprite, then return control to the sprite's Update() function. Here's what I have so far:

// SpriteStuff.h

typedef bool (AnimationStep*)(Sprite* sprite) ANIMATIONSTEP

class Sprite {
    //...
    ANIMATIONSTEP m_currentAnimation;

    void BeginAnimation(ANIMATIONSTEP step);
    void EndAnimation();

    void Update();
    //...
};

void Sprite::BeginAnimation(ANIMATIONSTEP step) {
    if (step != NULL)
        m_currentAnimation = step;
}
void Sprite::EndAnimation() {
    m_currentAnimation = NULL;
}

void Sprite::Update() {
    //...
    if (m_currentAnimation != NULL) 
        if (!m_currentAnimation(this)) EndAnimation();
    //...
}

// (off in some other code...)
void DoAnimateThing() {
    mySprite->BeginAnimation(GeneralFallAnimationStep);
}

bool GeneralFallAnimationStep(Sprite* sprite){
    return sprite->y++ > SOME_LIMIT_SOMEWHERE;
}

// Could possibly end it early...
void CancelAnimationOnThing() {
    mySprite->EndAnimation();
}


It seems like a pretty simple design that will do what I need, but almost too simple. I'm doing something terribly wrong, huh?

EDIT: So I've gotten some good input on this, but now I'm curious... Any suggestions how controlling the speed of these animations? Can this be done well in the Sprite class, or should that be handled strictly by the ANIMATIONSTEP?

Solution

Too simple? Hardly. That is pretty much a textbook implementation of animation using a callback-based event model. In a production-grade version there would be a few extra null checks and similar to check for programming mistakes, but the basic implemation could be very similar.

I'm assuming that elsewhere there is a main loop that periodically calls update on each relevant sprite. I'm also assuming that either update takes care of drawing the spite, or that code not shown is responsible for that.
One Weakness and Possible Solution

One thing though that may be problematic for complicated animations is that your design gives the function no scratch space in which to store any state information (complicated animations may want to know if this is the first or second time the sprite was at coordinate (457,758) for example).

An easy solution is to add an extra void * to the sprite. This would be an extra pointer the animation function can set to whatever it wants (usually an animation specific structure). Have BeginAnimation set this new pointer to NULL. Document that the pointer must either be left NULL, or allocated with new. EndAnimation would delete the pointer on the animation's behalf if it was not still NULL, since the animation is not given the opertunity to cleanup if EndAnimation is called directly.

There are cleaner solutions than the above, but the that one is easy to explain, and should work.

Context

StackExchange Code Review Q#5181, answer score: 3

Revisions (0)

No revisions yet.