feat: implement movement state machine, FPS camera rig, and test level builder scaffolding

This commit is contained in:
DottsGit
2026-06-04 00:29:19 -04:00
parent da277e9d35
commit 0fd921481b
3 changed files with 20 additions and 13 deletions
+4 -1
View File
@@ -65,7 +65,10 @@ func _process(delta: float) -> void:
camera.fov = lerpf(camera.fov, _target_fov, 1.0 - exp(-params.fov_lerp_speed * delta))
# ── Head bob ──────────────────────────────────────────────────────────
if player.is_on_floor() and hspeed > 1.0:
var sm = player.get_node_or_null("MovementStateMachine")
var is_sliding = sm and sm.current_state == "slide"
if player.is_on_floor() and hspeed > 1.0 and not is_sliding:
_bob_timer += delta * params.head_bob_frequency * (hspeed / params.walk_speed)
var bob_y := sin(_bob_timer) * params.head_bob_amplitude
var bob_x := cos(_bob_timer * 0.5) * params.head_bob_amplitude * 0.5
-5
View File
@@ -124,11 +124,6 @@ func _build_floor() -> void:
# Main arena floor (80x80)
_box_static(Vector3(0, -0.5, 0), Vector3(80, 1.0, 80), Color(0.22, 0.22, 0.25), "Floor_Main")
# Grid lines on floor for spatial reference
for i in range(-40, 41, 5):
_box_static(Vector3(float(i), 0.01, 0), Vector3(0.05, 0.02, 80), Color(0.35, 0.35, 0.4), "GridX_%d" % i)
_box_static(Vector3(0, 0.01, float(i)), Vector3(80, 0.02, 0.05), Color(0.35, 0.35, 0.4), "GridZ_%d" % i)
# ── Arena Walls ───────────────────────────────────────────────────────────────
+16 -7
View File
@@ -62,7 +62,7 @@ func _physics_process(delta: float) -> void:
jump_buffer_time = maxf(jump_buffer_time - delta, 0.0)
# Update chain timer
if chain_timer > 0.0:
if chain_timer > 0.0 and on_ground:
chain_timer -= delta
if chain_timer <= 0.0:
chain_count = 0
@@ -115,14 +115,23 @@ func switch_to(new_state_name: String, data: Dictionary = {}) -> void:
func register_chain_mechanic(_mechanic_name: String) -> void:
if chain_timer > 0.0 and chain_count > 0:
chain_count = mini(chain_count + 1, 10)
chain_count += 1
else:
chain_count = 1
chain_timer = params.chain_window
current_chain_bonus = minf(
float(chain_count) * params.chain_bonus_per_success,
params.chain_bonus_cap
)
# Shrink the chain window as the chain gets longer to make it increasingly punishing
# Drops by 0.05 seconds per successful chain, down to a minimum of 0.4 seconds
var current_window = maxf(0.4, params.chain_window - (float(chain_count) * 0.05))
chain_timer = current_window
var raw_bonus = float(chain_count) * params.chain_bonus_per_success
if raw_bonus <= params.chain_bonus_cap:
current_chain_bonus = raw_bonus
else:
# Soft cap: diminishing returns past the cap
var over_bonus = raw_bonus - params.chain_bonus_cap
current_chain_bonus = params.chain_bonus_cap + (over_bonus / (1.0 + over_bonus * 3.0))
movement_event.emit("chain_updated", {
"count": chain_count,
"bonus": current_chain_bonus