summaryrefslogtreecommitdiff
path: root/Scenes/Entities/Enemies/Components/Movement.gd
blob: 3174508c7b5a602f32fc362a95ead4fa77f53780 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
class_name ComponentMovement
extends Node


signal direction_changed

@export_node_path("CharacterBody2D") var entityPath: NodePath
@onready var entity: CharacterBody2D = get_node(entityPath)

@export_node_path("AnimatedSprite2D") var spritePath: NodePath
@onready var sprite: AnimatedSprite2D = get_node(spritePath)

@export var SPEED: float

const DIRECTIONS = [Vector2.UP, Vector2.RIGHT, Vector2.DOWN, Vector2.LEFT]
var CURRENT_DIRECTION = Vector2.UP
var LAST_DIRECTION = Vector2.UP
var was_colliding = false

var animations: Dictionary = {
	"default": "default",
	"up": "up",
	"down": "down",
	"left": "left",
	"right": "right",
}

@export var timer_time: float = 3.0
@onready var MovementTimer: Timer = Timer.new()

@export var follows: bool = false
@export_range(1, 100, 1) var follow_chance: int = 100


func _ready():
	MovementTimer.wait_time = timer_time
	MovementTimer.autostart = true
	MovementTimer.connect("timeout", Callable(_on_movement_timer_timeout))
	add_child(MovementTimer)


func physics_process(delta):
	if CURRENT_DIRECTION == Vector2.UP:
		entity.velocity.y -= SPEED/2
		if sprite.sprite_frames.has_animation(animations["up"]):
			sprite.play(animations["up"])
	elif CURRENT_DIRECTION == Vector2.DOWN:
		entity.velocity.y += SPEED/2
		if sprite.sprite_frames.has_animation(animations["down"]):
			sprite.play(animations["down"])
	elif CURRENT_DIRECTION == Vector2.LEFT:
		entity.velocity.x -= SPEED/2
		if sprite.sprite_frames.has_animation(animations["left"]):
			sprite.play(animations["left"])
	elif CURRENT_DIRECTION == Vector2.RIGHT:
		entity.velocity.x += SPEED/2
		if sprite.sprite_frames.has_animation(animations["right"]):
			sprite.play(animations["right"])
	
	if sprite.sprite_frames.has_animation(animations["default"]):
		sprite.play(animations["default"])
	
	var collision = entity.move_and_collide(entity.velocity * delta)
	entity.velocity = entity.velocity.lerp(Vector2(0, 0), 1) # speed too low => no collision
	
	# todo movement along grid (maybe move position to current tile center)
	var target_grid_position = Utilities.from_grid_to_position(Utilities.get_level_position(entity) + CURRENT_DIRECTION)
	entity.position = entity.position.move_toward(target_grid_position, delta*SPEED/2)
	# todo or set velocity to tiles per SPEED per second somehow, instead of Timer
	
	if collision:
		was_colliding = true
		if MovementTimer.time_left > 0:
			_on_movement_timer_timeout()
	else:
		was_colliding = false
	
	return collision


func set_animations(new_animations: Dictionary):
	animations.merge(new_animations, true)


func _on_movement_timer_timeout():
	var randomize_direction = false

	if false and follows and randi_range(0, 100) <= follow_chance:
		var player_direction = entity.position.direction_to(Global.player.position)
		var query = PhysicsRayQueryParameters2D.new()
		query.set_from(entity.position)
		query.set_to(Global.player.position)
		query.set_collision_mask(entity.collision_mask)
		var intersection = entity.get_world_2d().direct_space_state.intersect_ray(query)
		if intersection:
			randomize_direction = true
		
		if abs(player_direction.x) >= abs(player_direction.y):
			if player_direction.x >= 0:
				CURRENT_DIRECTION = Vector2.RIGHT
			elif player_direction.x < 0:
				CURRENT_DIRECTION = Vector2.LEFT
		elif abs(player_direction.y) > abs(player_direction.x):
			if player_direction.y >= 0:
				CURRENT_DIRECTION = Vector2.DOWN
			elif player_direction.y < 0:
				CURRENT_DIRECTION = Vector2.UP
		
		if was_colliding and LAST_DIRECTION == CURRENT_DIRECTION:
			randomize_direction = true
	else:
		randomize_direction = true
		
	if randomize_direction:
		var directions = DIRECTIONS.duplicate()
		
		directions.erase(CURRENT_DIRECTION)
		directions.shuffle()
			
		if not directions.is_empty():
			CURRENT_DIRECTION = directions[0]

	emit_signal("direction_changed", CURRENT_DIRECTION)
	LAST_DIRECTION = CURRENT_DIRECTION
	
	if not sprite.sprite_frames.has_animation(animations["default"]):
		var frame = sprite.frame
		var progress = sprite.frame_progress
		if CURRENT_DIRECTION == Vector2.UP and sprite.sprite_frames.has_animation(animations["up"]):
			sprite.play(animations["up"])
		elif CURRENT_DIRECTION == Vector2.DOWN and sprite.sprite_frames.has_animation(animations["down"]):
			sprite.play(animations["down"])
		elif CURRENT_DIRECTION == Vector2.LEFT and sprite.sprite_frames.has_animation(animations["left"]):
			sprite.play(animations["left"])
		elif CURRENT_DIRECTION == Vector2.RIGHT and sprite.sprite_frames.has_animation(animations["right"]):
			sprite.play(animations["right"])
		sprite.set_frame_and_progress(frame, progress)
	
	MovementTimer.start()