跳到正文
DEV Community· Gábor Mészáros·· 3 小時前AI 評分50

Claude Code 模組 Brickfall:特效豐富而不妨礙操作的打磚塊遊戲

Claude Code mods: Brickfall, a brick breaker that's loud without getting in the way

AI 導讀

Gábor Mészáros 為 Claude Code 製作 Brickfall,一款在對話紀錄旁運行的打磚塊遊戲,主打特效豐富但不妨礙操作。遊戲每幀傳送約 58,000 個像素,會按繪製速度調整清晰度,最低約 29,000 個像素;滑鼠控制球拍,指標離開畫面後遊戲會稍後暫停。

正文

After the Minesweeper and Doom, the third game in the arcade is a brick breaker after Arkanoid. The brief was one word: louder. Sparkle, big numbers, things raining down, a backdrop that shimmers. Brickfall plays in a pane beside the transcript while Claude works.

Brickfall in a Claude Code pane while Claude documents a small project and runs its tests

/bricks opens the pane. In kitty or Ghostty the field is a real picture; anywhere else it is drawn in quadrant block characters, four pixels a cell. You steer with the mouse, and there are thirteen kinds of capsule (laser, split, lightning, a giant ball, a shield of light...), gems that build toward a FEVER of double points, volt bricks that blow up their neighbours in chains, and ten rounds that come round again faster.

Loud, but never in the way

Every hit lands: light bursts where the brick was, the brick swells and burns out, the walls flash its colour, and a big number flies off it. My first loud version also shook the screen. It looked great in a screenshot and was miserable to play, because you can't catch a ball that jumps around with the field. The shake went, and two rules stayed:

  • nothing moves the field or stops the play, however much is going off
  • the ball, the paddle and anything falling are drawn on top of every effect, so what you need to catch stays in sight

Every pixel goes through Claude Code

Doom's frames never touch Claude Code: the engine writes a file and Claude Code hands kitty the path. Brickfall has no engine. The game runs inside the mod, so each frame is RGBA bytes handed to an Image:

state.rgba = toRgba(canvas, state.rgba ?? undefined)
state.source = { rgba: base64(state.rgba), width: canvas.w, height: canvas.h }

That makes sharpness a budget. kitty stretches the picture to fill the pane and smooths it as it goes, so the picture is only as sharp as the pixels you send, and every pixel crosses into the terminal on every frame. Brickfall sends about 58,000 a frame:

export const IMAGE_PIXELS = 36000
export const QUALITY = [1.6, 1.25, 1, 0.8] as const

On a busy machine it gives up a little sharpness, never below half (about 29,000), and only when frames stay slow, so a burst of fireworks never costs it. It wins the sharpness back as soon as the sharper step would still draw in time:

const fits = sharper !== null && (cost * sharper) / here < FRAME_BUDGET_MS * 0.75
const slow = cost > FRAME_BUDGET_MS ? pace.slow + 1 : 0
const quick = fits ? pace.quick + 1 : 0
if (slow >= PACE_FRAMES.down && pace.quality < QUALITY.length - 1) return { quality: pace.quality + 1, slow: 0, quick: 0 }
if (quick >= PACE_FRAMES.up) return { quality: pace.quality - 1, slow: 0, quick: 0 }

45 slow frames to step down, 30 quick ones to step back up. An earlier version kept its sharpness fix to the first round, and later rounds went soft; stepping both ways fixed it.

The paddle follows the pointer

In Claude Code's fullscreen layout (CLAUDE_CODE_NO_FLICKER=1) the terminal reports every pointer move, not just clicks and drags. An invisible Client lies over the picture and posts where the pointer is, and the paddle goes there:

if (pad.x !== null && pad.isInside !== false) aim(g, pad.x * W)
if (pad.isInside === false) state.awaySince ??= Date.now()

Move the pointer off the field to read Claude's answer and the game pauses after a moment, so the ball isn't lost while you look away. Bring it back and play goes on. The keys work too (a and d), but a terminal never says when a key comes up, so a held key moves in steps. The mouse is how it's meant to be played.

What recording the clip taught me

The clip above shows Claude reading three files, writing a DOCS.md and running the tests while the game plays. The first takes stuttered: the field froze for over half a second whenever Claude wrote its file.

It wasn't the game. I recorded control takes and logged Claude Code's main-thread CPU four times a second:

take effects Claude working longest freeze
1 on yes 567 ms
2 off yes 733 ms
3 on no 233 ms (the serve pause)

Both freezes landed on the second Claude Code drew its 16-line file write, with the main thread at 92–100% for about three quarters of a second. While it is drawing a big tool result, a mod can't paint. So if you build a mod with animation, expect the hitch when Claude writes a long file. And if you record one, start the game after the big writes.

What it touches

It reads and changes nothing the model sees. claude plugin validate lists every hook and call before any of its code runs:

❯ ./register.ts hooks: session.start, command.run{command=bricks}, ui.render{component=Pane}, ui.message, ui.close, session.end

No prompt, tool or attachment hook, no network call, no child process. The best score is kept in the plugin's own store.

Play it

In a Claude Code session:

/plugin marketplace add reporails/arcade
/plugin install brickfall@reporails-arcade

Then start Claude Code in the fullscreen layout, which the mouse needs, and run /bricks:

CLAUDE_CODE_NO_FLICKER=1 claude

Mods load by default from Claude Code 2.1.287. Use kitty for the real picture; Ghostty speaks the same protocol but I haven't tried it, and every other terminal gets the blocks. It has been played in kitty on Linux, and its 36 tests pass in CI on 2.1.285 and 2.1.288. If you play it on a Mac, Windows or Ghostty, tell me how it went.

The code is MIT, in reporails/arcade on GitHub.

來源:DEV Community · dev.to