From 26f0f31ce713ba5ccdc03c17b70b6e21beb31711 Mon Sep 17 00:00:00 2001 From: TheThomaas Date: Mon, 12 Oct 2026 09:57:35 +0200 Subject: [PATCH] Add aim reticule --- game/player/aim/aim_reticule.gd | 52 +++++++++++++++++++++++++++++ game/player/aim/aim_reticule.gd.uid | 1 + game/player/states/aim_state.gd | 8 +++++ game/player/states/throw_state.gd | 9 +++++ 4 files changed, 70 insertions(+) create mode 100644 game/player/aim/aim_reticule.gd create mode 100644 game/player/aim/aim_reticule.gd.uid diff --git a/game/player/aim/aim_reticule.gd b/game/player/aim/aim_reticule.gd new file mode 100644 index 0000000..198b2dc --- /dev/null +++ b/game/player/aim/aim_reticule.gd @@ -0,0 +1,52 @@ +extends CanvasLayer + +class_name AimReticle + +#reticule 2D au centre de l'ecran (visee libre / charge du lancer) +#cree a la volee, une seule instance partagee par AimState et ThrowState + +static var _instance : AimReticle + +static func get_instance(from : Node) -> AimReticle: + if is_instance_valid(_instance): return _instance + _instance = AimReticle.new() + from.get_tree().current_scene.add_child(_instance) + return _instance + +static func show_instance(from : Node) -> void: + get_instance(from).visible = true + +static func hide_instance() -> void: + if is_instance_valid(_instance): _instance.visible = false + +func _init() -> void: + layer = 10 + visible = false + add_child(Drawer.new()) + +class Drawer extends Control: + @export var radius : float = 14.0 + @export var tick_length : float = 8.0 + @export var color : Color = Color(1.0, 1.0, 1.0, 0.9) + @export var outline_color : Color = Color(0.0, 0.0, 0.0, 0.5) #contour sombre pour rester lisible sur fond clair + + func _init() -> void: + set_anchors_preset(Control.PRESET_FULL_RECT) + mouse_filter = Control.MOUSE_FILTER_IGNORE + + func _ready() -> void: + resized.connect(queue_redraw) + + func _draw() -> void: + var c : Vector2 = size / 2.0 + + #contour sombre, puis trait clair par-dessus + draw_arc(c, radius, 0.0, TAU, 40, outline_color, 4.0, true) + draw_circle(c, 3.0, outline_color) + for dir : Vector2 in [Vector2.UP, Vector2.DOWN, Vector2.LEFT, Vector2.RIGHT]: + draw_line(c + dir * (radius + 2.0), c + dir * (radius + 2.0 + tick_length), outline_color, 4.0) + + draw_arc(c, radius, 0.0, TAU, 40, color, 2.0, true) + draw_circle(c, 1.5, color) + for dir : Vector2 in [Vector2.UP, Vector2.DOWN, Vector2.LEFT, Vector2.RIGHT]: + draw_line(c + dir * (radius + 2.0), c + dir * (radius + 2.0 + tick_length), color, 2.0) diff --git a/game/player/aim/aim_reticule.gd.uid b/game/player/aim/aim_reticule.gd.uid new file mode 100644 index 0000000..547bea3 --- /dev/null +++ b/game/player/aim/aim_reticule.gd.uid @@ -0,0 +1 @@ +uid://d263upin4ab3e diff --git a/game/player/states/aim_state.gd b/game/player/states/aim_state.gd index ef32d77..4563567 100644 --- a/game/player/states/aim_state.gd +++ b/game/player/states/aim_state.gd @@ -57,6 +57,7 @@ func exit() -> void: if keep_aim_on_exit: keep_aim_on_exit = false return + AimReticle.hide_instance() if dodging_from_aim: #on roule en visant : la camera et la cible verrouillee restent actives pendant la roulade dodging_from_aim = false @@ -69,6 +70,7 @@ func physics_update(delta : float) -> void: play_char.gravity_apply(delta) if input_management(): return update_target() + update_reticle() move(delta) func applies() -> bool: @@ -123,6 +125,12 @@ func move(delta : float) -> void: play_char.velocity.x = lerp(play_char.velocity.x, 0.0, play_char.move_deccel * delta) play_char.velocity.z = lerp(play_char.velocity.z, 0.0, play_char.move_deccel * delta) +func update_reticle() -> void: + if is_instance_valid(play_char.aim_target): + AimReticle.hide_instance() #cible verrouillee : son propre indicateur suffit + else: + AimReticle.show_instance(self) + #---------- targeting ---------- func update_target() -> void: diff --git a/game/player/states/throw_state.gd b/game/player/states/throw_state.gd index 61145d1..790777b 100644 --- a/game/player/states/throw_state.gd +++ b/game/player/states/throw_state.gd @@ -91,6 +91,7 @@ func exit() -> void: if _keep_aim: _keep_aim = false return + AimReticle.hide_instance() _release_aim() func physics_update(delta : float) -> void: @@ -139,6 +140,7 @@ func charge(delta : float) -> void: return move_while_charging(delta) + update_reticle() func release() -> void: #RT relachee : on fige la cible et le point vise, puis le windup demarre @@ -176,10 +178,17 @@ func finish() -> void: var dir : Vector2 = Input.get_vector(play_char.move_left_action, play_char.move_right_action, play_char.move_forward_action, play_char.move_backward_action) transitioned.emit(self, play_char.walk_or_run if dir != Vector2.ZERO else "IdleState") +func update_reticle() -> void: + if is_instance_valid(play_char.aim_target): + AimReticle.hide_instance() #cible verrouillee : son propre indicateur suffit + else: + AimReticle.show_instance(self) + #---------- lancer ---------- func throw_ball() -> void: _thrown = true + AimReticle.hide_instance() var from : Vector3 = play_char.global_position + Vector3.UP * hand_height var to : Vector3 = _get_landing_point()