## Getting Started with PixiJS and TypeScript for 2D Games
Imagine crafting engaging 2D games that run buttery smooth in browsers—think platformers, puzzles, or endless runners. PixiJS, a lightning-fast 2D rendering engine built on WebGL, paired with TypeScript's type safety, makes this achievable without the headaches of raw canvas manipulation. This guide walks you through a battle-tested set of rules to structure your projects professionally. Whether you're solo or team-building, these practices ensure scalability, performance, and maintainability.
We'll journey from project initialization to deployment, hitting every critical aspect: setup, assets, scenes, UI, audio, input, animations, particles, optimization, and more. Follow these religiously for production-ready code. Pro tip: Use Cursor AI with this as your system prompt for supercharged development.
## Project Structure: Lay a Solid Foundation
Start with a monorepo mindset but keep it simple for games. Use Vite for bundling—it's fast, supports hot module replacement (HMR), and handles TypeScript out of the box. Initialize like this:
```bash
npm create vite@latest my-pixi-game -- --template vanilla-ts
cd my-pixi-game
npm install
npm install pixi.js @pixi/asset @pixi/sound
```
Organize your folders logically:
```
src/
├── assets/ # Images, audio (loaded via AssetLoader)
├── scenes/ # Scene classes (e.g., MenuScene, GameScene)
├── ui/ # Reusable UI components (Button, ProgressBar)
├── entities/ # Game objects (Player, Enemy)
├── utils/ # Helpers (math, easing)
├── core/ # App, GameManager, SceneManager
├── styles/ # CSS/SCSS
└── main.ts # Entry point
```
In `main.ts`, bootstrap your `Application`:
```typescript
import * as PIXI from 'pixi.js';
const app = new PIXI.Application({
width: 1024,
height: 768,
backgroundColor: 0x1099bb,
antialias: true,
autoDensity: true,
resolution: window.devicePixelRatio || 1,
});
document.body.appendChild(app.view as HTMLCanvasElement);
```
This setup scales to any resolution. Always enable `antialias` for crisp visuals on high-DPI screens.
## Core PixiJS Setup: Harness the Renderer
PixiJS v8+ uses a modern `Application` class that manages the ticker, renderer, and stage. Extend it sparingly—prefer composition. Key principles:
- **Single Canvas**: One `Application` instance per game. Resize dynamically:
```typescript
window.addEventListener('resize', () => {
app.renderer.resize(window.innerWidth, window.innerHeight);
});
```
- **Stage Management**: Use a `SceneManager` to swap scenes:
```typescript
class SceneManager {
currentScene: PIXI.Container | null = null;
push(scene: PIXI.Container) {
if (this.currentScene) app.stage.removeChild(this.currentScene);
app.stage.addChild(scene);
this.currentScene = scene;
}
}
```
For deeper dives, check the official [PixiJS repo](https://github.com/pixijs/pixijs) and [examples](https://github.com/pixijs/examples).
## Asset Management: Load Efficiently, No Blockers
Assets kill performance if mishandled. Use `@pixi/asset` loader exclusively:
```typescript
async function loadAssets() {
const loader = new PIXI.Assets();
await loader.load([
{ alias: 'player', src: 'assets/player.png' },
{ alias: 'bgMusic', src: 'assets/music.ogg', data: { preload: true } }
]);
// Start game
}
```
Rules:
- Prefix audio with `preload` in manifest for parallel loading.
- Use atlases (JSON + PNG) for spritesheets to minimize draw calls.
- Cache everything: `PIXI.Assets.cache.set(id, texture);`
- Handle errors: `loader.onError.add((error) => console.error(error));`
This prevents white screens and stuttering—assets load before scenes activate.
## Building Scenes: Modular and Reusable
Scenes encapsulate logic: Menu, Level, Pause. Each extends `PIXI.Container`:
```typescript
class GameScene extends PIXI.Container {
constructor() {
super();
this.build();
}
build() {
// Add background, player, UI
}
update(delta: number) {
// Logic here
}
}
```
Hook into the ticker:
```typescript
app.ticker.add((delta) => {
if (currentScene) currentScene.update(delta);
});
```
Scenes auto-cleanup on pop: Override `destroy()` to dispose children, textures.
## UI Elements: Crisp, Interactive Components
Roll your own UI—no external libs needed. Core primitives:
- **Text**: `PIXI.Text` with BitmapText for performance:
```typescript
const style = new PIXI.TextStyle({ fontFamily: 'Arial', fontSize: 24 });
const scoreText = new PIXI.Text('Score: 0', style);
```
- **Graphics**: Shapes, buttons:
```typescript
const button = new PIXI.Graphics();
button.beginFill(0xff0000).drawRoundedRect(0, 0, 200, 50, 10);
button.eventMode = 'static';
button.on('pointerdown', () => {});
```
- **NinePatch**: Stretchable UI via custom class.
Add hover effects: `button.on('pointerover', () => button.tint = 0xcccccc);`
## Audio: Immersive Without Lag
Use `@pixi/sound`:
```typescript
import { Sound } from '@pixi/sound';
Sound.from('bgMusic');
Sound.play('bgMusic', { loop: true, volume: 0.5 });
```
- Preload all SFX/BGM.
- Pool sounds for effects (e.g., 5 bullet shots).
- Pause on visibility change: `document.addEventListener('visibilitychange', () => Sound.pauseAll());`
## Input Handling: Responsive Controls
Unified input via `PIXI.FederatedPointerEvent` and keyboard:
```typescript
app.stage.eventMode = 'static';
app.stage.hitArea = app.renderer.screen;
// Keyboard
const keys = {};
window.addEventListener('keydown', (e) => keys[e.key] = true);
window.addEventListener('keyup', (e) => keys[e.key] = false);
// In update
if (keys['ArrowLeft']) player.x -= speed * delta;
```
Support gamepad too: `navigator.getGamepads()`. Normalize delta time for frame-rate independence.
## Animations and Spine: Bring to Life
- **Tween**: Use `GSAP` or Pixi `AnimatedSprite`:
```typescript
const frames = [];
for (let i = 1; i <= 4; i++) frames.push(PIXI.Texture.from(`player${i}.png`));
const anim = new PIXI.AnimatedSprite(frames);
anim.play();
```
- **Spine**: `@pixi/spine` for skeletal animation. Load via assets.
Sequence animations with promises for polish.
## Particles: Explosive Effects
`PIXI.ParticleContainer` for 1000s of sprites:
```typescript
import { ParticleContainer, Texture } from 'pixi.js';
const particles = new ParticleContainer(10000, {
scale: true,
position: true,
alpha: true
});
// Add emitters
```
For advanced, `@pixi/particles` with easings.
## Performance Optimization: 60 FPS Always
- Batch sprites: Same texture = one draw call.
- Culling: Custom bounds check in update.
- LOD: Swap low-res assets far away.
- Profile: `PIXI.Ticker.shared.autoStart = false;` for testing.
- WebGL2: Default in v8.
Target mobile: `powerPreference: 'high-performance'`.
## Deployment: From Dev to Prod
Build with `vite build`. Host on itch.io, GitHub Pages, or Steam (via Electron). Minify assets, use CDNs for PixiJS.
```bash
npm run build
```
Test on devices early.
## Wrapping Up: Your Game Dev Journey
Stick to these rules, and your PixiJS games will shine. Experiment with filters (blur, glow), filters, shaders for next-level effects. Scale to multiplayer with WebSockets. Happy coding—your first blockbuster awaits!
<div style="text-align: center; margin-top: 2rem;">
<a href="https://cursor.directory/pixijs-typescript-game-development-rules" target="_blank" rel="noopener noreferrer" class="view-full-resource-btn" style="display: inline-block; background-color: #f97316; color: white; padding: 12px 24px; border-radius: 8px; text-decoration: none; font-weight: 600; transition: background-color 0.2s;">View Full Resource</a>
</div>