monsterplex/sprites.md

8.0 KiB

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 node/flag/plate sprites: they are drawn centered on a 960x540 transparent canvas (1920x1080 at 2x) and displayed full-frame at a position, so where you draw the art on that canvas is where it appears in the game. Keep the subject centered in the frame, or it will show up shifted.

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 ~450x450 badge centered completed level node (number badge)
map_node_current assets/ui/map_node_current.png ~450x450 badge centered the next level to play ("start here" node)
map_node_locked assets/ui/map_node_locked.png ~450x450 badge centered locked level node
map_finish assets/ui/map_finish.png ~440x560 centered 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. Leave the bottom 60% open road/grass for the path to sit on. The node positions live in src/data/levels/index.js (positions, or auto-layout via src/data/levels/positioning.js) - check where your nodes will land before you paint, and keep that corridor readable.
  • Node states share one silhouette (same size/placement) in three moods: map_node (cleared, e.g. blue with the level number), map_node_current (the one to play next, e.g. gold - this one gets a gentle idle pulse), map_node_locked (greyed out, e.g. a padlock). If you want the badge to be a different size than ~450 units, also adjust BADGE_FRAC_OF_FRAME in src/util/mapArt.js.
  • map_finish.png - the flag sits just past the last node, on the road, so a base/mound that grounds it looks best; don't rely on the bottom of the 960x540 canvas being the ground line.
  • map_campaign_tag.png - a plate/banner with empty center space; the game writes "<name> 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 <link> 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).