From 4fc64dedae436b93ff4a25f265a4fd66f16aaada Mon Sep 17 00:00:00 2001 From: Richard Aasa Date: Wed, 10 Jun 2026 22:36:47 +0300 Subject: [PATCH] dash speed 3x, slam visual/damage fix --- camera_iso.gd | 90 +++++++++++++++---------------------------------- debug_params.gd | 10 +++--- player.gd | 51 +++++++++++++++------------- 3 files changed, 60 insertions(+), 91 deletions(-) diff --git a/camera_iso.gd b/camera_iso.gd index 3556e8b..c711361 100644 --- a/camera_iso.gd +++ b/camera_iso.gd @@ -4,58 +4,39 @@ extends Camera3D @export var horizontal_distance: float = 28.0 @export var horizontal_angle_deg: float = 45.0 -# --- ORTHOGRAPHIC ZOOM SETTINGS --- -@export var size_min: float = 5.0 # Maximum zoom in (small frame size) -@export var size_max: float = 30.0 # Maximum zoom out (large frame size) +@export var size_min: float = 5.0 +@export var size_max: float = 30.0 @export var default_size: float = 15.0 -# --- TILT-SHIFT DOF SETTINGS --- -@export var focus_slice_thickness: float = 6.0 -@export var blur_transition: float = 15.0 - -const _FLASH_DURATION: float = 0.30 +@export var focus_slice_thickness: float = 6.0 +@export var blur_transition: float = 15.0 var _shake_amount: float = 0.0 -var _shake_decay: float = 0.0 -var _flash_timer: float = 0.0 -var _flash_rect: ColorRect = null -var _target_size: float = 0.0 +var _shake_decay: float = 0.0 +var _user_size: float = 0.0 +var _charge_active: bool = false func _ready() -> void: set_as_top_level(true) - projection = Camera3D.PROJECTION_ORTHOGONAL # Switched to orthographic - _target_size = default_size + projection = Camera3D.PROJECTION_ORTHOGONAL + _user_size = default_size size = default_size - - near = 0.1 - far = 150.0 - - _setup_flash() - - -func _setup_flash() -> void: - var canvas := CanvasLayer.new() - canvas.layer = 20 - add_child(canvas) - _flash_rect = ColorRect.new() - _flash_rect.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) - _flash_rect.color = Color(1.0, 0.25, 0.2, 0.0) - _flash_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE - canvas.add_child(_flash_rect) + near = 0.1 + far = 150.0 func _unhandled_input(event: InputEvent) -> void: - # Zoom inputs now scale the Orthographic Size property if event.is_action_pressed("zoom_in"): - _target_size = clamp(_target_size / 1.2, size_min, size_max) + _user_size = clamp(_user_size / 1.2, size_min, size_max) if event.is_action_pressed("zoom_out"): - _target_size = clamp(_target_size * 1.2, size_min, size_max) + _user_size = clamp(_user_size * 1.2, size_min, size_max) func _process(delta: float) -> void: - size = lerpf(size, _target_size, delta * 10.0) - + var zoom_target := _user_size * DP.f("charge_zoom_factor") if _charge_active else _user_size + size = lerpf(size, zoom_target, delta * 8.0) + var angle_rad := deg_to_rad(horizontal_angle_deg) var offset := Vector3( sin(angle_rad) * horizontal_distance, @@ -66,7 +47,6 @@ func _process(delta: float) -> void: global_position = target.global_position + offset look_at(target.global_position, Vector3.UP) - # --- DYNAMIC TILT SHIFT CALCULATION --- _update_ortho_tilt_shift_dof(target.global_position) if _shake_amount > 0.005: @@ -77,54 +57,38 @@ func _process(delta: float) -> void: ) _shake_amount = move_toward(_shake_amount, 0.0, _shake_decay * delta) - if _flash_timer > 0.0: - _flash_timer = maxf(0.0, _flash_timer - delta) - _flash_rect.color.a = (_flash_timer / _FLASH_DURATION) * 0.6 - else: - _flash_rect.color.a = 0.0 - func trigger_hit(strength: float) -> void: _shake_amount = strength * 0.5 - _shake_decay = _shake_amount / 0.4 - _flash_timer = _FLASH_DURATION + _shake_decay = _shake_amount / 0.4 + + +func set_charge_active(active: bool) -> void: + _charge_active = active func _update_ortho_tilt_shift_dof(target_pos: Vector3) -> void: var cam_attr: CameraAttributesPractical = null - + if "attributes" in self and self.attributes is CameraAttributesPractical: cam_attr = self.attributes elif "camera_attributes" in self and self.camera_attributes is CameraAttributesPractical: cam_attr = self.camera_attributes if cam_attr != null: - # 1. Project distance onto the camera's true forward forward axis var to_target := target_pos - global_position var forward_vector := -global_transform.basis.z var ortho_depth := to_target.dot(forward_vector) - - # 2. Extract the dynamic zoom multiplier + var zoom_factor := size / default_size var dynamic_slice := focus_slice_thickness * zoom_factor var half_slice := dynamic_slice * 0.5 - - # Base transition modified by the zoom state + var base_transition := blur_transition * zoom_factor - # 3. Apply the focal zones - cam_attr.dof_blur_far_distance = ortho_depth + half_slice + cam_attr.dof_blur_far_distance = ortho_depth + half_slice cam_attr.dof_blur_near_distance = maxf(near + 0.1, ortho_depth - half_slice) - - # 4. ASYMMETRICAL CORRECTION FOR GODOT 4.7 FORWARD+ - # Far transition needs a massive punch to actually manifest on screen - cam_attr.dof_blur_far_transition = maxf(0.1, base_transition * 0.5) - - # Near transition needs to be greatly expanded (larger number = gentler slope) - # to stop it from snapping into massive instant blur + cam_attr.dof_blur_far_transition = maxf(0.1, base_transition * 0.5) cam_attr.dof_blur_near_transition = maxf(1.0, base_transition * 1.5) - - # 5. Keep both enabled - cam_attr.dof_blur_far_enabled = false + cam_attr.dof_blur_far_enabled = false cam_attr.dof_blur_near_enabled = false - diff --git a/debug_params.gd b/debug_params.gd index b2ec21b..f0ef528 100644 --- a/debug_params.gd +++ b/debug_params.gd @@ -83,6 +83,7 @@ func _register_all() -> void: _reg_f("Legs", "jump_tuck_fwd", -0.1, -0.5, 0.5) _reg_f("Legs", "jump_land_threshold", 1.5, 0.5, 5.0) # ── Camera ──────────────────────────────────────────────────────────────── + _reg_f("Camera", "charge_zoom_factor", 0.65, 0.3, 1.0, 0.05) _reg_f("Camera", "cam_lerp_power", 6.0, 0.5, 30.0) _reg_f("Camera", "cam_sensitivity", 0.005, 0.001, 0.05, 0.001) _reg_f("Camera", "cam_min_zoom", 3.5, 0.5, 20.0) @@ -118,11 +119,12 @@ func _register_all() -> void: _reg_f("Abilities", "kick_cooldown", 1.5, 0.2, 10.0, 0.1) _reg_f("Abilities", "kick_range", 3.5, 0.5, 8.0, 0.1) _reg_f("Abilities", "kick_strength", 12.0, 1.0, 30.0) - _reg_f("Abilities", "slam_cooldown", 4.0, 0.5, 15.0, 0.1) - _reg_f("Abilities", "slam_range", 4.0, 1.0, 10.0, 0.1) - _reg_f("Abilities", "slam_strength", 14.0, 1.0, 30.0) + _reg_f("Abilities", "slam_cooldown", 4.0, 0.5, 15.0, 0.1) + _reg_f("Abilities", "slam_jump_velocity", 7.0, 2.0, 20.0) + _reg_f("Abilities", "slam_range", 4.0, 1.0, 10.0, 0.1) + _reg_f("Abilities", "slam_strength", 14.0, 1.0, 30.0) _reg_f("Abilities", "dash_cooldown", 2.0, 0.5, 10.0, 0.1) - _reg_f("Abilities", "dash_speed", 22.0, 5.0, 60.0) + _reg_f("Abilities", "dash_speed", 66.0, 5.0, 200.0) # ── Debug ───────────────────────────────────────────────────────────────── _reg_b("Debug", "show_collisions", false) diff --git a/player.gd b/player.gd index 4fa1ffc..b685531 100644 --- a/player.gd +++ b/player.gd @@ -31,8 +31,8 @@ var _active_ability: int = -1 var _dash_dir: Vector3 = Vector3.ZERO var _bull_anim: AnimationPlayer = null -var _charge_overlay: ColorRect = null var _charge_ready_emitter: CPUParticles3D = null +var _slam_pending: bool = false var _huff_player: AudioStreamPlayer = null var _crowd_player: AudioStreamPlayer = null @@ -121,15 +121,6 @@ func _setup_charge_indicators() -> void: sphere.rings = 2 sphere.material = mat - # Screen overlay — red tint while charge-ahead (both buttons) is active - var ui := CanvasLayer.new() - add_child(ui) - _charge_overlay = ColorRect.new() - _charge_overlay.color = Color(0.9, 0.55, 0.0, 0.0) - _charge_overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE - _charge_overlay.set_anchors_preset(Control.PRESET_FULL_RECT) - ui.add_child(_charge_overlay) - # Orange spark burst when single-button charge hits max var burst_ramp := Gradient.new() burst_ramp.set_color(0, Color(1.0, 0.55, 0.0, 1.0)) @@ -262,16 +253,16 @@ func _activate_slam() -> void: ability_cd[1] = DP.f("slam_cooldown") _ability_active = true _active_ability = 1 - _ability_timer = 0.9 - if _bull_anim and _bull_anim.has_animation(&"Armature|SLAM"): - _bull_anim.play(&"Armature|SLAM") - _ability_timer = _bull_anim.get_animation(&"Armature|SLAM").length _legs.set(&"tail_ragdoll", true) - _spawn_slam_fx() - # Delay hit slightly so it lands when the first ring reaches the targets - get_tree().create_timer(0.15).timeout.connect( - func() -> void: _hit_matadors_radius(DP.f("slam_range"), DP.f("slam_strength")) - ) + _slam_pending = true + var jump_vel := DP.f("slam_jump_velocity") + velocity.y = jump_vel + var air_time := jump_vel / 9.8 * 2.0 + _ability_timer = air_time + 0.5 + if _bull_anim and _bull_anim.has_animation(&"Armature|SLAM"): + var anim_len := _bull_anim.get_animation(&"Armature|SLAM").length + _bull_anim.speed_scale = anim_len / maxf(air_time, 0.01) + _bull_anim.play(&"Armature|SLAM") func _activate_dash() -> void: @@ -592,12 +583,16 @@ func _physics_process(delta: float) -> void: _active_ability = -1 _legs.set(&"charge_pitch_target", 0.0) _legs.set(&"tail_ragdoll", false) + _slam_pending = false + if _bull_anim: + _bull_anim.speed_scale = 1.0 # ── Mouse button single-thrust actions ─────────────────────────────────────── # Left only → thrust NE (forward-right diagonal) # Right only → thrust NW (forward-left diagonal) var left_held := Input.is_action_pressed(&"thrust_left") var right_held := Input.is_action_pressed(&"thrust_right") + camera_pivot.call(&"set_charge_active", left_held and right_held) if left_held and right_held: _thrust_left_charge = 0.0 @@ -628,11 +623,6 @@ func _physics_process(delta: float) -> void: _charge_ready_emitter.restart() _charge_was_full = either_full - # Briefly flash overlay when dash is active - var target_alpha := 0.20 if (_active_ability == 2 and _ability_active) else 0.0 - var oc := _charge_overlay.color - _charge_overlay.color = Color(oc.r, oc.g, oc.b, lerpf(oc.a, target_alpha, delta * 12.0)) - # Reset kick timer on landing so the first kick after a bounce is immediate if on_floor and not _was_on_floor and direction: _kick_timer = 0.0 @@ -681,6 +671,19 @@ func _physics_process(delta: float) -> void: if impact > DP.f("bounce_min_impact"): velocity.y = impact * DP.f("bounce_restitution") + # ── Slam landing ────────────────────────────────────────────────────────── + if _slam_pending and is_on_floor() and not _was_on_floor: + _slam_pending = false + _ability_active = false + _active_ability = -1 + _ability_timer = 0.0 + _legs.set(&"charge_pitch_target", 0.0) + _legs.set(&"tail_ragdoll", false) + if _bull_anim: + _bull_anim.speed_scale = 1.0 + _spawn_slam_fx() + _hit_matadors_radius(DP.f("slam_range"), DP.f("slam_strength")) + # ── Dust ────────────────────────────────────────────────────────────────── if flat_speed > DP.f("dust_charge_spd") and on_floor: _set_dust_state(DustState.CHARGE)