Skip to content

PixiJS Project — Interactive 2D Game

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about PixiJS Project. We cover key concepts, practical examples, and best practices to help you master this topic.

This project walks through building a complete 2D game with PixiJS, combining sprites, animated characters, particle effects, collision detection, and Responsive Design.

What You'll Learn

By the end of this project, you will architect a game loop with PixiJS, implement player movement and shooting, create enemy spawning with difficulty curves, use particle effects for explosions, manage game state (menu, play, game over), and optimize for mobile.

Game Architecture

var Game = {
    state: 'menu',
    score: 0,
    player: null,
    enemies: [],
    bullets: [],
    particles: [],

    init: function() {
        this.app = new PIXI.Application({ width: 800, height: 600 });
        document.body.appendChild(this.app.view);

        this.setupStages();
        this.setupInput();
        this.gameLoop();
    },

    setupInput: function() {
        window.addEventListener('keydown', function(e) {
            Game.keys[e.code] = true;
        });
        window.addEventListener('keyup', function(e) {
            Game.keys[e.code] = false;
        });
    },

    gameLoop: function() {
        this.app.ticker.add(function(delta) {
            Game.update(delta);
        });
    }
};

Collision Detection

function checkCollisions() {
    for (var i = Game.enemies.length - 1; i >= 0; i--) {
        for (var j = Game.bullets.length - 1; j >= 0; j--) {
            if (rectsOverlap(Game.enemies[i], Game.bullets[j])) {
                Game.destroyEnemy(i);
                Game.destroyBullet(j);
                Game.score += 10;
                Game.spawnExplosion(Game.enemies[i].x, Game.enemies[i].y);
                break;
            }
        }
    }
}

function rectsOverlap(a, b) {
    var ab = a.getBounds();
    var bb = b.getBounds();
    return ab.x < bb.x + bb.width &&
           ab.x + ab.width > bb.x &&
           ab.y < bb.y + bb.height &&
           ab.y + ab.height > bb.y;
}

Common Mistakes

1. No Delta Time

Movement must be multiplied by delta for consistent speed across frame rates.

2. Memory Leaks from Bullets

Bullets that leave the screen must be destroyed. Use object pooling.

3. Collision Check Order

Check the least expensive collision first. Use spatial hashing for many objects.

4. Touch Not Working

Mobile needs touch controls. Add onscreen buttons or tap-to-shoot.

5. No Start Screen

Jumping straight into gameplay confuses users. Add a simple menu screen.

Practice Questions

Q1: How do you structure a PixiJS game? A: Use a game state machine with separate update and render methods.

Q2: How do you handle keyboard input? A: Listen to keydown/keyup events and track active keys in a map.

Q3: How do you detect sprite collisions? A: Use getBounds().x, .y, .width, .height for AABB collision checks.

Q4: How do you add delta time? A: The ticker callback receives delta. Multiply movement speeds by delta.

Q5: How do you create a particle explosion? A: Spawn 10-30 sprites at the explosion point with random velocities, fade alpha, and destroy after lifespan.

Challenge: Add power-ups that spawn every 10 seconds. Power-ups give triple shot for 5 seconds. Show a timer and visual indicator for the active power-up.

FAQ

Can I use PixiJS for mobile games?

Yes. PixiJS handles touch input and performs well on mobile with WebGL.

How do I add sound effects?

Use the Web Audio API or a library like Howler.js alongside PixiJS.

How do I create scrolling levels?

Use TilingSprites for background and scroll containers for game objects.

Can I use PixiJS with a physics engine?

Yes. Integrate Matter.js or Planck.js for physics.

How do I save high scores?

Use localStorage to persist scores between sessions.

Try It Yourself

Build a simple space shooter.

<!DOCTYPE html>
<html>
<head>
    <title>PixiJS Space Shooter</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/7.3/pixi.min.js"></script>
</head>
<body style="font-family:sans-serif;padding:20px;">
<h2>Space Shooter</h2>
<p>Arrow keys to move, Space to shoot</p>
<canvas id="game" style="border:1px solid #333;border-radius:8px;"></canvas>
<div id="score" style="margin-top:8px;font-size:18px;font-weight:bold;">Score: 0</div>
<script>
var app = new PIXI.Application({ width: 600, height: 450, background: 0x0a0a1a, view: document.getElementById('game') });

// Player
var player = new PIXI.Graphics();
player.beginFill(0x4ecdc4);
player.moveTo(30, 0);
player.lineTo(-20, -15);
player.lineTo(-20, 15);
player.closePath();
player.endFill();
player.x = 300;
player.y = 400;
app.stage.addChild(player);

// Input
var keys = {};
window.addEventListener('keydown', function(e) { keys[e.code] = true; });
window.addEventListener('keyup', function(e) { keys[e.code] = false; });

// Bullets
var bullets = [];
var bulletTexture = (function() {
    var g = new PIXI.Graphics();
    g.beginFill(0xff6b35);
    g.drawRect(0, 0, 4, 12);
    g.endFill();
    return app.renderer.generateTexture(g);
})();

function shoot() {
    var bullet = new PIXI.Sprite(bulletTexture);
    bullet.x = player.x - 2;
    bullet.y = player.y - 20;
    app.stage.addChild(bullet);
    bullets.push(bullet);
}

// Enemies
var enemies = [];
var enemyTexture = (function() {
    var g = new PIXI.Graphics();
    g.beginFill(0xff6b35);
    g.drawCircle(0, 0, 12);
    g.endFill();
    return app.renderer.generateTexture(g);
})();

function spawnEnemy() {
    var enemy = new PIXI.Sprite(enemyTexture);
    enemy.x = Math.random() * 550 + 25;
    enemy.y = -30;
    app.stage.addChild(enemy);
    enemies.push(enemy);
}

setInterval(spawnEnemy, 1000);

// Score
var score = 0;
var scoreEl = document.getElementById('score');

function checkCollisions() {
    for (var i = enemies.length - 1; i >= 0; i--) {
        for (var j = bullets.length - 1; j >= 0; j--) {
            var eb = enemies[i].getBounds();
            var bb = bullets[j].getBounds();
            if (eb.x < bb.x + bb.width && eb.x + eb.width > bb.x &&
                eb.y < bb.y + bb.height && eb.y + eb.height > bb.y) {
                app.stage.removeChild(enemies[i]);
                app.stage.removeChild(bullets[j]);
                enemies.splice(i, 1);
                bullets.splice(j, 1);
                score += 10;
                scoreEl.textContent = 'Score: ' + score;
                break;
            }
        }
    }
}

var canShoot = true;

app.ticker.add(function(delta) {
    // Movement
    if (keys['ArrowLeft']) player.x -= 5 * delta;
    if (keys['ArrowRight']) player.x += 5 * delta;
    player.x = Math.max(30, Math.min(570, player.x));

    if (keys['Space'] && canShoot) {
        shoot();
        canShoot = false;
        setTimeout(function() { canShoot = true; }, 200);
    }

    // Update bullets
    for (var i = bullets.length - 1; i >= 0; i--) {
        bullets[i].y -= 7 * delta;
        if (bullets[i].y < -20) {
            app.stage.removeChild(bullets[i]);
            bullets.splice(i, 1);
        }
    }

    // Update enemies
    for (var i = enemies.length - 1; i >= 0; i--) {
        enemies[i].y += 2 * delta;
        if (enemies[i].y > 500) {
            app.stage.removeChild(enemies[i]);
            enemies.splice(i, 1);
        }
    }

    checkCollisions();
});
</script>
</body>
</html>

What's Next

Explore Phaser for Game Development.

Getting Started — Game development with Phaser.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro