extends RigidBody2D
# Variables for the mob
var health = 100
var max_health = 100
var speed = 100
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var is_chasing = false
var player = null
var patrol_distance = 100
var start_position = Vector2.ZERO
var velocity = Vector2.ZERO
var on_ground = false
var facing_right = true
var health_bar = null
var attack_range_collision_shape = null
var is_attacking = false
const ATTACK_DAMAGE = 20
# Define the animation states
enum State {
IDLE,
WALK,
ATTACK,
HURT,
DIE
}
var state = State.WALK
var attack_cooldown = 1.0
var time_since_last_attack = 0.0
func _ready():
player = get_parent().get_node("Player")
attack_range_collision_shape = $attackDetector # Your collision shape node
start_position = global_position
health_bar = $HealthBar
health_bar.max_value = max_health
health_bar.value = health
# Connect signals for attack detection
$attackDetector.connect("body_entered", Callable(self, "_on_attack_range_body_entered"))
$attackDetector.connect("body_exited", Callable(self, "_on_attack_range_body_exited"))
$playerDetection.connect("body_entered", Callable(self, "_on_player_detection_body_entered"))
$playerDetection.connect("body_exited", Callable(self, "_on_player_detection_body_exited"))
$HammerHit.connect("body_entered", Callable(self, "_on_hammer_hit_body_entered"))
$AnimationPlayer.play("walk")
func _integrate_forces(physics_state):
if state != State.DIE:
if not on_ground:
velocity.y += gravity * get_physics_process_delta_time()
else:
velocity.y = 0
physics_state.set_linear_velocity(velocity)
physics_state.set_angular_velocity(0)
set_rotation_degrees(0)
else:
physics_state.set_linear_velocity(Vector2.ZERO)
physics_state.set_angular_velocity(0)
set_rotation_degrees(0)
func _process(delta):
if $AnimationPlayer.current_animation == "attack1":
return
on_ground = is_on_floor()
match state:
State.WALK:
if is_chasing:
move_towards_player(delta)
else:
patrol(delta)
State.ATTACK:
attack_player(delta)
State.HURT:
hurt_animation()
State.DIE:
die_animation()
time_since_last_attack += delta
func move_towards_player(_delta):
if player and state != State.DIE:
var direction = (player.global_position - global_position).normalized()
velocity.x = direction.x * speed
if direction.x < 0 and facing_right:
flip_mob_left()
elif direction.x > 0 and not facing_right:
flip_mob_right()
if state != State.ATTACK:
velocity.x = direction.x * speed
func patrol(_delta):
if state != State.DIE:
var left_bound = start_position.x - patrol_distance
var right_bound = start_position.x + patrol_distance
if global_position.x <= left_bound and not facing_right:
flip_mob_right()
elif global_position.x >= right_bound and facing_right:
flip_mob_left()
velocity.x = speed if facing_right else -speed
func attack_player(_delta):
if time_since_last_attack >= attack_cooldown and state == State.ATTACK:
if not is_attacking:
start_attack()
func start_attack():
if not is_attacking:
is_attacking = true
$AnimationPlayer.play("attack1")
$HammerHit.set_deferred("monitoring", true) # Enable hitbox for attack
$AnimationPlayer.disconnect("animation_finished", Callable(self, "_on_attack_finished"))
$AnimationPlayer.connect("animation_finished", Callable(self, "_on_attack_finished"))
# Reset the attack cooldown timer
time_since_last_attack = 0.0
func _on_attack_finished(anim_name):
if anim_name == "attack1":
is_attacking = false
$HammerHit.set_deferred("monitoring", false)
if state != State.DIE:
state = State.WALK # Go back to walk or chasing after attacking
func hurt_animation():
if state != State.DIE:
$AnimationPlayer.play("hurt")
state = State.WALK
func die_animation():
if state == State.DIE:
velocity = Vector2.ZERO # Stop all movement
$AnimationPlayer.play("die")
await get_tree().create_timer(1.0).timeout
queue_free()
func _on_VisibleOnScreenNotifier2D_screen_exited():
queue_free()
func take_damage(damage):
health -= damage
update_health_bar()
if health <= 0:
state = State.DIE
die_animation()
else:
state = State.HURT
hurt_animation()
func update_health_bar():
health_bar.value = health
func _on_player_detection_body_entered(body):
if body.is_in_group("player") and state != State.DIE:
print("Player detected")
is_chasing = true
state = State.WALK
func _on_player_detection_body_exited(body):
if body.is_in_group("player") and state != State.DIE:
print("Player exited detection area")
is_chasing = false
state = State.WALK
func flip_mob_left():
if state != State.DIE:
facing_right = false
$AnimatedSprite2D.scale.x = -1
func flip_mob_right():
if state != State.DIE:
facing_right = true
$AnimatedSprite2D.scale.x = 1
func is_on_floor() -> bool:
var space_state = get_world_2d().direct_space_state
var query = PhysicsRayQueryParameters2D.new()
query.from = global_position
query.to = global_position + Vector2(0, 10)
query.exclude = [self]
var result = space_state.intersect_ray(query)
return result != null
func _on_hammer_hit_body_entered(body):
if body.is_in_group("player") and is_attacking and state != State.DIE:
print("Player hit")
body.take_damage(ATTACK_DAMAGE)
func _on_attack_range_body_entered(body):
if body.is_in_group("player") and state != State.DIE:
print("Player within attack range")
state = State.ATTACK
func _on_attack_range_body_exited(body):
if body.is_in_group("player") and state != State.DIE:
print("Player exited attack range")
state = State.WALK # Go back to walking or chasing when the player leaves attack range
You posted this in the wrong forum category. Try posting it in the help category of the forum. Also, describe your problem in more detail, possibly narrowing it down to a specific function you have problems with.
1 Like