diff --git a/README.md b/README.md index 0c17abf..94fa1ab 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ no code changes needed.** | `kid_idle` | `assets/sprites/kid_idle.png` | 28x28 | passenger while aboard | | `kid_ejected` | `assets/sprites/kid_ejected.png` | 28x28 | passenger after being thrown off | | `smash_items` | `assets/sprites/smash-items.png` | 64x64 x 6 frames | 1x6 spritesheet: intact/smashed TV, chair, cone (see Smashables below) | -| `bonus_items` | `assets/sprites/bonus-items.png` | 64x64 x 9 frames | 1x9 spritesheet: CTC box + 2 firework objects, guitar + 2, cash + 2 (see Bonus Items below) | +| `bonus_items` | `assets/sprites/bonus-items.png` | 64x64 x 12 frames | 1x12 spritesheet: CTC box + 2 firework objects, guitar + 2, cash + 2, flour + 2 (see Bonus Items below) | | `bg_far` | `assets/backgrounds/bg_far.png` | 256x540 | tiled, slowest parallax layer | | `bg_mid` | `assets/backgrounds/bg_mid.png` | 256x540 | tiled, mid parallax layer | | `bg_near` | `assets/backgrounds/bg_near.png` | 256x540 | tiled, fastest parallax layer | @@ -108,7 +108,7 @@ end-of-level score screen. The **level editor** (`editor.html`) has a "Placeables" section with a kind toggle: **Smashables** (TV / chair / cone, float or gravity mode) and -**Bonus items** (CTC box / guitar / cash, float-only). Pick the kind + type, +**Bonus items** (CTC box / guitar / cash / flour, float-only). Pick the kind + type, then click anywhere on the preview map to drop one there; click an existing item (on the map or in the list) to remove it. Exporting the level writes both the `items` and `bonusItems` arrays into the level file automatically. @@ -123,11 +123,11 @@ description / kids) and both placeable types stay editable, so you can tweak them and re-export. "Start a new level" clears the import and unlocks the section controls again. -## Bonus Items (CTC box / guitar / cash) +## Bonus Items (CTC box / guitar / cash / flour) -`assets/sprites/bonus-items.png` is a 1x9 spritesheet (CTC box, 2 firework -frames, guitar, 2 firework frames, cash, 2 firework frames - 64x64 per -frame), loaded as the `bonus_items` texture. Any level can carry an optional +`assets/sprites/bonus-items.png` is a 1x12 spritesheet (CTC box, 2 firework +frames, guitar, 2 firework frames, cash, 2 firework frames, flour, 2 firework +frames - 64x64 per frame), loaded as the `bonus_items` texture. Any level can carry an optional `bonusItems` array (see the editor's export for the exact shape): ```js @@ -155,12 +155,17 @@ kids (same trick as `SmashItemManager._smash`) so it can never bump the bus or flick a kid out of the compartment. It does still collide with terrain so it lands where it lands. Particles are tinted per the bonus type's own color scheme (`BONUS_ITEM.colors`): CTC = warm toast-brown/cinnamon, guitar -= bright/deep green, cash = muted sage/olive-grey. += bright/deep green, cash = muted sage/olive-grey, flour = warm off-white/tan. +Some types override the burst's look entirely via +`BONUS_ITEM.fireworkVariants`: flour's puffs launch 2-3x the standard +particle size at half opacity (a soft cloud of dust, still with the +standard-sized physics bodies underneath). Collected bonus items tally as `SCORE.perBonusItem` (100) each on the end-of-level score screen, revealed right after the smashed-props line. `BONUS_ITEM` in `config.js` holds all the tuning knobs (particle count, -speed range, spin, lifetime, tint palette, pop scale/duration). +speed range, spin, lifetime, tint palette, firework variants, pop +scale/duration). ## Phaser 4 loading diff --git a/assets/fx/bonus-flour.mp3 b/assets/fx/bonus-flour.mp3 new file mode 100644 index 0000000..bede253 Binary files /dev/null and b/assets/fx/bonus-flour.mp3 differ diff --git a/assets/sprites/bonus-items.png b/assets/sprites/bonus-items.png index ab4e8ba..8c9ed0b 100644 Binary files a/assets/sprites/bonus-items.png and b/assets/sprites/bonus-items.png differ diff --git a/assets/sprites/bonus-items.psd b/assets/sprites/bonus-items.psd index 4995052..3a04124 100644 Binary files a/assets/sprites/bonus-items.psd and b/assets/sprites/bonus-items.psd differ diff --git a/assets/voice/level11.mp3 b/assets/voice/level11.mp3 new file mode 100644 index 0000000..a77dc85 Binary files /dev/null and b/assets/voice/level11.mp3 differ diff --git a/sprites.md b/sprites.md index 32506f9..738ac4e 100644 --- a/sprites.md +++ b/sprites.md @@ -51,8 +51,14 @@ with it (same ratios, just re-derive from that one constant). only the texture is swapped per campaign), and a "lift kit": the wheel mount point sits ~8 design units lower under the chassis (see `wheelRestOffsetY2` in `src/config.js` and the `bus` block in - `src/data/themes.js`), so it reads as a lifted bus. Both wheels still - share one image per campaign. + `src/data/themes.js`), so it reads as a lifted bus. And its tires grip + harder: the per-campaign `bus` block also sets the wheel friction + coefficients (`wheelFriction2` / `wheelFrictionStatic2` in + `src/config.js`) - that's a physics feel change, not an art one. Its + shocks are different too - stiffer springs with less damping + (`suspensionStiffness2` / `suspensionDamping2`), so the wheel snaps + back to its rest position faster and bounces more vertically. Both + wheels still share one image per campaign. - 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 diff --git a/src/config.js b/src/config.js index 0b3a043..c9019ef 100644 --- a/src/config.js +++ b/src/config.js @@ -91,6 +91,12 @@ export const BUS = { wheelDensity: 0.004, wheelFriction: 0.9, wheelFrictionStatic: 1.4, + // Campaign 2's grippier tires (see `bus` in data/themes.js): higher + // friction coefficients for the bus_wheel_2 rubber - less spin/slip + // under throttle and brake, and the wheel grips the terrain harder. + // Dimensionless like the values above, not WORLD_SCALE-scaled. + wheelFriction2: 1.3, + wheelFrictionStatic2: 2.0, // Lowered a lot from the original 0.02 - that was quietly eating most of // the wheel's spin-up each second (it's a per-tick multiplicative decay, // so 0.02 was burning off roughly a third of angular velocity per second) @@ -103,6 +109,13 @@ export const BUS = { // oscillate (bounce) instead of settling immediately - "more shocks." suspensionStiffness: 0.35, suspensionDamping: 0.035, + // Campaign 2's shocks (see `bus` in data/themes.js): stiffer springs that + // snap the wheel back to its rest position faster, paired with LESS + // damping so the extra spring energy survives as visible vertical bounce + // instead of being absorbed - a quicker, bouncier ride than campaign 1's + // soft settle. + suspensionStiffness2: 0.4, + suspensionDamping2: 0.012, // How far the wheel can move up/down from wheelRestOffsetY. This will // visibly pop the wheel outside its wheel well on a hard landing - that's // the tradeoff for real suspension travel/bounce instead of a stiff ride. @@ -260,7 +273,7 @@ export const SMASH_ITEM = { floatHeight: 90 * WORLD_SCALE, }; -// Bonus items (assets/sprites/bonus-items.png - 9 frames of 64x64: a bonus +// Bonus items (assets/sprites/bonus-items.png - 12 frames of 64x64: a bonus // item followed by its two firework-object frames - see // src/entities/BonusItemManager.js for the type/frame/color table). Placed // per-level via the editor's "Placeable kind" switch ("Bonus items") and @@ -303,6 +316,18 @@ export const BONUS_ITEM = { lifeMs: 1300, // how long a particle stays visible; the fade-out is the last 40% of this particleDisplaySize: 40 * WORLD_SCALE, // each firework particle is shown square at this size (80 world px, half the bonus item's own 128) + // Optional per-type firework overrides (defaults: plain particleDisplaySize, + // full opacity). Flour's dust puffs are the only type that uses one: each + // firework sprite is shown 2-3x the normal particle size at ~half opacity, + // so a hit reads as a soft cloud of dust billowing over the bus instead of + // a confetti pop. Read per item in BonusItemManager._explode (variant = + // BONUS_ITEM.fireworkVariants[item.spec.type] || {}). NOTE: this is purely + // visual - the particles' physics bodies stay at the standard size (below), + // so the bigger sprites don't change how they settle on the terrain. + fireworkVariants: { + flour: { scaleMin: 2, scaleMax: 3, alpha: 0.5 }, + }, + // Tint per bonus type, matched to each item's art: the firework sprites // (which are drawn in their own colors) get a PHASER.MULTIPLY tint of // these so the burst reads as an echo of the item's own color scheme @@ -313,6 +338,7 @@ export const BONUS_ITEM = { ctc: { main: 0xe0a040, accent: 0x703818 }, // warm toast-brown / cinnamon guitar: { main: 0x50c050, accent: 0x105018 }, // bright green / deep forest cash: { main: 0xaab888, accent: 0x404030 }, // muted sage / olive-grey (cash's own scheme is near-white grey-green) + flour: { main: 0xf4f1e8, accent: 0xcbb58e }, // warm off-white / tan (flour's own scheme is pale beige) }, }; diff --git a/src/data/levels/level11.js b/src/data/levels/level11.js index 5daad30..14014db 100644 --- a/src/data/levels/level11.js +++ b/src/data/levels/level11.js @@ -1,10 +1,10 @@ // Generated by editor.html - review before dropping into src/data/levels/. export default { id: "level11", - name: "Uh oh!", - description: "What have I gotten myself into?", - kidsAboard: 3, - timeLimit: 119, + name: "Welcome to the Block", + description: "Oh shit!", + kidsAboard: 4, + timeLimit: 42, startPosition: { x: 200, y: 700 }, startAngle: 0, terrain: [ @@ -50,850 +50,217 @@ export default { { x: 2260, y: 1014 }, { x: 2330, y: 1018 }, { x: 2400, y: 1020 }, - { x: 2470, y: 1022 }, - { x: 2540, y: 1026 }, - { x: 2610, y: 1030 }, - { x: 2680, y: 1038 }, - { x: 2750, y: 1048 }, - { x: 2820, y: 1058 }, - { x: 2890, y: 1070 }, - { x: 2960, y: 1084 }, - { x: 3030, y: 1096 }, - { x: 3100, y: 1110 }, - { x: 3170, y: 1124 }, - { x: 3240, y: 1136 }, - { x: 3310, y: 1150 }, - { x: 3380, y: 1162 }, - { x: 3450, y: 1172 }, - { x: 3520, y: 1182 }, - { x: 3590, y: 1190 }, - { x: 3660, y: 1194 }, - { x: 3730, y: 1198 }, - { x: 3800, y: 1200 }, - { x: 3870, y: 1200 }, - { x: 3940, y: 1200 }, - { x: 4010, y: 1200 }, - { x: 4080, y: 1200 }, - { x: 4150, y: 1200 }, - { x: 4220, y: 1200 }, - { x: 4290, y: 1200 }, - { x: 4360, y: 1200 }, - { x: 4430, y: 1200 }, - { x: 4500, y: 1200 }, - { x: 4570, y: 1200 }, - { x: 4640, y: 1200 }, - { x: 4710, y: 1200 }, - { x: 4780, y: 1200 }, - { x: 4850, y: 1200 }, - { x: 4920, y: 1200 }, - { x: 4990, y: 1200 }, - { x: 5060, y: 1200 }, - { x: 5130, y: 1200 }, + { x: 2470, y: 1020 }, + { x: 2540, y: 1020 }, + { x: 2610, y: 1020 }, + { x: 2680, y: 1020 }, + { x: 2750, y: 1020 }, + { x: 2820, y: 1020 }, + { x: 2890, y: 1020 }, + { x: 2960, y: 1020 }, + { x: 3030, y: 1020 }, + { x: 3100, y: 1020 }, + { x: 3170, y: 1020 }, + { x: 3240, y: 1020 }, + { x: 3310, y: 1020 }, + { x: 3380, y: 1020 }, + { x: 3450, y: 1020 }, + { x: 3520, y: 1020 }, + { x: 3590, y: 1020 }, + { x: 3660, y: 1020 }, + { x: 3730, y: 1020 }, + { x: 3800, y: 1020 }, + { x: 3870, y: 1022 }, + { x: 3940, y: 1026 }, + { x: 4010, y: 1030 }, + { x: 4080, y: 1038 }, + { x: 4150, y: 1048 }, + { x: 4220, y: 1058 }, + { x: 4290, y: 1070 }, + { x: 4360, y: 1084 }, + { x: 4430, y: 1096 }, + { x: 4500, y: 1110 }, + { x: 4570, y: 1124 }, + { x: 4640, y: 1136 }, + { x: 4710, y: 1150 }, + { x: 4780, y: 1162 }, + { x: 4850, y: 1172 }, + { x: 4920, y: 1182 }, + { x: 4990, y: 1190 }, + { x: 5060, y: 1194 }, + { x: 5130, y: 1198 }, { x: 5200, y: 1200 }, - { x: 5270, y: 1202 }, - { x: 5340, y: 1206 }, - { x: 5410, y: 1218 }, - { x: 5480, y: 1238 }, - { x: 5550, y: 1264 }, - { x: 5620, y: 1296 }, - { x: 5690, y: 1330 }, - { x: 5760, y: 1362 }, - { x: 5830, y: 1396 }, - { x: 5900, y: 1428 }, - { x: 5970, y: 1460 }, - { x: 6040, y: 1494 }, - { x: 6110, y: 1526 }, - { x: 6180, y: 1560 }, - { x: 6250, y: 1592 }, - { x: 6320, y: 1624 }, - { x: 6390, y: 1658 }, - { x: 6460, y: 1690 }, - { x: 6530, y: 1724 }, - { x: 6600, y: 1756 }, - { x: 6670, y: 1788 }, - { x: 6740, y: 1818 }, - { x: 6810, y: 1848 }, - { x: 6880, y: 1878 }, - { x: 6950, y: 1904 }, - { x: 7020, y: 1930 }, - { x: 7090, y: 1956 }, - { x: 7160, y: 1982 }, - { x: 7230, y: 2006 }, - { x: 7300, y: 2030 }, - { x: 7370, y: 2054 }, - { x: 7440, y: 2078 }, - { x: 7510, y: 2102 }, - { x: 7580, y: 2128 }, - { x: 7650, y: 2152 }, - { x: 7720, y: 2176 }, - { x: 7790, y: 2200 }, - { x: 7860, y: 2224 }, - { x: 7930, y: 2250 }, - { x: 8000, y: 2274 }, - { x: 8070, y: 2298 }, - { x: 8140, y: 2322 }, - { x: 8210, y: 2346 }, - { x: 8280, y: 2370 }, - { x: 8350, y: 2396 }, - { x: 8420, y: 2420 }, - { x: 8490, y: 2444 }, - { x: 8560, y: 2468 }, - { x: 8630, y: 2492 }, - { x: 8700, y: 2516 }, - { x: 8770, y: 2542 }, - { x: 8840, y: 2566 }, - { x: 8900, y: 2586 }, - { x: 8970, y: 2606 }, - { x: 9040, y: 2618 }, - { x: 9110, y: 2614 }, - { x: 9180, y: 2594 }, - { x: 9250, y: 2556 }, - { x: 9320, y: 2508 }, - { x: 9390, y: 2456 }, - { x: 9460, y: 2404 }, - { x: 9530, y: 2404 }, + { x: 5270, y: 1200 }, + { x: 5340, y: 1196 }, + { x: 5410, y: 1186 }, + { x: 5480, y: 1166 }, + { x: 5550, y: 1138 }, + { x: 5620, y: 1104 }, + { x: 5690, y: 1070 }, + { x: 5760, y: 1034 }, + { x: 5830, y: 1034 }, ] }, { points: [ - { x: 9880, y: 2346 }, - { x: 9950, y: 2364 }, - { x: 10020, y: 2408 }, - { x: 10090, y: 2466 }, - { x: 10160, y: 2524 }, - { x: 10230, y: 2568 }, - { x: 10300, y: 2586 }, - { x: 10370, y: 2604 }, - { x: 10440, y: 2626 }, - { x: 10510, y: 2654 }, - { x: 10580, y: 2686 }, - { x: 10650, y: 2722 }, - { x: 10720, y: 2760 }, - { x: 10790, y: 2798 }, - { x: 10860, y: 2834 }, - { x: 10930, y: 2872 }, - { x: 11000, y: 2910 }, - { x: 11070, y: 2946 }, - { x: 11140, y: 2984 }, - { x: 11210, y: 3022 }, - { x: 11280, y: 3058 }, - { x: 11350, y: 3096 }, - { x: 11420, y: 3134 }, - { x: 11440, y: 3144 }, - { x: 11510, y: 3178 }, - { x: 11580, y: 3206 }, - { x: 11650, y: 3226 }, - { x: 11720, y: 3240 }, - { x: 11790, y: 3244 }, - { x: 11860, y: 3246 }, - { x: 11930, y: 3246 }, - { x: 12000, y: 3246 }, - { x: 12070, y: 3246 }, - { x: 12140, y: 3246 }, - { x: 12210, y: 3246 }, - { x: 12280, y: 3246 }, - { x: 12350, y: 3246 }, - { x: 12420, y: 3246 }, - { x: 12448, y: 3246 }, - { x: 12518, y: 3242 }, - { x: 12588, y: 3228 }, - { x: 12658, y: 3206 }, - { x: 12728, y: 3174 }, - { x: 12798, y: 3134 }, - { x: 12840, y: 3106 }, - { x: 12842, y: 3182 }, - { x: 12844, y: 3254 }, - { x: 12850, y: 3320 }, - { x: 12856, y: 3382 }, - { x: 12864, y: 3438 }, - { x: 12876, y: 3490 }, - { x: 12886, y: 3538 }, - { x: 12900, y: 3582 }, - { x: 12914, y: 3622 }, - { x: 12930, y: 3656 }, - { x: 12946, y: 3686 }, - { x: 12964, y: 3714 }, - { x: 12982, y: 3736 }, - { x: 13002, y: 3754 }, - { x: 13022, y: 3770 }, - { x: 13042, y: 3780 }, - { x: 13062, y: 3788 }, - { x: 13082, y: 3792 }, - { x: 13104, y: 3792 }, - { x: 13124, y: 3790 }, - { x: 13146, y: 3784 }, - { x: 13166, y: 3774 }, - { x: 13188, y: 3762 }, - { x: 13208, y: 3748 }, - { x: 13226, y: 3728 }, - { x: 13246, y: 3708 }, - { x: 13264, y: 3684 }, - { x: 13282, y: 3658 }, - { x: 13298, y: 3628 }, - { x: 13312, y: 3596 }, - { x: 13328, y: 3562 }, - { x: 13340, y: 3526 }, - { x: 13354, y: 3484 }, - { x: 13372, y: 3434 }, - { x: 13392, y: 3384 }, - { x: 13416, y: 3332 }, - { x: 13442, y: 3288 }, - { x: 13472, y: 3250 }, - { x: 13502, y: 3222 }, - { x: 13536, y: 3198 }, - { x: 13570, y: 3182 }, - { x: 13606, y: 3170 }, - { x: 13644, y: 3162 }, - { x: 13682, y: 3156 }, - { x: 13720, y: 3154 }, - { x: 13760, y: 3154 }, - { x: 13800, y: 3158 }, - { x: 13838, y: 3166 }, - { x: 13878, y: 3176 }, - { x: 13916, y: 3192 }, - { x: 13954, y: 3210 }, - { x: 13990, y: 3232 }, - { x: 14024, y: 3260 }, - { x: 14058, y: 3290 }, - { x: 14088, y: 3324 }, - { x: 14118, y: 3364 }, - { x: 14144, y: 3408 }, - { x: 14168, y: 3456 }, - { x: 14188, y: 3508 }, - { x: 14206, y: 3564 }, - { x: 14220, y: 3626 }, - { x: 14232, y: 3692 }, - { x: 14238, y: 3764 }, - { x: 14240, y: 3840 }, - { x: 14310, y: 3880 }, - { x: 14380, y: 3920 }, - { x: 14450, y: 3960 }, - { x: 14520, y: 4000 }, - { x: 14590, y: 4040 }, - { x: 14660, y: 4080 }, - { x: 14730, y: 4120 }, - { x: 14800, y: 4160 }, - { x: 14870, y: 4200 }, - { x: 14940, y: 4240 }, - { x: 15010, y: 4280 }, - { x: 15080, y: 4320 }, - { x: 15150, y: 4360 }, - { x: 15220, y: 4400 }, - { x: 15290, y: 4440 }, - { x: 15360, y: 4480 }, - { x: 15430, y: 4520 }, - { x: 15500, y: 4560 }, - { x: 15570, y: 4600 }, - { x: 15640, y: 4640 }, - { x: 15710, y: 4678 }, - { x: 15780, y: 4710 }, - { x: 15850, y: 4734 }, - { x: 15920, y: 4748 }, - { x: 15990, y: 4754 }, - { x: 16060, y: 4756 }, - { x: 16130, y: 4756 }, - { x: 16200, y: 4756 }, - { x: 16270, y: 4756 }, - { x: 16340, y: 4756 }, - { x: 16410, y: 4756 }, - { x: 16480, y: 4756 }, - { x: 16550, y: 4756 }, - { x: 16620, y: 4756 }, - { x: 16690, y: 4756 }, - { x: 16760, y: 4756 }, - { x: 16830, y: 4756 }, - { x: 16900, y: 4756 }, - { x: 16970, y: 4756 }, - { x: 17040, y: 4756 }, - { x: 17110, y: 4756 }, - { x: 17180, y: 4754 }, - { x: 17250, y: 4750 }, - { x: 17320, y: 4742 }, - { x: 17390, y: 4732 }, - { x: 17460, y: 4720 }, - { x: 17530, y: 4708 }, - { x: 17600, y: 4696 }, - { x: 17670, y: 4682 }, - { x: 17740, y: 4670 }, - { x: 17810, y: 4656 }, - { x: 17880, y: 4642 }, - { x: 17950, y: 4630 }, - { x: 18020, y: 4618 }, - { x: 18090, y: 4608 }, - { x: 18160, y: 4598 }, - { x: 18230, y: 4590 }, - { x: 18300, y: 4584 }, - { x: 18370, y: 4580 }, - { x: 18440, y: 4580 }, - { x: 18510, y: 4580 }, - { x: 18580, y: 4574 }, - { x: 18650, y: 4564 }, - { x: 18720, y: 4548 }, - { x: 18790, y: 4526 }, - { x: 18860, y: 4500 }, - { x: 18930, y: 4474 }, - { x: 19000, y: 4446 }, - { x: 19070, y: 4418 }, - { x: 19140, y: 4392 }, - { x: 19210, y: 4364 }, - { x: 19280, y: 4338 }, - { x: 19350, y: 4310 }, - { x: 19420, y: 4282 }, - { x: 19490, y: 4256 }, - { x: 19560, y: 4228 }, - { x: 19630, y: 4202 }, - { x: 19700, y: 4174 }, - { x: 19770, y: 4146 }, - { x: 19840, y: 4120 }, - { x: 19910, y: 4096 }, - { x: 19980, y: 4074 }, - { x: 20050, y: 4058 }, - { x: 20120, y: 4048 }, - { x: 20190, y: 4044 }, - { x: 20260, y: 4044 }, - { x: 20330, y: 4044 }, - { x: 20400, y: 4044 }, - { x: 20470, y: 4044 }, - { x: 20540, y: 4044 }, - { x: 20610, y: 4044 }, - { x: 20680, y: 4044 }, - { x: 20750, y: 4044 }, - { x: 20820, y: 4044 }, - { x: 20848, y: 4044 }, - { x: 20918, y: 4040 }, - { x: 20988, y: 4026 }, - { x: 21058, y: 4004 }, - { x: 21128, y: 3972 }, - { x: 21198, y: 3932 }, - { x: 21240, y: 3904 }, - { x: 21310, y: 3904 }, + { x: 6180, y: 1040 }, + { x: 6250, y: 1052 }, + { x: 6320, y: 1082 }, + { x: 6390, y: 1120 }, + { x: 6460, y: 1158 }, + { x: 6530, y: 1188 }, + { x: 6600, y: 1200 }, + { x: 6670, y: 1212 }, + { x: 6740, y: 1228 }, + { x: 6810, y: 1248 }, + { x: 6880, y: 1274 }, + { x: 6950, y: 1304 }, + { x: 7020, y: 1336 }, + { x: 7090, y: 1370 }, + { x: 7160, y: 1406 }, + { x: 7230, y: 1440 }, + { x: 7300, y: 1474 }, + { x: 7370, y: 1508 }, + { x: 7440, y: 1542 }, + { x: 7510, y: 1578 }, + { x: 7580, y: 1612 }, + { x: 7650, y: 1646 }, + { x: 7720, y: 1680 }, + { x: 7790, y: 1714 }, + { x: 7860, y: 1750 }, + { x: 7930, y: 1784 }, + { x: 8000, y: 1818 }, + { x: 8070, y: 1818 }, ] }, { points: [ - { x: 21800, y: 3904 }, - { x: 21870, y: 3904 }, - { x: 21940, y: 3904 }, - { x: 22010, y: 3904 }, - { x: 22080, y: 3904 }, - { x: 22150, y: 3904 }, - { x: 22220, y: 3904 }, - { x: 22290, y: 3904 }, - { x: 22360, y: 3904 }, - { x: 22430, y: 3904 }, - { x: 22500, y: 3904 }, - { x: 22570, y: 3904 }, - { x: 22640, y: 3904 }, - { x: 22710, y: 3888 }, - { x: 22780, y: 3872 }, - { x: 22850, y: 3856 }, - { x: 22920, y: 3840 }, - { x: 22990, y: 3824 }, - { x: 23060, y: 3808 }, - { x: 23130, y: 3792 }, - { x: 23200, y: 3776 }, - { x: 23270, y: 3760 }, - { x: 23340, y: 3744 }, - { x: 23410, y: 3728 }, - { x: 23480, y: 3712 }, - { x: 23550, y: 3696 }, - { x: 23620, y: 3680 }, - { x: 23690, y: 3664 }, - { x: 23760, y: 3648 }, - { x: 23830, y: 3632 }, - { x: 23900, y: 3616 }, - { x: 23970, y: 3600 }, - { x: 24040, y: 3584 }, - { x: 24110, y: 3568 }, - { x: 24180, y: 3554 }, - { x: 24250, y: 3540 }, - { x: 24320, y: 3528 }, - { x: 24390, y: 3518 }, - { x: 24460, y: 3510 }, - { x: 24530, y: 3498 }, - { x: 24600, y: 3478 }, - { x: 24670, y: 3454 }, - { x: 24740, y: 3426 }, - { x: 24810, y: 3398 }, - { x: 24880, y: 3372 }, - { x: 24950, y: 3352 }, - { x: 25020, y: 3340 }, - { x: 25090, y: 3336 }, - { x: 25160, y: 3340 }, - { x: 25230, y: 3352 }, - { x: 25300, y: 3372 }, - { x: 25370, y: 3398 }, - { x: 25440, y: 3426 }, - { x: 25440, y: 3424 }, - { x: 25510, y: 3452 }, - { x: 25580, y: 3478 }, - { x: 25650, y: 3498 }, - { x: 25720, y: 3510 }, - { x: 25790, y: 3514 }, - { x: 25860, y: 3510 }, - { x: 25930, y: 3498 }, - { x: 26000, y: 3478 }, - { x: 26070, y: 3452 }, - { x: 26140, y: 3424 }, - { x: 26210, y: 3396 }, - { x: 26280, y: 3372 }, - { x: 26350, y: 3352 }, - { x: 26420, y: 3338 }, - { x: 26490, y: 3334 }, - { x: 26560, y: 3338 }, - { x: 26630, y: 3352 }, - { x: 26700, y: 3372 }, - { x: 26770, y: 3396 }, - { x: 26840, y: 3424 }, - { x: 26910, y: 3452 }, - { x: 26980, y: 3478 }, - { x: 27050, y: 3498 }, - { x: 27120, y: 3510 }, - { x: 27190, y: 3514 }, - { x: 27260, y: 3510 }, - { x: 27330, y: 3498 }, - { x: 27400, y: 3478 }, - { x: 27470, y: 3452 }, - { x: 27540, y: 3424 }, - { x: 27610, y: 3396 }, - { x: 27680, y: 3372 }, - { x: 27750, y: 3352 }, - { x: 27820, y: 3338 }, - { x: 27890, y: 3334 }, - { x: 27960, y: 3338 }, - { x: 28030, y: 3352 }, - { x: 28100, y: 3372 }, - { x: 28170, y: 3396 }, - { x: 28240, y: 3424 }, - { x: 28310, y: 3424 }, - { x: 28380, y: 3424 }, - { x: 28450, y: 3424 }, - { x: 28520, y: 3424 }, - { x: 28590, y: 3424 }, - { x: 28660, y: 3424 }, - { x: 28730, y: 3424 }, - { x: 28800, y: 3424 }, - { x: 28870, y: 3424 }, - { x: 28940, y: 3424 }, - { x: 29010, y: 3424 }, - { x: 29080, y: 3424 }, - { x: 29150, y: 3424 }, - { x: 29220, y: 3424 }, - { x: 29248, y: 3424 }, - { x: 29318, y: 3420 }, - { x: 29388, y: 3406 }, - { x: 29458, y: 3384 }, - { x: 29528, y: 3352 }, - { x: 29598, y: 3312 }, - { x: 29640, y: 3284 }, - { x: 29657, y: 3272 }, - { x: 29673, y: 3258 }, - { x: 29690, y: 3248 }, - { x: 29707, y: 3240 }, - { x: 29723, y: 3236 }, - { x: 29740, y: 3236 }, - { x: 29757, y: 3238 }, - { x: 29773, y: 3246 }, - { x: 29790, y: 3256 }, - { x: 29807, y: 3268 }, - { x: 29823, y: 3282 }, - { x: 29840, y: 3298 }, - { x: 29857, y: 3314 }, - { x: 29873, y: 3328 }, - { x: 29890, y: 3342 }, - { x: 29907, y: 3352 }, - { x: 29923, y: 3360 }, - { x: 29940, y: 3364 }, - { x: 29957, y: 3366 }, - { x: 29973, y: 3364 }, - { x: 29990, y: 3358 }, - { x: 30007, y: 3352 }, - { x: 30023, y: 3342 }, - { x: 30040, y: 3332 }, - { x: 30057, y: 3322 }, - { x: 30073, y: 3314 }, - { x: 30090, y: 3306 }, - { x: 30107, y: 3302 }, - { x: 30123, y: 3300 }, - { x: 30140, y: 3302 }, - { x: 30157, y: 3308 }, - { x: 30173, y: 3318 }, - { x: 30190, y: 3330 }, - { x: 30207, y: 3344 }, - { x: 30223, y: 3362 }, - { x: 30240, y: 3378 }, - { x: 30257, y: 3396 }, - { x: 30273, y: 3414 }, - { x: 30290, y: 3428 }, - { x: 30307, y: 3440 }, - { x: 30323, y: 3450 }, - { x: 30340, y: 3456 }, - { x: 30357, y: 3458 }, - { x: 30373, y: 3458 }, - { x: 30390, y: 3454 }, - { x: 30407, y: 3448 }, - { x: 30423, y: 3440 }, - { x: 30440, y: 3430 }, - { x: 30457, y: 3420 }, - { x: 30473, y: 3412 }, - { x: 30490, y: 3406 }, - { x: 30507, y: 3402 }, - { x: 30523, y: 3400 }, - { x: 30540, y: 3402 }, - { x: 30557, y: 3408 }, - { x: 30573, y: 3418 }, - { x: 30590, y: 3430 }, - { x: 30607, y: 3444 }, - { x: 30623, y: 3460 }, - { x: 30640, y: 3476 }, - { x: 30657, y: 3494 }, - { x: 30673, y: 3510 }, - { x: 30690, y: 3524 }, - { x: 30707, y: 3536 }, - { x: 30723, y: 3544 }, - { x: 30740, y: 3548 }, - { x: 30757, y: 3550 }, - { x: 30773, y: 3546 }, - { x: 30790, y: 3540 }, - { x: 30807, y: 3532 }, - { x: 30823, y: 3522 }, - { x: 30840, y: 3512 }, - { x: 30857, y: 3500 }, - { x: 30873, y: 3488 }, - { x: 30890, y: 3480 }, - { x: 30907, y: 3474 }, - { x: 30923, y: 3470 }, - { x: 30940, y: 3468 }, - { x: 30957, y: 3472 }, - { x: 30973, y: 3478 }, - { x: 30990, y: 3486 }, - { x: 31007, y: 3498 }, - { x: 31023, y: 3510 }, - { x: 31040, y: 3524 }, - { x: 31057, y: 3538 }, - { x: 31073, y: 3552 }, - { x: 31090, y: 3564 }, - { x: 31107, y: 3578 }, - { x: 31123, y: 3590 }, - { x: 31140, y: 3600 }, - { x: 31157, y: 3612 }, - { x: 31173, y: 3620 }, - { x: 31190, y: 3628 }, - { x: 31207, y: 3636 }, - { x: 31223, y: 3642 }, - { x: 31240, y: 3648 }, - { x: 31257, y: 3652 }, - { x: 31273, y: 3656 }, - { x: 31290, y: 3658 }, - { x: 31307, y: 3660 }, - { x: 31323, y: 3660 }, - { x: 31340, y: 3660 }, - { x: 31357, y: 3660 }, - { x: 31373, y: 3658 }, - { x: 31390, y: 3656 }, - { x: 31407, y: 3654 }, - { x: 31423, y: 3650 }, - { x: 31440, y: 3646 }, - { x: 31457, y: 3644 }, - { x: 31473, y: 3640 }, - { x: 31490, y: 3636 }, - { x: 31507, y: 3634 }, - { x: 31523, y: 3634 }, - { x: 31540, y: 3634 }, - { x: 31557, y: 3638 }, - { x: 31573, y: 3642 }, - { x: 31590, y: 3646 }, - { x: 31607, y: 3654 }, - { x: 31623, y: 3660 }, - { x: 31640, y: 3668 }, - { x: 31657, y: 3676 }, - { x: 31673, y: 3684 }, - { x: 31690, y: 3692 }, - { x: 31707, y: 3696 }, - { x: 31723, y: 3702 }, - { x: 31740, y: 3704 }, - { x: 31757, y: 3704 }, - { x: 31773, y: 3704 }, - { x: 31790, y: 3702 }, - { x: 31807, y: 3700 }, - { x: 31823, y: 3696 }, - { x: 31840, y: 3692 }, - { x: 31857, y: 3688 }, - { x: 31873, y: 3684 }, - { x: 31890, y: 3680 }, - { x: 31907, y: 3680 }, - { x: 31923, y: 3678 }, - { x: 31940, y: 3680 }, - { x: 31957, y: 3682 }, - { x: 31973, y: 3686 }, - { x: 31990, y: 3692 }, - { x: 32007, y: 3698 }, - { x: 32023, y: 3706 }, - { x: 32040, y: 3712 }, - { x: 32057, y: 3720 }, - { x: 32073, y: 3728 }, - { x: 32090, y: 3734 }, - { x: 32107, y: 3740 }, - { x: 32123, y: 3742 }, - { x: 32140, y: 3746 }, - { x: 32157, y: 3746 }, - { x: 32173, y: 3744 }, - { x: 32190, y: 3742 }, - { x: 32207, y: 3738 }, - { x: 32223, y: 3734 }, - { x: 32240, y: 3728 }, - { x: 32257, y: 3724 }, - { x: 32273, y: 3718 }, - { x: 32290, y: 3714 }, - { x: 32307, y: 3712 }, - { x: 32323, y: 3710 }, - { x: 32340, y: 3710 }, - { x: 32357, y: 3710 }, - { x: 32373, y: 3714 }, - { x: 32390, y: 3718 }, - { x: 32407, y: 3722 }, - { x: 32423, y: 3728 }, - { x: 32440, y: 3734 }, - { x: 32510, y: 3734 }, - { x: 32580, y: 3734 }, - { x: 32650, y: 3734 }, - { x: 32720, y: 3734 }, - { x: 32790, y: 3734 }, - { x: 32860, y: 3734 }, - { x: 32930, y: 3734 }, - { x: 33000, y: 3734 }, - { x: 33070, y: 3734 }, - { x: 33140, y: 3734 }, - { x: 33210, y: 3734 }, - { x: 33280, y: 3734 }, - { x: 33350, y: 3734 }, - { x: 33420, y: 3734 }, - { x: 33490, y: 3734 }, - { x: 33560, y: 3734 }, - { x: 33630, y: 3734 }, - { x: 33700, y: 3734 }, - { x: 33770, y: 3734 }, - { x: 33840, y: 3734 }, - { x: 33910, y: 3732 }, - { x: 33980, y: 3728 }, - { x: 34050, y: 3714 }, - { x: 34120, y: 3694 }, - { x: 34190, y: 3666 }, - { x: 34260, y: 3632 }, - { x: 34330, y: 3596 }, - { x: 34400, y: 3562 }, - { x: 34470, y: 3562 }, + { x: 8720, y: 2298 }, + { x: 8790, y: 2298 }, + { x: 8860, y: 2298 }, + { x: 8900, y: 2298 }, + { x: 8970, y: 2314 }, + { x: 9040, y: 2330 }, + { x: 9110, y: 2346 }, + { x: 9180, y: 2362 }, + { x: 9250, y: 2378 }, + { x: 9320, y: 2394 }, + { x: 9390, y: 2410 }, + { x: 9460, y: 2426 }, + { x: 9530, y: 2442 }, + { x: 9600, y: 2458 }, + { x: 9670, y: 2474 }, + { x: 9740, y: 2490 }, + { x: 9810, y: 2506 }, + { x: 9880, y: 2522 }, + { x: 9950, y: 2538 }, + { x: 10020, y: 2554 }, + { x: 10090, y: 2570 }, + { x: 10160, y: 2586 }, + { x: 10230, y: 2602 }, + { x: 10300, y: 2618 }, + { x: 10370, y: 2618 }, + { x: 10440, y: 2618 }, + { x: 10510, y: 2618 }, + { x: 10580, y: 2618 }, + { x: 10650, y: 2618 }, + { x: 10720, y: 2618 }, + { x: 10790, y: 2618 }, + { x: 10860, y: 2618 }, + { x: 10930, y: 2618 }, + { x: 11000, y: 2618 }, + { x: 11070, y: 2618 }, + { x: 11140, y: 2618 }, + { x: 11210, y: 2618 }, + { x: 11280, y: 2618 }, + { x: 11350, y: 2618 }, + { x: 11420, y: 2618 }, + { x: 11490, y: 2618 }, + { x: 11560, y: 2618 }, + { x: 11630, y: 2618 }, + { x: 11700, y: 2618 }, + { x: 11770, y: 2618 }, + { x: 11840, y: 2618 }, + { x: 11910, y: 2618 }, + { x: 11980, y: 2618 }, + { x: 12050, y: 2618 }, + { x: 12120, y: 2618 }, + { x: 12190, y: 2618 }, + { x: 12260, y: 2618 }, + { x: 12330, y: 2618 }, + { x: 12400, y: 2618 }, + { x: 12470, y: 2618 }, + { x: 12540, y: 2618 }, + { x: 12610, y: 2618 }, + { x: 12680, y: 2618 }, + { x: 12708, y: 2618 }, + { x: 12778, y: 2614 }, + { x: 12848, y: 2600 }, + { x: 12918, y: 2578 }, + { x: 12988, y: 2548 }, + { x: 13058, y: 2506 }, + { x: 13100, y: 2478 }, + { x: 13170, y: 2478 }, ] }, { points: [ - { x: 34820, y: 3574 }, - { x: 34890, y: 3586 }, - { x: 34960, y: 3614 }, - { x: 35030, y: 3654 }, - { x: 35100, y: 3692 }, - { x: 35170, y: 3722 }, - { x: 35240, y: 3734 }, - { x: 35310, y: 3774 }, - { x: 35380, y: 3814 }, - { x: 35450, y: 3852 }, - { x: 35520, y: 3886 }, - { x: 35590, y: 3918 }, - { x: 35660, y: 3944 }, - { x: 35730, y: 3966 }, - { x: 35800, y: 3980 }, - { x: 35870, y: 3990 }, - { x: 35940, y: 3994 }, - { x: 36010, y: 3990 }, - { x: 36080, y: 3980 }, - { x: 36150, y: 3966 }, - { x: 36220, y: 3944 }, - { x: 36290, y: 3918 }, - { x: 36360, y: 3886 }, - { x: 36430, y: 3852 }, - { x: 36500, y: 3814 }, - { x: 36570, y: 3774 }, - { x: 36640, y: 3734 }, - { x: 36710, y: 3698 }, - { x: 36780, y: 3664 }, - { x: 36850, y: 3628 }, - { x: 36920, y: 3594 }, - { x: 36990, y: 3558 }, - { x: 37060, y: 3524 }, - { x: 37130, y: 3488 }, - { x: 37200, y: 3454 }, - { x: 37270, y: 3454 }, - ] }, - { points: [ - { x: 37620, y: 3574 }, - { x: 37690, y: 3586 }, - { x: 37760, y: 3614 }, - { x: 37830, y: 3654 }, - { x: 37900, y: 3692 }, - { x: 37970, y: 3722 }, - { x: 38040, y: 3734 }, - { x: 38110, y: 3774 }, - { x: 38180, y: 3814 }, - { x: 38250, y: 3852 }, - { x: 38320, y: 3886 }, - { x: 38390, y: 3918 }, - { x: 38460, y: 3944 }, - { x: 38530, y: 3966 }, - { x: 38600, y: 3980 }, - { x: 38670, y: 3990 }, - { x: 38740, y: 3994 }, - { x: 38810, y: 3990 }, - { x: 38880, y: 3980 }, - { x: 38950, y: 3966 }, - { x: 39020, y: 3944 }, - { x: 39090, y: 3918 }, - { x: 39160, y: 3886 }, - { x: 39230, y: 3852 }, - { x: 39300, y: 3814 }, - { x: 39370, y: 3774 }, - { x: 39440, y: 3734 }, - { x: 39510, y: 3698 }, - { x: 39580, y: 3664 }, - { x: 39650, y: 3628 }, - { x: 39720, y: 3594 }, - { x: 39790, y: 3558 }, - { x: 39860, y: 3524 }, - { x: 39930, y: 3488 }, - { x: 40000, y: 3454 }, - { x: 40070, y: 3454 }, - ] }, - { points: [ - { x: 40420, y: 3574 }, - { x: 40490, y: 3586 }, - { x: 40560, y: 3614 }, - { x: 40630, y: 3654 }, - { x: 40700, y: 3692 }, - { x: 40770, y: 3722 }, - { x: 40840, y: 3734 }, - { x: 40910, y: 3774 }, - { x: 40980, y: 3814 }, - { x: 41050, y: 3852 }, - { x: 41120, y: 3886 }, - { x: 41190, y: 3918 }, - { x: 41260, y: 3944 }, - { x: 41330, y: 3966 }, - { x: 41400, y: 3980 }, - { x: 41470, y: 3990 }, - { x: 41540, y: 3994 }, - { x: 41610, y: 3990 }, - { x: 41680, y: 3980 }, - { x: 41750, y: 3966 }, - { x: 41820, y: 3944 }, - { x: 41890, y: 3918 }, - { x: 41960, y: 3886 }, - { x: 42030, y: 3852 }, - { x: 42100, y: 3814 }, - { x: 42170, y: 3774 }, - { x: 42240, y: 3734 }, - { x: 42310, y: 3698 }, - { x: 42380, y: 3664 }, - { x: 42450, y: 3628 }, - { x: 42520, y: 3594 }, - { x: 42590, y: 3558 }, - { x: 42660, y: 3524 }, - { x: 42730, y: 3488 }, - { x: 42800, y: 3454 }, - { x: 42870, y: 3454 }, - ] }, - { points: [ - { x: 43220, y: 3574 }, - { x: 43290, y: 3586 }, - { x: 43360, y: 3614 }, - { x: 43430, y: 3654 }, - { x: 43500, y: 3692 }, - { x: 43570, y: 3722 }, - { x: 43640, y: 3734 }, - { x: 43710, y: 3750 }, - { x: 43780, y: 3766 }, - { x: 43850, y: 3782 }, - { x: 43920, y: 3798 }, - { x: 43990, y: 3814 }, - { x: 44060, y: 3830 }, - { x: 44130, y: 3846 }, - { x: 44200, y: 3862 }, - { x: 44270, y: 3878 }, - { x: 44340, y: 3894 }, - { x: 44410, y: 3910 }, - { x: 44480, y: 3926 }, - { x: 44550, y: 3942 }, - { x: 44620, y: 3958 }, - { x: 44690, y: 3974 }, - { x: 44760, y: 3990 }, - { x: 44830, y: 4006 }, - { x: 44900, y: 4022 }, - { x: 44970, y: 4038 }, - { x: 45040, y: 4054 }, - { x: 45110, y: 4054 }, - { x: 45180, y: 4054 }, - { x: 45250, y: 4054 }, - { x: 45320, y: 4054 }, - { x: 45390, y: 4054 }, - { x: 45460, y: 4054 }, - { x: 45530, y: 4054 }, - { x: 45600, y: 4054 }, - { x: 45670, y: 4054 }, - { x: 45740, y: 4054 }, - { x: 45810, y: 4054 }, - { x: 45880, y: 4054 }, - { x: 45950, y: 4054 }, - { x: 46020, y: 4054 }, - { x: 46090, y: 4054 }, - { x: 46160, y: 4054 }, - { x: 46230, y: 4054 }, - { x: 46300, y: 4054 }, - { x: 46370, y: 4054 }, - { x: 46440, y: 4054 }, - { x: 46510, y: 4054 }, - { x: 46580, y: 4054 }, - { x: 46650, y: 4054 }, - { x: 46720, y: 4054 }, - { x: 46790, y: 4054 }, - { x: 46860, y: 4054 }, - { x: 46930, y: 4054 }, - { x: 47000, y: 4054 }, - { x: 47070, y: 4054 }, - { x: 47140, y: 4054 }, - { x: 47210, y: 4054 }, - { x: 47280, y: 4054 }, - { x: 47350, y: 4054 }, - { x: 47420, y: 4054 }, - { x: 47490, y: 4054 }, - { x: 47560, y: 4054 }, - { x: 47630, y: 4054 }, - { x: 47700, y: 4054 }, - { x: 47770, y: 4054 }, - { x: 47840, y: 4054 }, + { x: 13660, y: 2478 }, + { x: 13730, y: 2478 }, + { x: 13800, y: 2478 }, + { x: 13870, y: 2478 }, + { x: 13940, y: 2478 }, + { x: 14010, y: 2478 }, + { x: 14080, y: 2478 }, + { x: 14150, y: 2478 }, + { x: 14220, y: 2478 }, + { x: 14290, y: 2478 }, + { x: 14360, y: 2478 }, + { x: 14430, y: 2478 }, + { x: 14500, y: 2478 }, + { x: 14570, y: 3078 }, + { x: 14640, y: 3084 }, + { x: 14710, y: 3090 }, + { x: 14780, y: 3096 }, + { x: 14850, y: 3102 }, + { x: 14920, y: 3108 }, + { x: 14990, y: 3114 }, + { x: 15060, y: 3118 }, + { x: 15130, y: 3124 }, + { x: 15200, y: 3130 }, + { x: 15270, y: 3136 }, + { x: 15340, y: 3142 }, + { x: 15410, y: 3148 }, + { x: 15480, y: 3154 }, + { x: 15550, y: 3160 }, + { x: 15620, y: 3166 }, + { x: 15690, y: 3172 }, + { x: 15760, y: 3176 }, + { x: 15830, y: 3182 }, + { x: 15900, y: 3188 }, + { x: 15970, y: 3188 }, + { x: 16040, y: 3188 }, + { x: 16110, y: 3188 }, + { x: 16180, y: 3188 }, + { x: 16250, y: 3188 }, + { x: 16320, y: 3188 }, + { x: 16390, y: 3188 }, + { x: 16460, y: 3188 }, + { x: 16530, y: 3188 }, + { x: 16600, y: 3188 }, + { x: 16670, y: 3188 }, + { x: 16740, y: 3188 }, + { x: 16810, y: 3188 }, + { x: 16880, y: 3188 }, + { x: 16950, y: 3188 }, + { x: 17020, y: 3188 }, + { x: 17090, y: 3188 }, + { x: 17160, y: 3188 }, + { x: 17230, y: 3188 }, + { x: 17300, y: 3188 }, ] }, ], obstacles: [], - items: [ - { type: "tv", mode: "gravity", x: 4563, y: 1067 }, - { type: "chair", mode: "gravity", x: 4279, y: 1058 }, - { type: "chair", mode: "gravity", x: 4796, y: 1042 }, - { type: "cone", mode: "gravity", x: 16321, y: 4583 }, - { type: "cone", mode: "gravity", x: 16563, y: 4525 }, - { type: "cone", mode: "gravity", x: 16871, y: 4550 }, - { type: "tv", mode: "float", x: 37346, y: 3083 }, - { type: "tv", mode: "float", x: 37979, y: 3367 }, - { type: "cone", mode: "float", x: 40179, y: 3058 }, - { type: "cone", mode: "float", x: 40779, y: 3317 }, - { type: "chair", mode: "float", x: 34529, y: 3300 }, - { type: "chair", mode: "float", x: 35038, y: 3433 }, - { type: "chair", mode: "float", x: 46904, y: 3933 }, - { type: "tv", mode: "float", x: 46688, y: 3892 }, - ], bonusItems: [ - { type: "ctc", x: 21546, y: 3450 }, - { type: "ctc", x: 30488, y: 2908 }, - { type: "cash", x: 37663, y: 3200 }, - { type: "cash", x: 40488, y: 3200 }, - { type: "cash", x: 43246, y: 3250 }, - { type: "guitar", x: 25296, y: 3075 }, - { type: "guitar", x: 5538, y: 992 }, - { type: "cash", x: 10054, y: 2133 }, - { type: "ctc", x: 13729, y: 2933 }, - { type: "cash", x: 34788, y: 3258 }, - { type: "cash", x: 46429, y: 3875 }, + { type: "flour", x: 5888, y: 775 }, + { type: "flour", x: 8804, y: 2017 }, + { type: "flour", x: 13238, y: 2200 }, + { type: "cash", x: 15696, y: 2958 }, ], - goal: { x: 47600, y: 3813, width: 280, height: 640 }, - cameraBounds: { x: -600, y: 0, width: 49240, height: 5556 }, + goal: { x: 17060, y: 2948, width: 280, height: 640 }, + cameraBounds: { x: -600, y: 0, width: 18700, height: 3988 }, }; diff --git a/src/data/themes.js b/src/data/themes.js index 8b866c8..2acff90 100644 --- a/src/data/themes.js +++ b/src/data/themes.js @@ -84,14 +84,21 @@ export const DEFAULT_THEME = { // `wheelTextureKey` is the texture both wheels render with; `wheelRadius` // is the physics/display radius in world pixels; `wheelRestOffsetY` is // the wheel mount point, local to the chassis (y down) - raising it is - // the "lift kit" knob (campaign 2). A bigger radius keeps the wheel - // centered on its axle (the wishbone anchors derive from these - // offsets, so they stay put) - only the size changes. + // the "lift kit" knob (campaign 2); `wheelFriction`/`wheelFrictionStatic` + // are the tire grip coefficients (campaign 2's tires grip harder); + // `suspensionStiffness`/`suspensionDamping` are the shock settings + // (campaign 2's shocks snap back faster and bounce more). A bigger radius + // keeps the wheel centered on its axle (the wishbone anchors derive from + // these offsets, so they stay put) - only the size changes. bus: { chassisKey: 'bus_chassis', wheelTextureKey: 'bus_wheel', wheelRadius: BUS.wheelRadius, wheelRestOffsetY: BUS.wheelRestOffsetY, + wheelFriction: BUS.wheelFriction, + wheelFrictionStatic: BUS.wheelFrictionStatic, + suspensionStiffness: BUS.suspensionStiffness, + suspensionDamping: BUS.suspensionDamping, }, // The three parallax layers, back to front. `far` is the full-viewport // sky; `mid`/`near` are bottom-anchored ground tiles (see PlayScene's @@ -129,6 +136,16 @@ export const THEMES = { // campaign 1's (see BUS.wheelRestOffsetY2) - the bus sits taller and // the bigger wheels hang lower under the body. wheelRestOffsetY: BUS.wheelRestOffsetY2, + // Grippier tires (see BUS.wheelFriction2 / wheelFrictionStatic2 in + // config.js) - less slip under throttle/brake, harder grip on the + // road. + wheelFriction: BUS.wheelFriction2, + wheelFrictionStatic: BUS.wheelFrictionStatic2, + // Stiffer, less-damped shocks (see BUS.suspensionStiffness2 / + // suspensionDamping2) - the wheel returns to its rest position + // faster and the extra spring energy shows up as vertical bounce. + suspensionStiffness: BUS.suspensionStiffness2, + suspensionDamping: BUS.suspensionDamping2, }, }, // Add campaign03: { ... } here when it's ready. diff --git a/src/editor/main.js b/src/editor/main.js index e30768e..05082b3 100644 --- a/src/editor/main.js +++ b/src/editor/main.js @@ -29,7 +29,7 @@ const state = { imported: null, // Smashable props + bonus items placed on the course. Each entry has a // `kind`: 'smashable' (TV/chair/cone - can float or fall, smash off on hit) - // or 'bonus' (CTC/guitar/cash - always float, pop into fireworks on hit). + // or 'bonus' (CTC/guitar/cash/flour - always float, pop into fireworks on hit). // x/y are in the SAME scaled world units the preview canvas plots (and that // the exported level uses); refIndex is the track section it was added // under (rebased on reordering). @@ -204,19 +204,20 @@ const ITEM_SPRITE_FRAMES = { tv: 0, chair: 2, cone: 4 }; const ITEM_SPRITE_CELL = 64; // Bonus items ("Placeables" toggle -> "Bonus items"): float-only collectible -// prizes - CTC box / guitar / cash. See BonusItemManager.js in the game for -// the type/frame/color table; frames here are the BONUS frame of each pair -// (0 CTC, 3 guitar, 6 cash). +// prizes - CTC box / guitar / cash / flour. See BonusItemManager.js in the +// game for the type/frame/color table; frames here are the BONUS frame of +// each pair (0 CTC, 3 guitar, 6 cash, 9 flour). const BONUS_TYPES = [ { id: 'ctc', label: 'CTC Box' }, { id: 'guitar', label: 'Guitar' }, { id: 'cash', label: 'Cash' }, + { id: 'flour', label: 'Flour' }, ]; -const BONUS_COLORS = { ctc: '#e0a040', guitar: '#4b9a45', cash: '#b3ad9c' }; -const BONUS_ICONS = { ctc: 'CT', guitar: 'GT', cash: '$' }; +const BONUS_COLORS = { ctc: '#e0a040', guitar: '#4b9a45', cash: '#b3ad9c', flour: '#cbb58e' }; +const BONUS_ICONS = { ctc: 'CT', guitar: 'GT', cash: '$', flour: 'FL' }; const BONUS_SPRITE = new Image(); BONUS_SPRITE.src = 'assets/sprites/bonus-items.png'; -const BONUS_SPRITE_FRAMES = { ctc: 0, guitar: 3, cash: 6 }; +const BONUS_SPRITE_FRAMES = { ctc: 0, guitar: 3, cash: 6, flour: 9 }; // Samples the terrain surface Y (highest ground) at a given world X - used // to draw the "falls to here" drop line for gravity-mode items in the @@ -249,7 +250,7 @@ function buildItemsForm() { itemsFormEl.appendChild(fieldset); // --- Placeable kind toggle: smashables (TV/chair/cone) vs bonus items - // (CTC/guitar/cash). Only the relevant type+mode controls show below, + // (CTC/guitar/cash/flour). Only the relevant type+mode controls show below, // and clicks on the preview place whichever kind is selected. const kindRadios = []; for (const kind of ['smashable', 'bonus']) { @@ -265,7 +266,7 @@ function buildItemsForm() { }); const label = document.createElement('label'); label.className = 'checkbox-row'; - label.append(radio, kind === 'smashable' ? 'Smashables (TV / Chair / Cone)' : 'Bonus items (CTC / Guitar / Cash)'); + label.append(radio, kind === 'smashable' ? 'Smashables (TV / Chair / Cone)' : 'Bonus items (CTC / Guitar / Cash / Flour)'); kindRadios.push(label); } const kindWrap = document.createElement('div'); diff --git a/src/entities/BonusItemManager.js b/src/entities/BonusItemManager.js index 143f103..69a4c6c 100644 --- a/src/entities/BonusItemManager.js +++ b/src/entities/BonusItemManager.js @@ -1,15 +1,17 @@ import { BONUS_ITEM } from '../config.js'; -// bonus-items.png is 9 frames of 64x64, in order: +// bonus-items.png is 12 frames of 64x64, in order: // 0 CTC box, 1 CTC firework object 1, 2 CTC firework object 2, // 3 Guitar, 4 Guitar firework object 1, 5 Guitar firework object 2, -// 6 Cash, 7 Cash firework object 1, 8 Cash firework object 2. +// 6 Cash, 7 Cash firework object 1, 8 Cash firework object 2, +// 9 Flour, 10 Flour firework object 1, 11 Flour firework object 2. // Each bonus item is followed by its two firework-object frames, which are // the sprites the explosion burst is made of (see _explode below). const BONUS_TYPES = { ctc: { frame: 0, fireworks: [1, 2], label: 'CTC Box', soundKey: 'bonus_ctc' }, guitar: { frame: 3, fireworks: [4, 5], label: 'Guitar', soundKey: 'bonus_guitar' }, cash: { frame: 6, fireworks: [7, 8], label: 'Cash', soundKey: 'bonus_cash' }, + flour: { frame: 9, fireworks: [10, 11], label: 'Flour', soundKey: 'bonus_flour' }, }; export default class BonusItemManager { @@ -121,7 +123,7 @@ export default class BonusItemManager { const { scene } = this; // SFX: the item's own bonus clip (bonus-ctc.mp3 / bonus-guitar.mp3 / - // bonus-cash.mp3, loaded in PreloadScene). cache.audio.exists guards + // bonus-cash.mp3 / bonus-flour.mp3, loaded in PreloadScene). cache.audio.exists guards // against a failed load - same load-tolerant pattern as voiceLine.js / // kidFallSound.js, so a missing clip degrades to silent instead of // throwing. Each item collects at most once, so no overlap concern. @@ -145,6 +147,12 @@ export default class BonusItemManager { const palette = BONUS_ITEM.colors[item.spec.type] || BONUS_ITEM.colors.ctc; const [mainTint, accentTint] = [palette.main, palette.accent]; + // Optional per-type firework override (BONUS_ITEM.fireworkVariants): + // flour's dust puffs launch 2-3x bigger and semi-transparent (the soft + // "cloud of dust" read) - every other type falls back to the standard + // size/full-opacity show. scaleRange is applied per particle below. + const variant = BONUS_ITEM.fireworkVariants[item.spec.type] || {}; + const count = BONUS_ITEM.particleCount; for (let i = 0; i < count; i++) { // Alternate the two firework-object frames around the ring (and the @@ -167,7 +175,10 @@ export default class BonusItemManager { const particle = scene.matter.add.image(x, y, 'bonus_items', frame, { // Circle hitbox, same displaySize/4 convention as the item's own // hitbox above (and SMASH_ITEM.radius) - keeps every circle body in - // the game on one consistent sizing rule. + // the game on one consistent sizing rule. NOTE: this always uses the + // STANDARD particleDisplaySize, even when the sprite below is shown + // bigger (flour's dust variant) - the physics footprint stays the + // same size for every item type, only the visible sprite grows. shape: { type: 'circle', radius: BONUS_ITEM.particleDisplaySize / 4 }, density: 0.001, friction: 0.4, @@ -175,9 +186,22 @@ export default class BonusItemManager { restitution: 0.25, // small bounce when they settle on the ground collisionFilter: { mask: 0xffffffff & ~this.bus.busCategory & ~this.bus.kidCategory }, }); - particle.setDisplaySize(BONUS_ITEM.particleDisplaySize, BONUS_ITEM.particleDisplaySize); + // Per-particle size: every type defaults to the standard particle size; + // a type with a firework variant (flour) varies each particle's scale + // between scaleMin and scaleMax of it, so the burst reads as soft, + // differently-sized puffs rather than one uniform ring. + const scaleRange = variant.scaleMax - variant.scaleMin; + // 1 (no variant) or scaleMin..scaleMax when a variant defines one. + const particleScale = scaleRange > 0 + ? variant.scaleMin + Math.random() * scaleRange + : 1; + particle.setDisplaySize( + BONUS_ITEM.particleDisplaySize * particleScale, + BONUS_ITEM.particleDisplaySize * particleScale, + ); particle.setDepth(5); // above the bus, under the HUD - this is the show, let it read on top particle.setTint(tint); + if (variant.alpha !== undefined) particle.setAlpha(variant.alpha); // e.g. flour's semi-transparent dust // Launch outward. setVelocity is the Phaser Matter component (px per // 60Hz physics step, matching every other velocity in this codebase - diff --git a/src/entities/Bus.js b/src/entities/Bus.js index 742e391..4eca996 100644 --- a/src/entities/Bus.js +++ b/src/entities/Bus.js @@ -12,25 +12,37 @@ export default class Bus { this.scene = scene; const matter = scene.matter; // Per-campaign bus look (see `bus` in data/themes.js): chassis and - // wheel texture, the physics/display wheel radius, and the wheel - // mount point (wheelRestOffsetY - campaign 2's "lift kit", which drops - // the wheels further under the chassis). Defaults to campaign 1's - // values, so existing callers (and any bus built outside a themed - // scene) are unchanged. The chassis texture is visual only - the - // physics body stays the same BUS.chassisWidth/Height rectangle - // either way. (The wishbone anchors below are DERIVED from these - // values, so a bigger radius and/or a lower mount point both stay - // correctly centered on the same axle line.) + // wheel texture, the physics/display wheel radius, the wheel mount + // point (wheelRestOffsetY - campaign 2's "lift kit", which drops the + // wheels further under the chassis), the tire grip (the + // wheelFriction/wheelFrictionStatic coefficients - campaign 2's tires + // grip the road harder), and the shocks (suspensionStiffness / + // suspensionDamping - campaign 2's return faster and bounce more). + // Defaults to campaign 1's values, so existing callers (and any bus + // built outside a themed scene) are unchanged. + // The chassis texture is visual only - the physics body stays the same + // BUS.chassisWidth/Height rectangle either way. (The wishbone anchors + // below are DERIVED from these values, so a bigger radius and/or a + // lower mount point both stay correctly centered on the same axle + // line.) const { chassisKey = 'bus_chassis', wheelTextureKey = 'bus_wheel', wheelRadius = BUS.wheelRadius, wheelRestOffsetY = BUS.wheelRestOffsetY, + wheelFriction = BUS.wheelFriction, + wheelFrictionStatic = BUS.wheelFrictionStatic, + suspensionStiffness = BUS.suspensionStiffness, + suspensionDamping = BUS.suspensionDamping, } = busTheme || {}; this.chassisKey = chassisKey; this.wheelTextureKey = wheelTextureKey; this.wheelRadius = wheelRadius; this._wheelRestOffsetY = wheelRestOffsetY; + this._wheelFriction = wheelFriction; + this._wheelFrictionStatic = wheelFrictionStatic; + this._suspensionStiffness = suspensionStiffness; + this._suspensionDamping = suspensionDamping; this.group = matter.world.nextGroup(true); // Dedicated category so the compartment fixtures below can target kids @@ -239,12 +251,13 @@ export default class Bus { const options = (anchorX) => ({ pointA: { x: anchorX, y: anchorY }, pointB: { x: 0, y: 0 }, - damping: BUS.suspensionDamping, + // Per-campaign shocks (see the constructor's busTheme comment). + damping: this._suspensionDamping, }); return [ - matter.add.constraint(this.chassis, wheel, length, BUS.suspensionStiffness, options(offsetX - BUS.axleSpread)), - matter.add.constraint(this.chassis, wheel, length, BUS.suspensionStiffness, options(offsetX + BUS.axleSpread)), + matter.add.constraint(this.chassis, wheel, length, this._suspensionStiffness, options(offsetX - BUS.axleSpread)), + matter.add.constraint(this.chassis, wheel, length, this._suspensionStiffness, options(offsetX + BUS.axleSpread)), ]; } @@ -252,8 +265,11 @@ export default class Bus { const wheel = this.scene.matter.add.image(x, y, textureKey, null, { shape: { type: 'circle', radius }, density: BUS.wheelDensity, - friction: BUS.wheelFriction, - frictionStatic: BUS.wheelFrictionStatic, + // Per-campaign tire grip (campaign 2's bus_wheel_2 rubber is + // stickier - see the busTheme block in the constructor and + // BUS.wheelFriction2 in config.js). + friction: this._wheelFriction, + frictionStatic: this._wheelFrictionStatic, frictionAir: BUS.wheelFrictionAir, restitution: BUS.wheelRestitution, collisionFilter: { group: this.group, category: this.busCategory }, diff --git a/src/scenes/PreloadScene.js b/src/scenes/PreloadScene.js index 26beced..139c8aa 100644 --- a/src/scenes/PreloadScene.js +++ b/src/scenes/PreloadScene.js @@ -42,6 +42,7 @@ export default class PreloadScene extends Phaser.Scene { this.load.audio('bonus_cash', 'assets/fx/bonus-cash.mp3'); this.load.audio('bonus_ctc', 'assets/fx/bonus-ctc.mp3'); this.load.audio('bonus_guitar', 'assets/fx/bonus-guitar.mp3'); + this.load.audio('bonus_flour', 'assets/fx/bonus-flour.mp3'); loadKidFallSounds(this.load); // Not every level has a voice-over - this just attempts one per level diff --git a/src/util/assetManifest.js b/src/util/assetManifest.js index 6fcc53c..1110f51 100644 --- a/src/util/assetManifest.js +++ b/src/util/assetManifest.js @@ -26,8 +26,8 @@ export const ASSET_MANIFEST = [ // frameWidth/frameHeight are raw SOURCE pixels (one 64x64 cell each), // same convention as the kid sheets above. { key: 'smash_items', path: 'assets/sprites/smash-items.png', width: 64 * WORLD_SCALE, height: 64 * WORLD_SCALE, kind: 'rect', color: 0x4c8a5c, frameWidth: 64, frameHeight: 64 }, - // 9 frames of 64x64 bonus items (CTC box + 2 firework frames, guitar + 2, - // cash + 2 - see BONUS_ITEM in config.js and BonusItemManager.js). + // 12 frames of 64x64 bonus items (CTC box + 2 firework frames, guitar + 2, + // cash + 2, flour + 2 - see BONUS_ITEM in config.js and BonusItemManager.js). { key: 'bonus_items', path: 'assets/sprites/bonus-items.png', width: 64 * WORLD_SCALE, height: 64 * WORLD_SCALE, kind: 'rect', color: 0xe0a040, frameWidth: 64, frameHeight: 64 }, // Campaign 1 ("Evergreen Lake") parallax set - see DEFAULT_THEME in // data/themes.js. The _2 set is campaign 2's; both are 3136x672 natively