ALLEGRO_ANIMATED_BITMAP
Christopher Bludau

EDIT:
Newest version in this post

Hi, as posted in this thread I wanted to think about an animated bitmap and so I wanted to show what I came up with.

1) How you use it.

1// create an array with bitmaps
2ALLEGRO_BITMAP* bitmaps[5];
3bitmaps[0] = bmp1;
4bitmaps[1] = bmp2;
5bitmaps[2] = bmp3;
6bitmaps[3] = bmp4;
7bitmaps[4] = bmp5;
8 
9// then create an animated bitmap
10// - you pass the array of the bitmaps
11// - the amount of time each frame should be visible
12// - the number of frames
13ALLEGRO_ANIMATED_BITMAP* anim = create_animation(bitmaps, 0.1, 5);
14 
15// in you update part you update the animated image
16// you pass the animated bitmap and the delta time
17update_animation(anim, dt);
18 
19//In you drawing part you draw the image like this
20al_draw_bitmap(get_active_animation(anim), x_pos, y_pos, 0);
21 
22 
23// when you are done you free the memory
24destroy_animation(anim);
25 
26 
27// NOTE: if you don't use delta time but fixed frame timing then you
28// pass the amount of passed frames here. You will specify the time each
29// frame should be visible in frames as well when creating the animation

2) The code behind it

1 
2typedef struct ALLEGRO_ANIMATED_BITMAP {
3 int frames; // contains the number of frames
4 float frame_time; // the time each frame should be visible
5 float current_time; // the elapsed time so far
6 int active_frame; // the currently active frame
7 ALLEGRO_BITMAP *bitmaps[]; // containing all the different bmps
8 // for the different frams
9}ALLEGRO_ANIMATED_BITMAP;
10 
11 
12ALLEGRO_ANIMATED_BITMAP* create_animation(ALLEGRO_BITMAP *bitmaps[], float frame_time, int frames)
13{
14 ALLEGRO_ANIMATED_BITMAP *anim;
15 anim = (ALLEGRO_ANIMATED_BITMAP*) malloc(sizeof(ALLEGRO_ANIMATED_BITMAP) + frames * sizeof(ALLEGRO_BITMAP*));
16 anim->frames = frames;
17 anim->active_frame = 0;
18 anim->current_time = 0;
19 anim->frame_time = frame_time;
20 
21 for (int i = 0; i < frames; i++)
22 {
23 anim->bitmaps<i> = bitmaps<i>;
24 }
25 
26 return anim;
27}
28 
29void update_animation(ALLEGRO_ANIMATED_BITMAP *anim, float delta_time)
30{
31 float total_time = delta_time + anim->current_time;
32 int delta_frames = (int)(total_time / anim->frame_time);
33 anim->current_time = total_time;
34 while (anim->current_time > anim->frame_time)
35 {
36 anim->current_time -= anim->frame_time;
37 }
38 anim->active_frame = (anim->active_frame + delta_frames) % anim->frames;
39}
40 
41ALLEGRO_BITMAP* get_active_animation(ALLEGRO_ANIMATED_BITMAP *anim)
42{
43 return anim->bitmaps[anim->active_frame];
44}
45 
46void destroy_animation(ALLEGRO_ANIMATED_BITMAP *animated_bitmap)
47{
48 free(animated_bitmap);
49}

Just the first version of the code.
Tested with allegro 4.9.8. Worked.
The destroy method is probably not doing all it should (destroying the bitmaps?) and the create methid could need some error handling.

So what do you think about it?

SiegeLord

How do you specify ping-pong animations? Looping vs nonlooping? Variable frame-rate?

Matthew Leverton

With what respect do you want us to comment? If by the AD forum, you mean included as part of A5, then I say no. This is something that is hard to abstract away. To do it right, you need a complete framework, which really isn't the same thing as a library (add-on or not).

Christopher Bludau
Quote:

How do you specify ping-pong animations? Looping vs nonlooping?

Didn't think of that. But possible.

Quote:

Variable frame-rate?

Thats one thing I haven't solved yet. Any ideas?

Quote:

With what respect do you want us to comment? If by the AD forum, you mean included as part of A5, then I say no. This is something that is hard to abstract away. To do it right, you need a complete framework, which really isn't the same thing as a library (add-on or not).

Yea, I was looking for that kind of comment. But not only.
Comments about the code are welcome too, or ideas I missed like SiegeLord did.

Would you care to elaborate why this wouldn't fit in a library - or better - why this would need a framework?
I hoped due to the simple update mechanics it was able to be used outside of a framework. Not wanting to change your mind. :) Just want to know what problems you see.

Matthew Leverton

I'm not going to try to define fuzzy terms like "framework," but the point is that there are many ways to do an animated bitmap. To me, the things that should belong in Allegro 5 core or first class add-ons are things that are a) very complex (playing sound) or b) easy to agree on a standard method (loading a PNG file, getting clipboard data).

As soon as one person submits his version of animated bitmaps, somebody else is going to want to submit his own version. Then you have to decide which is better, when in reality they may just be different (and incompatible).

Essentially, I think it's just too high level of a concept. I think that it's something that people will find useful if they like your methodologies, but I think we should be careful about adding all sorts of things like this to Allegro just because we can.

Evert
Quote:

Essentially, I think it's just too high level of a concept. I think that it's something that people will find useful if they like your methodologies, but I think we should be careful about adding all sorts of things like this to Allegro just because we can.

I agree.

Which isn't to say you can't provide something like that in the form of a third party addon. That would be good. We like third party addons.
;)

Christopher Bludau

Ok. Sounds reasonable.

I will try to add the features SiegeLord mentioned tomorrow.
Code/Feature comments welcome. :)

Dustin Dettmer

For those interested, I'm going to ramble on about animation libraries.

Take, for instance, this simple sprite character.

Here is the datafile for the sprite, located at datafile.txt for a nice reference (shown below).

1Angel.walk_right.frames.[+].url=tod/walk_right.1.gif
2Angel.walk_right.frames.[].width=15
3Angel.walk_right.frames.[].height=26
4Angel.walk_right.frames.[].ttl=125
5Angel.walk_right.frames.[+].url=tod/walk_right.2.gif
6Angel.walk_right.frames.[].width=15
7Angel.walk_right.frames.[].height=26
8Angel.walk_right.frames.[].ttl=125
9Angel.walk_right.frames.[+].url=tod/walk_right.3.gif
10Angel.walk_right.frames.[].width=15
11Angel.walk_right.frames.[].height=26
12Angel.walk_right.frames.[].ttl=125
13Angel.walk_right.frames.[+].url=tod/walk_right.4.gif
14Angel.walk_right.frames.[].width=15
15Angel.walk_right.frames.[].height=26
16Angel.walk_right.frames.[].ttl=125
17 
18Angel.walk_left.frames.[+].url=tod/walk_left.1.gif
19Angel.walk_left.frames.[].width=15
20Angel.walk_left.frames.[].height=26
21Angel.walk_left.frames.[].ttl=125
22Angel.walk_left.frames.[+].url=tod/walk_left.2.gif
23Angel.walk_left.frames.[].width=15
24Angel.walk_left.frames.[].height=26
25Angel.walk_left.frames.[].ttl=125
26Angel.walk_left.frames.[+].url=tod/walk_left.3.gif
27Angel.walk_left.frames.[].width=15
28Angel.walk_left.frames.[].height=26
29Angel.walk_left.frames.[].ttl=125
30Angel.walk_left.frames.[+].url=tod/walk_left.4.gif
31Angel.walk_left.frames.[].width=15
32Angel.walk_left.frames.[].height=26
33Angel.walk_left.frames.[].ttl=125
34 
35Angel.up_right.frames.[+].url=tod/up_right.1.gif
36Angel.up_right.frames.[].width=15
37Angel.up_right.frames.[].height=26
38Angel.up_left.frames.[+].url=tod/up_left.1.gif
39Angel.up_left.frames.[].width=15
40Angel.up_left.frames.[].height=26
41 
42Angel.hover_right.frames.[+].url=tod/hover_right.1.gif
43Angel.hover_right.frames.[].width=15
44Angel.hover_right.frames.[].height=26
45Angel.hover_left.frames.[+].url=tod/hover_left.1.gif
46Angel.hover_left.frames.[].width=15
47Angel.hover_left.frames.[].height=26
48 
49Angel.down_right.frames.[+].url=tod/down_right.1.gif
50Angel.down_right.frames.[].width=15
51Angel.down_right.frames.[].height=26
52Angel.down_left.frames.[+].url=tod/down_left.1.gif
53Angel.down_left.frames.[1].width=15
54Angel.down_left.frames.[].height=26

When the sprite starts walking right the display switches to walk_right at the first frame. After 125 milliseconds the next frame is shown and so on.

The system needs to be smart enough to accept events that cause a frame to start over at frame 0 and loop from there. You also need to be able to "run once" and quit.

Another thing to consider: What if the game pauses? In certain cases the animations should pause as well. Also, what if the computer goes to sleep for some length of time and returns? This last one is a harder problem that I think is mostly safe to ignore though an easy solution would be worth considering.

Milan Mimica

You should to it in spirit of A5 - emit an event when an animated bitmap is updated.

Trezker

I think you should have ALLEGRO_ANIMATION to which you can load an animation file.
Then an ALLEGRO_ANIMATION_INSTANCE with functions for playback of an animation.

Thus you can use the same animation at different speeds and loop settings at the same time.

Christopher Bludau
Quote:

For those interested, I'm going to ramble on about animation libraries.

Will have a look at this. Thanks!

Quote:

Another thing to consider: What if the game pauses? In certain cases the animations should pause as well.

If the game pauses then it shouldn't call the update methods for any of its containing objects. Not doing so causes the animation to pause too.

Quote:

Also, what if the computer goes to sleep for some length of time and returns? This last one is a harder problem that I think is mostly safe to ignore though an easy solution would be worth considering.

After such a case the delta time would be huge updating the bitmap accordingly and correct. Or I misunderstood you here.

Quote:

You also need to be able to "run once" and quit.

I will add nonlopping animation today after work. What do you mean with quit?
That the animation gets destroyed?

Quote:

You should to it in spirit of A5 - emit an event when an animated bitmap is updated.

Ok. Will have to look into that.
When should the event be emitted? When the update method is called? Or when the animtaion is switching to the next frame?
The second thing seems more logically.
What happpens if the delta time is so huge, that the animtaion is skipping one frame. Should only one event be emitted? Or should the amount of events be similar to the skipped frames?

EDIT:

Quote:

I think you should have ALLEGRO_ANIMATION to which you can load an animation file.
Then an ALLEGRO_ANIMATION_INSTANCE with functions for playback of an animation.

Thus you can use the same animation at different speeds and loop settings at the same time.

Don't think I get what you mean here. Could you explain a little bit more?

Audric

Most games needs much more than just sprite number + duration on each frame.
Some examples:
- character dimensions, for axis-aligned bounding box.
- sprite offsets
- collision flags (think a Street fighter animation : which parts of character are hitting, which parts are vulnerable)
- position of "attachments" (character holding an object: which Shield sprite do we display, at which coords.)
- a function pointer, to handle anything.

Each game has different needs, so the best system for a tactical RPG isn't going to be good for a VS fighting game or a platform shooter.

Christopher Bludau

Yea. But originally I only wanted to do an animated bitmap. That has nothing to do with all the collision stuff... but i get you point here.

But this proofs why it would be a bad idea to integrate something like that into allegro.

Trezker

I give code example.

1ALLEGRO_ANIMATION* my_animation = al_animation_load("animated_thing.ani");
2//Instances hold a pointer to the animation.
3ALLEGRO_ANIMATION_INSTANCE *slow_thing = al_animation_create_instance(my_animation);
4ALLEGRO_ANIMATION_INSTANCE *quick_thing = al_animation_create_instance(my_animation);
5//Set slow thing to run at half speed
6al_animation_set_speed(slow_thing, .5);
7//Set quick thing to run at double speed
8al_animation_set_speed(quick_thing, 2);
9 
10float dt = [insert time code here]
11al_animation_update(slow_thing, dt);
12al_animation_update(quick_thing, dt);
13 
14al_draw_bitmap(al_animation_current_frame(slow_thing), slow_x, slow_y, 0);
15al_draw_bitmap(al_animation_current_frame(quick_thing), quick_x, quick_y, 0);
16 
17al_animation_destroy_instance(slow_thing);
18al_animation_destroy_instance(quick_thing);
19al_animation_destroy(my_animation);

Christopher Bludau

Ah, ok. Now I got it. I like the idea.

What I don't see is how a variable frame rate would be possible with this.
But I think that wasn't your goal to show with this approach.
But I already have an idea how to solve the varialbe frame rate thing.

Edgar Reynaldo
Quote:

What I don't see is how a variable frame rate would be possible with this.

You can take a look at a C++ animation example I coded up a while ago :
http://www.allegro.cc/forums/thread/599116/792937#target

Look at the AnimBase::AdvanceTime function to see what I did for it. All you have to do is store the frame rate in seconds per frame and store the residual time accumulated so far. When it exceeds the frame rate, advance by the correct number of frames using division and then assign the residual time a new value using modulus and the frame rate.

Kotlet

I am currently coping with bitmap animation as well. Ideas spread by you guys around the forum helped me a lot, thank you all. In my opinion Trezker's idea is very interesting. Keeping bitmap sequences and animation instances separate makes stuff more flexible. Keep them in two data structures in some animation manager object and you got everything simple and under control.

Christopher Bludau

Ok, a new version is finally available.
New features are:
- varialbe frame rate
- looping
- ping pong
- Trezker's animation_instance idea

What's missing:
- events (haven't looked into allegro's events yet, if you have tips feel free to say where I can look)
- loading from file so the arrays and stuff don't have to be created manually

1) So again first how you would use it:

1// create an array with bitmaps
2ALLEGRO_BITMAP* bitmaps[5];
3bitmaps[0] = bmp1;
4bitmaps[1] = bmp2;
5bitmaps[2] = bmp3;
6bitmaps[3] = bmp4;
7bitmaps[4] = bmp5;
8 
9// crate an array with frame times
10float frame_times[5];
11frame_times[0] = 0.5;
12frame_times[1] = 0.5;
13frame_times[2] = 0.5;
14frame_times[3] = 0.5;
15frame_times[4] = 0.5;
16 
17 
18// then create an animation
19// - you pass the array of the bitmaps
20// - array with frame times
21// - the number of frames
22ANIMATION* anim = create_animation(bitmaps, frame_times, 5);
23 
24 
25// then you create an animation instance
26// - you pass the animation
27// - whether it should loop or not
28// - ping pong or not
29// - the speed multiplier
30// this would be a non ping pong, looping animation with doubled speed
31ANIMATION_INSTANCE* anim_instance = create_animation_instance(anim, true, false, 2.0);
32 
33// in you update part you update the animation_instance
34// you pass the animated bitmap and the delta time
35update_animation(anim_instance, dt);
36 
37//In you drawing part you draw the image like this
38al_draw_bitmap(get_active_animation(anim_instance), x_pos, y_pos, 0);
39 
40 
41// when you are done you free the memory
42destroy_animation(anim);
43destroy_animation_instance(anim_instance);

2) the code

1typedef struct ANIMATION_FRAME {
2 float frame_time; // the time this frame should be visible
3 float current_time; // the elapsed time so far
4 ALLEGRO_BITMAP *bitmap;
5} ANIMATION_FRAME;
6 
7typedef struct ANIMATION {
8 int frame_count; // contains the number of frames
9 int active_frame; // the currently active frame
10 ANIMATION_FRAME *frames[]; // containing all the different bmps
11 // for the different frams
12}ANIMATION;
13 
14typedef struct ANIMATION_INSTANCE {
15 bool run; // is set to false after a total animation
16 // if looping is false
17 bool looping;
18 bool ping_pong;
19 int direction; // 1 = upwards, -1 = downwards (for ping pong)
20 float speed_multiplier;
21 ANIMATION *animation;
22} ANIMATION_INSTANCE;
23 
24 
25ANIMATION* create_animation(ALLEGRO_BITMAP *bitmaps[], float frame_time[], int frame_count)
26{
27 ANIMATION *anim;
28 anim = (ANIMATION*) malloc(sizeof(ANIMATION) + frame_count * sizeof(ANIMATION_FRAME));
29 anim->frame_count = frame_count;
30 anim->active_frame = 0;
31 
32 for (int i = 0; i < frame_count; i++)
33 {
34 ANIMATION_FRAME *f = new ANIMATION_FRAME;
35 f->bitmap = bitmaps<i>;
36 f->current_time = 0;
37 f->frame_time = frame_time<i>;
38 anim->frames<i> = f;
39 }
40 
41 return anim;
42}
43 
44ANIMATION_INSTANCE* create_animation_instance(ANIMATION *anim, bool looping, bool ping_pong, float speed_multiplier)
45{
46 ANIMATION_INSTANCE *anim_instance = new ANIMATION_INSTANCE;
47 anim_instance->animation = anim;
48 anim_instance->looping = looping;
49 anim_instance->ping_pong = ping_pong;
50 anim_instance->speed_multiplier = speed_multiplier;
51 anim_instance->run = true;
52 anim_instance->direction = 1;
53 
54 return anim_instance;
55}
56 
57void update_animation(ANIMATION_INSTANCE *anim_instance, float delta_time)
58{
59 ANIMATION *anim = anim_instance->animation;
60 int i = anim->active_frame;
61 while (delta_time > 0 && anim_instance->run)
62 {
63 if (i >= anim->frame_count)
64 {
65 // restarts a lopping anim at frame 0
66 if(anim_instance->looping && !anim_instance->ping_pong)
67 i = 0;
68 
69 // reverses the ping pong direction
70 if(anim_instance->ping_pong)
71 {
72 // we don't want to see the last frame twice
73 // that's why we substract 2
74 i = anim->frame_count-2;
75 anim_instance->direction = -1;
76 }
77 
78 // animation stop
79 if(!anim_instance->looping && !anim_instance->ping_pong)
80 {
81 delta_time = 0;
82 i = anim->frame_count-1;
83 anim_instance->run = false;
84 }
85 }
86 if (i < 0)
87 {
88 // reverses the ping pong direction
89 if(anim_instance->looping && anim_instance->ping_pong)
90 {
91 // we don't want to see the first frame twice
92 // thats' why we set i to 1
93 i = 1;
94 anim_instance->direction = 1;
95 }
96 
97 // animation stop
98 if(!anim_instance->looping && anim_instance->ping_pong)
99 {
100 delta_time = 0;
101 i = 0;
102 anim_instance->run = false;
103 }
104 }
105 delta_time -= (anim->frames<i>->frame_time / anim_instance->speed_multiplier) - anim->frames<i>->current_time;
106 anim->frames<i>->current_time = 0;
107 if(delta_time > 0)
108 i+=anim_instance->direction;
109 }
110 anim->frames<i>->current_time = (anim->frames<i>->frame_time / anim_instance->speed_multiplier) + delta_time;
111 anim->active_frame = i;
112}
113 
114ALLEGRO_BITMAP* get_active_animation(ANIMATION_INSTANCE *anim_instance)
115{
116 return anim_instance->animation->frames[anim_instance->animation->active_frame]->bitmap;
117}
118 
119void destroy_animation(ANIMATION *anim)
120{
121 for(int i = 0; i < anim->frame_count; i++)
122 {
123 free(anim->frames<i>);
124 }
125 free(anim);
126}
127 
128void destroy_animation_instance(ANIMATION_INSTANCE *anim_instance)
129{
130 free(anim_instance);
131}

So again, comments, ideas, feature requests welcome!

Milan Mimica

I don't think you need events any more.

GullRaDriel

You should include a check and a destroy_animation call into destroy_animation_instance.

I mean:

1void destroy_animation(ANIMATION **anim)
2{
3 for(int i = 0; i < (*anim)->frame_count; i++)
4 {
5 free((*anim)->frames<i>);
6 }
7 free((*anim));
8 (*anim) = NULL ;
9}
10 
11void destroy_animation_instance(ANIMATION_INSTANCE **anim_instance)
12{
13 if( (*anim_instance) -> anim )
14 destroy_animation( &(*anim_instance) -> anim )
15
16 free((*anim_instance));
17 (*anim_instance) = NULL ;
18}

I probably messed up something, but the idea behind that is that when you make a call to destroy_animation_instance it also check and destroy the frames if needed.

Hoping you get what I mean :-/

Christopher Bludau

Yea, I get what you mean.
At first I had this included in the destroy_animation_instance function.

BUT then I thought about it, and one animation could be part of MANY animation_instances (that's the point of the animation_instance).

So only beacuse I destroy one instance I can't destroy the contained animation.
Other instances would stop working then beacause they lost their animation.

Hope that makes sense?

Quote:

I don't think you need events any more.

How comes that?

Dustin Dettmer

What would be really great is datafile integration.

Thomas Fjellstrom
Quote:

You should include a check and a destroy_animation call into destroy_animation_instance.

Maybe I'm just being stupid, but why in the hell would you want to destroy the ANIMATION when you're just freeing the ANIMATION_INSTANCE? Other ANIMATION_INSTANCES could be using that ANIMATION at the time, or you may want to use it again after the call to destroy_animation_instance.

Christopher Bludau

No, not stupid at all.
I think the same as you do here:

Quote:

and one animation could be part of MANY animation_instances (that's the point of the animation_instance).

So only beacuse I destroy one instance I can't destroy the contained animation.
Other instances would stop working then beacause they lost their animation.

Quote:

What would be really great is datafile integration.

Wow, didn't think of that. Nice idea!
Will have to think about the whole animation loading/file/datafile things...

Dustin Dettmer

.gif Import and stuff.

Christopher Bludau
Quote:

.gif Import

Do you mean so that a gif can be converted to an allegro animation?
Sounds interesting. Would have to look into the gif format though.

EDIT:

Ok. It took some time but I was busy with other things.
Today I did a first try at a loading method.

1ANIMATION* load_animation(const char *path)
2{
3 ALLEGRO_FS_ENTRY *ani_file = al_fopen(path, "r");
4
5 char *line = (char*)malloc(300);
6 line = al_fgets(ani_file, 300, line);
7 int amount = atoi(line);
8 
9 ALLEGRO_BITMAP **bmps = (ALLEGRO_BITMAP**)malloc(amount*sizeof(ALLEGRO_BITMAP*));
10 float *times = (float*)malloc(amount*sizeof(float));
11 
12 
13 int i = 0;
14 while(line!=NULL)
15 {
16 line = al_fgets(ani_file, 300, line);
17 if (line!=NULL)
18 {
19 char *filename = line;
20 bmps<i> = al_iio_load(filename);
21 line = al_fgets(ani_file, 300, line);
22 float time = atof(line);
23 times<i> = time;
24 i++;
25 }
26 }
27 
28 ANIMATION *anim = create_animation(bmps, times, amount);
29 
30 free(times);
31 free(bmps);
32 free(line);
33 al_destroy_entry(ani_file);
34 
35 return anim;
36}

Usage now would be

...
ANIMATION* anim = load_animation("test.ani");
ANIMATION_INSTANCE* anim_instance = create_animation_instance(anim, true, true, 2.0);
...

The ani file should look like

2
bmp1.bmp
0.5
bmp2.bmp
0.5

I'm not good with file stuff, so feel free to comment on the loading method.
And currently there is NO error handling. Comments on what should be added are welcome too.

Some issues I really would like to here some comments about:

1) The line can only be 300 chars long, so if a path is passed which is longer theere would be a problem. Solutions?
Maybe:
ANIMATION* load_animation(const char *path, int max_line_length) ?

2) When using the create_.. method the user creates the bitmaps and passed them into. He would be responsible to destroy them. Or in other words: it would be wrong to destroy them in the destroy_animation method because the user may uses them for different things.
But when using the load method the load method creates the bitmaps and it would be wrong to force the user to destroy them.
Maybe a second method destroy_animation_with_bitmaps?
Or should it be forbidden to use the create methos manually? So the load method would be the only option and the destroy_animation methods destroy the bitmaps as well.

3) Because I us al_gets the file has to end with a emempy line.
This will work

frames/newline
bitmapname/newline
time/newline
bitmapname/newline
time/newline

This won't

frames/newline
bitmapname/newline
time/newline
bitmapname/newline
time

Is this a problem?

Alianix

It's none of my business but i would say something like this does not belong in A5, it's too high level and too specific. What i would suggest is a simple function to load an array of bitmaps, like in A4 , from a bitmap file. The bitmaps could be simply stored in the file with some magic colors indicating the boundaries of the bitmaps. This way sequences could be stored in one file instead of loading each frame from a separate one. But again even this is probably too much to ask of the API.Maybe an addon?

Thomas Fjellstrom

It's none of my business but i would say something like this does not belong in A5, it's too high level and too specific.

Its not going to be included in the core. It most likely wont make it into the addons directory either. But we do HIGHLY encourage 3rd party addons.

Peter Wang

Please don't use the ALLEGRO_* or al_* prefixes, though.

Christopher Bludau

@Alianix
Loading an animation from one file is on my list. Still some things I need to plan out.
But I won't use magic colors to set the borders though.
I would just allow only frames that are all the same size, than it will be possible to load the single frames without a visible border.

I removed all al_ or ALLEGRO_ prefixes after it was said that it doesn't belong in the lib.
I just didn't edit the first post.

I have no clue though how a thid party addon would be distributed.
Any hints?

EDIT:
Btw, no comments about the 3 point in my previous post?

Thomas Fjellstrom

I have no clue though how a thid party addon would be distributed.

Find a host some place, possibly SourceForge, BerliOS.de, or GNU Savannah.

But if necessary I wouldn't mind hosting some basic sites for a5 addons at strangesoft.net, could host svn at svn.tomasu.org as well.

Christopher Bludau

I have a site where I could host it.
But I think if the different addons are cluttered on many different sites it will be hard to find them and probably most people won't download them then.

I think if the addons could be found on one site (think of it as the official allegro addon repository ) it will be much easier for people to have an overview about which addons exist.

That doesn't necessary mean that ALL addons have to be accepted. The site owner or the dev team could vote for addons... Or just accept them all. Details which are only interestin if something like this should exist

Thomas Fjellstrom

think of it as the official allegro addon repository

the Official addons are in allegro's svn any others are unofficial.

But putting links to all addons on the wiki, and/or the website would be good.

Dustin Dettmer

Good work! A cool add-on indeed.

I also agree a central add-on website that stays up is a great idea. Indie websites for specific add-ons tend to disappear when people lose interest.

Thomas Fjellstrom

If people have lost interest the addon probably deserves to disappear. Means its no longer supported and SHOULDN'T be used.

Dustin Dettmer

That is just silly. I whole-heartidly disagree with this mindset.

No sense losing things for no good reason. And besides, there <strike>aren't even</strike> barely any add-ons now. Why work to filter something there are none of?

Thomas Fjellstrom

Really? so its page disappears, and it never re appears, and you think its still viable? I don't it means its DEAD.

Why work to filter something there are none of?

Thats just it, we'd have to work harder to put together a common repo for 3rd party addons, and support it. If YOU want to do that, go right ahead. I doubt any of the devs will.

Dustin Dettmer

Someone else might want to take over the project.

Thomas Fjellstrom

Someone else might want to take over the project.

Then they likely already have a copy.

Alianix

Chris,

I've long wanted to work on such an addon I mentioned earlier. Maybe we could put it together and save some time for each other hopefully. However, i think it should be flexible enough to interpret an array of bitmaps of different size, this way it will always work, whether they are the same size or not. There are situations when it's just a waste of space to have all the same size bitmaps. It does make coding it more difficult though. Let me know if u are up to sharing ideas on this.

...Could avoid multiple files and .ani file with using the memfile and zip loaders from the API.(I don't know if it's complete yet)

Christopher Bludau

Do you want different animations with different sizes in one bitmap? Or do you want to support animations where each frame of ONE animation have different sizes?

If the first then the solution I think about will support that do (without the borders but with some minimal input from the user).
If the second I initially didn't plan on supporting this because when the frames have different sizes you need some more infos. For example the offset of each frame to the position of the animation. It's something to think about what would be more usefull and still stay useable.

Alianix said:

...Could avoid multiple files and .ani file

The ani file would still be needed. Otherwise you would have no place where you specify the frame times.

Good work!

Thanks! Happy to hear you like it

Alianix

I guess if it has different animations on one bitmap the .ani file is justifiable, and in either case it should be able to support varying size frames for the particular animation. This could be easily implemented with some border color coding, or it could be stored in the .ani file. I prefer the use of the .ani file as little as possible. The reason is that it's easier to organize frames on a bitmap in a drawing program, and then have the loader sort it out. This gives flexibility while designing graphics. Otherwise much time will be spent on manually counting pixels and entering data into the .ani which is prone to error not to mention tedious. Let the machine do the tedious work...

#SelectExpand
1/* 2Here's one of the ideas i had on the bitmap layout. 3magic_color1 = 0 (could be white) marks the bounding box 4magic_color2 = 1 (could be black) marks the outside corners of the frame 5 6A Bitmap holding 4 frames of two different animations of different size frames: 7 810000000000010000000000000000 <- 2 Animation frames for first sequence 90XXXXXXXXXX00XXXXXXXXXXXXXXX0 (Only pixels of X-s are part of frames.) 100XXXXXXXXXX00XXXXXXXXXXXXXXX0 110XXXXXXXXXX00XXXXXXXXXXXXXXX0 120XXXXXXXXXX00XXXXXXXXXXXXXXX0 130XXXXXXXXXX00XXXXXXXXXXXXXXX0 140000000000010XXXXXXXXXXXXXXX0 15 0XXXXXXXXXXXXXXX0 16 00000000000000001 17 181000000000001000000000000000000 <- 2 Animation frames for 2nd sequence 190XXXXXXXXXX00XXXXXXXXXXXXXXXXX0 200XXXXXXXXXX00XXXXXXXXXXXXXXXXX0 210XXXXXXXXXX00XXXXXXXXXXXXXXXXX0 220XXXXXXXXXX00XXXXXXXXXXXXXXXXX0 230XXXXXXXXXX00XXXXXXXXXXXXXXXXX0 240000000000010XXXXXXXXXXXXXXXXX0 25 0XXXXXXXXXXXXXXXXX0 26 0XXXXXXXXXXXXXXXXX0 27 0000000000000000001 28 29 30Sorry this sucks these should be square. 31 32New line of bitmaps marks new sequence (animation). 33 34The .ani file should have info about the name of the animations also. 35 36Then maybe like: 37*/ 38typedef struct ANI_FILE{ 39 char bitmap_file[]; // the file containing the animations 40 char *name_list[]; // possible list of names of the animations 41}ANI_FILE;

All other data can be figured out from the bitmap layout.

Christopher Bludau

To be honest I dont like the bitmap border idea.
What if one animation has a transparent (read magic pink) background, another one has a black, another one a white, red, green.... background.
What colours do you want to choose for the borders then?
In my opinion this is too limiting.

Another reason I don't like it is because the loading would be slow. Getting pixel information is not the fastest thing. So for me it is also a performance issue.

Also if you don't want the user to make the dirty work hacking numbers into a file I would take it one step further.
Don't let the user do the dirty stuff in the bitmap editor as well.
What I mean is that it would be possible to write an editor where the user can create the animation and the editor will save the ani file with the needed information and the huge bitmap with all the needed frames.

That's the way I would like to go. Much cleaner in my opinion because it's not so limiting (border colour problem) and better load performance. And the editor will deliver a nice enduser experience

If you disagree please continue to post
Didn't want to talk your idea down. Just wanted to share my ideas. Maybe you like them or maybe you havzze some points for your idea I didn't got yet and in the end your idea will be better.

Alianix

"To be honest I dont like the bitmap border idea."

A: All pixels within the bounding square would be part of the frame like it says in my diagram.

"What colours do you want to choose for the borders then?"

A: The bounding square's two magic colors could be any colors actually, just tell the loader that the first two pixel colors in the bitmap are the magic colors.:), (and like i said all else within the square is part of the frame regardless of it being a magic color or not. I will post the code here soon if's not clear how this algorithm would work, and the good thing also is that it shows clearly the boundaries of the frames while u are editing which is nice so you can clearly see the pixel offsets of the sprites.)

"Another reason I don't like it is because the loading would be slow. Getting pixel information is not the fastest thing. So for me it is also a performance issue."

A: I don't know what you are referring to being slow. Once you load the bitmap into memory reading pixels off it would be pretty fast especially if it's a memory bitmap. Say you have a 64x64 bitmap u will read about 128 pixels before you can determine the size of the frame. I can hardly see this as a performance problem.

I'm open and flexible on the frame storing issue if you don't like it for some reason it's not a big deal, we can change that.

However I firmly against having to write an editor to save some bitmaps image just so you can have .ani., it's too much work for so little gain and there are plenty of graphics editors out there and I don't think we should need another one. Also most people want to use editors they are used to rather then having to learn another one just to make some animation frames.;)

Christopher Bludau

On the train so only short reply from my mobile.

I still see the problem if you want to add an animation which has the background color that you are currently using for the magic colors. Then you would have to change the borders in the whole bitmap.
I admit that this is a rare case. But it still makes me feel uneasy.

Quote:

reading pixels of it would be pretty fast

Maybe it's fast. But not needing to do it at all is faster
And if you want to save multiple animations in one file it can get bigger than 64x64 easily. So you would have to chack many pixels.
Loading is a onetime process. So maybe it doesn't even matter that much. But I could imagine that when loading much animations or a big file it will be noticeably slower when it needs to check many pixels.

About the editor:
I didn't mean to write a bitmap editor but an animation editor.
You create the single frames with the tool you like and then use the animation editor to load your bitmaps and create the animation with it.

There is one thing I need to think about. If multiple animations are stored in one bitmap would it be faster to create small bitmaps for internal use or should all animations work with the big file. If the solution with one big file is better (which I could imagine becuase I read that graphic cards like one big file better than much small ones) than the freeing of the bitmap could not be done when one animation is deleted because the other animations created from this bitmap would still need it.
So the bitmap could only be destroyed when the last animation gets destroyed. I have something in my mind but I need to think about it a little more.

Alianix

You can use any color you want as long as it is consistent throughout the bitmap. So the color issue is not really there. Each bitmap can have it's own different border color code.
The loader would recognize that whatever colors u chose as the first two pixels are the border markers. So obviously don't use the same color for borders as your background, mainly because its hard to see the difference. From the loader's point of view it would not matter even if you chose the same colors.

It would be interesting to check if it would be faster in your method actually. Reading formatted input from a file actually takes a while. I'm not sure if it's even faster then reading some pixels from memory. We could test that i guess. But in any case I don't think you would gain or loose significant performance, maybe less then a percent.

(surely, if you have a bunch of large size frames this is not true...but we are not designing a new hd video codec here are we ...? most sprite animations are pretty small less then 100 pixels dimensions.)

I think going with the one big bitmap is the way to go for the same reasons you mentioned.
Also Usually when loading animations they will go into some bitmap_frames array. Once they are all processed in this way the containing bitmap and file could be discarded. Why would you want to load only part of your animations ?

Christopher Bludau

If you use the big bitmap how can that be discarded? The animations would only contain a pointer to this big bitmap and additional info where to find the frame.
So I don't get what you mean with discarding it after processing is finished...

[EDIT]
What I mean was this

If multiple animations are stored in one bitmap would it be faster to create small bitmaps for internal use or should all animations work with the big file.

So I want to load the big bitmap once and then only use this. Using this solution the bitmap couldn't be discarded because it is the only source for the animations.
I think your solution sounds more like creating mcuh small bitmaps out of the big bitmap and then discarding it.

Which one makes more sense was the question I had. I didn't mean to load only a part of the big bitmap.
[/EDIT]

I also don't get how your loader works when the border/corner has the same colour as the background. How would you determine the end of one animation or frame when the border is no longer existent?

Maybe I misunderstood something

And one more question.
I still don't get how you want to solve the offset problem without the ani file?

And with your solution I think the different animation frames are besides each other and the different animations are one below the other.
It would not be possible to align them freely in the file. Which would make sense if you have some space unused somewhere. Would be good to use it and place different animation besides each other as well.

Alianix

"If you use the big bitmap how can that be discarded?"

It should not be needed since the frames will be used individually as part of a new bitmap array. Otherwise do you want to have to use sub bitmap blitting in AL5 ?

"I think your solution sounds more like creating mcuh small bitmaps out of the big bitmap and then discarding it"

Yepp that's what i was thinking... You would need an extra structure holding the position and size info with your method, then do sub bitmap drawing...I don't see why this is better...

"I also don't get how your loader works.."

I will post some code for this, but if you look at my diagram closely u can see that i use two magic colors one is the corners (1) and (0) is the border...

"I still don't get how you want to solve the offset problem without the ani file?"

You mean the offset of the sprites ?

And yes, with my method there may be some wasted space. It's hard to avoid that if you have different sized frames with either method.

Yes, I see the advantages of your method, I don't see a seamless implementation of it however, without the mentioned editor...::) Honestly I would hate to have to edit some file to enter correct pixel info and counting pixels manually.

Just had an idea !
Actually My loader code could be used to actually create an .ani file , and then the frames could be loaded with the help of the .ani or optionally maybe with the loader. Basically the loader could read the bitmap info, create an .ani file, then get rid of the borders and the magic colors. I think maybe this is the solution to avoid the editor...:) Of course the .ani file is not created at runtime but is made with a small .ani creator executable.

Like: makeani.exe input.bmp output.ani output.bmp

Christopher Bludau
Alianix said:

You would need an extra structure holding the position and size info with your method, then do sub bitmap drawing...I don't see why this is better...

I don't know if it is better. I just said, that we have to figure out what is better.
a) loading the big bitmap, create lot of small bitmaps, discard the big bitmap
b) load the big bitmap, use this as the blitting source.

The reason why I asked this was this:

which I could imagine becuase I read that graphic cards like one big file better than much small ones

If the big bitmap isn't used internally what is the benefit of puttin all animations in one file?

---

Alianix said:

You mean the offset of the sprites ?

Yes. The offsets will require the most work/pixl counting. When the border bitmap solution doesn't solve this problem I don't see the that much of a benefit because the hardest work would still be done manually (and the border maybe make it even harder to calulate the offset by hand).

---

Quote:

Honestly I would hate to have to edit some file to enter correct pixel info and counting pixels manually.

Yea see your point here :) Totaly agree. It would be a pain.

---

Quote:

Actually My loader code could be used to actually create an .ani file [...]

Sounds interesting. But then there would be still the problem with the offsets which couldn't be generated out of the bitmap file...

Neil Walker
Alianix said:

Otherwise do you want to have to use sub bitmap blitting in AL5 ?

Is that a negative statement saying there's something wrong with sub-bitmaps in A5, or just a general question?

Alianix

Nothing wrong with A5's sub bitmaps I guess,the performance loss is minimal i too, it's just that an extra data structure is needed to hold positions and size.

I thought a lot about offsets before, and i think it could be completely eliminated, the sprite should be placed on the frame including the offset. This is how it's generally done I believe, (but of course this wastes the most space).

Otherwise, again the loader could generate the offsets too and place it in the .ani,then the problem is solved again. (I have not yet figured out how to mark the offsets in the frames though...)

Ok...if we wANT to use sprite offset data, basically we will probably need a hard set magic color for the background I'm afraid, unless I come up something better. I will think about this...

Anyways to understand how the loader/.ani-generator works, just assume that it can generate offsets and position and frame count for the .ani and it can remove the unwanted pixels from the input bitmap to save some space too.)

SiegeLord

Using sub-bitmaps is better for the GPU, in terms of rendering performance.

Christopher Bludau
SiegeLord said:

Using sub-bitmaps is better for the GPU, in terms of rendering performance.

That's what I thought. So using the big bitmap as the source would be better?
(just wanting to make sure i understood correctly)

Alianix said:

it's just that an extra data structure is needed to hold positions and size.

I already have a data structure which contains the frametimes. Adding the offset data would be no problem. Not is size nor in performance.

Quote:

if we wANT to use sprite offset data

If we want to support animations with different frame sizes we have no choice.
We have to use offset data.

Neil Walker

Why do you need to store a data structure? Creating a sub-bitmap just stores a reference to the main graphic so you just create your sub-bitmap and use that.

Just in case you were after features to stick in an animation library, in my animation library I allow any mix of separate graphic files and sub-bitmaps, about 6 or so different looping types, independent 'free' timers, differing animation speeds between frames, semi-automated self-destruction/cleanup, grid based and non-grid based sprite sheets, video/memory/system bitmaps, fading, etc. They are all useful. The animation/graphic file is xml based, rather than some randomly created file format.

Christopher Bludau

Why do you need to store a data structure? Creating a sub-bitmap just stores a reference to the main graphic so you just create your sub-bitmap and use that.

The data structure is currently used to store the frametimes of each frame. This has to be stored somewhere beacuse you can't store that into a bitmap.
The offset has to be stored as well if we want to use only the main bitmap.
A reference to the main bitmap wouldn't be enoguh because you have to know WHERE on this big bitmap the frame is located. This info needs to be stored somewhere too.
Using this solution no sub bitmaps would be created.

Quote:

Just in case you were after...

Some of this feature are already supported as well already.
But when I have some more time I will have a look at it. Thanks

Quote:

The animation/graphic file is xml based, rather than some randomly created file format.

I didn't use xml on purpose.
Using xml would require an aditional dependency.
When I started to write this I set myself the goal that this animation addon will work only with standard c and allegro 5.
No additional libs and no c++ stuff. And currently I don't think it's that bad.

Alianix

Thanks SiegeLord , so subbitmaps are no problem then, I agree on not using XML also only c and AL5.

I have a math test tomorrow so I'll think more about the offset solution after that.

Another question is should it support all pixel formats or only alpha ones?

Ok, I got the offset problem solved for the loader. Basically the frame corner's magic color could be used to store a pixel at the position where the sprite's upper left corner is going to be. The difference between this position and the frames corner is the offset. Again the loader could clean up the wasted space in the bitmap, and write the offset in the .ani.

The good thing about the loader this way is that it can load from an original bitmap, or it can create a .ani and cleanup the bitmap so later the loading will be a breeze.

By the way I wrote the code to test the speed of the loader reading pixel info from memory bitmap vs reading pixel info from a file. Reading from file was 3x faster when the bitmaps are about 100x100 pixels and almost 20x faster with large 800x800 bitmaps. This is with processing about a 100000 bitmaps of course. So this difference would probably not be realistically noticable.::)
I used al_get_pixel() with al_unmap_rgba() vs fscanf(), I will later try reading pixels directly with al_lock_bitmap from a memory bitmap, should be a lot faster...

Christopher Bludau

Ok, new version.

New stuff:
- offsets now supported
- loading animations from one big source bitmap.
The animations can be placed anywhere in the bitmap and one frame could even be used for multiple animations.
- new draw_animation method

TODO:
- more error checking
- more drawing options

Like always, first how to use it :)

1) Usage

A) an animation created from multiple bitmaps
(changed a little, so showing it again)

multiple bitmaps#SelectExpand
1// loading 2ANIMATION *animation = load_animation("test.ani"); 3ANIMATION_INSTANCE *animation_instance = create_animation_instance(animation, looping, pingpong, speed); 4 5// update 6update_animation(animation_instance, delta); 7 8//draw 9draw_animation(animation_instance, pos_x, pos_y); 10 11// destroying 12void destroy_animation(ANIMATION *anim); 13void destroy_animation_instance(ANIMATION_INSTANCE *anim_instance);

B) Now the new bitmap

new big bitmap#SelectExpand
1// at first you load the bitmap containing ALL the animations 2// into an ANIMATION_SET 3ANIMATION_SET *set = load_animation_set("data/all.bmp"); 4 5// when creating the animation the set is passed and used from 6// here on for this animation 7ANIMATION *animation = load_animation_from_set("test_big.ani", set); 8 9//creating the instance, update and draw are the same as above 10 11// destroying 12void destroy_animation(ANIMATIOanimation); 13void destroy_animation_instance(ANIMATION_INSTANCE *anim_instance); 14void destroy_animation_set(ANIMATION_SET *set);

2) File formats

for multi bitmap animatios#SelectExpand
1framecount 2path/bitmapname 3frametime 4offset_x 5offset_y 6...

for set animation#SelectExpand
1framecount 2frametime 3pos_in_set_x 4pos_in_set_y 5size_x 6size_y 7offset_x 8offset_y 9...

3) The code

Ok.. with the code in the code tags the post is too big :)
Will attach the files

Alianix

I'm speechless...:-X;D

Chris, Is that all the code u wrote so far for this?

I just don't wanna start writing some of this if you already did it. I don't see any loader specs or .ani file structures and such.

Christopher Bludau

Yea, the code in the attached source files is all thats needed do to the above things(loading, updating, drawing an animation either from multiple bmps or from one file).
So all the features I mentioned already work.

The ani file structure is not put in any structs.
The loading methods just assume that the file is in the specified format and loads the values in the specified order.

Are you speachless because you like it or because you don't like it/you expected more?

Peter Wang

It's time to move this thread to a different part of the forum. Thanks.

Alianix

Hmmm, it seems like we are getting moved...anyways...

...I was speechless because I did not expect you've written all that already.
::)

It looks pretty good to me so far. Some thoughts / questions:

1) Do we really need and extra struct for ANIMATION_INSTANCE? All this could fit into ANIMATION itself, or are you thinking of having different instances of the same animation? I don't see too much use of this but u tell me...

2) I would like to see some identifiers in the ANIMATION structure, like a "char *name" string & "int id". This very handy when loading or drawing animations can be referred to by their names for example. If you have multiple animations of characters on a bitmap for example. The .ani should contain these strings for each sequence so when it's loaded they'll get a nice name & id.

3) Please, please, can we not do things like this:
;D

ANIMATION_FRAME *f = new ANIMATION_FRAME;

4) It would be nice to provide some function to load individual frames.
Maybe like so:

ALLEGRO_BITMAP* get_animation_frame(ANIMATION_SET *set, char *animation_name, int frame_index);
ANIMATION_FRAME* get_animation_frame(ANIMATION_SET *set, char *animation_name, int frame_index);
ALLEGRO_BITMAP* load_animation_frame(const char *path, char *animation_name, int frame_index);
ANIMATION_FRAME* load_animation_frame(const char *path, char *animation_name, int frame_index);

I'm working on the bitmap loader so I will post it.... It should conform to whatever you have so far.

...Nice photo's...what linux distro do you use ?

Christopher Bludau

1)
With the ANIMATION_INSTANCE you can load one ANIMATION and then do something like this:

ANIMATION_INSTANCE *normal = create_animation_instance(animation, looping, pingpong, 1);
ANIMATION_INSTANCE *half_speed = create_animation_instance(animation, looping, pingpong, 0.5);
ANIMATION_INSTANCE *double_speed = create_animation_instance(animation, looping, pingpong, 2);

So you have only ONE animation in memory and you can play that animation with different speeds. One animation could be looping one not, or one of them could be a pingpong animation.

So, it could fit into the animation itself, but you would loose this possibility then.
At first I had ONLY the animation. But Trezker posted the idea with the animation_instance and I really liked the idea.

2)
Should be no problem. But I don't see how it can be used.
When you have a pointer to the animation you are able to get the name.
But why would you want to? You already have the animation and probably know what it is?

3)
I don't see what this would produce? It would only contain an empty animation without any data since nothing is loaded from a file (since no file was specified)

But the answer is simple. Since this is a C lib and new is a c++ keyword this is out of question anyway.

Alianix said:

I'm working on the bitmap loader so I will post it.... It should conform to whatever you have so far.

Sounds good Looking forward to see it.

Alianix

"I don't see what this would produce? It would only contain an empty animation without any data since nothing is loaded from a file (since no file was specified)"

I was trying to ask you NOT to use "new", I think you misread... ::) Or did you not code this , it's from your animation.c ?
:o

ANIMATION_SET* load_animation_set(const char *path)
{
  ALLEGRO_BITMAP *bitmap = al_iio_load(path);
  ANIMATION_SET *set = new ANIMATION_SET;  //<- HERE
  set->bitmap = bitmap;
  return set;
}

Christopher Bludau

I'm crazy... or an idiot
Seems I didn't think when I wrote that lines

Will fix it later!

Alianix

;D;D....;) That's funny ...ok I'm glad we are over that bump...by the way there is lot more of those in the code...

So the "name" thing is kinda neat, if let's say you wanna have a game editor, or you have a bitmap with animations of different objects. It just helps to work with them outside your program. I don't know if I'm making sense, but it's very useful ??? :)

Christopher Bludau

Replaced the new statments with mallocs.
Updated the attachments in the thread with the newest version.

aniquilator

Hello dude.
Good working with animations...
I have done something like your work here with animations, and I will give you some tips about how I have done my animation class an so... (just to share).
I have done a class called spritePack, its like a class with a vector of BITMAP*...
but in each bitmap a put an offset for each sprite, and 2 fields for identification purposes, group and group_id. each frame has its group and its gorup id...
you can a name too...
I have an animation class too... this animation class is made of a vector of frames...
a frame have a group and a group_id of the sprite to display, a delay time, a mirroring stuff, and other minor effects, and an field called true id... it stores the true id of the sprite in the spritepack.
And finally we got an AnimationHandler class, it's a class that receives the animation obj and the spritePack obj...
this class have the frameOn field, and a timeOn field.
you pass the animation and the spritePack to it, so the first thing it does is to optimize the animation finding the correct indexes to each frame in the animation...
I don't know if what I'm saying here will help you, give you more ideas... but I'm trying

with this concept, you can have a obj with all your sprites and a lot of animation obj that uses a lot of sprites in this pack, you can use the same sprite a lot of time, and you will never have to allocate space for the same bitmap...

Christopher Bludau

Thanks for the tips.
The animations routines I wrote work similar to the classes you descriped.
Even loading a bitmap only once and then reuse it is possible.

The only real difference is that it is not made with classes and vectors.
Just structs and dynamic arrays. The reason for this is, because it should only use plain C and no C++ stuff
So it can be used together with allegro which is a plain C lib as well.

aniquilator

When I said vector and classes my intention was to generalize them...
you know. good work dude... perhaps[off] do you know why my game topic was closed?[/off]

LennyLen

do you know why my game topic was closed?

If you mean this thread, it's because threads automatically get closed after a week of inactivity.

Alianix

Chris, I'm making the offset coding now ...I was debating whether to have negative offsets also or not, but i think for now I'm going to include it even though it makes it all a lot more complicated and it's seemingly useless. All offsets will be relative to upper left corner of the sprite's always.

Also ,I'm not sure exactly what set_pos_x in your frame struct refers to ?

Christopher Bludau
Quote:

Also ,I'm not sure exactly what set_pos_x refers to ?

The name is probably not the best.
It refers to the x position of the animation frame in the animation_set.
So its the position in pixels of the frame in the big bitmap.

Alianix

I see so I guessed it right then.
::)

(Ok, I'm eliminating negative offsets, there is really no need because their effect can always be emulated by using larger positive offsets in the frame set. Done...)

Chris, I found a small oversight in your code, you are allocating too much space for frame pointers...

#SelectExpand
1ANIMATION* create_animation_set(ANIMATION_SET *set, float frame_time[], int set_poss_x[], int set_poss_y[], int sizes_x[], 2 int sizes_y[], int offsets_x[], int offsets_y[], int frame_count) 3{ 4 ANIMATION *anim; 5 anim = (ANIMATION*) malloc(sizeof(ANIMATION) + frame_count * sizeof(ANIMATION_FRAME)); 6 7/* SHOULD BE like this 8 9 anim = (ANIMATION*) malloc(sizeof(ANIMATION) + frame_count * sizeof(ANIMATION_FRAME *)); <- allocate for pointers not the whole struct 10 11*/ 12 13 anim->frame_count = frame_count; 14 anim->active_frame = 0; 15 anim->type = ANIMATION::SET; 16 anim->animation_set = set; 17 18 for (int i = 0; i < frame_count; i++) 19 { 20 ANIMATION_FRAME *f = (ANIMATION_FRAME*) malloc(sizeof(ANIMATION_FRAME)); 21 f->current_time = 0; 22 f->frame_time = frame_time[i]; 23 f->set_pos_x = set_poss_x[i]; 24 f->set_pos_y = set_poss_y[i]; 25 f->size_x = sizes_x[i]; 26 f->size_y = sizes_y[i]; 27 f->offset_x = offsets_x[i]; 28 f->offset_y = offsets_y[i]; 29 anim->frames[i] = f; 30 } 31 32 return anim; 33}

Same thing later in create_animation_multi()...

Also Here this is not C:

  if (anim_instance->animation->type == ANIMATION::MULTIPLE_BITMAPS){} /* <-crime scene, this is C++*/

;D

I got a super busy week at school, so I'm still working on the bitmap interpreter, I'm probably 50% done with it,hopefully by the end of the week it should be done.

Christopher Bludau
Alianix said:

I found a small oversight in your code

Good catch :D
Fixed. Will attach code later.

Quote:

Also Here this is not C

My C skills are more rusty then I expected... :)
We could also use #defines for this task (and make the type an int). That way we would get rid of the enum completely.

Cons? Pros?
What do you say?

Quote:

hopefully by the end of the week it should be done.

Don't hurry! Take the time you need (for school and coding!) ;)

Alianix

Yes I would say get rid of enum and use #define. It's only a couple of different defines anyhow so make it an int I guess.

Thanks ! 8-)

One more thingie...

for( int i = 0;... <- this is not allowed i believe either

int i; for( i = 0;... <- this is OK

Thomas Fjellstrom

I dunno, I've started using Enums a lot more than I used to, and they are valid C, and you get better type checking, and you'll get warned if a switch doesn't cover all enum items (which is usually a good thing).

for( int i = 0;... // this is not allowed i believe either

C99 and GCC is fine with that. C++ is as well (obviously).

Quote:

int i; for( i = 0;... // this is OK

Depends. If you're using C89, it has to go at the top of the function, if you use C99, it can go in the for, or just before the for.

Christopher Bludau
Quote:

for loop stuff

Thanks! Will change that too. Don't know how many will use this with C89 but since it is easy to change I'll do it.

I dunno, I've started using Enums a lot more than I used to, and they are valid C and you get better type checking

I like them because of this reason too. That's why I wanted to use them...
But since I'm more used to C++ than to C I don't know I don't know what is wrong with this statement in C

Alianix said:

if (anim_instance->animation->type == ANIMATION::MULTIPLE_BITMAPS){} /* <-crime scene, this is C++*/

Is the problem that I access the enum via the ANIMATION struct?
Already googled it, but found nothing usefull yet... will search more later.

But if anyone is would point out what the problem with this is I would be glad :)

Arthur Kalliokoski

A struct in C uses a single dot, e.g. ANIMATION.MULTIPLE_BITMAPS

Thomas Fjellstrom

A struct in C uses a single dot, e.g. ANIMATION.MULTIPLE_BITMAPS

You can actually use enum items that way? I didn't think the enum was "namespaced" into the struct itself. But then I only started using Enums after I started using C++ more often.

Alianix

Yep that's news for me too, I don't see any good use of it in our situation yet though...Anyways if Chris wants to keep it that way that's totally fine. I actually kinda like it... ANIMATION.SET, pretty neat...;)

Christopher Bludau

Hmm... when I change it to ANIMATION.MULTIPLE_BITMAPS i get a warning in msvc (C4832).
MSDN said the following:

// C4832.cpp
// compile with: /W1
struct A {
   enum { e };
};

int main() {
   return A.e;   // C4832
   // try the following line instead
   // return A::e;
}

So MSVC wants it with ::

With mingw I get an error: "...\animation_c.c|16|error: expected primary-expression before '.' token|"

???

Alianix

It may be because of your file extension is .cpp so it assumes C++ code, but I'm pretty sure that :: is not C.

It works like this for me: (gcc 4.3.2 linux)

struct ANIMATION {
        enum { THISTYPE, THATTYPE }type;
        }ANIMATION;

    printf("%d\n", ANIMATION.type );

Christopher Bludau

Hmm... I thought that there is a way to deal with enums and structs that is valid in C and C++. ???

I want the code to be usable in a C as well in a C++ program. So I have to find a way that is correct in both languages.
Seems the defines are the easiest solution for now unless someone can point me in the right direction regarding this enum topic...

weapon_S

IIRC using an enum as a namespace (or struct) is not standard.

Thread #599436. Printed from Allegro.cc