Animations programmées¶
Interpolation¶
Une interpolation c'est ce qui nous permet de "remplir les trous" entre deux points pour obtenir une transition lisse.
Imaginons un personnage qui doit se déplacer de la gauche (point A) vers la droite (point B) en trois secondes.
❌ Sans interpolation : Le personnage sauterait du point A au point B sans transition.
✅ Avec interpolation : Le mouvement est décomposé en plusieurs petites étapes, faisant apparaître le personnage à diverses positions intermédiaires, donnant l'impression qu'il se déplace en douceur à travers l'écran. Voyez cela un peu comme les images par secondes au cinéma🍿.
Interpolation avec Phaser¶
Pour animer un élément de jeu, on peut utiliser le système d'interpolation de Phaser. Cela peut se faire par une animation interpolée (Tweens), par une séquence d'animations (Timeline / TweenChain) ou par une animation de parcours (PathFollow).
Animation interpolée (Tween)¶
De manière générale, une animation interpolée représente simplement une transformation géométrique 📐.
Pour créer une nouvelle animation (Tween), on doit écrire la commande this.tweens.add({});
. Cela indique à la scène Phaser qu'une animation doit être déclenchée. Voici la syntaxe d'un exemple très minimal, sans spécification sur l'animation :
this.tweens.add({
targets: objet_à_animer,
});
Translation¶
create() {
const circle = this.add.circle(100, config.height / 2, 10, 0xffffff);
this.tweens.add({
targets: circle,
x: 600,
duration: 3000,
repeat: -1
});
}
x
: La nouvelle position sur l'axe des X. L'image se déplacera horizontalement jusqu'à cette position.
create() {
const circle = this.add.circle(config.width / 2, 50, 10, 0xffffff);
this.tweens.add({
targets: circle,
y: 300,
duration: 1500,
repeat: -1,
yoyo: true
});
}
y
: La nouvelle position sur l'axe des Y. L'image se déplacera verticalement jusqu'à cette position.
Rotation¶
create() {
const ellipse = this.add.ellipse(config.width / 2, config.height / 2, 50, 20, 0xffffff)
this.tweens.add({
targets: ellipse,
angle: 360,
duration: 1500,
repeat: -1
})
}
angle
: La nouvelle valeur de l'angle en degrés. Par exemple, une valeur de 360 fera tourner l'objet d'un tour complet.
create() {
const ellipse = this.add.ellipse(config.width / 2, config.height / 2, 50, 20, 0xffffff)
this.tweens.add({
targets: ellipse,
rotation: Math.PI * 2,
duration: 1500,
repeat: -1
})
}
rotation
: La nouvelle valeur de la rotation en radians. Une valeur de Math.PI (3.14159...) équivaut à une rotation de 180 degrés.
Échelle¶
create() {
const circle = this.add.circle(config.width / 2, config.height / 2, 10, 0xffffff);
this.tweens.add({
targets: circle,
scale: 3,
duration: 1000,
repeat: -1,
yoyo: true
});
}
scale
: Modifie la taille de l'élément. Une valeur de 2 doublera la taille, tandis qu'une valeur de 0.5 la réduira de moitié.
Transparence¶
create() {
const circle = this.add.circle(config.width / 2, config.height / 2, 10, 0xffffff)
this.tweens.add({
targets: circle,
alpha: 0,
duration: 1500,
repeat: -1,
yoyo: true
})
}
alpha
: Modifie l'opacité de l'élément. La valeur doit se situer entre 0 et 1. Une valeur de 1 signifie que l'élément est complètement opaque (100% d'opacité), tandis qu'une valeur de 0 le rend totalement transparent. Les valeurs entre 0 et 1 représentent différents niveaux de transparence.
Fonctions d'accélération¶
this.tweens.add({
targets: belleLune,
x: 700,
duration: 5000,
repeat: -1,
ease: 'Circ.easeOut'
});
Liste des fonctions d'accélération Phaser
Autres propriétés¶
this.tweens.add({
targets: sprite,
x: 0,
y: 0,
alpha: 1.0,
scale: 1,
angle: 0,
rotation: 0,
duration: 0,
ease: 'Linear',
delay: 0, // Délai avant l'animation
repeat: 0, // Nombre de répétitions (-1 pour infini)
yoyo: false,
hold: 0, // Temps de pause entre les yoyo
repeatDelay: 0, // Délai entre chaque répétition
paused: false, // Commencer en pause
onStart: function (tween, targets) {
console.log('Animation commencée');
},
onComplete: function (tween, targets) {
console.log('Animation terminée');
},
onYoyo: function (tween, targets) {
console.log('Yoyo');
},
onRepeat: function (tween, targets) {
console.log('Répétition');
},
onUpdate: function (tween, targets) {
console.log('Mise à jour');
}
});
Séquence d'animations¶
Chaine d'animation¶
La chaine n'animation déclenche un tween après l'autre tout simplement. Voici la syntaxe :
create() {
this.tweens.chain({
targets: img,
loop: -1, // infini
tweens: [
{
x: 400,
angle: -90,
duration: 1500
},
{
y: 100,
duration: 1500
},
{
x: 100,
y: 200,
angle: 360,
duration: 1000,
onComplete: () => {
// Callback
}
}
]
});
}
Exemple complet¶
Ligne du temps (timeline)¶
L'usage de ligne du temps sert à spécifier plus précisément à quel moment une animation dans une séquence s'animations doit s'activer.
Cette méthode permet de superposer des animations au lieu de les déclencher séquentiellement (chain).
Pour définir une nouvelle séquence d'animations de type timeline, on doit la déclarer dans une variable.
let timeline = this.add.timeline();
On y ajoute ensuite des animations avec la structure suivante :
timeline.add({
at: 0,
tween: {
// Paramètres de l'animation
},
});
timeline.add({
at: 1500,
tween: {
// Paramètres de l'animation
},
});
timeline.add({
at: 5400,
tween: {
// Paramètres de l'animation
},
});
at
: Spécifie en millisecondes le moment où l'animation (Tween) doit commencer par rapport au début de sa séquence (Timeline).
Finalement, pour démarrer la séquence, il faut simplement appeler la fonction play()
:
timeline.play();
Pour répéter l'animation, il ne suffit que d'appeler la fonction repeat()
:
timeline.play().repeat();
Exemple complet¶
Animation de parcours (follower)¶
Pour créer une animation de parcours le plus simplement possible, il faut créer un chemin vectoriel.
const cheminVectoriel = new Phaser.Curves.Path();
Ensuite, on assigne des coordonnées. Par exemple, une simple ligne comporte 2 coordonnées; le départ et la fin.
cheminVectoriel.moveTo(200, 100);
cheminVectoriel.lineTo(600, 300);
Finalement, il faut créer un follower
et appeler sa fonction startFollow
. Voici un exemple :
class Example extends Phaser.Scene {
preload() {
this.load.image("img", "chemin/vers/mon/image.png");
}
create() {
const cheminVectoriel = new Phaser.Curves.Path(200, 100).lineTo(600, 300);
const graphics = this.add.graphics(); // Facultatif
graphics.lineStyle(3, 0xffffff, 1); // Facultatif
cheminVectoriel.draw(graphics); // Facultatif
this.add.follower(cheminVectoriel, 0, 0, "img").startFollow({
positionOnPath: true,
duration: 2000,
yoyo: true,
repeat: -1,
rotateToPath: true
});
}
}
Exemple simple¶
Exemple intermédiaire¶
Exemple avancé¶
Exemple avec physique¶
Le système de physique et des animations programmées sont complètement différents et ne fonctionne normalement pas ensemble. Toutefois, il est possible de simuler l'animation désirée et d'applique les coordonnées de cette animation à la vélocité d'un objet.
Autrement dit, exécute ces trois étapes :
- On défini le chemin d'animation
- On exécute mathématiquement l'animation
- On applique une vélocité en fonction des coordonnées de l'animation
update(time, delta) {
// Supposons que 't' est mis à jour par un tween ou un calcul du temps
const t = (time % duration) / duration;
// Position cible sur le chemin
const targetPosition = path.getPoint(t);
// Calcul de la direction vers la position cible
const direction = new Phaser.Math.Vector2(
targetPosition.x - sprite.x,
targetPosition.y - sprite.y
).normalize();
// Application de la vélocité en fonction de la direction
sprite.body.setVelocity(
direction.x * speed,
direction.y * speed
);
}
Exercices¶
Exercice - Phaser
Sssssss
Exercice - Phaser
L'ambulance ambulante
Exercice - Phaser
La tête dans les nuages
Devoir¶
Devoir 6 | Partie 1/2
Ajouter au moins une animation programmée dans votre jeu. Cela peut être exécuté dans n'importe quelle scène, pas seulement la scène jeu, même si ce serait sans doute la plus pertinente.
Remise : 28 octobre à 23h59