Within the asset paths allowed by the current Phaser Work Item, convert a set of independent transparent PNG frames intoanchor-stablehorizontal spritesheets and a Phaser preload/animation contract. This Skill only handles deterministic raster normalization, packing, and machine quality gates; it does not replace the $phaser4-game-workflow-control scope, risk, and evidence gates.
Entry point
node <skill-dir>/scripts/frame-animation.mjs --help
The minimal invocation is as follows; the output directory must be included in the current Work Item's allowed paths in advance:
node <skill-dir>/scripts/frame-animation.mjs `
--input-dir art/hero/idle `
--output-sheet public/assets/hero-idle.png `
--output-report evidence/hero-idle.frame-animation.json `
--animation-key hero-idle `
--texture-key hero-idle-texture `
--frame-rate 12 `
--padding 2 `
--loop
All regular files in the input directory must be PNGs, and frames are sorted by filename in natural order (for example, frame2.png before frame10.png ). At least two frames are required; empty alpha frames, invalid PNGs, writing output back to input frames, and overwriting existing output by default will all block, and only an explicit --force allows overwriting existing non-input output.
The script uses by default ground-contact: take the robust median of visible x in the bottom contact band of the alpha bounding box as the root anchor, and only perform integer translation: no scaling, no stretching, no frame interpolation, and no cropping of the visible subject. Grounded idle/walk uses the default mode; jump/airborne must choose fixed-canvas to preserve the existing displacement trajectory within the canvas, or choose explicit and provide a per-frame semantic root anchor via --anchor-file . All alignment modes compute a fixed cell based on the maximum bounding extent around the root anchor, eliminating accidental jumps caused by differences in transparent margins in the source canvas.
frame-animation.mjs It can also be used as a Node API, with the main entry being packCharacterFrames(options); quality failures will still write candidate PNGs and a JSON report, but return exitCode=3. Invalid input returns exitCode=2, success returns exitCode=0. For detailed fields, metrics, and threshold semantics, see quality contract。
Phaser integration
In the report, phaser.preload can be directly mapped to this.load.spritesheet,phaser.anims can be directly mapped to this.anims.create, and Sprite should be fixedly called according to phaser.sprite_origin for sprite.setOrigin。repeat=-1 means loop,repeat=0 means play once. Before formal integration, it is still necessary to sample and check animation switching, event frames, hit detection, and feedback timing over time in the Phaser runtime; this Skill's machine gate cannot prove that the dynamic presentation already meets product visual acceptance.
Control plane boundary
Control plane boundary: can propose, can review, can modify within the scope of the current user task's Work Item, and must return to $phaser4-game-workflow-control audit and state transition.
The control plane is exclusively held by $phaser4-game-workflow-control : this Skill only generates candidates and reports within the current Work Item's Implementation Package, A level, and allowed paths, and does not change global state, create additional approvals, or directly modify main game code. If the anchor rules, frame order, loop semantics, or visual baseline change, it should return to the control plane to update the plan and re-validate, rather than overriding facts in the report.