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.