Implemented demon enemy combat, enemy knockback, and directional player attacks

- Added Demon enemy scene with detection, pursuit, attack, hurt, and death states
- Configured Demon collision layers, detection area, and attack hitbox
- Fixed Demon movement to pursue player horizontally and attack at close range
- Allowed enemy/player overlap for melee combat encounters
- Added enemy damage and death handling
- Added knockback system for enemies when hit
- Fixed player punch hitbox positioning based on facing direction
- Corrected directional melee attacks so enemies can be hit from both left and right sides
- Fixed collision mask issues affecting floors and enemy detection
- Improved memory piece pickup interaction to support button-based collection
- Continued testing and debugging combat interactions in Graveyard and Demon levels
This commit is contained in:
doctorbatmanwho-creator committed 2026-06-18 20:27:14 -04:00
1 parent f0d3931c37
commit 13f95562a7
7 files changed
+90 -14

No files matched your search

+24 -2
View File
@@ -14,6 +14,7 @@ var is_dead := false
var is_hurt := false
var is_attacking := false
var attack_cooldown := false
var knockback_velocity := Vector2.ZERO
func _ready() -> void:
health = max_health
@@ -28,7 +29,18 @@ func _physics_process(_delta: float) -> void:
if is_dead:
return
if is_hurt or is_attacking:
if is_hurt:
velocity = knockback_velocity
knockback_velocity = knockback_velocity.move_toward(
Vector2.ZERO,
800 * _delta
)
move_and_slide()
return
if is_attacking:
velocity = Vector2.ZERO
move_and_slide()
return
@@ -92,11 +104,20 @@ func take_damage(amount: int = 1) -> void:
if health <= 0:
die()
else:
is_hurt = true
velocity = Vector2.ZERO
if player:
var knockback_direction = sign(global_position.x - player.global_position.x)
knockback_velocity = Vector2(knockback_direction * 200, 0)
sprite.play("hurt")
await get_tree().create_timer(0.3).timeout
is_hurt = false
knockback_velocity = Vector2.ZERO
func die() -> void:
if is_dead:
return
@@ -119,6 +140,7 @@ func _on_detection_body_exited(body: Node) -> void:
func _on_animation_finished() -> void:
if sprite.animation == "hurt":
is_hurt = false
knockback_velocity = Vector2.ZERO
if sprite.animation == "attack":
is_attacking = false
+32 -4
View File
@@ -13,7 +13,7 @@ const JUMP_VELOCITY = -400.0
@onready var child_graphic: AnimatedSprite2D = $ChildGraphic
@onready var punch_hitbox: Area2D = $PunchHitbox
var using_child_form := false
var punch_hitbox_start_x := 0.0
enum FaceDirection{LEFT, RIGHT}
var facing:FaceDirection = FaceDirection.RIGHT
@@ -122,11 +122,38 @@ func handle_movement(_delta):
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
if direction < 0:
facing = FaceDirection.LEFT
get_active_graphic().flip_h = true
punch_hitbox.position.x = -punch_hitbox_start_x
if direction > 0:
facing = FaceDirection.RIGHT
get_active_graphic().flip_h = false
punch_hitbox.position.x = punch_hitbox_start_x
if current_state == State.PUNCH:
velocity.x = 0
return
func update_punch_hitbox_position() -> void:
if facing == FaceDirection.LEFT:
punch_hitbox.position.x = -punch_hitbox_start_x
else:
punch_hitbox.position.x = punch_hitbox_start_x
print("Facing: ", facing)
print("PunchHitbox X: ", punch_hitbox.position.x)
func handle_input():
direction = Input.get_axis("ui_left", "ui_right")
if direction < 0:
facing = FaceDirection.LEFT
if direction > 0:
facing = FaceDirection.RIGHT
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = JUMP_VELOCITY
current_state = State.JUMP
@@ -134,7 +161,9 @@ func handle_input():
if Input.is_action_just_pressed("attack"):
print("ATTACK PRESSED")
update_punch_hitbox_position()
current_state = State.PUNCH
await get_tree().create_timer(0.25).timeout
_do_punch_damage()
if Input.is_action_just_pressed("shove") && pushEnabled:
@@ -154,9 +183,6 @@ func handle_input():
%SceneManager.makeBullet(left_spawn.global_transform, -700)
# Get the input direction and handle the movement/deceleration.
direction = Input.get_axis("ui_left", "ui_right")
func handle_collisions():
for i in get_slide_collision_count():
var c = get_slide_collision(i)
@@ -188,6 +214,7 @@ func _ready() -> void:
_set_stair_collision(false)
floor_max_angle = deg_to_rad(60)
punch_hitbox.monitoring = false
punch_hitbox_start_x = abs(punch_hitbox.position.x)
func set_camera_limits(left: int, top: int, right: int, bottom: int) -> void:
camera.limit_left = left
@@ -251,6 +278,7 @@ func _do_punch_damage() -> void:
punch_hitbox.monitoring = true
await get_tree().physics_frame
await get_tree().physics_frame
var bodies = punch_hitbox.get_overlapping_bodies()
print("Punch overlaps: ", bodies.size())
+24 -3
View File
@@ -10,7 +10,7 @@ extends CharacterBody2D
@export var memory_wardrobe: Node2D
@onready var sprite: AnimatedSprite2D = $AnimatedSprite2D
@onready var detection_area: Area2D = $Area2D
@onready var detection_area: Area2D = $DetectionArea
@onready var attack_hitbox = $AttackHitbox
@@ -20,6 +20,7 @@ var is_dead := false
var is_hurt := false
var is_attacking := false
var attack_cooldown := false
var knockback_velocity := Vector2.ZERO
func _ready() -> void:
health = max_health
@@ -38,7 +39,18 @@ func _physics_process(delta: float) -> void:
if not is_on_floor():
velocity.y += gravity * delta
if is_hurt or is_attacking:
if is_hurt:
velocity = knockback_velocity
knockback_velocity = knockback_velocity.move_toward(
Vector2.ZERO,
800 * delta
)
move_and_slide()
return
if is_attacking:
velocity.x = 0
move_and_slide()
return
@@ -105,9 +117,17 @@ func take_damage(amount: int = 1) -> void:
die()
else:
is_hurt = true
velocity.x = 0
if player:
var knockback_direction = sign(global_position.x - player.global_position.x)
knockback_velocity = Vector2(knockback_direction * 125, 0)
sprite.play("hurt")
await get_tree().create_timer(0.3).timeout
is_hurt = false
knockback_velocity = Vector2.ZERO
func die() -> void:
if is_dead:
return
@@ -130,6 +150,7 @@ func _on_detection_body_exited(body: Node) -> void:
func _on_animation_finished() -> void:
if sprite.animation == "hurt":
is_hurt = false
knockback_velocity = Vector2.ZERO
if sprite.animation == "attack":
is_attacking = false