Restructure into monorepo: game/ is the Godot lane

Repo root moves up from game/ to the project folder. Lanes live as top-level
dirs (game/ now, web/ planned); LANES/ will hold parallel-session specs.
3D-STORE asset vault stays out of git. History preserved as renames.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Monster Robot Party 2026-07-14 15:33:13 +10:00
parent b78ea04183
commit 5852322606
29 changed files with 126 additions and 49 deletions

13
.gitignore vendored
View File

@ -1,9 +1,8 @@
# Godot 4 editor cache & reimportable data
.godot/
# Godot export output
/build/
/export/
# macOS
.DS_Store
# The 700MB source-asset vault (pulled from the M1 Ultra "ultra" node) lives
# outside git — it's Blender/Unreal source material, not repo content.
# Canonical copies: ~/Documents/Destroyulater/3D-STORE (M3) and
# johnking@ultra:~/Documents/3D-STORE (origin).
3D-STORE/

View File

@ -1,49 +1,26 @@
# Destroyulator — Cascade Prototype
# DESTROYULATOR
Mac-first (Apple Silicon / Metal), **Godot 4.7**, **Jolt** physics. Built to prove two
things on the M3 *before* committing: the destruction feels good, and the frame rate holds.
*Clock out. Smash everything.*
## Run it
A comedic, non-violent, first-person workplace-destruction game from Monster Robot
Party. Level 01 is our actual record store. Nobody gets hurt but the furniture.
**Editor (easiest):** open `/Applications/Godot.app`, import this folder (`game/`), press **F5** / ▶.
## Monorepo layout — one lane per directory
**CLI:**
```sh
/Applications/Godot.app/Contents/MacOS/Godot --path /Users/m3ultra/Documents/Destroyulater/game
```
| Dir | Lane | What |
|---|---|---|
| `game/` | **Lane 1 — the game** | Godot 4.7 (Jolt physics, Mac-native). The shippable build. |
| `web/` | **Lane 3 — web toy** | Three.js dig-and-destroy demo (planned; thriftgod-adjacent). |
| `LANES/` | coordination | Execution specs for parallel Claude/Opus work sessions. |
| `3D-STORE/` | *not in git* | 700MB Blender/Unreal source-asset vault (see `.gitignore`). |
| `destroyulater.txt` | lore | The founding chat where the idea happened. |
## Controls
Asset generation lives in its own repo: `~/Documents/meshgod` (text→GLB factory).
| Input | Does |
|---|---|
| **Left-click** | Swing the (nerf) hammer at whatever's under the cursor |
| **S** | Rain **500** rigid bodies — the **Day-0 stress gate**. Watch the FPS counter hold. |
| **R** | Reset the rack |
## Rules for parallel work sessions
Top-left HUD shows **FPS · live body count · things smashed**.
## What it's proving — the cascade
The rack is nested the same way your store's DB is (`rack → shelf → crate → jacket → record`):
- **Frame + shelves** start *frozen* (act static, hold everything up).
- Smash a **shelf** → it bursts into shards and vanishes → the **crates** on it fall →
the **cardboard jackets** spill → the **vinyl records** tumble out →
- **records are brittle** (`brittle_speed` in `Smashable.gd`) → they **crack a beat later
when they smack the floor**. A record that lands flat *survives* — there's your comedy/score beat.
No scripted "release" logic — gravity reads the hierarchy. That's the whole point.
## Files
- `scripts/Smashable.gd` — one component for every breakable piece. The `PROFILES` table is
where **material identity** is authored (color · shard count · brittleness · bounce).
Swap `wood/cardboard/vinyl/glass/steel` behaviours here.
- `scripts/Main.gd` — builds the world + rack from primitives, hammer raycast, stress test, HUD.
## Next step: real art (one function)
Everything is grey primitives so it runs with zero import deps. To use your actual assets,
change `_piece()` in `Main.gd` to load a GLB instead of building a BoxMesh, e.g.
`load("res://assets/wooden-rack-type-long.glb").instantiate()` for the visual, keep the
convex collider. Your `3D-STORE/clean_glbs/*.glb` are ready to copy into `game/assets/`.
- **A lane session writes ONLY inside its own directory.** Cross-lane contracts
(asset formats, file drops) are specified in `LANES/*.md`.
- Every change to `game/` must pass the headless smoke test before commit:
`Godot --headless --path game --quit-after 180` with zero script errors.
- GLB convention everywhere: glTF Y-up, 1 unit = 1 m, origin at floor-center.

43
destroyulater.txt Normal file
View File

@ -0,0 +1,43 @@
Oh, this is absolute gold. Workplace Destroyulator is a spectacular pivot, and honestly, its the perfect counterweight to a traditional simulator.
While Record Store Simulator lets you meticulously organize, curate, and obsess over every piece of vinyl, Destroyulator taps into the chaotic, primal urge of anyone who has ever worked a retail or office job and thought, "What if I just took a baseball bat to this printer?" Because youve already built the 3D assets for the store in Three.js and are migrating them to Unreal Engine, you are sitting on a goldmine. You have the perfect initial testbed.
Let's break down why this works so well, how Unreal's tech makes it feasible, and how your specific record store assets translate into pure gameplay loop mechanics.
The Core Gameplay Mechanics
For this to be more than just a tech demo, the destruction needs to feel deeply satisfying and arcady. You mentioned different strengths for different materials—this is where the strategy comes in.
1. The Weapon vs. Material Matrix
In Unreal, you can set up physical materials and damage thresholds.
• The Sledgehammer / Cricket Bat: High impact, slow swing. Perfect for shattering heavy wooden record racks, smashing the glass storefront, or obliterating the point-of-sale (POS) counter.
• The Box Cutter: Fast, low impact. Completely useless against a desk, but it shreds cardboard boxes, posters, and wall decals, leaving satisfying hanging ribbons of paper.
• The Projectile (e.g., An old faulty amplifier or a heavy turntable): High risk, high reward. You throw it across the room to trigger a domino effect of falling record crates.
2. The Physics of Vinyl Destruction
Since you have the record and sleeve assets ready, think about how they behave under stress:
• The Sleeves: Light, high-surface-area physics objects. If you smash a crate, 50 sleeves should erupt into the air like a deck of cards thrown in the wind, slowly drifting down.
• The Records: Vinyl is brittle under high impact but flexible under low pressure. In Unreal, you can use the Chaos Destruction system to make records shatter into sharp, jagged shards when hit with a blunt object, or scale a "shrapnel" particle effect.
3. The "Combo" and Triage System
To make it an arcade hit, players shouldn't just mindlessly swing. They need to maximize their score within the time limit:
• Chain Reactions: Smashing the bottom support of a custom-built rack causes the top shelves to collapse, creating a cascade of breaking glass, splintering wood, and flying wax.
• High-Value Targets: The rare wall-gems. Smashing a standard dollar-bin record gives you 10 points. Spotting the rare bootleg on the wall and snapping it in half gives you a 50x Combo Multiplier.
Why Unreal Engine is Perfect for This
Moving from Three.js to Unreal Engine for a destruction game is like upgrading from a bicycle to a monster truck.
Unreal Chaos Physics & Fracturing
Unreal Engine features Chaos Destruction. You don't need to manually animate things breaking. You import your static meshes (your racks, crates, tables), and use the Chaos tool to "fracture" them into hundreds of pieces. You can control:
• Damage Thresholds: How hard a physics object needs to hit the rack before it breaks.
• Connection Fields: Keeping a structure together until a specific structural pillar is destroyed, causing the whole thing to succumb to gravity.
Niagara Particle Systems
To make the destruction feel good (the "juice" of the game), you need visual feedback.
• When wood breaks, Niagara can shoot out splinters and sawdust.
• When a record breaks, you get a burst of shiny black vinyl dust and flying shards.
• Smashing an old CRT monitor or an amp? Cue electrical sparks and popping capacitors.
The "Franchise" Expansion Potential
You hit the nail on the head: the asset pipeline transfers to any workplace. Once you lock down the character controller, the weapon logic, and the scoring system in Unreal, changing the level is just a matter of swapping the static meshes.
• Level 1: The Indie Record Store (Splintering wood, flying cardboard, shattering vinyl, exploding stereo speakers).
• Level 2: The Cubicle Farm Office (Shattering fluorescent lights, exploding PC towers, copy machines spewing paper everywhere).
• Level 3: The Fast Food Kitchen (Denting stainless steel, smashing tile walls, slippery grease mechanics on the floor).
• Level 4: The Trendy Boutique / Hypebeast Store (Shattering glass mannequins, tearing down expensive displays).
How to Build the Foundation Right Now
Since you already have the room, bare racks, empty crates, and a vinyl record with its sleeve in Unreal, your immediate prototyping checklist is incredibly straightforward:
1. Set up a First-Person or Third-Person Character with a basic line-trace or collision volume for a "swing/attack" mechanic.
2. Take your Record Rack mesh into the Chaos Fracture editor. Fracture it into 2030 chunks. Give it a high damage threshold so it requires a heavy weapon.
3. Take your Vinyl Record mesh, fracture it into 56 sharp shards, and set its threshold lower so a light swing snaps it.
4. Scatter 500 records into a few crates using basic rigid body physics, walk up to it with a bat, and see how satisfying it feels to watch them fly.
The beauty of this is that the code and asset optimization you do for Destroyulator (handling hundreds of physics objects on screen at once) will actually help you optimize the Record Store Simulator later if you ever want to build the peaceful version.
Which weapon are you planning to code into the prototype first to test out the physics?

9
game/.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
# Godot 4 editor cache & reimportable data
.godot/
# Godot export output
/build/
/export/
# macOS
.DS_Store

49
game/README.md Normal file
View File

@ -0,0 +1,49 @@
# Destroyulator — Cascade Prototype
Mac-first (Apple Silicon / Metal), **Godot 4.7**, **Jolt** physics. Built to prove two
things on the M3 *before* committing: the destruction feels good, and the frame rate holds.
## Run it
**Editor (easiest):** open `/Applications/Godot.app`, import this folder (`game/`), press **F5** / ▶.
**CLI:**
```sh
/Applications/Godot.app/Contents/MacOS/Godot --path /Users/m3ultra/Documents/Destroyulater/game
```
## Controls
| Input | Does |
|---|---|
| **Left-click** | Swing the (nerf) hammer at whatever's under the cursor |
| **S** | Rain **500** rigid bodies — the **Day-0 stress gate**. Watch the FPS counter hold. |
| **R** | Reset the rack |
Top-left HUD shows **FPS · live body count · things smashed**.
## What it's proving — the cascade
The rack is nested the same way your store's DB is (`rack → shelf → crate → jacket → record`):
- **Frame + shelves** start *frozen* (act static, hold everything up).
- Smash a **shelf** → it bursts into shards and vanishes → the **crates** on it fall →
the **cardboard jackets** spill → the **vinyl records** tumble out →
- **records are brittle** (`brittle_speed` in `Smashable.gd`) → they **crack a beat later
when they smack the floor**. A record that lands flat *survives* — there's your comedy/score beat.
No scripted "release" logic — gravity reads the hierarchy. That's the whole point.
## Files
- `scripts/Smashable.gd` — one component for every breakable piece. The `PROFILES` table is
where **material identity** is authored (color · shard count · brittleness · bounce).
Swap `wood/cardboard/vinyl/glass/steel` behaviours here.
- `scripts/Main.gd` — builds the world + rack from primitives, hammer raycast, stress test, HUD.
## Next step: real art (one function)
Everything is grey primitives so it runs with zero import deps. To use your actual assets,
change `_piece()` in `Main.gd` to load a GLB instead of building a BoxMesh, e.g.
`load("res://assets/wooden-rack-type-long.glb").instantiate()` for the visual, keep the
convex collider. Your `3D-STORE/clean_glbs/*.glb` are ready to copy into `game/assets/`.

View File

Before

Width:  |  Height:  |  Size: 766 KiB

After

Width:  |  Height:  |  Size: 766 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.6 MiB