I'm working on a texture management and animation solution for a small side project of mine. Although the project uses Allegro for rendering and input, my question mostly revolves around C and memory management. I wanted to post it here to get thoughts and insight into the approach, as I'm terrible when it comes to pointers.
Essentially what I'm trying to do is load all of my texture resources into a central manager (textureManager) - which is essentially an array of structs containing ALLEGRO_BITMAP objects. The textures stored within the textureManager are mostly full sprite sheets.
From there, I have an anim(ation) struct, which contains animation-specific information (along with a pointer to the corresponding texture within the textureManager).
To give you an idea, here's how I setup and play the players 'walk' animation:
createAnimation(&player.animations[0], "media/characters/player/walk.png", player.w, player.h);
playAnimation(&player.animations[0], 10);
Rendering the animations current frame is just a case of blitting a specific region of the sprite sheet stored in textureManager.
For reference, here's the code for anim.h and anim.c. I'm sure what I'm doing here is probably a terrible approach for a number of reasons. I'd like to hear about them! Am I opening myself to any pitfalls? Will this work as I'm hoping?
anim.h
#ifndef ANIM_H
#define ANIM_H
#define ANIM_MAX_FRAMES 10
#define MAX_TEXTURES 50
struct texture {
bool active;
ALLEGRO_BITMAP *bmp;
};
struct texture textureManager[MAX_TEXTURES];
typedef struct tAnim {
ALLEGRO_BITMAP **sprite;
int w, h;
int curFrame, numFrames, frameCount;
float delay;
} anim;
void setupTextureManager(void);
int addTexture(char *filename);
int createAnimation(anim *a, char *filename, int w, int h);
void playAnimation(anim *a, float delay);
void updateAnimation(anim *a);
#endif
anim.c
void setupTextureManager() {
int i = 0;
for(i = 0; i < MAX_TEXTURES; i++) {
textureManager[i].active = false;
}
}
int addTextureToManager(char *filename) {
int i = 0;
for(i = 0; i < MAX_TEXTURES; i++) {
if(!textureManager[i].active) {
textureManager[i].bmp = al_load_bitmap(filename);
textureManager[i].active = true;
if(!textureManager[i].bmp) {
printf("Error loading texture: %s", filename);
return -1;
}
return i;
}
}
return -1;
}
int createAnimation(anim *a, char *filename, int w, int h) {
int textureId = addTextureToManager(filename);
if(textureId > -1) {
a->sprite = textureManager[textureId].bmp;
a->w = w;
a->h = h;
a->numFrames = al_get_bitmap_width(a->sprite) / w;
printf("Animation loaded with %i frames, given resource id: %i\n", a->numFrames, textureId);
} else {
printf("Texture manager full\n");
return 1;
}
return 0;
}
void playAnimation(anim *a, float delay) {
a->curFrame = 0;
a->frameCount = 0;
a->delay = delay;
}
void updateAnimation(anim *a) {
a->frameCount ++;
if(a->frameCount >= a->delay) {
a->frameCount = 0;
a->curFrame ++;
if(a->curFrame >= a->numFrames) {
a->curFrame = 0;
}
}
}