POUNCE// README

Building a browser cat platformer with a hand-built tile level · play the game →

About Pounce

Pounce is a free browser side-scrolling platformer. The player picks one of four cats and bounds through three hand-built levels (960, 720, and 720 tiles wide) on the way to a cozy bed. Bonk boxes for cat-food cans (grow bigger) or magic fish (unlock fishbone projectiles), stomp dogs and crawling kids, shoot or pounce the wasps that fly above. Vanilla HTML, CSS, and JavaScript on top of an HTML5 Canvas with Web Audio for both sound effects and a chiptune music loop. No build step, no framework, no runtime dependency beyond Google Fonts and Supabase for the global high-score leaderboard.

The project shares its DNA with cat-ski: same author, same plain-prose voice, same free deploy toolchain (GitHub → Vercel), same four cat palettes. Source is at github.com/ashtonmorrow/bros. The production URL is pounce.mike-lee.me.

Pounce sits alongside the other small browser experiments at mike-lee.me: cat-ski (a SkiFree tribute), pear, and go. They all share the same vanilla stack and ship-on-push deploy pattern.

How to play

The cat starts on a flat patch of grass. Walking right takes the player through a four-movement level structured in kishōtenketsu acts: a tutorial, a development section with the first floating-platform challenges, a vertical climb across disconnected platforms, and a rooftop run that recovers the pace before the goal staircase. Each level ends at a cozy bed on a raised wooden plateau. Levels 2 and 3 follow the same beat structure with their own themes (a wasp-heavy night garden, a final-sprint homecoming).

InputAction
A / D or ← / →Move
W, ↑, or SpaceJump
S or ↓ (in mid-air)Down-pounce — fast slam, instant kill on impact
XThrow a fishbone (only in shooter state, after eating a magic fish)
PPause
M / NToggle music / sound effects (also buttons below the game frame)
CToggle high-contrast mode
R, Enter, or SpaceRestart after a game over or win
1 / 2 / 3 (title screen)Jump straight to that level if unlocked
E / H (title screen)Switch difficulty to easy / hard (normal is the default)
← / → or click (title screen)Cycle / select the cat picker

Standard-layout gamepads are also auto-detected: A jumps, X shoots, B pounces, Start advances, Select pauses, the left stick or D-pad moves. On phones and tablets, on-canvas touch buttons appear automatically.

The cat starts small. Bonking a red ?-style box from below pops a cat-food can; eating it grows the cat to big, which absorbs one extra hit before death. Bonking another box while big pops a magic fish; eating it grants the shooter state and the X-key fishbone projectile that arcs, bounces off the floor up to four times, and one-shots any enemy on contact. Hits revert the cat all the way back to small, Mario-style.

Three obstacle animals oppose the cat. Dogs walk and patrol the ground, can be stomped from above or shot. Crawling children are shorter and slower; their hitbox is low enough that a normal jump usually clears them. Wasps fly in a sine wave and cannot be stomped from a regular jump — you have to either shoot them with a fishbone or come down on them with a down-pounce. Down-pounce one-shots anything, even wasps, and pays out 200 points instead of the standard 100 stomp bonus.

Score adds up across treats (10 each), yarn balls (50 each), pop-up cans (100), magic fish (500), stomps (100), pound-stomps (200), and projectile kills (200). Time bonus on the level-complete screen at 5 points per second remaining. A pit fall costs a life and respawns the cat at the start; the cat starts with three lives.

The top three high scores are global, backed by a Supabase table with a localStorage cache so the strip paints instantly even before the network has responded. If your final score cracks the top three, a five-character name prompt appears.

How the game is built

The game is split across four small JavaScript files plus an index.html entry point. There is no build step, no framework, and no runtime dependency. The constraint of staying on a vanilla stack is deliberate: it keeps the deploy pipeline as small as possible (a git push triggers an automatic Vercel rebuild that takes seconds), and it forces honest engineering decisions because no library is going to paper over a bad choice.

ComponentImplementation
RenderingHTML5 Canvas at 800 × 480, image-rendering: pixelated
Game loopVanilla JS, requestAnimationFrame, dt clamped to 50 ms
PhysicsPer-axis tilemap collision; gravity 0.5 px / frame²
Variable jumpReduced gravity (0.275) while ascending and jump is held
Forgiveness0.10 s coyote time, 0.10 s jump buffer
Down-pouncevy snaps to 14 (faster than gravity terminal velocity), vx locked to 0; instant kill on impact, +200 score
World spritesProcedural pixel art via ctx.fillRect
Cat spritesVector primitives, four palettes shared with cat-ski; small & big size sets baked at startup
SFXWeb Audio API, OscillatorNode tones
MusicWeb Audio chiptune loop — square-wave melody + triangle bass over an I–V–vi–IV progression in C, 132 BPM, 4 bars; 1.4× panic-mode tempo at the last 30 seconds
LeaderboardSupabase (anon key, RLS-protected) for the global top-3; localStorage cache so the strip paints instantly
State persistencelocalStorage for selected cat, music preference, leaderboard cache, last-used name
PWAmanifest.json + sw.js; network-first for HTML, cache-first for assets, bumped CACHE_NAME on each release
HostingVercel, deployed from GitHub on push

Designing the levels

Pounce ships three levels — MEADOW WALK (960 tiles wide), NIGHT GARDEN (720), and HOMEWARD BOUND (720). Each tile is 32 × 32 pixels in the world; tilemaps are 15 rows tall. The horizontal camera follows the cat and clamps at the world's left and right edges so the player can't walk off-screen behind the start or past the goal. The camera also leads the cat's facing direction by a small eased look-ahead so the player can see what's coming.

The level data is not a hand-typed ASCII grid. It is built programmatically in js/level.js through a thin builder API (ground, plat, ent, treatArc) that writes features into a 2D char array. Each level function builds its own grid with the builder's makeBuilder(width) factory, so the three levels don't accidentally write into one another. The grids are exposed via window.LEVELS for game.js to load.

Each level follows the four-act kishōtenketsu framework popularised by Koichi Hayashida at Nintendo (intro → development → twist → conclusion), and each section is annotated with which of the six 2D platformer level design patterns it uses (Guidance, Foreshadowing, Safe Zone, Layering, Branching, Pace Breaking).

LevelWidthTheme
1. MEADOW WALK960 tiles The full tutorial-through-mastery arc. Four movements: tutorial-and-pits, forest gauntlet with a wasp corridor, cliff approach with a vertical staircase, and a rooftop run with a mid-air stepping plat over a wide canyon. Ends at a goal staircase to the bed. Two hidden sky routes for curious players. Tutorial hints fade in along the early stretch to teach jump, pounce, and shoot.
2. NIGHT GARDEN720 tiles Wasp-heavy. The hidden-sky-route trick from level 1 gets re-used as the required path through one stretch (the row-3 plateau is the only solid surface for thirty tiles; falling = pit death). Followed by a lily-pond movement (four floating pads over a wide pit), a hedge tunnel funneling the cat under a wasp swarm, and a twilight stair into the goal.
3. HOMEWARD BOUND720 tiles The trilogy's climax. No tutorial — the player has earned this. Builds to a long “boss room” flat packing every enemy type into one space with a low ceiling, a climactic vertical staircase with a sentry wasp at the apex, a hidden rest spot above the descent valley, and a calm runway into the final cozy bed.

The cat's running jump can clear about six tiles flat (or seven and a half with a full variable-jump hold) and reach about five and a half tiles vertically. Every pit in every level was sized to stay inside those bounds, with mid-air stepping platforms placed in any gap wider than six tiles. A programmatic audit walks each level after build, flagging any pit that exceeds the six-tile flat-jump threshold without a step inside it — the build is rejected if any survives.

The four cats

The player picks a cat on the title screen. Four palettes are available: SHADOW (black), WHISKERS (tabby), PATCHES (calico), and GINGER (orange). The drawing code is the same vector function used in cat-ski, parameterised by a palette object. A single set of geometry produces all four cats.

CatPalette character
SHADOW (black)Pure-black fur, gold eyes, no markings
WHISKERS (tabby)Warm orange fur with mackerel stripes and a forehead M
PATCHES (calico)White base with orange and black irregular patches; cool blue eyes
GINGER (orange)Bright orange tabby with green eyes

The cat is drawn front-facing rather than as a side-view sprite, so it doesn't flip when you change direction. That is a deliberate trade-off: the vector geometry doesn't survive a horizontal flip cleanly because markings and patches mirror with it. A front-facing chibi cat reads correctly to the player without the flip.

Working with Claude

The project was built with Claude as a coding collaborator, in roughly the same workflow used to build cat-ski: a long prompt at the start that lays out the constraints (vanilla stack, no copyrighted assets, original art, keep it small enough to swap in better art later), then iterating in short cycles where each cycle adds one feature, runs a verification step (node --check on every JS file plus a programmatic level sanity check), and ships.

The character picker is a useful example. The first version of the cat sprite was procedural pixel art drawn with fillRect. It read as "small orange thing" but not unmistakably as a cat. Rather than redo the pixel art, the fix was to share the existing vector drawCat function from cat-ski. Claude pulled the function and its four palettes from the cat-ski source, baked each palette × state combination into a small canvas at startup, and wired a swatch-and-arrow picker into the title screen. The change took one iteration because the constraint — "the cat needs to look like a cat at all four colours without forking the drawing code" — was the same constraint cat-ski had already solved.

How you can build this yourself

You don't need much. The toolchain Pounce uses is free or open source.

What forTool
EditorAny text editor — VS Code, Sublime, even TextEdit will work
Coding collaboratorClaude
Version controlGitHub (free for public repos)
HostingVercel (free tier; auto-deploys from GitHub)
Local previewpython3 -m http.server or npx serve
Browser dev toolsBuilt into Chrome / Safari / Firefox

The single most useful constraint is to start without a framework. The surface area of vanilla HTML / Canvas / Web Audio is small enough to learn in an afternoon, and the resulting game is small enough that you can deploy a change in under a minute and reload to see it. If a feature starts asking for a framework, that's signal that the feature is too big for this kind of project; pick a smaller version of it.