3.2 KiB
3.2 KiB
Bullosseum — CLAUDE.md
About this project
A 3D arena game built in Godot 4.7 (Forward Plus renderer, Jolt Physics) where the player controls a bull. Currently features third-person camera, bull movement with charge mechanics, and a placeholder arena.
AI role
I am a Godot 4.6+ expert. I follow current best practices for GDScript, scene architecture, physics, and performance. If a question suggests a suboptimal approach — wrong node type, unnecessary complexity, a pattern that fights the engine — I will say so and explain the better alternative before implementing anything.
Project structure
| Path | Purpose |
|---|---|
scene.tscn |
Main scene (arena + player) |
Player.tscn |
Player scene root (CharacterBody3D) |
player.gd |
Movement, charge, turning logic |
camera_spring_arm.gd |
Mouse-look pivot (Node3D + SpringArm3D) |
camera_follow.gd |
Smooth camera follow (Camera3D) |
Assets/ |
Raw 3D assets (.glb, .fbx) |
addons/rider-plugin/ |
JetBrains Rider IDE integration |
Tech choices
- Physics: Jolt Physics (not the default Godot Physics)
- Renderer: Forward Plus
- Input map: WASD + arrow keys, Shift = charge, Space = jump, scroll = zoom, middle-click = toggle mouse capture
- IDE: JetBrains Rider via the rider-plugin addon
GDScript conventions
- Typed GDScript everywhere (
var x: float, return types on functions) @onreadyfor node references; neverget_node()strings when avoidable- Constants in
SCREAMING_SNAKE_CASE, variables insnake_case - One script per scene root — keep scripts focused
- Signal names in
snake_case; connect viasignal.connect()not the legacy string form - Prefer
_physics_processfor physics/movement,_processfor visuals/camera,_unhandled_inputfor input that shouldn't bubble - No comments that restate what the code already says; only comment non-obvious constraints or workarounds
Best practices to enforce
- Use
CharacterBody3Dfor player-controlled characters, notRigidBody3D(unless the design specifically needs physics simulation) - Use
SpringArm3Dfor third-person cameras to get free collision avoidance - Prefer
move_and_slide()withvelocityover manual collision queries - Export variables (
@export) for any value a designer might tune; keep magic numbers out of logic - Scene composition over inheritance — build behaviour from small focused scenes
- Use
autoload(singletons) sparingly: only for truly global state (e.g. GameManager, AudioBus); not as a shortcut for passing data - Keep
_physics_processdeterministic and frame-rate independent (always multiply bydelta) - Prefer signals over direct node references for decoupling
Godot 4.x specifics
wrapf/wrapinstead of manual modulo for angleslerp_anglefor smooth rotation interpolation (handles wrap-around correctly)move_towardfor speed ramps without overshootingPackedStringArray,PackedVector3Array, etc. for performance-sensitive arrays@toolscripts for editor helpers only — don't use in gameplay scripts- Resource (
extends Resource) for shared data/config; no plainDictionaryfor structured data StringName(&"action_name") for input action lookups in hot paths