Debug menu F1 (use ctrl to lock cam). Design.md doc
This commit is contained in:
@@ -1,19 +1,6 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
const WALK_SPEED = 6.0
|
||||
const CHARGE_SPEED = 180.0
|
||||
const WALK_ACCEL = 14.0
|
||||
const CHARGE_ACCEL = 40.0
|
||||
const DECELERATION = 12.0
|
||||
const CHARGE_DECEL = 3.5
|
||||
|
||||
const WALK_TURN_FAST = 8.0
|
||||
const WALK_TURN_SLOW = 3.5
|
||||
const CHARGE_TURN = 0.55
|
||||
|
||||
const JUMP_VELOCITY = 4.5
|
||||
|
||||
# Hoof positions in bull_v10 local space — tweak y/z if hooves don't line up with the model
|
||||
# Hoof positions in bull_v10 local space — adjust y/z if puffs don't land on the hooves
|
||||
const HOOF_OFFSETS: Array = [
|
||||
Vector3(-0.30, -0.25, -0.50),
|
||||
Vector3( 0.30, -0.25, -0.50),
|
||||
@@ -21,8 +8,6 @@ const HOOF_OFFSETS: Array = [
|
||||
Vector3( 0.30, -0.25, 0.60),
|
||||
]
|
||||
|
||||
@export var visual_turn_speed: float = 12.0
|
||||
|
||||
@onready var camera_pivot: Node3D = $SpringArmPivot
|
||||
@onready var cube_guy: Node3D = $bull_v10
|
||||
|
||||
@@ -37,6 +22,7 @@ var _dust_state: _DustState = _DustState.NONE
|
||||
|
||||
func _ready() -> void:
|
||||
_setup_hoof_dust()
|
||||
DP.any_changed.connect(_on_dp_changed)
|
||||
|
||||
|
||||
func _setup_hoof_dust() -> void:
|
||||
@@ -46,7 +32,6 @@ func _setup_hoof_dust() -> void:
|
||||
mat.vertex_color_use_as_albedo = true
|
||||
mat.cull_mode = BaseMaterial3D.CULL_DISABLED
|
||||
|
||||
# 4×2 sphere = chunky low-poly diamond shape
|
||||
var sphere := SphereMesh.new()
|
||||
sphere.radius = 0.10
|
||||
sphere.height = 0.20
|
||||
@@ -54,12 +39,10 @@ func _setup_hoof_dust() -> void:
|
||||
sphere.rings = 2
|
||||
sphere.material = mat
|
||||
|
||||
# sand colour, fades to transparent over lifetime
|
||||
var ramp := Gradient.new()
|
||||
ramp.set_color(0, Color(0.80, 0.69, 0.46, 1.0))
|
||||
ramp.set_color(1, Color(0.80, 0.69, 0.46, 0.0))
|
||||
|
||||
# puff blooms up then vanishes
|
||||
var scale_curve := Curve.new()
|
||||
scale_curve.add_point(Vector2(0.0, 0.2))
|
||||
scale_curve.add_point(Vector2(0.4, 1.0))
|
||||
@@ -70,17 +53,17 @@ func _setup_hoof_dust() -> void:
|
||||
p.position = offset
|
||||
p.emitting = false
|
||||
p.amount = 12
|
||||
p.lifetime = 0.9
|
||||
p.explosiveness = 0.35
|
||||
p.lifetime = DP.f("dust_lifetime")
|
||||
p.explosiveness = DP.f("dust_explosiveness")
|
||||
p.randomness = 0.6
|
||||
p.local_coords = false
|
||||
p.direction = Vector3(0.0, 1.0, 0.0)
|
||||
p.spread = 45.0
|
||||
p.gravity = Vector3(0.0, -1.5, 0.0)
|
||||
p.initial_velocity_min = 0.8
|
||||
p.initial_velocity_max = 1.8
|
||||
p.scale_amount_min = 0.4
|
||||
p.scale_amount_max = 0.7
|
||||
p.spread = DP.f("dust_spread")
|
||||
p.gravity = Vector3(0.0, DP.f("dust_gravity_y"), 0.0)
|
||||
p.initial_velocity_min = DP.f("walk_vel_min")
|
||||
p.initial_velocity_max = DP.f("walk_vel_max")
|
||||
p.scale_amount_min = DP.f("walk_scale_min")
|
||||
p.scale_amount_max = DP.f("walk_scale_max")
|
||||
p.mesh = sphere
|
||||
p.color_ramp = ramp
|
||||
p.scale_amount_curve = scale_curve
|
||||
@@ -93,29 +76,42 @@ func _set_dust_state(new_state: _DustState) -> void:
|
||||
return
|
||||
_dust_state = new_state
|
||||
for p: CPUParticles3D in _hoof_emitters:
|
||||
p.lifetime = DP.f("dust_lifetime")
|
||||
p.explosiveness = DP.f("dust_explosiveness")
|
||||
p.spread = DP.f("dust_spread")
|
||||
p.gravity = Vector3(0.0, DP.f("dust_gravity_y"), 0.0)
|
||||
match new_state:
|
||||
_DustState.NONE:
|
||||
p.emitting = false
|
||||
_DustState.WALK:
|
||||
p.scale_amount_min = 0.35
|
||||
p.scale_amount_max = 0.65
|
||||
p.initial_velocity_min = 0.8
|
||||
p.initial_velocity_max = 1.8
|
||||
p.scale_amount_min = DP.f("walk_scale_min")
|
||||
p.scale_amount_max = DP.f("walk_scale_max")
|
||||
p.initial_velocity_min = DP.f("walk_vel_min")
|
||||
p.initial_velocity_max = DP.f("walk_vel_max")
|
||||
p.emitting = true
|
||||
_DustState.CHARGE:
|
||||
p.scale_amount_min = 1.0
|
||||
p.scale_amount_max = 2.2
|
||||
p.initial_velocity_min = 2.8
|
||||
p.initial_velocity_max = 5.5
|
||||
p.scale_amount_min = DP.f("charge_scale_min")
|
||||
p.scale_amount_max = DP.f("charge_scale_max")
|
||||
p.initial_velocity_min = DP.f("charge_vel_min")
|
||||
p.initial_velocity_max = DP.f("charge_vel_max")
|
||||
p.emitting = true
|
||||
|
||||
|
||||
func _on_dp_changed(_key: String, _val: Variant) -> void:
|
||||
# Force re-apply so slider changes take effect without needing a state transition
|
||||
if _hoof_emitters.is_empty() or _dust_state == _DustState.NONE:
|
||||
return
|
||||
var prev := _dust_state
|
||||
_dust_state = _DustState.NONE
|
||||
_set_dust_state(prev)
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if not is_on_floor():
|
||||
velocity += get_gravity() * delta
|
||||
|
||||
if Input.is_action_just_pressed("jump") and is_on_floor():
|
||||
velocity.y = JUMP_VELOCITY
|
||||
velocity.y = DP.f("jump_velocity")
|
||||
|
||||
var input_dir := Input.get_vector("move_left", "move_right", "move_forward", "move_back")
|
||||
var cam_basis := camera_pivot.global_transform.basis
|
||||
@@ -123,35 +119,36 @@ func _physics_process(delta: float) -> void:
|
||||
var flat_right := Vector3(cam_basis.x.x, 0.0, cam_basis.x.z).normalized()
|
||||
var direction := (flat_forward * -input_dir.y + flat_right * input_dir.x).normalized()
|
||||
|
||||
var charging := Input.is_action_pressed(&"charge")
|
||||
|
||||
if direction:
|
||||
var target_angle := atan2(direction.x, direction.z)
|
||||
|
||||
if current_speed < 0.01:
|
||||
facing_angle = target_angle
|
||||
|
||||
var charging := Input.is_key_pressed(KEY_SHIFT)
|
||||
var speed_t: float = clampf(current_speed / WALK_SPEED, 0.0, 1.0)
|
||||
var turn_rate: float = CHARGE_TURN if charging else lerpf(WALK_TURN_FAST, WALK_TURN_SLOW, speed_t)
|
||||
var speed_t: float = clampf(current_speed / DP.f("walk_speed"), 0.0, 1.0)
|
||||
var turn_rate: float = DP.f("charge_turn") if charging \
|
||||
else lerpf(DP.f("walk_turn_fast"), DP.f("walk_turn_slow"), speed_t)
|
||||
|
||||
var diff := wrapf(target_angle - facing_angle, -PI, PI)
|
||||
facing_angle += clampf(diff, -turn_rate * delta, turn_rate * delta)
|
||||
|
||||
var top_speed: float = CHARGE_SPEED if charging else WALK_SPEED
|
||||
var accel: float = CHARGE_ACCEL if charging else WALK_ACCEL
|
||||
var top_speed: float = DP.f("charge_speed") if charging else DP.f("walk_speed")
|
||||
var accel: float = DP.f("charge_accel") if charging else DP.f("walk_accel")
|
||||
current_speed = move_toward(current_speed, top_speed, accel * delta)
|
||||
else:
|
||||
var charging := Input.is_key_pressed(KEY_SHIFT)
|
||||
var decel: float = CHARGE_DECEL if charging else DECELERATION
|
||||
var decel: float = DP.f("charge_decel") if charging else DP.f("deceleration")
|
||||
current_speed = move_toward(current_speed, 0.0, decel * delta)
|
||||
|
||||
velocity.x = sin(facing_angle) * current_speed
|
||||
velocity.z = cos(facing_angle) * current_speed
|
||||
|
||||
cube_guy.rotation.y = lerp_angle(cube_guy.rotation.y, facing_angle, delta * visual_turn_speed)
|
||||
cube_guy.rotation.y = lerp_angle(cube_guy.rotation.y, facing_angle,
|
||||
delta * DP.f("visual_turn_speed"))
|
||||
|
||||
move_and_slide()
|
||||
|
||||
var charging := Input.is_key_pressed(KEY_SHIFT)
|
||||
if current_speed > 0.5 and is_on_floor():
|
||||
_set_dust_state(_DustState.CHARGE if charging else _DustState.WALK)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user