diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..63b77538 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "mcp/godot-mcp"] + path = mcp/godot-mcp + url = https://github.com/tugcantopaloglu/godot-mcp.git diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 00000000..b13c2114 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "godot-mcp": { + "command": "node", + "args": ["mcp/godot-mcp/build/index.js"], + "env": { + "GODOT_PATH": "" + } + } + } +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..6af3b8b0 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,44 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +Important rule: never create co-authored commits. Never mention Claude in commits. + +## Project overview + +Cosmic Clash is an open-source, physics-based "vehicle soccer" game (a spiritual successor to Rocket League) built in Godot 4.4, using space ships instead of cars. The project is GDScript/Godot only right now — the "C# backend" mentioned in README.md is planned but not yet started. There is no server-side code; the MVP is local-only play against bots. + +Because the gameplay concept (vehicle soccer) can't be copyrighted but specific expression can, all code/art/assets must be original — this is why the project uses Godot instead of Unreal/Unity and ships instead of cars. Keep this in mind when writing code or pulling in assets: don't port or closely mirror Rocket League's actual implementation. + +## Godot MCP server + +This repo vendors [godot-mcp](https://github.com/tugcantopaloglu/godot-mcp) as a git submodule at `mcp/godot-mcp` and registers it in `.mcp.json`. **Prefer the godot-mcp tools over manual file edits or shell commands** when the task involves inspecting or modifying the Godot project — reading/editing scenes, nodes, scripts, running the project, or interacting with a live Godot editor/runtime instance. It understands Godot's scene tree and `.tscn`/`.gd` structures directly, which is more reliable than hand-parsing them. + +Setup after cloning (submodules aren't checked out by default): + +```bash +git submodule update --init --recursive +cd mcp/godot-mcp +npm install +npm run build +``` + +`GODOT_PATH` (env var in `.mcp.json`) is left blank to auto-detect the Godot executable; set it explicitly if auto-detection fails on your machine. + +## Commands + +There is no build step, linter, or automated test suite for the GDScript project itself — Godot projects run directly from source. + +- **Open the project**: open `Game/` as a project in the Godot 4.4 editor, or run `godot --path Game` from the repo root. +- **Run the game**: press Play in the editor, or `godot --path Game Game/scenes/main_menu.tscn`. +- The `mcp/godot-mcp` submodule is a separate Node/TypeScript project with its own `npm install` / `npm run build` (see above) — it is tooling, not part of the game itself. + +## Architecture + +- **Scene flow**: `main_menu.tscn` → (Play button, `main_menu_play_button.gd`) → `scenes/Game.tscn` → on match timer expiry, back to `main_menu.tscn`. The match is a fixed 150-second timer (`game.gd`). +- **Game.tscn** instances `objects/ship.tscn` (player-controlled ship), `objects/ball.tscn`, and `objects/goal.tscn` over a static terrain body. +- **Ship physics** (`scripts/ship.gd`, class `Ship`, extends `RigidBody3D`): all movement is force/torque-based (`_integrate_forces`), not kinematic — thrust and rotation inputs are converted to world-space forces/torques relative to the ship's orientation, with manual drag and speed/angular-speed clamping applied each physics tick. Physics formulas are commented inline; see `FLIGHT_MANUAL.md` for the player-facing explanation of controls and flight model. +- **Vehicle.gd** (`scripts/Vehicle.gd`) is a separate, simpler `RigidBody3D` base class used by `objects/vehicle.tscn`. It is *not* currently the base class for `Ship` — `ship.gd` reimplements similar logic directly. Treat these as two independent, currently-diverging implementations rather than a class hierarchy. +- **HUD / telemetry pattern**: `Ship` computes flight data (speed, altitude, attitude, heading, thrust, angular velocity, camera mode) once per physics tick and emits it via signals, only when the value changes past a threshold (see the `_last_*` fields and `*_THRESHOLD` constants in `ship.gd`). `HUDController` (`scripts/HUDController.gd`, on `scenes/HUD.tscn`, instanced inside `ship.tscn`) discovers the ship and game manager via Godot groups (`"ship"`, `"game"`) rather than direct node paths, connects to their signals, and only updates label text in response — it does no polling. Follow this discovery-by-group + signal-push pattern when adding new instruments or cross-node communication, rather than `get_node` with hardcoded paths or per-frame polling. +- **Input actions** are defined in `Game/project.godot` under `[input]` (`move_forward`, `turn_left`, `turbo`, etc.) and read via `Input.is_action_pressed(...)` — add new controls there rather than hardcoding key/button checks. +- Physics engine is Jolt (`Game/project.godot`, `[physics] 3d/physics_engine="Jolt Physics"`).