basketball-tactics/scripts/player.gd

161 lines
5.7 KiB
GDScript3
Raw Normal View History

2026-02-11 03:11:28 +00:00
@icon("res://assets/icons/player.svg")
2026-02-11 03:01:44 +00:00
class_name Player
extends CharacterBody2D
2026-02-11 03:01:44 +00:00
2026-02-16 03:45:13 +00:00
## Signals
signal ball_dropped
signal grab_attempted
signal turn_finished
2026-02-16 03:45:13 +00:00
## Export variables
2026-02-11 03:01:44 +00:00
@export var attributes: PlayerAttributes ## The attributes resource that defines the player's abilities, vitals etc.
2026-02-16 03:45:13 +00:00
## Regular variables
var current_ball: Ball: set = set_current_ball
2026-02-16 03:45:13 +00:00
var ball_within_reach: bool = false
var has_ball: bool = false: set = set_has_ball
var is_active: bool = false: set = set_active
var desired_velocity: Vector2
var player_label_offset: Vector2
2026-02-16 03:45:13 +00:00
## Onready variables
## Child nodes
@onready var player_camera: Camera2D = $PlayerCamera
2026-02-16 03:45:13 +00:00
@onready var player_hands: Node2D = $PlayerHands
@onready var player_left_hand: RemoteTransform2D = %PlayerLeftHand
@onready var player_right_hand: RemoteTransform2D = %PlayerRightHand
@onready var player_label: PlayerLabel = $PlayerLabel
2026-02-11 03:01:44 +00:00
@onready var player_nav: NavigationAgent2D = $PlayerNav
@onready var player_reach: Area2D = $PlayerReach
@onready var nav_target_sprite: Sprite2D = $NavTargetSprite
2026-02-11 03:01:44 +00:00
@onready var player_sprite: Sprite2D = $PlayerSprite
@onready var player_ui: CanvasLayer = $PlayerUI
2026-02-11 03:01:44 +00:00
2026-02-16 03:45:13 +00:00
## -- Overrides -- ##
2026-02-11 03:01:44 +00:00
func _ready() -> void:
_connect_signals()
2026-02-11 03:01:44 +00:00
if attributes:
2026-02-16 03:45:13 +00:00
_apply_attributes()
player_label_offset = player_label.position
func _process(_delta: float) -> void:
2026-02-16 03:45:13 +00:00
player_label.global_position = global_position + player_label_offset
if is_active:
2026-02-16 03:45:13 +00:00
nav_target_sprite.global_position = get_global_mouse_position()
func _physics_process(_delta: float) -> void:
desired_velocity = global_position.direction_to(player_nav.get_next_path_position()) * attributes.movement_speed * 100.0
player_nav.velocity = desired_velocity
func _input(event: InputEvent) -> void:
if event.is_action_pressed("end_turn"):
end_turn()
2026-02-16 03:45:13 +00:00
if event.is_action_pressed("drop_ball"):
if has_ball: drop_ball(current_ball)
else: print_debug("%s can't drop the ball" % attributes.player_name)
if event.is_action_pressed("grab_ball"):
if ball_within_reach: attempt_grab(current_ball)
2026-02-16 03:45:13 +00:00
else: print_debug("%s can't grab the ball" % attributes.player_name)
if event is InputEventMouseButton and event.is_pressed() and event.button_index == 1:
var click_position_global = get_global_mouse_position()
print_debug("%s wants to navigate to %s" % [attributes.player_name, click_position_global])
player_nav.target_position = click_position_global
var target_distance = player_nav.distance_to_target()
print_debug("That's %s pixels/cm away" % target_distance)
2026-02-16 03:45:13 +00:00
## -- ACTIONS -- ##
func attempt_grab(_b: Ball) -> void:
print_debug("%s will attempt to grab the ball" % attributes.player_name)
grab_attempted.emit()
func drop_ball(_b: Ball) -> void:
2026-02-16 03:45:13 +00:00
print_debug("%s will attempt to drop the ball" % attributes.player_name)
for hand in player_hands.get_children():
hand = hand as RemoteTransform2D
hand.remote_path = NodePath("")
ball_dropped.emit()
2026-02-16 03:45:13 +00:00
func end_turn() -> void:
print_debug("%s says: I'd like my turn to end." % attributes.player_name)
is_active = false
turn_finished.emit()
## -- SETTERS -- ##
func set_active(active: bool) -> void:
is_active = active
if is_active:
print_debug("%s says: 'My turn!'" % attributes.player_name)
player_camera.enabled = true
player_camera.make_current()
nav_target_sprite.visible = true
2026-02-16 03:45:13 +00:00
player_nav.avoidance_priority = 0.0
set_process_input(true)
else:
print_debug("%s says: 'It's not my turn'" % attributes.player_name)
player_camera.enabled = false
nav_target_sprite.visible = false
2026-02-16 03:45:13 +00:00
player_nav.avoidance_priority = 0.5
set_process_input(false)
func set_current_ball(b: Ball) -> void:
current_ball = b
print_debug("%s sees the game ball" % attributes.player_name)
2026-02-16 03:45:13 +00:00
func set_has_ball(h_b: bool) -> void:
has_ball = h_b
if has_ball:
print_debug("%s says: I have the ball" % attributes.player_name)
if attributes.player_handedness == Globals.PlayerHandedness.LEFT:
player_left_hand.remote_path = player_left_hand.get_path_to(current_ball)
else:
player_right_hand.remote_path = player_right_hand.get_path_to(current_ball)
else:
print_debug("%s says: I no longer have the ball" % attributes.player_name)
if attributes.player_handedness == Globals.PlayerHandedness.LEFT:
player_left_hand.remote_path = NodePath("")
else:
player_right_hand.remote_path = NodePath("")
2026-02-16 03:45:13 +00:00
## -- RECEIVERS -- ##
func on_player_reach_body_entered(body: PhysicsBody2D) -> void:
if body is Player:
print_debug((body.attributes.player_name) + " has entered %s's reach area" % attributes.player_name)
func on_player_reach_area_entered(area: CollisionObject2D) -> void:
if area is Ball:
print_debug("The ball has entered %s's reach area" % attributes.player_name)
2026-02-16 03:45:13 +00:00
ball_within_reach = true
current_ball = area
func on_player_reach_body_exited(body: PhysicsBody2D) -> void:
if body is Player:
print_debug((body.attributes.player_name) + " has exited %s's reach area" % attributes.player_name)
func on_player_reach_area_exited(area: CollisionObject2D) -> void:
if area is Ball:
print_debug("The ball has exited %s's reach area" % attributes.player_name)
2026-02-16 03:45:13 +00:00
ball_within_reach = false
func on_velocity_computed(safe_velocity: Vector2) -> void:
velocity = safe_velocity
move_and_slide()
## -- HELPERS -- ##
func _apply_attributes() -> void:
player_label.player_name = attributes.player_name
player_label.player_number = attributes.player_number
player_label.player_position = attributes.player_position
player_sprite.texture = attributes.player_texture
func _connect_signals() -> void:
player_nav.connect("velocity_computed", on_velocity_computed)
player_reach.connect("body_entered", on_player_reach_body_entered)
player_reach.connect("body_exited", on_player_reach_body_exited)
player_reach.connect("area_entered", on_player_reach_area_entered)
player_reach.connect("area_exited", on_player_reach_area_exited)