Skip to content

Sprite

The Sprite component is the primary way to display 2D graphics. Add it to an entity in the scene editor along with LocalTransform to make the entity visible.

Properties

PropertyTypeDefaultDescription
texturenumberINVALID_TEXTURETexture handle. No texture = solid color
colorColor{r:1, g:1, b:1, a:1}Tint color RGBA (0–1)
sizeVec2{32, 32}Width and height in pixels
uvOffsetVec2{0, 0}Texture coordinate offset
uvScaleVec2{1, 1}Texture coordinate scale
layernumber0Render order (higher = on top)
flipXbooleanfalseFlip horizontally
flipYbooleanfalseFlip vertically
materialnumber0Material ID

Basic Usage

In the scene editor: create an entity → add LocalTransform and Sprite → set size and color in the inspector.

To modify sprites at runtime, query them in a system:

import { defineSystem, addSystem, Res, Time, Query, Mut, LocalTransform, Sprite } from 'esengine';
addSystem(defineSystem(
[Res(Time), Query(Mut(LocalTransform), Sprite)],
(time, query) => {
for (const [entity, transform, sprite] of query) {
transform.position.x = Math.sin(time.elapsed) * 100;
}
}
));

Loading a Texture

The texture property expects a texture handle (number), not a file path. Load the image first with assets.loadTexture(), then assign the handle:

import { defineSystem, addStartupSystem, Res, Query, Mut, Sprite } from 'esengine';
import { Assets } from 'esengine';
import { Player } from './components';
addStartupSystem(defineSystem(
[Res(Assets), Query(Mut(Sprite), Player)],
async (assets, query) => {
const tex = await assets.loadTexture('assets/player.png');
for (const [entity, sprite] of query) {
sprite.texture = tex.handle;
sprite.size = { x: tex.width, y: tex.height };
}
}
));

See Asset Loading for the full texture API (getTexture, releaseTexture, 9-slice metadata, etc.).

Solid Color Rectangle

Without a texture (default), the sprite renders as a solid rectangle using its color and size.

Color Tinting

The color property tints the sprite. With a texture, the texture color is multiplied by the tint.

sprite.color = { r: 1, g: 0, b: 0, a: 1 }; // Red tint
sprite.color = { r: 1, g: 1, b: 1, a: 0.5 }; // 50% transparent

Flipping

sprite.flipX = true; // Mirror horizontally
sprite.flipY = true; // Mirror vertically

Sprite Sheet Animation

Use uvOffset and uvScale to display a portion of a texture. Define a custom Animation component, attach it alongside Sprite on the entity in the editor:

import { defineComponent, defineSystem, addSystem, Res, Time, Query, Mut, Sprite } from 'esengine';
const Animation = defineComponent('Animation', {
frames: 4,
currentFrame: 0,
frameTime: 0.1,
elapsed: 0
});
addSystem(defineSystem(
[Res(Time), Query(Mut(Sprite), Animation)],
(time, query) => {
for (const [entity, sprite, anim] of query) {
anim.elapsed += time.delta;
if (anim.elapsed >= anim.frameTime) {
anim.elapsed = 0;
anim.currentFrame = (anim.currentFrame + 1) % anim.frames;
sprite.uvOffset.x = anim.currentFrame / anim.frames;
sprite.uvScale.x = 1 / anim.frames;
}
}
}
));

Render Order

Sprites are drawn by:

  1. Z position (transform.position.z) — lower Z draws first (behind)
  2. Layer (sprite.layer) — higher layer draws on top

Set these in the inspector or modify at runtime.

Runtime Spawning

For sprites created at runtime (bullets, particles):

import { defineSystem, addSystem, Commands, Sprite, LocalTransform } from 'esengine';
addSystem(defineSystem(
[Commands()],
(cmds) => {
cmds.spawn()
.insert(Sprite, {
size: { x: 10, y: 10 },
color: { r: 1, g: 1, b: 0, a: 1 }
})
.insert(LocalTransform, {
position: { x: 0, y: 0, z: 0 }
});
}
));