본문으로 건너뛰기
cccskills
무료GitHub에 공개

melonjs-sprites-and-animation

Create melonJS sprites from images or texture atlas regions, set up frame animations, and adjust tint, transparency, and flips. The guide also covers nine-slice panels and sprite positioning, including how the default centered anchor affects coordinates.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

원문원문 설명 보기

Use this skill when creating sprites, playing frame animations, or working with texture atlases in melonJS. Covers Sprite construction from a plain image or an atlas region, addAnimation/setCurrentAnimation, TextureAtlas for TexturePacker/ShoeBox/Aseprite, tint, flip, NineSliceSprite, and the centred anchorPoint that offsets naive positioning. Triggers on: Sprite, new Sprite, addAnimation, setCurrentAnimation, isCurrentAnimation, TextureAtlas, TexturePacker, Aseprite, ShoeBox, atlas, region, framewidth, frameheight, tint, flipX, flipY, NineSliceSprite, animation.

melonjs/melonJS스타 6,429(GitHub 6,429 + cccskills 0)

실행 점수 미검증

설치 방법 보기

이럴 때 유용합니다

  • Create a sprite from an image or atlas region
  • Set up idle, walking, or one-shot animations
  • Fix sprite placement using the anchor point
  • Stretch a panel while keeping its corners intact

포함된 파일(1)

  • SKILL.md8.1 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Sprites, animation and atlases

Creating sprites from images or atlases, driving frame animation, and the positioning trap that catches almost everyone.

pos is the centre, not the top-left

Renderable.anchorPoint defaults to (0.5, 0.5), so a sprite's pos is its centre. Container forces (0, 0) instead, which is why containers and sprites appear to disagree.

// a 64×64 sprite at (100, 100) covers 68..132, not 100..164
const s = new Sprite(100, 100, { image: "hero", framewidth: 64, frameheight: 64 });

s.anchorPoint.set(0, 0);   // switch to top-left positioning if you prefer

Writing top-left maths against the centred default puts everything half a sprite off, with no error. It is the most common source of "close but subtly wrong" placement.

Constructing a sprite

From a plain image:

const hero = new Sprite(x, y, {
    image: "hero",          // preloaded asset name
    framewidth: 32,
    frameheight: 32,
});

From a texture atlas region:

const atlas = new TextureAtlas(loader.getJSON("sprites"), loader.getImage("sprites"));
const coin = new Sprite(x, y, { image: atlas, region: "coin_01.png" });

framewidth / frameheight define the animation grid on a sheet. Omit them and the whole image is one frame.

Animation

hero.addAnimation("idle", [0, 1, 2, 3], 100);   // frames, ms per frame
hero.addAnimation("walk", [4, 5, 6, 7]);
hero.addAnimation("die",  [8, 9], 150);

hero.setCurrentAnimation("walk");
hero.setCurrentAnimation("die", "idle");                          // chain to idle when it ends
hero.setCurrentAnimation("die", { loop: false });                 // play once, hold the last frame
hero.setCurrentAnimation("die", { loop: false, onComplete: fn }); // …and call fn when it does
hero.setCurrentAnimation("use", { next: "idle", onComplete: fn }); // call fn, then chain to idle
hero.setCurrentAnimation("run", { onFrame: (frame) => {            // each frame playback reaches
    if (frame === 3 || frame === 8) footstep();
} });

if (hero.isCurrentAnimation("walk")) { /* … */ }

Frame indices are into the framewidth/frameheight grid. With an atlas, use atlas.getAnimationSettings([regionNames]) and spread it into the Sprite settings, or atlas.createAnimationFromName([regionNames]), which returns a ready-made Sprite. On a fixed-cell spritesheet only numeric indices are accepted — passing region names throws.

The second argument to setCurrentAnimation is polymorphic. A string chains to that animation when this one ends. An options object takes { loop, next, speed, onComplete, onFrame }, and only an explicit loop: false stops the looping. A bare function is the legacy form: it fires at every cycle end, and only holds the last frame if it returns false. Omit the argument entirely and the animation loops forever.

onFrame(frame) is called with frame 0 when the animation starts, then with each frame playback reaches, so a footstep or a hit lands on its frame without polling getCurrentAnimationFrame(). A long tick reports every frame it goes past. It is not called for a frame set with setAnimationFrame, nor for the frame 0 a play-once animation would wrap to. Keep the callback in a field when you call setCurrentAnimation every frame: re-selecting keeps the first one anyway.

With both next and onComplete, the callback runs first and the chained animation starts with none of its own, so a one-off action (a pickup, an attack) needs no manual switch back to idle.

Re-selecting the animation that is already current is a no-op, so calling setCurrentAnimation every frame is safe, and an isCurrentAnimation check around it adds nothing. An unknown id throws.

Texture atlases

TextureAtlas reads several formats:

sourcehow
TexturePacker / Free Texture Packer JSONnew TextureAtlas(loader.getJSON(name), loader.getImage(name))
Aseprite JSON exportsame as TexturePacker — the format is detected from meta.app
Aseprite .aseprite / .ase binaryloader type "aseprite", which stores the composited image and a JSON sidecar under the one asset name
ShoeBoxJSON export using the melonJS exporter settings file; same call as TexturePacker
fixed-cell spritesheetnew TextureAtlas({ framewidth, frameheight, anchorPoint }, loader.getImage(name))
multi-pagepass an array of atlas JSON objects as the first argument

Helpers: createSpriteFromName(name), createAnimationFromName([names]), getAnimationSettings([names]).

Atlases matter for performance: the GPU batchers bind several textures at once (up to renderer.maxTextures), so a handful of separate images still batch — but once a frame crosses that many distinct textures the batch has to flush. Packing into one atlas keeps everything on a single binding.

Visual properties

sprite.setTint("#ff8000");   // multiply tint
sprite.alpha = 0.5;
sprite.flipX(true);                   // mirror horizontally
sprite.flipY(true);
sprite.blendMode = "additive";        // see the effects skill for the full list
sprite.scale(2, 2);                   // ← multiplicative, see below

scale() is multiplicative, not absolute. Calling it every frame compounds. For absolute scaling reset first:

sprite.currentTransform.identity();
sprite.currentTransform.scale(s, s, 1);

This bites hardest with pooled sprites, which arrive carrying their previous life's transform.

NineSliceSprite

For panels and dialogue boxes that stretch without distorting their corners:

new NineSliceSprite(x, y, {
    image: "panel", width: 300, height: 120,
    insetx: 12, insety: 12,     // lowercase x/y — `insetX` is silently ignored
});

width and height are mandatory and the constructor throws without them. The insets default to a quarter of the frame.

Pooling

Frequently spawned sprites should be pooled:

import { createPool } from "melonjs";

const bulletPool = createPool((x, y) => {    // me.pool is deprecated
    const instance = new Bullet(x, y);
    return { instance, reset: (x, y) => instance.onResetEvent(x, y) };
});
const b = bulletPool.get(x, y);             // new Bullet(x, y), or reset(x, y) on a reused one
world.removeChild(b);                       // returns it to bulletPool automatically

Two consequences:

  • A recyclable class's onResetEvent must reset everything its lifetime mutates — alpha, tint, scale, animation state. Anything you forget carries over to the next use.
  • Pool-recycled objects do not fire onDestroyEvent on removal. Pair event subscriptions with onActivateEvent / onDeactivateEvent instead.

Symptom → cause

symptomcause
everything offset by half a spritetop-left maths against the centred anchorPoint
sprite grows every framescale() is multiplicative — reset the transform
a recycled sprite keeps its old lookonResetEvent does not restore every mutated property
event handlers leak on pooled objectsbound in the constructor rather than onActivateEvent
animation never advancesno framewidth/frameheight, so the sheet is one frame
animation plays once and stops{ loop: false }, or a callback that returned false
sprites do not batchmore distinct textures in one frame than renderer.maxTextures
nine-slice corners stretch anywayinsetX/insetY instead of insetx/insety

Related skills

  • melonjs-renderables — anchors, draw order, custom draw
  • melonjs-getting-started — preloading images and atlases

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

melonjs

무료

Use this entry point to find the melonJS guide for a game development task, from application setup and scenes to sprites, input, physics, audio, and 3D. It also points to companion packages and the API index when the guides do not cover a need.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Choose a guide for a melonJS game task
  • Find the right setup steps for a new game
  • Locate guidance for a 3D scene or imported model
melonjs/melonJS6.4천2026년 10월 30일 업데이트

Update older melonJS code for version 20.x. Review the asynchronous Application setup, renderer changes, post-effect API, and deprecated exports so you can identify outdated patterns when migrating or debugging expected APIs.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Migrating a game from melonJS 19.x
  • Checking why an older API is missing
  • Replacing deprecated shader assignments
melonjs/melonJS6.4천2026년 10월 30일 업데이트

Build 3D or 2.5D scenes in melonJS with cameras, meshes, billboards, lights, shadows, and depth sorting. This guide explains the engine’s Y-down and +Z-forward coordinates, camera setup, transparency, and fog, and identifies features that require a GPU renderer instead of the Canvas fallback.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Setting up a Camera3d for a game stage
  • Placing meshes, billboards, or repeated instances
  • Fixing depth order or transparency in a 3D scene
melonjs/melonJS6.4천2026년 10월 30일 업데이트

Load glTF, GLB, or OBJ/MTL assets into melonJS and understand how their materials, lights, animations, shadows, and instances are handled. The guide explains loader options and common format limitations so you can configure scenes and diagnose missing or incorrectly rendered asset features.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Loading a glTF or GLB scene into a melonJS level
  • Adding a static OBJ model with its MTL material
  • Checking why imported materials or lights look different
melonjs/melonJS6.4천2026년 10월 30일 업데이트

Manage sound in melonJS games: load audio, play effects and looping background tracks, control volume, and place sounds in the game world. It also covers generated tones and noise, whole-mix effects, and common causes of silent playback.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Loading sound files and choosing supported audio formats
  • Playing sound effects and looping background music
  • Positioning sounds around a player or game object
melonjs/melonJS6.4천2026년 10월 30일 업데이트

Use this skill to control melonJS cameras and draw shapes, lines, and gradients. It covers target following, camera bounds and effects, coordinate conversion, clipping, rendering into a canvas target, and reading rendered pixels for images or data.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Making a camera follow a player within world bounds
  • Converting pointer or 3D positions to screen coordinates
  • Drawing shapes or gradients in a custom draw method
melonjs/melonJS6.4천2026년 10월 30일 업데이트

melonjs의 스킬 모두 보기

이 스킬의 문제 신고