我正在为我的一个小型项目开发纹理管理和动画解决方案。尽管该项目使用 Allegro 进行渲染和输入,但我的问题主要围绕 C 和内存管理。我想在这里发布它以获得对方法的想法和洞察力,因为我在指针方面很糟糕。
基本上我要做的是将我所有的纹理资源加载到一个中央管理器(textureManager)中——它本质上是一个包含 ALLEGRO_BITMAP 对象的结构数组。存储在 textureManager 中的纹理大多是完整的精灵表。
从那里,我有一个 anim(ation) 结构,其中包含特定于动画的信息(以及指向纹理管理器中相应纹理的指针)。
为了给你一个想法,下面是我设置和播放玩家“行走”动画的方法:
createAnimation(&player.animations[0], "media/characters/player/walk.png", player.w, player.h);
playAnimation(&player.animations[0], 10);
渲染动画当前帧只是对存储在 textureManager 中的 sprite 表的特定区域进行 blitting 的情况。
作为参考,这里是 anim.h 和 anim.c 的代码。我敢肯定,出于多种原因,我在这里所做的可能是一种糟糕的方法。我想听听他们的消息!我是否正在向任何陷阱敞开心扉?这会像我希望的那样工作吗?
动画.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
动画.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;
}
}
}