Point at any game codebase (or a new game) to dramatically upgrade its graphics — derive a style guide, generate individual sprite assets via fal.ai, replace flat/placeholder art, and add multi-layer parallax depth (sky / clouds / hills / buildings / playfield / foreground) with procedurally-placed individual sprites, never baked looping strips.
Turn a functional-but-plain game into one that looks hand-crafted. This skill
covers three jobs, usually run in order:
Style guide — derive (or define) the game's visual language and write it
down so every asset generated afterward matches.
Asset generation — generate every visual element as its own individual
sprite through the fal.ai pipeline, styled against a single anchor.
Depth & parallax — rebuild the scene as layered, procedurally-dressed
parallax so the world has depth (side-scrollers especially), plus a juice
pass of cheap code-level polish.
Works on an existing codebase (audit → enhance in place) or a brand-new game
(define style first, build layered from day one). Engine-agnostic: the recipes
apply to HTML canvas / JS, Phaser, SwiftUI/SpriteKit, Unity 2D, Godot — only
the integration syntax changes.
Phase 0 — Audit (existing codebase only)
Before generating anything:
Inventory the visuals. Find every drawn element: backgrounds, player,
enemies, obstacles, pickups, UI chrome, particles. Note which are code-drawn
shapes (rects/circles), which are placeholder images, and which are baked
multi-object images that need splitting.
Map the scene graph. How is the background drawn? One image? A looping
strip? Is there any layering at all? Where's the render order defined?
Find the world clock. Identify (or plan) the single source of truth for
world scroll position — parallax hangs off exactly one clock.
List the sprite manifest. Write out every asset you'll generate, one
line each, grouped by layer. This manifest drives the whole job — every
entry becomes its own file. If the current art has a row of buildings baked
into one image, the manifest lists each building separately.
Back up any existing art before replacing it (e.g. copy to art/originals/).
Phase 1 — Style guide
Write a short STYLE.md (or a styles section) for the project before
generating asset #1. Every later prompt quotes from it. If the game already
has a look worth keeping, derive the guide from its best existing sprite; if
not, define one fresh. A proven default that reads great for casual games:
Hand-painted cartoon: thick warm (brown) outlines, saturated
kid-friendly colors, soft painterly shading. No flat vector, no
gradients-as-style, no photo textures. (Swap this line for the game's own
style if it has one — pixel art, flat-shade, etc. — the process below is
the same.)
Palette anchors: pick 5–7 named colors with jobs, e.g. warm wood browns,
a teal/sea-green secondary, cherry red for danger, leafy green for success,
gold/amber for score & celebration, cream for cards/UI. Write hex/RGB values
down.
Semantic color is sacred: red = danger/wrong, green = correct/go,
amber = time, gold = celebration. Never swap these.
Focal hierarchy: the background must be calmer than the playfield —
muted detail, a light pool at the play area's center, and a code vignette
(radial gradient, clear → black ~0.30 opacity, centered on the action). If
the background competes, dim the background — don't brighten the subject.
The lighting rules (what separates "cohesive" from "clipart")
Raw, unmodulated hues read cheap no matter how nice the shapes are. Every
sprite in the game obeys the same five points:
Shared warm undertone in every color — the whole game is "warm light
falling on saturated things".
One light direction — pick where the sun/lamp is and light every sprite
to it: bright highlight planes on the lit side, crisp cool shadow shapes
opposite, a thin warm rim light.
Real value range — distinct shadow and highlight shapes, not one flat
mid-tone (anime-style cel shading, not airbrush mush).
Aerial perspective — the farther back a parallax layer sits, the
lighter, hazier, and more desaturated its sprites. This alone sells depth.
A code light grade — a low-opacity warm radial wash from the light
source plus the gentle vignette, drawn over the composed scene. Cheap, and
it fuses separately-generated sprites into one lit world.
Phase 2 — Asset generation pipeline (fal.ai MCP)
The cardinal rule: one sprite = one object
Never generate a composite. Not a "row of buildings", not a "forest strip",
not a "background with trees". If the manifest says skyline, generate
building-1, building-2, building-3… as separate assets, each on its own
transparent canvas, and let code compose them procedurally (Phase 3). This
is what makes the world regenerable, recolorable, resizable, and non-repeating
piece by piece.
Pipeline steps
Generate the style anchor first. Pick the single most important sprite
(usually the player or the hero object) and iterate on it until it nails
the style guide. Everything else is generated against it.
Generate with fal-ai/nano-banana-pro — for every subsequent asset,
ALWAYS pass the anchor (or the best sprite of the same set) via /edit
(image_urls) as the style reference: "using the exact same hand-painted
cartoon style as this…". Edits preserve composition, so tuned layouts
survive recolors and relights. Chain the first good result of a set as the
style anchor for the rest of that set.
Cut out with pixelcut/background-removal, sync_mode: false always.
Edited sprites come back flattened — re-cutout every time, even after a
small edit.
Trim to the alpha bounding box and downscale. ~512px on the long edge
is plenty for most in-game sprites; go larger only for full-screen
backdrops.
Interchangeable set pieces share one footprint. Variants that slot into
the same spot (buildings in the skyline slot, trees in the treeline slot)
all render at one fixed dimension on the shared axis so any of them fits
flush; vary the other axis by kind (buildings vary height, never base
width). Composite paired icons onto identical canvases so they render at
the same scale in code.
Moving parts are separate sprites. Anything that animates independently
(a wheel, a flag, a door, a character's held item) is its own asset, and
the parent is generated WITHOUT it — prompt "empty space where the X would
go".
Animated characters get a real frame cycle, not a two-frame swap. A
running/walking/flapping character needs a proper cycle — for a run: 4
frames minimum (contact → pass → opposite contact → opposite pass).
Generate frame 1 first and approve it, then generate EVERY other frame as
an edit of frame 1 (not chained frame-to-frame, which drifts), with a
prompt that pins everything: "keep the character ABSOLUTELY IDENTICAL —
same head angle, same expression, same arms, same tail, same colors, same
size and position on the canvas. ONLY redraw the legs: this is the passing
frame — both legs gathered under the body, near knee bent high…". Naming
only the moving limbs is what keeps the rest stable across frames.
Normalize the whole cycle onto one shared canvas (bottom-anchored for
ground characters) so frames don't jump, and key frame advance to world
travel (distance moved), not wall time, so the cycle always matches
ground speed. Pick one frame (usually a tucked pass pose) as the held
airborne/jump pose.
No text zones baked into sprites. No sign plates, labels, or blank
panels waiting for numbers — bodies stay clean and ONE code-rendered
card/label carries any words. Baked plates double up with the UI, can't
animate, and lock layout to artwork.
Reuse beats regenerate. Mirror + hue-shift one arrow instead of
generating a second "similar" arrow — pixel-identical components read as
deliberate design; near-duplicates read as sloppiness.
Relight in place to restyle a set. To change the whole game's mood,
edit each existing sprite ("same building, same shapes, but lit by warm sun
from the upper right…") — composition survives, so no layout retuning.
Big soft-edged set pieces (mountains, fog banks, clouds) must be
generated as ISOLATED silhouettes — prompt "plain solid white
background all around; the landform must not touch the left or right
canvas edges; only the flat bottom edge is straight". Painted aerial
haze that runs to the canvas edge survives background removal as a
semi-opaque RECTANGLE, and the sprite renders as a hard-edged slab in
the scene. If a generation comes back haze-to-edge, don't try to rescue
it in processing — regenerate with the isolation wording (chain from a
correctly-composed sibling if one exists). As a safety net when
processing hazy sprites: dissolve near-white pixels (alpha ×
(242 − min(r,g,b)) / 30, clamped) and feather the outer ~9% of the
left/right edges to zero alpha so soft slopes dissolve instead of
ending in a wall.
Manifest order that works
Generate in this order so each layer can reference the ones before it:
style anchor → playfield objects → background set pieces (per-layer, far to
near, applying aerial-perspective desaturation as you go) → foreground props →
UI/affordance sprites (arrows, guides, icons — painted in-style, not system
icon fonts).
Phase 3 — Scene construction & parallax
The layer stack
Rebuild the scene as ordered layers, back to front. For a side-scroller the
canonical stack (with scroll factors relative to the playfield = 1.0):
#
Layer
Factor
Content
1
Sky
0–0.05
Painted gradient/backdrop; essentially fixed
2
Clouds
~0.1
Individual cloud sprites, plus their own slow self-drift
3a
Far hills / mountains (required)
0.10–0.15
Big hazy desaturated range pieces, near-continuous chain
3b
Near hills / mountains (required)
0.25–0.35
Warmer, more contrast, still calmer than the playfield
4
Buildings / trees (mid)
0.4–0.6
Individual set-piece sprites, one footprint per slot family
5
Playfield / ground plane
1.0
The gameplay: player, obstacles, pickups, ground
6
Foreground whip layer
1.5–1.8
Occasional props that sweep past close to camera, slightly blurred
The hills are not optional decoration — they ARE the depth. Every outdoor
scrolling scene includes the two hill/mountain layers, and they should be
dominant: sprite heights around 0.30–0.50 of screen height for the far
range and 0.22–0.36 for the near ridge, with LOW skip rates and spacing well
under a sprite width so pieces overlap into continuous ranges rather than
isolated bumps on the horizon. Two ranges sliding at different factors is
what sells parallax; one timid strip of hills reads flat. Differentiate them
with aerial perspective: far = palest, haziest, least contrast; near = warmer
and more detailed but still visibly calmer than the playfield.
Readability rule: the background must never impersonate an obstacle. If a
sprite family is used as (or resembles) something the player must react to —
the cacti they jump, the rocks they dodge — it must NOT appear in any
background or mid layer at any size: a small background cactus reads as a
thing to jump and causes false inputs. Dress background layers only with
shapes the gameplay never uses (mountains, dry trees, ruins, clouds). The
foreground whip layer is the one exception: obstacle-family props are fine
there because big + blurred + faster-than-gameplay reads as camera depth, not
threat — the blur is mandatory for that reason.
For a non-scrolling game the same stack still applies as static depth:
backdrop → object layer → foreground framing props that crop off the screen
edge (depth without 3D). In all cases nothing interactive is ever baked into
the background, and every playfield sprite is its own element — its own asset,
its own view/node, its own layout anchor — so any piece can be regenerated,
resized, or repositioned without touching the rest.
Parallax rules
One constant world clock drives every layer's offset
(offset = worldX × factor). The drift never speeds up, slows down, or
jumps for any game event — only the focal element moves on events. A steady
world is what makes the moving parts read.
Mid-scene dressing is individual sprites placed procedurally — never one
giant looping strip. Strip loops need mirror-tiling and the mirrored twins
are visible. Mirror-tiling is acceptable ONLY for genuinely uniform textures
(a plain ground fill, a flat wall).
Procedural placement recipe:
The world is divided into slots per layer (e.g. a building slot every
~220 world units).
hash(layerId, slotIndex) — any cheap deterministic integer hash — picks
the variant, the spacing jitter (±30–40% of slot width), the size wobble
(±10%), and an occasional skip (empty slot). Deterministic means the same
scenery reappears if the player backtracks, with zero storage.
Spawn slots a screen ahead of the camera, cull a screen behind. Never
store the whole world.
Adjacent slots avoid repeating the same variant (re-hash or +1 the pick).
Foreground props sweep past occasionally — roughly one per long cycle,
not a constant stream — with a slight blur for depth of field, and they
NEVER hit-test. Gameplay input is always the topmost interactive layer.
Layers resize from their anchored seam. A strip pinned to the horizon
grows UPWARD when scaled — shared edges between layers must never move, or
gaps flash at the seams on resize.
Aerial perspective per layer (from the style guide): far layers get the
lighter/hazier/desaturated versions of the sprites. If needed, apply a cheap
per-layer tint/haze overlay in code instead of regenerating.
Camera = a focus value, not teleports. Interpolate the camera/world
position along a focus index so rolling/walking parts can read the
interpolated travel each frame and match ground speed exactly (in SwiftUI
that means Animatable; in a canvas loop it's just per-frame lerp).
Polish pass (cheap, high-impact)
Never open static. A scene whose fantasy has motion opens already
moving (ease-out, no delay) — the player must never see the world "start
up".
Idle life on the focal element — a gentle bob, an ambient particle loop —
with ground-contact parts staying planted.
The code light grade from Phase 1: warm radial wash + vignette over the
composed scene. Do this last; it's what fuses the layers.
Landings never overshoot. Anything dropping onto a surface: ease-in fall
that stops DEAD at contact, a quick squash (≈0.78 wide / 1.12 tall, anchored
at the bottom, ~0.07s), a dust burst at the contact seam (anchor the burst
slightly BELOW the visual seam — burst patterns fan upward), then spring
back.
Reactions are layered: instant snap within one frame of input
(~0.04s) → rattle/jitter → brightness flash → recover. Input registers on
touch-down/press, never on release, and the first visual reaction lands
within one frame.
Settled things freeze forever. Physics debris drops, tumbles, settles —
then becomes immovable. Nothing idles, twirls, or jitters in the background
competing with the playfield.
Phase 4 — Integration & layout conventions
All positions are fractions of the viewport/scene size in a per-scene
Layout constant table — never absolute pixels. The playfield focal point
sits around (0.5 × width, 0.55–0.72 × height) for portrait; center-weight
horizontally for landscape scrollers.
One sprite, one node/view, one layout anchor. The file structure mirrors
the manifest.
Render order is the layer stack, explicit and in one place — not
emergent from insertion order scattered across files.
Time bases live in state, not locals. A phase anchor or start-time
captured as a plain local in render code resets on every re-render and snaps
animation clocks to zero (in SwiftUI: @State; in JS: module/instance
state, not per-frame Date.now() diffs from a re-created base).
Web-specific: preload the sprite manifest before first paint, use
image-rendering appropriate to the style, draw layers to the main canvas
in stack order (or use stacked canvases/CSS transforms for the far layers if
the game is DOM-based).
Verification
Don't call it done from stills alone:
Screenshot each layer toggled on cumulatively (sky → +clouds → +hills →
+buildings → +playfield → +foreground) to check seams, scale, and aerial
perspective steps.
Record video / animated capture of the world scrolling — stills cannot
judge parallax feel, easing, or drift steadiness. Watch for: mirrored
twins, variant repeats in adjacent slots, seam gaps on resize, foreground
props stealing attention.
Squint test: blur your eyes at a screenshot — the playfield focal point
must still be the obvious brightest/highest-contrast region. If a
background layer wins, dim it.
Checklist
Visual inventory + sprite manifest written (every object its own line)
STYLE.md: style sentence, palette anchors with values, semantic
colors, light direction
Style anchor sprite generated and approved
All manifest sprites generated via the pipeline (edit-with-reference →
background-removal → trim → footprint-normalized), originals backed up
No composite sprites anywhere — every building/tree/cloud/prop is its
own cutout
No baked text/label zones in any sprite
Layer stack implemented with per-layer scroll factors off ONE world
clock — BOTH hill/mountain layers present and dominant, no
obstacle-lookalike sprites in any background or mid layer
Animated characters have a full frame cycle (4+ frames for a run),
frames edited from frame 1, shared canvas, keyed to world travel
Foreground whip layer: occasional, blurred, never hit-tests
Aerial perspective across layers; code light grade (warm wash +
vignette) over the composed scene
Opens already in motion; idle life on the focal element; landing
squash recipe wherever things drop
Layout as viewport fractions; seams anchored; resize-safe
Verified with layer-by-layer screenshots AND a scrolling video capture
1---2name: game-assets-enhancement3description: Point at any game codebase (or a new game) to dramatically upgrade its graphics — derive a style guide, generate individual sprite assets via fal.ai, replace flat/placeholder art, and add multi-layer parallax depth (sky / clouds / hills / buildings / playfield / foreground) with procedurally-placed individual sprites, never baked looping strips.4---56# Game Assets Enhancement78Turn a functional-but-plain game into one that looks hand-crafted. This skill9covers three jobs, usually run in order:10111. **Style guide** — derive (or define) the game's visual language and write it12 down so every asset generated afterward matches.132. **Asset generation** — generate every visual element as its **own individual14 sprite** through the fal.ai pipeline, styled against a single anchor.153. **Depth & parallax** — rebuild the scene as layered, procedurally-dressed16 parallax so the world has depth (side-scrollers especially), plus a juice17 pass of cheap code-level polish.1819Works on an existing codebase (audit → enhance in place) or a brand-new game20(define style first, build layered from day one). Engine-agnostic: the recipes21apply to HTML canvas / JS, Phaser, SwiftUI/SpriteKit, Unity 2D, Godot — only22the integration syntax changes.2324---2526## Phase 0 — Audit (existing codebase only)2728Before generating anything:29301. **Inventory the visuals.** Find every drawn element: backgrounds, player,31 enemies, obstacles, pickups, UI chrome, particles. Note which are code-drawn32 shapes (rects/circles), which are placeholder images, and which are baked33 multi-object images that need splitting.342. **Map the scene graph.** How is the background drawn? One image? A looping35 strip? Is there any layering at all? Where's the render order defined?363. **Find the world clock.** Identify (or plan) the single source of truth for37 world scroll position — parallax hangs off exactly one clock.384. **List the sprite manifest.** Write out every asset you'll generate, one39 line each, grouped by layer. This manifest drives the whole job — every40 entry becomes its own file. If the current art has a row of buildings baked41 into one image, the manifest lists *each building* separately.4243Back up any existing art before replacing it (e.g. copy to `art/originals/`).4445---4647## Phase 1 — Style guide4849Write a short `STYLE.md` (or a styles section) for the project before50generating asset #1. Every later prompt quotes from it. If the game already51has a look worth keeping, derive the guide from its best existing sprite; if52not, define one fresh. A proven default that reads great for casual games:5354- **Hand-painted cartoon:** thick warm (brown) outlines, saturated55 kid-friendly colors, soft painterly shading. No flat vector, no56 gradients-as-style, no photo textures. (Swap this line for the game's own57 style if it has one — pixel art, flat-shade, etc. — the *process* below is58 the same.)59- **Palette anchors:** pick 5–7 named colors with jobs, e.g. warm wood browns,60 a teal/sea-green secondary, cherry red for danger, leafy green for success,61 gold/amber for score & celebration, cream for cards/UI. Write hex/RGB values62 down.63- **Semantic color is sacred:** red = danger/wrong, green = correct/go,64 amber = time, gold = celebration. Never swap these.65- **Focal hierarchy:** the background must be *calmer* than the playfield —66 muted detail, a light pool at the play area's center, and a code vignette67 (radial gradient, clear → black ~0.30 opacity, centered on the action). If68 the background competes, dim the background — don't brighten the subject.6970### The lighting rules (what separates "cohesive" from "clipart")7172Raw, unmodulated hues read cheap no matter how nice the shapes are. Every73sprite in the game obeys the same five points:74751. **Shared warm undertone** in every color — the whole game is "warm light76 falling on saturated things".772. **One light direction** — pick where the sun/lamp is and light every sprite78 to it: bright highlight planes on the lit side, crisp cool shadow shapes79 opposite, a thin warm rim light.803. **Real value range** — distinct shadow and highlight *shapes*, not one flat81 mid-tone (anime-style cel shading, not airbrush mush).824. **Aerial perspective** — the farther back a parallax layer sits, the83 lighter, hazier, and more desaturated its sprites. This alone sells depth.845. **A code light grade** — a low-opacity warm radial wash from the light85 source plus the gentle vignette, drawn over the composed scene. Cheap, and86 it fuses separately-generated sprites into one lit world.8788---8990## Phase 2 — Asset generation pipeline (fal.ai MCP)9192### The cardinal rule: one sprite = one object9394Never generate a composite. Not a "row of buildings", not a "forest strip",95not a "background with trees". If the manifest says skyline, generate96building-1, building-2, building-3… as separate assets, each on its own97transparent canvas, and let *code* compose them procedurally (Phase 3). This98is what makes the world regenerable, recolorable, resizable, and non-repeating99piece by piece.100101### Pipeline steps1021031. **Generate the style anchor first.** Pick the single most important sprite104 (usually the player or the hero object) and iterate on it until it nails105 the style guide. Everything else is generated *against* it.1062. **Generate with `fal-ai/nano-banana-pro`** — for every subsequent asset,107 ALWAYS pass the anchor (or the best sprite of the same set) via `/edit`108 (`image_urls`) as the style reference: *"using the exact same hand-painted109 cartoon style as this…"*. Edits preserve composition, so tuned layouts110 survive recolors and relights. Chain the first good result of a set as the111 style anchor for the rest of that set.1123. **Cut out with `pixelcut/background-removal`**, `sync_mode: false` always.113 Edited sprites come back flattened — re-cutout every time, even after a114 small edit.1154. **Trim to the alpha bounding box and downscale.** ~512px on the long edge116 is plenty for most in-game sprites; go larger only for full-screen117 backdrops.1185. **Interchangeable set pieces share one footprint.** Variants that slot into119 the same spot (buildings in the skyline slot, trees in the treeline slot)120 all render at one fixed dimension on the shared axis so any of them fits121 flush; vary the *other* axis by kind (buildings vary height, never base122 width). Composite paired icons onto identical canvases so they render at123 the same scale in code.1246. **Moving parts are separate sprites.** Anything that animates independently125 (a wheel, a flag, a door, a character's held item) is its own asset, and126 the parent is generated WITHOUT it — prompt *"empty space where the X would127 go"*.1287. **Animated characters get a real frame cycle, not a two-frame swap.** A129 running/walking/flapping character needs a proper cycle — for a run: 4130 frames minimum (contact → pass → opposite contact → opposite pass).131 Generate frame 1 first and approve it, then generate EVERY other frame as132 an edit **of frame 1** (not chained frame-to-frame, which drifts), with a133 prompt that pins everything: *"keep the character ABSOLUTELY IDENTICAL —134 same head angle, same expression, same arms, same tail, same colors, same135 size and position on the canvas. ONLY redraw the legs: this is the passing136 frame — both legs gathered under the body, near knee bent high…"*. Naming137 only the moving limbs is what keeps the rest stable across frames.138 Normalize the whole cycle onto one shared canvas (bottom-anchored for139 ground characters) so frames don't jump, and key frame advance to **world140 travel** (distance moved), not wall time, so the cycle always matches141 ground speed. Pick one frame (usually a tucked pass pose) as the held142 airborne/jump pose.1438. **No text zones baked into sprites.** No sign plates, labels, or blank144 panels waiting for numbers — bodies stay clean and ONE code-rendered145 card/label carries any words. Baked plates double up with the UI, can't146 animate, and lock layout to artwork.1479. **Reuse beats regenerate.** Mirror + hue-shift one arrow instead of148 generating a second "similar" arrow — pixel-identical components read as149 deliberate design; near-duplicates read as sloppiness.15010. **Relight in place to restyle a set.** To change the whole game's mood,151 edit each existing sprite ("same building, same shapes, but lit by warm sun152 from the upper right…") — composition survives, so no layout retuning.15315411. **Big soft-edged set pieces (mountains, fog banks, clouds) must be155 generated as ISOLATED silhouettes** — prompt *"plain solid white156 background all around; the landform must not touch the left or right157 canvas edges; only the flat bottom edge is straight"*. Painted aerial158 haze that runs to the canvas edge survives background removal as a159 semi-opaque RECTANGLE, and the sprite renders as a hard-edged slab in160 the scene. If a generation comes back haze-to-edge, don't try to rescue161 it in processing — regenerate with the isolation wording (chain from a162 correctly-composed sibling if one exists). As a safety net when163 processing hazy sprites: dissolve near-white pixels (alpha ×164 `(242 − min(r,g,b)) / 30`, clamped) and feather the outer ~9% of the165 left/right edges to zero alpha so soft slopes dissolve instead of166 ending in a wall.167168### Manifest order that works169170Generate in this order so each layer can reference the ones before it:171style anchor → playfield objects → background set pieces (per-layer, far to172near, applying aerial-perspective desaturation as you go) → foreground props →173UI/affordance sprites (arrows, guides, icons — painted in-style, not system174icon fonts).175176---177178## Phase 3 — Scene construction & parallax179180### The layer stack181182Rebuild the scene as ordered layers, back to front. For a side-scroller the183canonical stack (with scroll factors relative to the playfield = 1.0):184185| # | Layer | Factor | Content |186|---|---|---|---|187| 1 | Sky | 0–0.05 | Painted gradient/backdrop; essentially fixed |188| 2 | Clouds | ~0.1 | Individual cloud sprites, plus their own slow self-drift |189| 3a | **Far hills / mountains** (required) | 0.10–0.15 | Big hazy desaturated range pieces, near-continuous chain |190| 3b | **Near hills / mountains** (required) | 0.25–0.35 | Warmer, more contrast, still calmer than the playfield |191| 4 | Buildings / trees (mid) | 0.4–0.6 | Individual set-piece sprites, one footprint per slot family |192| 5 | Playfield / ground plane | **1.0** | The gameplay: player, obstacles, pickups, ground |193| 6 | Foreground whip layer | 1.5–1.8 | Occasional props that sweep past close to camera, slightly blurred |194195**The hills are not optional decoration — they ARE the depth.** Every outdoor196scrolling scene includes the two hill/mountain layers, and they should be197**dominant**: sprite heights around 0.30–0.50 of screen height for the far198range and 0.22–0.36 for the near ridge, with LOW skip rates and spacing well199under a sprite width so pieces overlap into continuous ranges rather than200isolated bumps on the horizon. Two ranges sliding at different factors is201what sells parallax; one timid strip of hills reads flat. Differentiate them202with aerial perspective: far = palest, haziest, least contrast; near = warmer203and more detailed but still visibly calmer than the playfield.204205**Readability rule: the background must never impersonate an obstacle.** If a206sprite family is used as (or resembles) something the player must react to —207the cacti they jump, the rocks they dodge — it must NOT appear in any208background or mid layer at any size: a small background cactus reads as a209thing to jump and causes false inputs. Dress background layers only with210shapes the gameplay never uses (mountains, dry trees, ruins, clouds). The211foreground whip layer is the one exception: obstacle-family props are fine212there because big + blurred + faster-than-gameplay reads as camera depth, not213threat — the blur is mandatory for that reason.214215For a non-scrolling game the same stack still applies as static depth:216backdrop → object layer → foreground framing props that crop off the screen217edge (depth without 3D). In all cases nothing interactive is ever baked into218the background, and every playfield sprite is its own element — its own asset,219its own view/node, its own layout anchor — so any piece can be regenerated,220resized, or repositioned without touching the rest.221222### Parallax rules223224- **One constant world clock** drives every layer's offset225 (`offset = worldX × factor`). The drift never speeds up, slows down, or226 jumps for any game event — only the focal element moves on events. A steady227 world is what makes the moving parts read.228- **Mid-scene dressing is individual sprites placed procedurally** — never one229 giant looping strip. Strip loops need mirror-tiling and the mirrored twins230 are visible. Mirror-tiling is acceptable ONLY for genuinely uniform textures231 (a plain ground fill, a flat wall).232233 Procedural placement recipe:234 - The world is divided into **slots** per layer (e.g. a building slot every235 ~220 world units).236 - `hash(layerId, slotIndex)` — any cheap deterministic integer hash — picks237 the variant, the spacing jitter (±30–40% of slot width), the size wobble238 (±10%), and an occasional skip (empty slot). Deterministic means the same239 scenery reappears if the player backtracks, with zero storage.240 - Spawn slots a screen ahead of the camera, cull a screen behind. Never241 store the whole world.242 - Adjacent slots avoid repeating the same variant (re-hash or +1 the pick).243- **Foreground props sweep past occasionally** — roughly one per long cycle,244 not a constant stream — with a slight blur for depth of field, and they245 NEVER hit-test. Gameplay input is always the topmost interactive layer.246- **Layers resize from their anchored seam.** A strip pinned to the horizon247 grows UPWARD when scaled — shared edges between layers must never move, or248 gaps flash at the seams on resize.249- **Aerial perspective per layer** (from the style guide): far layers get the250 lighter/hazier/desaturated versions of the sprites. If needed, apply a cheap251 per-layer tint/haze overlay in code instead of regenerating.252- **Camera = a focus value, not teleports.** Interpolate the camera/world253 position along a focus index so rolling/walking parts can read the254 *interpolated* travel each frame and match ground speed exactly (in SwiftUI255 that means `Animatable`; in a canvas loop it's just per-frame lerp).256257### Polish pass (cheap, high-impact)258259- **Never open static.** A scene whose fantasy has motion opens already260 moving (ease-out, no delay) — the player must never see the world "start261 up".262- **Idle life on the focal element** — a gentle bob, an ambient particle loop —263 with ground-contact parts staying planted.264- **The code light grade** from Phase 1: warm radial wash + vignette over the265 composed scene. Do this last; it's what fuses the layers.266- **Landings never overshoot.** Anything dropping onto a surface: ease-in fall267 that stops DEAD at contact, a quick squash (≈0.78 wide / 1.12 tall, anchored268 at the bottom, ~0.07s), a dust burst at the contact seam (anchor the burst269 slightly BELOW the visual seam — burst patterns fan upward), then spring270 back.271- **Reactions are layered:** instant snap within one frame of input272 (~0.04s) → rattle/jitter → brightness flash → recover. Input registers on273 touch-down/press, never on release, and the first visual reaction lands274 within one frame.275- **Settled things freeze forever.** Physics debris drops, tumbles, settles —276 then becomes immovable. Nothing idles, twirls, or jitters in the background277 competing with the playfield.278279---280281## Phase 4 — Integration & layout conventions282283- **All positions are fractions of the viewport/scene size** in a per-scene284 `Layout` constant table — never absolute pixels. The playfield focal point285 sits around `(0.5 × width, 0.55–0.72 × height)` for portrait; center-weight286 horizontally for landscape scrollers.287- **One sprite, one node/view, one layout anchor.** The file structure mirrors288 the manifest.289- **Render order is the layer stack**, explicit and in one place — not290 emergent from insertion order scattered across files.291- **Time bases live in state, not locals.** A phase anchor or start-time292 captured as a plain local in render code resets on every re-render and snaps293 animation clocks to zero (in SwiftUI: `@State`; in JS: module/instance294 state, not per-frame `Date.now()` diffs from a re-created base).295- Web-specific: preload the sprite manifest before first paint, use296 `image-rendering` appropriate to the style, draw layers to the main canvas297 in stack order (or use stacked canvases/CSS transforms for the far layers if298 the game is DOM-based).299300---301302## Verification303304Don't call it done from stills alone:3053061. **Screenshot** each layer toggled on cumulatively (sky → +clouds → +hills →307 +buildings → +playfield → +foreground) to check seams, scale, and aerial308 perspective steps.3092. **Record video / animated capture** of the world scrolling — stills cannot310 judge parallax feel, easing, or drift steadiness. Watch for: mirrored311 twins, variant repeats in adjacent slots, seam gaps on resize, foreground312 props stealing attention.3133. **Squint test:** blur your eyes at a screenshot — the playfield focal point314 must still be the obvious brightest/highest-contrast region. If a315 background layer wins, dim it.316317---318319## Checklist3203211. [ ] Visual inventory + sprite manifest written (every object its own line)3222. [ ] `STYLE.md`: style sentence, palette anchors with values, semantic323 colors, light direction3243. [ ] Style anchor sprite generated and approved3254. [ ] All manifest sprites generated via the pipeline (edit-with-reference →326 background-removal → trim → footprint-normalized), originals backed up3275. [ ] No composite sprites anywhere — every building/tree/cloud/prop is its328 own cutout3296. [ ] No baked text/label zones in any sprite3307. [ ] Layer stack implemented with per-layer scroll factors off ONE world331 clock — BOTH hill/mountain layers present and dominant, no332 obstacle-lookalike sprites in any background or mid layer3338. [ ] Animated characters have a full frame cycle (4+ frames for a run),334 frames edited from frame 1, shared canvas, keyed to world travel3359. [ ] Mid/far dressing placed procedurally (slot + hash: variant, jitter,336 size, skip), spawn-ahead/cull-behind33710. [ ] Foreground whip layer: occasional, blurred, never hit-tests33811. [ ] Aerial perspective across layers; code light grade (warm wash +339 vignette) over the composed scene34012. [ ] Opens already in motion; idle life on the focal element; landing341 squash recipe wherever things drop34213. [ ] Layout as viewport fractions; seams anchored; resize-safe34314. [ ] Verified with layer-by-layer screenshots AND a scrolling video capture
Run npx skillmds@latest add adamlyttleapps/game-assets-enhancement in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Point at any game codebase (or a new game) to dramatically upgrade its graphics — derive a style guide, generate individual sprite assets via fal.ai, replace flat/placeholder art, and add multi-layer parallax depth (sky / clouds / hills / buildings / playfield / foreground) with procedurally-placed individual sprites, never baked looping strips. It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Independent scanners report: SkillSpector: PASS, Skill Scanner: PASS. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
adamlyttleapps (@adamlyttleapps) published this skill. Their other Agent Skills are listed on their SkillMD profile.