extends CharacterBody2D # Child Nodes @onready var camera : Camera2D = $Camera2D; @onready var anim_sprite : AnimatedSprite2D = $AnimatedSprite2D; @onready var earth_aligner : Node2D = $EarthAligner; @onready var sword : Area2D = $Sword; # allow taking away player control var handle_input : bool = true # Gravity var earth_center = Vector2.ZERO; var max_fall_speed = 700; var gravity = 100; # Movement var facing = -1; var hspeed = 150; var jump_strength = 1100; var air_jumps_max = 1; var air_jumps_current = 1; # HP and Iframes signal health_changed(new_health : int) signal player_died var current_hp = 5: set(new_hp): current_hp = new_hp health_changed.emit(current_hp) var max_hp = 5; var hit_invulnerability = 0.5 var inv_time = 0; var dead = false; # Received Knockback var reset_to_velocity = Vector2.ZERO var knockback_strength = 1500 var damage_knockup = 500 # Attack Handling var atk_cooldown = 0.5 var atk_timer = 0 # Active Item var active_item = null var item_cooldown = 0 func _physics_process(delta: float) -> void: manage_iframes(delta) manage_movement_options() manage_active(delta) manage_animation() manage_attack(delta) manage_velocity(delta) move_and_slide() func manage_iframes(delta: float): if(inv_time > 0): inv_time = max(0, inv_time-delta) func manage_attack(delta : float): atk_timer = max(0, atk_timer-delta) if handle_input: if(Input.is_action_just_pressed("attack") and atk_timer <= 0): sword.swing() atk_timer = atk_cooldown func manage_active(delta : float): item_cooldown = max(item_cooldown - delta, 0) if(active_item != null and Input.is_action_just_pressed("item") and item_cooldown <= 0): active_item.activate() func manage_movement_options() -> void: if(is_on_floor()): air_jumps_current = air_jumps_max func manage_animation() -> void: var walk_dir = 0 if(handle_input): if(Input.is_action_pressed("move_right")): walk_dir += 1 if(Input.is_action_pressed("move_left")): walk_dir -= 1 if(walk_dir != 0): facing = walk_dir anim_sprite.scale.x = - abs(anim_sprite.scale.x) * facing if(is_on_floor()): anim_sprite.play("walk") else: anim_sprite.stop() # Later: Jump Animation? else : anim_sprite.stop() func manage_velocity(delta: float) -> void: up_direction = (position - earth_center).normalized(); var old_local_velocity = earth_aligner.local_from_global(velocity) var local_velocity = Vector2(old_local_velocity.x/pow(1.7,60*delta), old_local_velocity.y); local_velocity += Vector2(0, gravity) if handle_input: if(Input.is_action_pressed("move_right")): local_velocity += Vector2(hspeed, 0) if(Input.is_action_pressed("move_left")): local_velocity += Vector2(-hspeed, 0) if(Input.is_action_just_pressed("jump") and (is_on_floor() or air_jumps_current > 0)): var dropped = false if(not is_on_floor()): air_jumps_current -= 1; elif (Input.is_action_pressed("drop")): dropped = true self.position += earth_aligner.global_from_local(Vector2(0,3)) if(not dropped): local_velocity.y = -jump_strength if(local_velocity.y > max_fall_speed): local_velocity.y = max_fall_speed if(reset_to_velocity != Vector2.ZERO): local_velocity = reset_to_velocity reset_to_velocity = Vector2.ZERO velocity = earth_aligner.global_from_local(local_velocity) func hurt(dmg: int, dir: Vector2 = Vector2.ZERO): if(inv_time <= 0): current_hp -= dmg if(current_hp <= 0): die() inv_time = hit_invulnerability reset_to_velocity = Vector2(-sign(earth_aligner.local_from_global(dir).x)*knockback_strength, -damage_knockup) func die(): if not dead: player_died.emit() dead = true func _on_death_screen_visibility_changed() -> void: handle_input = !handle_input