export class Sprite extends Node { /** * * @param {string} name * @param {SpriteAtlas} atlas * @param {*} options */ constructor(name: string, atlas: SpriteAtlas, options?: any); atlas: SpriteAtlas; frameWidth: any; frameHeight: any; frame: any; offset: { x: any; y: any; }; flipH: boolean; flipV: boolean; modulate: any; opaque: any; framesPerRow: number; /** * convert frame index to atlas coordinates * * Example: 32x32 sprites in 256x256 atlas = 8 frames per row * Frame 0 = (0, 0) * Frame 5 = (160, 0) // 5 * 32 = 160 * Frame 8 = (0, 32) // wraps to next row */ getFrameRect(frameIndex: any): { x: number; y: number; width: any; height: any; }; /** * draw sprite to canvas * * * 1. Calculate world position (Node system handles this) * 2. Apply offset (pivot point) * 3. Get source rect from frame index * 4. Blit pixels using tessera's drawAtlasRegionToCanvas * * Note: We're NOT handling rotation/scale YET. That requires * per-pixel transforms which is slow in pure JS. For now, * rotation/scale affects position but not the sprite pixels. * * Future optimization: pre-render rotated sprites to cache, * * * If your atlas has no transparency (RGBA alpha always 255) and you don't need tint, call: * @param {Camera2D} camera */ _draw(canvas: any, camera: Camera2D): void; /** * Utility: set pivot to center of sprite */ centerOrigin(): void; } /** * * * why separate from Sprite: * - Not all sprites need animation (static decorations) * - Animation state (current frame, time accumulator) is extra memory * - Keeps Sprite class lean for performance * * Common use case: character walk cycles, enemy attack patterns */ export class AnimatedSprite extends Sprite { animations: any; currentAnimation: any; currentFrameIndex: number; frameTimer: number; playing: boolean; loop: boolean; onAnimationFinished: any; /** * start playing an animation * @param {string} animName * @param {boolean} restart * @returns */ play(animName: string, restart?: boolean): void; /** * stop animation (freeze on current frame) */ stop(): void; /** * pause (can resume with play()) */ pause(): void; /** * update animation state * * how frame timing works: * - animation has target FPS (e.g., 12 fps = 0.083s per frame) * - accumulate delta time until we hit frame duration * - advance to next frame * - loop or stop at end * * @param {number} delta * @returns */ _process(delta: number): void; /** * check if specific animation is playing * @param {string} animName * @returns */ isPlaying(animName?: string): boolean; /** * get current animation progress (0.0 to 1.0) */ getProgress(): number; } /** * for frame-by-frame animation using separate image files * * * Example: * ```js * const explosion = new Animator("explosion", renderer, { * animations: { * explode: { * frames: [ * "assets/explosion/frame_0.png", * "assets/explosion/frame_1.png", * "assets/explosion/frame_2.png", * "assets/explosion/frame_3.png" * ], * fps: 12, * loop: false * } * } * }); * explosion.play("explode"); * ``` */ export class Animator extends Node { /** * @param {string} name * @param {object} renderer - The renderer to load images * @param {object} options */ constructor(name: string, renderer: object, options?: object); renderer: any; animations: any; frameImages: {}; currentAnimation: any; currentFrameIndex: number; frameTimer: number; playing: boolean; loop: boolean; width: number; height: number; offset: { x: any; y: any; }; flipH: any; flipV: any; modulate: any; opaque: any; onAnimationFinished: any; load(): Promise; /** * Add an animation sequence * @param {string} name - Animation name * @param {string[]} imagePaths - Array of image file paths * @param {number} fps - Frames per second * @param {boolean} loop - Whether to loop */ addAnimation(name: string, imagePaths: string[], fps?: number, loop?: boolean): Promise; /** * Start playing an animation * @param {string} animName * @param {boolean} restart - Force restart if already playing */ play(animName: string, restart?: boolean): void; /** * Stop animation (freeze on current frame) */ stop(): void; /** * Pause animation */ pause(): void; /** * Resume paused animation */ resume(): void; /** * Get the current frame image */ getCurrentFrame(): any; /** * Update animation state * @param {number} delta - Time since last frame in seconds */ _process(delta: number): void; /** * Draw current animation frame * @param {object} canvas * @param {Camera2D} camera */ _draw(canvas: object, camera: Camera2D): void; /** * Center the sprite's pivot point */ centerOrigin(): void; /** * Check if specific animation is playing * @param {string} animName */ isPlaying(animName?: string): boolean; /** * Get current animation progress (0.0 to 1.0) */ getProgress(): number; /** * Clone this animator with all relevant data * @returns {Animator} A new Animator instance with cloned properties */ clone(): Animator; } /** * spriteAtlas - helper for managing shared atlases * * * - Multiple sprites often share the same atlas (all enemies, all UI icons) * - Loading atlas once and reusing saves memory * - Provides utilities for common atlas patterns (grid, packed) */ export class SpriteAtlas { /** * Utility: generate sequential frame array * Example: getFrameRange(0, 7) -> [0,1,2,3,4,5,6,7] */ static getFrameRange(start: any, end: any): any[]; constructor(renderer: any, path: any, options?: {}); path: any; image: any; frameWidth: any; frameHeight: any; framesPerRow: number; framesPerCol: number; totalFrames: number; /** * create a sprite from this atlas * @param {*} name * @param {*} frame * @param {*} options * @returns */ createSprite(name: any, frame?: any, options?: any): Sprite; /** * Create animated sprite from this atlas * @param {*} name * @param {*} animations * @param {*} options * @returns */ createAnimatedSprite(name: any, animations: any, options?: any): AnimatedSprite; } import { Node } from './core.js'; import { Camera2D } from './camera.js';