9.1 KiB
9.1 KiB
Implémentation Système de Vies, Obstacles et Coffre - TODO
✅ Ce qui est fait
1. Classes Créées
-
✅ TreasureChest (
src/entities/TreasureChest.ts)- Coffre qui s'ouvre avec 15 cadeaux collectés
- Donne +1000 points
- Effets visuels spectaculaires
-
✅ Player modifié avec invincibilité
- Méthode
makeInvincible() - Effet clignotant
- Timer d'invincibilité 2 secondes
- Méthode
2. Constantes Ajoutées
PLAYER_STARTING_LIVES = 3RESPAWN_INVINCIBILITY_TIME = 2000CHEST_REQUIRED_GIFTS = 15
3. Variables GameScene
lives: numbergiftsCollected: numberlastCheckpointX: numbertreasureChest: TreasureChest- UI texts pour vies et cadeaux
🚧 Ce qu'il reste à implémenter dans GameScene
1. Ajouter le coffre au niveau
Dans spawnTestObjects(), ajouter à la fin :
// Coffre final au bout du niveau
this.treasureChest = new TreasureChest(this, 7700, height - 300, CHEST_REQUIRED_GIFTS);
this.physics.add.overlap(this.player!, this.treasureChest, this.openChest, undefined, this);
2. Modifier createUI() - Ajouter affichage vies
Ajouter après le score :
// Vies
this.livesText = this.add.text(20, 60, `❤️ Vies: ${this.lives}`, {
fontSize: '28px',
color: '#ff0000',
stroke: '#000000',
strokeThickness: 4,
});
this.livesText.setScrollFactor(0);
this.livesText.setDepth(100);
// Cadeaux collectés
this.giftsCollectedText = this.add.text(20, 100, `🎁 Cadeaux: ${this.giftsCollected}/${CHEST_REQUIRED_GIFTS}`, {
fontSize: '24px',
color: '#FFD700',
stroke: '#000000',
strokeThickness: 3,
});
this.giftsCollectedText.setScrollFactor(0);
this.giftsCollectedText.setDepth(100);
3. Modifier collectGift() - Compter les cadeaux
private collectGift(_player: any, gift: any): void {
gift.destroy();
this.giftsCollected++;
this.addScore(100);
// Mettre à jour l'UI
this.giftsCollectedText?.setText(`🎁 Cadeaux: ${this.giftsCollected}/${CHEST_REQUIRED_GIFTS}`);
// Feedback si on a assez pour le coffre
if (this.giftsCollected >= CHEST_REQUIRED_GIFTS && !this.treasureChest?.getIsOpen()) {
// Flash doré
this.cameras.main.flash(100, 255, 215, 0, true);
const hint = this.add.text(
this.cameras.main.scrollX + this.cameras.main.width / 2,
this.cameras.main.height / 2,
'🏆 Assez de cadeaux! Trouvez le coffre! 🏆',
{
fontSize: '32px',
color: '#FFD700',
stroke: '#000000',
strokeThickness: 4,
}
);
hint.setOrigin(0.5);
hint.setScrollFactor(0);
hint.setDepth(1000);
this.tweens.add({
targets: hint,
alpha: 0,
duration: 3000,
onComplete: () => hint.destroy(),
});
}
}
4. Créer openChest() - Interaction avec le coffre
private openChest(_player: any, chest: any): void {
if (chest.canOpen(this.giftsCollected)) {
const bonus = chest.open(this);
this.addScore(bonus);
} else if (!chest.getIsOpen()) {
// Pas assez de cadeaux
const remaining = chest.getRequiredGifts() - this.giftsCollected;
const warning = this.add.text(
this.cameras.main.scrollX + this.cameras.main.width / 2,
this.cameras.main.height / 2,
`❌ Encore ${remaining} cadeaux nécessaires! ❌`,
{
fontSize: '28px',
color: '#FF0000',
stroke: '#000000',
strokeThickness: 4,
}
);
warning.setOrigin(0.5);
warning.setScrollFactor(0);
warning.setDepth(1000);
this.tweens.add({
targets: warning,
alpha: 0,
duration: 2000,
onComplete: () => warning.destroy(),
});
}
}
5. Modifier hitObstacle() - Système de vies
private hitObstacle(player: any, obstacle: any): void {
// Vérifier si on saute dessus (player au-dessus de l'obstacle)
const playerBody = player.body as Phaser.Physics.Arcade.Body;
const obstacleBody = obstacle.body as Phaser.Physics.Arcade.Body;
const isJumpingOn = playerBody.velocity.y > 0 &&
playerBody.bottom <= obstacleBody.top + 10;
if (isJumpingOn) {
// Sauter dessus = détruit l'obstacle
obstacle.destroy();
this.addScore(50); // Bonus pour avoir sauté dessus
player.jump(); // Petit rebond
// Effet visuel
this.add.circle(obstacleBody.x, obstacleBody.y, 20, 0x00FF00, 0.5)
.setDepth(100);
console.log('💚 Obstacle détruit en sautant dessus !');
} else {
// Collision frontale = perd une vie
if (player.getIsInvincible()) {
console.log('🛡️ Invincible - pas de dégâts');
return;
}
this.loseLife();
}
}
6. Créer loseLife() - Gestion perte de vie
private loseLife(): void {
this.lives--;
this.livesText?.setText(`❤️ Vies: ${this.lives}`);
// Flash rouge
this.cameras.main.flash(200, 255, 0, 0, true);
this.cameras.main.shake(200, 0.01);
console.log(`💔 Vie perdue! Vies restantes: ${this.lives}`);
if (this.lives <= 0) {
this.gameOver();
} else {
this.respawnPlayer();
}
}
7. Créer respawnPlayer() - Respawn au checkpoint
private respawnPlayer(): void {
if (!this.player) return;
// Téléporter au dernier checkpoint
this.player.setPosition(this.lastCheckpointX, this.cameras.main.height - 200);
this.player.setVelocity(0, 0);
// Activer invincibilité
this.player.makeInvincible(this);
// Message
const respawnText = this.add.text(
this.cameras.main.scrollX + this.cameras.main.width / 2,
this.cameras.main.height / 2,
`💫 RESPAWN! ${this.lives} ❤️ restantes`,
{
fontSize: '36px',
color: '#00FF00',
stroke: '#000000',
strokeThickness: 6,
}
);
respawnText.setOrigin(0.5);
respawnText.setScrollFactor(0);
respawnText.setDepth(1000);
this.tweens.add({
targets: respawnText,
alpha: 0,
duration: 2000,
onComplete: () => respawnText.destroy(),
});
}
8. Créer gameOver() - Game Over
private gameOver(): void {
console.log('💀 GAME OVER');
// Arrêter le jeu
this.physics.pause();
// Écran de game over
const gameOverText = this.add.text(
this.cameras.main.scrollX + this.cameras.main.width / 2,
this.cameras.main.height / 2 - 50,
'GAME OVER',
{
fontSize: '72px',
color: '#FF0000',
stroke: '#000000',
strokeThickness: 8,
fontStyle: 'bold',
}
);
gameOverText.setOrigin(0.5);
gameOverText.setScrollFactor(0);
gameOverText.setDepth(2000);
const scoreText = this.add.text(
this.cameras.main.scrollX + this.cameras.main.width / 2,
this.cameras.main.height / 2 + 50,
`Score Final: ${this.score}`,
{
fontSize: '36px',
color: '#FFFFFF',
stroke: '#000000',
strokeThickness: 4,
}
);
scoreText.setOrigin(0.5);
scoreText.setScrollFactor(0);
scoreText.setDepth(2000);
// Retour au menu après 3 secondes
this.time.delayedCall(3000, () => {
this.cleanup();
this.scene.start('MenuScene');
});
}
9. Système de Checkpoints (optionnel mais recommandé)
Dans update(), détecter quand le joueur passe un checkpoint :
// Mettre à jour le checkpoint tous les 1000px
if (this.player && this.player.x > this.lastCheckpointX + 1000) {
this.lastCheckpointX = this.player.x;
console.log(`🚩 Checkpoint! Position: ${this.lastCheckpointX}`);
}
🎮 Résumé des Mécaniques
Obstacles
- Sauter dessus : Détruit + 50 pts + rebond
- Collision frontale : Perd 1 vie (sauf si invincible)
Vies
- Départ : 3 vies
- Respawn : Position checkpoint + 2s invincibilité
- Game Over : 0 vies → retour menu
Coffre Final
- Requis : 15 cadeaux collectés
- Position : Fin du niveau (7700px)
- Récompense : +1000 points
- Feedback : Message si pas assez de cadeaux
UI
❤️ Vies: 3
🎁 Cadeaux: 12/15
Score: 2500
Timer: 2:15
📝 Fichiers à Modifier
- ✅
src/entities/TreasureChest.ts- Créé - ✅
src/entities/Player.ts- Modifié (invincibilité) - ✅
src/utils/constants.ts- Constantes ajoutées - 🚧
src/scenes/GameScene.ts- À compléter avec les fonctions ci-dessus
🔧 Test
- Lance le jeu
- Fonce dans un obstacle → perd 1 vie → respawn avec clignotement
- Saute sur un obstacle → détruit + bonus
- Collecte 15 cadeaux → message "Trouvez le coffre!"
- Va au bout du niveau et saute sur le coffre → MEGA BONUS!
Tout le code est prêt, il suffit de copier-coller les fonctions dans GameScene ! 🚀