iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Phaser (JS)

Phaser 3: 2D web game framework. Scenes, sprites, physics, input, and the patterns for shipping browser games fast.

Game dev — Phaser 3

EXAMPLE
# ===== Install =====
npm install phaser

# ===== Hello, game =====
import Phaser from 'phaser';

class MainScene extends Phaser.Scene {
  preload() {
    this.load.image('player', 'assets/player.png');
    this.load.image('ground', 'assets/ground.png');
  }

  create() {
    this.add.image(400, 300, 'ground');

    this.player = this.physics.add.sprite(400, 100, 'player');
    this.player.setBounce(0.2);
    this.player.setCollideWorldBounds(true);

    this.cursors = this.input.keyboard.createCursorKeys();
  }

  update() {
    if (this.cursors.left.isDown) this.player.setVelocityX(-200);
    else if (this.cursors.right.isDown) this.player.setVelocityX(200);
    else this.player.setVelocityX(0);

    if (this.cursors.up.isDown && this.player.body.touching.down) {
      this.player.setVelocityY(-400);
    }
  }
}

new Phaser.Game({
  type: Phaser.AUTO,
  width: 800, height: 600,
  parent: 'game',
  physics: { default: 'arcade', arcade: { gravity: { y: 600 } } },
  scene: [MainScene],
});

# ===== Scenes =====
# A game is a list of scenes. Switch with this.scene.start('SceneKey').
class MenuScene extends Phaser.Scene { /* ... */ }
class GameScene extends Phaser.Scene { /* ... */ }
class GameOver  extends Phaser.Scene { /* ... */ }

# ===== Physics: Arcade (fast) vs Matter (realistic) =====
# arcade: AABB collisions, fast, fine for platformers + shoot-em-ups
# matter: full rigid-body physics with joints / friction; more expensive

this.physics.add.collider(player, platforms);
this.physics.add.overlap(player, coins, collectCoin, null, this);

# ===== Input =====
this.input.on('pointerdown', (pointer) => { /* ... */ });
this.input.keyboard.on('keydown-SPACE', () => { /* ... */ });

# ===== Animations =====
this.anims.create({
  key: 'run',
  frames: this.anims.generateFrameNumbers('player', { start: 0, end: 7 }),
  frameRate: 10,
  repeat: -1,
});
this.player.play('run');

# ===== Sprite groups + pooling =====
const bullets = this.physics.add.group({
  defaultKey: 'bullet',
  maxSize: 50,
});
const b = bullets.get(player.x, player.y);
if (b) { b.setActive(true).setVisible(true).setVelocityY(-400); }

# ===== Cameras =====
this.cameras.main.startFollow(player, true, 0.05, 0.05);
this.cameras.main.setBounds(0, 0, 1600, 1200);

# ===== Tilemaps =====
const map = this.make.tilemap({ key: 'level1' });
const tiles = map.addTilesetImage('tiles', 'tiles');
const ground = map.createLayer('Ground', tiles);
ground.setCollisionByProperty({ collides: true });

# ===== Sound =====
this.load.audio('jump', 'assets/jump.wav');
const jump = this.sound.add('jump');
jump.play();

# ===== Build for production =====
# Vite + Phaser is the easiest dev experience:
npm create vite@latest mygame -- --template vanilla-ts
npm install phaser
# Then your scenes + main.ts as above; npm run build outputs static assets.

# ===== Mobile / packaging =====
# Wrap with Capacitor for iOS / Android (browser game in a webview).
# Or use Cordova / Electron for desktop.

# ===== Patterns to internalise =====
# - One scene per gameplay state (menu, play, pause, gameover)
# - Object pools for bullets / particles
# - Camera follow + bounds for level scrolling
# - Tilemaps for level design; do not hand-place every tile

# ===== Pitfalls =====
# - Loading huge images / audio without compression
# - Forgetting to set collision boundaries on tilemap layers
# - Re-creating game objects every frame instead of pooling
# - Heavy physics with no profiling -> frame drops on phones

Why it matters

Phaser 3 is the fastest path from idea to playable 2D web game. Scenes + Arcade physics + tilemaps + animations + pooling cover most genres. Pair with Vite for the dev loop and Capacitor / Cordova for app stores. Profile early; phones are not your dev laptop.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Phaser 3 minimal scene
class Game extends Phaser.Scene {
    preload() { this.load.image('player', 'p.png'); }
    create()  { this.p = this.add.sprite(100, 100, 'player'); }
    update(_, dt) { this.p.x += 0.2 * dt; }
}
new Phaser.Game({ width: 480, height: 270, scene: Game });
Try it Yourself »

Discussion

Loading…