139 lines
3.8 KiB
GDScript
139 lines
3.8 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: Timer = Timer.new()
|
|
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(on_end):
|
|
dash_cooldown_timer.start(dash_cooldown);
|
|
var target_dir = position.direction_to(target)
|
|
if (on_end):
|
|
dash_cooldown_timer.timeout.connect(func(): on_end.call(null, self, target_dir), CONNECT_ONE_SHOT);
|
|
velocity = move_direction * speed * 5;
|
|
|
|
func _ready():
|
|
screen_size = get_viewport_rect().size
|
|
knockback_timer.one_shot = true
|
|
dash_cooldown_timer.one_shot = true
|
|
add_child(knockback_timer);
|
|
add_child(dash_cooldown_timer);
|
|
|
|
func _process(_delta):
|
|
update_target_coords();
|
|
update_camera_position();
|
|
if (move_state != MoveState.Dashing):
|
|
update_move_direction();
|
|
|
|
# handle move_state
|
|
if knockback_timer.time_left > 0 or dash_cooldown_timer.time_left > 0:
|
|
pass
|
|
elif Input.is_action_just_pressed("dash"):
|
|
hand.discard(); # Must set move_state at start and end of 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);
|
|
$Shield.visible = false;
|
|
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;
|
|
$Shield.visible = true;
|
|
reset_score();
|
|
# hand.discard_all();
|