Commit Graph

10 Commits

Author SHA1 Message Date
Brian Fertig ebd26ad7ba Stop thrusting ship dead when it hits an obstacle or the tether rim
- constrainShip on Planet, Star, Station, JumpGate, and AsteroidCluster now
  returns a contact boolean (true only when position/velocity/acceleration
  actually changed) so the scene can distinguish "touched" from "no-op".
- GameScene.onPostUpdate reads those flags and, if the ship is in its
  Shift+click thrust state, calls stop() + setState('normal', 'contact')
  the first frame any solid or the tether rim touches it — the hold ends
  and the ship rests on the rim instead of driving through.
- Non-thrust ships are left alone by the rule; their existing arrival/brake
  logic still owns their stop.
- dev/contact.test.mjs: headless tests covering no-contact outside the
  keep-out, contact + push-out + inward-motion strip on approach, no
  spurious contact while sliding off the rim, the full thrust-into-planet
  stop-dead-on-rim integration, and that the rule only fires in thrust.
- dev/smoke-game.mjs: add a third thrusttest check (c) verifying a
  Shift+click straight into the planet stops it dead on the rim.
2026-09-07 00:21:30 -06:00
Brian Fertig 75c9f99ecb Add Shift+click throttle lock for committed-heading flight
- Ship gains a `thrust` state and `thrustToward()` that commits to the heading toward the click point and holds full throttle past it, until a plain click or stop steers out.
- GameScene pointer handler branches on `pointer.event.shiftKey`: Shift+click locks the heading (raw aim), plain click still flies to the clamped stop point.
- Mining teardown no longer stomps the ship state when the player has already moved it into `thrust`/`normal`.
- Update hint text and add unit tests (tests 7–10) plus a live-scene smoke harness (`?thrusttest=1`) verifying past-click flight, steer-back arrival, stop braking, and mining-exit signaling.
2026-09-07 00:06:57 -06:00
Brian Fertig 520cba85f6 Add mining economy: rock shrink, split/shatter, and mineral hold
- Extract minerals from the latched asteroid at ratePerSec × miningSpeed; each mineral shrinks the rock by 1 px so the beam stays latched to its rim.
- Break rocks that lose ~1/3 of their original size: large ones halve in place (beam keeps mining one half), small ones shatter into pieces that fly home and load the hold.
- Add ship.minerals hold with addMinerals/setMinerals capped at stats.mineralStorage; a full hold ends the run instead of grinding the rock away.
- Persist the hold in save/restore (captureState writes ship.minerals, applyRestore restores it) and keep legacy saves working when the field is absent.
- Play new mining_split sfx on each break and surface split/absorbed/storageFull events as console toasts.
- Expose AsteroidCluster rock surgery (setSize/addRock/removeMember) for runtime splits, and add headless Phaser stub + loader plus a mining test suite covering extraction, halving, shattering, full-hold stop, and the hold API.
2026-09-05 11:18:35 -06:00
Brian Fertig fdd5f8a506 Small adjustments to prepare for mining. 2026-09-05 10:29:02 -06:00
Brian Fertig 9ca0fa55a8 Add music system, UI SFX, and ship base stats
- New shared audio voices: js/utils/Sfx.js (playSfxOn/stopSfxOn/sfxPlayingOn)
  and js/utils/Music.js (loop voice + shuffle playlist), both with v4 guard
  rails (cache.audio.has, stopByKey, isPlaying) so missing assets never throw.
- data/music.json: menu loop, shuffled deep-space soundtrack for GameScene,
  and per-world surface loops keyed by planets.png frame; new mp3 assets in
  assets/music/.
- data/sfx.json: add ui_hover/ui_click/ui_window/ui_close/mining_loop and a
  dedicated scan track; wire UI components (buttons, panels, popups, save
  vault) to the shared voice via scene.playSfx seam.
- GameScene: start/stop the shuffle on create/shutdown, stop both soundtrack
  and mining hum on 'sleep' (landing launch+sleep) and resume on 'wake';
  mining hum loops while beam is live and stops quietly on 'stopped'.
- SurfaceScene: preload and loop the world's track from landing through
  takeoff; fix landing frame hand-off to pass sheetFrame instead of the
  texture Frame object.
- MenuScene: preload SFX + menu music, start the menu hum in create, stop it
  on the 'shutdown' event (v4 never calls shutdown() on transition).
- data/ship.json → stats: hullIntegrity/shields/cargoHold/mineralStorage,
  exposed as ship.stats for future combat/trading/mining systems.
- Tests: dev/sfx.test.mjs and dev/music.test.mjs cover the shared voices,
  guards, and data contracts; ship-behavior and system-hud tests extended
  for base stats and the mining hum lifecycle.
2026-09-05 10:10:18 -06:00
Brian Fertig 75767dc5a5 Add ship state machine and let movement break the mining sequence
- Introduce `Ship.state` ('normal' | 'mining') with `setState()` and an
  `onStateChange` callback so the scene can react to state exits.
- Any player-initiated movement (world click or compass autopilot) now
  drops the ship back to 'normal', which ends the mining sequence via the
  scene's handler; Mining.update() enforces the gate as a belt-and-braces.
- Rename `Mining.isLocked` to `isActive` and update GameScene click logic:
  clicks no longer hold during extension — they move the ship and abort the
  arm's reach.
- Tighten the popup-button swallow window from 300 ms to 20 ms and add a
  `containsScreen()` hit-test so only the exact button press is consumed,
  not subsequent deliberate clicks on the panel area.
- Expand the headless mining test to cover the new movement-abort contract:
  world click mid-extension breaks the arm, autopilot retracts the beam,
  and ship state transitions are asserted at every stage.
2026-09-04 18:06:33 -06:00
Brian Fertig 23fcbe7176 Replace procedural ship sprite with spritesheet art and facing offset
- Load `assets/images/ships-player.png` as a Phaser spritesheet via
  `data/ship.json` (`texture`, `frameWidth`, `frameHeight`, `frame`)
- Add `artFacing` config; Ship applies a constant `artOffset` so heading
  math is unchanged while the frame art (facing north) renders correctly
- Scale sprite as `(size * scale) / frameWidth` to preserve the 46 px world
  hull size and collision radius regardless of frame dimensions
- Fall back to the built-in procedural dart when the sheet is missing or
  fails to load, with a console warning in GameScene.create()
- Update ship-behavior tests to account for `artOffset` in heading checks
- Add source art (`ships-player.psd`, landed-ship reference) and a demo
  video; document the new pattern in README and PROJECT_NOTES
2026-09-03 21:40:33 -06:00
Brian Fertig e7b52cc33d Add the home planet: a solid world the ship can approach but not enter
Adds the player's home planet to the starting system, rendered from the new
planets.png spritesheet. The planet is a solid disc: the ship may come within
shipClearance of its rim but can never cross it, and clicks on the planet
clamp to the keep-out rim so the ship always has a reachable destination.

- js/entities/Planet.js: solid-disc entity with a circle keep-out constraint
  (constrainShip/resolve, pure and scene-free) plus edgePoint/aimPoint helpers
- data/planets.json (+ manifest entry): texture, frame size, scale, homePlanet,
  shipClearance, spawnDistanceFromEdge
- Ship.js: exposes a radius (half the hull width) for the keep-out math
- GameScene.js: loads the spritesheet, spawns the home world at the origin,
  starts the ship ~150 px off its rim in a seed-derived direction, and applies
  the constraint each frame after the ship moves
- dev/planet.test.mjs: Node tests of the constraint against real config;
  dev/test-game.html gains a <base href> so asset paths resolve from /dev
2026-09-03 14:44:01 -06:00
Brian Fertig 7cf96bb237 Ship Travel and Orientation Updates 2026-09-03 10:25:54 -06:00
Brian Fertig eddbedbf1c Add v0.1 foundation: menu, click-to-fly ship, and JSON config system
- Boot the game from a static server with no build step (Phaser 4 vendored in lib/)
- Main menu (New Game button) and GameScene where clicking makes the ship fly there
- All tunables live in data/*.json (game/menu/ship), loaded via manifest + Config singleton
- Ship behavior driven by arcade physics (thrust, drag, maxSpeed, arrival) with a Node test harness (dev/ship-behavior.test.mjs) and a dev smoke page that boots straight into GameScene
- Project conventions documented in docs/PROJECT_NOTES.md; README rewritten to describe layout, run instructions, and dev tools
2026-09-02 22:31:34 -06:00