2018-12-05
On a vu dans les articles précédents comment encoder des images pour la GameBoy et qu'il y avait plusieurs couches permettant d'afficher ces images. Dans cet article il sera question de la couche Background. Si vous avez lu les deux précédents articles, vous avez déjà vu quelques exemples utilisant cette couche pour afficher des images, mais on va aller un peu plus dans les détails cette fois-ci.
La couche Background est probablement l'une des plus importantes : c'est elle que l'on utilise pour afficher le niveau (pensez à la carte sur laquelle on se déplace dans Pokemon, ou les plateformes dans Super Mario). Certains jeux n'utilisent même que cette couche-là.
--------------------------------------------------------------------------------
📝️ Note:
--------------------------------------------------------------------------------
Cet article fait partie d'une série sur le développement GameBoy en C avec le compilateur SDCC et la bibliothèque gbdk-n. Cette série est toujours en cours et de nouveaux articles paraissent de temps à autre.
Articles de la série :
--------------------------------------------------------------------------------
Pour rappel, cette couche est l'une des « trois » disponibles, et comme son nom l'indique, il s'agit de celle qui se trouve en dessous :
Position de la couche Background
La couche Background a pour dimensions 32×32 tuiles, ce qui est plus grand que ce que peut afficher l'écran de la GameBoy (qui a pour dimensions 20×18 tuiles). Seule une partie de la couche est donc visible à l'écran à un instant donné :
Comparaison de la taille de la couche Background avec celle de l'écran de la GameBoy
L'intérêt que la couche soit plus grande que l'écran, est qu'il est possible de la faire défiler (on parle de scrolling). Lorsque l'on arrive au bord de la couche et que l'on continue de la faire défiler, elle reboucle par le côté opposé :
Animation du défilement de la couche Background
C'est à peu près tout ce qu'il faut savoir sur la couche Background, on va maintenant voir comment on s'en sert.
GBDK nous fournit tout un ensemble de fonctions et de macros pour manipuler la couche Background, on va toutes les voir en détail dans cette section.
Pour commencer, on va parler des deux macros permettant d'afficher et de masquer la couche Background.
Par défaut, la couche est masquée, il faudra donc la rendre visible si on veut être en mesure de tester les exemples suivants :
SHOW_BKG;
Et on peut la masquer à nouveau via la macro suivante :
HIDE_BKG;
Pour afficher des tuiles, il faut commencer par les copier dans la mémoire vidéo, cela se fait à l'aide de la fonction suivante :
void set_bkg_data(UINT8 first_tile, UINT8 nb_tiles, unsigned char *data);
Je ne remets pas d'exemple pour cette fonction, on en a déjà un de bien détaillé dans l'article « Développement GameBoy #4 : Afficher des images »
Développement GameBoy #4 : Afficher des images
Une fois les tuiles dans la mémoire vidéo de la GameBoy, il faut lui indiquer où les afficher. Pour ce faire, il faut lui fournir une tilemap.
Pour envoyer une tilemap dans la mémoire vidéo, il faut utiliser la fonction suivante :
void set_bkg_tiles(UINT8 x, UINT8 y, UINT8 w, UINT8 h, unsigned char *tiles);
Illustration de la copie d'une tilemap dans la couche Background
Cette fois encore, un exemple est disponible dans l'article « Développement GameBoy #4 : Afficher des images ».
Développement GameBoy #4 : Afficher des images
En plus de nous permettre de coller des tilesmaps sur la couche Background, GBDK nous fournit une seconde fonction permettant de récupérer ces données (pour savoir à quoi ressemble la couche à un instant donné) :
void get_bkg_tiles(UINT8 x, UINT8 y, UINT8 w, UINT8 h, unsigned char *tiles);
Par exemple, si on veut dupliquer une partie de la couche Background, on peut écrire le code suivant :
void main(void) { // Tableau suffisamment grand pour stocker le contenu que l'on va copier UINT8 house[8 * 7]; // [...] Mettre des trucs dans la couche Background // On duplique une partie de la couche Background get_bkg_tiles(5, 4, 8, 7, house); set_bkg_tiles(5, 12, 8, 7, house); }
Duplication d'une partie de la couche Background
GBDK nous fournit deux fonctions différentes pour déplacer le Background :
void scroll_bkg(INT8 x, INT8 y);
void move_bkg(UINT8 x, UINT8 y);
Maintenant qu'on connait toutes les fonctions et macros permettant de manipuler la couche Background, voici un petit exemple histoire de voir tout ça en action :
#include <gb/gb.h> // Je vous laisse regarder dans l'article précédent pour avoir une // idée du contenu des fichiers tileset.h et tilemap.h :) #include "tileset.h" #include "tilemap.h" void main(void) { UINT8 keys; // On copie les tuiles dans la mémoire vidéo set_bkg_data(0, TILESET_TILE_COUNT, TILESET); // On copie la tilemap dans la mémoire vidéo (dans notre cas, // la tilemap contient tout le contenu de la couche background) set_bkg_tiles(0, 0, TILEMAP_WIDTH, TILEMAP_HEIGHT, TILEMAP); // On affiche la couche Background, sinon on ne verra rien du tout SHOW_BKG; while (1) { keys = joypad(); // On fait défiler la couche Background lors de l'appui sur l'un // des boutons du D-PAD if (keys & J_UP) scroll_bkg(0, -1); if (keys & J_DOWN) scroll_bkg(0, 1); if (keys & J_LEFT) scroll_bkg(-1, 0); if (keys & J_RIGHT) scroll_bkg(1, 0); // On retourne à la vue d'origine (0, 0) lorsque l'on appuie sur START if (keys & J_START) move_bkg(0, 0); // On attend que l'écran ait été rafraichi. Si on ne fait pas ça, // le déplacement sera beaucoup trop rapide et la vue sera déformée // durant le déplacement... Vous pouvez supprimer cette ligne // si vous voulez tester ;) wait_vbl_done(); } }
Cet exemple affiche une carte de 32×32 tuiles dans laquelle il est possible de se déplacer à l'aide de la croix directionnelle. Un appui sur START réinitialise la vue à sa position initiale.
Capture d'écran de l'exemple une fois lancé dans un émilateur
Comme d'habitude, vous retrouverez les sources complètes de l'exemple sur Github :
https://github.com/flozz/gameboy-examples/tree/master/06-graphics3-background
C'est ici que s'achève cet article, et moi je vais m'efforcer d'écrire le suivant rapidement pour qu'il sorte d'ici 15 jours environ... 🙂️
--------------------------------------------------------------------------------