enchant.js - 7e partie

Rédigé par Fred - - Aucun commentaire

Il existe plusieurs plugins pour enchantjs dont certains ont été intégrés directement dans enchant.js. Par exemple avatar, ui, box2d, gl, timeline

On va commencer par s’intéresser à timeline, plugin qui n’en est plus un maintenant.

timeline

Supposons que l’on veuille déplacer un sprite d’un point A à un point B sur une certaine période de temps. Il va falloir : prendre en compte la distance entre les deux points, le taux de frame par seconde, et calculer de combien le sprite doit se déplacer. Le « plugin » timeline permet de faire ça plus simplement : il permet de contrôler les entités suivant le temps (et aussi suivant les frames). En faisant un_sprite.tl.setTimeBased(), on indiquera un temps dans les méthodes du plugin, alors que par défaut (ou avec un_sprite.tl.setFrameBased()) on indiquera un nombre de frames.

Par exemple, bear.tl.moveTo(250, 250, 2000); fera bouger bear vers le point (250, 250) en 2 secondes ou en 2000 frames (de la même manière, il existe moveBy qui permet de se déplacer d’un certain nombre de pixels). On peut également faire tourner (rotateTo et rotateBy), mettre à l’échelle (scaleTo et scaleBy) ou alors régler l’opacité du sprite (fadeIn, fadeOut et fadeTo) de la même façon.

Ce qui est pratique, c’est qu’on peut enchaîner les instructions :

bear.tl.moveTo(250, 250, 2000).scaleTo(-1, 1, 250)
     .moveTo(10, 10, 2000).scaleTo(1, 1, 250);

On se déplace, se tourne, puis on retourne au point de départ, et on se remet dans le bon sens. Cela n’empêche en rien l’ajout d’écouteur comme on peut le voir dans l’exemple 2.

Dans l’exemple suivant, on voit que les méthodes loop, delay et then font ce que leur nom indique : loop permet de répéter à l’infini une séquence, delay permet de temporiser et then permet l’appel à une fonction. (Pour arrêter la boucle, on peut utiliser unloop.)

Si on veut enchaîner les appels à delay/then :

bear.tl.delay(30).then(une_fonction).
    delay(15).then(function{}(
        dosomething(foo));).
    delay(10).then(function{}(
        this.anotherthing(););

on peut utiliser cue à la place :

bear.tl.cue({
    30: une_noction,
    45: function{}(do_something(foo)),
    55: function{}(this.anotherthing())
});

Dans l’exemple 4, on a deux sprites qui se comportent de façon identique, l’un avec delay/then, l’autre avec cue.

On a vu précédemment, que bear.tl.moveTo(250, 250, 2000).scaleTo(-1, 1, 250) permettait au sprite de se déplacer, puis de se retourner. Si on veut faire les deux actions en même temps, on peut soit utiliser la méthode tween :

bear1.tl.tween({
    x: 250,
    y: 250,
    scaleX: 2,
    rotation: 45,
    opacity: 0.5,
    time: 2000});

qui permet de faire toutes ces opérations en même temps, soit utiliser la méthode and :

bear2.tl.delay(2000).moveTo(250, 10, 3000).and().
    scaleTo(3, 1, 4000).and().
    fadeTo(0.5, 100);

qui permet de chaîner les instructions (et également de mettre des durées d’action différentes) comme le montre l’exemple 5.

La ligne de temps est en fait gérée sous forme de queue. Et quand on fait bear.tl.moveBy(10,10,10); la timeline est retournée. On peut donc soit enchaîner les actions sur une même ligne, soit les mettre sur plusieurs :

bear.tl.moveBy(10,10,10).rotateTo(90,100);
//est équivalent à
bear.tl.moveBy(10,10,10);
bear.tl.rotateTo(90,100);

On peut aussi arrêter/redémarrer la ligne de temps :

bear1.on('touchstart', function(){
    if (flag){
        bear1.tl.pause();
    }else{
        bear1.tl.resume();
    }
    flag = !flag;

});

Et attendre un événement avec la méthode waitUntil qui prend en argument une fonction qui va retourner vrai au bout d’un moment ce qui permet de passer à l’action d’après :

bear3.tl.waitUntil(function(){
    bear3.moveBy(1,1);
    return bear3.x>200;
}).moveTo(150, 150, 1000).waitUntil(function(){
    return flag;}).moveTo(200, 200, 1000);

Ici, bear3 va se déplacer d’un pixel par un pixel, et lorsque qu’il aura dépassé la borne, il ira en (150, 150), puis attendra que flag soit à true et se déplacera à nouveau.

Il existe encore d’autres méthodes, mais on ne va pas les voir (je vous invite à regarder le code source), à part la méthode action qui prend comme paramètre la durée d’exécution de l’action (avec time), une fonction d’initialisation, une fonction de fin, et une fonction à exécuter durant l’exécution de l’action :

bear2.tl.delay(1000).action({
        time: 2000,
        onactionstart: function(){
            lbl.text = "ça commence";
            bear2.tl.show();
        },
        onactionend: function(){
            lbl.text = "c’est fini";
            bear2.tl.removeFromScene();
        },
        onactiontick: function(){
            lbl.text = "c’est en cours";
            bear2.x++;
            bear2.opacity -= 1 / 60;
        }
});

Ces trois derniers points sont regroupés dans l’exemple 6.

Pour terminer, on va s’intéresser à un argument que prennent la plupart de ces méthodes. On peut en effet contrôler la vitesse d’exécution des animations (easings.net). Pour cela on ajoute la fonction en dernier paramètre :

sprite.tl.moveBy(100, 100, enchant.Easing.QUAD_EASEOUT).
      fadeTo(0.5, enchant.Easing.SWING)

Les différentes fonctions possibles sont montrées dans l’exemple suivant.

ui

Le plugin ui définit un certain nombre de classes comme une croix directionnel, un pad analogique, la création de bouton, et moultes autres choses bien sympathiques. On va voir la plupart.

Croix directionnelle, pad analogique

On a fait un jeu qui utilise les flèches du clavier, mais on veut que notre jeu soit jouable sur tablette. Comment faire ? On utilise la classe Pad ou APad du plugin :

var pad = new Pad();
pad.x = 0;
pad.y = 220;
game.rootScene.addChild(pad);


var apad = new APad();
apad.x = 0;
apad.y = 220;
game.rootScene.addChild(apad);

Dans le cas de la croix directionnelle, on peut utiliser game.input.left, comme pour le clavier. On a donc seulement le code du dessus à ajouter pour avoir un pad qui fonctionne : la différence entre l’exemple 8 et l’exemple 8b, c’est uniquement le code ci-dessus.

On peut faire en sorte que l’utilisateur ait un retour sur le fait qu’il clique bien sur la croix :

pad.frame = 0;
if (game.input.left) {
    this.vx = -4;
    pad.frame = 1;
    pad.rotation = 270;
}

Le frame 1 de la croix a le bouton du haut de grisé. En jouant sur la rotation, on obtient l’effet souhaité.

Pour le pad analogique, c’est tout aussi simple. Il suffit d’ajouter

this.moveBy(apad.vx*5, apad.vy*5);

comme le montre l’exemple 8c. Si on veut ne gérer que le pad, il suffit de supprimer les contrôles sur game.input. À l’inverse, on peut aussi ne pas vouloir se déplacer à la fois avec le pad et les flèches. Il suffit de contrôler si le pad est touché avec apad.touched :

if (apad.isTouched){
    this.vx = apad.vx*5;
    this.vy = apad.vy*5;
}

C’est ce qui est fait dans l’exemple 8d.

Les boutons

Le plugin permet aussi de créer de jolis boutons facilement. Le code

btn_un = new Button("Un premier bouton", "blue", 50, 150);

crée un bouton de 50×150 avec le texte Un premier bouton en appliquant le thème bleu. On peut bien sûr ajouter des thèmes pour choisir ses propres couleurs. Quand on appuie sur le bouton, btn.pressed passe à true, btn.y est incrémenté, et le thème active est appliqué. Quand on relâche, btn.pressed passe à false, btn.y est décrémenté, et le thème repasse à normal. Pour voir ça en action, c’est dans l’exemple 9.

Affichage de texte

Les labels utilisent les polices de l’ordinateur. Si vous avez un peu regardé les images fournies par enchant.js, vous avez certainement remarqué que dans font0.png, il y a des icônes pour chaque lettre (ascii). Pour les utiliser facilement, on peut se servir de la classe MutableText. On donne en paramètre les coordonnées, ainsi que la largeur de la zone :

var mt = new MutableText(100,0,120);
mt.text = 'Are you ready?';

Le texte sera alors affiché avec les lettres du fichier font0.png ce qui fait un peu plus jeu vidéo.

Une sous-classe de MutableText est ScoreLabel. Elle permet d’afficher… un score. Ce score est en fait composé d’une variable label — par défaut, "Score:" — et d’un nombre, qui défile pour atteindre la variable score. Si on ne veut pas faire défiler le score, il suffit de mettre la variable easing à 0. Sinon, plus ce nombre est grand, plus il défile doucement.

var sl = new ScoreLabel(20, 70);
sl.label = 'Points: ';
sl.easing = 5;
game.rootScene.onenterframe = function(){
    if (this.age % 50 ===0){
        sl.score += 1000;
    }};

Dans le même genre, il y a la classe TimeLabel qui affiche un chronomètre, ou un compte à rebours :

var tl1 = new TimeLabel(0, 100);
game.rootScene.addChild(tl1);

var tl2 = new TimeLabel(0, 120, 'countdown');
tl2.label = 'Reste: ';
tl2.time = 20;
game.rootScene.addChild(tl2);

Là aussi le texte — par défaut à "Time:" — peut être modifié.

La classe LifeLabel permet d’afficher le nombre de cœurs. On précise le nombre de cœur maximum au début, et quand on incrémente le compteur, celui-ci ne dépassera pas ce maximum.

var ll = new LifeLabel(0, 150, 5);
ll.label.text = 'Vie : ';
ll.life = 3;
game.rootScene.onenterframe = function(){
    if (this.age % 50 ===0){
        ll.life++;
    }
}

Pas vraiment du texte pour cette dernière classe, mais elle est liée à la LifeLabel puisqu’elle permet d’afficher une barre de vie (ou de points de magie, de l’expérience…) :

var bar = new Bar(10, 220);
game.rootScene.addChild(bar);
bar.maxvalue = 300;
bar.value = bar.maxvalue;
bar.ontouchstart = function(){
    bar.value -= 50;
}

On peut utiliser bar.image pour changer l’image de la barre, la direction de la barre avec bar.direction = 'left'; pour la faire diminuer dans l’autre sens, et utiliser bar.easing pour changer la vitesse d’animation.

Toutes ces classes sont regroupés dans ce dernier exemple.

Autres plugins

Dans le dossier examples/plugins d’enchant.js, il y a des exemples pour ces deux plugins, ainsi que pour avatar (animation d’avatar), box2d (pour la physique 2D), gl (pour utiliser webgl, ce qui permet entre autre de faire de la 3D), widget (pour avoir des boutons, menu de navigation, etc.) ou encore wiiu (pour jouer sur la Wii U). Mais ça, je vous laisse regarder par vous-même.


Écrire un commentaire

Quelle est la dernière lettre du mot dssm ?