knockback; base enemy scene; police van

This commit is contained in:
Michael Campbell 2026-03-18 16:14:34 -04:00
parent 370eb54163
commit d0bfe8d1be
13 changed files with 218 additions and 111 deletions

23
enemies/base_enemy.tscn Normal file
View file

@ -0,0 +1,23 @@
[gd_scene format=3 uid="uid://oyqyvj5xo5mf"]
[ext_resource type="Script" uid="uid://c6xr2j0g1ep7j" path="res://enemies/enemy.gd" id="1_j7qyq"]
[sub_resource type="Curve" id="Curve_spw8y"]
_limits = [1.0, 20.0, -1.0, 1.0]
_data = [Vector2(-1, 20), 0.0, 0.0, 0, 0, Vector2(0.20895529, 4.7216473), -18.980904, 0.0, 0, 0, Vector2(1, 1), 0.0, 0.0, 0, 0]
point_count = 3
[node name="Enemy" type="CharacterBody3D" unique_id=206023291]
collision_layer = 8
collision_mask = 15
script = ExtResource("1_j7qyq")
dot_curve = SubResource("Curve_spw8y")
[node name="NavAgent" type="NavigationAgent3D" parent="." unique_id=774393024]
unique_name_in_owner = true
[node name="Hurtbox" type="Area3D" parent="." unique_id=688205599]
collision_layer = 0
collision_mask = 2
[connection signal="body_entered" from="Hurtbox" to="." method="_on_hurtbox_body_entered"]

64
enemies/enemy.gd Normal file
View file

@ -0,0 +1,64 @@
class_name PoliceCar
extends CharacterBody3D
const FRAME_IDXS := 10
@export var dot_curve: Curve
@export var max_speed := 8.
@export var health := 10.
@export var knockback_mul := 1.
var frame_idx := 0
var frame_count := 0
var knockback := Vector3.ZERO
func exp_lerp(a: Variant, b: Variant, decay: float, dt: float) -> Variant:
return lerp(a, b, 1 - exp(-decay * dt))
func _ready() -> void:
frame_idx = randi() % FRAME_IDXS
func _update_nav_agent() -> void:
%NavAgent.target_position = Player.instance.global_position
func _process_movement(delta: float) -> void:
var dir := global_position.direction_to(%NavAgent.get_next_path_position())
dir.y = 0
var dot := dir.dot(velocity.normalized())
var dot_power := dot_curve.sample(dot)
velocity += dir * 8. * delta * dot_power
velocity = velocity.limit_length(max_speed)
func _process(delta: float) -> void:
frame_count = (frame_count + 1) % FRAME_IDXS
if frame_count == frame_idx:
_update_nav_agent()
if knockback.length() < 0.1:
_process_movement(delta)
rotation.y = Vector2(velocity.x, -velocity.z).angle()
position.y = 0.01
else:
velocity = knockback
knockback = exp_lerp(knockback, Vector3.ZERO, 15., delta)
move_and_slide()
func hit(proj: Node3D, damage: float) -> bool:
health -= damage
if health <= 0:
queue_free()
else:
if proj is PlayerProjectile:
knockback = proj.velocity * 2. * knockback_mul * proj.knockback_mul
return true
func _on_hurtbox_body_entered(body: Node3D) -> void:
if body is Player:
body.damage(self)

View file

@ -1,44 +0,0 @@
class_name PoliceCar
extends CharacterBody3D
const FRAME_IDXS := 10
@export var dot_curve: Curve
var health := 10.
var frame_idx := 0
func _ready() -> void:
frame_idx = randi() % FRAME_IDXS
func _update_nav_agent() -> void:
%NavAgent.target_position = Player.instance.global_position
var frame_count := 0
func _process(delta: float) -> void:
frame_count = (frame_count + 1) % FRAME_IDXS
if frame_count == frame_idx:
_update_nav_agent()
var dir := global_position.direction_to(%NavAgent.get_next_path_position())
dir.y = 0
var dot_power := dot_curve.sample(dir.dot(velocity.normalized()))
velocity += dir * 8. * delta * dot_power
velocity = velocity.limit_length(8.)
move_and_slide()
rotation.y = Vector2(velocity.x, -velocity.z).angle()
position.y = 0.01
func hit(_proj: PlayerProjectile, damage: float) -> bool:
health -= damage
if health <= 0:
queue_free()
return true
func _on_hurtbox_body_entered(body: Node3D) -> void:
if body is Player:
body.damage(self)

View file

@ -1,90 +1,74 @@
[gd_scene format=3 uid="uid://dusfu1hidkmsk"]
[ext_resource type="Script" uid="uid://c6xr2j0g1ep7j" path="res://enemies/police_car/police_car.gd" id="1_spw8y"]
[ext_resource type="PackedScene" uid="uid://oyqyvj5xo5mf" path="res://enemies/base_enemy.tscn" id="1_s5uvd"]
[ext_resource type="Script" uid="uid://c14x24qxx1wc3" path="res://enemies/police_car/weak_point.gd" id="2_8ru0n"]
[sub_resource type="Curve" id="Curve_spw8y"]
_limits = [1.0, 20.0, -1.0, 1.0]
_data = [Vector2(-1, 20), 0.0, 0.0, 0, 0, Vector2(0.20895529, 4.7216473), -18.980904, 0.0, 0, 0, Vector2(1, 1), 0.0, 0.0, 0, 0]
point_count = 3
[sub_resource type="BoxShape3D" id="BoxShape3D_8ru0n"]
size = Vector3(1.7734375, 0.5839844, 1.1367188)
[sub_resource type="BoxMesh" id="BoxMesh_2kvnc"]
[sub_resource type="BoxMesh" id="BoxMesh_s5uvd"]
size = Vector3(1, 0.25, 0.5)
[sub_resource type="BoxShape3D" id="BoxShape3D_spw8y"]
size = Vector3(1, 0.25, 0.5)
[sub_resource type="BoxMesh" id="BoxMesh_spw8y"]
[sub_resource type="BoxMesh" id="BoxMesh_8ru0n"]
size = Vector3(0.1, 0.05, 0.2)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_8364l"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_8t57f"]
albedo_color = Color(1, 0.32, 0.32, 1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_6u34r"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_s7vp5"]
albedo_color = Color(0.26, 0.45733315, 1, 1)
[sub_resource type="CylinderMesh" id="CylinderMesh_e8ulu"]
[sub_resource type="CylinderMesh" id="CylinderMesh_tdg6c"]
top_radius = 0.1
bottom_radius = 0.1
height = 0.5
[sub_resource type="BoxShape3D" id="BoxShape3D_8364l"]
size = Vector3(1.7734375, 0.5839844, 1.1367188)
[sub_resource type="BoxShape3D" id="BoxShape3D_s5uvd"]
size = Vector3(1, 0.25, 0.5)
[sub_resource type="BoxShape3D" id="BoxShape3D_8t57f"]
size = Vector3(0.6993408, 1, 0.88671875)
[node name="PoliceCar" type="CharacterBody3D" unique_id=206023291]
collision_layer = 8
collision_mask = 15
script = ExtResource("1_spw8y")
dot_curve = SubResource("Curve_spw8y")
[node name="PoliceCar" unique_id=206023291 instance=ExtResource("1_s5uvd")]
[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=423323850]
[node name="CollisionShape3D" type="CollisionShape3D" parent="Hurtbox" parent_id_path=PackedInt32Array(688205599) index="0" unique_id=1939097710]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, -0.122092836, 0.34972915, -0.0012522953)
mesh = SubResource("BoxMesh_2kvnc")
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=637101729]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, -0.122092836, 0.34972915, -0.0012522953)
shape = SubResource("BoxShape3D_spw8y")
[node name="MeshInstance3D4" type="MeshInstance3D" parent="." unique_id=1230197866]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0.59585166, 0.65602696, 0.24429089)
mesh = SubResource("BoxMesh_spw8y")
surface_material_override/0 = SubResource("StandardMaterial3D_8364l")
[node name="MeshInstance3D5" type="MeshInstance3D" parent="." unique_id=100028974]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0.60364604, 0.65602696, -0.23176795)
mesh = SubResource("BoxMesh_spw8y")
surface_material_override/0 = SubResource("StandardMaterial3D_6u34r")
[node name="MeshInstance3D2" type="MeshInstance3D" parent="." unique_id=425081066]
transform = Transform3D(2, 0, 0, 0, -8.742278e-08, -2, 0, 2, -8.742278e-08, -0.8505253, -0.079150766, -0.0012522853)
mesh = SubResource("CylinderMesh_e8ulu")
[node name="MeshInstance3D3" type="MeshInstance3D" parent="." unique_id=1992142361]
transform = Transform3D(2, 0, 0, 0, -8.742278e-08, -2, 0, 2, -8.742278e-08, 0.62777025, -0.079150766, -0.0012522853)
mesh = SubResource("CylinderMesh_e8ulu")
[node name="NavAgent" type="NavigationAgent3D" parent="." unique_id=774393024]
unique_name_in_owner = true
[node name="Hurtbox" type="Area3D" parent="." unique_id=688205599]
collision_layer = 0
collision_mask = 2
[node name="CollisionShape3D" type="CollisionShape3D" parent="Hurtbox" unique_id=192758567]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, -0.122092836, 0.34972915, -0.0012522953)
shape = SubResource("BoxShape3D_8364l")
shape = SubResource("BoxShape3D_8ru0n")
debug_color = Color(0.9913104, 0, 0.27320355, 0.41960785)
[node name="WeakPoint" type="Area3D" parent="." unique_id=1032610086]
[node name="Meshes" type="Node3D" parent="." index="2" unique_id=1144793877]
[node name="MeshInstance3D6" type="MeshInstance3D" parent="Meshes" index="0" unique_id=1731567677]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, -0.122092836, 0.34972915, -0.0012522953)
mesh = SubResource("BoxMesh_s5uvd")
[node name="MeshInstance3D7" type="MeshInstance3D" parent="Meshes" index="1" unique_id=761614106]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0.59585166, 0.65602696, 0.24429089)
mesh = SubResource("BoxMesh_8ru0n")
surface_material_override/0 = SubResource("StandardMaterial3D_8t57f")
[node name="MeshInstance3D8" type="MeshInstance3D" parent="Meshes" index="2" unique_id=765553113]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0.60364604, 0.65602696, -0.23176795)
mesh = SubResource("BoxMesh_8ru0n")
surface_material_override/0 = SubResource("StandardMaterial3D_s7vp5")
[node name="MeshInstance3D9" type="MeshInstance3D" parent="Meshes" index="3" unique_id=1082889749]
transform = Transform3D(2, 0, 0, 0, -8.742278e-08, -2, 0, 2, -8.742278e-08, -0.8505253, -0.079150766, -0.0012522853)
mesh = SubResource("CylinderMesh_tdg6c")
[node name="MeshInstance3D10" type="MeshInstance3D" parent="Meshes" index="4" unique_id=609558882]
transform = Transform3D(2, 0, 0, 0, -8.742278e-08, -2, 0, 2, -8.742278e-08, 0.62777025, -0.079150766, -0.0012522853)
mesh = SubResource("CylinderMesh_tdg6c")
[node name="CollisionShape3D" type="CollisionShape3D" parent="." index="3" unique_id=1488758257]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, -0.122092836, 0.34972915, -0.0012522953)
shape = SubResource("BoxShape3D_s5uvd")
[node name="WeakPoint" type="Area3D" parent="." index="4" unique_id=403044177]
collision_layer = 8
collision_mask = 0
script = ExtResource("2_8ru0n")
[node name="CollisionShape3D" type="CollisionShape3D" parent="WeakPoint" unique_id=950314743]
[node name="CollisionShape3D" type="CollisionShape3D" parent="WeakPoint" index="0" unique_id=1979015401]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.9923661, 0.27572453, -0.0006608963)
shape = SubResource("BoxShape3D_s5uvd")
[connection signal="body_entered" from="Hurtbox" to="." method="_on_hurtbox_body_entered"]
shape = SubResource("BoxShape3D_8t57f")

View file

@ -6,8 +6,11 @@ func _ready() -> void:
assert(get_parent() is PoliceCar)
parent = get_parent()
func hit(projectile: PlayerProjectile, _damage: float) -> bool:
if projectile == null: return false
func hit(proj: Node3D, _damage: float) -> bool:
if proj == null: return false
if proj is not PlayerProjectile: return false
var projectile := proj as PlayerProjectile
if not projectile.can_hit_weak_points: return false
var angle := projectile.velocity.angle_to(-parent.velocity)

View file

@ -0,0 +1,71 @@
[gd_scene format=3 uid="uid://b7oinpdwh22ux"]
[ext_resource type="PackedScene" uid="uid://oyqyvj5xo5mf" path="res://enemies/base_enemy.tscn" id="1_7uqh4"]
[sub_resource type="BoxShape3D" id="BoxShape3D_6pftu"]
size = Vector3(4.9189453, 2.0439758, 1.8857422)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_o57g8"]
albedo_color = Color(0.16999999, 0, 0.6, 1)
[sub_resource type="BoxMesh" id="BoxMesh_6pftu"]
size = Vector3(1, 0.25, 0.5)
[sub_resource type="BoxMesh" id="BoxMesh_o57g8"]
size = Vector3(0.1, 0.05, 0.2)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_7ka6v"]
albedo_color = Color(1, 0.32, 0.32, 1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_k34o4"]
albedo_color = Color(0.26, 0.45733315, 1, 1)
[sub_resource type="CylinderMesh" id="CylinderMesh_whvud"]
top_radius = 0.1
bottom_radius = 0.1
height = 0.5
[sub_resource type="BoxShape3D" id="BoxShape3D_7ka6v"]
size = Vector3(2.9560547, 0.7812805, 1.4785156)
[node name="PoliceVan" unique_id=206023291 instance=ExtResource("1_7uqh4")]
max_speed = 10.0
health = 12.0
knockback_mul = 2.0
[node name="CollisionShape3D" type="CollisionShape3D" parent="Hurtbox" parent_id_path=PackedInt32Array(688205599) index="0" unique_id=1007044077]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.12426758, 0.57774353, 0)
shape = SubResource("BoxShape3D_6pftu")
debug_color = Color(0.99790066, 0, 0.16589326, 0.41960785)
[node name="Meshes" type="Node3D" parent="." index="2" unique_id=1084825396]
transform = Transform3D(1.4942238, 0, 0, 0, 1.4942238, 0, 0, 0, 1.4942238, 0, 0, 0)
[node name="MeshInstance3D6" type="MeshInstance3D" parent="Meshes" index="0" unique_id=898884562]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, -0.122092836, 0.34972915, -0.0012522953)
material_override = SubResource("StandardMaterial3D_o57g8")
mesh = SubResource("BoxMesh_6pftu")
[node name="MeshInstance3D7" type="MeshInstance3D" parent="Meshes" index="1" unique_id=419090161]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0.59585166, 0.65602696, 0.24429089)
mesh = SubResource("BoxMesh_o57g8")
surface_material_override/0 = SubResource("StandardMaterial3D_7ka6v")
[node name="MeshInstance3D8" type="MeshInstance3D" parent="Meshes" index="2" unique_id=1520738519]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0.60364604, 0.65602696, -0.23176795)
mesh = SubResource("BoxMesh_o57g8")
surface_material_override/0 = SubResource("StandardMaterial3D_k34o4")
[node name="MeshInstance3D9" type="MeshInstance3D" parent="Meshes" index="3" unique_id=1406960495]
transform = Transform3D(2, 0, 0, 0, -8.742278e-08, -2, 0, 2, -8.742278e-08, -0.8505253, -0.079150766, -0.0012522853)
material_override = SubResource("StandardMaterial3D_o57g8")
mesh = SubResource("CylinderMesh_whvud")
[node name="MeshInstance3D10" type="MeshInstance3D" parent="Meshes" index="4" unique_id=883792586]
transform = Transform3D(2, 0, 0, 0, -8.742278e-08, -2, 0, 2, -8.742278e-08, 0.62777025, -0.079150766, -0.0012522853)
material_override = SubResource("StandardMaterial3D_o57g8")
mesh = SubResource("CylinderMesh_whvud")
[node name="CollisionShape3D" type="CollisionShape3D" parent="." index="3" unique_id=829093714]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.19335938, 0.5453949, 0)
shape = SubResource("BoxShape3D_7ka6v")