Sprite
A textured 2D node — the workhorse of a 2D scene. Extends Node2D, so it has the
full transform, hierarchy, events, and aspect surface. Sprite-sheet animation is not built in:
attach the SpriteAnimation aspect.
At a glance
const tex = await Texture2D.load(asset('./hero.png'))
const hero = new Sprite({ texture: tex, anchor: [0.5, 1], layer: 1 })
.aspect(SpriteAnimation, { size: [32, 48], fps: 10, clips: { idle: [0], walk: [1, 2, 3, 4] } })
hero.position = [120, 64]
hero.anim.play('walk')
scene.add(hero)Creating
new Sprite(options?: {
texture?: Texture2D | Canvas // a Canvas bakes to a texture on assign
anchor?: Vec2Like // pivot: [0,0] top-left … [1,1] bottom-right; default [0.5, 0.5]
size?: Vec2Like // world size; default = the texture's pixel dimensions
frame?: [u0, v0, u1, v1] // normalized UV sub-rect
color?: ColorInput // tint, multiplied with the texture
opacity?: number // 0..1
layer?: number // draw layer (see Scene2D layers)
position?: Vec2Like
})Note
anchor space is Y-down even though the world is Y-up: [0.5, 1] is the sprite's
bottom-center ("feet"). Use it for anything on a Y-sorted layer so depth sorts by feet.
Texture & size
sprite.texture = tex // Texture2D, or a Canvas (baked on assign)
sprite.size = [w, h] // world units; resets native default when texture changes- Default size is the texture's pixel dimensions — 1 texel = 1 world unit = 1 logical px at zoom 1.
- A
Canvas-backed sprite defaults to the canvas's logical size, sopixelRatioon the canvas affects crispness only, never on-screen size. See Canvas.
Frames (atlases / spritesheets)
sprite.frame = [u0, v0, u1, v1] // normalized UV sub-rect
sprite.setFramePx(x, y, w, h): this // sub-rect in texture pixels — chainablesetFramePx is the one to use with an atlas: coordinates match what an image editor shows.
Changing the frame does not change size — set size once to the frame's pixel dimensions if
you want unscaled output.
For frame-by-frame animation, don't drive frame yourself — attach
SpriteAnimation and define clips.
Appearance
sprite.color = '#ff8800' // tint (multiplied); default white = untinted
sprite.opacity = 0.5 // 0..1
sprite.flipX = true // mirror horizontally (facing left/right without negative scale)
sprite.flipY = truePitfalls
// ✗ expecting scale to affect physics — Shape2D extents are raw world units, unscaled
sprite.scale = 2 // draws 2×, but its physics box stays the size you declared
// ✗ per-frame texture swaps for animation
setLoop(() => sprite.setFramePx(...)) // works, but re-implements SpriteAnimation poorlySee also
- Node2D — transform, hierarchy, events (inherited)
- SpriteAnimation — clips, fps, play/loop events
- Texture2D — loading images
- Scene2D — layers, Y-sort, adding nodes