Enemies & very basic enemy AI
This commit is contained in:
parent
020b995c94
commit
6bc0e995db
4 changed files with 206 additions and 2 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
[gd_scene load_steps=11 format=3 uid="uid://bauklhpieuivd"]
|
[gd_scene load_steps=12 format=3 uid="uid://bauklhpieuivd"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://d0qswyhwbhdua" path="res://scripts/game.gd" id="1_u5sy4"]
|
[ext_resource type="Script" uid="uid://d0qswyhwbhdua" path="res://scripts/game.gd" id="1_u5sy4"]
|
||||||
[ext_resource type="Texture2D" uid="uid://dtwo7g0ipc4k" path="res://textures/ship_1.png" id="1_uwrxv"]
|
[ext_resource type="Texture2D" uid="uid://dtwo7g0ipc4k" path="res://textures/ship_1.png" id="1_uwrxv"]
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
[ext_resource type="AudioStream" uid="uid://5tr30e1tmdp6" path="res://sounds/collision.mp3" id="2_lbhrr"]
|
[ext_resource type="AudioStream" uid="uid://5tr30e1tmdp6" path="res://sounds/collision.mp3" id="2_lbhrr"]
|
||||||
[ext_resource type="AudioStream" uid="uid://b6tyof2j3ytbv" path="res://sounds/concrete_halls.mp3" id="3_0tnpc"]
|
[ext_resource type="AudioStream" uid="uid://b6tyof2j3ytbv" path="res://sounds/concrete_halls.mp3" id="3_0tnpc"]
|
||||||
[ext_resource type="AudioStream" uid="uid://b1ung55xg31l3" path="res://sounds/boost_finish.mp3" id="3_p57ef"]
|
[ext_resource type="AudioStream" uid="uid://b1ung55xg31l3" path="res://sounds/boost_finish.mp3" id="3_p57ef"]
|
||||||
|
[ext_resource type="Script" uid="uid://8d4jhy3fo32b" path="res://scripts/enemy.gd" id="9_0tnpc"]
|
||||||
|
|
||||||
[sub_resource type="CircleShape2D" id="CircleShape2D_uwrxv"]
|
[sub_resource type="CircleShape2D" id="CircleShape2D_uwrxv"]
|
||||||
radius = 16.0
|
radius = 16.0
|
||||||
|
|
@ -59,6 +60,36 @@ rotation_smoothing_speed = 15.0
|
||||||
shape = SubResource("CircleShape2D_lnu2h")
|
shape = SubResource("CircleShape2D_lnu2h")
|
||||||
debug_color = Color(0.9686392, 0, 0.4696517, 0.41960785)
|
debug_color = Color(0.9686392, 0, 0.4696517, 0.41960785)
|
||||||
|
|
||||||
|
[node name="Enemy" type="RigidBody2D" parent="."]
|
||||||
|
position = Vector2(0, -418)
|
||||||
|
linear_damp = 6.247
|
||||||
|
script = ExtResource("9_0tnpc")
|
||||||
|
|
||||||
|
[node name="Boost" type="AudioStreamPlayer" parent="Enemy"]
|
||||||
|
stream = ExtResource("2_iywne")
|
||||||
|
|
||||||
|
[node name="BoostFinish" type="AudioStreamPlayer" parent="Enemy"]
|
||||||
|
stream = ExtResource("3_p57ef")
|
||||||
|
volume_db = -8.0
|
||||||
|
|
||||||
|
[node name="Collision" type="AudioStreamPlayer" parent="Enemy"]
|
||||||
|
stream = ExtResource("2_lbhrr")
|
||||||
|
|
||||||
|
[node name="Sprite" type="Sprite2D" parent="Enemy"]
|
||||||
|
texture = ExtResource("1_uwrxv")
|
||||||
|
|
||||||
|
[node name="CollisionShape" type="CollisionShape2D" parent="Enemy"]
|
||||||
|
shape = SubResource("CircleShape2D_uwrxv")
|
||||||
|
|
||||||
|
[node name="Hitbox" type="Area2D" parent="Enemy"]
|
||||||
|
|
||||||
|
[node name="CollisionShape" type="CollisionShape2D" parent="Enemy/Hitbox"]
|
||||||
|
shape = SubResource("CircleShape2D_lnu2h")
|
||||||
|
debug_color = Color(0.9686392, 0, 0.4696517, 0.41960785)
|
||||||
|
|
||||||
|
[node name="SightCast" type="RayCast2D" parent="Enemy"]
|
||||||
|
target_position = Vector2(0, -256)
|
||||||
|
|
||||||
[node name="Unloadables" type="Node2D" parent="."]
|
[node name="Unloadables" type="Node2D" parent="."]
|
||||||
|
|
||||||
[node name="UI" type="CanvasLayer" parent="."]
|
[node name="UI" type="CanvasLayer" parent="."]
|
||||||
|
|
@ -89,3 +120,4 @@ grow_vertical = 2
|
||||||
text = "DIST: 2048"
|
text = "DIST: 2048"
|
||||||
|
|
||||||
[connection signal="body_shape_entered" from="Player/Hitbox" to="Player" method="_on_hitbox_body_shape_entered"]
|
[connection signal="body_shape_entered" from="Player/Hitbox" to="Player" method="_on_hitbox_body_shape_entered"]
|
||||||
|
[connection signal="body_shape_entered" from="Enemy/Hitbox" to="Enemy" method="_on_hitbox_body_shape_entered"]
|
||||||
|
|
|
||||||
171
scripts/enemy.gd
Normal file
171
scripts/enemy.gd
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
extends RigidBody2D
|
||||||
|
|
||||||
|
var health = 1000
|
||||||
|
var boost = 100
|
||||||
|
var speed = 480
|
||||||
|
var time_since_last_collision = 1
|
||||||
|
var boosting = false
|
||||||
|
|
||||||
|
var axis = 0
|
||||||
|
var movement_axis = -1
|
||||||
|
|
||||||
|
var AI_MODE_ATTACK = 1
|
||||||
|
|
||||||
|
var ai_mode = AI_MODE_ATTACK
|
||||||
|
|
||||||
|
var AI_STATE_EVADE_OBJECT = 1
|
||||||
|
var AI_STATE_TRACK_ENEMY = 2
|
||||||
|
var AI_STATE_STATIONARY_ENEMY = 3
|
||||||
|
|
||||||
|
var object_to_evade = null
|
||||||
|
var last_ai_state_before_evasion = AI_STATE_TRACK_ENEMY
|
||||||
|
|
||||||
|
var ai_state = AI_STATE_TRACK_ENEMY
|
||||||
|
var target_rotation = 0
|
||||||
|
var target_rotation_speed = 1
|
||||||
|
|
||||||
|
var ai_tick = 0.1
|
||||||
|
@onready var player = get_parent().get_node("Player")
|
||||||
|
|
||||||
|
func cast(angle):
|
||||||
|
$SightCast.rotation_degrees = angle
|
||||||
|
$SightCast.force_raycast_update()
|
||||||
|
|
||||||
|
return $SightCast.get_collider()
|
||||||
|
|
||||||
|
func check_front():
|
||||||
|
var front_cast = cast(0)
|
||||||
|
if !front_cast:
|
||||||
|
$SightCast.position.x = -20
|
||||||
|
front_cast = cast(0)
|
||||||
|
|
||||||
|
if !front_cast:
|
||||||
|
$SightCast.position.x = 20
|
||||||
|
front_cast = cast(0)
|
||||||
|
|
||||||
|
$SightCast.position.x = 0
|
||||||
|
|
||||||
|
if front_cast:
|
||||||
|
$SightCast.position.x = -20
|
||||||
|
$SightCast.force_raycast_update()
|
||||||
|
var cast_left = $SightCast.get_collision_point()
|
||||||
|
|
||||||
|
$SightCast.position.x = 20
|
||||||
|
$SightCast.force_raycast_update()
|
||||||
|
var cast_right = $SightCast.get_collision_point()
|
||||||
|
|
||||||
|
$SightCast.position.x = 0
|
||||||
|
|
||||||
|
if (cast_left - $SightCast.position).length() > (cast_right - $SightCast.position).length(): return -1
|
||||||
|
else: return 1
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
ai_tick -= delta
|
||||||
|
|
||||||
|
if boosting:
|
||||||
|
if Input.is_action_pressed("boost"):
|
||||||
|
boost -= delta * 40
|
||||||
|
|
||||||
|
if boost <= 0:
|
||||||
|
boost = 0
|
||||||
|
boosting = false
|
||||||
|
$BoostFinish.play()
|
||||||
|
else:
|
||||||
|
boosting = false
|
||||||
|
$BoostFinish.play()
|
||||||
|
else:
|
||||||
|
boost += delta * 25
|
||||||
|
if boost > 100: boost = 100
|
||||||
|
|
||||||
|
$Boost.stop()
|
||||||
|
if Input.is_action_just_pressed("boost") and (boost > 33):
|
||||||
|
boosting = true
|
||||||
|
$Boost.play()
|
||||||
|
|
||||||
|
if time_since_last_collision <= 1:
|
||||||
|
time_since_last_collision += delta
|
||||||
|
|
||||||
|
if ai_tick < 0:
|
||||||
|
ai_tick = 0.1
|
||||||
|
|
||||||
|
movement_axis = -1
|
||||||
|
|
||||||
|
if ai_state == AI_STATE_TRACK_ENEMY:
|
||||||
|
target_rotation = global_position.direction_to(player.position).angle() + deg_to_rad(270)
|
||||||
|
|
||||||
|
if ai_state == AI_STATE_STATIONARY_ENEMY:
|
||||||
|
target_rotation = global_position.direction_to(player.position).angle() + deg_to_rad(270)
|
||||||
|
movement_axis = 0
|
||||||
|
|
||||||
|
var front_cast = cast(0)
|
||||||
|
if !front_cast:
|
||||||
|
$SightCast.position.x = -20
|
||||||
|
front_cast = cast(0)
|
||||||
|
|
||||||
|
if !front_cast:
|
||||||
|
$SightCast.position.x = 20
|
||||||
|
front_cast = cast(0)
|
||||||
|
|
||||||
|
$SightCast.position.x = 0
|
||||||
|
|
||||||
|
if front_cast:
|
||||||
|
var front_cast_distance = ($SightCast.get_collision_point() - position).length()
|
||||||
|
|
||||||
|
if (front_cast_distance < 160 * (speed / 300)) and (front_cast_distance < (player.position - position).length()):
|
||||||
|
if ai_state != AI_STATE_EVADE_OBJECT: last_ai_state_before_evasion = ai_state
|
||||||
|
|
||||||
|
ai_state = AI_STATE_EVADE_OBJECT
|
||||||
|
target_rotation += deg_to_rad(45) * check_front()
|
||||||
|
|
||||||
|
object_to_evade = front_cast
|
||||||
|
|
||||||
|
target_rotation_speed = 1
|
||||||
|
|
||||||
|
if ai_state == AI_STATE_EVADE_OBJECT:
|
||||||
|
if not front_cast:
|
||||||
|
ai_state = last_ai_state_before_evasion
|
||||||
|
else:
|
||||||
|
var front_cast_distance = ($SightCast.get_collision_point() - position).length()
|
||||||
|
if front_cast_distance > 160 * (speed / 300):
|
||||||
|
ai_state = last_ai_state_before_evasion
|
||||||
|
|
||||||
|
print(ai_state)
|
||||||
|
|
||||||
|
func _physics_process(delta: float) -> void:
|
||||||
|
axis = 0
|
||||||
|
|
||||||
|
var difference = fmod(target_rotation, deg_to_rad(360)) - fmod(rotation, deg_to_rad(360))
|
||||||
|
var normalized_difference = fmod(difference + deg_to_rad(180), deg_to_rad(360)) - deg_to_rad(180)
|
||||||
|
var target_distance = normalized_difference
|
||||||
|
|
||||||
|
if target_distance < 0:
|
||||||
|
axis = target_rotation_speed
|
||||||
|
if target_distance > 0:
|
||||||
|
axis = -target_rotation_speed
|
||||||
|
|
||||||
|
angular_velocity = deg_to_rad(180 * axis)
|
||||||
|
|
||||||
|
var final_speed = speed
|
||||||
|
|
||||||
|
if boosting:
|
||||||
|
movement_axis = -1
|
||||||
|
final_speed = 1024
|
||||||
|
|
||||||
|
# Slow down on collision and gradually speed up
|
||||||
|
if time_since_last_collision < 0.85: final_speed *= (time_since_last_collision + 0.15)
|
||||||
|
|
||||||
|
var new_velocity = transform.y * movement_axis * final_speed
|
||||||
|
|
||||||
|
if (new_velocity.length() > linear_velocity.length() - 12):
|
||||||
|
linear_velocity = new_velocity
|
||||||
|
|
||||||
|
|
||||||
|
func _on_hitbox_body_shape_entered(body_rid: RID, body: Node2D, body_shape_index: int, local_shape_index: int) -> void:
|
||||||
|
if body.linear_velocity.length() + linear_velocity.length() > 256:
|
||||||
|
health -= 100
|
||||||
|
|
||||||
|
$Collision.play()
|
||||||
|
|
||||||
|
time_since_last_collision = 0
|
||||||
1
scripts/enemy.gd.uid
Normal file
1
scripts/enemy.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://8d4jhy3fo32b
|
||||||
|
|
@ -27,7 +27,7 @@ func _process(delta: float) -> void:
|
||||||
if time_since_last_atmospheric_track > 60:
|
if time_since_last_atmospheric_track > 60:
|
||||||
var tracks = [$BalladOfTheCats, $ConcreteHalls]
|
var tracks = [$BalladOfTheCats, $ConcreteHalls]
|
||||||
|
|
||||||
current_atmospheric_track = tracks[randi_range(0, tracks.size())]
|
current_atmospheric_track = tracks[randi_range(0, tracks.size() - 1)]
|
||||||
current_atmospheric_track.play()
|
current_atmospheric_track.play()
|
||||||
|
|
||||||
chunk_tick_timer -= delta
|
chunk_tick_timer -= delta
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue