La technique du "Tile mapping"

Bonjour à tous,

Dans l’optique de faire un tuto pour programmer un jeu de plateformes, nous allons voir ici une technique qui est utilisé pour ce type de jeux, mais aussi dans des shoot them up ou autre jeu avec une vue de dessus: jeu de labyrinthes, jeu d’exploration etc…

Vous avez certainement joué à des jeux utilisant de très grands décors: cartes, jeu de plateformes type Mario. Notre but va être de faire la même chose: afficher un écran qui se déplacera en fonction de certaines conditions dépendant du jeu.

Par exemple sur une carte, quand le joueur est proche d’un bord de la carte, celle-ci se recentre sur lui en affichant une nouvelle partie dans la direction vers laquelle le joueur se déplace
https://pub.phyks.me/sdz/sdz/medias/uploads.siteduzero.com_files_211001_212000_211822.png mais nous verrons cette technique plus tard et nous verrons qu’il y a plusieurs façons de le faire en fonction du jeu et du résultat souhaité.

Une image prend une place importante en mémoire, notre ESPboy a de la mémoire mais si nous voulions stocker une image qui contienne toute une carte, cela la consommerait en totalité ou quasiment en fonction de la taille désirée de la carte, c’est pourquoi les jeux ont rapidement utilisés la technique du Tile Mapping en partant d’un concept simple: dans les jeux ont utilise souvent des objets ayant des propriétés et une apparence identique. L’idée est de décomposer notre carte ou notre niveau en un ensemble de motifs que l’on utilisera de nombreuses fois. Ces motifs sont appelé des ‘tiles’ (ou tuiles en français). La carte (Map) sera donc l’enregistrement de la combinaison de ces tuiles.

On peut donc imaginer une carte composée d’un tableau indiquant cette séquence de tuiles et d’une image qui regroupe toutes ces tuiles les unes à côté des autres: le tileset

Et bien commençons:

A l’aide d’un outils adapté (dans nos tutoriel nous utiliserons Aesprite) dessinez tous vos tiles en utilisant la même palette.

Note: Si cela est possible, utilisez la palette standard de l’ESPboy:

(Vous pouvez récupérer le fichier palette ESPboy pour Aesprite ici: https://github.com/Jicehel/ESPBoy/blob/main/ESP_palette.aseprite)

Voici par exemple le tileset que nous utiliserons pour cette première étape:
Tileset

Une fois cette image créée, nous allons la convertir en données intégrables dans un fichier de notre code. Pour cela nous allons utiliser un convertisseur hexadécimal dédié.
Dans notre exemple nous utiliserons LVGL (https://lvgl.io/tools/imageconverter)
Votre image doit avoir une palette de 16 couleurs indexées (Si vous ne savez pas de quoi il en retourne, cela sera vu plus tard dans un tuto dédié aux opérations de base dans Aesprite)

Dans LVGL, commencez par cliquer sur “Choisir un fichier” en face de “Image file”.
Allez chercher votre image.
Indiquez le nom que vous désirez en sortie (par exemple Tileset dans notre cas)
Dans “Color format” choisissez le format désiré: 16 colors indexed
Dans “Output format” vous devez déjà avoir “c array”

Si oui, cliquez sur “Convert” et le programme va vous générer un fichier texte (Tileset.c dans notre exemple) contenant l’encodage de votre Tileset dans un tableau c

Ouvrez le fichier, nous aurons besoin de recopier les valeurs situées après /Color of index 15/ jusqu’à l’accolade fermante suivante.

Nous coderons les tiles dans l’ordre, c’est à dire que le premier bloc de 16 x 16 pixels à gauche de cette image (tout vert) sera la tuile 1, celui à sa droite, le 2 est presque le même mais avec 2 petites fleurs, le 3ème représente un chemin vertical, le 4ème, un chemin horizontal, le 5ème, une intersection entre le chemin horizontal et le vertical, le 6ème représente le haut d’une étendue d’eau, le 7, le ford situé à droite d’une étendu d’eau, le 8 représente en bloc d’eau, le 9 le bord gauche et le 10 le bord bas. Il n’y a que 10 tiles dans cet exemple, nous verrons plus tard que nous pouvons en ajouter.

J’ai pris 10 tiles, en commençant à 1, j’aurais pu commencer à 0 et coder ces 10 tiles de 0 à 9 mais voilà, dans un niveau, il est certain que 10 tiles risquent de ne pas suffire à construire un niveau. Je vous donne une méthode juste après pour pouvoir en coder plus, mais il y a beaucoup de possibilités et vous pourrez adapter sans problème mon exemple en fonction de vos besoins.

Nous, après 9, nous passerons à A. Puisque l’on utilise les codes de l’ESPboy, le caractère de A est le 17ème caractère après celui du 0. Si le code de la table est plus grand que 9, nous retirerons donc 7 au code renseigné dans la table afin que A vale 10. Ainsi, nous obtenons la possibilité d’utiliser 35 sur notre carte et cela sera largement suffisant pour nos exemples.

Code de cette première partie

Notre objectif va donc être de remplir l’écran ave les tuiles que nous voulons pour dessiner une petites carte (carte fixe)

Vous pouvez retrouver ce code complet ici: https://github.com/Jicehel/ESPBoy/tree/main/Tileset-16px-map

/*
     Tile mapping demo for
           ESPBoy
         by Jicehel
         and Roman
 --------------------------------
  This prog will display a map
  on the screen (128 x 128 pixels)
  composed of a combination
  of 8 tiles of 16 x 16 pixels
  
*/


// Set delay after plotting the sprite
#define DELAY 20

// Width and height of tile (an element of the map)
#define WIDTH_TILE  16
#define HEIGHT_TILE 16

// Define the number of blocs used
#define X_TILES 8
#define Y_TILES 8

#include "image.h"
#include "ESPboyInit.h"

#define Tileset_size 160

ESPboyInit myESPboy;       // Invoke custom library
TFT_eSprite spr = TFT_eSprite(&myESPboy.tft);     // Declare Sprite object "spr" with pointer to "tft" object

uint16_t bit4palette[] = {TFT_BLACK, TFT_GREEN, TFT_RED, TFT_ORANGE, TFT_YELLOW, TFT_BROWN, TFT_BLUE, TFT_PURPLE, TFT_DARKGREY, TFT_WHITE, TFT_CYAN, TFT_MAGENTA, TFT_MAROON, TFT_DARKGREEN, TFT_NAVY, TFT_PINK};

char* table[] = {
  "12132111",
  "11231121",
  "44452662",
  "11239887",
  "21132AA1",
  "62131121",
  "87232112",
  "A1231111",
};


void drawmap() {
  uint8_t nb;
  for(uint8_t i=0; i<Y_TILES; i++) {
    for(uint8_t j=0; j<X_TILES; j++) { 
      nb = table[i][j] - '0';
      if (nb > 10) nb = nb - 7;
      spr.pushSprite(j * WIDTH_TILE, i * HEIGHT_TILE, (nb - 1) * WIDTH_TILE, 0, WIDTH_TILE, HEIGHT_TILE);
    } 
  } 
}


void setup(){
  myESPboy.begin("Tile mapping");   //Set up the display
  spr.setColorDepth(4);
  spr.createPalette(bit4palette); 
  spr.createSprite(Tileset_size, HEIGHT_TILE); // Create a sprite of defined size
  spr.pushImage(0, 0, Tileset_size, HEIGHT_TILE, (uint16_t *)tileset, 16);
  // spr.pushSprite(0,0);
}


void loop(void){
  drawmap();
  delay(DELAY*100);
}   

Nous étudierons plus en détail ce code dans le post suivant

Analysons notre programme précédent.

Après un petit commentaire qui présente le programme, nous définissons quelques constantes:

  • une (DELAY) pour pouvoir choisir le temps entre 2 cycles de la boucle principale (elle permet de faire attendre le programme quand il a fini de traiter la procédure principale “loop” avant de la relancer)
  • les 2 suivantes (WIDTH_TILE et HEIGHT_TILE) définissent la taille d’un des éléments de la carte.
  • les 2 suivantes (X_TILES et Y_TILES) définissent le nombre de TILES que nous allons utiliser dans la largeur et dans la hauteur.

Nous incluons ensuite 2 fichiers:

  • image.h c’est dans ce fichier que nous mettons tous les codes correspondant aux images que nous allons utiliser (dans cet exemple, il n’y aura que la conversion de notre tileset)
//Our 4 bits Tileset (16 coulours indexed)
const uint8_t tileset[] PROGMEM = {
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd1, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x14, 0x1d, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x6d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd6, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6d, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd1, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0xdd, 0xdd, 0xd6, 0x66, 0x66, 0x66, 0x6d, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0xc5, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0xc5, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x6d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd6, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd6, 0xdd, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xcc, 0xcc, 0xcc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd6, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xcc, 0xcc, 0x55, 0x55, 0x55, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x6d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd6, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0x55, 0x55, 0x55, 0xcc, 0xcc, 0xcc, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x6d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd6, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x6d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd6, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd1, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x6d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd6, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x13, 0x1d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0xcc, 0xdd, 0xdd, 0xdd, 0xcc, 0xcc, 0xc5, 0x55, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x55, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x6d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd1, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x6d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd6, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0x6d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd6, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0x55, 0x5c, 0xdd, 0xdd, 0xdd, 0xd6, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 
};
  • Vous connaissez le second fichier que nous appelons: “ESPboyInit.h” qui permet d’initialiser l’ESPboy

Nous ajoutons ensuite la constante Tileset_size que nous initialisons avec la valeur de la largeur en pixels de notre Tileset (160 dans notre exemple)

Nous créons ensuite une instance de notre ESPboy en l’initialisant:

ESPboyInit myESPboy;       // Invoke custom library

Puis nous créons avec l’instruction ci-dessous le sprite spr qui s’affichera sur l’objet TFT de notre ESPBoy qui a été initialisé lors de la commande précédente.

TFT_eSprite spr = TFT_eSprite(&myESPboy.tft); 

Nous créons ensuite un tableau avec les valeurs standards pour les couleurs.

En dessous, nous avons créé une table (table) contenant 8 lignes correspondant à des chaines de caractères indiquant dans l’ordre des tiles.


Ensuite vient la procédure drawmap(). Cette procédure est chargée de parcourir la table à l’aide de 2 boucles: la première correspondant au parcours de la ligne en X et l’autre au Y.
Pour poser la bonne tuile de notre tileset, nous utilisons la commande:

spr.pushSprite(j * WIDTH_TILE, i * HEIGHT_TILE, (nb - 1) * WIDTH_TILE, 0, WIDTH_TILE, HEIGHT_TILE);

Décomposons cette commande. Elle est composée de:

  • spr (le nom de notre sprite contenant notre Tileset)
  • pushSprite (la commande elle même qui indique que l’on va afficher notre sprite spr à l’écran qui comprend elle même ces éléments:
    • j * WIDTH_TILE, i * HEIGHT_TILE: ce sont les coordonnées du coin supérieur gauche de où nous voulons que le sprite soit affiché à l’écran
    • (nb - 1) * WIDTH_TILE, 0 : coordonnées du coin supérieur gauche de la section que nous voulons copier depuis le Tileset
    • WIDTH_TILE, HEIGHT_TILE largeur et hauteur du bloc à copier depuis la position précédente dans le sprite

La procédure setup()

On initialise l’ESPBoy : myESPboy.begin(“Tile mapping”); Le logo de l’ESPBoy s’affichera avec le titre Tile mapping en dessous mais surtout cet appel s’occupe de remettre l’ESPBoy dans son état initial.

On indique SetColorph(4) afin d’indiquer à l’ESPB que nous allons travailler avec des graphismes aux couleurs 4 bits copiées

spr.createSprite(Tileset_size, HEIGHT_TILE); Permet de créer l’objet sprite (spr) de longueur: Tileset_size et de hauteur: HEIGHT_TILE

on utilise ensuite pushImage pour pousser le contenu de l’image dans le sprite (spr)

Je n’explique pas loop() car cette procédure qui se lance à chaque cycle est très simple: à chaque exécution. Elle lance la procédure drawmap() puis attends en fonction de la valeur indiquée dans DELAY

Voilà, nous avons atteint notre objectif, remplir l’écran avec 8 tuiles de 16 pixels de large par 16 pixels de haut. 16 pixels est une taille qui n’est pas choisie aux hasard: c’est un multiple de 8, c’est plus simple pour le “lire” en hexadécimal et ça facilite le traitement.

Tout le paramétrage de notre carte est dans le tableau table et nous le parcourons en dessinant la table en utilisant 2 boucles for (i représentant les lignes et j représentant les colonnes). La dimension des tuiles étant fixe, nous pouvons remplir notre quadrillage en allant chercher les informations à mettre dans la case en prenant la portion du tileset (ou ensemble de tuiles mais la traduction française est trop longue…) correspondant à la valeur indiquée dans le tableau. Comme nous avons mis toutes les tuiles en ligne, c’est très simple. Nous pourrions également avoir plusieurs lignes et dans ce cas, il faudrait gérer avec une petite équation la position dans le tileset de la tuile à afficher.

Bien maintenant que nous savons remplir l’écran avec de petites portions d’une image, réfléchissons un peu à la suite.
Tout d’abord une remarque: S’il y a plusieurs tableau ou si la carte est très grande, je vous conseille de la déplacer dans un fichier .h : ça n’encombrera pas votre programme principal, ça facilitera la lecture de votre carte et sa maintenance, l’ajout de niveaux supplémentaires, etc (d’ailleurs si vous avez de nombreux niveaux, n’hésitez pas à couper le fichier .h en plusieurs fichiers de tailles raisonnables qui vous éviterons d’avoir à parcourir trop de lignes lorsque vous voudrez modifier une valeur)
Enfin noté que nous utilisons dans notre programme les chiffres et les lettres (on a donc 35 tuiles utilisables) ce qui correspond à certains types de jeux mais nous pouvons aussi utiliser directement des valeurs pour utiliser par exemple 255 tuiles différentes. Si vous avez besoin de plus, vous pouvez bien sur utiliser des entiers plus grands mais pensez toutefois à la taille que prendra votre carte en mémoire. si vous dépassez 255, vous devrez utiliser 2 octets et la taille en mémoire de votre carte doublera. Normalement avec 255 tuiles, vous devriez déjà avoir de quoi faire pas mal de chose (il est rare, très rare même que des jeux en utilise plus)
Dans la prochaine étape, nous allons définir les propriétés des tuiles. Pour le moment, faisant une carte, nous allons faire simple: une tuile sera franchissable ou non franchissable… simple, je vous dit… On y va tranquille et surtout pour le moment, vous n’avez rien qui bouge donc pour ce prochain exemple, vous devrez me faire confiance aveuglément… J’aime ce pouvoir… (rire diabolique)

Bravo Jicehel, tu as l’art et la manière d’expliquer pas à pas et simplement.
Et puis quel courage de te lancer dans ces tutos qui sont les bases de la programmation 8 bits.

Une des techniques que j’ai bien aimé à l’époque c’est l’arrivé dans les jeux vidéo du " Défilement parallaxe" qui a donner de la profondeur et de la dynamique.

Tu m’as donné le gout de renouer avec toutes ces techniques de base qui sont les piliers des jeux vidéo.

Merci Wil, j’en suis vraiment très content et ça fait plaisir d’avoir du retour. Ca permet de se rendre compte que ça peut être utile. Ca motive. J’espère profiter aussi de ton expérience si tu te remets sur les techniques de bases. A plusieurs, on avancera plus vite et mieux :slight_smile: