- Expand smash-items spritesheet from 6 to 12 frames (8x2 grid) with new trash can, tent, and cat props plus their smash sound effects
- Expand bonus-items spritesheet from 12 to 18 frames (9x2 grid) with new spray paint and backpack collectibles plus their firework sounds
- Add level12 ("Curb Check") as a designed level and levels 13-20 as placeholder stubs to fill campaign 2's 10-level map
- Give campaign 2 a custom 3-row serpentine layout on the level select screen to differentiate it from campaign 1's two-lane design
- Update editor preview rendering to handle multi-row spritesheet grids and expose the new item types in the placeables panel
- Create `src/data/themes.js` with theme definitions (background color, parallax layers) and a `getTheme()` resolver that falls back to campaign 1's default look
- Update `PlayScene` to load the active campaign's theme instead of hardcoding colors/texture keys
- Register campaign 2's `_2` background assets in the asset manifest with placeholder fallbacks
- Add updated background art for campaign 2 (`bg_far_2.png`)
- Add levels 7-10 and move all 10 into campaign01 (campaign02 left empty
as scaffolding)
- Replace the old S-curve auto-layout with a 2-lane circuit: top lane
runs right→left, bottom lane left→right, finish flag in the
bottom-right corner. Comfortable up to ~12 levels per campaign.
- Re-export node/flag sprites as tight 512x512 badges (badge IS the
file) instead of centered-on-960x540 frames; update mapArt.js tables
(BADGE_FILE_FRAC, BADGE_HIT_FRAC, NODE_ART_FRAMES) and asset manifest
accordingly
- Size the finish-flag nudge to stay on-screen when a custom `positions`
layout ends at an edge (flips direction if out of bounds)
- Guard against empty campaigns: skip path/flag rendering when there are
no points, and bail early in _playFirst()
- Shrink node pill font slightly so the longest tag fits under tightly
spaced nodes
- Update README.md and sprites.md to reflect the new sprite convention,
lane geometry, and level count
- Refactor level select scene to handle variable node texture dimensions
instead of assuming all node art is centered on a 960×540 canvas
- Change BADGE_FILE_FRAC and nodeDisplaySize to accept per-state keys,
allowing map_node_current (512×512 badge) to differ from the other
nodes (960×540 frames)
- Update map_finish to use its new 512×512 tight export; reduce its
display scale accordingly
- Rename campaigns: "Sunny Suburbs" → "Evergreen Lake",
"Dusk Junction" → "Underprivileged Community"
- Update asset manifest dimensions and sprites.md documentation
Replace the flat level-grid level select screen with a campaign-based
map view. Levels are grouped into themed campaigns (e.g. "Sunny Suburbs",
"Dusk Junction") each with its own background art and node positions
rendered along a Catmull-Rom spline ribbon.
Key changes:
- Introduce CAMPAIGNS array in src/data/levels/index.js with helpers for
campaign/level lookup.
- Add src/data/levels/positioning.js for auto-layout S-curve generation
and Catmull-Rom spline sampling.
- Rewrite LevelSelectScene.js to render per-campaign maps with animated
node entrance, idle pulse on the current level, hover states,
tool-tips for locked levels, and ← → / P keyboard navigation.
- Remove the now-unused LevelCompleteScene; scores now record progress
and return directly to the map via LevelScoreScene.
- Add map assets (campaign backgrounds, node/flag/tag sprites) and
manifest entries with a documented 960x540 centered-canvas convention.
- Add src/util/mapArt.js for shared map geometry constants and scaling.
- New browser level editor (editor.html + src/editor/): assemble levels
from snap-together section generators (flat/inclines/hills/ditch/jump)
with a live canvas preview, metadata form, and export to ready-to-drop
levelNN.js source; example export registered as level04.js.
- Add parallax background sprites (bg_far/mid/near).
- Bus retune: softer, bouncier suspension (stiffness 0.45->0.35, damping
0.08->0.035, travel 12->30, restitution 0.3->0.45) with wheel rest
point raised 22->34 for a bouncier stance; drive force cut ~60%
(0.011->0.0045) for a much longer runway and lower top speed.
- Gravity 1 -> 0.675 for ~1.5x hang time off jumps; constraintIterations
2 -> 10 so the soft wishbone springs converge within one step.
- Bus: clamp each wheel to the underside of its wishbone anchor line on
every matter afterupdate, fixing wheels punching through to the
mirrored solution and sticking high on the chassis after hard impacts;
add no-op destroy() for the world listener.
- CameraRig: speed-driven horizontal lookahead (bus framed ~10% from the
left edge at rest, out to 1/3 of the screen at speed) via followOffset;
PlayScene scales the g-force grace period to 5.5s for the new gravity
and calls the new update()/destroy() hooks.
- Extend level01's terrain runway by 30x.