Licence CC BY-NC-SA

La fin du niveau

Dernière mise à jour :

Pour finir le niveau, il faut bien définir ce qui va nous servir de repère. Il y a plusieurs possibilités bien sûr :

  • Le score
  • Un repère géographique
  • La collision avec un objet déterminé

Et c'est ce dernier élément que l'on va choisir. Et comme Raymond est un mouton, quoi de plus logique que de le faire rentrer à la bergerie ? :P

Créer la bergerie

Comme pour notre joueur, il faut commencer par créer un Sprite personnalisé. Et comme j'aime bien tout nommer en anglais, on va l'appeler Sheepfold (bergerie, donc) :

1
2
3
4
5
Q.Sprite.extend('Sheepfold', {
    init: function(p) {
        this._super(p, { sheet: 'my_sheepfold' });
    }
});

Mais avant, il ne faut pas oublier de charger l'image correspondante et de préparer la feuille correspondante (oui, on va créer un sprite avec une seule tile) :

1
Q.sheet('my_sheepfold', 'sheepfold-sprite.png', { tileW: 30, tileH: 30 });

Et maintenant, mesdames et messieurs… la bergerie !

La bergerie

N'oubliez pas d'ajouter l'image au pré chargement, comme toujours !

Il ne faudrait pas non plus oublier de l'ajouter à notre niveau :

1
2
3
4
stage.insert(new Q.Sheepfold({ // Il faut positionner le centre du sprite, qui sera tout en haut à droite de la scène
    x: tiles.p.w - Q.sheets['my_sheepfold'].tileW/2, // Calé à droite
    y: Q.sheets['my_sheepfold'].tileW/2 // Calé en haut
}));

Gérer la collision

Pour détecter si le joueur est arrivé au bon endroit, il suffit de savoir s'il entre en collision avec notre bergerie.

Pour cela, on va ajouter un écouteur dans le constructeur du joueur (l'objet Player dans le code) :

1
2
3
4
5
this.on('hit.sprite',function(collision) { // Quand le joueur entre en collision avec un autre Sprite
    if(collision.obj.isA('Sheepfold')) { // S'il s'agit d'une bergerie
        console.log('Bienvenue à la bergerie !');
    }
});

Notez que si vous pouvez obtenir pas mal d'infos sur les collisions. N'hésitez pas à tester !

L'écran de fin

Une fois notre joueur arrivé à la fin du niveau, il ne nous reste plus qu'à le féliciter, vous ne croyez pas ?

Pour cela, on va donc lancer une nouvelle scène, à laquelle on pourra passer des paramètres (vous verrez, ça peut parfois être très pratique), lors de la collision

1
2
3
/* À ajouter dans l'écouteur créé précédemment */
Q.stageScene('endGame', 1, { label: 'Gagné !' }); // On lance l'écran de fin avec un message personnalisé
this.destroy(); // On détruit notre joueur, vu que la partie est terminée

On va aussi s'empresser de créer cette fameuse scène, avec un conteneur et un bouton pour relancer le jeu :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Q.scene('endGame', function (stage) {
    var container = stage.insert(new Q.UI.Container({
        x: Q.width/2,
        y: Q.height/2,
        fill: 'rgba(0, 0, 0, 0.5)',
        radius: 5
    }));

    var button = container.insert(new Q.UI.Button({ x: 0, y: 0, fill: '#f7f7f7', label: 'Rejouer', highlight: '#ffffff', radius: 2 }));

    button.on('click', function() { // On place un écouteur sur le bouton, mais vous savez déjà faire normalement…
        Q.clearStages(); // On vide les scènes affichées, pour repartir sur un canvas vierge
        console.log('Bouton cliqué, redémarrage du jeu…');
        Q.stageScene('game', 0); // On relance le jeu
    });

    container.fit(10);
});

Bah… et notre paramètre alors ⁈

Justement, j'y venais !

Ce serait quand même sympa d'afficher un message personnalisé à notre joueur quand il finit le niveau, non ?

On va donc insérer un élément texte juste avant notre bouton, pour afficher notre fameux paramètre, qui peut être récupéré grâce à stage.options :

1
2
3
4
5
6
7
8
9
if (stage.options.label) {
    container.insert(new Q.UI.Text({
        x: 0,
        y: 0,
        color: '#ffffff',
        align: 'center',
        label: stage.options.label
    }));
}

Le problème maintenant c'est que notre bouton et notre texte sont superposés. Il va donc falloir recalculer la position verticale du bouton.

Pour cela, un va créer une variable avant d'ajouter quoi que ce soit au conteneur :

1
var button_y = 0; // Par défaut il n'y a pas besoin de décaler le bouton

Ensuite, après avoir ajouté notre texte, il va falloir recalculer tout ça :

1
button_y += Math.ceil(container.children[container.children.length - 1].p.h) + 10;

Explication : On récupère la hauteur du texte (qui se trouve être le dernier enfant du conteneur jusqu'à présent — le bouton n'étant ajouté qu'après), on arrondit à l'entier supérieur et on ajoute une marge de 10 pixels.

Il donc n'y a plus qu'à utiliser cette variable pour positionner notre bouton en remplaçant y: 0 par y: button_y. Et le tour est joué !


Et voilà, notre Raymond adoré peut maintenant rentrer tranquillement rejoindre ses copains !

Mais pour combien de temps encore… ?