# Adding real art Nothing in the code needs to change to swap in real art. `src/util/assetManifest.js` lists every image the game expects, with an exact `path`. `PreloadScene` tries to load each one; if the file doesn't exist (or fails to load), it falls back to a synthesized colored placeholder shape instead. **Drop a real PNG at the exact path below, refresh the page, and it's used automatically.** ## Where files go All paths are relative to the project root (`/home/brianfertig/git/monsterplex/`). The folders already exist and are currently empty. | key | path | size used in-game | shape | notes | |---|---|---|---|---| | `bus_chassis` | `assets/sprites/bus_chassis.png` | 340 x 128 | rectangle | see "Bus" below | | `bus_wheel` | `assets/sprites/bus_wheel.png` | 104 x 104 | circle | one image, used for both wheels | | `kid_idle` | `assets/sprites/kid_idle.png` | 56 x 56 | circle | passenger while aboard the bus | | `kid_ejected` | `assets/sprites/kid_ejected.png` | 56 x 56 | circle | passenger after being thrown off | | `bg_far` | `assets/backgrounds/bg_far.png` | tiled, 512 x 1080 native | - | slowest-scrolling parallax layer (sky/distant) | | `bg_mid` | `assets/backgrounds/bg_mid.png` | tiled, 512 x 1080 native | - | mid-speed parallax layer | | `bg_near` | `assets/backgrounds/bg_near.png` | tiled, 512 x 1080 native | - | fastest-scrolling parallax layer (closest) | | `icon_kid` | `assets/ui/icon_kid.png` | 48 x 48 | - | small HUD "kids aboard" icon, top-left | | `favicon` | `assets/favicon.png` | 32 x 32 | - | browser tab icon - see caveat below | "Size used in-game" is the size the game actually displays the image at (`setDisplaySize`), **not** a requirement on the source file's resolution - see "Resolution" below. These numbers are the game's current 1920x1080 resolution (`WORLD_SCALE = 2` in `src/config.js`) - if that changes again, every size in this table changes with it (same ratios, just re-derive from that one constant). ## Bus - `bus_chassis.png` and `bus_wheel.png`, transparent background (PNG alpha). - **The bus always faces right** (nose/front toward positive x - the direction it drives at level start) and there's no left/right flip when reversing, so draw the chassis facing right. - The chassis's rectangle *is* the physics hitbox (with rounded corners baked in by the physics engine, not the art). Keep the bus's silhouette roughly filling a 340x128 box so the visual matches where it actually collides. - `bus_wheel.png` is used for **both** wheels (front and rear) - same image, no separate left/right variant needed. It's a real physics body, so it visually spins as the bus drives; a plain hubcap/circle reads better at speed than fine detail. - If you want a bus with different proportions (longer, taller, etc.) than 340x128, tell me the size you want art at - that number is also the physics body size in `src/config.js` (`BUS.chassisWidth`/`chassisHeight`), so it needs a matching code change, not just a differently-shaped image. ## Kids - `kid_idle.png` (aboard) and `kid_ejected.png` (mid-air after being thrown off) - two separate images, swapped automatically when a kid is ejected. - Physics shape is a circle, but the *image* itself renders as a full square at 56x56 - draw the character centered in a square canvas with transparent padding around them rather than filling every corner, or they'll look like they're poking out past their own collision circle. - `kid_ejected` is a good place to show some "yikes" energy (arms out, startled face, etc.) since it only appears for the ~2 seconds after a kid gets thrown clear. ## Parallax backgrounds - `bg_far` / `bg_mid` / `bg_near` are rendered as horizontally **tiling** strips (`TileSprite`), not single stretched images - whatever you supply repeats sideways as the camera scrolls. - Make the **left and right edges match** so the seam is invisible when it tiles (or design something patternable, like scattered clouds/hills on a transparent background). - far/mid/near are layered back-to-front and scroll at different speeds for depth (far moves slowest, near moves fastest) - a plain sky for far, hills or treeline silhouettes for mid, and closer foreground detail for near works well. - Native resolution isn't locked to 512x1080 the way the bus/kid sprites are - a wider or taller source image just changes how often the tile repeats, so use whatever gives a clean seamless loop. ## Level select map The level select screen is a map per campaign: a themed background with a road ribbon snaking between level nodes, a finish flag past the last node, and a banner plate behind the campaign title. There is one of each of these per campaign, plus the shared node/flag/plate sprites. **Important convention for these sprites:** each is displayed at a fixed display size with origin (0.5, 0.5) at its map position, so **keep the subject centered in its file** or it will show up shifted. The node badges and the flag ship as tight 512x512 images (the badge/flag IS the file); `map_campaign_tag` is a full-screen 1920x1080 frame with the plate centered near the top. Sizes below are the display sizes the game uses (design units); the source file's own resolution only affects crispness. | key | path | subject size (design units) | notes | |---|---|---|---| | `campaign01_bg` | `assets/backgrounds/campaign01_bg.png` | full frame 960x540 | Campaign 1 "Sunny Suburbs" background | | `campaign02_bg` | `assets/backgrounds/campaign02_bg.png` | full frame 960x540 | Campaign 2 "Dusk Junction" background | | `map_node` | `assets/ui/map_node.png` | ~58x58 badge (512x512 file) | completed level node | | `map_node_current` | `assets/ui/map_node_current.png` | ~71x71 badge (512x512 file) | the next level to play ("start here" node) | | `map_node_locked` | `assets/ui/map_node_locked.png` | ~58x58 badge (512x512 file) | locked level node | | `map_finish` | `assets/ui/map_finish.png` | ~345x345 (512x512 file) | flag past the last node | | `map_campaign_tag` | `assets/ui/map_campaign_tag.png` | ~1440x300 plate centered near top | banner behind the campaign title text (title is drawn on top at y≈82/540) | Per-campaign notes: - **`campaign0X_bg.png`** - full 960x540 (or 2x) scene, no transparency needed. The top ~150 units are behind the title plate, so keep that area fairly quiet. Node positions are auto-placed in a **2-lane serpentine** that sits in the band **y ≈ 268-412** (design units) across the full map width (x ≈ 90-870) - both lanes - so keep that horizontal strip fairly open and readable, and leave the bottom ~60 units clear for the `< Menu` / hint chrome. The exact lane y-values live in `src/data/levels/positioning.js` (`LANE_TOP`/`LANE_BOTTOM`) and per-campaign overrides in `src/data/levels/index.js` (`positions`) - check where your nodes will land before you paint. - **Node states** share one silhouette (same size/placement) in three moods: `map_node` (cleared), `map_node_current` (the one to play next - this one gets a gentle idle pulse), `map_node_locked` (greyed out, e.g. a padlock). All three ship as 512x512 badge images with no padding frame; their display size and hit area are driven by `NODE_ART_FRAMES` + `BADGE_FILE_FRAC` per-key in `src/util/mapArt.js`, so a different frame size there is fine as long as those tables are updated. If you want the badge to be a different display size than ~58-71 units, adjust `BADGE_FRAC_OF_FRAME` / the per-state `BADGE_FILE_FRAC` entries in `src/util/mapArt.js` (the click area follows the art, not these knobs). - **`map_finish.png`** - the flag sits just past the last node, so a base/mound that grounds it looks best. Currently ships as a tight 512x512 image (flag ink is ~60% of the width, full height); the scene displays it at 0.18x the game screen, so keep the flag roughly centered in a square frame if you re-export it. The auto-layout circuit ends at the bottom-right, so the flag lands in the bottom-right corner past the final node (with custom `positions` the nudge flips to stay on-screen when the last node is at an edge). - **`map_campaign_tag.png`** - a plate/banner with empty center space; the game writes `" x/y cleared"` on top of it in dark ink (#1a1f29), so the middle should be a light, uncluttered fill. ## Favicon - `favicon.png` is the one asset **without** a placeholder fallback for its actual purpose - the browser tab icon comes from a plain `` tag in `index.html`, not from Phaser's loader, so until a real file exists at `assets/favicon.png` the browser just shows its default icon (nothing broken, just nothing shown). ## Resolution Supply art at the "size used in-game" from the table above, or a clean multiple of it (2x/3x) for a crisper look on high-DPI screens - everything gets scaled to the table's size regardless of the source file's actual pixel dimensions, so it won't come in stretched or huge, but a very different aspect ratio than the target box will get squashed/stretched to fit. ## Testing Just refresh the browser tab after dropping files into `assets/` - no build step, no server restart needed (unless the static server itself isn't running yet, in which case see `README.md`).