Yodacon Ship Pack · Tutorial Note 7 · October 2026
Thirty-Six Textures on One Image: How the PixiJS Example Uses the Pack
Abstract—The PixiJS example loads a pack ship's sheet-alpha.png once, cuts it into 36 textures that share one source using the library's frameRect(), and flies a sprite by swapping its texture each tick. This note follows the page's source.
Index Terms—PixiJS, texture atlases, sprite sheets, pixel art.
I. Introduction
PixiJS draws sprites from textures, and a texture can frame part of a shared image. The PixiJS example
uses that to turn the pack's sheet into 36 textures over one GPU upload, then flies a sprite by swapping its
texture. PixiJS 8.6.6 is imported from a pinned URL (index.html:32).
II. Assets Used
| Asset | Read at | Used for |
|---|---|---|
ship.json | index.html:36 | Frame grid, stats, name |
sheet-alpha.png | index.html:50 | One texture source |
frameRect(), frameIndex() | index.html:33 | Cells and frame choice |
III. Pixel Art First
Before any texture exists, the default sampling is set to nearest-neighbour
(index.html:41), and the application is created without antialiasing
(index.html:45). Every texture made afterwards keeps the 1997 pixels square.
IV. Thirty-Six Textures, One Source
Assets.load loads the sheet once. Each frame is then a Texture that shares the
sheet's source and frames one cell, with the rectangle from the library's
frameRect() (Listing 1):
(x, y, w, h) = ((f mod 6) · w, ⌊f / 6⌋ · h, w, h)(1)
index.html:50–5450const sheet = await Assets.load(ship.urls.sheet);51const frames = Array.from({ length: 36 }, (_, i) => {52 const r = frameRect(ship, i);53 return new Texture({ source: sheet.source, frame: new Rectangle(r.x, r.y, r.w, r.h) });54});
Because all 36 share one source, the GPU holds one image, and switching frames costs nothing but a pointer.
V. The Sprite
The sprite starts on frame 0 with its anchor at the centre, so it turns about its middle, and a
whole-number scale (index.html:61–63).
VI. Each Tick
The ticker turns the heading, picks f = frameIndex(θ) and assigns
frames[f] to the sprite (Listing 2). As in every example, sprite.rotation stays 0.
Thrust follows the frame shown, along (sin a, −cos a) with a = 10f°.
index.html:75–8475app.ticker.add((ticker) => {76 const dt = Math.min(ticker.deltaMS / 1000, 0.1);77 if (keys.ArrowLeft) heading -= TURN * dt;78 if (keys.ArrowRight) heading += TURN * dt;79 heading = (heading + 360) % 360;80 const frame = frameIndex(heading);81 sprite.texture = frames[frame]; // swap the frame; never set sprite.rotation8283 const a = (frame * 10 * Math.PI) / 180; // heading 0 = up, clockwise84 if (keys.ArrowUp) { vx += Math.sin(a) * ACCEL * dt; vy -= Math.cos(a) * ACCEL * dt; }
VII. Using It in Your Project
- Set
scaleMode = "nearest"before loading. Assets.loadthe sheet; build the 36 frame textures once per ship type.- Give every ship its own
Spriteand assignframes[frameIndex(heading)].
Pixi's AnimatedSprite takes the same array if you want a ship that simply spins.
VIII. Conclusion
The sheet becomes an array of textures indexed by Equation (1)'s frame number; from there the pack ship is an ordinary Pixi sprite.
References
- Yodacon Ship Pack, “From sprite sheet to moving ship,” Tutorial Note 1, examples/, 2026. examples/#tutorial
- Yodacon Ship Pack, lib/yodacon-ship-pack.js, v2.0.0, 2026.
- PixiJS authors, PixiJS v8.6.6, 2024. [Online]. Available: pixijs.com