Add flour bonus item type with custom firework variant
- Extend bonus items spritesheet from 9 to 12 frames (add flour + 2 firework objects) - Add `flour` type to BONUS_ITEM config with warm off-white/tan color palette and firework variant (2-3x scale, half opacity for dust cloud effect) - Implement per-type firework variants in BonusItemManager._explode() - particles can now have varied sizes and alpha while maintaining standard physics body size - Add flour SFX asset (bonus-flour.mp3) and preload it - Update editor to support placing flour bonus items with appropriate icon, color, and sprite frame - Update all documentation (README, sprites.md) to reflect the new bonus item type Additionally: - Add campaign 2 bus physics customization: grippier tires (higher friction coefficients) and stiffer/less-damped suspension for bouncier ride - Thread per-campaign wheel friction and suspension parameters through Bus entity from themes.js - Redesign level11 with shorter course, fewer kids (4 vs 3), tighter time limit (42s vs 119s), and flour bonus items replacing most cash/CTC/guitar
This commit is contained in:
parent
8cba629232
commit
1eea919c8b
21
README.md
21
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
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 86 KiB |
Binary file not shown.
Binary file not shown.
10
sprites.md
10
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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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 -
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue