Outils pour utilisateurs

Outils du site


allegro:bitmaps

Allegro — Bitmaps

Dans cet article nous allons voir comment créer des bitmaps et comment dessiner dessus.

Note importante : Allegro 5 utilise un backend OpenGL ou DirectX pour ses Bitmaps, ce qui impose certaines contraintes :
Les bitmaps trop grands(dépend du matériel) ne pourront être créés, et souvent les bitmaps ne pourrons pas être de taille inférieure à 16*16.
De plus la plupart des systèmes n'acceptent que des bitmaps dont la taille est une puissance de 2.
Si on demande à Allegro de créer un Bitmap d'une taille qui ne convient pas au matériel, Allegro renvoie un bitmaps de la première taille au dessus qui correspond.

Pour toutes ces raisons faites attention quand vous dessinez sur votre Bitmap, il se pourrait bien qu'il soit plus grand que vous ne le pensiez !

Buffer de dessin

Allegro 5 introduit le concept de buffer de dessin, le buffer de dessin n'est pas affiché.

Quand on crée un display, on crée automatiquement un buffer de dessin.

Toutes les opérations de dessin doivent se faire sur le buffer de dessin du display actuel.

Exemple basique

Encore une fois il est basé sur l'exemple de l'article précédent.

main.c
#include <stdio.h>
#include <allegro5/allegro.h>
 
const float FPS = 60;
const int SCREEN_W = 640;
const int SCREEN_H = 480;
const int BOUNCER_SIZE = 32;
 
int main(int argc, char **argv)
{
   ALLEGRO_DISPLAY *display = NULL;
   ALLEGRO_EVENT_QUEUE *event_queue = NULL;
   ALLEGRO_TIMER *timer = NULL;
   ALLEGRO_BITMAP *bouncer = NULL;
   float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0;
   float bouncer_y = SCREEN_H / 2.0 - BOUNCER_SIZE / 2.0;
   float bouncer_dx = -4.0, bouncer_dy = 4.0;
   bool redraw = true;
 
   if(!al_init()) {
      fprintf(stderr, "failed to initialize allegro!\n");
      return -1;
   }
 
   timer = al_create_timer(1.0 / FPS);
   if(!timer) {
      fprintf(stderr, "failed to create timer!\n");
      return -1;
   }
 
   display = al_create_display(SCREEN_W, SCREEN_H);
   if(!display) {
      fprintf(stderr, "failed to create display!\n");
      al_destroy_timer(timer);
      return -1;
   }
 
   bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE);
   if(!bouncer) {
      fprintf(stderr, "failed to create bouncer bitmap!\n");
      al_destroy_display(display);
      al_destroy_timer(timer);
      return -1;
   }
 
   al_set_target_bitmap(bouncer);
 
   al_clear_to_color(al_map_rgb(255, 0, 255));
 
   al_set_target_bitmap(al_get_backbuffer(display));
 
   event_queue = al_create_event_queue();
   if(!event_queue) {
      fprintf(stderr, "failed to create event_queue!\n");
      al_destroy_bitmap(bouncer);
      al_destroy_display(display);
      al_destroy_timer(timer);
      return -1;
   }
 
   al_register_event_source(event_queue, al_get_display_event_source(display));
 
   al_register_event_source(event_queue, al_get_timer_event_source(timer));
 
   al_clear_to_color(al_map_rgb(0,0,0));
 
   al_flip_display();
 
   al_start_timer(timer);
 
   while(1)
   {
      ALLEGRO_EVENT ev;
      al_wait_for_event(event_queue, &ev);
 
      if(ev.type == ALLEGRO_EVENT_TIMER) {
         if(bouncer_x < 0 || bouncer_x > SCREEN_W - BOUNCER_SIZE) {
            bouncer_dx = -bouncer_dx;
         }
 
         if(bouncer_y < 0 || bouncer_y > SCREEN_H - BOUNCER_SIZE) {
            bouncer_dy = -bouncer_dy;
         }
 
         bouncer_x += bouncer_dx;
         bouncer_y += bouncer_dy;
 
         redraw = true;
      }
      else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
         break;
      }
 
      if(redraw && al_is_event_queue_empty(event_queue)) {
         redraw = false;
 
         al_clear_to_color(al_map_rgb(0,0,0));
 
         al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0);
 
         al_flip_display();
      }
   }
 
   al_destroy_bitmap(bouncer);
   al_destroy_timer(timer);
   al_destroy_display(display);
   al_destroy_event_queue(event_queue);
 
   return 0;
}

Détails

On ajoute une image rebondissante. On détaillera les nouveautés et modifications.

const int SCREEN_W = 640;
const int SCREEN_H = 480;
const int BOUNCER_SIZE = 32;

On définit des constantes afin de nous rendre la vie plus facile. Les deux premières définissent la taille du Display, et la troisième définit les deux dimensions de l'image.

   bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE);
   if(!bouncer) {
      fprintf(stderr, "failed to create bouncer bitmap!\n");
      al_destroy_display(display);
      al_destroy_timer(timer);
      return -1;
   }

On crée notre image avec al_create_bitmap les paramètres sont la largeur(width) et la hauteur(height), ici c'est BOUNCER_SIZE. En cas d'échec cette fonction renvoie NULL, dans ce cas on nettoie les objets précédemment crées et on quitte le programme.

   al_set_target_bitmap(bouncer);

Ici on introduit un nouveau concept. Le target bitmap est le buffer de dessin dans lequel toutes les fonctions de dessin dessinent. C'est normalement géré par allegro, mais si vous devez dessiner directement dans un bitmap, vous appelez al_set_target_bitmap puis utilisez les fonctions de dessin normalement.

   al_clear_to_color(al_map_rgb(255, 0, 255));

Comme précédemment, excepté que al_clear_to_color va éditer notre bitmap, au lieu du display.

   al_set_target_bitmap(al_get_backbuffer(display));

Remet la cible des fonctions de dessin sur le display.

         if(bouncer_x < 0 || bouncer_x > SCREEN_W - BOUNCER_SIZE) {
            bouncer_dx = -bouncer_dx;
         }
 
         if(bouncer_y < 0 || bouncer_y > SCREEN_H - BOUNCER_SIZE) {
            bouncer_dy = -bouncer_dy;
         }
 
         bouncer_x += bouncer_dx;
         bouncer_y += bouncer_dy;

Pas particulièrement intéressant. C'est le code pour faire le rebondissement. Si le carré touche un bord du display, il change de direction. Ce code est appelé à la suite d'un event de Timer, ainsi le bitmap se déplacera à la même vitesse sur toutes les machines.

         al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0);

dessine notre bitmap sur le display.

   al_destroy_bitmap(bouncer);

Détruit un objet de type bitmap.

Charger des bitmaps depuis le disque

Voici la méthode utilisant les fonctions path d'allegro afin de garantir un code portable

ALLEGRO_BITMAP * get_resource_image(const char * filename) {
   ALLEGRO_PATH *path;
   ALLEGRO_BITMAP *image;
 
   path = al_get_standard_path(ALLEGRO_RESOURCES_PATH);
   al_append_path_component(path, "images");
   al_set_path_filename(path, filename);
 
   image = al_load_bitmap(al_path_cstr(path, '/'));
   al_destroy_path(path);
   return image;
}

Dans ce cas de figure, les ressources de notre jeu sont placées dans le dossier image relativement à l'exécutable.
Ce code fait pointer path sur le dossier contenant le fichier exécutable de notre jeu grâce au paramètre ALLEGRO_RESOURCES_PATH, puis ajoute le dossier “images” et enfin le nom de notre fichier au path.

al_path_cstr(path, '/') permet de rendre notre path valide sur tous les OS.

La fonction al_load_bitmap va chercher la fonction capable de charger l'image en fonction de son extension (.jpg, .bmp …), et renvoit NULL si elle ne la trouve pas ou si la fonction a échouée à charger l'image.

Par défaut allegro ne gère aucun format d'image, il faut utiliser le greffon ImageIO afin de pouvoir charger quelques formats.

Nous en avons fini avec les bitmaps d'Allegro 5.

Précédent « Sommaire » Suivant

allegro/bitmaps.txt · Dernière modification: 2012/06/29 17:02 par mrhide