2010-03-16 13 views
1

Je travaille sur une solution de gestion et d'animation de texture pour un petit projet de mine. Bien que le projet utilise Allegro pour le rendu et la saisie, ma question tourne principalement autour de la gestion du C et de la mémoire. Je voulais poster ici pour avoir des idées et un aperçu de l'approche, car je suis terrible quand il s'agit de pointeurs. Essentiellement, ce que j'essaie de faire est de charger toutes mes ressources de texture dans un gestionnaire central (textureManager) - qui est essentiellement un tableau de structures contenant des objets ALLEGRO_BITMAP. Les textures stockées dans le textureManager sont pour la plupart des feuilles de sprites complètes. De là, j'ai une structure anim (ation), qui contient des informations spécifiques à l'animation (avec un pointeur sur la texture correspondante dans le textureManager).Question de gestion/pointeur de textures

Pour vous donner une idée, voici comment je configurer et jouer les animation joueurs de marche ':

createAnimation(&player.animations[0], "media/characters/player/walk.png", player.w, player.h); 
playAnimation(&player.animations[0], 10); 

rendu les animations image actuelle est juste un cas de blitting une région spécifique de la feuille de sprite stocké dans textureManager.

Pour référence, voici le code pour anim.h et anim.c. Je suis sûr que ce que je fais ici est probablement une approche terrible pour un certain nombre de raisons. J'aimerais entendre parler d'eux! Est-ce que je m'ouvre à des pièges? Cela fonctionnera-t-il comme j'espère?

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

Répondre

0

Vous pouvez envisager une structure d'animation plus flexible qui contient un tableau de structures de cadre. Chaque structure de trame peut contenir le retard de trame, un décalage de hotspot x/y, etc. De cette façon, différentes images d'une même animation peuvent avoir des tailles et des retards différents. Mais si vous n'avez pas besoin de ces fonctionnalités, alors ce que vous faites est bien.

Je suppose que vous exécuterez la logique à une fréquence fixe (nombre d'images logiques constant par seconde)? Si c'est le cas, les paramètres de délai devraient bien fonctionner.

Un commentaire rapide au sujet de votre code:

textureManager[i].active = true;

Vous ne devriez probablement pas marquer comme actif qu'après avoir vérifié si le bitmap chargé.

Notez également que Allegro 4.9/5.0 est entièrement soutenu par des textures OpenGL ou D3D et, en tant que tel, de grandes images ne pourront pas charger sur certaines cartes vidéo!Cela pourrait être un problème si vous générez de grandes feuilles de sprite. À partir de la version actuelle, vous devez vous en occuper vous-même.

Vous pouvez faire quelque chose comme:

al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP); 
ALLEGRO_BITMAP *sprite_sheet = al_load_bitmap("sprites.png"); 
al_set_new_bitmap_flags(0); 
if (!sprite_sheet) return -1; // error 

// loop over sprite sheet, creating new video bitmaps for each frame 
for (i = 0; i < num_sprites; ++i) 
{ 
    animation.frame[i].bmp = al_create_bitmap(...); 
    al_set_target_bitmap(animation.frame[i].bmp); 
    al_draw_bitmap_region(sprite_sheet, ...); 
} 

al_destroy_bitmap(sprite_sheet); 

al_set_target_bitmap(al_get_backbuffer()); 

Pour être clair: ceci est une limitation de la carte vidéo. Ainsi, une grande feuille de sprite peut fonctionner sur votre ordinateur mais ne pas charger sur un autre. L'approche ci-dessus charge la feuille de sprite dans un bitmap de mémoire (essentiellement garanti pour réussir) et crée ensuite une nouvelle bitmap vidéo accélérée matérielle plus petite par image.

0

Êtes-vous sûr que vous avez besoin d'un pointeur vers pointeur pour ALLEGRO_BITMAP **sprite; dans anim? Les poignées Allegro BITMAP sont déjà des pointeurs, il n'est donc pas nécessaire de les référencer deux fois, car il semble que vous souhaitiez uniquement stocker un bitmap par animation. Vous devez utiliser ALLEGRO_BITMAP *sprite; en anim.

Je ne vois aucun autre problème avec votre code.

+0

Le ALLEGRO_BITMAP n'est pas un pointeur, mais vous êtes par ailleurs correct. Comme il utilise une feuille de sprite (un bitmap avec plusieurs images), il n'aura besoin que d'un seul pointeur vers une seule bitmap. – Matthew