Allegro.cc - Online Community

Allegro.cc Forums » The Depot » ALLEGRO_ANIMATED_BITMAP

This thread is locked; no one can reply to it. rss feed Print
 1   2   3   4 
ALLEGRO_ANIMATED_BITMAP
Alianix
Member #10,518
December 2008
avatar

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
Member #7,827
October 2006
avatar

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

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

count
Member #5,401
January 2005

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
Member #210
April 2000
avatar

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.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

count
Member #5,401
January 2005

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
Member #10,518
December 2008
avatar

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...

count
Member #5,401
January 2005

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
Member #10,518
December 2008
avatar

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.

count
Member #5,401
January 2005

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
Member #23
April 2000

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

Alianix
Member #10,518
December 2008
avatar

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 ?

count
Member #5,401
January 2005

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
Member #10,518
December 2008
avatar

"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;
}

count
Member #5,401
January 2005

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

Will fix it later!

Alianix
Member #10,518
December 2008
avatar

;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 ??? :)

count
Member #5,401
January 2005

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

aniquilator
Member #9,841
May 2008
avatar

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...

count
Member #5,401
January 2005

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
Member #9,841
May 2008
avatar

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
Member #5,313
December 2004
avatar

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
Member #10,518
December 2008
avatar

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 ?

count
Member #5,401
January 2005

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
Member #10,518
December 2008
avatar

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.

count
Member #5,401
January 2005

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
Member #10,518
December 2008
avatar

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

 1   2   3   4 


Go to: