Godot Version
4.3
Question
i have setted up an enemy that targets the player and moves via tilemap and astargrid, however i have 1 problem
i want the enemy to move to a random tile (only a walkable tile) when it goes into a certain state, luckily path (a variable i made) had an indentifier called “pick_random”, so i tried it and the enemy isnt going to random tiles, it just freezes until it switches to another state that allows it to chase the player
is it because of something i forgot to type? or something else? here’s where “pick_random()” is located in:
func chase():
print("CHASE")
is_moving = true
var path = astar_grid.get_id_path(
tile_map.local_to_map(global_position),
tile_map.local_to_map(player.global_position)
)
path.pop_front()
if path.size() == 0:
print("arrived at pacman")
return
if path.is_empty():
print("cant find path")
return
var original_position = Vector2(global_position)
global_position = tile_map.map_to_local(path[0])
body.global_position = original_position
var movement_direction = global_position - body.global_position
update_direction(movement_direction)
is_moving = true
target.global_position
current_state = GhostState.CHASE
if current_state == GhostState.RUN_AWAY:
is_moving = true
path.pick_random()
elif current_state == GhostState.EATEN:
pass
and also heres the full code of the enemy:
extends Node2D
class_name Ghost
enum GhostState {CHASE, RUN_AWAY, EATEN}
signal frightened_timeout
@onready var player: Sprite2D = $"../Player" as PacMan
@onready var tile_map: TileMap = $"../TileMap"
@onready var body = $Sprite2D as BodySprite
@onready var target: Sprite2D = $Target
@onready var eyes = $Sprite2D/eyes as EyesSprite
@onready var ghostsiren: AudioStreamPlayer2D = $"../SFX/ghostsiren"
var current_state: GhostState
@onready var frightened_timer: Timer = $"../Frightened_Timer"
@export var color: Color
@onready var area_2d: Area2D = $Sprite2D/Area2D
@onready var frightenedghost: AudioStreamPlayer2D = $"../SFX/frightenedghost"
@onready var gate_tile: Sprite2D = $"../GateTile"
@onready var ghosteaten: AudioStreamPlayer2D = $"../SFX/ghosteaten"
var is_blinking = false
@export var move_speed: float = 1
var direction = null
var astar_grid: AStarGrid2D
var is_moving: bool
func _ready() -> void:
move_speed = 0.9
ghostsiren.play()
is_blinking = false
area_2d.set_collision_mask_value(1, true)
body.normal()
eyes.show()
astar_grid = AStarGrid2D.new()
astar_grid.region = tile_map.get_used_rect()
astar_grid.cell_size = Vector2(8, 8)
astar_grid.diagonal_mode = AStarGrid2D.DIAGONAL_MODE_NEVER
astar_grid.update()
var region_size = astar_grid.region.size
var region_position = astar_grid.region.position
for x in region_size.x:
for y in region_size.y:
var tile_position = Vector2i(
x + region_position.x,
y + region_position.y,
)
var tile_data = tile_map.get_cell_tile_data(0, tile_position)
if tile_data == null or not tile_data.get_custom_data("walk_tiles") or tile_data.get_custom_data("gate"):
astar_grid.set_point_solid(tile_position)
func _process(_delta: float) -> void:
if is_moving:
return
states()
if !frightened_timer.is_stopped() && frightened_timer.time_left < frightened_timer.wait_time / 5 && !is_blinking:
start_flashing()
func chase():
print("CHASE")
is_moving = true
var path = astar_grid.get_id_path(
tile_map.local_to_map(global_position),
tile_map.local_to_map(player.global_position)
)
path.pop_front()
if path.size() == 0:
print("arrived at pacman")
return
if path.is_empty():
print("cant find path")
return
var original_position = Vector2(global_position)
global_position = tile_map.map_to_local(path[0])
body.global_position = original_position
var movement_direction = global_position - body.global_position
update_direction(movement_direction)
is_moving = true
target.global_position
current_state = GhostState.CHASE
if current_state == GhostState.RUN_AWAY:
is_moving = true
path.pick_random()
elif current_state == GhostState.EATEN:
pass
func _physics_process(_delta: float) -> void:
if is_moving:
body.global_position = body.global_position.move_toward(global_position, move_speed)
if body.global_position == global_position:
is_moving = false
func update_direction(movement: Vector2) -> void:
if movement.x > 0:
direction = Vector2.RIGHT
elif movement.x < 0:
direction = Vector2.LEFT
elif movement.y > 0:
direction = Vector2.DOWN
elif movement.y < 0:
direction = Vector2.UP
# Now, update the sprite texture based on the direction
eyes.change_texture_based_on_direction(direction)
func _on_area_2d_body_entered(_body = player) -> void:
if current_state == GhostState.RUN_AWAY:
print("EATEN")
get_eaten()
elif current_state == GhostState.CHASE:
print("DEATH")
area_2d.set_collision_mask_value(1, false)
get_tree().quit()
func frightened_mode():
print("FRIGHTENED")
if frightened_timer.is_stopped():
ghostsiren.stop()
body.frightened()
eyes.hide_eyes()
frightened_timer.start()
is_blinking = false
move_speed = 0.6
current_state = GhostState.RUN_AWAY
func _on_frightened_timer_timeout():
print("BACK TO CHASE")
frightened_timeout.emit()
is_blinking = false
eyes.show_eyes()
body.normal()
chase()
ghostsiren.play()
frightenedghost.stop()
move_speed = 0.9
current_state = GhostState.CHASE
func get_eaten():
if current_state != GhostState.EATEN:
print("EATEN")
ghosteaten.play()
body.eaten()
eyes.show_eyes()
Global.score += 200
frightened_timer.stop()
frightenedghost.stop()
frightened_timeout.emit()
current_state = GhostState.EATEN
$"200Points".show()
await get_tree().create_timer(1).timeout
$"200Points".hide()
is_moving = true
var eaten_path = astar_grid.get_id_path(
tile_map.local_to_map(global_position),
tile_map.local_to_map(gate_tile.global_position)
)
eaten_path.pop_front()
move_speed = 5
func start_flashing():
body.flashing()
func states():
if current_state == GhostState.CHASE:
chase()
elif current_state == GhostState.RUN_AWAY:
frightened_mode()
elif current_state == GhostState.EATEN:
get_eaten()
func start_chase_after_eaten():
chase()
body.normal()
body.show()
move_speed = 0.9