asteroid-logistics

A procedually generated asteroid mining and logistics simulation game built with PixiJS · play asteroid-logistics · devlog

  • v0.34.1 - split building stories

    Split the monolithic BuildingShowcase Storybook component into individual stories per building type — Habitat, Mine, LandingPad, ProbeFactory, ShipFactory, Spaceport, and Production buildings. Each story lives in src/components/buildings/ with a shared BuildingDecorator, BuildingShell, and useBuildingCanvas hook for consistent rendering. Renamed “showcase” to “buildings” throughout.

  • v0.34 - freighter polish and log indicator

    Polished the freighter system with per-spaceport countdown timers and a branded BuildingId type for type-safe building references. Fixed a countdown bypass bug where freighters could skip their departure timer. Added debug controls for freighter transition speed and a dynamic speed multiplier.

    Added a log count indicator in the top bar with a debounced counter and pulse animation, plus log buffer clearing on page reload with a fix for the clear race condition. Unified entity selection into a single selectionAtom, dropping the per-domain getSelected methods.

    Fixed spaceport click area hit detection and added typed showcase component props with branded type Storybook stories.

  • v0.33 - freighters and spaceport

    Added spaceport buildings that spawn freighter ships for hauling cargo between asteroids. Freighters have their own behavior system — a state machine that drives ship actions like docking, loading, transiting, and unloading. The ships modal now shows freighters with a find button that pans the camera to the selected ship.

    Replaced GSAP with a custom tween engine to eliminate the dependency and gain more control over animation timing. Rewrote the game CLI from a plain JS script to TypeScript with Commander, adding proper error handling and throwing on silent no-ops instead of swallowing them.

    Fixed a cascade of issues: MineMask destroy order crash on load, freighter HUD/landing/thrust/pathing bugs, localStorage quota overflow, and PixiJS deprecation warnings. Unified building selection through BuildingManager and added a ship scuttle command. Auth errors and debug state now persist in saves.

  • v0.32 - CLI expansion and ship fixes

    Expanded the game CLI with traversable query methods — you can now browse command groups and drill into entity state interactively. Added the full HTTP bridge between the CLI and the running game.

    Ships now persist across asteroid regeneration instead of being lost. Fixed a stale orbit center bug where ships would orbit the wrong point after an asteroid moved, and fixed an orphaned ramp-down animation that was killing landing thrust prematurely. Added ShipOrbit tests to cover the orbit calculation edge cases.

  • v0.31 - game CLI and ships modal

    Built the asteroids game CLI — a command-line interface that exposes the Game.ts facade over HTTP via a Vite plugin. The CLI uses a gameApiRegistry to map method names to game operations, with resolveParam handling entity ID resolution and serializeResult formatting responses. This lets me (or an AI agent) inspect and control the running game from the terminal.

    Added a ships modal accessible from a new icon-based top bar, replacing the old menu button. The modal lists all ships with their current status and location. Blocked keyboard hotkeys while typing in form inputs so ship names and other text fields don’t trigger game actions.

  • v0.30 - production progress and polish

    Added a production progress bar to the building HUD showing real-time recipe completion. Selecting a mine now reveals its resource regions on the asteroid surface, making it easy to see what a mine is extracting.

    Fixed a mine region rendering artifact when regions were hidden, and fixed the oval hover effect on the menu close button. Made the save menu handle loading states gracefully during save and delete operations.

  • v0.29 - ship jobs and cloud saves

    Big day. Added a ship delivery job system — ships can now be assigned jobs to haul resources between asteroids. Moved the ship build button into the factory HUD for a cleaner flow.

    Implemented Firebase authentication and cloud saves so game state persists across devices. Fixed several persistence bugs: landing pad reservations lost on reload, landed ship renderers not recreated, buildings lost on cross-machine save/load, and thrust disappearing on return leg transitions.

    Migrated the UI from custom styles to Tailwind + Base UI, then further to MUI with the Exo 2 font. Added a curl-able world dump endpoint for inspecting game state from the terminal. The HUD now shows load progress, and the dump output includes resource buffers and ship jobs.

  • v0.28 - session persistence

    Added game persistence — asteroids, buildings, and ships now survive across browser sessions via GamePersistence. Buildings and ships serialize their state on save and restore it on load, so you can close the tab and pick up where you left off.

    Added ChemLab and BioReactor production buildings. The ProductionManager now uses proportional resource allocation when multiple buildings compete for the same inputs, preventing starvation.

    Fixed region labels rendering incorrectly on concave polygons by extracting a proper calculateLabelPosition utility. Fixed ship selection not working on landing pads, and fixed angled liftoff after a reload where ships were restoring stale rotation state.

  • v0.27 - meat production path

    Added the meat production path — CultureVat and SlabCutter buildings that process raw resources into food. Each has its own visual style and production recipe. The building HUD now shows the active recipe with input and output resources.

    Fixed the mine resource percentage calculation which was reporting incorrect values, and added boundary rejection so mines can’t be placed where they’d pierce the asteroid edge. Added tests for both mine boundary checks and resource percentage calculations. Fixed regressions in the production and mine HUD displays.

  • v0.26.1 - complexity reduction

    Focused on reducing complexity across managers. The biggest win was breaking ShipManager apart — extracted landShipOnPad, spawnShipAtFactory, and transitionToAsteroid into their own modules. Each handles a specific ship lifecycle operation that was previously buried in the monolithic manager.

    Simplified MouseManager, FogOfWarManager, BuildingManager, and AsteroidManager by breaking up long methods and reducing nesting. Cleaned up shipAnimations and AsteroidShape rendering. Extracted a localToWorld coordinate transform utility shared across ship operations.

  • v0.26 - grouped facade and bug fixes

    Refactored Game.ts into a proper grouped facade pattern — slimmed it down from a monolithic class to a thin delegation layer that organizes methods into domain groups. Extracted BuildingManager from the game operations, which took a big chunk of building-related logic out of Game.ts.

    Fixed a phantom ship bug caused by a reconcile race condition in ShipManager, and fixed habitats piercing the asteroid boundary when building basements. Added a dump world data debug button for inspecting the full game state. Renamed GameOperations to Game throughout.

  • v0.25 - Game.ts facade

    Introduced the Game.ts facade — a single entry point that exposes the entire game API as organized domain groups (game.asteroids, game.buildings, game.ships, game.buildMode). This replaces the previous GameOperations approach with a cleaner grouped API. Added useGame as the React hook for accessing it.

    Separated asteroid rotation into its own atom to fix an FPS regression where rotation updates were triggering unnecessary re-renders. Cleaned up all the migration planning docs (PLAN.md, RULES.md, STATE-UPDATE.md, etc.) now that the refactor is complete. Updated ARCHITECTURE.md to document the new structure.

  • v0.24 - atom iteration

    Continued iterating on the atom-based state architecture. Refactored GameOperations to streamline the API surface and simplified AsteroidShape rendering significantly. Expanded AsteroidManager to handle more lifecycle responsibilities and added ShipManager tests.

    Removed the old generateLandingPads utility in favour of inline generation within the manager. Slowed down asteroid rotation for a more relaxed feel. Renamed the sync method for clarity across the codebase.

  • v0.23 - state migration phases 6-7

    Continued the state migration through phases 6 and 7. Extracted all ship animations into a dedicated shipAnimations.ts module and added animateDrillDepth for mine drilling transitions. The GameOperations facade grew substantially — it now handles ship routing, landing toggles, probe queuing and launching, and production management.

    Simplified entity classes significantly by moving logic up into managers and operations. Ship, Habitat, Mine, ProbeFactory, and other entities shed their imperative methods in favour of being driven by the operations layer. Removed AsteroidInventory and Inventory from entities in favour of the new AsteroidState and ShipState data types. Added a shipsAtom and expanded buildingsAtom with richer building state serialization.

  • v0.22 - state migration step 1

    Started migrating game state to a proper data layer. Added BuildingState types that serialize building state into plain objects for the React layer, with a buildingsAtom that bridges the game engine and UI. Introduced useGameOperations as a React hook to access the game operations facade.

    Updated all HUD components to consume state through the new atoms instead of reaching into game objects directly. Buildings now expose serialization methods to produce their state snapshots. This is the first step toward fully decoupling the rendering engine from the React UI.

  • v0.21 - architecture refactor

    Big restructuring day. Moved all game entities and managers under src/game/core/ and introduced a GameOperations facade that provides a clean CQRS-style API for the React layer to interact with game state through Jotai atoms. This separates selection state management from the game engine — atoms now derive from GameOperations rather than reaching into managers directly.

    Slimmed down GameManager significantly by delegating responsibilities to the new operations layer. Removed the old E2E tests and callback bridge in favour of the new architecture. Added unit tests for Habitat and Mine entities with test helpers for creating game and asteroid instances.

    Fixed mine hole cleanup when a mine is destroyed. Merged the separate vitest config into the main vite config and suppressed PixiJS deprecation warnings.

  • v0.20 - production system

    Built the production system. A ProductionManager runs recipes that transform input resources into outputs over time, with progress bars on buildings. Added three new production building types — AlgaeTank, BlockFormer, and Centrifuge — each with their own visual style. Buildings that produce resources now track an Inventory and feed into an AsteroidInventory that aggregates everything per asteroid.

    Refactored the monolithic Hud.tsx into separate components: AsteroidHud, BuildingHud, ShipHud, and LevelControls. Added a confirmation modal for destructive actions like the new destroy button on the building HUD.

    Region labels now render at zoom-independent sizes so they’re always readable. Made the mine mask translucent in region view mode. Added an AsteroidDebug pane with a dump button for inspecting asteroid state, and extracted drawDrillShape into a shared utility.

  • v0.19 - habitat controls and polish

    Added habitat level controls — build up and down to grow or shrink habitat towers, plus demolish controls to tear levels back down. Landing pads are now toggleable so you can enable or disable them. Both are controlled through the HUD when the building is selected.

    Made the asteroid field circular instead of the previous rectangular distribution, which looks much more natural. Added a toggleable FPS counter widget and a pointer debug pane for tuning glow settings on selected entities. Fixed the selection glow animation and click feedback. Added a ships debug toggle to the debug panel.

  • v0.18 - probes and drilling

    Christmas day coding session. Added probe factory buildings that queue and launch probes to explore the asteroid surface, expanding the fog of war. The ProbeManager handles probe lifecycle from launch to landing, with a debug panel for tuning probe parameters.

    Mines now have drill depth controls displayed in the HUD — you can drill deeper or shallower, and a MineMask overlay shows the resource percentage being extracted at the current depth. The intersection area calculation figures out how much of each Voronoi resource region falls within the mine’s drill radius.

    Limited camera zoom-out to the revealed fog area so you can’t zoom past the explored regions. Extracted shared button and menu styles into their own modules and refactored BuildMenu to use them.

  • v0.17 - building selection

    Added building selection — clicking a building now selects it and shows its details in the HUD. Extracted a shared SelectionBehavior to handle the selection logic across all building types (habitats, mines, landing pads, ship factories). Each building’s draw function now renders a selection highlight when active.

    Fixed a bug where asteroids would disappear on hover due to a rendering issue in AsteroidShape. Also improved the MouseManager to properly handle click targets across buildings and other entities.

  • v0.16 - mine buildings and voronoi regions

    Added mine buildings to the build menu. Mines reveal the resource regions beneath them using a MineMask with a darkened fill overlay that masks the fog-of-war over the mined area. The region reveal creates a nice exploration feel where you discover what resources are under each segment.

    Switched the region generation algorithm to use Voronoi tessellation, which produces much more natural-looking resource distributions. Borders between adjacent regions of the same resource type are now hidden so contiguous deposits read as a single area. Extracted shared utilities like drawPolygonPath and regionEdges into their own modules.

  • v0.15 - resource regions

    Started building the mineral discovery and extraction system. I added resource types and two region generation algorithms — a basic one that creates simple contiguous regions and a more sophisticated generator that produces organic, overlapping resource distributions across asteroid surfaces. A RegionsOverlay renders the regions visually and a ResourcesDebug panel controls the generation parameters across all asteroids.

    Set up Playwright for e2e testing with an asteroid screenshot test that captures the rendered asteroid for visual regression. Added .nvmrc for consistent Node versions.

    Fixed build mode breaking after zoom-to-asteroid and added auto-zoom to the first asteroid on startup. Extracted selectAsteroidByName into its own state module.

  • v0.14 - ship factory

    Added a README to the project. Set up the browser to open automatically on dev server launch.

    Fixed ship visibility when fog is disabled and fixed fog resize when the window resizes. Added ship factory buildings with orbit exit debugging - buildings that produce new ships!

    Improved the orbit system: buildings now show their exit points, ship orbits update when clearance changes, and the orbit entry calculation is shared for pad takeoff. Tuned thrust behavior - reduced thrust during liftoff rotation and added thrust ramp-down on orbit entry.

    Fixed a janky issue with multi-ship transitions. Split WorldDebug into separate panels for better organization. The ship factory now has a proper build queue system, and ships reinitialize correctly when asteroids regenerate.

  • v0.13 - building placement

    Set up VS Code launch configuration for debugging.

    Zoom now centers on the current selection or cursor position rather than the viewport center - much more intuitive. Fixed selection box strokes to render correctly at all zoom levels.

    The big feature was the building placement system! You can now place structures on asteroids.

  • v0.12 - fog of war and HUD

    Implemented fog of war! Used a smoke effect with soft noisy edges that looks great. Added a debug tool for revealing fog and an animation that reveals from the edges. The fog panel has a reset button for testing.

    Added a HUD system using Jotai for state management. Asteroids now display their names, and selected ships show in the HUD. Fixed ship selection stroke rendering gaps and clamped keyboard zoom to stay within limits.

    Did some deployment fixes - trailing slash redirects, renamed the page title, and switched to relative base paths for assets.

  • v0.11 - controls and visual polish

    Added full keyboard support - arrow keys and WASD for panning, Q/E for zooming.

    Visual improvements were the star of the show today. Added a parallax starfield with subtle glow effects in the background - really sells the space vibe. Added hover glow for selectable items so it’s clear what you can interact with.

    Ships got a lot of love: they now rotate toward their target on liftoff, have thrust particle effects during flight, ramp down thrust when arriving at orbit, and the orbit-to-path transition is smoother. Also optimized the orbit path to landing pad routing.

  • v0.10 - CI/CD and landing pads

    Cleaned up unused methods and tweaked member accessibility modifiers in the code. Set up Netlify for CI/CD deployment - the game is now live on the web!

    The main feature was the ship landing pad system. Ships now have designated spots to land on asteroids, with proper entry point calculations for approach. This makes the docking feel much more intentional.

  • v0.9 - selection fix

    Fixed ship click behavior - clicking a ship now properly deselects others instead of adding to the selection.

  • v0.8 - MouseManager and multi-selection

    Created a MouseManager to centralize all mouse handling - selection, panning, zooming, and clicking are now in one place. Moved path interaction into it as well. Right-click on an asteroid now moves selected ships there.

    Did a bunch of renaming for clarity: SavedPairsManager became SavedRoutes, GameViewport became GameManager. Replaced all hardcoded colors with the open-color palette for consistency.

    Fixed several bugs: multi-ship movement on right-click, ship snap-back at end of path, and clamped zoom/pan to world bounds so you can’t scroll into the void.

    Refactored Asteroid into its own directory, extracted path animation and geometry helpers, and added jscpd for detecting duplicate code. Made ship pathfinding async with a cached graph for better performance.

  • v0.7 - architecture improvements

    Added style linter rules to Biome for consistent code formatting. Refactored the pathfinding code into proper modules and renamed files to match their export names.

    The big user-facing feature today was ship selection and click-to-navigate. You can now click a ship to select it, then click on another asteroid to send it there. Also made it so each asteroid spawns with its own ship.

  • v0.6 - cleanup

    Cleanup day. Removed the refactor checks that were getting in the way, deleted old unused scripts, and reorganized the debug systems. Moved PathDebug into a dedicated path directory and WorldDebug into a world directory.

    Cleaned up dependencies and quieted down the test output. Much tidier codebase now.

  • v0.5 - arc tangent pathfinding

    Continued the pathfinding work. Implemented arcTangentPathFinder for smoother curved paths. Added persistence for path debug points and save/restore functionality for debug pairs.

    The big improvements were internal tangents support, precomputing the tangent graph for performance, and making pathfinding async so it doesn’t block the main thread.

    Simplified the orbit system by replacing elliptical orbits with circular ones - less realistic but much easier to reason about for pathfinding. Removed the Dubins path approach in favor of the arc tangent system.

    Added ship transitions between asteroids with GSAP easing for smooth animations. The transition now has a pre-tween to the path start, smooth orbit-to-path transitions, and ships can be interrupted mid-flight. Also added a station visibility toggle for debugging.

  • v0.4 - pathfinding deep dive

    Massive session today. Fixed a blank screen bug that was preventing asteroids from generating on init, then dove deep into the pathfinding system.

    Added debug visualization for paths which was essential for debugging. The path finding went through several iterations - fixed external tangent line calculations, corrected arc directions, improved the algorithm with proper tangent points. I extracted a dedicated tangentPathFinder module to keep things clean.

    Also added persistence for debug pane values (finally!), set up a commit message validation script, and created slash commands for the dev workflow. Added test cases for the pathfinding edge cases I discovered.

    Ships can now transition between asteroids which is a huge milestone!

  • v0.3 - stations and orbits

    Big day! I added landing stations on asteroids and implemented an orbit system so objects can circle around asteroids. This is the foundation for how ships will approach and dock.

    Also set up the verify script for code quality checks and added the first ship entity. Left things in a work-in-progress state with some rough edges to polish later.

  • v0.2 - zoom fix

    Quick fix today - the zoom functionality was broken and needed some attention. Not glamorous work but necessary.

  • v0.1 - project genesis

    Today I kicked off the Asteroid Logistics project. Started with the basic scaffolding - got the initial project structure in place, added a viewport system for handling the game canvas, and integrated Tweakpane for debugging controls.

    The main focus was getting asteroids rendering properly. I implemented the core asteroid entity with configurable radius and rotation. Added interactivity so you can click on them, and then expanded to support multiple asteroids in the world. Feels good to have something tangible on screen already!