- Created Skeleton enemy scene with idle, walk, attack, hurt, and death animations - Added player detection and enemy pursuit AI - Implemented skeleton attack system and player damage - Added player punch attack for adult character - Implemented enemy damage and health system - Added skeleton death handling - Connected MemoryPiece spawning to defeated skeletons - Added configurable memory piece textures and wardrobe assignments - Implemented memory piece collection and return-to-graveyard workflow - Added interact action to Input Map - Continued development of Wardrobe 1 combat encounter - Fixed multiple collision, hitbox, and animation issues
150 lines
3.2 KiB
GDScript
150 lines
3.2 KiB
GDScript
extends CharacterBody2D
|
|
|
|
@export var speed := 75.0
|
|
@export var gravity := 980.0
|
|
@export var max_health := 3
|
|
@export var attack_range := 40.0
|
|
@export var memory_piece_scene: PackedScene
|
|
@export var memory_texture: Texture2D
|
|
@export var memory_return_spawn: Marker2D
|
|
@export var memory_wardrobe: Node2D
|
|
|
|
@onready var sprite: AnimatedSprite2D = $AnimatedSprite2D
|
|
@onready var detection_area: Area2D = $Area2D
|
|
@onready var attack_hitbox = $AttackHitbox
|
|
|
|
|
|
var health := 3
|
|
var player: Player = null
|
|
var is_dead := false
|
|
var is_hurt := false
|
|
var is_attacking := false
|
|
var attack_cooldown := false
|
|
|
|
func _ready() -> void:
|
|
health = max_health
|
|
attack_hitbox.monitoring = false
|
|
sprite.play("idle")
|
|
|
|
detection_area.body_entered.connect(_on_detection_body_entered)
|
|
detection_area.body_exited.connect(_on_detection_body_exited)
|
|
|
|
sprite.animation_finished.connect(_on_animation_finished)
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
if is_dead:
|
|
return
|
|
|
|
if not is_on_floor():
|
|
velocity.y += gravity * delta
|
|
|
|
if is_hurt or is_attacking:
|
|
velocity.x = 0
|
|
move_and_slide()
|
|
return
|
|
|
|
if player:
|
|
var direction := player.global_position.x - global_position.x
|
|
|
|
if abs(direction) > attack_range:
|
|
velocity.x = sign(direction) * speed
|
|
sprite.play("walk")
|
|
|
|
if velocity.x < 0:
|
|
sprite.flip_h = true
|
|
elif velocity.x > 0:
|
|
sprite.flip_h = false
|
|
else:
|
|
velocity.x = 0
|
|
attack()
|
|
else:
|
|
velocity.x = move_toward(velocity.x, 0, speed)
|
|
sprite.play("idle")
|
|
|
|
move_and_slide()
|
|
|
|
func attack() -> void:
|
|
if is_attacking:
|
|
return
|
|
if attack_cooldown:
|
|
return
|
|
is_attacking = true
|
|
attack_cooldown = true
|
|
velocity.x = 0
|
|
sprite.play("attack")
|
|
|
|
await get_tree().create_timer(0.2).timeout
|
|
|
|
do_attack_damage()
|
|
|
|
func do_attack_damage() -> void:
|
|
print("Checking attack hit")
|
|
|
|
attack_hitbox.monitoring = true
|
|
await get_tree().physics_frame
|
|
await get_tree().physics_frame
|
|
|
|
var bodies = attack_hitbox.get_overlapping_bodies()
|
|
print("Bodies found: ", bodies.size())
|
|
|
|
for body in bodies:
|
|
if body is Player:
|
|
print("PLAYER HIT")
|
|
body.playerTakesDamage(1)
|
|
|
|
attack_hitbox.monitoring = false
|
|
|
|
func take_damage(amount: int = 1) -> void:
|
|
if is_dead:
|
|
return
|
|
|
|
health -= amount
|
|
print("Skeleton health:", health)
|
|
|
|
if health <= 0:
|
|
die()
|
|
else:
|
|
is_hurt = true
|
|
velocity.x = 0
|
|
sprite.play("hurt")
|
|
|
|
func die() -> void:
|
|
if is_dead:
|
|
return
|
|
|
|
is_dead = true
|
|
velocity.x = 0
|
|
sprite.play("death")
|
|
print("Skeleton died")
|
|
|
|
func _on_detection_body_entered(body: Node) -> void:
|
|
if body is Player:
|
|
player = body
|
|
print("Skeleton detected player")
|
|
|
|
func _on_detection_body_exited(body: Node) -> void:
|
|
if body == player:
|
|
player = null
|
|
print("Skeleton lost player")
|
|
|
|
func _on_animation_finished() -> void:
|
|
if sprite.animation == "hurt":
|
|
is_hurt = false
|
|
|
|
if sprite.animation == "attack":
|
|
is_attacking = false
|
|
await get_tree().create_timer(1.0).timeout
|
|
attack_cooldown = false
|
|
|
|
if sprite.animation == "death":
|
|
if memory_piece_scene:
|
|
var piece = memory_piece_scene.instantiate()
|
|
get_parent().add_child(piece)
|
|
piece.global_position = global_position
|
|
|
|
piece.memory_texture = memory_texture
|
|
piece.return_spawn = memory_return_spawn
|
|
piece.wardrobe = memory_wardrobe
|
|
|
|
queue_free()
|