diff --git a/game/characters/enemies/abstract_color_cultist.gd b/game/characters/enemies/abstract_color_cultist.gd index 4dc7a2e..1075bc2 100644 --- a/game/characters/enemies/abstract_color_cultist.gd +++ b/game/characters/enemies/abstract_color_cultist.gd @@ -6,5 +6,4 @@ extends AbstractCultist func _ready() -> void: - super._ready() collision_switcher.material = sprite.material diff --git a/game/characters/enemies/abstract_cultist.gd b/game/characters/enemies/abstract_cultist.gd index 4c825d6..4beeda8 100644 --- a/game/characters/enemies/abstract_cultist.gd +++ b/game/characters/enemies/abstract_cultist.gd @@ -2,43 +2,14 @@ class_name AbstractCultist extends CharacterBody2D -enum Type { - Standing, - Walking, - Random, -} - -enum State { - Idle, - WalkLeft, - WalkRight, - LookAround, - ChasingLeft, - ChasingRight, -} - - const MAX_WALK_SPEED = 85 const MAX_CHASE_SPEED = 170 const ACCELERATION = 600.0 -const LOOK_AROUND_CHANCE = 25 -const WALK_CHANCE = 25 - -const DIRECTION_LEFT = -1 -const DIRECTION_RIGHT = 1 - - -@export var type : Type = Type.Standing -@export var initial_state : State = State.Idle var target_x := 0.0 -var _target_found := false -var _state : State: - set = _set_state - @onready var sprite : AnimatedSprite2D = $CultistSprite @onready var left_wall_ray : RayCast2D = $%LeftWallRay @@ -50,217 +21,24 @@ var _state : State: @onready var left_player_distant_ray : RayCast2D = $%LeftPlayerDistantRay @onready var right_player_distant_ray : RayCast2D = $%RightPlayerDistantRay - -func _ready() -> void: - _state = initial_state +@onready var state_machine : CultistStateMachine = $CultistStateMachine +@onready var chase_left_state : CultistState = $CultistStateMachine/ChaseLeftState +@onready var chase_right_state : CultistState = $CultistStateMachine/ChaseRightState -func _physics_process(delta: float) -> void: - match _state: - State.ChasingLeft: - _process_player_ray(left_player_distant_ray) - if position.x < target_x: - SoundManager.play_sfx_stream(SoundManager.sfx_stream_player_lost, global_position) - _state = State.LookAround - else: - update_x_velocity(DIRECTION_LEFT, MAX_CHASE_SPEED, delta) - _check_wall_collision_and_switch_state(DIRECTION_LEFT) - _update_animation() - move_and_slide() - State.ChasingRight: - _process_player_ray(right_player_distant_ray) - if position.x > target_x: - SoundManager.play_sfx_stream(SoundManager.sfx_stream_player_lost, global_position) - _state = State.LookAround - else: - update_x_velocity(DIRECTION_RIGHT, MAX_CHASE_SPEED, delta) - _check_wall_collision_and_switch_state(DIRECTION_RIGHT) - _update_animation() - move_and_slide() - State.WalkLeft: - if _process_player_ray(left_player_distant_ray): - _set_chase_state() - update_x_velocity(DIRECTION_LEFT, MAX_WALK_SPEED, delta) - _check_wall_collision_and_switch_state(DIRECTION_LEFT) - _update_animation() - move_and_slide() - State.WalkRight: - if _process_player_ray(right_player_distant_ray): - _set_chase_state() - update_x_velocity(DIRECTION_RIGHT, MAX_WALK_SPEED, delta) - _check_wall_collision_and_switch_state(DIRECTION_RIGHT) - _update_animation() - move_and_slide() - State.LookAround: - update_x_velocity(0, MAX_WALK_SPEED * 2, delta) - if not _target_found: - var close_rays : Array[RayCast2D] = [left_player_close_ray, right_player_close_ray] - _target_found = _process_player_rays(close_rays) - _update_animation() - move_and_slide() - - -func _set_state(value: State) -> void: - _state = value - - left_player_close_ray.process_mode = Node.PROCESS_MODE_DISABLED - right_player_close_ray.process_mode = Node.PROCESS_MODE_DISABLED - left_player_distant_ray.process_mode = Node.PROCESS_MODE_DISABLED - right_player_distant_ray.process_mode = Node.PROCESS_MODE_DISABLED - left_player_close_ray.hide() - right_player_close_ray.hide() - left_player_distant_ray.hide() - right_player_distant_ray.hide() - - match _state: - State.ChasingLeft, State.WalkLeft: - left_player_distant_ray.process_mode = Node.PROCESS_MODE_INHERIT - left_player_distant_ray.show() - State.ChasingRight, State.WalkRight: - right_player_distant_ray.process_mode = Node.PROCESS_MODE_INHERIT - right_player_distant_ray.show() - State.LookAround: - left_player_close_ray.process_mode = Node.PROCESS_MODE_INHERIT - right_player_close_ray.process_mode = Node.PROCESS_MODE_INHERIT - left_player_close_ray.show() - right_player_close_ray.show() - - -func _process_player_ray(ray: RayCast2D) -> bool: - if ray.is_colliding(): - ray.force_raycast_update() - var collider := ray.get_collider() - if collider is Player: - target_x = collider.position.x - return true - return false - - -func _process_player_rays(rays: Array[RayCast2D]) -> bool: - for ray in rays: - if _process_player_ray(ray): - return true - return false +func _physics_process(_delta: float) -> void: + move_and_slide() func update_x_velocity(direction: int, max_speed: float, delta: float) -> void: velocity.x = move_toward(velocity.x, direction * max_speed, ACCELERATION * delta) -func _check_wall_collision_and_switch_state(direction: int) -> void: - var this_wall_ray := _get_wall_ray(direction) - var other_wall_ray := _get_wall_ray(-direction) - - if this_wall_ray.is_colliding(): - if other_wall_ray.is_colliding(): - _state = State.LookAround - else: - match _state: - State.WalkLeft: - _state = State.WalkRight - State.WalkRight: - _state = State.WalkLeft - State.ChasingLeft, State.ChasingRight: - var stream := SoundManager.sfx_stream_player_lost - SoundManager.play_sfx_stream(stream, global_position) - _state = State.LookAround - - -func _get_wall_ray(direction: int) -> RayCast2D: - if direction < 0: - return left_wall_ray - else: - return right_wall_ray - - -func _update_animation() -> void: - if is_zero_approx(velocity.y): - match _state: - State.WalkLeft: - _play_animation(CultistSprite.ANIMATION_WALK_LEFT) - State.WalkRight: - _play_animation(CultistSprite.ANIMATION_WALK_RIGHT) - State.ChasingLeft: - _play_animation(CultistSprite.ANIMATION_CHASE_LEFT) - State.ChasingRight: - _play_animation(CultistSprite.ANIMATION_CHASE_RIGHT) - State.Idle: - _play_idle_animation() - State.LookAround: - _play_look_around_animation() - - -func _play_idle_animation() -> void: - _play_animation(CultistSprite.ANIMATION_IDLE) - - -func _play_look_around_animation() -> void: - if _is_current_animation_look_around(): return - _play_animation(CultistSprite.LOOK_AROUND_ANIMATIONS.pick_random()) - - -func _is_current_animation_look_around() -> bool: - if not sprite.is_playing(): return false - if sprite.animation in CultistSprite.LOOK_AROUND_ANIMATIONS: return true - return false - - -func _play_animation(animation: String) -> void: - if not sprite.is_playing() or sprite.animation != animation: - sprite.play(animation) - - -func _set_walking_state() -> void: - var is_left_colliding := left_wall_ray.is_colliding() - var is_right_colliding := right_wall_ray.is_colliding() - - if is_left_colliding and is_right_colliding: - _state = State.Idle - elif not is_left_colliding and not is_right_colliding: - _state = State.WalkLeft if randi_range(1, 2) == 1 else State.WalkRight - elif not is_left_colliding: - _state = State.WalkLeft - else: - _state = State.WalkRight - - -func _set_chase_state() -> void: - SoundManager.play_sfx_stream(SoundManager.sfx_stream_player_spoted, global_position) - if target_x < position.x: - _state = State.ChasingLeft - else: - _state = State.ChasingRight - - -func _is_walking_state() -> bool: - return _state == State.WalkLeft or _state == State.WalkRight - - -func _on_animation_finished() -> void: - if _target_found: - _set_chase_state() - _target_found = false - return - - match type: - Type.Standing: - _state = State.Idle - Type.Walking: - _set_walking_state() - Type.Random: - if randi_range(1, 100) <= WALK_CHANCE: - _set_walking_state() - else: - _state = State.Idle - - -func _on_animation_looped() -> void: - if _state == State.Idle or (type == Type.Random and _is_walking_state()): - if randi_range(1, 100) <= LOOK_AROUND_CHANCE: - _state = State.LookAround - - +#TODO Rework func _on_player_touch_area_entered(body: Node2D) -> void: if body is Player: target_x = body.position.x - _set_chase_state() + if body.position.x < position.x: + state_machine._change_state(chase_left_state) + else: + state_machine._change_state(chase_right_state) diff --git a/game/characters/enemies/abstract_cultist.tscn b/game/characters/enemies/abstract_cultist.tscn index df110eb..cf214f1 100644 --- a/game/characters/enemies/abstract_cultist.tscn +++ b/game/characters/enemies/abstract_cultist.tscn @@ -10,8 +10,10 @@ [ext_resource type="Script" uid="uid://b8o0lvuy6a5q1" path="res://game/characters/enemies/state_machine/fall_left_state.gd" id="8_2opx4"] [ext_resource type="Script" uid="uid://cxg54u14yb6go" path="res://game/characters/enemies/state_machine/fall_right_state.gd" id="9_lu83c"] [ext_resource type="Script" uid="uid://bfp8gywqqkju7" path="res://game/characters/enemies/state_machine/look_around_state.gd" id="10_lu83c"] -[ext_resource type="Script" uid="uid://hgn4yll571hp" path="res://game/characters/enemies/state_machine/move_left_state.gd" id="11_lh753"] -[ext_resource type="Script" uid="uid://bwwhmjxhg2adp" path="res://game/characters/enemies/state_machine/move_right_state.gd" id="12_lh753"] +[ext_resource type="Script" uid="uid://hgn4yll571hp" path="res://game/characters/enemies/state_machine/walk_left_state.gd" id="11_lh753"] +[ext_resource type="Script" uid="uid://bwwhmjxhg2adp" path="res://game/characters/enemies/state_machine/walk_right_state.gd" id="12_lh753"] +[ext_resource type="Script" uid="uid://cn2lfl4kuxvjk" path="res://game/characters/enemies/state_machine/chase_left_state.gd" id="13_42ivi"] +[ext_resource type="Script" uid="uid://3kl84tu1vwiv" path="res://game/characters/enemies/state_machine/chase_right_state.gd" id="14_cqp7f"] [sub_resource type="CapsuleShape2D" id="CapsuleShape2D_mocsw"] radius = 4.0 @@ -112,19 +114,37 @@ fall_state = NodePath("../FallState") look_around_state = NodePath("../LookAroundState") cultist = NodePath("../..") -[node name="LookAroundState" parent="CultistStateMachine" unique_id=2025927882 node_paths=PackedStringArray("fall_state", "cultist") instance=ExtResource("5_tu2pi")] +[node name="LookAroundState" parent="CultistStateMachine" unique_id=2025927882 node_paths=PackedStringArray("fall_state", "chase_left_state", "chase_right_state", "cultist") instance=ExtResource("5_tu2pi")] script = ExtResource("10_lu83c") fall_state = NodePath("../FallState") +chase_left_state = NodePath("../ChaseLeftState") +chase_right_state = NodePath("../ChaseRightState") +cultist = NodePath("../..") + +[node name="WalkLeftState" parent="CultistStateMachine" unique_id=276543931 node_paths=PackedStringArray("chase_state", "another_direction_walk_state", "fall_state", "cultist") instance=ExtResource("5_tu2pi")] +script = ExtResource("11_lh753") +chase_state = NodePath("../ChaseLeftState") +another_direction_walk_state = NodePath("../WalkRightState") +fall_state = NodePath("../FallLeftState") +cultist = NodePath("../..") + +[node name="WalkRightState" parent="CultistStateMachine" unique_id=1671686910 node_paths=PackedStringArray("chase_state", "another_direction_walk_state", "fall_state", "cultist") instance=ExtResource("5_tu2pi")] +script = ExtResource("12_lh753") +chase_state = NodePath("../ChaseRightState") +another_direction_walk_state = NodePath("../WalkLeftState") +fall_state = NodePath("../FallRightState") +cultist = NodePath("../..") + +[node name="ChaseLeftState" parent="CultistStateMachine" unique_id=209480830 node_paths=PackedStringArray("look_around_state", "fall_state", "cultist") instance=ExtResource("5_tu2pi")] +script = ExtResource("13_42ivi") +look_around_state = NodePath("../LookAroundState") +fall_state = NodePath("../FallState") cultist = NodePath("../..") -[node name="MoveLeftState" parent="CultistStateMachine" unique_id=276543931 node_paths=PackedStringArray("another_direction_move_state", "cultist") instance=ExtResource("5_tu2pi")] -script = ExtResource("11_lh753") -another_direction_move_state = NodePath("../MoveRightState") -cultist = NodePath("../..") - -[node name="MoveRightState" parent="CultistStateMachine" unique_id=1671686910 node_paths=PackedStringArray("another_direction_move_state", "cultist") instance=ExtResource("5_tu2pi")] -script = ExtResource("12_lh753") -another_direction_move_state = NodePath("../MoveLeftState") +[node name="ChaseRightState" parent="CultistStateMachine" unique_id=383038915 node_paths=PackedStringArray("look_around_state", "fall_state", "cultist") instance=ExtResource("5_tu2pi")] +script = ExtResource("14_cqp7f") +look_around_state = NodePath("../LookAroundState") +fall_state = NodePath("../FallState") cultist = NodePath("../..") [connection signal="animation_finished" from="CultistSprite" to="." method="_on_animation_finished"] diff --git a/game/characters/enemies/state_machine/move_left_state.gd b/game/characters/enemies/state_machine/chase_left_state.gd similarity index 76% rename from game/characters/enemies/state_machine/move_left_state.gd rename to game/characters/enemies/state_machine/chase_left_state.gd index d1f2cf7..e707c29 100644 --- a/game/characters/enemies/state_machine/move_left_state.gd +++ b/game/characters/enemies/state_machine/chase_left_state.gd @@ -1,7 +1,9 @@ -extends CultistMoveState +extends CultistChaseState func _ready() -> void: + super._ready() + _direction = DIRECTION_LEFT _wall_ray_cast = cultist.left_wall_ray _player_ray_cast = cultist.left_player_distant_ray diff --git a/game/characters/enemies/state_machine/chase_left_state.gd.uid b/game/characters/enemies/state_machine/chase_left_state.gd.uid new file mode 100644 index 0000000..f4874e8 --- /dev/null +++ b/game/characters/enemies/state_machine/chase_left_state.gd.uid @@ -0,0 +1 @@ +uid://cn2lfl4kuxvjk diff --git a/game/characters/enemies/state_machine/chase_right_state.gd b/game/characters/enemies/state_machine/chase_right_state.gd new file mode 100644 index 0000000..7747d3f --- /dev/null +++ b/game/characters/enemies/state_machine/chase_right_state.gd @@ -0,0 +1,9 @@ +extends CultistChaseState + + +func _ready() -> void: + super._ready() + + _direction = DIRECTION_RIGHT + _wall_ray_cast = cultist.right_wall_ray + _player_ray_cast = cultist.right_player_distant_ray diff --git a/game/characters/enemies/state_machine/chase_right_state.gd.uid b/game/characters/enemies/state_machine/chase_right_state.gd.uid new file mode 100644 index 0000000..1b47ec1 --- /dev/null +++ b/game/characters/enemies/state_machine/chase_right_state.gd.uid @@ -0,0 +1 @@ +uid://3kl84tu1vwiv diff --git a/game/characters/enemies/state_machine/chase_state.gd b/game/characters/enemies/state_machine/chase_state.gd new file mode 100644 index 0000000..77bf44d --- /dev/null +++ b/game/characters/enemies/state_machine/chase_state.gd @@ -0,0 +1,19 @@ +class_name CultistChaseState +extends CultistMoveState + + +@export var look_around_state: CultistState + + +func physics_process(delta: float) -> void: + if not cultist.is_on_floor(): + switch_state.emit(fall_state) + else: + var player := _get_colliding_player(_player_ray_cast) + if player != null: + cultist.target_x = player.position.x + + if is_equal_approx(cultist.position.x, cultist.target_x): + switch_state.emit(look_around_state) + else: + cultist.update_x_velocity(_direction, cultist.MAX_CHASE_SPEED, delta) diff --git a/game/characters/enemies/state_machine/chase_state.gd.uid b/game/characters/enemies/state_machine/chase_state.gd.uid new file mode 100644 index 0000000..ec9b708 --- /dev/null +++ b/game/characters/enemies/state_machine/chase_state.gd.uid @@ -0,0 +1 @@ +uid://beu06w0gntfay diff --git a/game/characters/enemies/state_machine/cultist_state.gd b/game/characters/enemies/state_machine/cultist_state.gd index d9ff78e..ff6654c 100644 --- a/game/characters/enemies/state_machine/cultist_state.gd +++ b/game/characters/enemies/state_machine/cultist_state.gd @@ -5,5 +5,30 @@ extends AbstractState @export var cultist: AbstractCultist + +func _ready() -> void: + if not cultist.is_node_ready(): + await cultist.ready + + func _set_ray_cast_enable(ray_cast: RayCast2D, enabled: bool) -> void: ray_cast.process_mode = Node.PROCESS_MODE_INHERIT if enabled else Node.PROCESS_MODE_DISABLED + + +func _get_colliding_player(ray_cast: RayCast2D) -> Player: + ray_cast.force_raycast_update() + + if ray_cast.is_colliding(): + var collider := ray_cast.get_collider() + if collider is Player: + return collider + return null + + +func _chase_if_player_in_ray_cast(ray_cast: RayCast2D, chase_state: CultistState) -> bool: + var player := _get_colliding_player(ray_cast) + if player != null: + cultist.target_x = player.position.x + switch_state.emit(chase_state) + return true + return false diff --git a/game/characters/enemies/state_machine/look_around_state.gd b/game/characters/enemies/state_machine/look_around_state.gd index 87e4ae2..5482d4c 100644 --- a/game/characters/enemies/state_machine/look_around_state.gd +++ b/game/characters/enemies/state_machine/look_around_state.gd @@ -2,6 +2,8 @@ extends CultistState @export var fall_state: CultistState +@export var chase_left_state: CultistState +@export var chase_right_state: CultistState func enter() -> void: @@ -14,6 +16,13 @@ func enter() -> void: func physics_process(_delta: float) -> void: if not cultist.is_on_floor(): switch_state.emit(fall_state) + return + + if _chase_if_player_in_ray_cast(cultist.left_player_close_ray, chase_left_state): + return + + if _chase_if_player_in_ray_cast(cultist.right_player_close_ray, chase_right_state): + return func exit() -> void: diff --git a/game/characters/enemies/state_machine/move_state.gd b/game/characters/enemies/state_machine/move_state.gd index 3d942b0..771d7ab 100644 --- a/game/characters/enemies/state_machine/move_state.gd +++ b/game/characters/enemies/state_machine/move_state.gd @@ -3,18 +3,16 @@ class_name CultistMoveState extends CultistState -const MAX_WALK_SPEED = 85 - const DIRECTION_LEFT = -1 const DIRECTION_RIGHT = 1 @export var fall_state: CultistState -@export var chase_state: CultistState -@export var another_direction_move_state: CultistState +@warning_ignore("unused_private_class_variable") var _direction := 0 +@warning_ignore("unused_private_class_variable") var _wall_ray_cast : RayCast2D var _player_ray_cast : RayCast2D @@ -25,27 +23,3 @@ func enter() -> void: func exit() -> void: _set_ray_cast_enable(_player_ray_cast, false) - - -func physics_process(delta: float) -> void: - if not cultist.is_on_floor(): - switch_state.emit(fall_state) - else: - var player := _get_colliding_player(_player_ray_cast) - if player != null: - cultist.target_x = player.position.x - switch_state.emit(chase_state) - elif _wall_ray_cast.is_colliding(): - switch_state.emit(another_direction_move_state) - else: - cultist.update_x_velocity(_direction, MAX_WALK_SPEED, delta) - - -func _get_colliding_player(ray_cast: RayCast2D) -> Player: - ray_cast.force_raycast_update() - - if ray_cast.is_colliding(): - var collider := ray_cast.get_collider() - if collider is Player: - return collider - return null diff --git a/game/characters/enemies/state_machine/move_state.gd.uid b/game/characters/enemies/state_machine/move_state.gd.uid index 4b257a5..f54117d 100644 --- a/game/characters/enemies/state_machine/move_state.gd.uid +++ b/game/characters/enemies/state_machine/move_state.gd.uid @@ -1 +1 @@ -uid://lplif1gcjbai +uid://cw5hhiv8uih7d diff --git a/game/characters/enemies/state_machine/walk_left_state.gd b/game/characters/enemies/state_machine/walk_left_state.gd new file mode 100644 index 0000000..528b051 --- /dev/null +++ b/game/characters/enemies/state_machine/walk_left_state.gd @@ -0,0 +1,11 @@ +extends CultistWalkState + + +func _ready() -> void: + super._ready() + + print(cultist.left_player_distant_ray) + + _direction = DIRECTION_LEFT + _wall_ray_cast = cultist.left_wall_ray + _player_ray_cast = cultist.left_player_distant_ray diff --git a/game/characters/enemies/state_machine/move_left_state.gd.uid b/game/characters/enemies/state_machine/walk_left_state.gd.uid similarity index 100% rename from game/characters/enemies/state_machine/move_left_state.gd.uid rename to game/characters/enemies/state_machine/walk_left_state.gd.uid diff --git a/game/characters/enemies/state_machine/move_right_state.gd b/game/characters/enemies/state_machine/walk_right_state.gd similarity index 77% rename from game/characters/enemies/state_machine/move_right_state.gd rename to game/characters/enemies/state_machine/walk_right_state.gd index 5dd5225..ea583c1 100644 --- a/game/characters/enemies/state_machine/move_right_state.gd +++ b/game/characters/enemies/state_machine/walk_right_state.gd @@ -1,7 +1,9 @@ -extends CultistMoveState +extends CultistWalkState func _ready() -> void: + super._ready() + _direction = DIRECTION_RIGHT _wall_ray_cast = cultist.right_wall_ray _player_ray_cast = cultist.right_player_distant_ray diff --git a/game/characters/enemies/state_machine/move_right_state.gd.uid b/game/characters/enemies/state_machine/walk_right_state.gd.uid similarity index 100% rename from game/characters/enemies/state_machine/move_right_state.gd.uid rename to game/characters/enemies/state_machine/walk_right_state.gd.uid diff --git a/game/characters/enemies/state_machine/walk_state.gd b/game/characters/enemies/state_machine/walk_state.gd new file mode 100644 index 0000000..c66a872 --- /dev/null +++ b/game/characters/enemies/state_machine/walk_state.gd @@ -0,0 +1,20 @@ +@abstract +class_name CultistWalkState +extends CultistMoveState + + +@export var chase_state: CultistState +@export var another_direction_walk_state: CultistState + + +func physics_process(delta: float) -> void: + if not cultist.is_on_floor(): + switch_state.emit(fall_state) + else: + if not _chase_if_player_in_ray_cast(_player_ray_cast, chase_state): + if _wall_ray_cast.is_colliding(): + var stream := SoundManager.sfx_stream_player_lost + SoundManager.play_sfx_stream(stream, cultist.global_position) + switch_state.emit(another_direction_walk_state) + else: + cultist.update_x_velocity(_direction, cultist.MAX_WALK_SPEED, delta) diff --git a/game/characters/enemies/state_machine/walk_state.gd.uid b/game/characters/enemies/state_machine/walk_state.gd.uid new file mode 100644 index 0000000..4b257a5 --- /dev/null +++ b/game/characters/enemies/state_machine/walk_state.gd.uid @@ -0,0 +1 @@ +uid://lplif1gcjbai