A top-down open-world survival game that runs entirely in your browser.
Wash ashore with nothing. Chop, mine, forage, craft, build, fight, and sail between islands before thirst, hunger, or the wolves get to you first.
Castoff is a complete survival sandbox built from scratch β no game engine, no physics library, no sprite packs. The world is generated procedurally and drawn with raw Canvas 2D calls, wrapped in an Angular shell that handles the UI.
It's a real loop: manage three vitals, gather across a biome-varied archipelago, climb a tool tier, fortify a base, survive the night, and sail to new islands.
A 100Γ100 tile archipelago generated at runtime with wobbly, organic coastlines and blended shorelines β three islands, each with its own resource character:
| Island | Location | Character |
|---|---|---|
| Home | Center | Balanced β a fair start |
| Rocky Isle | Northeast | Stone-rich, sparse trees |
| Forest Isle | Southwest | Dense forest and berries β and wolves |
Health, thirst, and hunger drain in real time. Let thirst or hunger bottom out and health starts draining too. Eat berries, drink at the shore, or rest beside a campfire to recover.
Tools aren't cosmetic β the best one you own auto-equips as your weapon, and a matching tool doubles your gather yield.
| Item | Cost | Effect |
|---|---|---|
| πͺ Axe | 3 wood | 2Γ wood per chop Β· 14 dmg |
| βοΈ Pickaxe | 2 wood, 2 stone | 2Γ stone per mine Β· 12 dmg |
| π‘οΈ Spear | 4 wood, 2 stone | Longest reach Β· 18 dmg |
| πΆ Raft | 8 wood, 3 stone | Sail between islands |
| π₯ Campfire | 6 wood | Light source + passive healing |
| π§± Wall | 4 wood | Solid barrier β fortify a base |
| π¦ Chest | 5 wood | Persistent storage |
Bare fists deal 8 damage β an axe nearly doubles that.
A full cycle runs every three minutes. Nights fall genuinely dark: visibility collapses to a bubble around you, punched open by any campfire you've built. Wolves see much farther after sundown, so darkness is a real threat rather than a palette swap.
Two enemy types with distinct AI, speed, and aggression. Crabs patrol the sand; wolves hunt the forest isle β faster, harder-hitting, with eyes that glow at night. Both wander until they spot you, then chase and strike.
Build a raft, board it at any shoreline, and cross open water. Step onto land and you disembark automatically.
All three islands, your heading, your structures, and live enemy positions at a glance.
Progress persists to localStorage every 5 seconds and on tab close β position,
vitals, inventory, harvested resources, built structures, and time of day all
survive a refresh.
| Input | Action |
|---|---|
| W A S D / arrows | Move |
| E | Open the context action wheel |
| 1 β 4 | Pick a wheel action (or click it) |
| Space | Attack |
| Esc | Close wheel / chest |
The action wheel is contextual β it only offers what's valid where you stand. Next to a tree you get Chop; at the shore, Drink and Build Raft; facing open ground, Build Wall and Build Chest.
git clone https://github.com/arafatomer66/castoff.git
cd castoff
npm install
npm startThen open http://localhost:4200.
npm run build # production build
npm run build:pages # build for GitHub Pages (sets base href)Requires Node 24+.
The core design decision: Angular renders the UI, raw Canvas renders the world. Pushing 10,000 tiles through change detection every frame would be pointless overhead β so the game loop lives in plain TypeScript classes, and only the state the HUD actually cares about crosses into Angular, as signals.
src/app/game/
βββ game-engine.service.ts # Game loop, rendering, signal bridge to the UI
βββ core/
β βββ camera.ts # Viewport follow + worldβscreen transform
β βββ input.ts # Key state + edge detection
β βββ util.ts # Deterministic hash, clamp, lerp, colour
βββ world/
β βββ tilemap.ts # Procedural archipelago generation
β βββ world.ts # Spatial buckets, collision, resource scatter
β βββ actions.ts # Context-sensitive action wheel builder
β βββ resource-node.ts # Trees, rocks, berry bushes
β βββ structure.ts # Campfires, walls, chests
β βββ tile-types.ts # Terrain palette + walkability
βββ entities/
β βββ player.ts # Position, vitals, inventory
β βββ enemy.ts # Crab & wolf state
βββ combat/combat.ts # Weapon tiers, enemy AI, damage resolution
βββ persistence.ts # localStorage save/load
βββ game-canvas/ # Canvas host component
βββ hud/ # Stats, hotbar, action wheel, minimap, chest
- Deterministic generation β a hash function seeds terrain and resource placement, so the same world regenerates identically on every load. Saves need only store deltas (what you harvested), never the whole map.
- Spatial bucketing β resource nodes are indexed by tile, keeping proximity queries O(nearby) instead of scanning every node each frame.
- Cached minimap terrain β rasterized once at 1px-per-tile and blitted per frame, rather than re-walking 10,000 tiles.
- Composite-op lighting β night is a dark overlay with light sources punched
out via
destination-out, giving soft radial falloff cheaply. - Zero game dependencies β every sprite is drawn with Canvas primitives. Nothing but Angular itself is installed.
Pushing to main triggers a GitHub Actions workflow that builds the app and
publishes it to GitHub Pages. It's a fully static bundle with no backend, so the
whole game ships as a handful of files.
- More biomes and a larger archipelago
- Tool durability and higher tiers
- Cookable food and a crafting bench
- Mobile touch controls
- Ambient audio and effects
MIT β do what you like with it.