Appearance
@carrot/engine-framework-sprites ​
ts
Sprite rendering behaviours for the Carrot engine framework - image loading, texture creation, material setup, and render pipeline integration.
Installation ​
bash
npm install @carrot/engine-framework-spritesArchitecture / How It Works ​
Sprite + SpriteRenderer Pattern ​
Sprites use a two-behaviour pattern:
- Sprite - loads an image asset, creates a
Texture2D,Material2DSprite,MaterialInstance, and a quadMeshsized to the image dimensions (or an optionalsizeoverride). Callstexture.upload()during init. Exposestint,mainTexture,spriteSize, and a typedmaterialInstancefor convenient runtime control. - SpriteRenderer - a
RenderBehaviourthat reads mesh/material from a siblingSpriteand exposes them to the render pipeline. Providessubmit()to add a DrawCall to the renderer's draw list, anddraw(camera)for immediate-mode rendering. Internally usesbindMaterial()andcreateDrawCall()from the renderer packages.
Both behaviours must be on the same entity. SpriteRenderer finds its Sprite sibling in start().
Inheritance Chain ​
Behaviour
-> Sprite (image + texture + material + mesh)
-> SpriteAnimated (frame-based animation - stub)
-> SpritePacked (texture atlas/packing - stub)
RenderBehaviour
-> SpriteRenderer (reads from Sprite, exposes to pipeline)Bundle Registration ​
registerSpriteBehaviours(registry) registers all four types on a BehaviourRegistry, enabling template-based instantiation:
'sprite'-new Sprite(props.image)'spriteRenderer'-new SpriteRenderer()'spriteAnimated'-new SpriteAnimated(props.image)'spritePacked'-new SpritePacked(props.image)
Image Loading ​
Sprite.initialize() resolves the image source (string path or AssetImage instance), loads it, then creates the GPU resources. On failure, falls back to AssetImage.fallback and dispatches onImageFailed.
Dependencies ​
| Package | Used For |
|---|---|
@carrot/engine-framework | Behaviour, RenderBehaviour, BehaviourRegistry |
@carrot/engine-materials | Material2DSprite, MaterialInstance |
@carrot/engine-meshes | Mesh, meshFromQuad |
@carrot/engine-textures | Texture2D |
@carrot/engine-renderer-shaders | (transitive - shader support) |
@carrot/engine-shaders | (transitive - shader programs) |
@carrot/assets | AssetImage for image loading and fallback |
@carrot/signals | Signal for onImageLoaded/onImageFailed |
Build ​
bash
npm run build # runs tscOutput goes to dist/. Package is ESM ("type": "module").
Usage Guide ​
Sprite rendering behaviours for the Carrot engine framework.
Import ​
ts
import {
Sprite, SpriteRenderer, SpriteAnimated, SpritePacked,
registerSpriteBehaviours,
} from '@carrot/engine-framework-sprites';Common Patterns ​
1. Basic sprite entity ​
ts
import { Entity } from '@carrot/engine-framework';
import { Sprite, SpriteRenderer } from '@carrot/engine-framework-sprites';
const player = Entity.create2d('Player');
player.addBehaviour(new Sprite('player.png'));
player.addBehaviour(new SpriteRenderer());
scene.addEntity(player);2. Using an AssetImage directly ​
ts
import { AssetImage } from '@carrot/assets';
const image = AssetImage.get('characters/hero.png');
await image.load();
const entity = Entity.create2d('Hero');
entity.addBehaviour(new Sprite(image));
entity.addBehaviour(new SpriteRenderer());3. Handling load events ​
ts
const sprite = new Sprite('enemy.png');
sprite.onImageLoaded.add((image) => {
console.log(`Loaded: ${image.width}x${image.height}`);
});
sprite.onImageFailed.add((error) => {
console.error('Failed to load sprite:', error.message);
});
entity.addBehaviour(sprite);4. Register sprite behaviours for templates ​
ts
import { registerSpriteBehaviours } from '@carrot/engine-framework-sprites';
registerSpriteBehaviours(game.behaviours);
// Now templates can reference sprite types by name
const prefab: EntityTemplate = {
name: 'Bullet',
transform: { type: '2d', x: 0, y: 0 },
behaviours: [
{ type: 'sprite', properties: { image: 'bullet.png' } },
{ type: 'spriteRenderer', properties: {} },
],
};5. Checking render readiness ​
ts
const renderer = entity.getBehaviour(SpriteRenderer);
if (renderer?.visible) {
// mesh and material are both available - safe to draw
}6. Custom sprite size ​
ts
import { Size2 } from '@carrot/maths-geometry';
// Override the mesh size instead of using the image's natural dimensions
const sprite = new Sprite('tile.png', new Size2(64, 64));
entity.addBehaviour(sprite);7. Tint and texture access ​
ts
const sprite = entity.getBehaviour(Sprite)!;
// Change tint at runtime
sprite.tint = { r: 1, g: 0, b: 0, a: 1 };
// Swap the texture
sprite.mainTexture = anotherTexture;
// Read sprite dimensions
console.log(`Size: ${sprite.spriteSize.width}x${sprite.spriteSize.height}`);8. Submitting and drawing sprites ​
ts
const renderer = entity.getBehaviour(SpriteRenderer)!;
// Option A: submit a draw call to the renderer's draw list (batched)
renderer.submit();
// Option B: immediate-mode rendering - useful for one-off draws
renderer.draw(camera);9. Multiple sprites on one entity ​
ts
// Each Sprite creates its own mesh/material, but SpriteRenderer
// finds the first Sprite sibling. For multiple sprites, use
// separate child entities:
const ship = Entity.create2d('Ship');
const hull = Entity.create2d('Hull');
hull.addBehaviour(new Sprite('hull.png'));
hull.addBehaviour(new SpriteRenderer());
ship.addChild(hull);
const turret = Entity.create2d('Turret');
turret.addBehaviour(new Sprite('turret.png'));
turret.addBehaviour(new SpriteRenderer());
ship.addChild(turret);