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

melonjs-audio

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

原文原文の説明を見る

Use this skill for sound and music in melonJS — loading audio, playing effects, background tracks, audio sprites, volume and muting, spatial audio, procedural tone/noise generation, and effects such as reverb or a compressor on the whole mix. Covers the mandatory audio.init format list, the directory-not-file src convention, playTrack versus play, the fixed listener and pixel-scale distances of positional sound, and browser autoplay unlocking. Triggers on: audio, sound, audio.init, audio.play, playTrack, stopTrack, audio.load, sfx, music, volume, mute, fade, rate, pitch, sprite audio, stereo, panner, position, listener, refDistance, reverb, echo, delay, compressor, distortion, filter, audio effect, audio.tone, audio.noise, getAudioContext, getMasterGain, hasAudio, hasFormat, autoplay, no sound, sound stopped working, context suspended, silent after idle, clips silent but tones play.

melonjs/melonJSスター 6,429(GitHub 6,429 + cccskills 0)

実行スコア 未検証

インストール方法を見る

こんなときに便利

  • 効果音とBGMを読み込みたいとき
  • ゲーム内の位置に応じて音を鳴らしたいとき
  • 音声ファイルなしで短い音を作りたいとき
  • 無音や自動再生の問題を調べたいとき

日本語での紹介

できること

melonJSの音声機能を使い、効果音やBGMの読み込み、再生、停止、音量調整を行います。効果音と、現在のトラックとして管理するBGMの使い分け、音声スプライト、再生位置や速度の変更、フェードにも触れます。ゲーム内の位置に応じて音を配置したり、リスナーを動かして距離や左右の聞こえ方を調整したりする方法も扱います。音声ファイルを使わないトーンやノイズの生成、Web Audioを使ったミックス全体へのリバーブなどの適用も対象です。

こんなときに便利

melonJSでゲームの音を実装するときや、BGMが切り替わらない、音が鳴らないといった問題を調べるときに役立ちます。音声形式の指定、読み込みパス、ブラウザーの自動再生制限、ストリーミング音声で使えない空間音響など、設定時につまずきやすい点も確認できます。

使い方の例

  • 「効果音とBGMを読み込み、シーンごとに再生する方法を教えて」
  • 「プレイヤーの位置に追従する効果音を設定して」
  • 「クリック後に音を再生するよう、自動再生制限への対応を整理して」

注意点

音声ファイルの再生形式は audio.init() で読み込み前に指定します。空間音響やトーン・ノイズ生成、ミックスへのエフェクト適用にはWeb Audioが必要です。ブラウザーでは最初のユーザー操作まで音声再生が保留される場合があります。

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

含まれるファイル(1)

  • SKILL.md25.6 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Audio

Two setup rules

import { audio, loader } from "melonjs";

audio.init("mp3,ogg");                      // 1. BEFORE preloading any audio

await loader.preload([
    { name: "cling", type: "audio", src: "data/sfx/" },   // 2. a PREFIX, not a file
]);
  1. audio.init(format) must run before any audio asset is preloaded, and lists the formats you actually ship. Preloading first throws target audio extension(s) should be set through me.audio.init() before calling the preloader. It returns false when no audio backend is available, so it is worth checking. The format list defaults to "mp3".
  2. src is a prefix, not a file. The loader appends the asset name plus each configured extension and uses the first that loads — so data/sfx/ + cling + mp3 → data/sfx/cling.mp3. Passing a full filename gives you a 404. A data:audio/... URL is the one exception: it is used verbatim, prefix and extension skipped.

audio.hasAudio() says whether the browser can play audio at all, and audio.hasFormat("ogg") whether it can play one codec — useful for choosing the init list or hiding a sound toggle on a device with no audio.

Order matters — melonJS tries the listed formats left to right, so put the preferred one first. Two formats ("webm,mp3" or "mp3,ogg") is the usual belt-and-braces for codec coverage. Accepted tokens: mp3, mpeg, opus, ogg, oga, wav, aac, caf, m4a, m4b, mp4, weba, webm, dolby, flac.

Effects versus music

audio.play("cling");                    // fire and forget
audio.play("cling", false, null, 0.5);  // loop, onend, volume
const id = audio.play("engine", true);  // looping; keep the id to stop it

audio.playTrack("theme");               // background music
audio.stopTrack();

Use playTrack for music, not play. playTrack(name, volume?) always loops, and it records the name as the current track — which is what app.pauseOnBlur / resumeOnFocus / stopOnBlur act on, via state.pause(true) → pauseTrack(). stopTrack(), pauseTrack(), resumeTrack() and getCurrentTrack() all read that same single slot, so there is only ever one current track name.

playTrack stops the track it replaces (20.9.0 and later; before that it only assigned the slot, and the previous bed kept looping underneath where stopTrack() could no longer reach it). So a scene just states its own music and nothing cancels anything:

class PlayScreen extends Stage {
    onResetEvent() { audio.playTrack("battle", 0.6); }
}

Calling it with the track already playing restarts it, the same as play() on any other clip. A scene that wants the bed to carry on across a screen change should not call it again, rather than rely on it doing nothing.

stopTrack() is for where nothing follows: a scene whose successor has no music of its own, or a game going quiet. state.change destroys the outgoing stage before it resets the incoming one, so a stopTrack() in onDestroyEvent and a playTrack() in the next onResetEvent are in that order and never cancel each other.

To end a track on an event rather than on a screen change, say a run ending while the player stays on the same screen, audio.fade(name, from, 0, ms) takes it down gently. A fade to zero is silence, not a stop, so the voice is still live until something stops it or replaces it.

Every per-clip function throws audio clip <name> does not exist if the clip was never loaded, and play additionally throws when a named sprite region is missing.

Audio sprites

One file carrying many effects, with named regions in milliseconds:

await loader.preload([{
    name: "sfx", type: "audio", src: "data/sfx/",
    sprite: { jump: [0, 450], hit: [2000, 250], music: [4000, 12000, true] },
}]);

audio.play("sfx", { sprite: "jump" });

A loop with no gap

An MP3 encoder pads the end of its file. Chrome and Firefox trim the padding when they decode it, Safari keeps it, so a looping MP3 has a short silence at every loop there (27 ms on a 12 s clip at 22 kHz, measured). Declare a region of the loop's exact length and loop on that: the voice never reaches the padding.

await loader.preload([{
    name: "ambience", type: "audio", src: "data/sfx/",
    sprite: { loop: [0, 12000] },
}]);
audio.playTrack("ambience", { sprite: "loop", volume: 0.6 });
// or, as a plain clip: audio.play("ambience", { sprite: "loop", loop: true })

Ogg Vorbis carries no such padding.

The optional third element marks a region as looping: it loops unless play() is told loop: false (before 20.11 it only looped when loop: true was passed as well). play()'s second argument takes either the original loop boolean or a PlayOptions object (sprite, loop, onend, volume, plus the spatial follow, at and stopWithTarget) — both forms work. Object fields win over the positional onend / volume arguments when both are supplied.

Clip state

audio.duration("theme");        // seconds — 0 while still loading
audio.duration("sfx", id);      // duration of the region THAT instance plays
audio.playing("theme");         // is anything playing?
audio.playing("theme", id);     // is that instance playing?
audio.state("theme");           // "unloaded" | "loading" | "loaded"

stop(), pause() and resume() take an optional instance id too; omit it and the whole group is affected. audio.stop() with no arguments at all stops every sound. audio.seek(name) reads the position, audio.seek(name, s, id?) writes it; audio.rate(name, r, id?) changes speed and pitch together (0.5..4.0, 1 is normal) and audio.fade(name, from, to, ms, id?) ramps the volume (0..1, over milliseconds).

Volume and muting

audio.setVolume(0.5);           // global, 0..1
audio.getVolume();              // read it back
audio.mute("cling");            // one clip  — mute(name, id?, shouldMute = true)
audio.unmute("cling");
audio.muteAll();                // everything (audio.disable() is an alias)
audio.unmuteAll();              // (audio.enable() is an alias)
audio.muted();                  // global mute state

audio.unload(name) / audio.unloadAll() free the decoded buffers; unload also clears the current-track pointer if it named that clip.

Losing focus mutes everything

When the window loses focus the engine mutes all audio, and unmutes it on focus. That covers sound effects, procedural tone / noise and the mixer effects, not just the music track that state.pause() pauses. Set pauseOnBlur: false in the application settings if a clip has to keep playing in the background.

Spatial audio

audio.position("engine", x, y, z);
audio.orientation("engine", x, y, z);
audio.stereo("engine", -1);     // -1 left … 1 right
audio.panner("engine", { coneInnerAngle: 90, /* … */ });

position(name, x, y = 0, z = -0.5, id?) and orientation(name, x, y, z, id?) both default id to "the whole group". Called with just the clip name, each of the four returns the current value — stereo gives 0 and position gives [0, 0, 0] before they have ever been set.

Let the engine place the sound: follow and at

The shortest path to positional audio is a play option. Both take world pixels, the same numbers as pos.x / pos.y, and the engine converts to audio space for you:

// tracks the renderable every frame, and stops when it is destroyed
audio.play("ufo", { follow: this, stopWithTarget: true });

// pinned to a fixed world point
audio.play("portal", { at: { x: 1200, y: 480 } });

follow and at are mutually exclusive: passing both throws, rather than quietly picking one. follow re-reads the target's absolute position each frame, so a renderable nested in a moving container is placed correctly. stopWithTarget is what you want for a sound that belongs to an entity: without it a looping clip on a destroyed renderable keeps playing from wherever it last was. audio.unfollow(id) detaches a sound and leaves it playing where it is.

Move the listener, don't do the subtraction yourself

audio.setListener(player);                  // tracked every frame
audio.listener(x, y, z);                    // or place it by hand
audio.listener();                           // → [x, y, z] in world pixels
audio.listenerOrientation(fx, fy, fz, ux, uy, uz);
audio.setListener(null);                    // stop tracking

With a listener in the world, source positions are absolute world coordinates, not offsets. The older idiom — passing source.pos.x - player.pos.x every frame with the ear stuck at the origin — still works, but only if you leave the listener at (0, 0, 0); mixing the two double-counts the player's position.

setListener places the ear at the target's absolute position after the world updates. A plain renderable contributes position only, so a side-scroller keeps the default "facing into the screen" and gets left-right panning plus distance falloff from the one call.

A Camera3d target also contributes its orientation, taken from its own basis, so turning the camera swings the stereo image with it. That is the whole of what a posed 3D scene needs:

audio.setListener(app.viewport);                 // in a 3D scene this is a Camera3d
audio.play("drone", { follow: saucer });         // scene coordinates, directly

Y is down. Every one of these calls takes and returns melonJS world coordinates, where y grows downward; the Y-up flip Web Audio wants happens inside the engine. Pass pos.y as it is.

The defaults are tuned for pixels

audio.setSpatialDefaults() / getSpatialDefaults() set the panner attributes a sound placed through follow or at starts from, and the shipped values assume a 2D game measured in pixels:

attributedefault
refDistance240
maxDistance10000
panningModel"equalpower"
distanceModel"inverse"

With those, a placed sound is at full volume out to 240 px and then halves each time the distance doubles: about half at 480, a quarter at 960, roughly an eighth at 2000. maxDistance is where it stops getting quieter.

They apply to placed sounds only. A plain audio.play() followed by a bare audio.position() keeps WebAudio's own defaults, where refDistance is 1 METRE and a source 100 px out is already near silent. That path is unchanged, which is what keeps old code working.

Widen or tighten the field once, globally:

audio.setSpatialDefaults({ refDistance: 400, maxDistance: 20000 });

audio.panner(name, attrs, id?) still overrides per clip or per voice, and it merges over the current values rather than replacing them, so writing one field no longer resets the rest. Called without an id it writes the group defaults, which is what a clip-wide tuning call looks like.

For a 3D scene where front-to-back matters, panningModel: "HRTF" is worth the cost; for a 2D one it mostly muddies the stereo image.

stereo and position: last writer wins

Both drive the same per-instance panner node, and the engine swaps the node to match whichever you called last: stereo() after position() gives you plain left-right panning, and position() after stereo() gives you 3D falloff. Neither silently does nothing any more, and the order you call them in no longer matters.

Still pick one per voice and stay with it. A 2D game usually wants stereo() alone; reach for position() (or follow / at) when distance falloff matters.

Spatial audio is WebAudio-only. On a clip loaded with stream: true (or html5: true, or preload: false) stereo / position / orientation return early and do nothing — which is exactly the case for the long music tracks people reach for first. follow and at are equally inert on a streamed clip.

Procedural sound

For beeps, blips and noise without shipping files. Both take one options object, and duration (in seconds) is required:

audio.tone({ freq: 440, duration: 0.2, gain: 0.3, pan: -0.5 });
audio.tone({ freq: [440, 660, 880], duration: 0.4 });   // layered partials
audio.noise({ duration: 0.5, filter: { type: "lowpass", frequency: 800 } });

tone also takes wave (default "sine"), attack (0.005) and pitchSlide (1). noise takes type ("white" | "pink" | "brown", default "white"), attack, pan, filter and filterSweep. gain defaults to 0.1 on both.

Sequencing: delay, not setTimeout

Both take delay — seconds before the sound starts, scheduled on the audio clock. That is what builds a multi-part sound: a stinger's second note, an explosion's double-tap.

audio.tone({ freq: 392, duration: 0.12 });
audio.tone({ freq: 587, duration: 0.18, delay: 0.11 });
audio.tone({ freq: [784, 1176], duration: 0.75, delay: 0.23 });

Do not reach for setTimeout here. A timer fires on the main thread, so a busy frame slips the note late and the sequence audibly loses time — the fault is easy to blame on the sound design rather than the scheduling. delay is sample-accurate because the whole envelope is scheduled up front.

Both are silent no-ops when there is no WebAudio context — they bail on getAudioContext() === null rather than throwing. Neither needs the clip to be loaded; neither goes through the file-playback path at all.

audio.getAudioContext() and audio.getMasterGain() are the escape hatches for custom Web Audio work; both return null when audio is unavailable, so guard. Connect a custom graph to the master gain rather than ctx.destination if you want it to respect setVolume / muteAll.

Effects on all game audio: reverb, echo, compressor

There is no built-in reverb, delay, distortion or compressor, and no per-clip filter on file playback. There does not need to be one for the common case: every buffered clip and every tone / noise passes through the master gain on its way to the speakers, so an effect inserted after it applies to the whole mix.

const ctx = audio.getAudioContext();   // creates the context if needed
const master = audio.getMasterGain();
if (ctx && master) {                   // null when audio is unavailable
    const comp = ctx.createDynamicsCompressor();
    master.disconnect();               // master -> speakers becomes
    master.connect(comp);              // master -> compressor -> speakers
    comp.connect(ctx.destination);
}

Any Web Audio node or chain works the same way: a ConvolverNode with an impulse response for reverb, a DelayNode with a feedback gain for echo, a BiquadFilterNode for an underwater low-pass, a WaveShaperNode for distortion. Do it once, at startup; the master gain lives as long as the context.

  • setVolume / muteAll still work, because they act on the master gain, which is now upstream of the effect.
  • Streamed clips are not affected. A stream: true (html5: true) clip plays through an <audio> element and never reaches the master gain — which is usually the music. Preload the music buffered if it must go through the effect.
  • It is all or nothing. The per-instance nodes are not public, so an effect on one clip only (muffling one sound behind a wall) is not possible through this route; noise has its own filter for generated sounds.
  • To remove it, reverse the wiring: master.disconnect(); master.connect(ctx.destination);.

Autoplay: sound is silent until the first gesture

Browsers create the audio context in the suspended state and keep it there until a user interaction. Nothing errors — audio simply does not play, which reads as a bug. melonJS installs one-shot touchstart / touchend / click / keydown unlock listeners on document, so the first real gesture anywhere unlocks it and fires the clip's on.unlock callback. Design for it: start music on the first click or key press, not on load. The usual way to guarantee one is a gate screen — a splash, a "press any key", or a health/photosensitivity notice — whose dismissal is the gesture, so the menu behind it can start its music unconditionally. Note the unlock listens for keydown too, so a keyboard-only player is covered.

The context can stop again, long after it was unlocked

Unlocking is only the first half. A context that has been running can be stopped later: melonJS suspends it itself after thirty idle seconds to save power, and browsers stop it for their own reasons, a backgrounded tab among them. Recovery is automatic and you do not have to write it: a user gesture or the tab coming back to the front revives it, and a deliberate idle suspension is left alone so the power saving still works.

The symptom worth memorising, because it points straight at the cause: if tone and noise are audible while loaded clips are silent, the context is healthy and the engine's playback state is wrong. The generators only need a live context, where a clip goes through the engine's state machine and can be parked waiting for a resume. It is never "the context died".

Both routes ask the same owner to resume, so hearing a tone tells you the hardware is back; it tells you nothing about whether the clips waiting on the engine's state have been let go.

That asymmetry was a real Safari-only bug: thirty idle seconds before the first click left the engine waiting on a suspend the browser never confirmed, so every clip queued for the life of the page while generated sound played normally. Fixed in 20.9, and the lesson generalises: a clip that will not play is a state question, not a hardware one.

Playback also starts asynchronously: play() returns an id while the instance is still starting, so playing() can legitimately be false on the very next line.

Load-time options

{ name: "sfx", type: "audio", src: "data/sfx/",
  sprite: { jump: [0, 450] },
  pool: 5,            // finished instances kept for reuse — NOT a concurrency cap
  rate: 1.0,          // initial playback rate, 0.5..4.0
  mute: false,
  loop: false,
  autoplay: false,
  preload: true,      // false: fetched on first play, then streamed; or "metadata"
  format: "mp3",      // explicit hint when the URL has no usable extension
  stream: true,       // long music: stream rather than decode into memory
  on: { play() {}, end() {}, stop() {}, unlock() {} },
}

pool (default 5) is a reuse cap on finished voices, not a limit on simultaneous playback: when the number of ended voices exceeds it, the surplus are disconnected and dropped. Raise it for a clip triggered in rapid bursts, not to allow more overlap.

Use stream: true for long music tracks — it plays through an HTML5 <audio> element instead of decoding the whole file into memory. (html5: true is the same switch under its backend name.) on accepts the full lifecycle set: play, pause, stop, end, fade, seek, rate, volume, mute, unlock.

preload: false keeps a clip out of the preload. Nothing is downloaded for it until it is first played (audio.play, audio.playTrack, or autoplay). That play fetches it and streams it, as stream: true does, so the sound starts as soon as enough of the file has arrived, not once all of it has; a clip never played is never downloaded. Use it for music a player may never reach (a boss theme, the ending) to shorten the wait before the game starts.

  • The loader reports such a clip done at once: audio.state(name) is "unloaded" until its first play, then "loading", then "loaded".
  • It starts with the short delay of a stream on its first play. Keep a sound effect that must sound the instant it is triggered preloaded.
  • Being streamed, it has the limits of stream: true: positional sound does not apply to it, and it ignores withCredentials (see below).
  • Before 20.12.0 such a clip was never fetched at all, and stayed silent.

stream: true alone still fetches the clip during the preload; combine it with preload: false to defer that too. preload: "metadata" only matters for a streamed clip: the preload fetches just enough to know its duration.

Outside a preload, audio.load(asset, onload?, onerror?) takes the same descriptor and loads one clip at runtime — for a level's sounds fetched when the level starts. The loader calls the same function, so the same rules apply.

Re-preloading a manifest that already contains a loaded clip is a no-op — audio.unload(name) first if you genuinely want to reload it.

Credentials use the same global switch as every other asset type — loader.setOptions({ withCredentials: true }), not an audio-specific option. Buffered audio fetches through the shared loader path, so it honours it exactly as an image or a JSON file does. A streamed clip (stream: true, or preload: false) does not: it plays through an <audio> element, which needs a crossorigin attribute rather than fetch credentials. Preload a clip buffered if it sits behind a login.

Failing clips and setStopOnAudioError(false). The default is to fail the preload when a clip cannot be loaded after its retries: the error reaches the loader, so await loader.preload(...) rejects and your catch runs, and the reason is logged. Turn the flag off and the engine mutes audio, warns (failed loading <name>, disabling audio) and lets the load continue — the preload finishes and the game reaches the next scene without sound.

Before 20.4 both halves were broken: with the flag off it disabled audio and failed the preload anyway, and a clip whose bytes arrived but would not decode (a missing file served as HTML by an SPA rewrite, say) reported nothing at all either way — blank screen, empty console.

Symptom → cause

symptomcause
audio assets 404src given as a full filename instead of a directory prefix
target audio extension(s) should be set... thrown at preloadaudio.init() not called before preloading
audio clip X does not existthe clip was never preloaded, or the name is mis-cased — every per-clip call throws this
nothing plays until the user clicksbrowser autoplay policy — expected, design around it
playing() is false right after play()playback starts asynchronously
music keeps playing after leaving a sceneused play instead of playTrack, or no stopTrack in teardown
two music tracks playing at once, and stopTrack() only silences onemelonJS before 20.9.0: playTrack did not stop the previous track, so the scene that started it had to stopTrack() on the way out
the music restarts when returning to a screenplayTrack with the track already playing restarts it; don't call it again if the bed should carry on
stereo / position do nothingthe clip was loaded with stream: true or preload: false — spatial is WebAudio-only
a preload: false clip never plays, and audio.state() stays "unloaded"melonJS before 20.12.0 never fetched such a clip; preload it, or update
one format works, another does notthat codec is not in the audio.init() list
audio behind a login fails, or the preload hangsloader.setOptions({ withCredentials: true }) — the same switch every asset type uses
a streamed clip ignores withCredentialsstream: true plays through an <audio> element; preload it buffered instead
audio.tone(440, {...}) does nothing / errorstone takes a single options object with a required duration
tone / noise are silent with no errorno WebAudio context — getAudioContext() returned null
a positioned sound is silent, or only audible right next to the playerplaced by hand with audio.position(), which keeps WebAudio's metre defaults (refDistance: 1) — use follow / at, or set refDistance in pixels with audio.panner()
a positioned sound does not follow the playernothing is placing it — audio.play(name, { follow: entity }), and audio.setListener(player) once
a followed sound pans to the wrong side as the player movesthe listener was moved and positions are still relative to the player — with a listener in the world, pass absolute world coordinates
a looping sound outlives the entity that owns itfollow without stopWithTarget: true
a voice panned with stereo() loses its 3D placement, or the reverseone panner node per voice and last writer wins — pick one per voice and stay with it
a reverb / compressor on the master gain does not affect the musicthe music is stream: true, which bypasses the master gain — preload it buffered
a looping MP3 drops out for a moment at every loop, in Safari onlySafari keeps the encoder's padding at the end of the file: loop a sprite region of the clip's exact length (see "A loop with no gap")
sound effects keep playing after the window loses focuspauseOnBlur and stopOnBlur are both off, so the engine is deliberately leaving the game running in the background

Related skills

  • melonjs-getting-started — preloading and asset ordering

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。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-camera-and-drawing

無料概要あり

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

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

melonjs-deployment

無料概要あり

melonJSゲームのWeb向けビルドやネイティブアプリ化、ミニゲーム配信に向けた準備を進め、ブラウザー対応や容量の注意点も確認できます。

  • 配布用のゲームプロジェクトを作りたいとき
  • iOSやAndroid向けにアプリ化したいとき
  • 古いブラウザーへの対応を検討したいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs のスキルをすべて見る

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