This repository has been archived on 2023-10-28. You can view files and clone it, but cannot push or open issues or pull requests.
2DHackAndSlay/Scripts/Enemy/EnemyLook.gd

109 lines
3 KiB
GDScript3
Raw Normal View History

extends Node2D
@export_group("Movement Properties")
@export var speed = 25
@export var turn_speed = 25
@export_group("Vision Properties")
@export var ray : RayCast2D
@export_flags_2d_physics var player_collision_layer := 2
@export var max_view_distance := 50
@export_range(0.0, 360.0) var angle_cone_of_vision : float = 120
@export_range(0, 72) var sweeping_steps : int = 24
@export var debug_vision := false
var sees_player : bool
var player_positions : Array
func _ready():
# Set Raycast into view Direction
ray.target_position = Vector2(max_view_distance, 0)
pass
func view():
# Swipe the Raycast instead of using a lot to get better performance
# Set Raycast to starting position
ray.rotation_degrees = -angle_cone_of_vision / 2
# Create Array to Store Angles of Hits
var hit_angles : Array
# Clear Player Positions Array
player_positions.clear()
for step in sweeping_steps + 1:
# Check Ray
ray.force_raycast_update()
if ray.is_colliding():
# Get Collider
var collider = ray.get_collider()
var collider_class = collider.get_class()
var collision_layer : int
# Get Collision Layer
if collider_class == "TileMap":
collider = collider as TileMap
collision_layer = collider.tile_set.get_physics_layer_collision_layer(0)
else:
collision_layer = collider.get_collision_layer()
# Checking Collision Layer
if collision_layer & player_collision_layer > 0:
hit_angles.append(ray.rotation_degrees)
player_positions.append(to_local(ray.get_collision_point()))
# Rotate Ray
ray.rotation_degrees += angle_cone_of_vision / sweeping_steps
return hit_angles
func rotate_to_player(delta : float):
# Get All Angles at which the Player can be seen
var hit_angles = view()
# If The Player cant be seen, return and do nothing
if hit_angles.size() <= 0:
sees_player = false
return
sees_player = true
# Calculate Average Angle Of Player
var average_angle : float
for angle in hit_angles:
average_angle += angle
average_angle /= hit_angles.size()
# Rotate towards Player, but limit it by rotation speed
self.rotation_degrees += clampf(average_angle, -2 * PI * delta * turn_speed, 2 * PI * delta * turn_speed)
pass
func _physics_process(delta):
rotate_to_player(delta)
pass
func _process(delta):
if debug_vision:
queue_redraw()
pass
func _draw():
# Draw a Debug Arc in case that Debug Vision is enabled
if debug_vision:
# Draw All Ray Positions
var angle = -angle_cone_of_vision / 2
for step in sweeping_steps + 1:
self.draw_line(Vector2(), Vector2(max_view_distance,0).rotated(deg_to_rad(angle)), Color.DARK_RED, 0.5, false)
angle += angle_cone_of_vision / sweeping_steps
# Draw Ray Arc
self.draw_arc(Vector2(), max_view_distance, deg_to_rad(-angle_cone_of_vision / 2), deg_to_rad(angle_cone_of_vision / 2), sweeping_steps + 1, Color.RED, 0.5, false)
# Draw A Circle Around the Player if hes seen
if sees_player:
for pos in player_positions:
self.draw_circle(pos, 4, Color.ORANGE_RED)
pass