melonJS
    Preparing search index...

    Class UIBaseElement

    A clickable, draggable container: the base every UI widget builds on (UITextButton, UICheckbox, UISlider, UIPanel, UISpriteElement). Extend it to make a widget of your own; it can hold other renderables as children.

    It uses screen coordinates (floating is true), so it stays put when the camera moves. Children added to it should keep floating at false.

    Override these in a subclass:

    Elements under the pointer are asked topmost first, and the event carries on to the ones below until a handler returns false. onClick and onRelease return false by default, so a press on a UI element stops there: a button over the game does not also click the world behind it. Return true from them to let the press through as well. Hover is not stopped by default: return false from onOver for that.

    Set UIBaseElement#enabled to false: it stops answering the pointer, the keys and the pad, and a press in progress is called off.

    Set UIBaseElement#isDraggable: the element then follows the pointer while held. onClick is the pick-up, UIBaseElement#onMove runs on each move, and onRelease is the drop. Inside a scrolling UIPanel, a drag that starts on a widget scrolls the panel instead; set UIBaseElement#keepsDrag on a widget that is dragged itself.

    UIBaseElement#hoverScale and UIBaseElement#pressScale scale the drawing under the pointer and while held, easing there and back. The hit area and the layout do not change.

    For a game played without a mouse or a touch screen. Nothing listens until a widget takes the focus with UIBaseElement#focus; until then the arrow keys and the pad are left to the game. With a widget focused:

    • the arrow keys or the D-pad move the focus to the nearest UIBaseElement#focusable widget that way, measured edge to edge;
    • Enter, Space or the pad's A button press the focused widget, as a click does;
    • a ring in UIBaseElement.focusRingColor shows the focus while the keyboard or a pad is used, and hides when the mouse moves;
    • a focused widget inside a scrolling UIPanel is scrolled into view;
    • UIBaseElement#blur, or removing the widget, gives the keys and the pad back to the game.

    The built-in widgets are focusable. A widget of your own sets focusable and can override UIBaseElement#onNavigate to use the arrows itself.

    // a widget of your own: draws itself, bounces, and acts on release
    import { UIBaseElement } from "melonjs";

    class Card extends UIBaseElement {
    constructor(x, y) {
    super(x, y, 120, 160);
    this.focusable = true; // reachable with the arrow keys and the pad
    this.hoverScale = 1.05;
    this.pressScale = 0.95;
    }
    draw(renderer, viewport) {
    renderer.setColor(this.hover ? "#ffffff" : "#cccccc");
    renderer.fillRect(this.pos.x, this.pos.y, this.width, this.height);
    super.draw(renderer, viewport); // draws the children
    }
    onRelease() {
    console.log("card picked");
    return false; // stop the event here (the default)
    }
    }

    app.world.addChild(new Card(50, 50));
    // a token dragged around and snapped to a 32 pixel grid when dropped
    import { UIBaseElement, Sprite } from "melonjs";

    class Token extends UIBaseElement {
    constructor(x, y) {
    super(x, y, 64, 64);
    this.isDraggable = true;
    // a sprite is centred on its position by default
    this.addChild(new Sprite(32, 32, { image: "token" }));
    }
    onMove() {
    // runs on each move while dragged: this.pos follows the pointer
    }
    onRelease() {
    this.pos.x = Math.round(this.pos.x / 32) * 32;
    this.pos.y = Math.round(this.pos.y / 32) * 32;
    return false;
    }
    }
    // a menu played with the keyboard or a pad: start on the first button
    import { UITextButton, state } from "melonjs";

    const play = new UITextButton(100, 200, {
    text: "Play",
    onClick: () => state.change(state.PLAY),
    });
    const quit = new UITextButton(100, 260, {
    text: "Quit",
    onClick: () => state.change(state.MENU),
    });
    app.world.addChild(play);
    app.world.addChild(quit);
    // the arrows / D-pad now move between them, Enter / Space / A press;
    // the mouse still works as before
    play.focus();
    // a panel that is opaque to hover too, and comes to the front when picked
    // (UIPanel does this with its `blocking` setting)
    import { UIBaseElement, input } from "melonjs";

    class Dialog extends UIBaseElement {
    onClick() {
    this.ancestor.moveToTop(this);
    return false;
    }
    // the frame the pointer crosses in
    onOver() {
    return false;
    }
    // and every frame after that, when the pointer is already inside and
    // `onOver` no longer fires
    onActivateEvent() {
    super.onActivateEvent();
    input.registerPointerEvent("pointermove", this, () => false);
    }
    onDeactivateEvent() {
    input.releasePointerEvent("pointermove", this);
    super.onDeactivateEvent();
    }
    }

    Hierarchy (View Summary)

    Index
    • Parameters

      • x: number

        the x position of the element, in screen pixels

      • y: number

        the y position of the element, in screen pixels

      • Optionalw: number

        the width of the element, in pixels

      • Optionalh: number

        the height of the element, in pixels

      Returns UIBaseElement

    alpha: number

    Define the renderable opacity
    Set to zero if you do not wish an object to be drawn

    Opacity cascades: it is multiplied with the alpha already on the renderer, so fading a Container fades everything inside it, and a child at alpha 0.5 inside a parent at 0.5 draws at 0.25. Each renderable keeps its own value — the composition happens at draw time, and is undone when the renderable is done.

    That is different from Container#setChildsProperty, which assigns a value onto the children themselves. Use alpha to fade a subtree, and setChildsProperty to change what the children are.

    • Renderable#setOpacity
    • Renderable#getOpacity
    • Container#setChildsProperty
    1.0
    
    // fades the whole rig, parts included
    myModel.alpha = 0.3;
    alwaysUpdate: boolean

    Whether the renderable object will always update, even when outside of the viewport

    false
    
    ancestor: Container | Entity

    a reference to the parent object that contains this renderable

    undefined
    
    anchorPoint: ObservablePoint

    The anchor point is used for attachment behavior, and/or when applying transformations.
    The coordinate system places the origin at the top left corner of the frame (0, 0) and (1, 1) means the bottom-right corner

    a Renderable's anchor point defaults to (0.5,0.5), which corresponds to the center position.

    Note: Object created through Tiled will have their anchorPoint set to (0, 0) to match Tiled Level editor implementation. To specify a value through Tiled, use a json expression like json:{"x":0.5,"y":0.5}, or (since 19.9) a plain string preset such as bottom.
    At construction time, settings.anchorPoint also accepts the named presets "center", "top", "bottom", "left", "right", "top-left", "top-right", "bottom-left", "bottom-right" on every renderable that consumes it (Sprite, Entity, Collectable, ImageLayer, Text, BitmapText, Sprite3d and subclasses).
    Note: a body's collision shapes are measured from the same frame this places the renderable in, so a shape of Rect(0, 0, width, height) covers the renderable whatever the anchor is (since 20.7; before that shapes were measured from pos regardless, and a non-corner anchor collided where it was not drawn). A shape's own pos still offsets it inside that frame. A renderable that has cleared Renderable#applyAnchorTransform takes no offset at all, on the drawing or on its shapes. Note also that the adapters read the anchor when the body is created, so changing it afterwards moves the drawing but not an already-built body.

    <0.5,0.5>
    
    applyAnchorTransform: boolean

    Whether Renderable#preDraw applies the Renderable#anchorPoint offset to the renderer transform.

    When true (the default), the renderable is shifted by -anchorPoint × (width, height) so its anchor — not its top-left corner — aligns with its position. Correct for sprites and other 2D renderables.

    Set to false for a renderable that emits its own final world coordinates and takes its origin from geometry rather than a bounds box — e.g. a Mesh on the Camera3d world-space path (a 3D mesh is positioned by its transform and has no anchor). The WebGL mesh batcher reuses this same renderer transform as its view matrix, so applying the normalized anchor there would shift every mesh by half its OWN bounds box; because scene meshes size that box per node, props and the platforms they rest on would drift apart and overlap.

    true
    

    Mesh#preDraw

    autoDepth: boolean

    Specify if the children z index should automatically be managed by the parent container

    true
    
    autoSort: boolean

    Whether the container keeps its children sorted by itself.

    • When a child is added, the container sorts (on the next tick).
    • On a "x" or "y" sort, it also keeps its children in order every frame, as they move: at the end of each update, after physics and the children's own updates, it checks the order and re-sorts when anything is out of place. A character walking around a y-sorted scene passes in front of and behind things with no sort() call. A frame where nothing moved costs one pass over the children, and nothing is redrawn because of it.
    • On a "z" sort, changing a child's depth after adding it does NOT re-sort: call Container#sort, or use Container#moveToTop and the other move methods, which reorder the children themselves. "depth" is re-sorted every frame by its Camera3d.

    Turn it off to keep the children in the order you put them.

    true
    
    autoTransform: boolean

    When enabled, an object container will automatically apply any defined transformation before calling the child draw method.

    true
    
    // enable "automatic" transformation when the object is activated
    onActivateEvent: function () {
    // reset the transformation matrix
    this.currentTransform.identity();
    // ensure the anchor point is the renderable center
    this.anchorPoint.set(0.5, 0.5);
    // enable auto transform
    this.autoTransform = true;
    ....
    }
    backgroundColor: Color

    define a background color for this container

    (0, 0, 0, 0.0)
    
    // add a red background color to this container
    this.backgroundColor.setColor(255, 0, 0);
    blendMode: string

    the blend mode to be applied to this renderable — any of the modes listed on CanvasRenderer#setBlendMode, honoured identically by every renderer

    "normal"
    
    • CanvasRenderer#setBlendMode
    • WebGLRenderer#setBlendMode

    the renderable physics body — the handle returned by the active PhysicsAdapter's addBody (or constructed imperatively via new Body(...)). Typed as the portable PhysicsBody interface; cast to the adapter-specific concrete type (MatterAdapter.Body, BuiltinAdapter.Body, or the legacy Body class) to reach native fields.

    // define a new Player Class
    class PlayerEntity extends me.Sprite {
    // constructor
    constructor(x, y, settings) {
    // call the parent constructor
    super(x, y , settings);

    // define a basic walking animation
    this.addAnimation("walk", [...]);
    // define a standing animation (using the first frame)
    this.addAnimation("stand", [...]);
    // set the standing animation as default
    this.setCurrentAnimation("stand");

    // add a physic body
    this.body = new me.Body(this);
    // add a default collision shape
    this.body.addShape(new me.Rect(0, 0, this.width, this.height));
    // configure max speed, friction, and initial force to be applied
    this.body.setMaxVelocity(3, 15);
    this.body.setFriction(0.4, 0);
    this.body.force.set(3, 0);
    this.isKinematic = false;

    // set the display to follow our position on both axis
    app.viewport.follow(this, app.viewport.AXIS.BOTH);
    }

    ...

    }
    bodyDef: object | undefined

    Declarative body definition consumed by the active PhysicsAdapter when this renderable is added to a container. Adapter API only — leave undefined if you build a body imperatively via this.body = new Body(...).

    When set, the parent container forwards it to world.adapter.addBody(this, this.bodyDef), which constructs the underlying physics body (matter, builtin SAT, …) and assigns the engine-portable wrapper to this.body. This is the engine-portable path: the same bodyDef produces an equivalent body under any adapter.

    Typical fields: type ("static"/"dynamic"/"kinematic"), shapes, collisionType, collisionMask, restitution, frictionAir, density, gravityScale, isSensor, maxVelocity, fixedRotation. See BodyDefinitionInit.

    shapes is normally a list of collision shapes, but it can also name a collision shape file preloaded as JSON, paired with id naming the body to read out of it. The file is resolved before any adapter sees the definition, so the same one works unchanged on every backend.

    undefined
    
    // a shape authored in code
    this.bodyDef = {
    type: "dynamic",
    shapes: [new me.Rect(0, 0, this.width, this.height)],
    };
    // shapes drawn in a physics-shape editor, preloaded as JSON with
    // { name: "shapes", type: "json", src: "data/physics/shapes.json" }
    this.bodyDef = { type: "dynamic", shapes: "shapes", id: "hotdog" };

    // the density, friction and bounce the shapes were authored with
    // come with them, unless the definition states otherwise (each is
    // honoured by whichever backends support it):
    this.bodyDef = {
    type: "dynamic",
    shapes: "shapes",
    id: "hotdog",
    restitution: 0.9, // wins over whatever the file carries
    };
    clipping: boolean

    Specify if the container draw operation should clip its children to its own bounds

    false
    
    collisionMask?: number
    collisionType?: number

    Optional per-shape collision settings, honoured by Body#addShape and defaulted there. Declared rather than initialized: the body writes them when the shape joins it, so a class field here would emit an undefined own property on every shape ever built. See addShape for the table of defaults and what each one does.

    Body#addShape

    currentTransform: Matrix3d

    the renderable transformation matrix (4x4). For standard 2D use, only the 2D components are used (rotate around Z, scale X/Y, translate X/Y). For 3D use (e.g. Mesh), the full 4x4 matrix supports rotation around any axis, 3D translation, and perspective projection. Use the rotate(), scale(), and translate() methods rather than modifying this directly.

    edges: Vector2d[]

    The edges here are the direction of the nth edge of the polygon, relative to the nth point. If you want to draw a given edge from the edge value, you must first translate to the position of the starting point.

    enableChildBoundsUpdate: boolean

    Re-measure this container's bounds from its children, so they follow the children as they move: on every update (after the children have been updated), whenever a child is added or removed, and, while the container is culled, before each visibility check, so a group whose members come back into view is drawn again. Expensive — every update walks the whole child list — and off by default, because a parent almost never needs it.

    Enable it for a group whose extent genuinely IS its members' union and moves as they do: a flock of birds, a squad of enemies. A container whose size is known (or fixed) should be given that size with Renderable#resize instead, which costs nothing per frame — that is what GLTFModel does, from the glTF scene's own bounding box.

    Note that a container with neither — no dimensions of its own and this left off — reports an EMPTY bounds (min +Infinity, max -Infinity), since Container#updateBounds then has nothing to measure. Anything reading it is wrong about where the container is, and the physics broadphase, which files every item by getBounds(), cannot place it at all.

    false
    

    Renderable#getBounds

    floating: boolean = true

    UI elements use screen coordinates by default, so they stay put when the camera moves. Children added to a UIBaseElement should keep their own floating at false.

    Renderable.floating

    true
    
    focusable: boolean = false

    Whether this element can take the keyboard and gamepad focus: see UIBaseElement#focus. The built-in buttons, checkboxes and sliders set it; set it on a widget of your own to make it reachable. A disabled or hidden element is skipped.

    false
    
    grabOffset: Vector2d | undefined

    While dragged: where the element was grabbed, relative to its position. undefined otherwise.

    GUID: string

    (G)ame (U)nique (Id)entifier"
    a GUID will be allocated for any renderable object added
    to an object container (including the app.world container)

    holdThreshold: number

    How long a press must be held before UIBaseElement#onHold runs, in milliseconds. Needs isHoldable.

    250
    
    hover: boolean

    true while the pointer is over the element. A tap on a touch screen does not set it. Cleared when the element is removed, so one added back later is not drawn lit until the pointer comes over it again.

    false
    
    hoverScale: number = 1

    The scale the widget is drawn at under the pointer, or while it shows the focus ring: a little bounce, such as 1.05. 1 turns it off.

    Only the drawing scales, about the widget's centre. Its hit area and its place in a layout stay the same, so the widgets around it do not move. The scale eases there and back by itself (about 0.2 s). A disabled widget does not grow.

    1
    
    button.hoverScale = 1.05;
    button.pressScale = 0.92;
    indices: number[]

    a list of indices for all vertices composing this polygon, filled in by Polygon#getIndices and invalidated by Polygon#recalc.

    A subclass may repurpose this name for geometry of its own: a Mesh holds a GPU index buffer here, a typed array rather than a plain one. recalc therefore only clears the slot when it owns it — anything else reading it should check what it got.

    isActive?: boolean

    false takes this shape out of collision without removing it

    isClickable: boolean

    Whether the pointer can press the element. The low-level flag under UIBaseElement#enabled: prefer enabled, which also calls off a press in progress, blocks the keys and the pad, and draws a built-in widget disabled.

    true
    
    isDirty: boolean

    when true the renderable will be redrawn during the next update cycle

    true
    
    isDraggable: boolean

    Whether the element follows the pointer while held. onClick runs on the pick-up, UIBaseElement#onMove on each move and onRelease on the drop.

    false
    
    isHoldable: boolean

    Whether a press held for holdThreshold ms calls UIBaseElement#onHold.

    false
    
    isKinematic: boolean

    If true then physic collision and input events will not impact this renderable

    true
    
    isPersistent: boolean

    make the renderable object persistent over level changes

    false
    
    isTrigger?: boolean

    true reports contacts but skips the position correction

    keepsDrag: boolean = false

    Whether a drag that starts on this element belongs to it.

    When false, a drag that starts on the element inside a scrolling UIPanel scrolls the panel and calls off the press. Set it on a widget that handles its own drags, such as a knob or a colour picker, as UISlider does. An isDraggable element keeps its drags anyway.

    false
    
    // a colour wheel that reads drags itself, inside a scrolling panel
    class ColourWheel extends UIBaseElement {
    constructor(x, y) {
    super(x, y, 128, 128);
    this.keepsDrag = true;
    }
    }

    A mask limits rendering elements to the shape and position of the given mask object. So, if the renderable is larger than the mask, only the intersecting part of the renderable will be visible.

    undefined
    
    // apply a mask in the shape of a Star
    myNPCSprite.mask = new me.Polygon(myNPCSprite.width / 2, 0, [
    // draw a star
    {x: 0, y: 0},
    {x: 14, y: 30},
    {x: 47, y: 35},
    {x: 23, y: 57},
    {x: 44, y: 90},
    {x: 0, y: 62},
    {x: -44, y: 90},
    {x: -23, y: 57},
    {x: -47, y: 35},
    {x: -14, y: 30}
    ]);
    name: string

    The name of the renderable

    ""
    
    onCanvasResize: (() => void) | undefined
    onChildChange: () => void

    a callback to be extended, triggered after a child has been added or removed

    onVisibilityChange: Function

    an event handler that is called when the renderable leave or enter a camera viewport

    undefined
    
    this.onVisibilityChange = function(inViewport) {
    if (inViewport === true) {
    console.log("object has entered the in a camera viewport!");
    }
    };
    points: Vector2d[]

    Array of points defining the Polygon
    Note: If you manually change points, you must call recalcafterwards so that the changes get applied correctly.

    origin point of the Polygon

    postEffectNeedsCapture: boolean

    whether a single post effect on this renderable needs an offscreen capture instead of the renderer's shader-swap fast path.

    One effect is normally applied by drawing the renderable with the effect's own program rather than capturing and post-processing it, which costs no render target. That is only equivalent when everything the renderable draws is a textured quad. fillRect and the shape dispatch go through a batcher that never looks at that shader, so a single effect on a renderable that draws with primitives silently does nothing. Set this and the capture is used instead, at the cost of a render target while the effect is active.

    Two or more effects always capture, so this only ever changes the single-effect case.

    false
    
    class Bar extends Renderable {
    constructor(x, y, w, h) {
    super(x, y, w, h);
    // this draws itself with primitives, not as a sprite
    this.postEffectNeedsCapture = true;
    }
    draw(renderer) {
    renderer.fillRect(this.pos.x, this.pos.y, this.width, this.height);
    }
    }
    postEffects: (ShaderEffect | GLShader)[]

    the list of post-processing shader effects applied to this renderable (GPU backends — WebGL and WebGPU). Effects are applied in order. Use addPostEffect, getPostEffect, and removePostEffect to manage effects, or assign directly. On the Canvas renderer effects stay inert (the scene keeps rendering un-effected).

    []
    
    // add effects via helper methods
    mySprite.addPostEffect(new DesaturateEffect(renderer));
    mySprite.addPostEffect(new VignetteEffect(renderer));
    // assign directly
    mySprite.postEffects = [new SepiaEffect(renderer), new VignetteEffect(renderer)];
    pressScale: number = 1

    The scale the widget is drawn at while held down, such as 0.92. 1 turns it off. Drawing only, as UIBaseElement#hoverScale.

    1
    
    released: boolean

    false while the element is held down (by the pointer, or by Enter / A with the focus), true otherwise. Removing a held element calls the press off (see UIBaseElement#cancelPress), so it is true again once out of the scene.

    true
    
    root: boolean

    whether the container is the root of the scene

    false
    
    type: string = "Rectangle"

    The shape type (used internally).

    updateWhenPaused: boolean

    Whether to update this object when the game is paused.

    On a container it covers everything under it: a child steps through a pause on its own opt-in or on one from any container above it, so a pause menu flags itself once and its nested labels follow.

    false
    
    visibilityLayer: number

    The layers this renderable belongs to, as bits (1, 2, 4, 8... up to 32 of them). A camera draws it only if it shares a bit with the camera's Camera2d#cullMask: by default every renderable is on layer 1 and every camera draws every layer, so it shows in all of them. Put something on a layer a camera leaves out to keep it off that camera only, such as the particles off a minimap. A container left out is left out with everything inside it (the world included), and a renderable on no layer, 0, is drawn by no camera.

    It decides what a camera draws, and nothing else: the renderable still updates, collides and receives pointer events. A Light2d a camera leaves out, itself or a container it is in, neither glows, nor cuts its hole in the darkness, nor lights normal-mapped sprites in that camera (a Light3d lights the meshes of every camera). A floating renderable must also pass the camera's floating rule (see Renderable#visibleInAllCameras). On an object of a Tiled map it can be set as an int custom property of the object.

    1
    

    Camera2d#cullMask

    // particles on their own layer, and a minimap that leaves it out
    const PARTICLES = 2;
    emitter.visibilityLayer = PARTICLES;
    minimap.cullMask = ~PARTICLES;
    visibleInAllCameras: boolean

    If true, this floating renderable will be rendered by all cameras (e.g. background image layers). If false (default), floating elements are only rendered by the default camera (e.g. UI/HUD elements), zoomed or not. Only applies to floating renderables in multi-camera setups.

    false
    
    focusRingColor: string = "#ffcc33"

    The colour of the ring drawn around the element with the focus, for every element. Any CSS colour.

    "#ffcc33"
    
    UIBaseElement.focusRingColor = "#00e0ff";
    
    • get enabled(): boolean

      Whether the widget answers input: the switch to turn a widget off.

      Turning it off clears isClickable, calls off a press in progress (see UIBaseElement#cancelPress), and skips it in keyboard and gamepad navigation. The built-in widgets draw themselves disabled: their disabled skin region, or at half opacity. A widget of your own reads enabled in its draw.

      isClickable is the low-level flag underneath; setting it alone does not change enabled or the look.

      Returns boolean

      true
      
      // greyed out until a save exists
      continueButton.enabled = false;
      // ... later
      continueButton.enabled = true;
    • set enabled(value: boolean): void

      Parameters

      • value: boolean

      Returns void

    • get isFloating(): boolean

      Whether the renderable object is floating (i.e. used screen coordinates), or contained in a floating parent container

      Returns boolean

      Renderable#floating

    • get sortOffset(): number

      An offset, in pixels, added to this renderable's position when its parent container sorts its children on "y" (or "x"), and used for nothing else. It never moves the renderable and never changes where or how it is drawn: it only decides whether it is drawn before or after its siblings, and so which one is on top, and which one a pointer hits.

      A container sorted on "y" draws its children from the smallest pos.y to the largest, the last one on top. A child with a sortOffset is lined up as if it stood that many pixels lower (positive) or higher (negative), while staying where it is. Use it when pos is not the point a renderable should be sorted by: the top of a Tiled tile object's image, the top left corner of a container, or the top of a particle emitter's spawn area.

      • A container that keeps itself sorted (autoSort, the default) picks a change up at its next update; with autoSort off, call its sort().
      • Containers sorted on "z" or "depth" ignore it, and on "x" and "y" a different pos.z still decides first.
      • Two children that come out equal keep their order, which draws the one added last BEHIND the other: an offset of 1 settles such a tie on purpose.
      • A renderable taken from a pool starts again at 0.

      Returns number

      0
      

      if set to anything but a finite number

      // a torch hung on a wall at the wall's own position: line it up
      // 1 px lower, so that it is drawn over the wall
      torch.sortOffset = 1;
      // a particle emitter's pos is the top of its spawn area. Dust rising at
      // the foot of a door sits far below the door's pos, and would be drawn
      // over everything between the two: line it up with the door instead
      dust.sortOffset = door.pos.y - dust.pos.y;
    • set sortOffset(value: number): void

      Parameters

      • value: number

      Returns void

    • get sortOn(): "x" | "y" | "z" | "depth"

      The property of the child object that should be used to sort on this container.

      • "x" / "y" — 2D scroll-order, descending on both axes (higher pos.z first; tied z, higher pos.x or pos.y first). Suited to side-scrollers and top-down games. Each child is compared at pos.x / pos.y plus its Renderable#sortOffset, which changes the order and never the position. With Container#autoSort on (the default), the children are kept in that order every frame as they move.
      • "z" — descending pos.z (higher z draws on top). Default for Camera2d — matches the painter's-algorithm 2D layering model where pos.z is "layer index".
      • "depth" — Camera3d-only. Ascending squared distance from the active camera (closest first in the array → far drawn first → close drawn on top under Container.draw's reverse-iteration walk). This is the only correct sort for alpha-blended sprites under perspective projection, where neither pos.z nor pos.x/y layering produces correct occlusion (the closer/farther relationship flips as the camera orbits). Set automatically when an Application or Stage is constructed with cameraClass: Camera3d. Has no useful effect under Camera2d (ortho projection doesn't need camera-distance ordering) and pays an O(N log N) sort per frame, so don't enable it manually in 2D-only games.

      Returns "x" | "y" | "z" | "depth"

      "z"
      
    • set sortOn(value: "x" | "y" | "z" | "depth"): void

      Parameters

      • value: "x" | "y" | "z" | "depth"

      Returns void

    • get tint(): Color

      define a tint for this renderable. a (255, 255, 255) r, g, b value will remove the tint effect.

      Returns Color

      (255, 255, 255)
      
      // add a red tint to this renderable
      this.tint.setColor(255, 128, 128);
      // remove the tint
      this.tint.setColor(255, 255, 255);
    • set tint(value: string | Color): void

      Takes a Color to copy, or a CSS colour string.

      It COPIES rather than holds, so a caller that goes on mutating what it passed does not steer this renderable's tint by accident. What the getter hands back is always a Color, whichever form went in.

      Parameters

      • value: string | Color

        the colour to tint with

      Returns void

    • Add a child to the container
      if auto-sort is disabled, the object will be appended at the bottom of the list. Adding a child to the container will automatically remove it from its other container. Meaning a child can only have one parent. This is important if you add a renderable to a container then add it to the World container it will move it out of the original container. Then when the World container reset() method is called the renderable will not be in any container.
      if the given child implements an onActivateEvent method, that method will be called once the child is added to this container, when this container is in the world (or as soon as it is added to it). Each onActivateEvent is matched by exactly one onDeactivateEvent when the child leaves the world again.
      Once this container is in the world, the physics body of the child (its bodyDef, or a pre-built Body) is registered with the world's physics adapter, and so is the body of every renderable below it if it is a container, at any depth. They are taken out again when the child leaves the world, so moving a whole group from one container to another keeps its bodies simulated, once each.

      Parameters

      Returns Renderable

      the added child

    • Give up the focus, if this element has it. With nothing focused, the arrow keys and the pad go back to the game. Removing the element from the scene does the same.

      Returns void

      // leaving the menu for the game: the arrows move the player again
      UIBaseElement.focusOwner?.blur();
    • Call off a press in progress, without calling onRelease: UIBaseElement#onCancel runs instead.

      The element goes back to its released look, and the pointer-up that follows does nothing. A scrolling UIPanel calls this when a drag that started on the element turns out to be a scroll, so a button dragged to scroll its list is not clicked. Setting enabled to false, losing the focus or the window losing focus while Enter or A is held, and removing the element while it is held call it too.

      Returns void

    • Whether this container shows its children at a point.

      Always true unless Container#clipping is on, in which case only its own rectangle is shown. The pointer asks every container above a region before letting it answer, so a child cropped out of view cannot be clicked where it is not drawn.

      Parameters

      • x: number

        the point, in the same coordinates as the bounds of this container (screen pixels for a floating one)

      • y: number

        the point

      Returns boolean

      false where the children are clipped away

    • Returns true if the polygon contains the given point.
      (Note: it is highly recommended to first do a hit test on the corresponding
      bounding rect, as the function can be highly consuming with complex shapes)

      Parameters

      • x: number

        x coordinate or a vector point to check

      • y: number

        y coordinate

      Returns boolean

      True if the polygon contain the point, otherwise false

      if (polygon.contains(10, 10)) {
      // do something
      }
      // or
      if (polygon.contains(myVector2d)) {
      // do something
      }
    • Returns true if the polygon contains the given point.
      (Note: it is highly recommended to first do a hit test on the corresponding
      bounding rect, as the function can be highly consuming with complex shapes)

      Parameters

      • vector: XYPoint

      Returns boolean

      True if the polygon contain the point, otherwise false

      if (polygon.contains(10, 10)) {
      // do something
      }
      // or
      if (polygon.contains(myVector2d)) {
      // do something
      }
    • Take the keyboard and gamepad focus, for a game played without a mouse or a touch screen. Call it once the element is in the scene.

      Nothing has the focus until a game gives it to an element, and until then the arrow keys and the pad are left to the game. From then on: the arrows or the D-pad move the focus to the nearest focusable element that way; Enter, Space or the pad's A button press the focused one as a click does (a slider steps on left and right instead). The focus ring shows, and hides again while the mouse is used. A focused element in a scrolling panel is scrolled into view.

      Does nothing on an element that is not focusable.

      Returns void

      // a menu played with the keyboard or a pad: start on Play
      app.world.addChild(playButton);
      app.world.addChild(optionsButton);
      playButton.focus();
      // a pause menu in a panel: focus its first button when it opens
      panel.addChild(resumeButton);
      panel.addChild(quitButton);
      app.world.addChild(panel);
      resumeButton.focus();
    • Called when Enter, Space or A is pressed with the focus here: the widget goes down, as under the pointer, and onClick runs with no event. Override it only to change what accept does.

      Returns boolean

      whether it went down: not when disabled, or already held

    • The forEach() method executes a provided function once per child element.
      the callback function is invoked with three arguments:

      • The current element being processed in the array
      • The index of element in the array.
      • The array forEach() was called upon.

      Parameters

      • callback: Function

        function to execute on each element

      • OptionalthisArg: object

        value to use as this(i.e reference Object) when executing callback.

      Returns void

      // iterate through all children of this container
      container.forEach((child) => {
      // do something with the child
      child.doSomething();
      });
      container.forEach((child, index) => { ... });
      container.forEach((child, index, array) => { ... });
      container.forEach((child, index, array) => { ... }, thisArg);
    • Where this renderable IS in the game world — its own pos plus every ancestor's, as a Vector3d so the z component is summed across the chain too (important for Camera3d's frustum culling, which previously read obj.depth — local pos.z — and mis-culled children nested under a container with its own non-zero depth).

      Reach for this for anything positional: culling, distance checks, hit tests, placing one renderable relative to another. It is cheap, and it is what the engine's own culling uses.

      Reach for Renderable#getWorldTransform instead when a position is not enough — when rotation, scale or flip along the ancestor chain matters, or when you need to map an arbitrary point rather than just the origin. This method sums translations only, so under a rotated or scaled ancestor it reports where the renderable's pivot is and nothing about how its content is oriented.

      Note the two also frame the question differently. This one is "where am I"; getWorldTransform() is "what space is my content drawn in". For a Container those coincide, because a container offsets its children by its own position. For a leaf they differ by exactly that position, which a leaf applies inside its own draw().

      The returned vector is pooled and reused — copy it if you need to hold onto the value across another call.

      Returns Vector3d

      this renderable's absolute position

      Renderable#getWorldTransform

    • returns the list of children with the specified name
      as defined in Tiled (Name field of the Object Properties)
      note : avoid calling this function every frame since it parses the whole object list each time

      Parameters

      • name: string | number | boolean | RegExp

        child name

      Returns Renderable[]

      Array of children

    • return the child corresponding to the given property and value.
      note : avoid calling this function every frame since it parses the whole object tree each time

      Parameters

      • prop: string

        Property name

      • value: string | number | boolean | RegExp

        Value of the property

      • objList: any[] = []

      Returns Renderable[]

      Array of children

      // get the first child object called "mainPlayer" in a specific container :
      let ent = myContainer.getChildByProp("name", "mainPlayer");

      // or query the whole world :
      let ent = container.getChildByProp("name", "mainPlayer");

      // partial property matches are also allowed by using a RegExp.
      // the following matches "redCOIN", "bluecoin", "bagOfCoins", etc :
      let allCoins = container.getChildByProp("name", /coin/i);

      // searching for numbers or other data types :
      let depth10 = container.getChildByProp("depth", 10);
      let inViewport = container.getChildByProp("inViewport", true);
    • Get post-processing shader effects. When called with a class, returns the first effect matching the given class. When called without arguments, returns the full effects array.

      Parameters

      • OptionaleffectClass: Function

        the effect class to search for

      Returns any[] | ShaderEffect | GLShader | undefined

      the matching effect, the effects array, or undefined

      const desat = sprite.getPostEffect(DesaturateEffect);
      const allEffects = sprite.getPostEffect();
    • The space this renderable's content is drawn IN, as a matrix — the full form of Renderable#getAbsolutePosition, which sums positions up the ancestor chain and therefore cannot represent the rotation, scale or flip accumulated along the way.

      Reach for getAbsolutePosition() instead for ordinary positional work — culling, distance checks, hit tests. It is cheaper and it is what the engine culls with. Use this when a position is not enough:

      • an ancestor is rotated or scaled, so a translation cannot describe the result
      • you need to map an arbitrary point, not just the origin — a corner, a click position, one renderable's coordinates into another's space
      • you need to compose or invert the transform (inv(A) · B converts between two frames, which is how ParticleEmitter.referenceSpace measures particles against a container that is not their parent)

      The two also frame the question differently, and it shows on a leaf. getAbsolutePosition() is "where am I"; this is "what space is my content drawn in". For a Container those coincide, because a container offsets its children by its own position. For a leaf they differ by exactly that position, which a leaf applies inside its own draw(). So with no rotation, scale or flip anywhere, a container's translation column equals its getAbsolutePosition() while a leaf's equals its PARENT's.

      The walk stops at a floating ancestor, because a floating renderable draws in screen space: Container#draw resets the transform outright for those, so the chain genuinely ends there rather than continuing to the root.

      The camera needs no special handling — Camera2d folds its view transform into the root container's currentTransform, so it is picked up like any other level.

      Parameters

      • out: Matrix3d

        matrix to write into; nothing is stored on the renderable itself, so callers own the lifetime

      Returns Matrix3d

      out, for chaining

      Renderable#getAbsolutePosition

      // map a point from one renderable's space into another's
      const from = a.getWorldTransform(new Matrix3d());
      const into = b.getWorldTransform(new Matrix3d()).invert();
      const point = new Vector2d(10, 20); // in a's space
      from.apply(point); // -> world
      into.apply(point); // -> b's space
      // just need to know where something is? use the cheaper call
      const where = renderable.getAbsolutePosition();
    • Returns true if the vertices composing this polygon form a convex shape (vertices must be in clockwise order).

      Returns boolean | null

      true if the vertices are convex, false if not, null if not computable

    • Called when the element is pressed: the pointer went down on it, or Enter / Space / A with the focus here (then with no event). Override it in a subclass.

      This is the press, not a completed click: see UIBaseElement#onRelease for the end of it.

      Parameters

      • Optional_event: Pointer

        the pointer event, or undefined from the keyboard or the pad

      Returns boolean

      false, the default, to stop the event here; true to let elements below get it too

    • Legacy collision callback — fires every frame this renderable body is overlapping another body. Kept for backward compatibility with code written against pre-19.5 melonJS; semantics are unchanged from the 19.4 contract.

      NOTE — onCollision is NOT equivalent to Renderable.onCollisionActive. The two handlers exist side by side and have intentionally different contracts:

      onCollision (legacy) onCollisionActive (modern)
      Cadence for dynamic-dynamic pairs 2× per frame per side 1× per frame per side
      response.a semantics Fixed per pair (first body in detector call) Always the receiver (response.a === this)
      response.b semantics Fixed per pair Always the partner (response.b === other)
      response.normal / response.depth ✗ ✓ — normal.y < -0.7 = "push me up"
      return false to skip push-out ✓ (honored by SAT) ✗ — use bodyDef.isSensor or setSensor instead

      If you're writing new code, prefer onCollisionActive. Keep onCollision only when its every-frame, return-false, fixed-a/b semantics are what you want.

      Parameters

      • response: ResponseObject

        the SAT response object; the legacy handler receives this, not the adapter's CollisionResponse, which is why normal and depth are absent from the table above

      • other: Renderable

        the other renderable touching this one (a reference to response.a or response.b)

      Returns boolean

      true if the object should respond to the collision (its position and velocity will be corrected); the return value is only honored by the builtin SAT adapter.

      // legacy collision handler — note the receiver-side check on response.a
      onCollision(response) {
      if (response.b.body.collisionType === me.collision.types.ENEMY_OBJECT) {
      this.pos.sub(response.overlapV);
      this.hurt();
      return false; // skip the SAT push-out
      }
      return true;
      }
    • OnDestroy Notification function
      Called by engine before deleting the object. Receives whatever destroy(...args) was called with — the production path (Container.removeChildNow) passes nothing. Stage has its own onDestroyEvent, which does forward the active Application.

      Parameters

      • ..._args: any[]

        forwarded by destroy(...args); normally empty

      Returns void

    • Called for an arrow key or a D-pad direction while this element has the focus. Return true to handle it yourself (the focus stays here), as a slider does to step. Return false, the default, to move the focus to the nearest widget that way.

      Enter, Space and A do not come here: they press the widget through UIBaseElement#focusPress and UIBaseElement#focusRelease.

      Parameters

      • _action: UINavAction

        which way: "up", "down", "left" or "right"

      Returns boolean

      true when handled

      // a picker: left and right change the choice, up and down move on
      class Picker extends UIBaseElement {
      constructor(x, y, choices) {
      super(x, y, 160, 32);
      this.focusable = true;
      this.choices = choices;
      this.index = 0;
      }
      onNavigate(action) {
      if (action === "left" || action === "right") {
      const step = action === "right" ? 1 : -1;
      const n = this.choices.length;
      this.index = (this.index + step + n) % n;
      this.isDirty = true;
      return true;
      }
      return false;
      }
      }
    • Called when the pointer leaves the element. Override it in a subclass.

      Also fires when the pointer is still inside but something drawn above has stopped the move, since the pointer is then over that instead. A press in progress ends first, through onRelease.

      Unlike UIBaseElement#onOver it cannot stop the event: an element that skipped its own leave would stay lit after the pointer had gone.

      Parameters

      • Optional_event: Pointer

        the pointer event

      Returns void

    • Called when the pointer comes over the element. Override it in a subclass.

      Fires once, on the frame the pointer crosses into the element. To stay opaque to hover for as long as the pointer rests on it, also register a "pointermove" callback through input.registerPointerEvent that returns false (see the class example).

      Parameters

      • Optional_event: Pointer

        the pointer event

      Returns boolean | void

      false to stop the event here, so an element covered by this one does not also light up

    • Called when a press ends. Override it in a subclass.

      It runs when the pointer comes up, but also when the pointer leaves the element while held, or the browser cancels the press: it is the end of a press, not proof of a completed click. (For a click that only counts when completed, use a UITextButton and its onClick setting.) A press called off by UIBaseElement#cancelPress does not come here.

      Parameters

      • Optional_event: Pointer

        the pointer event, or undefined from the keyboard or the pad

      Returns boolean

      false, the default, to stop the event here; true to let elements below get it too

    • Apply the bounce, and draw the focus ring, behind the widget.

      Here and not in draw: a container translates to its own position in draw, so from preDraw on, the widget and the ring share the parent's coordinates, whatever the widget does in its own draw.

      Parameters

      • renderer: Renderer

        the renderer to draw with

      Returns void

    • Rotate this renderable by the specified angle (in radians). When called with just an angle, rotates around the Z axis (2D rotation). When called with an angle and a Vector3d axis, rotates around that axis in 3D.

      Parameters

      • angle: number

        The angle to rotate (in radians)

      • Optionalv: Vector3d

        the axis to rotate around (defaults to Z axis for 2D)

      Returns UIBaseElement

      Reference to this object for method chaining

    • scale the renderable around his anchor point. Scaling actually applies changes to the currentTransform member which is used by the renderer to scale the object when rendering. It does not scale the object itself. For example if the renderable is an image, the image.width and image.height properties are unaltered but the currentTransform member will be changed.

      Parameters

      • x: number

        a number representing the abscissa of the scaling vector.

      • Optionaly: number = x

        a number representing the ordinate of the scaling vector.

      • Optionalz: number = 1

        a number representing the depth of the scaling vector.

      Returns UIBaseElement

      Reference to this object for method chaining

    • Automatically set the specified property of all childs to the given value

      This ASSIGNS to the children — after it, their own property carries the value. To fade a subtree without touching what the children are, set Renderable#alpha on the container instead: opacity cascades at draw time and leaves every child's own value alone.

      Parameters

      • prop: string

        property name

      • value: any

        property value; whatever the named property holds, so a flag is a boolean and a colour is a string, not only an object

      • Optionalrecursive: boolean

        recursively apply the value to child containers if true

      Returns void

      Renderable#alpha

    • Move this renderable, optionally in three dimensions.

      pos holds an ObservableVector3d, but the geometry this class inherits from declares it as a 2D vector, so from TypeScript pos.set(x, y) takes two arguments and silently writes a zero z. Anything with a depth then drops to the near plane. Reaching past that previously meant a double cast or assigning pos.x, pos.y and depth by hand, which is why that pattern is written out dozens of times across the examples.

      Omitting z leaves the depth exactly as it was, rather than zeroing it. That is the whole difference from pos.set(x, y), and it is what makes this safe to call on a 2D sprite that happens to sit at a depth, or on a Camera2d, without having to know whether it does.

      Parameters

      • x: number

        the new x position

      • y: number

        the new y position

      • Optionalz: number

        the new depth; left untouched when omitted

      Returns UIBaseElement

      this renderable, for chaining

      sprite.setPosition(120, 64);        // 2D: depth unchanged
      mesh.setPosition(0, -20, 140); // 3D
      camera.setPosition(0, 0, -300).lookAt(player);
    • set new value to the Polygon

      Parameters

      • x: number

        position of the Polygon

      • y: number

        position of the Polygon

      • points: PolygonVertices | LineVertices

        array of vector or vertices defining the Polygon

      Returns UIBaseElement

      this instance for object chaining

    • Tint this renderable, chainably.

      Exactly Renderable#tint's own setter, returning the renderable so it can be chained with the other set* methods. It exists because tint is a live Color, so reaching for it means choosing between setColor (0 to 255), setFloat (0 to 1), parseCSS, setHSL and setLinear — and picking the wrong one is silent, it just renders the wrong colour.

      Deliberately sRGB only. A LINEAR value, which in practice means a glTF baseColorFactor or emissiveFactor, stays an explicit tint.setLinear(...) so the conversion is never silent; for a mesh built from an asset, pass Mesh#baseColorFactor as a setting and the loader's value is applied for you.

      Parameters

      • value: string | Color

        a Color to copy, or a CSS colour string

      Returns UIBaseElement

      this renderable, for chaining

      sprite.setTint("#ff8800");
      // the same on any renderable, mesh included
      mesh.setTint(theme.accent).setOpacity(0.5);
      // remove a tint
      sprite.setTint("#ffffff");
    • Shifts the Polygon to the given position vector.

      Parameters

      • x: number

        The x coordinate or a vector point to shift to.

      • Optionaly: number

        The y coordinate. This parameter is required if the first parameter is a number.

      Returns void

      polygon.shift(10, 10);
      // or
      polygon.shift(myVector2d);
    • Shifts the Polygon to the given position vector.

      Parameters

      • vector: XYPoint

      Returns void

      polygon.shift(10, 10);
      // or
      polygon.shift(myVector2d);
    • Synchronous variant of Container#sort. Sorts immediately — no defer — using the current _comparator. Intended for per-frame callers that need the order to be valid for the very next render (e.g. Camera3d refreshing the "depth" sort after the camera has moved, where waiting for the deferred sort tick would render a stale frame).

      Parameters

      • Optionalrecursive: boolean

        recursively sort sub-containers

      Returns void