Skip to content

Skills: NineSliceSprite in the UI skill, the audio skill brought up to the implementation, and open 20.9.0 - #1723

Merged
obiot merged 2 commits into
masterfrom
claude/exciting-allen-xjjbhb
Oct 7, 2026
Merged

obiot merged 2 commits into
masterfrom
claude/exciting-allen-xjjbhb

Conversation

@obiot

@obiot obiot commented Oct 7, 2026

Copy link
Copy Markdown
Member

Description

Two skill updates, plus the version bump that opens 20.9.0 for them. No engine code changes.

UI skill (melonjs-ui-and-text): its description listed "NineSliceSprite panels" among what it covers, but the body never mentioned them. New section, "Panels and boxes that stretch: NineSliceSprite":

  • both ways to make one, each taken from a shipped example: createSpriteFromName(name, { width, height }, true) from an atlas (the UI example's draggable panel), and the constructor from an image (the Text example's dialogue box)
  • the three things that trip people up: width / height are the size to stretch to and the constructor throws without them; insetx / insety default to a quarter of the image, not its border; the anchor is the centre
  • it resizes live through the width / height setters (checked in nineslicesprite.js: both write nss_width / nss_height, which draw() reads)

Audio skill (melonjs-audio): checked against every export of the audio module and the vendored backend. Added what positional sound needs and the skill did not say:

  • the listener is fixed at the origin: the backend has a listener pos() but nothing public reaches it, so positions must be passed relative to the player, every frame
  • the panner defaults assume metres: inverse / refDistance: 1 puts a source 100 px away at ~1%, so a sound positioned in pixels is near silent a few tiles out; set refDistance in pixels or scale positions down
  • stereo() and position() are exclusive per instance: both create the instance's one panner if it doesn't exist, and each only updates a panner of its own type (spatial.ts), so whichever runs first makes the other a silent no-op
  • new section "Effects on all game audio": reverb, echo, a compressor etc. inserted after getMasterGain(). Notes that setVolume / muteAll still apply, that a stream: true clip plays through an <audio> element and bypasses the master gain (voice.ts), and that per-clip effects are not reachable
  • hasAudio(), hasFormat(), runtime audio.load(), and the rate (0.5..4.0) and fade ranges
  • four symptom-table rows and new triggers (reverb, compressor, listener, refDistance, getMasterGain, ...); the description stays under the 1024-character limit (795)

Version: packages/melonjs/package.json and .claude-plugin/plugin.json both move to 20.9.0 together, with an unreleased [20.9.0] changelog section carrying both entries under Fixed.

Type of change

  • Bug fix
  • New feature
  • Documentation update
  • Performance improvement
  • Refactoring (no functional changes)

Checklist

  • I have read the Contributing Guide
  • My code follows the existing code style (pnpm lint passes)
  • I have tested my changes locally (pnpm test passes): not run; no source or test changes
  • I have added tests that cover my changes (if applicable): not applicable, documentation only
  • The build succeeds (pnpm build), as part of pnpm lint

Related issues

None. The audio audit surfaced two engine gaps that are not fixed here: the listener cannot be moved through the public API, and stereo() / position() fail silently on an instance whose panner is the other type.

🤖 Generated with Claude Code

https://claude.ai/code/session_0146cnBA4Z2zLzWYa3wjnYaW


Generated by Claude Code

claude added 2 commits October 7, 2026 06:11
The UI skill's description listed NineSliceSprite panels among what it
covers, but the body never mentioned them. It now shows both ways to make
one (createSpriteFromName with the nineSlice flag, as the UI example's
draggable panel does, and the constructor, as the Text example's dialogue
box does) and the three things that trip people up: width/height are the
size to stretch to and are mandatory, insetx/insety default to a quarter
of the image rather than its border, and the anchor is the centre.

melonjs and .claude-plugin/plugin.json move to 20.9.0 together, with an
unreleased 20.9.0 section in the changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0146cnBA4Z2zLzWYa3wjnYaW
…nd the rest of the API

Checked against every export of the audio module and the vendored backend:

- the listener is fixed at the origin and has no public setter, so
  positions must be passed relative to the player
- the panner defaults (inverse, refDistance 1) assume metres: a source
  100 px away plays at ~1%, so set refDistance in pixels or scale down
- stereo() and position() share one per-instance panner; whichever runs
  first fixes its type and the other silently does nothing
- reverb / echo / compressor on the whole mix: insert after
  getMasterGain(); streamed clips bypass the master gain, and per-clip
  effects are not reachable
- hasAudio(), hasFormat(), runtime audio.load(), rate and fade ranges
- four new symptom-table rows, and triggers for effects and listener

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0146cnBA4Z2zLzWYa3wjnYaW
Copilot AI balanced review requested due to automatic review settings October 7, 2026 06:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@obiot
obiot merged commit d31bb8c into master Oct 7, 2026
6 checks passed
@obiot
obiot deleted the claude/exciting-allen-xjjbhb branch October 7, 2026 07:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants