Animated Sprite Class +example

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Animated Sprite Class +example

Post by arras »

This is simple class capable of displaying animated sprites.

Download: http://www.spintz.com/arras/Files/Anima ... 070904.zip [25 kb]
Download includes header file and example showing basic functions of class.

Version 1.1 changes:

-Support for reverse animation added as suggested by FuzzYspo0N.
There is one more parameter for addAnimation() function which sets reverse play.
Two coresponding functions added: reverseAnimation() and isAnimationReversed().

-Function setAnimationLoopState() added.

Code: Select all

/*-----------------------------------------------------------------------------*
| headerfile AnimSprite.h                                                      |
|                                                                              |
| version 1.1                                                                  |
| date: (04.09.2007)                                                           |
|                                                                              |
| author:  Michal Švantner                                                     |
|                                                                              |
| for Irrlicht engine                                                          |
| 2d animated sprite class                                                     |
*-----------------------------------------------------------------------------*/

#ifndef ANIMSPRITE_H
#define ANIMSPRITE_H

#include <irrlicht.h>
using namespace irr;

class AnimSprite
{
    struct Animation
    {
        s32 start;
        s32 end;
        u32 speed;
        bool loop;
        bool reverse;
    };
    
    video::ITexture *texture;
    core::array< core::rect<s32> > frame;
    s32 currentFrame;
    core::rect<s32> position;
    
    core::array<Animation> animation;
    u32 currentAnim;
    
    u32 oldTime;
    
    IrrlichtDevice *Device;
    
public:
    
    // constructor
    // \param idevice -pointer to Irrlicht device
    // \param itexture -pointer to texture used, must be power of two size
    // \param divX - number of frames along X axis
    // \param divY - number of frames along Y axis
    AnimSprite(IrrlichtDevice *idevice, video::ITexture *itexture, s32 divX = 1, s32 divY = 1)
    {
        Device = idevice;
        
        texture = itexture;
        
        core::dimension2d<s32> spriteSize(texture->getSize());
        spriteSize.Width = spriteSize.Width / divX;
        spriteSize.Height = spriteSize.Height / divY;
        
        frame.set_used(divX * divY);
        
        u32 n = 0;
        for(s32 j=0; j<divY; j++)
            for(s32 i=0; i<divX; i++)
            {
                frame[n] = core::rect<s32>(
                    i*spriteSize.Width, j*spriteSize.Height, 
                    (i+1)*spriteSize.Width, (j+1)*spriteSize.Height);
                n++;
            }
        
        currentFrame = 0;
        
        position.UpperLeftCorner = core::position2d<s32>(0,0);
        position.LowerRightCorner = core::position2d<s32>(spriteSize.Width,spriteSize.Height);
        
        currentAnim = 0;
    }
    
    // copy constructor
    // \param other -sprite to coppy
    AnimSprite(AnimSprite &other)
    {
        texture = other.texture;
        
        frame.set_used(other.frame.size());
        for(u32 i=0; i<frame.size(); i++) frame[i] = other.frame[i];
        
        currentFrame = 0;
        
        position.UpperLeftCorner = core::position2d<s32>(0,0);
        position.LowerRightCorner = other.position.LowerRightCorner - other.position.UpperLeftCorner;
        
        animation.set_used(other.animation.size());
        for(u32 i=0; i<animation.size(); i++)
        {
            animation[i].start = other.animation[i].start;
            animation[i].end = other.animation[i].end;
            animation[i].speed = other.animation[i].speed;
            animation[i].loop = other.animation[i].loop;
            animation[i].reverse = other.animation[i].reverse;
        }
        
        currentAnim = 0;
        
        Device = other.Device;
    }
    
    // destructor
    ~AnimSprite(){}
    
    // draw frame
    // \param num -frame id number based on 0 based index
    virtual void draw(u32 num = 0)
    {
        Device->getVideoDriver()->draw2DImage(texture, position, frame[num], 0, 0, true);
    }
    
    // play sprite
    virtual void play()
    {
        if(animation.empty())
        {
            draw(0);
            return;
        }
        
        u32 time = Device->getTimer()->getTime();
        
        if(oldTime + animation[currentAnim].speed <= time)
        {
            if(animation[currentAnim].reverse)
            {
                currentFrame--;
                if(currentFrame < animation[currentAnim].start)
                {
                    if(animation[currentAnim].loop)currentFrame = animation[currentAnim].end;
                    else currentFrame++;
                }
            }
            else
            {
                currentFrame++;
            
                if(currentFrame > animation[currentAnim].end)
                {
                    if(animation[currentAnim].loop)currentFrame = animation[currentAnim].start;
                    else currentFrame--;
                }
            }
            
            oldTime = time;
        }
        
        draw(currentFrame);
    }
    
    // add new animation
    // returns id number of animation
    // \param start -start frame number
    // \param end - end frame number
    // \param speed - animation speed in miliseconds
    // \param loop - true if animation should loop, false if not
    // \param reverse - true if animation should play reversed, false if not
    virtual u32 addAnimation(u32 start, u32 end, u32 speed, bool loop = false, bool reverse = false)
    {
        Animation tmp;
        tmp.start = start;
        tmp.end = end;
        tmp.speed = speed;
        tmp.loop = loop;
        tmp.reverse = reverse;
        
        animation.push_back(tmp);
        
        return animation.size()-1;
    }
    
    // remove animation
    // \param num -animation id number
    virtual void removeAnimation(u32 num)
    {
        animation.erase(num);
        
        if(currentAnim == num)
        {
            currentAnim = 0;
            currentFrame = 0;
        }
        
        if(currentAnim > num) currentAnim--;
    }
    
    // remove all animations
    virtual void clearAnimations()
    {
        animation.clear();
        currentAnim = 0;
        currentFrame = 0;
    }
    
    // set animation to play
    // \param num -animation id number
    virtual void setAnimation(u32 num)
    {
        currentAnim = num;
        if(animation[currentAnim].reverse)
            currentFrame = animation[currentAnim].end;
        else
            currentFrame = animation[currentAnim].start;
        oldTime = Device->getTimer()->getTime();
    }
    
    // return id number of animation played
    virtual u32 getCurrentAnimation()
    {
        return currentAnim;
    }
    
    // set speed of animation
    // \param num -animation id number
    // \param newspeed -new animation speed in miliseconds
    virtual void setAnimationSpeed(u32 num, u32 newspeed)
    {
        if(animation.empty()) return;
        animation[num].speed = newspeed;
    }
    
    // return speed of animation
    // \param num -animation id number
    virtual u32 getAnimationSpeed(u32 num)
    {
        if(animation.empty()) return 0;
        return animation[num].speed;
    }
    
    // return id number of animation start frame
    // \param num -animation id number
    virtual u32 getAnimationStart(u32 num)
    {
        return animation[num].start;
    }
    
    // return id number of animation end frame
    // \param num -animation id number
    virtual u32 getAnimationEnd(u32 num)
    {
        return animation[num].end;
    }
    
    // set animation loop state
    // \param num -animation id number
    // \param loop -true if animation should loop, false if not
    virtual void setAnimationLoopState(u32 num, bool loop)
    {
        animation[num].loop = loop;
    }
    
    // return true if animation loopes, false if not
    // \param num -animation id number
    virtual bool getAnimationLoopState(u32 num)
    {
        return animation[num].loop;
    }
    
    // set animation reverse state
    // \param num -animation id number
    // \param reverse -true if animation should play reversed, false if not
    virtual void reverseAnimation(u32 num, bool reverse)
    {
        animation[num].reverse = reverse;
    }
    
    // return true if animation play reverse, false if not
    // \param num -animation id number
    virtual bool isAnimationReversed(u32 num)
    {
        return animation[num].reverse;
    }
    
    // set position of sprite on screen
    // \param x - screen X coordinate of new position
    // \param y - screen Y coordinate of new position
    virtual void setPosition(s32 x, s32 y)
    {
        position.LowerRightCorner = position.LowerRightCorner - position.UpperLeftCorner + core::position2d<s32>(x,y);
        position.UpperLeftCorner = core::position2d<s32>(x,y);
    }
    
    // return position of sprite on screen
    virtual core::position2d<s32> getPosition()
    {
        return position.UpperLeftCorner;
    }
    
    // return number of frames in sprite
    virtual u32 getFrameCount()
    {
        return frame.size();
    }
    
    // return number of animations in sprite
    virtual u32 getAnimationCount()
    {
        return animation.size();
    }
    
    // set new texture sprite should use
    // \param newtexture - pointer to texture sprite should use
    //                     must be the same size as original texture
    virtual void setTexture(video::ITexture *newtexture)
    {
        texture = newtexture;
    }
    
    // return pointer to texture sprite is using
    virtual video::ITexture* getTexture()
    {
        return texture;
    }
    
    // return size of sprite in pixels
    virtual core::dimension2d<s32> getSize()
    {
        core::dimension2d<s32> size;
        
        size.Width = position.LowerRightCorner.X - position.UpperLeftCorner.X;
        size.Height = position.LowerRightCorner.Y - position.UpperLeftCorner.Y;
        
        return size;
    }
};

#endif
Last edited by arras on Tue Sep 04, 2007 4:24 pm, edited 1 time in total.
i2k
Posts: 2
Joined: Thu Jun 14, 2007 6:49 am

Post by i2k »

Super
Slappy
Posts: 2
Joined: Tue Aug 21, 2007 7:05 pm
Location: Slovakia

animation

Post by Slappy »

IMHO thiss is good...
But there are several problems, which should be solved...
I created similiar animation too - for animated cursors

btw: for Slovakian only:
ak máte záujem a hľadáte programátora, pracujete na nejakej hre atd ozvite sa mi...
Pridal by som sa k vám...
Chcel by som sa naučiť niečo viac, prípadne spolupracovať...
Anteater
Posts: 266
Joined: Thu Jun 01, 2006 4:02 pm
Location: Earth
Contact:

Post by Anteater »

Cool! What's the license?
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Slappy >> What problems do you refer to?

Anteater >> No license, use it as much as you want and way you want. Its free. Of course, small credit wont hurt :)
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

When I try to compile it with VC6 I get this error:
Deleting intermediate files and output files for project 'AnimatedSpriteExample - Win32 Debug'.
--------------------Configuration: AnimatedSpriteExample - Win32 Debug--------------------
Compiling...
main.cpp
Compiling Irrlicht with Visual Studio 6.0, support for DX9 is disabled.
Linking...
main.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) class irr::IrrlichtDevice * __cdecl irr::createDevice(enum irr::video::E_DRIVER_TYPE,class irr::core::dimension2d<int> const &,unsigned int,bool,bool,bool,class irr::IEventR
eceiver *,char const *)" (__imp_?createDevice@irr@@YAPAVIrrlichtDevice@1@W4E_DRIVER_TYPE@video@1@ABV?$dimension2d@H@core@1@I_N22PAVIEventReceiver@1@PBD@Z)
Debug/AnimatedSpriteExample.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

AnimatedSpriteExample.exe - 2 error(s), 0 warning(s)
And I have irrlicht dll file in the right place.
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

From that report I just understand that it is problem with linking, but not much more since everything mentioned there is Irrlicht stuff.

I see that you compile example code ...can you try to coment out all code related to AnimSprite ...so just general stuff is left (device, drivers, while loop, draw calls) to see what happen ....

Then uncoment parts of code part by part to see what lines cause problem?
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

I fell into despair trying to compile it, from creating D:\programing... like u did (saw it in the projects options) and from trying what you said..
Bummer, well, maybe you can make a zip with VC6 project so I wont have configuration problems (if this is the problem) and make it with v1.3.1 please - if you don't mind, I would really appreciate it.
Thanks anyway..
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Do not use that AnimatedSpriteExample.dev file, it is DevC++ project, I doubt it can be of some help to you. You have to set your own project for VC6. Sorry but I have no experience with VC so I can't help.

I do not have Irrlicht 1.31 instaled on my machine yet but I do not think something need to be changed in code since 1.31 just correct few bugs from 1.3.
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

This is what I did, new project and just added your files and this link error happened.
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

You are not linking against the Irrlicht.lib. Please read the beginner's forum on this topic. You will find hundreds of postings about exactly this problem. It's what happens to every new user who sets up a project on his own...
Ico
Posts: 289
Joined: Tue Aug 22, 2006 11:35 pm

Post by Ico »

Maybe you just forgot to include "irrlicht.lib" into the linker's file list?

You could use i.e.

Code: Select all

#pragma coment(lib,"irrlicht.lib")
to do this.

If you did, it may be outdated or so.
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

I'm so stupid , of course this is the problem! :lol:
Thanks!

Now I see it, Nice work, good job!
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
FuzzYspo0N
Posts: 914
Joined: Fri Aug 03, 2007 12:43 pm
Location: South Africa
Contact:

Post by FuzzYspo0N »

Hhaha, thats ok MasterGod its an easy mistake to make :)

ANyway, i added a reverse / forward flag in the play function (i will try get the code from home today) but maybe the author wants to add to it?

like play(int dir)

then that way you dont need two animations for reversing it? i trie reversing starting and ending numbers ,

But anyway :)

great work on the add
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Reverse animation is good idea. I added suport for reverse animation play. Check first post at the begining. Download link updated.

FuzzYspo0N >> I added one bool flag to Animation structure. If you have found better way, post it here.
Post Reply