@icon("res://assets/icons/player.svg") class_name Player extends CharacterBody2D ## Signals signal turn_finished ## Export variables @export var attributes: PlayerAttributes ## The attributes resource that defines the player's abilities, vitals etc. ## Regular variables var current_ball: Ball 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: set = set_desired_velocity var player_label_offset: Vector2 ## Onready variables ## Child nodes @onready var player_camera: Camera2D = $PlayerCamera @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 @onready var player_nav: NavigationAgent2D = $PlayerNav @onready var player_reach_area: Area2D = $PlayerReachArea @onready var nav_target_sprite: Sprite2D = $NavTargetSprite @onready var player_sprite: Sprite2D = $PlayerSprite @onready var player_ui: CanvasLayer = $PlayerUI #@onready var end_turn_button: Button = %EndTurnButton ## -- Overrides -- ## func _ready() -> void: _connect_signals() if attributes: _apply_attributes() player_label_offset = player_label.position func _process(_delta: float) -> void: player_label.global_position = global_position + player_label_offset if is_active: 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.speed if get_last_slide_collision(): var collision = get_last_slide_collision() var collider = collision.get_collider() if collider is Ball: collider.apply_central_impulse(collision.get_normal() * -1.0) if has_ball: current_ball.apply_central_force( current_ball.global_position.direction_to(global_position) * current_ball.global_position.distance_to(global_position) ) func _input(event: InputEvent) -> void: if event.is_action_pressed("end_turn"): end_turn() 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: grab_ball(current_ball) 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) ## -- ACTIONS -- ## func drop_ball(b: Ball) -> void: 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("") has_ball = false func end_turn() -> void: print_debug("%s says: I'd like my turn to end." % attributes.player_name) is_active = false turn_finished.emit() func grab_ball(b: Ball) -> void: print_debug("%s will attempt to grab the ball" % attributes.player_name) #if attributes.player_handedness == Globals.PlayerHandedness.LEFT: #player_left_hand.remote_path = player_left_hand.get_path_to(b) #else: #player_right_hand.remote_path = player_right_hand.get_path_to(b) has_ball = true ## -- 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 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 player_nav.avoidance_priority = 0.5 set_process_input(false) func set_desired_velocity(d_v: Vector2) -> void: desired_velocity = d_v player_nav.velocity = desired_velocity func set_has_ball(h_b: bool) -> void: has_ball = h_b if has_ball: print_debug("%s has the ball" % attributes.player_name) else: print_debug("%s no longer as the ball" % attributes.player_name) ## -- 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_area.connect("body_entered", on_player_reach_area_body_entered) player_reach_area.connect("body_exited", on_player_reach_area_body_exited) ## -- RECEIVERS -- ## func on_player_reach_area_body_entered(body: PhysicsBody2D) -> void: if body is Player: print_debug((body.attributes.player_name) + " has entered %s's reach area" % attributes.player_name) elif body is Ball: print_debug("The ball has entered %s's reach area" % attributes.player_name) ball_within_reach = true current_ball = body func on_player_reach_area_body_exited(body: PhysicsBody2D) -> void: if body is Player: print_debug((body.attributes.player_name) + " has exited %s's reach area" % attributes.player_name) elif body is Ball: print_debug("The ball has exited %s's reach area" % attributes.player_name) ball_within_reach = false func on_velocity_computed(safe_velocity: Vector2) -> void: look_at(player_nav.get_next_path_position()) velocity = safe_velocity move_and_slide()