Phaser
25 minutes
linux
macos
windows

Project Setup

Set up a Phaser 3 project with Vite, TypeScript, and modern development tooling.

What you'll accomplish

Have a working Phaser development environment with hot reload.

Prerequisites

  • Node.js 18+ installed
  • Basic terminal knowledge
  • Completed "What is Phaser?" lesson

Project Setup Options

You can set up a Phaser project in several ways:

MethodProsCons
Vite + TypeScriptFast, modern, type safetyRequires build step
Phaser templateReady to goLess flexibility
CDN script tagSimplestNo modules, no types

We'll use Vite + TypeScript - the professional approach with the best developer experience.

Step 1: Create Project

Create a new Vite project:

bash
npm create vite@latest my-phaser-game -- --template vanilla-ts
cd my-phaser-game

This creates a basic TypeScript project. We'll add Phaser next.

Step 2: Install Phaser

bash
npm install phaser

Step 3: Clean Up Template

Delete the template files we don't need:

Step 4: Update HTML

Replace index.html:

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Phaser Game</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      body {
        background-color: #000;
        display: flex;
        justify-content: center;
        align-items: center;
        min-height: 100vh;
      }
      canvas {
        display: block;
      }
    </style>
  </head>
  <body>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

Step 5: Create Game Entry Point

Replace src/main.ts:

typescript
import Phaser from 'phaser';
import { MainScene } from './scenes/MainScene';

const config: Phaser.Types.Core.GameConfig = {
  type: Phaser.AUTO,
  width: 800,
  height: 600,
  backgroundColor: '#2d2d2d',
  parent: 'game-container',
  physics: {
    default: 'arcade',
    arcade: {
      gravity: { x: 0, y: 0 },
      debug: true, // Set to false for production
    },
  },
  scene: [MainScene],
};

new Phaser.Game(config);
  • type: Phaser.AUTO - Automatically choose WebGL or Canvas
  • width: 800, height: 600 - Game resolution in pixels
  • backgroundColor - Color shown when nothing else is drawn
  • physics.default: 'arcade' - Simple physics engine for most games
  • physics.arcade.debug: true - Show collision boxes (helpful for development)
  • scene: [MainScene] - Which scenes to load

Step 6: Create Your First Scene

Create src/scenes/MainScene.ts:

typescript
import Phaser from 'phaser';

export class MainScene extends Phaser.Scene {
  constructor() {
    super('MainScene');
  }

  preload(): void {
    // We'll load assets here later
  }

  create(): void {
    // Create game objects
    const text = this.add.text(400, 300, 'Hello Phaser!', {
      fontSize: '32px',
      color: '#ffffff',
    });
    text.setOrigin(0.5, 0.5); // Center the text

    // Log to confirm it's working
    console.log('MainScene created!');
  }

  update(): void {
    // Game loop - runs 60x per second
    // We'll add game logic here
  }
}

Step 7: Run the Development Server

bash
npm run dev

Open http://localhost:5173 in your browser. You should see "Hello Phaser!" on a gray background.

Tip

Vite provides hot reload - changes to your code appear instantly without refreshing!

Project Structure

Your project should look like:

my-phaser-game/
├── public/            # Static assets (images, sounds)
├── src/
│   ├── scenes/        # Game scenes
│   │   └── MainScene.ts
│   ├── main.ts        # Entry point
│   └── vite-env.d.ts  # TypeScript Vite types
├── index.html
├── package.json
├── tsconfig.json
└── vite.config.ts

Adding Assets

Download Sample Assets

For testing, download some free assets. Create a public/assets folder:

bash
mkdir -p public/assets

For now, let's create a simple colored square programmatically.

Update MainScene.ts:

typescript
import Phaser from 'phaser';

export class MainScene extends Phaser.Scene {
  private player!: Phaser.GameObjects.Rectangle;

  constructor() {
    super('MainScene');
  }

  preload(): void {
    // No external assets yet
  }

  create(): void {
    // Create a simple rectangle as our player
    this.player = this.add.rectangle(400, 300, 50, 50, 0x00ff00);

    // Make it a physics object
    this.physics.add.existing(this.player);

    // Add some text
    this.add.text(400, 50, 'Use Arrow Keys to Move', {
      fontSize: '24px',
      color: '#ffffff',
    }).setOrigin(0.5);
  }

  update(): void {
    const cursors = this.input.keyboard?.createCursorKeys();

    if (!cursors) return;

    const body = this.player.body as Phaser.Physics.Arcade.Body;
    const speed = 200;

    // Reset velocity
    body.setVelocity(0);

    // Handle input
    if (cursors.left.isDown) {
      body.setVelocityX(-speed);
    } else if (cursors.right.isDown) {
      body.setVelocityX(speed);
    }

    if (cursors.up.isDown) {
      body.setVelocityY(-speed);
    } else if (cursors.down.isDown) {
      body.setVelocityY(speed);
    }
  }
}

Now you have a green square you can move with arrow keys!

TypeScript Configuration

The default tsconfig.json works, but here's an optimized version:

json
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,

    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,

    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"]
}

Vite Configuration

Create vite.config.ts:

typescript
import { defineConfig } from 'vite';

export default defineConfig({
  base: './',  // Relative paths (important for deployment)
  build: {
    outDir: 'dist',
    assetsDir: 'assets',
    sourcemap: false,
  },
  server: {
    port: 5173,
    open: true,  // Auto-open browser
  },
});

npm Scripts

Add useful scripts to package.json:

json
{
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "typecheck": "tsc --noEmit"
  }
}
ScriptPurpose
npm run devStart development server
npm run buildBuild for production
npm run previewPreview production build
npm run typecheckCheck for TypeScript errors

Common Issues

Frequently Asked Questions

Make sure you installed Phaser:

bash
npm install phaser

Then restart the dev server.

Check the browser console for errors. Common causes:

  • Scene name mismatch
  • Missing scene in config
  • JavaScript error in create()

Click on the game canvas first! The canvas needs focus to receive keyboard events.

Make sure @types/phaser isn't installed - Phaser includes its own types. If installed, remove it:

bash
npm uninstall @types/phaser

Put images in public/assets/ and load them in preload():

typescript
preload() {
  this.load.image('player', 'assets/player.png');
}

Verify Your Understanding

You've completed this lesson if you can:

0/5

Next: Learn about scenes and the game loop in depth.