In this section, you will learn how to build a complete game in Phaser by following a structured, step-by-step approach. We will apply the concepts learned throughout the course, from setting up scenes to handling input, managing game state, and adding polish. By the end, you’ll have a playable game and a clear understanding of how to structure your own projects.
- Planning the Game Structure
Before coding, it’s crucial to outline the game’s structure:
- Game Genre: Platformer (player jumps and collects stars)
- Core Features:
- Player movement and jumping
- Collectible items (stars)
- Score tracking
- Simple enemy
- Game over and restart
Game Flow Table:
Step | Description |
---|---|
1. Boot/Preload | Load assets |
2. Main Menu | Start game, show instructions |
3. Gameplay | Player controls, collect stars, avoid enemy |
4. Game Over/Win | Show score, option to restart |
- Setting Up the Project
Directory Structure:
index.html Example:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Phaser Platformer Game</title> <script src="https://cdn.jsdelivr.net/npm/phaser@3/dist/phaser.js"></script> </head> <body> <script src="main.js"></script> </body> </html>
- Creating the Game Scenes
We’ll use three scenes: PreloadScene
, MenuScene
, and GameScene
.
3.1 PreloadScene
Loads all assets.
class PreloadScene extends Phaser.Scene { constructor() { super('PreloadScene'); } preload() { this.load.image('background', 'assets/background.png'); this.load.image('player', 'assets/player.png'); this.load.image('star', 'assets/star.png'); this.load.image('enemy', 'assets/enemy.png'); } create() { this.scene.start('MenuScene'); } }
3.2 MenuScene
Displays the main menu and starts the game.
class MenuScene extends Phaser.Scene { constructor() { super('MenuScene'); } create() { this.add.text(100, 100, 'Platformer Game', { fontSize: '32px', fill: '#fff' }); this.add.text(100, 150, 'Press SPACE to Start', { fontSize: '24px', fill: '#fff' }); this.input.keyboard.once('keydown-SPACE', () => { this.scene.start('GameScene'); }); } }
3.3 GameScene
Handles the main gameplay.
class GameScene extends Phaser.Scene { constructor() { super('GameScene'); this.score = 0; } create() { // Background this.add.image(400, 300, 'background'); // Player this.player = this.physics.add.sprite(100, 450, 'player'); this.player.setCollideWorldBounds(true); // Stars group this.stars = this.physics.add.group({ key: 'star', repeat: 5, setXY: { x: 120, y: 0, stepX: 120 } }); // Enemy this.enemy = this.physics.add.sprite(400, 500, 'enemy'); this.enemy.setVelocityX(100); this.enemy.setCollideWorldBounds(true); this.enemy.setBounce(1, 0); // Score text this.scoreText = this.add.text(16, 16, 'Score: 0', { fontSize: '24px', fill: '#fff' }); // Input this.cursors = this.input.keyboard.createCursorKeys(); // Collisions this.physics.add.overlap(this.player, this.stars, this.collectStar, null, this); this.physics.add.overlap(this.player, this.enemy, this.hitEnemy, null, this); } update() { // Player movement if (this.cursors.left.isDown) { this.player.setVelocityX(-160); } else if (this.cursors.right.isDown) { this.player.setVelocityX(160); } else { this.player.setVelocityX(0); } if (this.cursors.up.isDown && this.player.body.touching.down) { this.player.setVelocityY(-330); } } collectStar(player, star) { star.disableBody(true, true); this.score += 10; this.scoreText.setText('Score: ' + this.score); // Win condition if (this.stars.countActive(true) === 0) { this.scene.restart(); alert('You win! Final Score: ' + this.score); } } hitEnemy(player, enemy) { this.physics.pause(); player.setTint(0xff0000); this.scoreText.setText('Game Over! Final Score: ' + this.score); this.input.keyboard.once('keydown-SPACE', () => { this.scene.restart(); }); } }
- Initializing the Game
main.js Example:
const config = { type: Phaser.AUTO, width: 800, height: 600, physics: { default: 'arcade', arcade: { gravity: { y: 300 }, debug: false } }, scene: [PreloadScene, MenuScene, GameScene] }; const game = new Phaser.Game(config);
- Testing and Iterating
- Test: Open
index.html
in your browser. - Iterate: Adjust player speed, add more stars, tweak enemy behavior, or improve visuals as desired.
- Exercise: Add a Double Jump Feature
Task:
Modify the player so they can jump twice before landing.
Hint:
Track the number of jumps and reset it when the player lands.
Solution:
// In GameScene class create() { // ... existing code ... this.jumpCount = 0; // ... existing code ... } update() { // ... existing code ... if (this.cursors.up.isDown && (this.player.body.touching.down || this.jumpCount < 2)) { if (this.player.body.touching.down) { this.jumpCount = 0; } if (!this.jumpPressed) { this.player.setVelocityY(-330); this.jumpCount++; this.jumpPressed = true; } } else if (!this.cursors.up.isDown) { this.jumpPressed = false; } if (this.player.body.touching.down) { this.jumpCount = 0; } }
Common Mistake:
Forgetting to reset jumpCount
when the player lands, which prevents further jumps.
- Summary
You have now built a simple but complete game using Phaser, applying all the core concepts: scenes, sprites, input, physics, collisions, and game state management. You also learned how to extend gameplay with new features. This step-by-step approach can be adapted to create more complex games. In the next section, you’ll learn how to polish and finalize your game for release.
Phaser - Game Development with JavaScript
Module 1: Introduction to Game Development and Phaser
- What is Game Development?
- Overview of Phaser
- Setting Up Your Development Environment
- Your First Phaser Project
Module 2: Phaser Basics
- Understanding the Game Loop
- Game Configuration and Scenes
- Loading and Displaying Images
- Working with Text
- Handling Input (Keyboard and Mouse)
Module 3: Sprites and Animation
Module 4: Game Physics and Interactivity
- Introduction to Physics in Phaser
- Enabling Physics on Sprites
- Collisions and Overlaps
- Interactive Objects and Events