128 lines
5.3 KiB
JavaScript
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;
|