melonJS
    Preparing search index...

    Class SquishEffect

    A shader effect that squishes a sprite: its middle bulges out, or pinches in, while its top and bottom rows stay where they are.

    Paired with a change of height, it gives squash and stretch that keeps the sprite's volume: scale the sprite to scaleY of its height and set the bulge to 1 - scaleY, so a stretched sprite pinches in and a squashed one bulges out (see the example).

    A bulge widens the sprite past its own frame. Like a shader that scales VERTEX in its vertex function, the effect draws on a quad widened by 1 + bulge and narrows the texture back in its fragment, so the sprite needs no transparent margin. Made for a sprite carrying it as its only effect: chained with other effects, or on a camera, it squishes the whole frame instead. The bulge is not part of the sprite's bounds, so it is not counted for culling or pointer events.

    // bulge a sprite out by half its width across the middle
    const squish = new SquishEffect(renderer, { bulge: 0.5 });
    mySprite.addPostEffect(squish);
    // squash and stretch a platformer character: stretch on take-off,
    // squash on landing, then ease back to rest
    const squish = new SquishEffect(renderer);
    player.addPostEffect(squish);

    // scale the height about the feet, and bulge the other way
    const stretch = (scaleY) => {
    const feet = player.height * (1 - player.anchorPoint.y);
    player.currentTransform
    .identity()
    .translate(0, feet)
    .scale(1, scaleY)
    .translate(0, -feet);
    squish.setBulge(1 - scaleY);
    };

    const stretchTo = (scaleY) => {
    const state = { scaleY };
    stretch(scaleY);
    new Tween(state)
    .to({ scaleY: 1 }, { duration: 300, easing: Tween.Easing.Back.Out })
    .onUpdate(() => stretch(state.scaleY))
    .start();
    };

    stretchTo(1.3); // jumping: 30% taller, pinched in
    stretchTo(0.75); // landing: 25% shorter, bulging out

    Hierarchy (View Summary)

    Index
    destroyed: boolean = false

    true once destroy has been called. Distinct from enabled — which also toggles transiently across a context lost / restored cycle — to give callers a stable signal for "this effect has been explicitly released."

    enabled: boolean = false

    whether this effect is active (false in Canvas mode, false after destroy, and false while the WebGL context is suspended between an ONCONTEXT_LOST and the matching ONCONTEXT_RESTORED event).

    shared: boolean = false

    When true, a renderable will NOT auto-destroy this effect when it is removed from its postEffects (via the shader setter, Renderable#removePostEffect, Renderable#clearPostEffects) or when the renderable itself is destroyed. Set this on an effect shared across several renderables so one of them going away doesn't free the GL program still used by the others — you then own its lifecycle and call destroy yourself.

    false
    
    • set how far the middle of the sprite bulges out, or pinches in

      Parameters

      • bulge: number

        from -1 to 1: positive bulges out, up to twice the width across the middle; negative pinches in, down to nothing at -1; 0 leaves the sprite as it is

      Returns void

    • Bind an extra texture to a named sampler2D uniform in this shader, so a custom effect can read a second texture — a noise map, mask, gradient, flow/lookup table — besides the sprite/target it post-processes (uSampler). The engine uploads, caches, and re-binds it to a reserved texture unit each time the effect draws, and points the sampler uniform at it — no raw WebGL texture-unit juggling.

      Declare the sampler in your fragment (uniform sampler2D <name>;) and pass that name here. Any engine texture works — a Texture2d asset (NoiseTexture2d, TextureAtlas, …) can be passed directly, or a raw drawable source. No-op in Canvas mode.

      Parameters

      • name: string

        the sampler2D uniform name declared in the fragment

      • image: HTMLCanvasElement | HTMLImageElement | OffscreenCanvas | ImageBitmap | Texture2d

        the texture: an engine texture asset, or a raw drawable source

      • Optionalrepeat: "repeat" | "no-repeat" | "repeat-x" | "repeat-y" = "no-repeat"

        wrap mode; use "repeat" for a tiled/scrolled texture

      Returns ShaderEffect

      this effect for chaining

      // "water": distort the sprite by a static noise texture scrolled over time
      const noise = new me.NoiseTexture2d({ width: 256, height: 256, seamless: true });
      const water = new me.ShaderEffect(renderer, `
      uniform sampler2D uNoise;
      uniform float uTime;
      vec4 apply(vec4 color, vec2 uv) {
      vec2 flow = texture2D(uNoise, uv + uTime * 0.03).rg - 0.5;
      return texture2D(uSampler, uv + flow * 0.02);
      }`);
      water.setTexture("uNoise", noise, "repeat");
      waterSprite.addPostEffect(water);
      // each frame, in your Stage's update(dt):
      water.setTime(me.timer.getTime() / 1000);
    • Set the shader's uTime uniform (elapsed time, in seconds). A convenience over setUniform("uTime", ...); call it once per frame from your update loop to animate a shader that declares uniform float uTime (e.g. scrolling a static noise texture's UVs, pulsing, waving). Drive it with whatever clock you like — real time, a paused/scaled/scrubbed one.

      No-op if the shader does not declare a uTime uniform (nothing to update), or in Canvas mode. The engine does NOT call this for you — animation is opt-in, exactly like re-baking a NoiseTexture2d with update(dt).

      Parameters

      • seconds: number

        elapsed time in seconds

      Returns ShaderEffect

      this effect for chaining

      // a shader that scrolls a static seamless noise texture over time
      const flow = new me.ShaderEffect(renderer, `
      uniform float uTime;
      vec4 apply(vec4 color, vec2 uv) {
      return texture2D(uSampler, uv + vec2(uTime * 0.05, 0.0));
      }`);
      mySprite.addPostEffect(flow);
      // then in your Stage's update(dt):
      flow.setTime(me.timer.getTime() / 1000);
    • Set the uniform to the given value

      Parameters

      • name: string

        the uniform name

      • value: number | boolean | object | number[] | Float32Array<ArrayBufferLike>

        the value to assign to that uniform. Scalars (float, int, bool) take a number or a boolean; vectors and matrices take an array, a Float32Array, or any object exposing toArray() — which is every Vector2d, Vector3d, Color and Matrix3d.

        Sprites drawn one after the other through the same effect share one draw call. A new value draws the sprites queued before it first, so each sprite draws with the values it was given; the value it already has changes nothing, and keeps the draw shared.

      Returns void

      // a scalar the body declares as `uniform float uStrength;`
      fx.setUniform("uStrength", 0.5);
      // a vec3 — an array, or anything with toArray()
      fx.setUniform("uTint", [1.0, 0.82, 0.55]);
      fx.setUniform("uOrigin", new me.Vector2d(0.5, 0.5));
      // one outline shared by every enemy: drawn in a single call. Marked
      // shared, so the first enemy destroyed does not destroy it for the rest
      const outline = new me.OutlineEffect(renderer, { color: [1, 1, 1] });
      outline.shared = true;
      for (const enemy of enemies) {
      enemy.addPostEffect(outline);
      }