feat: world-grid level materials + real movement test suite

- Generated CC0-style prototype grid textures (0.5 m cells) and a shared
  LevelMaterials factory: world-space triplanar mapping over every code-built
  level (test level, dust2, procedural arena) with the existing color coding
  kept as tints. Readable surfaces at speed instead of flat color boxes;
  materials are cached per tint so identical surfaces batch.
- .gdignore + .gitignore the raw downloaded asset packs in addons/ whose
  overlong paths broke Godot import scans and spammed git warnings.
- Replaced the rotted FSM test file (invalid call(t) on Callables, stateless
  stub nodes, hung forever without quitting) with a real suite: 10 tests
  covering state registration, jump bookkeeping, wall-run momentum
  preservation and upward-carry cap, per-player dash cooldown (regression for
  the old shared static), dash speed stacking, chain soft cap, landing
  events, and slide entry momentum. New headless entrypoint:
  godot --headless --path . -s res://movement/tests/run_fsm_tests.gd

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Nicholas Butzke
2026-07-17 12:14:30 -04:00
co-authored by Claude Fable 5
parent 7da7f9f3f2
commit 198345177a
11 changed files with 222 additions and 140 deletions
+41
View File
@@ -0,0 +1,41 @@
extends Object
class_name LevelMaterials
## Shared prototype-grid materials for code-built levels.
##
## Every level builder makes its geometry from flat-colored boxes; this gives
## them all the same world-space grid surface (0.5 m cells via triplanar
## mapping) so speed and distance stay readable at movement-shooter velocity,
## while keeping each builder's color coding as a tint.
const GRID_GRAY := "res://assets/textures/prototype/grid_gray.png"
const GRID_DARK := "res://assets/textures/prototype/grid_dark.png"
## One texture tile = 2 m of world, so one grid cell = 0.5 m.
const WORLD_UNITS_PER_TILE := 2.0
static var _cache: Dictionary = {}
## A tinted grid material. Cached per (tint, dark) so identical surfaces share
## one material (fewer draw-state changes, and edits apply everywhere).
static func tinted(tint: Color, dark: bool = false) -> StandardMaterial3D:
var key := "%s|%s" % [tint.to_html(), dark]
if _cache.has(key):
return _cache[key]
var mat := StandardMaterial3D.new()
var tex_path := GRID_DARK if dark else GRID_GRAY
var tex: Texture2D = load(tex_path) if ResourceLoader.exists(tex_path) else null
if tex:
mat.albedo_texture = tex
# World triplanar: boxes need no UVs and the grid stays world-scaled.
mat.uv1_triplanar = true
mat.uv1_world_triplanar = true
mat.uv1_scale = Vector3.ONE / WORLD_UNITS_PER_TILE
# The texture is grayscale ~mid value; multiply by ~2x-brightened tint to
# land near the original flat color while keeping the grid contrast.
mat.albedo_color = Color(
minf(tint.r * 1.9, 1.0), minf(tint.g * 1.9, 1.0), minf(tint.b * 1.9, 1.0))
mat.roughness = 0.85
_cache[key] = mat
return mat