monsterplex/src/config.js

128 lines
5.3 KiB
JavaScript

// Every spatial (pixel) constant in this file and in src/data/levels/*.js is
// multiplied by WORLD_SCALE, so the whole game - canvas, physics bodies,
// terrain, UI - resizes together. Change this one number to rescale it again.
export const WORLD_SCALE = 2; // 960x540 base design -> 1920x1080
export const GAME_WIDTH = 960 * WORLD_SCALE;
export const GAME_HEIGHT = 540 * WORLD_SCALE;
// Set true to show live g-force / debug readouts during PlayScene.
export const DEBUG = false;
export const STORAGE_KEY = 'monsterplex.progress.v1';
// Matter runs Phaser's default fixed 60Hz step.
export const PHYSICS_TIMESTEP_SECONDS = 1 / 60;
export const BUS = {
chassisWidth: 170 * WORLD_SCALE,
chassisHeight: 64 * WORLD_SCALE,
// Measured directly from assets/sprites/bus_chassis.png's baked-in wheel
// wells (it's a real photo bus - long rear overhang, short front hood, so
// the axles are NOT symmetric around the chassis center). Offsets are from
// the chassis center; re-measure these if bus_chassis.png is replaced.
wheelRadius: 17 * WORLD_SCALE,
rearWheelOffsetX: -35 * WORLD_SCALE,
frontWheelOffsetX: 64 * WORLD_SCALE,
// Where the wheel's CENTER rests at equilibrium - this is the measured
// wheel-well position itself, not an attachment point the wheel then
// hangs further below (that was the placeholder-art version's model,
// before there was real art dictating exactly where the wheel belongs).
wheelRestOffsetY: 22 * WORLD_SCALE,
// Horizontal spread between the two suspension links each wheel hangs
// from (a "wishbone") - a single point-to-point constraint can't resist
// sideways drift at all (it's radially symmetric), so each wheel is held
// by two constraints spread by this much, which resists side-to-side
// wander while still allowing the wheel to compress/extend vertically.
axleSpread: 6 * WORLD_SCALE,
maxSeats: 5,
// Density/friction/stiffness/damping are dimensionless ratios, not pixel
// distances - they don't scale with WORLD_SCALE.
chassisDensity: 0.0015,
chassisFriction: 0.4,
chassisFrictionAir: 0.01,
wheelDensity: 0.004,
wheelFriction: 0.9,
wheelFrictionStatic: 1.4,
// 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)
// and was the main reason the bus felt sluggish rather than Trials-fast.
wheelFrictionAir: 0.008,
// Some bounce on landing, not just suspension absorbing everything.
wheelRestitution: 0.3,
// Softer and less damped than before - more travel, and lets it actually
// oscillate (bounce) instead of settling immediately - "more shocks."
suspensionStiffness: 0.45,
suspensionDamping: 0.08,
// 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.
suspensionTravel: 12 * WORLD_SCALE,
// Angular velocities/torque steps are rotational (radians), not linear
// pixel distances, so they're left unscaled - wheel radius already scaled,
// so linear surface speed (angularVelocity * radius) scales automatically.
// Pushed way up from the original values for Trials/Snuggle-Truck-style
// speed - the old numbers made the bus crawl.
maxWheelAngularVelocity: 5,
driveTorque: 0.6,
brakeTorque: 0.4,
maxBrakeAngularVelocity: 3.5,
// Measured via headless testing: spinning the wheel faster alone barely
// moved the chassis - past a point the wheel just slips (friction force
// is capped by frictionCoefficient * normalForce regardless of how fast
// the wheel spins beyond matching ground speed), so throttle applies a
// direct force to the chassis itself, along its current facing/tilt, on
// top of the wheel spin. This is the standard fix in arcade 2D driving
// games for exactly this problem. Expressed as target acceleration
// (Bus.js computes force = chassis mass * this) rather than a raw force,
// so it stays correct if chassisDensity/size ever changes - tune these
// to change top speed feel.
driveAcceleration: 0.011,
brakeAcceleration: 0.007,
// Bumped up to stay responsive at the new higher speed - sluggish lean
// control would feel wrong on a bus that's now moving quickly.
maxLeanAngularVelocity: 0.13,
leanTorqueStep: 0.018,
};
export const GFORCE = {
// Scaled with WORLD_SCALE so "meters" keeps the same real-world meaning
// relative to the bus, and ejectThresholdG doesn't need re-tuning.
pixelsPerMeter: 50 * WORLD_SCALE,
ejectThresholdG: 6, // primary tuning knob - not physically derived, tune by playtesting
gracePeriodMs: 500,
ejectImpulseMagnitude: 0.03 * WORLD_SCALE,
// A single hard landing can stay above threshold for several consecutive
// physics ticks; without a cooldown that would eject several kids from one
// impact instead of one. Debounces ejections to one per impact.
ejectCooldownMs: 400,
};
export const KID = {
radius: 14 * WORLD_SCALE,
density: 0.001,
friction: 0.6,
seatStiffness: 0.22,
seatDamping: 0.1,
seatLength: 4 * WORLD_SCALE,
settleTimeMs: 2000,
};
export const CAMERA = {
lerpX: 0.1,
lerpY: 0.1,
deadzoneWidth: 220 * WORLD_SCALE,
deadzoneHeight: 140 * WORLD_SCALE,
};
export const TERRAIN_DEPTH = 400 * WORLD_SCALE;