Sprite
A textured 2D node: an image drawn in a Scene2D. Extends Node2D,
so it has the full transform, hierarchy, events and aspect surface. To animate it from a sprite
sheet, attach the SpriteAnimation aspect; to name an image's regions and
clips in a file, use a sprite sheet (.sprite.ts).
- draw an image in a 2D scene
- show one frame or region of a texture atlas
- put the sprite's pivot at its feet
- resize a sprite or draw it at the image's pixel size
- tint a sprite, fade it, or flip it to face left
Platforms: iOS, Android, desktop and the web player; not on the web (Web Lite); headless tests run it but draw nothing.
At a glance
async function main() {
const scene = new Scene2D()
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)
scene.open()
}
main()Create a sprite: new Sprite
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
})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 and size: texture, size
sprite.texture = tex // Texture2D, or a Canvas (baked on assign)
sprite.size = [w, h] // world units; an explicit size survives a texture change- 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. - Assigning a texture resets the frame to the whole texture.
- A sprite without a texture draws nothing.
Frames (atlases / spritesheets)
sprite.frame = [u0, v0, u1, v1] // normalized UV sub-rect; [0, 0] = the texture's top-left
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.
async function main() {
const scene = new Scene2D()
const tex = await Texture2D.load(asset('./items.png'))
const coin = new Sprite({ texture: tex, size: [16, 16], position: [40, 40] })
.setFramePx(32, 0, 16, 16) // the cell at x 32, y 0 of the atlas, drawn unscaled
scene.add(coin)
scene.open()
}
main()For frame-by-frame animation, don't drive frame yourself — attach
SpriteAnimation and define clips.
Tint, fade and flip: color, opacity, flipX
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 = true
sprite.animateTo({ opacity: 0, color: '#ff0000', duration: 300 }) // + the Node2D transform propsThe tint's alpha is ignored — fade with opacity. animateTo / animateFrom take opacity and
color on top of the transform props and return the
Animation handle.
Pitfalls
// ✗ expecting scale to resize a declared collider — explicit Shape2D extents ignore scale
sprite.scale = 2 // draws 2×, but its physics box stays the size you declared
// ✗ animating by swapping frames yourself — works, but re-implements SpriteAnimation
sprite.setFramePx(frame * 32, 0, 32, 48) // from a per-frame updateSee also
- Node2D — transform, hierarchy, events (inherited)
- SpriteAnimation — clips, fps, play/loop events
- Sprite sheets — named regions and clips in a
.sprite.tsfile - Texture2D — loading images
- Scene2D — layers, Y-sort, adding nodes