本文へ移動
cccskills
無料GitHub で公開日本語紹介

melonjs-sprites-and-animation

melonJSで画像やテクスチャアトラスからスプライトを作り、フレームアニメーションを設定する方法を扱います。位置合わせ、色変更、反転、伸縮パネルも確認できます。

原文原文の説明を見る

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)

実行スコア 未検証

インストール方法を見る

こんなときに便利

  • 画像からスプライトを作りたいとき
  • フレームアニメーションを設定したいとき
  • アトラスから画像領域を読み込みたいとき
  • 角を保ってパネルを伸縮したいとき

日本語での紹介

できること

通常の画像やテクスチャアトラスの領域からスプライトを作成し、フレーム単位のアニメーションを設定する手順を扱います。待機・歩行・一度だけ再生する動作の切り替えや、終了後に次のアニメーションへつなぐ方法、特定フレームで処理を呼ぶ方法も確認できます。TexturePacker、ShoeBox、Asepriteなどのアトラス形式、色味や透明度の変更、左右・上下反転にも対応します。角を保ったままパネルを伸縮するNineSliceSpriteも紹介します。

こんなときに便利

キャラクターやアイテムの表示を始めるとき、スプライトの位置が半分ずれて見えるとき、アニメーションが進まないときに役立ちます。画像の整理にアトラスを使いたい場合や、会話枠などを画面サイズに合わせて伸ばしたい場合にも参照できます。

使い方の例

  • 「この画像から歩行アニメーション付きのスプライトを作ってください」
  • 「Asepriteのアトラスから指定した領域を読み込んでください」
  • 「角をつぶさずに会話パネルを伸ばしてください」

注意点

アニメーション用の画像にはframewidthとframeheightの設定が必要です。NineSliceSpriteでは幅・高さが必須で、インセット設定名は小文字のinsetx、insetyです。

この紹介文は、公開されている SKILL.md をもとに AI(OpenAI Codex)が作成しました。正確な仕様は下の原文を確認してください。

含まれるファイル(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 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

melonjs

無料概要あり

melonJSを使ったゲーム制作で、目的に合う専門ガイドを選ぶための入口です。初期化から描画、入力、物理演算、音声、2D・3D機能まで案内します。

  • melonJSで作る内容に合うガイドを探したいとき
  • 新しいゲームの初期化手順を知りたいとき
  • 3Dやモデル読み込みの参照先を探したいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs-20-migration

無料概要あり

melonJS 19.x以前の知識を20.x向けに更新し、初期化や描画効果、廃止・非推奨APIの変更点を確認して移行時の不具合を調べられます。

  • 19.x以前のゲームを20.xへ移行したいとき
  • 古いAPIが見つからない原因を調べたいとき
  • 非推奨の描画効果を置き換えたいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs-3d

無料概要あり

melonJSの3D・2.5Dゲーム向けに、カメラ、メッシュ、ライト、奥行き順、透明表現やフォグの設定と座標系の注意点を確認できます。

  • 3Dカメラをステージに設定したいとき
  • メッシュやビルボードを配置したいとき
  • 奥行き順や透明表現を調整したいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs-3d-assets

無料概要あり

melonJSでglTF・GLBやOBJ・MTLの3Dモデルを読み込み、マテリアルやライト、アニメーション、影、インスタンスの扱い方を確認できます。

  • glTF・GLBのシーンを読み込みたいとき
  • OBJモデルとMTL素材を使いたいとき
  • モデルの向きや大きさを調整したいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs-audio

無料概要あり

melonJSで効果音やBGMを読み込み、再生・停止・音量調整するほか、位置に応じた音や音声合成、ミックス全体へのエフェクト設定を扱うスキルです。

  • 効果音とBGMを読み込みたいとき
  • ゲーム内の位置に応じて音を鳴らしたいとき
  • 音声ファイルなしで短い音を作りたいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs-camera-and-drawing

無料概要あり

melonJSのカメラ追従や画面効果、座標変換、図形描画を実装する際の要点を確認できます。描画のクリッピングやCanvasへの焼き込み、ピクセルの読み出しも扱います。

  • プレイヤーを追うカメラの範囲を設定したいとき
  • ワールド座標と画面座標を変換したいとき
  • 独自描画に図形やグラデーションを使いたいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs のスキルをすべて見る

このスキルの問題を報告する