원클릭으로
visual-test
How to visually validate scenes, characters, and animations using the Playwright screenshot pipeline
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
How to visually validate scenes, characters, and animations using the Playwright screenshot pipeline
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use this skill whenever introducing a new Go programming concept that needs to be explained visually to beginners. Triggers when the user asks to explain, illustrate, animate, or teach any Go concept — including but not limited to: variables, functions, packages, imports, structs, interfaces, goroutines, channels, error handling, maps, slices, pointers, closures, or methods. Also triggers when the user says things like "add a new scene", "introduce X concept", "animate how X works", or "show the next concept". Always use this skill before writing any animation code — it defines the entire design system, analogy model, and scene structure that all Go animations must follow.
How to write and extend beginner mode content — pre-level concept briefings for new players
How to add new game content (chapters, bosses, story) to SIGNAL
Audit engine output patterns for common Go pitfalls — ensures every step has targeted feedback for Printf/Println, whitespace, format mismatches, and other gotchas
How to write and tune AI system prompts for Maya's 3-tier LLM backend
How to write zen rules for new SIGNAL levels — idiomatic Go detection, jolts, suggestions, testing
| name | visual-test |
| description | How to visually validate scenes, characters, and animations using the Playwright screenshot pipeline |
| allowed-tools | Read, Write, Edit, Glob, Grep, Bash |
Every sprite art change MUST be verified through the Playwright screenshot pipeline. This is the visual equivalent of a unit test — it catches proportion errors, missing props, broken animations, and rendering regressions.
test-visual/
├── render-scene.html # HTML with labeled canvases
├── render-scene.ts # Renders scenes + characters into canvases
├── visual.spec.ts # Playwright test — opens page, waits, screenshots
└── screenshot.png # Output — inspect this after every run
Run: npx playwright test test-visual/visual.spec.ts
Output: test-visual/screenshot.png
The test uses Vite to serve render-scene.html, which imports from src/lib/sprites/* directly. The page sets document.title = "RENDERED" when done — Playwright waits for this signal.
The screenshot currently includes:
| Canvas | Size | What it shows |
|---|---|---|
cell | 640x420 | Cell B-09 background only |
corridor | 640x420 | Corridor background only |
chase | 640x420 | Chase (alarm corridor) background only |
server | 640x420 | Server room background only |
composite | 640x420 | Maya + Guard standing in cell scene with debug floor line |
maya | 160x256 | Maya idle frame 0, standalone |
guard | 160x256 | Guard idle frame 0, standalone |
maya-walk | 960x256 | Maya walk-right, all 8 frames in strip |
guard-walk | 960x256 | Guard walk-right, all 8 frames in strip |
render-scene.html:<div>
<div class="label">NEW SCENE (640x420)</div>
<canvas id="new-scene" width="640" height="420"></canvas>
</div>
render-scene.ts:// Inside the scene loop — add the type to the array:
for (const type of ["cell", "corridor", "chase", "server", "new-scene"] as const) {
Add a frame strip canvas (width = frames x 120, height = 256):
<div>
<div class="label">MAYA RUN CYCLE (8 frames)</div>
<canvas id="maya-run" width="960" height="256"></canvas>
</div>
try {
const frames = paintMayaFrames("run-right", 3);
const canvas = document.getElementById("maya-run") as HTMLCanvasElement;
const ctx = canvas.getContext("2d")!;
ctx.imageSmoothingEnabled = false;
ctx.fillStyle = "#080e16";
ctx.fillRect(0, 0, 960, 256);
frames.forEach((f, i) => {
ctx.drawImage(f, i * 120, 0);
ctx.fillStyle = "#6effa0";
ctx.font = "9px monospace";
ctx.fillText(`F${i}`, i * 120 + 2, 250);
});
} catch (e) {
console.error("Error painting maya run:", e);
}
When adding characters to a new scene, always render a composite with a debug floor line:
const bg = paintScene("new-scene", W, H);
const mayaFrames = paintMayaFrames("idle", 3);
const ctx = compCanvas.getContext("2d")!;
ctx.drawImage(bg, 0, 0);
// Debug floor line
const floorY = Math.floor(H * 0.50); // match scene's wallBotY ratio
ctx.strokeStyle = "rgba(110,255,160,0.3)";
ctx.setLineDash([4, 4]);
ctx.beginPath();
ctx.moveTo(0, floorY);
ctx.lineTo(W, floorY);
ctx.stroke();
ctx.setLineDash([]);
// Character with feet anchored at floor + offset
const feetY = floorY + 60;
const mf = mayaFrames[0];
ctx.drawImage(mf, charX - mf.width / 2, feetY - mf.height);
After every npx playwright test test-visual/visual.spec.ts, open test-visual/screenshot.png and verify:
When authoring a new chapter that introduces a new scene or character state:
scenes.ts: paint the background and verify via screenshotReference the sprite-art skill for painting conventions (palette, layer order, prop sizing, walk cycle poses).
Blank canvas: Check the console output in the test — errors are logged with console.error. Usually a missing export or wrong function signature.
"No tests found": The spec file is visual.spec.ts, not screenshot.spec.ts.
Props disappear at game resolution: The visual test paints at 640x420 but in-game scenes are 1040x600 (viewport + padding). Props using fixed pixel sizes will be undersized at larger resolution. Always use proportional sizing (ch * multiplier).
Character floating in-game but grounded in test: Scene coordinates differ. The visual test is direct pixel placement. In PixiScene, actor.y is in scene coordinates (1040x600), and the sprite anchor is at feet (0.5, 1). Double-check scenes.ts actor positions against the scene's floor wallBotY ratio.