/** * A textured **quad in 3D space** — the 3D counterpart of {@link Sprite}, * for rendering sprites under a {@link Camera3d} (the 2.5D workflow: characters, * pickups, foliage, signs, particles in a 3D scene). It's a thin {@link Mesh} * subclass, so it rides the same world-space mesh pipeline (depth testing, * frustum culling) and supports the same material features (`lit`, `emissive`, * `alphaCutoff`). * * Its headline feature is **billboarding** — keeping the quad facing the camera * regardless of camera orientation (see {@link Sprite3d#billboard}). With * billboarding off it's a fixed-orientation quad (decals, posters, ground * markers). * * **Frame animation** is supported through the same API as {@link Sprite} * ({@link Sprite3d#addAnimation}, {@link Sprite3d#setCurrentAnimation}, * {@link Sprite3d#play}/`pause`/`stop`) — pass `framewidth`/`frameheight` for a * spritesheet, or a packed {@link TextureAtlas}, exactly as you would for a 2D * `Sprite`. Both share the {@link FrameAnimation} engine, so the timing, looping * and chaining behavior is identical; `Sprite3d` maps the current frame onto the * quad each step — including packer **rotated** and **trimmed** regions, mapped * to full parity with the 2D `Sprite`. * * **Camera3d only.** Like {@link Mesh}, `Sprite3d` renders through the 3D * world-space path; under a 2D `Camera2d` it falls back to the mesh's * self-projection and **billboarding has no effect** (a 2D scene has no camera * orientation to face). Use a regular {@link Sprite} for 2D. * * **Anchoring.** Unlike its {@link Mesh} parent — where `anchorPoint` is inert * on the 3D path and transforms pivot at the model origin — Sprite3d's * `anchorPoint` is live: the anchor is baked into the quad's local vertices * (never applied as a renderer transform on either camera path) and can be * changed at runtime via `anchorPoint.set(...)`, which re-bakes the quad and * re-derives the cull bounds. Same key, convention and centered default as * the 2D {@link Sprite}, including the named presets (`"bottom"`, …). * @augments Mesh * @category Game Objects * @example * import { Application, Camera3d, Sprite3d } from "melonjs"; * * // a 3D app (Camera3d is required for billboarding) * const app = new Application(1024, 768, { cameraClass: Camera3d }); * * // a tree that always faces the camera but stays upright (2.5D). * // its texture has a transparent background — the mesh pass is opaque, so * // `alphaCutoff` (default 0.5) discards those texels for a clean silhouette. * const tree = new Sprite3d(0, 0, { * image: "tree", // a preloaded image with transparency * width: 64, height: 96, * z: -200, // 3D depth (world z) * billboard: true, // = "cylindrical" * // alphaCutoff: 0.5, // the default — lower it to keep softer edges, * // or set 0 for a fully-opaque quad * }); * app.world.addChild(tree); // add it to the game world, like any Renderable * * // an animated, fully camera-facing pickup from a spritesheet, mirrored * const coin = new Sprite3d(0, 0, { * image: "coins", * framewidth: 32, frameheight: 32, * width: 48, height: 48, * billboard: "spherical", * alphaCutoff: 0.5, // cut out the transparent frame background * }); * coin.addAnimation("spin", [0, 1, 2, 3, 4, 5]); * coin.setCurrentAnimation("spin"); * coin.flipX(); // face the other way (mirrors the sprite) * app.world.addChild(coin); * * // a character anchored at the feet, so `pos` sits on the ground plane * // instead of at the sprite's geometric center * const hero = new Sprite3d(0, 0, { * image: "hero", * width: 48, height: 64, * billboard: "cylindrical", * anchorPoint: "bottom", // == { x: 0.5, y: 1 } * }); */ export default class Sprite3d extends Mesh { /** * @param {number} x - world x position * @param {number} y - world y position * @param {object} settings - configuration * @param {HTMLImageElement|HTMLCanvasElement|Texture2d|string} [settings.image] - the sprite texture (image name, image, or a {@link Texture2d} asset such as a {@link TextureAtlas}). Alias: `settings.texture`. * @param {number} [settings.width=settings.framewidth] - quad width in world units (pixels) * @param {number} [settings.height=settings.width] - quad height in world units * @param {number} [settings.framewidth] - width of a single frame within a spritesheet (enables frame animation) * @param {number} [settings.frameheight] - height of a single frame within a spritesheet * @param {string} [settings.region] - region name when using a texture atlas (see {@link TextureAtlas}) * @param {object[]} [settings.anims] - predefined animations (same shape as {@link Sprite}) * @param {number} [settings.z=0] - 3D depth (world z); also settable later via `.depth` * @param {boolean|string} [settings.billboard=false] - billboard mode: `false` (fixed orientation), `true` / `"cylindrical"` (faces the camera but stays upright — the 2.5D default), or `"spherical"` (faces the camera on all axes). Only applies under a `Camera3d`. * @param {string|Vector2d|{x:number,y:number}} [settings.anchorPoint={x:0.5,y:0.5}] - anchor of the quad relative to `pos` — same key, normalized 0..1 convention (`x`: 0 left→1 right, `y`: 0 top→1 bottom) and centered default as the 2D {@link Sprite}. Also accepts the named presets `"center"`, `"top"`, `"bottom"`, `"left"`, `"right"`, `"top-left"`, `"top-right"`, `"bottom-left"`, `"bottom-right"`. Baked into the quad's local vertices (composes with billboarding, flips, and trimmed/rotated atlas frames) — never applied as a renderer transform on either camera path. Mutable at runtime via `this.anchorPoint.set(...)` (re-bakes the quad and re-derives the cull bounds). Invalid values throw. * @param {boolean} [settings.flipX=false] - mirror the sprite horizontally (see {@link Sprite3d#flipX}) * @param {boolean} [settings.flipY=false] - mirror the sprite vertically (see {@link Sprite3d#flipY}) * @param {boolean} [settings.lit=false] - shade through the lit mesh batcher (see {@link Mesh}) * @param {number[]|Float32Array} [settings.emissive] - emissive color (see {@link Mesh}) * @param {number} [settings.shadowGroundY] - world Y of the floor the blob shadow lands on. Omit and it falls back to the sprite's own base — which for a billboard moves with the camera, so a scene that knows where its floor is should say so. * @param {number} [settings.shadowOpacity=0.45] - opacity of the shadow directly beneath the sprite, before any height fade * @param {boolean} [settings.castGroundShadow] - give this sprite a blob ground shadow, overriding the application's `castGroundShadow` setting in both directions. Omit to inherit. Needs a GPU backend and a {@link Camera3d}. * @param {boolean} [settings.fog] - set `false` to exempt this sprite from the camera's distance fog ({@link Camera3d#setFog}); omit to fog whenever the camera does. A sun or a moon wants this — everything else at that distance dissolves into the haze, and so would it. * @param {boolean} [settings.transparent] - draw in the transparent pass (blended, back-to-front, no depth write) instead of the opaque one. Omit and the sprite goes transparent whenever its draw alpha is fractional; `true` for a soft-alpha sprite such as an additive glow; `false` to stay opaque however faded. * @param {number} [settings.alphaCutoff=0.5] - alpha cutout threshold (see {@link Mesh}). The mesh pass is opaque (no alpha blending), so this defaults to `0.5` to discard a sprite's transparent background (clean cutout silhouette, correct depth, no sorting). Set `0` for a fully-opaque quad, or tune the threshold. */ constructor(x: number, y: number, settings: { image?: string | HTMLImageElement | HTMLCanvasElement | Texture2d | undefined; width?: number | undefined; height?: number | undefined; framewidth?: number | undefined; frameheight?: number | undefined; region?: string | undefined; anims?: object[] | undefined; z?: number | undefined; billboard?: string | boolean | undefined; anchorPoint?: string | Vector2d | { x: number; y: number; }; flipX?: boolean | undefined; flipY?: boolean | undefined; lit?: boolean | undefined; emissive?: number[] | Float32Array | undefined; shadowGroundY?: number | undefined; shadowOpacity?: number | undefined; castGroundShadow?: boolean | undefined; fog?: boolean | undefined; transparent?: boolean | undefined; alphaCutoff?: number | undefined; }); /** * a callback fired when the current animation completes a cycle. * @type {Function} */ onended: Function; /** * Billboard mode — keeps the quad facing the active {@link Camera3d}: * - `false` (default) — fixed orientation (a flat quad in the XY plane; * decals, posters, ground markers). * - `true` / `"cylindrical"` — faces the camera but stays upright * (rotates only around the world up axis). The 2.5D default — trees, * characters, items. * - `"spherical"` — faces the camera on all axes (particles, glints). * * **Only applies under a `Camera3d`**; ignored on the 2D path. * * Note: while billboarding, orientation comes from the camera, so the * renderable's `currentTransform` (`rotate()` / `scale()` / parent-container * transforms) and `meshScale` are **not** applied — only `pos` / `depth`, * `flipX` / `flipY`, and the quad's authored size. With billboarding `false` * the standard {@link Mesh} world transform applies as usual. * @type {boolean|string} * @default false */ billboard: boolean | string; /** * defined animations, keyed by id (see {@link Sprite3d#addAnimation}). * @type {object} */ get anim(): object; /** * current frame information (name / index / texture offset & size / trim). * @type {object} */ get current(): object; set dt(value: number); /** * elapsed time within the current animation frame, in milliseconds. * @type {number} */ get dt(): number; set animationspeed(value: number); /** * animation cycling speed (delay between frames in ms). * @type {number} * @default 100 */ get animationspeed(): number; set animationpause(value: boolean); /** * pause the frame animation, freezing the current frame. * @type {boolean} * @default false */ get animationpause(): boolean; /** * Add an animation, identical to {@link Sprite#addAnimation}. * @param {string} name - animation id * @param {number[]|string[]|object[]} index - frame indices / names (see {@link Sprite#addAnimation}) * @param {number} [animationspeed] - cycling speed in ms * @returns {number} number of frames added */ addAnimation(name: string, index: number[] | string[] | object[], animationspeed?: number): number; /** * Select the active animation, identical to {@link Sprite#setCurrentAnimation}. * @param {string} name - animation id * @param {string|Function|object} [resetAnim] - loop / chain / completion behavior * @param {boolean} [preserve_dt=false] * @returns {Sprite3d} Reference to this object for method chaining */ setCurrentAnimation(name: string, resetAnim?: string | Function | object, preserve_dt?: boolean): Sprite3d; /** * Reverse the given (or current) animation in place (see {@link Sprite#reverseAnimation}). * @param {string} [name] - animation id * @returns {Sprite3d} Reference to this object for method chaining */ reverseAnimation(name?: string): Sprite3d; /** * Mirror the sprite horizontally (e.g. flip a character to face the other * way). Unlike the 2D {@link Sprite}, the flip mirrors the quad's local * geometry so it works for every billboard mode and for rotated/trimmed atlas * regions alike. Takes effect immediately on the current frame. * @param {boolean} [flip=true] * @returns {Sprite3d} Reference to this object for method chaining */ flipX(flip?: boolean): Sprite3d; /** * Mirror the sprite vertically. See {@link Sprite3d#flipX}. * @param {boolean} [flip=true] * @returns {Sprite3d} Reference to this object for method chaining */ flipY(flip?: boolean): Sprite3d; /** * @returns {boolean} true if the sprite is mirrored horizontally. */ isFlippedX(): boolean; /** * @returns {boolean} true if the sprite is mirrored vertically. */ isFlippedY(): boolean; /** * Play (and optionally switch to) an animation, identical to {@link Sprite#play}. * @param {string} [name] - animation id to play; omit to resume * @param {string|Function|object} [options] - loop / chain / completion behavior * @returns {Sprite3d} Reference to this object for method chaining */ play(name?: string, options?: string | Function | object): Sprite3d; /** * Pause the current animation, freezing the current frame (see {@link Sprite#pause}). * @returns {Sprite3d} Reference to this object for method chaining */ pause(): Sprite3d; /** * Stop and reset the current animation to its first frame (see {@link Sprite#stop}). * @returns {Sprite3d} Reference to this object for method chaining */ stop(): Sprite3d; /** * Force the current animation frame index (see {@link Sprite#setAnimationFrame}). * @param {number} [index=0] - animation frame index * @returns {Sprite3d} Reference to this object for method chaining */ setAnimationFrame(index?: number): Sprite3d; /** * Apply a texture region directly (see {@link Sprite#setRegion}). * @param {object} region - typically from `texture.getRegion(name)` * @returns {Sprite3d} Reference to this object for method chaining */ setRegion(region: object): Sprite3d; /** * @param {string} name - animation id * @returns {boolean} true if `name` is the current animation (see {@link Sprite#isCurrentAnimation}). */ isCurrentAnimation(name: string): boolean; /** * @returns {string[]} the names of every defined animation (see {@link Sprite#getAnimationNames}). */ getAnimationNames(): string[]; /** * @returns {number} the current animation frame index (see {@link Sprite#getCurrentAnimationFrame}). */ getCurrentAnimationFrame(): number; } import Mesh from "./mesh.js"; import FrameAnimation from "./frameAnimation.js"; import Camera3d from "../camera/camera3d.ts"; import Texture2d from "../video/texture/texture2d.ts"; //# sourceMappingURL=sprite3d.d.ts.map