Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Chapitre 5 : Génération de sprites

Par gnicos (Nicolas Gauville), le 13 juillet 2012
Navigation rapide :

<< Chapitre 4 - Sommaire - Chapitre 6 >>

Nous allons maintenant dessiner quelques tuiles, et utiliser notre début de moteur isométrique pour créer une petite carte !

I. Dessinons un peu !

Dans ce chapitre, nous allons donc dessiner des tuiles, et utiliser les classes précédemment créées pour les afficher. Le fichier gfx.js contiendra nos dessins.

Au niveau de l'organisation : nous allons simplement créer un objet “gfx” qui contiendra des fonctions, chacune retournant le dessin correspondant, sous forme d'instance de la classe shape.

var gfx = {};
 
/**
 * Exemple de tuile
 */
gfx.exemple = function ()
{
        //On crée une instance de la classe Shape.
        this.gfx = new Shape();
 
 
        //On dessine grâce à la propriété "graphics" de la classe shape.
 
 
        //On envoie le résultat.
        return this.gfx;
};

Pour réaliser nos dessins, dès que cela se complique, l'outil “Export for CreateJS” est probablement la meilleure solution. Vous verrez que le code généré est très clair et très similaire à ce que je vous présente ici.

Biensur, pour des dessins très simples (comme c'est le cas ici), on peu réfléchir un peu, et écrire soit même. Dans le cas d'un sol par exemple (en tenant compte du fait qu'on le centre par rapport à l'origine du dessin) :

Avec un dessin, on voit assez facilement comment on peut faire. Au niveau du code, nous allons donc utiliser les méthodes de la propriété “graphics” de la classe Shape, et appliquer ce que nous venons de voir.

/**
 * Function exemple
 * @purpose : Génère un sol.
 */
gfx.sol = function ()
{
        //On crée une nouvelle instance de la classe Shape
        this.gfx = new Shape();
 
        //On accéde a la propriété grapgics
        this.gfx.graphics
                //On initie un nouveau tracé (ici, gris)
                .beginFill("#CCCCCC")
                //On applique les actions vues dans le schémà
                .moveTo(64,0)
                .lineTo(0,-32)
                .lineTo(-64,0)
                .lineTo(0,32)
                .lineTo(64,0)
                //On termine le tracé.
                .closePath();
        return this.gfx;
};

Nous allons maintenant utiliser cette tuile.

II. Une petite carte

Pour la suite, nous allons cette fois modifier le fichier “core.js”, qui va utiliser nos classes et notre tuile pour créer une première carte.

Nous commençons, évidement, par définir l'objet “stage” :

var gameview = document.getElementById('gameview'), stage;
stage = new Stage(gameview);

Ensuite, il faut savoir que dans EaselJS, l'affichage ne se met pas à jour automatiquement par défaut, il faut utiliser la méthode “update” à chaque changement.

Pour éviter cela, nous allons utiliser la classe statique “Ticker” pour définir un framerate, et ainsi fixer un nombre d'images à afficher par secondes.

L'oeil humain étant capable de percevoir 24 images par secondes environ, c'est la valeur que l'on utilise le plus souvent. En définissant un framerate de 24, la méthode “update” sera donc utilisée 24 fois chaque seconde.

Ticker.setFPS(24);
Ticker.addListener(stage);

Nous allons ensuite définir un variable “map” qui correspondra à notre carte :

var myMap = new Map ();

Pour centrer notre carte, nous n'avons actuellement pas de système qui gère la position automatiquement, cela n'étant pas forcément utile tant que nous n'utilisons pas de scrolling (ce qui sera toutefois probablement abordé en annexe). Nous allons, pour l'instant, nous contenter d'utiliser l'offset de la carte pour la centrer manuellement :

myMap.offsetX = 400;
myMap.offsetY = 200;

Enfin, nous devons ajouter notre carte à la liste d'affichage :

stage.addChild ( myMap );

Pour ajouter les tuiles, nous verrons plus tard plusieurs méthodes pour gérer les cartes (ouvrir un fichier qui contient les positions de chaque tuiles au lancement du jeu, par exemple). Pour l'instant, nous n'en avons pas besoin, et, pour l'instant, nous allons nous contenter d'une double boucle for qui ajoutera des tuiles, dans cet exemple, j'ai choisi une carte de 5×5 tuiles :

for ( var i = 0; i < 5; i++ )
{
        for ( var j = 0; j < 5; j++ )
        {
                //On ajoute une tuile
        }
}

Pour ajouter une tuile, nous allons donc avoir plusieurs choses à faire.

  1. 1 : On commence par récupérer le graphique à utiliser dans la tuile :
    gfx.sol()
  2. 2 : On crée une tuile avec ce graphique. Pour les paramètres de notre tuile, nous utilisons donc le type “TileType.DRAW” (c'est un dessin), et true comme troisième paramètre (walkable, c'est un sol, donc on peu marcher dessus) :
    new Tile ( TileType.DRAW, gfx.sol(), true )
  3. 3 : Maintenant, on utilise notre tuile. On utilise donc la méthode “addTile” de la classe Map. Pour la position de la tuile, on choisi donc i et j (les variables données par la double boucle for), et 0 en Z :
    myMap.addTile ( new Tile ( TileType.DRAW, gfx.sol(), true ), i, j, 0 );

Notre fichier “core.js” contient donc le code suivant :

var gameview = document.getElementById('gameview'), stage;
stage = new Stage(gameview);
 
Ticker.setFPS(24);
Ticker.addListener(stage);
 
 
var myMap = new Map ();
myMap.offsetX = 400;
myMap.offsetY = 200;
stage.addChild ( myMap );
 
for ( var i = 0; i < 5; i++ )
{
        for ( var j = 0; j < 5; j++ )
        {
                myMap.addTile ( new Tile ( TileType.DRAW, gfx.sol(128,128,128), true ), i, j, 0 );
        }
}

Et, si tout se passe bien, nous avons le résultat suivant :

III. Aller un peu plus loin

Nous allons maintenant retourner dans le fichier “gfx.js” pour créer d'autres tuiles. Evidement, il faudra modifier un peu le fichier “core.js” pour utiliser ces tuiles, mais je ne détaillerai pas les changements dans le fichier “core.js”, les modifications à effectuer sont en effet minimes et très simples.

Changer les couleurs

Pour commencer, le gros avantage du dessin en code, c'est de pouvoir ensuite configurer très simplement notre dessin. La chose la plus simple à modifier ici est probablement la couleur. Ainsi, nous pourrions par exemple ajouter des paramètres $r, $g, $b à notre fonction “sol”.

Nous avons donc notre méthode “gfx.sol ( $r, $g, $b )”. Première étape : vérifier que les trois paramètres ont été donnés. Si ce n'est pas le cas (c'est à dire que la fonction à été utiliser sans paramètres, par exemple), nous pouvons définir une couleur par défaut.

Un léger problème se pose ici : nous devons vérifier l'existence des trois variables. La fonction “isset” que nous utilisons dans d'autres langages, comme le php, n'existe malheureusement pas en JavaScript.

Pour tester l'existence d'une variable $x, en JavaScript, on utilise généralement les conditions du type :

if ( !$x )
{
     // $x n'existe pas
}

Le problème ici, c'est que $r, $g et $b sont des nombres, et donc que si l'un d'eux vaut 0, cette condition ne fera pas la différence. Nous devrons donc tester également que notre variable ne vaut pas 0 de façon stricte (type et valeur correspondant).

Si vous préférez utiliser la fonction isset, un exemple de portage de cette fonction en JavaScript est donné ici : http://phpjs.org/functions/isset:454

Nous obtenons donc ceci :

if ( (!$r && $r !== 0) || (!$g && $g !== 0) || (!$b && $b !== 0) )
{
        //Tous les paramètres ne sont pas définis, on choisit donc une couleur "par défaut".
        $color = "#CCCCCC";
}

Si, à l'inverse, les paramètres sont tous définis, nous pouvoir utiliser la méthode “getRGB” de la classe graphics (d'EaselJS) pour définir la couleur :

if ( (!$r && $r !== 0) || (!$g && $g !== 0) || (!$b && $b !== 0) )
{
        $color = "#CCCCCC";
}
else
{
        $color = Graphics.getRGB ( $r, $g, $b );
}

Enfin, le reste de notre fonction ne change pas, mais avec notre petite modification, nous pouvons maintenant changer de couleur très simplement !

/**
 * Function sol
 * @purpose : Génère un sol.
 * $color : couleur du sol.
 */
gfx.sol = function ( $r, $g, $b )
{
        if ( (!$r && $r !== 0) || (!$g && $g !== 0) || (!$b && $b !== 0) )
        {
                $color = "#CCCCCC";
        }
        else
        {
                $color = Graphics.getRGB ( $r, $g, $b );
        }
 
        this.gfx = new Shape();
        this.gfx.name = $color;
        this.gfx.graphics.beginFill($color)
                         .moveTo(64,0)
                         .lineTo(0,-32)
                         .lineTo(-64,0)
                         .lineTo(0,32)
                         .lineTo(64,0)
                         .closePath();
        return this.gfx;
};

Sprite aléatoire

Une petite partie ajoutée grâce à Kosic (qui a abordé le sujet sur le forum) : les tuiles aléatoires. C'est assez simple à faire, généralement, la méthode la plus simple est d'utiliser des nombres aléatoires, grâce aux fonctions “Math.random” et “Math.round” pour arrondir le nombre généré. Par exemple, dans le cas de trois variantes, nous ferions comme ceci :

var n = Math.round(Math.random()*2);
 
switch ( n )
{
     case 0:
          //Cas 1
          break;
     case 1:
          //Cas 2
          break;
     case 2:
          //Cas 3
          break;
     default: break;
}

Ici, nous allons voir un autre exemple : une couleur aléatoire. Pour cela, nous allons donc générer trois variables ($r, $g, $b), comprises entre 0 et 255. Ensuite, on peu utiliser notre méthode sol pour avoir le résultat. On obtient alors ceci :

/**
 * Function solAlea
 * @purpose : Génère un sol de couleur aléatoire.
 */
gfx.solAlea = function ()
{
        var r = Math.round(Math.random()*255), g = Math.round(Math.random()*255), b = Math.round(Math.random()*255);
 
        return this.sol ( r, g, b );
};

On obtient alors un résultat comme celui-ci :

Evidement, sa peut sembler peu utile comme ça, mais sa peut permettre énormément d'effets, et c'est très simple à faire. Par exemple, nous pouvons faire une fonction qui, au lieu de choisir une couleur aléatoire, fait varier légèrement une couleur choisie de façon aléatoire, de façon à faire varier le décor.

/**
 * Function solTAlea
 * @purpose : Génère un sol avec une variation de teinte aléatoire.
 */
gfx.solTAlea = function ( $r, $g, $b )
{
        var r = $r - Math.round(Math.random()*40), g = $g - Math.round(Math.random()*40), b = $b - Math.round(Math.random()*40);
 
        return this.sol ( r, g, b );
};

Nous pouvons avoir un résultat comme celui-ci pour un sol d'herbe par exemple :

Enfin, traiter les couleurs peut également permettre d'obtenir, par exemple, des variations de luminosité, en multipliant les trois composantes par un coefficient. Par exemple, si nous souhaitons dessiner un mur, nous aurons besoin de couleurs pour les trois faces. Nous pouvons donc utiliser une couleur donnée, puis la même à 80% et 60% d'intensité, de façon à obtenir les trois faces.

Nous pouvons ainsi obtenir une fonction permettant de configurer simplement la couleur, comme pour le sol :

/**
 * Function mur
 * @purpose : Génère un mur.
 * $color : couleur du mur.
 */
gfx.mur = function ( $r, $g, $b )
{
	if ( (!$r && $r !== 0) || (!$g && $g !== 0) || (!$b && $b !== 0) ) { $r = $g = $b = 200; }
        this.gfx = new Shape();
 
        /**
         * On définit les couleurs des côtés (plus sombres).
         */
        $color = Graphics.getRGB ( $r, $g, $b );
 
        /**
         * Création des deux autr couleurs.
         */
        $color_g = Graphics.getRGB ( Math.round(0.8 * $r), Math.round(0.8 * $g), Math.round(0.8 * $b) );
        $color_d = Graphics.getRGB ( Math.round(0.6 * $r), Math.round(0.6 * $g), Math.round(0.6 * $b) );
 
        /**
         * Face droite.
         */
	this.gfx.graphics.beginFill($color_d);
        this.gfx.graphics.moveTo(0,-18).lineTo(0,32).lineTo(64,0).lineTo(64,-50).lineTo(0,-18);
 
        /**
         * Face supérieure.
         */
        this.gfx.graphics.beginFill($color);
        this.gfx.graphics.moveTo(64,-50).lineTo(0,-82).lineTo(-64,-50).lineTo(0,-18).lineTo(64,-50);
 
        /**
         * Face gauche.
         */
        this.gfx.graphics.beginFill($color_g);
        this.gfx.graphics.moveTo(-64,-50).lineTo(-64,0).lineTo(0,32).lineTo(0,-18).lineTo(-64,-50).beginFill();
        this.gfx.graphics.closePath();
 
	return this.gfx;
};

Conclusion

Nous avons ainsi vu comment utiliser les classes créées précédemment avec des tuiles dessinées, et comment créer des graphismes configurables et éventuellement aléatoires.

Dans le prochain chapitre, nous nous attaquerons à la classe “Player”, et nous permettrons à notre joueur de parcourir une petite carte !

Navigation rapide :

<< Chapitre 4 - Sommaire - Chapitre 6 >>