| name | basementuniverse-sprite |
| description | Use this skill when working with @basementuniverse/sprite - a 2D sprite component for games with animations, directions, attachment points, and debug visualization. Invoke when creating or modifying game sprites, implementing sprite animations, setting up directional sprites (e.g., walk-left, walk-right), working with attachment points for composite sprites, or integrating with Content Manager for asset loading.
|
Basement Universe Sprite
Use this skill when working with @basementuniverse/sprite.
Overview
@basementuniverse/sprite is a TypeScript library for creating and managing 2D animated sprites in canvas-based games. It provides:
- Multi-directional animations: Define animations that vary by direction (e.g., walk-left, walk-right, walk-up, walk-down)
- Flexible animation modes: Loop indefinitely, play once and stop, or play once and reset
- Attachment points: Define named points on sprites that can be animated and queried in world space (useful for attaching weapons, effects, etc.)
- Transform support: Position, rotation, scale, and origin offset
- Debug visualization: Built-in rendering for bounding boxes, transforms, and attachment points
- Content Manager integration: Optional integration with
@basementuniverse/content-manager for asset loading
Installation
npm install @basementuniverse/sprite
Basic Usage
Creating a Sprite
import { Sprite } from '@basementuniverse/sprite';
const sprite = new Sprite({
directions: ['left', 'right', 'up', 'down'],
defaultDirection: 'down',
animations: {
idle: {
'*': {
name: 'idle',
frameCount: 1,
frameRate: 1,
images: [idleImage],
}
},
walk: {
left: {
name: 'walk',
frameCount: 4,
frameRate: 8,
mode: 'repeat',
images: [walkLeft1, walkLeft2, walkLeft3, walkLeft4],
},
right: {
name: 'walk',
frameCount: 4,
frameRate: 8,
mode: 'repeat',
images: [walkRight1, walkRight2, walkRight3, walkRight4],
},
}
},
defaultAnimation: 'idle',
});
Game Loop Integration
sprite.update(dt);
sprite.draw(context);
Controlling Sprites
sprite.position = vec(100, 100);
sprite.rotation = Math.PI / 4;
sprite.scale = 1.5;
sprite.animation = 'walk';
sprite.direction = 'right';
sprite.playAnimation();
sprite.pauseAnimation();
sprite.resetAnimation();
Key Concepts
Direction Fallbacks
When looking up an animation for a specific direction:
- First tries the exact direction name
- Falls back to
'*' (wildcard) if defined
- Falls back to the first available direction
- Throws error if animation doesn't exist
Animation Repeat Modes
'repeat': Loop indefinitely (default)
'play-once-and-stop': Play once and remain on last frame
'play-once-and-reset': Play once and return to first frame
Attachment Points
Attachment points are named positions on a sprite that can be:
- Defined with a default offset from the sprite origin
- Animated per-frame using keyframes in animations
- Retrieved in world space (accounting for sprite transforms)
const sprite = new Sprite({
attachmentPoints: [
{ name: 'hand', offset: vec(10, 5) }
],
animations: {
attack: {
'*': {
name: 'attack',
frameCount: 3,
frameRate: 10,
attachmentPointKeyframes: {
hand: [
{ frame: 0, offset: vec(10, 5) },
{ frame: 1, offset: vec(15, 3) },
{ frame: 2, offset: vec(10, 5) },
]
}
}
}
}
});
const handPosition = sprite.getAttachmentPoint('hand');
if (handPosition) {
}
Content Manager Integration
For projects using @basementuniverse/content-manager, use SpriteOptionsData with asset names instead of loaded images:
import { spriteOptionsContentProcessor } from '@basementuniverse/sprite';
ContentManager.registerProcessor('sprite', spriteOptionsContentProcessor);
const spriteData: SpriteOptionsData = {
imageName: 'base-sprite',
animations: {
walk: {
left: {
name: 'walk',
frameCount: 4,
imageNames: ['walk-left-1', 'walk-left-2', 'walk-left-3', 'walk-left-4'],
}
}
}
};
Common Patterns
Multi-directional Character Sprite
const character = new Sprite({
directions: ['up', 'down', 'left', 'right'],
defaultDirection: 'down',
animations: {
idle: {
'*': { name: 'idle', frameCount: 1, images: [idleImage] }
},
walk: {
up: { name: 'walk', frameCount: 4, frameRate: 8, images: walkUpFrames },
down: { name: 'walk', frameCount: 4, frameRate: 8, images: walkDownFrames },
left: { name: 'walk', frameCount: 4, frameRate: 8, images: walkLeftFrames },
right: { name: 'walk', frameCount: 4, frameRate: 8, images: walkRightFrames },
}
},
defaultAnimation: 'idle',
});
if (movementDetected) {
character.animation = 'walk';
character.direction = movementDirection;
} else {
character.animation = 'idle';
}
Composite Sprites with Attachments
const body = new Sprite({
attachmentPoints: [
{ name: 'leftHand', offset: vec(-10, 0) },
{ name: 'rightHand', offset: vec(10, 0) },
],
});
const weapon = new Sprite({ });
const handPos = body.getAttachmentPoint('rightHand');
if (handPos) {
weapon.position = handPos;
}
Debug Visualization
const sprite = new Sprite({
debug: {
showSpriteTransforms: true,
showSpriteBoundingBox: true,
showAttachmentPoints: true,
}
});
const sprite = new Sprite({
debug: true
});
Important Notes
- Coordinates: Uses
@basementuniverse/vec for 2D vectors (vec2)
- Rotation: Measured in radians
- Frame indexing: Zero-based (frame 0 is the first frame)
- Image fallback: If animation frame image is missing, falls back to base image
- Empty sprites: Sprites can exist without images (useful as attachment point hosts)
- Transform order: Translate(position) → Scale(scale) → Rotate(rotation)
References