mwg API
    Preparing search index...

    Class AnimatedSprite

    A sprite that plays named animations, and can still be tinted.

    Animations are registered once and played by name, which is how a character ends up reading as hero.play('walk') rather than juggling frame arrays.

    Nothing advances on its own: call update(dt) from the scene, or add the sprite to a SpriteGroup, so that pausing the game pauses the animations with it.

    Frames may carry their own duration, and the animation may start partway into itself, which is what Wesnoth's image=a.png:120,b.png:80 and start_time=-450 mean. A frame may also carry an offset, so a swing recoils a few pixels without a second texture: frameOffset reports it, and the caller adds it where it already positions the sprite. The framework does not apply it itself, on purpose - this sprite's position belongs to whoever put it there (a GridMover, a walk tween, a camera projection), and a sprite that overwrote y every frame would undo that every frame. FloatingText learned the same rule the hard way.

    Reduced motion deliberately does not pause this. A frame cycle is usually game state - a walking enemy that freezes when the player has asked for less motion is a bug, not an accommodation, and the article's own "Don't Reduce Too Much" is about exactly this. A game whose loops are purely decorative (torches, rippling water) can stop those itself through paused, or not add the sprite at all.

    Extends TintedSprite directly, so alpha composes with tint/colorAdd the same way here too - a translucent, animated ghost is alpha = 0.5 plus whatever tint, no different from a still one (see TintedSprite's own doc comment).

    import { AnimatedSprite, SpriteSheet } from '@datamoc/mw_games/two-d/render';

    declare const sheet: SpriteSheet;

    const hero = new AnimatedSprite();
    hero.add('idle', sheet.pick(0, 0, 0, 1), { fps: 2 });
    hero.add('walk', sheet.range(6, 10), { fps: 10 });
    hero.add('die', sheet.range(11, 14), { fps: 10, loop: false });
    hero.add(
    'thrust',
    [
    { texture: sheet.get(20), duration: 0.4 },
    { texture: sheet.get(21), duration: 0.1, offsetX: 3 }, // the lunge
    ],
    { startTime: -0.2 },
    );
    hero.play('idle');

    hero.onFinish = (name) => console.log(`${name} finished`);
    hero.update(1 / 60); // advance one frame's worth of time

    Hierarchy (View Summary)

    Index
    onFinish: ((name: string) => void) | null = null

    fires once when a non-looping animation reaches its last frame

    paused: boolean = false
    • get colorAdd(): number

      the packed additive colour; use setColorAdd or lerpTint rather than setting it raw

      Returns number

    • set colorAdd(value: number): void

      Parameters

      • value: number

      Returns void

    • get frameOffset(): { x: number; y: number }

      Where the current frame is drawn relative to the sprite's own position, in pixels. The caller adds it, as in sprite.position.set(x + sprite.frameOffset.x, y + sprite.frameOffset.y). Both are zero for a frame with no offset of its own.

      Returns { x: number; y: number }

    • Moves the sprite strength of the way towards color, leaving its shading intact.

      This sets both halves of the transform: the tint carries 1 - strength and the additive term carries color × strength.

      Parameters

      • color: number
      • strength: number

      Returns void

    • Starts an animation.

      Playing the one already running does nothing, so a movement loop can call play('walk') every frame without restarting it. Pass restart to force it.

      Parameters

      • name: string
      • restart: boolean = false

      Returns this