enchant.js - 6e partie

Rédigé par Fred - - Aucun commentaire

On va maintenant voir l’objet Map pour comprendre les deux exemples expert qui nous reste à voir : Action et RPG.

L’objet Group

Avant de commencer avec les Map, on va voir comment déplacer plusieurs choses en même temps. Dans le premier exemple, on regroupe deux sprites bear et bear2 dans un Group :

var stage = new Group();
stage.addChild(bear);
stage.addChild(bear2);

Le premier a pour coordonnées (0, 0), le second (50, 50). Mais comme on peut le voir, le second est au milieu de la rootScene, et pas à (50, 50). C’est parce que l’on a déplacé le groupe de 100 :

stage.x = 100;
stage.y = 100;

Ça permet par exemple de faire circuler le « fond » plutôt que de faire avancer le sprite : dans le deuxième exemple, on déplace le groupe à chaque frame :

stage.onenterframe = function() {
    this.x = (game.width - bear.width) / 2 - bear.x;
};

Au fur et à mesure que l’ours avance, bear.x grandit, et donc stage.x décroît, laissant l’ours au milieu de l’écran. Au passage :

stage.onenterframe = function() {

est simplement un raccourci pour

stage.addEventListener('enterframe', function() {

ou pour

stage.on('enterframe', function() {

Dans l’exemple suivant, on laisse à nouveau le sprite au milieu de l’écran, mais stage.x est au maximum à 0, et au minimum à -sa largeur+un écran de jeu :

stage.onenterframe = function() {
    this.x =(game.width - bear.width) / 2 - bear.x;
    if (this.x > 0)
        this.x = 0;
    if (this.x<game.width - background.width)
        this.x=game.width - background.width;
};

Ainsi, le sprite background est toujours affiché, et ne défile qu’à partir du moment où l’ours est au milieu de l’écran. On peut diminuer les lignes de codes en utilisant les fonctions min et max :

stage.onenterframe = function() {
    var x = Math.min((game.width  - bear.width) / 2 - bear.x, 0);
    this.x = Math.max(game.width,  x + background.width)  - background.width;
};

Si on ajoute en plus des contraintes sur les coordonnées de l’ours:

if (game.input.left)  
    this.x -= 4;
if (this.x<0) this.x = 0;
if (game.input.right) this.x += 4;
if (this.x>background.width - 32)
    this.x = background.width - 32;

tout reste toujours affiché, et on a un scrolling horizontal qui commence à ressembler à quelque chose !

L’objet Map

Après ce petit préambule, abordons les Map. Un peu à la manière des sprites avec les frames, on associe une grande image à une Map, découpée en plusieurs carreaux (tiles), et on dit quels carreaux afficher :

var map = new Map(16, 16);
map.image = game.assets['../images/map2.png'];
map.loadData(tab_carte);

Dans l’exemple 4, on découpe l’image map2.png en carreaux de 16×16. Et on charge les carreaux indiqués par le tableau tab_carte. Un tableau de 12×10 affichera une carte de 12×10 carreaux de 16×16. Comme pour les frame avec les sprites, une valeur de 0 dans le tableau affichera le 1er carreau de l’image map2.png. À la différence des sprites, une valeur trop grande n’affichera rien. Tout comme une valeur négative. Enfin, une ligne du tableau peut ne pas être complète ; l’affichage sera vide également.

Et si on veut superposer plusieurs tiles ? On crée plusieurs cartes que l’on charge dans l’ordre inverse d’affichage : map_both.loadData(tab_carte_bkg, tab_carte_ftg); le « fond » en premier, le plus proche en dernier. Dans l’exemple 5, on a une carte pour le fond, une pour les objets, et la troisième montre la combinaison des deux.

Lorsqu’on va déplacer un joueur sur une carte, il va falloir détecter les objets. Pour cela, on ne va pas passer par la méthode intersect des sprites mais par les méthodes hitTest et checkTile des maps.

Pour une map, map.checkTile(x, y) retourne le carreau du tableau chargé en premier avec loadData aux coordonnées (x, y) de la map et non du tableau (de (0, 0) à (16, 16) on a donc la même valeur). De manière similaire, map.hitTest(x, y) retourne vrai s’il y a un carreau (dans le premier tableau) aux coordonnées (x, y) de la map. Dans l’exemple suivant, on affiche le retour de checkTile et hitTest pour la 7e colonne, ainsi que pour le pixel (0, 0). On constate alors que : la valeur retournée par les fonctions est la même que le pixel correspondant au carreau soit transparent ou non ; si on a mis un « fond » hitTest retournera toujours vrai.

Pour pouvoir contourner ce problème, il existe l’attribut collisionData : un tableau de même dimension que les autres, avec des 0 pour dire que l’on ne doit rien détecter, et des 1 sinon. L’exemple 7 montre la différence entre une carte avec et sans collisionData.

Le dernier exemple reprend tout ce qu'on a vu en simplifiant le code du rpg au niveau du déplacement du joueur (dans leur exemple, le joueur s’arrête forcément sur une case). Pour que ce soit encore plus lisible, les tableaux pour les cartes sont dans un fichier séparé. Et on peut ouvrir le coffre en ramassant la clé (pour revoir un peu la gestion des collisions).

Et c’est tout pour la base d’enchantjs. On terminera quand même avec un dernier tutoriel pour dire un mot sur les plugins disponibles.


Écrire un commentaire

Quelle est la première lettre du mot srknu ?