This commit is contained in:
Andriy Yednarovych
2026-02-22 19:26:26 +01:00
parent fd1ff19c4c
commit e877c5f058
211 changed files with 9385 additions and 0 deletions

11
player/scripts/camera.gd Normal file
View File

@@ -0,0 +1,11 @@
class_name Camera extends Camera2D
func _ready() -> void:
LevelManager.Tilemap_boudns_change.connect(update_limits)
func update_limits(bounds: Array[Vector2]) -> void:
limit_left = int(bounds[0].x)
limit_top = int(bounds[0].y)
limit_right = int(bounds[1].x)
limit_bottom = int(bounds[1].y)

View File

@@ -0,0 +1 @@
uid://gyjl7owe3dxx

87
player/scripts/player.gd Normal file
View File

@@ -0,0 +1,87 @@
class_name Player extends CharacterBody2D
const DIR_4 = [
Vector2.RIGHT,
Vector2.DOWN,
Vector2.LEFT,
Vector2.UP,
]
signal direction_change(new_direction: Vector2)
signal player_damaged(hurtbox: Hurtbox)
@onready var animation_player : AnimationPlayer = $AnimationPlayer
@onready var sprite : Sprite2D = $Sprite2D
@onready var state_machine: PlayerStateMachine = $state_machine
@onready var hitbox: Hitbox = $Hitbox
@onready var effect_animation: AnimationPlayer = $effect_animation
@export_group("Stats")
@export var hp: int = 6
@export var maxHp: int = 6
var cardinal_direction : Vector2 = Vector2.DOWN
var direction : Vector2 = Vector2.ZERO
var invlunerable: bool = false
func _ready() -> void:
PlayerManager.player = self
state_machine.initialize(self)
hitbox.damaged.connect(on_damage)
update_hp(99)
func _process(_delta: float) -> void:
direction = Vector2(
Input.get_axis("left", "right"),
Input.get_axis("up", "down"),
).normalized()
func _physics_process(_delta: float) -> void:
move_and_slide()
func set_direction() -> bool:
if direction == Vector2.ZERO:
return false
var new_direction = DIR_4[int(round((direction + cardinal_direction * 0.1).angle() / TAU * DIR_4.size()))]
if new_direction == cardinal_direction:
return false
cardinal_direction = new_direction
direction_change.emit(new_direction)
sprite.scale.x = -1 if cardinal_direction == Vector2.LEFT else 1
return true
func update_animation(state: String) -> void:
animation_player.play(state + "_" + anim_direction())
func anim_direction() -> String:
var direction_result : String = "side"
if cardinal_direction == Vector2.DOWN:
direction_result = "down"
elif cardinal_direction == Vector2.UP:
direction_result = "up"
return direction_result
func on_damage(hurtbox: Hurtbox) -> void:
if invlunerable:
return
update_hp(-hurtbox.damage)
if hp > 0:
player_damaged.emit(hurtbox)
else:
player_damaged.emit(hurtbox)
update_hp(99)
func update_hp(more_hp: int) -> void:
hp = clampi(hp + more_hp, 0, maxHp)
Hud.update_hp(hp, maxHp)
func make_invulnerable(duration: float = 1.0) -> void:
invlunerable = true
hitbox.monitoring = false
await get_tree().create_timer(duration).timeout
invlunerable = false
hitbox.monitoring = true

View File

@@ -0,0 +1 @@
uid://bh2madpelppjn

View File

@@ -0,0 +1,19 @@
class_name PlayerInteractionsHost extends Node2D
@onready var player: Player = $".."
func _ready() -> void:
player.direction_change.connect(update_direction)
func update_direction(new_direction: Vector2) -> void:
match new_direction:
Vector2.DOWN:
rotation_degrees = 0
Vector2.UP:
rotation_degrees = 180
Vector2.LEFT:
rotation_degrees = 90
Vector2.RIGHT:
rotation_degrees = 270
_:
rotation_degrees = 0

View File

@@ -0,0 +1 @@
uid://ba6scm5um18sd

View File

@@ -0,0 +1,46 @@
class_name PlayerStateMachine extends Node
var states: Array[State]
var previous_state: State
var current_state: State
func _ready() -> void:
process_mode = Node.PROCESS_MODE_DISABLED
func _process(delta: float) -> void:
change_state(current_state.process(delta))
func _physics_process(delta: float) -> void:
change_state(current_state.process(delta))
func _unhandled_input(event) -> void:
change_state(current_state.handle_input(event))
func initialize(player: Player) -> void:
states = []
for child in get_children():
if child is State:
states.append(child)
if states.is_empty():
return
var firstState = states[0]
firstState.player = player
firstState.state_machine = self
for state in states:
state.init()
change_state(firstState)
process_mode = Node.PROCESS_MODE_INHERIT
func change_state(new_state: State) -> void:
if new_state == null or new_state == current_state:
return
if current_state:
current_state.exit()
previous_state = current_state
current_state = new_state
current_state.enter()

View File

@@ -0,0 +1 @@
uid://cbmwqg1xr14sg

View File

@@ -0,0 +1,13 @@
extends Area2D
func _ready() -> void:
body_entered.connect(on_body_entered)
body_exited.connect(on_body_exited)
func on_body_entered(body: Node2D) -> void:
if body is PushableStatute:
body.push_direction = PlayerManager.player.direction
func on_body_exited(body: Node2D) -> void:
if body is PushableStatute:
body.push_direction = Vector2.ZERO

View File

@@ -0,0 +1 @@
uid://cyff8l2rrvtl

25
player/scripts/state.gd Normal file
View File

@@ -0,0 +1,25 @@
class_name State extends Node
static var player : Player
static var state_machine: PlayerStateMachine
func _ready() -> void:
pass
func init() -> void:
pass
func enter() -> void:
pass
func exit() -> void:
pass
func process(_delta : float) -> State:
return null
func physics(_delta : float) -> State:
return null
func handle_input(_event : InputEvent) -> State:
return null

View File

@@ -0,0 +1 @@
uid://cmcwtkqxxkhik

View File

@@ -0,0 +1,44 @@
class_name State_Attack extends State
@onready var walk: State = $"../walk"
@onready var idle: State = $"../idle"
@onready var animation_player: AnimationPlayer = $"../../AnimationPlayer"
@onready var attack_animation_player: AnimationPlayer = $"../../Sprite2D/attack_effect/AnimationPlayer"
@onready var audio_player: AudioStreamPlayer2D = $"../../audio/audio"
@onready var hurtbox: Hurtbox = %attack_hurtbox
@export var attack_sound: AudioStream
@export_range(1, 20, 0.5) var decelerate_speed: float = 5.0
var attacking: bool = false
func enter() -> void:
animation_player.animation_finished.connect(end_attack)
player.update_animation("attack")
attack_animation_player.play("attack_" + player.anim_direction())
audio_player.stream = attack_sound
audio_player.pitch_scale = randf_range(0.9, 1.1)
audio_player.play()
attacking = true
await get_tree().create_timer(0.075).timeout
if attacking:
hurtbox.monitoring = true
func exit() -> void:
animation_player.animation_finished.disconnect(end_attack)
attacking = false
hurtbox.monitoring = false
func process(delta : float) -> State:
player.velocity -= player.velocity * decelerate_speed * delta
if attacking:
return null
return idle if player.direction == Vector2.ZERO else walk
func physics(_delta : float) -> State:
return null
func handle_input(_event : InputEvent) -> State:
return null
func end_attack(_new_animation_name: String) -> void:
attacking = false

View File

@@ -0,0 +1 @@
uid://rkjhx7gfma1e

View File

@@ -0,0 +1,26 @@
class_name State_Idle extends State
@onready var walk: State = $"../walk"
@onready var attack: State = $"../attack"
func enter() -> void:
player.update_animation("idle")
func exit() -> void:
pass
func process(_delta : float) -> State:
if player.direction != Vector2.ZERO:
return walk
player.velocity = Vector2.ZERO
return null
func physics(_delta : float) -> State:
return null
func handle_input(event : InputEvent) -> State:
if event.is_action_pressed("attack"):
return attack
if event.is_action_pressed("interact"):
PlayerManager.interact_pressed.emit()
return null

View File

@@ -0,0 +1 @@
uid://cabtgwm5i08oe

View File

@@ -0,0 +1,46 @@
class_name StateStun extends State
@export var knockback_speed: float = 200.0
@export var decelerate_speed: float = 10.0
@export var invulnerable_duration: float = 1.0
@onready var idle: State = $"../idle"
var hurtbox: Hurtbox
var direction: Vector2
var next_state: State
func init() -> void:
player.player_damaged.connect(on_damaged)
func enter() -> void:
player.animation_player.animation_finished.connect(on_animation_finished)
direction = player.global_position.direction_to(hurtbox.global_position)
player.velocity = direction * -knockback_speed
player.set_direction()
player.update_animation("stun")
player.make_invulnerable(invulnerable_duration)
player.effect_animation.play("damaged")
func exit() -> void:
player.animation_player.animation_finished.disconnect(on_animation_finished)
next_state = null
func process(delta: float) -> State:
player.velocity -= player.velocity * decelerate_speed * delta
return next_state
func physics(_delta: float) -> State:
return null
func handle_input(_event: InputEvent) -> State:
return null
func on_damaged(incomig_hurtbox: Hurtbox) -> void:
hurtbox = incomig_hurtbox
state_machine.change_state(self)
func on_animation_finished(_name: String) -> void:
next_state = idle

View File

@@ -0,0 +1 @@
uid://pr4o7w6faw08

View File

@@ -0,0 +1,31 @@
class_name State_Walk extends State
@export var move_speed: float = 100.0
@onready var idle: State = $"../idle"
@onready var attack: State = $"../attack"
func enter() -> void:
player.update_animation("walk")
func exit() -> void:
pass
func process(_delta : float) -> State:
if player.direction == Vector2.ZERO:
return idle
player.velocity = player.direction * move_speed
if player.set_direction():
player.update_animation("walk")
return null
func physics(_delta : float) -> State:
return null
func handle_input(event : InputEvent) -> State:
if event.is_action_pressed("attack"):
return attack
if event.is_action_pressed("interact"):
PlayerManager.interact_pressed.emit()
return null

View File

@@ -0,0 +1 @@
uid://c6p40pfivsfxo