Files
hsgj25-growth/growth/player.gd
SondreElg e25a2eed60 aaaaa
2025-10-05 14:47:20 +02:00

144 lines
3.6 KiB
GDScript

extends CharacterBody2D
# ActionState should probably be expandable to
enum ActionState {None, Cycling, Firing, Charging}
enum MoveState {Still, Moving, Dashing, Knockback}
@export var speed = 200 # How fast the player will move (pixels/sec).
@export var dash_cooldown = 0.3
@onready var camera: Camera2D = %PlayerCamera
@onready var sprite: AnimatedSprite2D = $PlayerSprite
@onready var hand: Control = %Hand;
@onready var shield: Sprite2D = $Shield
@onready var score_counter: RichTextLabel = %ScoreCounter
var score = 0;
var high_score = 0;
var shield_active = true;
var move_direction = Vector2.ZERO;
var target = Vector2.ZERO # The position of the player's cursor.
var screen_size # Size of the game window.
var action_state = ActionState.None
var move_state = MoveState.Still
var charge_level = 0;
var charge_rate = 1;
var charged = false;
var dash_cooldown_timer = 0;
var dash_on_cooldown = false;
var knockback_timer: Timer = Timer.new()
func get_target_pos():
return self.get_global_mouse_position()
func update_move_direction():
move_direction = Vector2.ZERO
if Input.is_action_pressed("move_right"):
move_direction.x += 1
if Input.is_action_pressed("move_left"):
move_direction.x -= 1
if Input.is_action_pressed("move_down"):
move_direction.y += 1
if Input.is_action_pressed("move_up"):
move_direction.y -= 1
move_direction = move_direction.normalized()
func update_target_coords():
target = get_viewport().get_mouse_position()
sprite.look_at(get_global_mouse_position())
func update_camera_position():
if not camera:
return;
var camera_target = (target - screen_size / 2) / 2
camera.position = camera.position.lerp(camera_target, 0.1)
func charge():
# Charge attack
if not charged and action_state == ActionState.Charging:
charge_level += charge_rate;
if charge_level >= 100:
charged = false;
charge_level = 0;
elif charge_level > 0:
# Gradual charge dropoff
charge_level = max(charge_level - charge_rate * 2, 0);
func dash():
if dash_on_cooldown:
return;
hand.discard(); # Must set move_state at start and end of dash
dash_on_cooldown = true;
func _ready():
screen_size = get_viewport_rect().size
knockback_timer.one_shot = true
add_child(knockback_timer);
func _process(delta):
update_target_coords();
update_camera_position();
if (move_state != MoveState.Dashing):
update_move_direction();
if (dash_on_cooldown):
dash_cooldown_timer += delta;
if (dash_cooldown_timer >= dash_cooldown):
dash_on_cooldown = false;
dash_cooldown_timer = 0;
# handle move_state
if knockback_timer.time_left > 0:
pass
elif Input.is_action_just_pressed("dash"):
dash();
elif (move_state != MoveState.Dashing):
velocity = move_direction * speed;
if velocity.x || velocity.y:
move_state = MoveState.Moving;
else:
move_state = MoveState.Still;
move_and_slide();
func take_hit(_damage, knockback_vector, knockback_strength = 1):
# Called when the player takes damage
$HitSFX.play()
if shield_active:
shield_active = false;
# TODO visualize shield
# $Shield.hide();
move_state = MoveState.Knockback;
velocity = knockback_vector;
knockback_timer.start(0.2 * knockback_strength);
else:
reboot();
func add_to_score(amount):
score += amount;
if score > high_score:
high_score = score;
score_counter.text = "Score: %d\nHigh Score: %d" % [score, high_score]
func reset_score():
score = 0;
score_counter.text = "Score: %d\nHigh Score: %d" % [score, high_score]
func reboot():
# Called when the player dies
# For now, just reset position and state
position = Vector2.ZERO;
velocity = Vector2.ZERO;
move_state = MoveState.Still;
shield_active = true;
reset_score();
# hand.discard_all();