Créons un jeu de plateformes de A à Z !



Tutoriel présenté par : Jérémie F. Bellanger
Dernière mise à jour : 08 novembre 2010
Difficulté :  



6. Gérer le scrolling de la map


    Vous avez toujours rêvé de scroller sans jamais savoir comment faire  ? Eh bien, c'est votre jour de chance !

    On va en effet rajouter un scrolling à notre map, que nous dirigerons au clavier (pour l'instant), et ça va être rapide et super facile ! Si, si, faites-moi confiance !



Résultat à la fin de ce chapitre : on scrolle la map au clavier  !



    Alors tout d'abord, vous allez télécharger une nouvelle map, à enregistrer dans le dossier du projet (Aron) dans le sous-dossier map à la place de l'ancienne. Celle-ci est déjà préconçue pour vous permettre de scroller (un peu) (N.B. : La map se trouve dans le projet correspondant au chapitre dans l'archive téléchargeable) :

map1.txt

    Voilà une bonne chose de faite, nous pouvons donc maintenant modifier notre code !
    Première chose à faire, nous allons rajouter la fonction update() dans la boucle de notre main pour traiter les inputs du clavier et permettre à la map de scroller.

Nom du fichier : main.c


    #include "main.h"

    int main( int argc, char *argv[ ] )
   {
    unsigned int frameLimit = SDL_GetTicks() + 16;
    int go;

    /* Initialisation de la SDL dans une fonction séparée (voir après) */
        init("Aron");

   /* Appelle la fonction cleanup à la fin du programme */
         atexit(cleanup);

    go = 1;


    /* Boucle infinie, principale, du jeu */

    while (go == 1)
    {

        /* On vérifie l'état des entrées (clavier puis plus tard joystick) */
        getInput();

        /* On met à jour le jeu */
        update();

        /* On affiche tout */
        draw();

        /* Gestion des 60 fps ( 60 images pas seconde : soit 1s ->1000ms/60 = 16.6 -> 16
        On doit donc attendre 16 ms entre chaque image (frame) */

        delay(frameLimit);
        frameLimit = SDL_GetTicks() + 16;

    }

    /* Exit */
    exit(0);

    }

      


    Et nous rajouterons donc le prototype de cette fonction dans main.h (vous devriez commencer à avoir l'habitude maintenant ) :

Nom du fichier : main.h


  extern void update(void);



    On va maintenant implémenter cette fonction dans le fichier input.c en-dessous de getInput() :

Nom du fichier : input.c


 void update(void)
{

     if (input.left == 1)
    {
        map.startX -= TILE_SIZE;

        if (map.startX < 0)
        {
            map.startX = 0;
        }
    }

    else if (input.right == 1)
    {
        map.startX += TILE_SIZE;

        if (map.startX + SCREEN_WIDTH >= map.maxX)
        {
            map.startX = map.maxX - SCREEN_WIDTH;
        }
    }

    if (input.up == 1)
    {
        map.startY -= TILE_SIZE;

        if (map.startY < 0)
        {
            map.startY = 0;
        }
    }

    else if (input.down == 1)
    {
        map.startY += TILE_SIZE;

        if (map.startY + SCREEN_HEIGHT >= map.maxY)
        {
            map.startY = map.maxY - SCREEN_HEIGHT;
        }
    }

}


 

 

    Comme vous pouvez le voir, cette fonction est on ne peut plus simple.
    On teste s'il y a un appui sur les touches fléchées haut, bas, gauche, droite du clavier (à l'aide des variables input mises à jour par la fonction getInput() ) et en fonction de ça on scrolle de la valeur de TILE_SIZE, c'est-à-dire de 32 pixels. Vous pouvez faire varier cette valeur pour un scrolling plus ou moins rapide .
    Par sécurité, on vérifie aussi, si on ne sort pas de la map, en calant le scrolling à sa valeur max si les coordonnées de la carte (map.startX et map.startY) les atteignent ou les dépassent.

    Et n'oublions pas d'ajouter dans input.h :


  extern Map map;
 

    Il ne reste maintenant plus qu'à mettre à jour notre fonction drawMap() :

Nom du fichier : map.c


  void drawMap(void)
 {
    int x, y, mapX, x1, x2, mapY, y1, y2, xsource, ysource, a;

   /* On initialise mapX à la 1ère colonne qu'on doit blitter.
    Celle-ci correspond au x de la map (en pixels) divisés par la taille d'une tile (32)
    pour obtenir la bonne colonne de notre map
    Exemple : si x du début de la map = 1026, on fait 1026 / 32
    et on sait qu'on doit commencer par afficher la 32eme colonne de tiles de notre map */
    mapX = map.startX / TILE_SIZE;

    /* Coordonnées de départ pour l'affichage de la map : permet
    de déterminer à quels coordonnées blitter la 1ère colonne de tiles au pixel près
    (par exemple, si la 1ère colonne n'est visible qu'en partie, on devra commencer à blitter
    hors écran, donc avoir des coordonnées négatives - d'où le -1). */
    x1 = (map.startX % TILE_SIZE) * -1;

    /* Calcul des coordonnées de la fin de la map : jusqu'où doit-on blitter ?
    Logiquement, on doit aller à x1 (départ) + SCREEN_WIDTH (la largeur de l'écran).
    Mais si on a commencé à blitter en dehors de l'écran la première colonne, il
    va falloir rajouter une autre colonne de tiles sinon on va avoir des pixels
    blancs. C'est ce que fait : x1 == 0 ? 0 : TILE_SIZE qu'on pourrait traduire par:
    if(x1 != 0)
        x2 = x1 + SCREEN_WIDTH + TILE_SIZE , mais forcément, c'est plus long ;)*/
    x2 = x1 + SCREEN_WIDTH + (x1 == 0 ? 0 : TILE_SIZE);

    /* On fait exactement pareil pour calculer y */
    mapY = map.startY / TILE_SIZE;
    y1 = (map.startY % TILE_SIZE) * -1;
    y2 = y1 + SCREEN_HEIGHT + (y1 == 0 ? 0 : TILE_SIZE);

   
    /* Dessine la carte en commençant par startX et startY */

    /* On dessine ligne par ligne en commençant par y1 (0) jusqu'à y2 (480)
    A chaque fois, on rajoute TILE_SIZE (donc 32), car on descend d'une ligne
    de tile (qui fait 32 pixels de hauteur) */

    for (y = y1; y < y2; y += TILE_SIZE)
    {
        /* A chaque début de ligne, on réinitialise mapX qui contient la colonne
        (0 au début puisqu'on ne scrolle pas) */

        mapX = map.startX / TILE_SIZE;

        /* A chaque colonne de tile, on dessine la bonne tile en allant
        de x = 0 à x = 640 */

        for (x = x1; x < x2; x += TILE_SIZE)
        {

            /* Suivant le numéro de notre tile, on découpe le tileset */

            a = map.tile[mapY][mapX];

            /* Calcul pour obtenir son y (pour un tileset de 10 tiles
            par ligne, d'où le 10 */

            ysource = a / 10 * TILE_SIZE;

            /* Et son x */

            xsource = a % 10 * TILE_SIZE;

            /* Fonction qui blitte la bonne tile au bon endroit */

            drawTile(map.tileSet, x, y, xsource, ysource);

            mapX++;
        }

        mapY++;
    }
  }
 


    Ici, on efface les calculs simplifiés de l'affichage de la map et on les remplace par les calculs en commentaires.

    Les explications sont fournies directement ligne par ligne ci-dessus.
    Pour faire court, on calcule par quelles colonne et ligne de tiles on doit commencer l'affichage, selon les valeurs de map.startX et map.startY (qui augmentent/diminuent selon les inputs) et ensuite on calcule où commencer à blitter la première colonne et la première ligne (parfois hors-écran selon le scrolling). Enfin, on calcule où arrêter l'affichage de la map : si la 1ère ligne/colonne a été blittée hors écran, il va en effet falloir blitter une ligne/colonne de plus.

    Vous pouvez vous amuser à changer ces calculs pour mieux comprendre comment cela fonctionne (ça peut paraître un peu difficile au début, c'est normal ). Supprimez, par exemple :
(x1 == 0 ? 0 : TILE_SIZE) pour voir son importance !

 
    Eh voilà notre scrolling est terminé (quoi ? déjà  !!!), on est maintenant prêt à compiler... BUILD... RUN et tadaaaaam !
Appuyez sur les touches fléchées du clavier, et ça scrolle  !!!



    Et maintenant, prochaine étape : un level editor  !!






     

 

 

Connexion

CoalaWeb Traffic

Today74
Yesterday274
This week1145
This month4819
Total1744026

27/04/24