JEU DE PACMAN
Partie 2 : Graphismes
------------------------------------------------------------------
Une fenêtre noire c'est tristounet, affichons des ellipse pleines pour montrer que ça marche effectivement, le tracé d'ellipse est déjà implémenté par Allegro (heureusement car c'est pas donné) et est défini comme cela :
- Code: Tout sélectionner
void ellipsefill(BITMAP *bmp, int x, int y, int rx, int ry, int color);
Mais avant tout quelques notions méritent d'être mises (si possible) au clair.
:arrow: Type BITMAP et clipping :
Le type BITMAP est une zone mémoire où l'on stocke une image, en particulier ça peut être un buffer ou un sprite. Il est défini comme celà :
- Code: Tout sélectionner
typedef struct BITMAP
{
int w, h; // taille de l'image
int clip; // différent de zéro si on active le "clipping"
int cl, cr, ct, cb; // zone du "clipping"
unsigned char *line[]; // pointeurs au début de chaque ligne, pas important pour nous mais c'est là qu'est l'image
};
Le clipping permet d'afficher seulement une partie d'une image. Ce procédé est très souvent utilisé pour des petits sprites et des animations 2D, par exmple pour le jeu zelda on peut utiliser tout les sprites (décor, menu, personages, objets, effêts, police...) à partir d'une image (ou presque) :
Rien de mieux qu'une image pour montrer l'utilisation des variables cl, cr, ct et cb respectivement de clipping left, right, top et bottom (gauche, droite, haut, et bas) :

NB : le clipping signifie aussi le fait d'afficher une partie d'un sprite qui est a moitié en dehors de l'écran en évitant de dessiner les pixels qui dépassent de l'écran. (mais ça ne se présentera pas dans notre jeu)
Creation d'un objet bitmap :
Dans le jeu on utilisera un intermédiaire de dessin nommé "buffer" que l'on affichera à l'écran par la suite une fois l'image prête. (c'est un peu ça le double buffering ou le triple buffering de vos cartes graphiques)
- Code: Tout sélectionner
BITMAP *buffer;
// Allocation du pointeur :
buffer = create_bitmap(640, 480); // simple, merci allegro !
if (!buffer) exit(-1); // si il y a un probleme de création on quitte
(...) // notre "objet" bitmap est crée, on peut s'en servir
// ne faut pas oublier de le détruire à la fin
destroy_bitmap(buffer);
:arrow: Les couleurs :
Comme on l'a vu dans la partie précédente les couleurs seront en 32bits, codées comme des entiers. Comment trouver l'entier qui correspond a une couleur donnée allez vous me dire.
Il faut tout d'abord savoir qu'une couleur est crée par trois "pigments" rouge, vert et bleu (RGB : red green blue). Chaque couleur est définie de manière unique par son "coefficient" de rouge, de vert et de bleu. En 32bits, chaque coefficient est codé sur un octet ils vont de 0 à 255 (8 bits!).
Ainsi on a les couleurs RGB suivantes :
0,0,0 : noir
255,0,0 : rouge
128,128,128 : gris
255,0,255 : violet
Pour visualiser allez dans Microsoft Paint puis dans Couleurs->Modifier les couleurs...
Ensuite on recrée l'entier couleur 32bits (mais on utilise que 24bits en réalité car on a 3 octets) grace a la fonction Allegro suivante :
- Code: Tout sélectionner
int makecol32(int r, int g, int b);
Ainsi on peut créer la couleur jaune :
- Code: Tout sélectionner
int jaune;
jaune = makecol32(255,255,0);
Il existe aussi le mode RGBA pour faire des effets de transparence où A signifie "alpha" c'est le coefficient de transparence du pixel (toujours codé sur un octet, et là au total on utilise les 32bits via les 4 octets).
On va enfin pouvoir tracer nos superbes ellipses de couleurs 32bits!
Voici le code source non commenté:
- Code: Tout sélectionner
#include <allegro.h>
void init()
{
(voir contenu en fin de partie 1)
}
void deinit()
{
(idem)
}
int main()
{
int jaune, blanc;
char quit = false; // Rôle booléen
init();
jaune = makecol32(255,255,0);
blanc = makecol32(255,255,255);
ellipsefill(screen, 300, 150, 200, 100, jaune);
ellipsefill(screen, 400, 200, 50, 200, blanc);
while (!quit)
{
if (key[KEY_ESC]) quit=true;
}
deinit();
return 0;
}
END_OF_MAIN()
Le résultat après compilation et exécution est le suivant :
Voyons cela de plus près :
- Code: Tout sélectionner
ellipsefill(screen, 300, 150, 200, 100, jaune);
ellipsefill(screen, 400, 200, 50, 200, blanc);
Notons déjà l'apparition de screen qui est automatiquement crée par Allegro, c'est la zone mémoire de votre carte graphique (dumoin ça s'y apparente), elle est constamment rafraichie sur votre écran.
Ce n'est pas propre comme méthode de travail mais c'est juste pour montrer qu'il fonctionne comme le buffer et les sprites BITMAP que l'on utilisera par la suite.
On remarque aussi que les ellipses se superposent dans l'ordre dans lequel elles sont dessinées (normal a priori!) donc le principe de base dans un jeu est de dessiner le fond, les personnages, les objets, puis les effets et enfin le texte et/ou l'interface.
Ici on va utiliser une fonction Allegro qui crée notre BITMAP et qui récupère une image à partir d'un fichier en même temps. Puis on va utiliser une fonction qui l'affiche à l'écran aux coordonnées choisies. Simple non?
- Code: Tout sélectionner
BITMAP *image;
image = load_bitmap("image.bmp", NULL); // Allegro est aussi compatible LBM, PCX et TGA. ne vous préoccupez pas du NULL
if (!image) exit(-1); // si erreur de création (notamment fichier introuvable) on quitte!
// il reste plus qu'a l'afficher!
draw_sprite(screen, image, 100, 200);
// puis le détruire à la fin du programme
destroy_bitmap(image);
Pensez bien sur a mettre votre image dans le dossier de votre projet (probablement C:\Dev-Cpp\Pacman\) !
Voici le résultat :
Je vous épargne le code source entier, vous êtes assez grands!
Ici on va juste utiliser une nouvelle fonction : blit qui copie un BITMAP sur un autre. On ca s'en servir pour transmettre le buffer à l'écran après avoir dessiné.
- Code: Tout sélectionner
void blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);
- Code: Tout sélectionner
BITMAP *buffer;
BITMAP *image;
buffer = create_bitmap(640, 480);
if (!buffer) exit(-1);
image = load_bitmap("image.bmp", NULL);
if (!image) exit(-1);
draw_sprite(buffer, image, 100, 200);
blit(screen, buffer, 0, 0, 0, 0, 640, 480);
destroy_bitmap(buffer);
destroy_bitmap(image);
NB : Et là vous allez me dire "Quelle est la différence entre draw_sprite et blit?". Je répondrais simplement que c'est la même chose! (avec moins de parametres pour draw_sprite qui en plus est un nom inadapté pour la copie d'un buffer)
Nous voilà sufisamment armés pour vraiment aborder le jeu en lui même!
Rendez-vous dans la partie 3!






