Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411990 Posts in 69441 Topics- by 58486 Members - Latest Member: Fuimus

June 17, 2024, 12:14:42 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Animation class?
Pages: [1]
Print
Author Topic: Animation class?  (Read 3116 times)
Trevor Dunbar
Level 10
*****


Working on unannouned fighting game.


View Profile
« on: January 04, 2009, 12:00:23 PM »

Can someone help me cook up a animation class for C++?

An animation needs to consist of frames, which can be added dynamically- thus frames would be it's own struct/class.
Then frames would consist of time per frame shown, sprite frame to use, character offset, etc.
Logged

Toucantastic.
Gravious
Level 2
**


"Swedish meatballs"


View Profile WWW
« Reply #1 on: January 04, 2009, 12:10:29 PM »

I'm working on one of these at the moment, I'd show you what i have so far, but its not tested yet! Sad

When its running, if you still need help I'll let you look, see if what I'm doing is any use
Logged

One day I'll think about doing something to stop procrastinating.
J.G. Martins
Level 2
**


AKA anvilfolk


View Profile WWW
« Reply #2 on: January 04, 2009, 12:24:57 PM »

I'm no expert, but further separation might be a good idea.

First off, simple images (no actual X,Y positioning, just the image data) should be in one class. Then you could have an animated sprite class that defined sequences of images.

And finally, your displayable on-screen class, that would have position coordinates and a pointer to an animated sprite class, or possibly several, if you want your character to have multiple animations (walking, running, etc). This way, all the information regarding animations only exists in one place.

The animated sprite could be as simple as an array of Image* and a counter (where in the animation you are), along with nextImage() and previousImage() calls.

I hope this helped!

--- edit ---

When you say dynamically, do you mean that an animation will have a variable amount of frames at different times? Or can you know before-hand how many frames each animation will have? Typically, I presume, you'd know how many frames an animation has. In that case, like I said, I suggest a normal array, which you can access directly.

If you plan on modifying the animation itself by adding or removing sprites in mid-game, I suggest using STL's List. I haven't touched STL in a long time, but I know it's a bit more complicated than the above array suggestions, only it avoids creating new arrays all the time to minimize unused space or increasing space.

Watch how you access it though, because using list.get(i) has to perform i iterations, while an array uses a single operation. I suggest looking up iterators (those ugly things, eesh). Java is so much prettier!

But anyway, again, I hope it helps a little, even though it's a little off-topic!
« Last Edit: January 04, 2009, 12:31:17 PM by Anvilfolk » Logged

Gold is for the mistress -- silver for the maid --
Copper for the craftsman cunning at his trade.
"Good!" cried the Baron, sitting in his hall,
"But iron, cold iron, is the master of them all."
--- Rudyard Kipling
Javilop
Level 2
**



View Profile
« Reply #3 on: January 04, 2009, 01:02:10 PM »

That's exactly what IND_AnimationManager and IND_Animation object does. IndieLib is open source, so you can use that classes on your sourcecode.

You have a tutorial here (of how to use make animations using IndieLib and that animation classes), just for showing you an example:
http://www.indielib.com/wiki/index.php?title=Tutorial_04_IND_Animation

Logged
Trevor Dunbar
Level 10
*****


Working on unannouned fighting game.


View Profile
« Reply #4 on: January 04, 2009, 01:11:55 PM »

I already have a sprite class set up- it's part of rendering TO the direct x scene.
The animation class should just tell the sprite what frame to use during our current game loop

I wanted an animation class where you can do this:
psuedo code-

Frames class-
SpriteCell, TimeInFrames, offset, nested CollisionBox class
-end

Create animation blahblah:
Animation
comes with : -frames[0]

ANIMATION *Ani = &blahblah;

//Class function AppendFrame
Ani.AppendFrame(&blahblah, SpriteCell, TimeInFrames, offset, &CollisionBox)
Ani.AppendFrame(&blahblah, SpriteCell, TimeInFrames, offset, &CollisionBox)
Ani.AppendFrame(&blahblah, SpriteCell, TimeInFrames, offset, &CollisionBox)

now blahblah animation looks like this:
Animation
now has: -frames[3]

Then do the same thing with an animationSet, which just stacks animations together in a nice container
« Last Edit: January 04, 2009, 01:19:13 PM by Draco9898 » Logged

Toucantastic.
Javilop
Level 2
**



View Profile
« Reply #5 on: January 04, 2009, 01:17:36 PM »

It is really necessary to set the frames on real time? Why not having them in an XML file in which you can define as many sequences as you wish (like I showed you)?
Logged
Trevor Dunbar
Level 10
*****


Working on unannouned fighting game.


View Profile
« Reply #6 on: January 04, 2009, 01:20:55 PM »

I suppose that makes sense. Adding frames doesn't have to be during run-time. But can the animation have a variable number of frames once created I don't want every animation to take up 50 frames by default

I'm also going to need to create a crappy animation tool that creates something like an encrypted animations file.
Logged

Toucantastic.
Javilop
Level 2
**



View Profile
« Reply #7 on: January 04, 2009, 01:37:49 PM »

Quote
I suppose that makes sense. Adding frames doesn't have to be during run-time. But can the animation have a variable number of frames once created I don't want every animation to take up 50 frames by default

I'm also going to need to create a crappy animation tool that creates something like an encrypted animations file.

Have you check out the link I provided to you? http://www.indielib.com/wiki/index.php?title=Tutorial_04_IND_Animation

Ok, I'll put an example here:

Code:
<?xml version="1.0" encoding="utf-8"?>
<animation>
<!-- frames declaration -->
<frames>
<frame name="Rock1" file="..\resources\animations\advance\Rock_Avanza_01.png" offset_x="2" offset_y="2" />
<frame name="Rock2" file="..\resources\animations\advance\Rock_Avanza_02.png" offset_x="2" offset_y="2" />
<frame name="Rock3" file="..\resources\animations\advance\Rock_Avanza_03.png" />
<frame name="Rock4" file="..\resources\animations\advance\Rock_Avanza_04.png" />
<frame name="Rock5" file="..\resources\animations\advance\Rock_Avanza_05.png" />
<frame name="Rock6" file="..\resources\animations\advance\Rock_Avanza_06.png" />
<frame name="Rock7" file="..\resources\animations\advance\Rock_Avanza_07.png" />
<frame name="Rock8" file="..\resources\animations\advance\Rock_Avanza_08.png" />
<frame name="Rock9" file="..\resources\animations\advance\Rock_Avanza_09.png" />
<frame name="Rock10" file="..\resources\animations\advance\Rock_Avanza_10.png" />
</frames>
 
<!-- sequences declaration -->
<sequences>
<sequence name="rock_advance">
<frame name="Rock1" time="150" />
<frame name="Rock2" time="150" />
<frame name="Rock3" time="150" />
<frame name="Rock4" time="150" />
<frame name="Rock5" time="150" />
<frame name="Rock6" time="150" />
<frame name="Rock7" time="150" />
<frame name="Rock8" time="150" />
<frame name="Rock9" time="150" />
<frame name="Rock10" time="150" />
</sequence>
<sequence name="rock_2">
<frame name="Rock5" time="150" />
<frame name="Rock4" time="150" />
<frame name="Rock3" time="150" />
<frame name="Rock1" time="150" />
</sequence>
</sequences>
</animation>

First you define all the frames (the sprites) (as many as you want). Later you can define as many sequences as you want too. Using references to the frames.

You can also set a collision per frame. Here it is the tutorial: http://www.indielib.com/wiki/index.php?title=Tutorial_08_Collisions

Example:

Code:
<?xml version="1.0" encoding="utf-8"?>
<animation>
<!-- frames declaration -->
<frames>
<!-- Sword Master 1 -->
<frame name="sword1" file="..\resources\animations\sword_master\sword_master01.png" collision="..\resources\animations\sword_master\sword_master01_collisions.xml" />
<frame name="sword2" file="..\resources\animations\sword_master\sword_master02.png" collision="..\resources\animations\sword_master\sword_master02_collisions.xml" />
<frame name="sword3" file="..\resources\animations\sword_master\sword_master03.png" collision="..\resources\animations\sword_master\sword_master03_collisions.xml" />
<frame name="sword4" file="..\resources\animations\sword_master\sword_master04.png" collision="..\resources\animations\sword_master\sword_master04_collisions.xml" />
<frame name="sword5" file="..\resources\animations\sword_master\sword_master05.png" collision="..\resources\animations\sword_master\sword_master05_collisions.xml" />
<frame name="sword6" file="..\resources\animations\sword_master\sword_master06.png" collision="..\resources\animations\sword_master\sword_master06_collisions.xml" />
<frame name="sword7" file="..\resources\animations\sword_master\sword_master07.png" collision="..\resources\animations\sword_master\sword_master07_collisions.xml" />
</frames>
 
<!-- sequences declaration -->
<sequences>
<!-- character 1 -->
<sequence name="sword_attack">
<frame name="sword1" time="1000" />
<frame name="sword2" time="1000" />
<frame name="sword3" time="1000" />
<frame name="sword4" time="1000" />
<frame name="sword5" time="1000" />
<frame name="sword6" time="1000" />
<frame name="sword7" time="3000" />
</sequence>
</sequences>
</animation>

And a collision file is something like this example:

Code:
<?xml version="1.0" encoding="utf-8"?>
<bounding_areas>
<circle id="rocket_boy_head" x="120" y="65" radius="65" />
<triangle id="rocket_head" ax="352" ay="152" bx="300" by="127" cx="300" cy="175" />
<rectangle id="engines" x="20" y="187" width="106" height="30" />
<rectangle id="engines" x="20" y="105" width="40" height="30" />
</bounding_areas>

You have all the sourcecode for doing this on IndieLib repository. Or you can directly use IndieLib engine, this would be easier and faster: you will be able to focus on game logic and I'll be able to help you better in this and in future tasks Wink


   


Logged
Hideous
That's cool.
Level 10
*****


3D models are the best


View Profile WWW
« Reply #8 on: January 04, 2009, 02:02:27 PM »

That's exactly what IND_AnimationManager and IND_Animation object does. IndieLib is open source, so you can use that classes on your sourcecode.

You have a tutorial here (of how to use make animations using IndieLib and that animation classes), just for showing you an example:
http://www.indielib.com/wiki/index.php?title=Tutorial_04_IND_Animation



Man, you pimp IndieLib everywhere.
Logged

Javilop
Level 2
**



View Profile
« Reply #9 on: January 04, 2009, 02:12:43 PM »

Quote
Man, you pimp IndieLib everywhere.

What a pity it is free and I'm not earning anything... wait! It is worse this way, if it is free and nobody uses it the it would be a total disaster. I think I pimp it everywhere because that  Durr...?
Logged
J.G. Martins
Level 2
**


AKA anvilfolk


View Profile WWW
« Reply #10 on: January 04, 2009, 02:21:24 PM »

Just for the record, I'm OK with Loover Hand Money Left pimpin' Hand Money Right his engine everywhere. Sure, I've seen him do it several times (been a lurker), and so have plenty of regulars around here, but hey, until it takes on a following and essentially "promotes itself", there's nothing wrong with trying to get people to use your hard work for free.
Logged

Gold is for the mistress -- silver for the maid --
Copper for the craftsman cunning at his trade.
"Good!" cried the Baron, sitting in his hall,
"But iron, cold iron, is the master of them all."
--- Rudyard Kipling
mirosurabu
Guest
« Reply #11 on: January 04, 2009, 02:37:35 PM »

I tend to use two classes. One called Animation and one called AnimPlayer.

The first one provides interface for loading and locating frame bitmaps. The name is kinda misnomer and names such as "AnimatedBitmap" or "BitmapSequence" are perhaps more appropriate.

Code:
class Animation
{
private:
std::vector <ANIMFRAME> aframes; // Animation frame
public:
// Used for adding new animation frames to class instance
void Add ( BITMAP *bmp );
void Add ( BITMAP *bmp, int d );

// Returns bitmap of animation frame specified by f
BITMAP *GetFrameBitmap ( int f );
int GetFrameDuration( int f ) { return aframes[f].duration; }

void SetIntervalToAll( int d );

int FrameCount() { return aframes.size(); }
};

In order to play animation you will have to keep information on what's current frame, the rate at which animation is played, is it paused or not and such. AnimPlayer class provides this functionality. This is what you use for actual animation.

Code:
class AnimPlayer
{
private:
Animation *animation;

bool paused; // If set to true, calls to FrameTick() will have no effect

int
rate, // Frame-count rate (4-bytes precision)
frame_counter, // Keeps the number of logical frames passed since last animation frame
current_aframe; // Keeps the information about current animation frame

std::string anim_name;
public:
AnimPlayer();
AnimPlayer(Animation *a, char *name);

// Sets animation
void SetAnimation( Animation *a ) { animation = a; }

// Frame bitmaps
BITMAP *FrameBitmap( int f ) { return animation->GetFrameBitmap(f); }
BITMAP *CurrentFrameBitmap() { return animation->GetFrameBitmap(current_aframe); }

// Skips to specific animation frame
void GoToFrame( int f ) { current_aframe = f; }

// Updates animation for one logical frame
void FrameTick ( void );

void Pause() { paused = true; }
void Unpause() { paused = false; }
void SetRate(int r) { rate = r; }

const char *GetAnimName() { return anim_name.c_str(); }
};

To animate you just make call to FrameTick method each frame/tick. To draw, just simply get the current frame bitmap by making call to CurrentFrameBitmap and draw that bitmap onto the screen.

That's how I do it. Maybe not the best solution, but it's fine for my needs.
Logged
handCraftedRadio
The Ultimate Samurai
Level 10
*



View Profile WWW
« Reply #12 on: January 04, 2009, 02:52:35 PM »

If you are just looking for a simple way to do animations, that looks way too complicated to me. The way I do it is with one sprite class who has one image (a sprite sheet). The height and width of each frame are defined when created, and you can tell it which frame to start and stop before the animation is played in the code. The sprite class has an update method that cycles the frames after a certain delay and draws the part of the sprite sheet that is the correct frame.

This may be too simple of a solution than what you are looking for, but it's how I do it, I can provide code if you'd like.
Logged

Gravious
Level 2
**


"Swedish meatballs"


View Profile WWW
« Reply #13 on: January 04, 2009, 02:53:16 PM »

That's exactly what IND_AnimationManager and IND_Animation object does. IndieLib is open source, so you can use that classes on your sourcecode.

You have a tutorial here (of how to use make animations using IndieLib and that animation classes), just for showing you an example:
http://www.indielib.com/wiki/index.php?title=Tutorial_04_IND_Animation



Man, you pimp IndieLib everywhere.

Haha, i was going to say the same :D

nothing wrong with that at all mind you...
Logged

One day I'll think about doing something to stop procrastinating.
Mr. Yes
Level 5
*****



View Profile WWW
« Reply #14 on: January 04, 2009, 03:02:22 PM »

I do it more or less exactly how HandCraftedRadio just explained it (except that mine asks for the width of one sprite and divides the image by that, which actually is pretty dumb since it limits you to one animation per image, SO DON'T LISTEN TO ME).
Logged

J.G. Martins
Level 2
**


AKA anvilfolk


View Profile WWW
« Reply #15 on: January 04, 2009, 03:21:53 PM »

HandCraftedRadio, what you said fits perfectly within these ideas.

Why can't you have a subclass SubImage of the Image class that does exactly what you say? All it does is keep a pointer to the real image, and the rectangle defining the sub-image. As far as I know, most gamedev/graphics API's already allow this, so all that changes is the draw() method, or its equivalent! Grin

It's not that much more work for a system that is so much more expressive and extensible. You can define all sorts of stuff based on this, like centers of mass/pivot points for each sprite, how many ticks each frame will get so you get variable-duration frames, etc etc!
Logged

Gold is for the mistress -- silver for the maid --
Copper for the craftsman cunning at his trade.
"Good!" cried the Baron, sitting in his hall,
"But iron, cold iron, is the master of them all."
--- Rudyard Kipling
handCraftedRadio
The Ultimate Samurai
Level 10
*



View Profile WWW
« Reply #16 on: January 04, 2009, 03:50:01 PM »

That would work, but I tend to do that sort of thing outside of the sprite class. Within the game, if I have some class that has a method, Walk, I would set the walk animation whenever that method is called.

Code:
void Walk()
{
 if (!walking)
 {
  sprite->SetLayer(2); // the animation is on the 3rd layer down from the top
  sprite->SetAnimation(0,4); // animation ranges from frame 0 to 4
  sprite->SetAnimationDelay(5); // slows down animation
  sprite->StartAnimation();
 }
 walking = TRUE;
}

Like I said before, this is just a very simple way to do this. I have never had the need for using anything more complicated than this (like pivot points and center of mass, but I would probably keep that away from the image data too). I just like to keep my stuff simple if I have no use for more complicated things.

All this stuff could be done in the Sprite class or SubImage class as well, it's just a matter of preference I guess.
Logged

Reiss
Level 1
*



View Profile
« Reply #17 on: January 04, 2009, 07:17:52 PM »

If you are just looking for a simple way to do animations, that looks way too complicated to me. The way I do it is with one sprite class who has one image (a sprite sheet). The height and width of each frame are defined when created, and you can tell it which frame to start and stop before the animation is played in the code. The sprite class has an update method that cycles the frames after a certain delay and draws the part of the sprite sheet that is the correct frame.

This may be too simple of a solution than what you are looking for, but it's how I do it, I can provide code if you'd like.

I generally do that too, except instead of an update() method an update_at(int x, int y) method (actually, more like update_at(unsigned int time_passed, int x, int y), but how you decide to pass around the updated time doesn't really matter).  That way I can paint the sprite in a different location on the screen without changing it's coordinates, to allow for an imaginary "camera" in the scene, the advantage of which is performance: in games where the player's character stays centered at some location onscreen, and everything else scrolls, instead of iterating through a list of sprites and moving each one you just change the camera coordinates (and move the player's character back to wherever it's centered) and you're done.

Although if you're doing a non-scrolling game, like the Knytt games, there's no real point using an imaginary camera, so you can disregard everything I said.

HandCraftedRadio, what you said fits perfectly within these ideas.

Why can't you have a subclass SubImage of the Image class that does exactly what you say? All it does is keep a pointer to the real image, and the rectangle defining the sub-image. As far as I know, most gamedev/graphics API's already allow this, so all that changes is the draw() method, or its equivalent! Grin

It's not that much more work for a system that is so much more expressive and extensible. You can define all sorts of stuff based on this, like centers of mass/pivot points for each sprite, how many ticks each frame will get so you get variable-duration frames, etc etc!

Sounds cool - I've never done that before.  Must be especially good for dealing with things like clothing in an RPG-type game, although it sounds like you also use it for physics?  Nice idea.

Although HandCraftedRadio's got a point, if you're just trying to get a simple animation up onscreen, that might be a little much at first.

Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic