charging enemy

This commit is contained in:
Michael Campbell 2026-03-19 01:21:25 -04:00
parent 5a7c93a573
commit 1d1d201520
5 changed files with 187 additions and 4 deletions

View file

@ -0,0 +1,96 @@
extends Node3D
@export var noise: FastNoiseLite
@onready var enemy: PoliceCar = get_parent()
const CHARGE_COOLDOWN := 5. # time charger has to wait between charges before being able to charge again
const CHARGE_COOLUP := 0.5 # time the charger has to see the player before charging
const CHARGE_SPEED := 50.
const HOLD_TIME := 1.
const CHARGE_TIME := 16. / CHARGE_SPEED
var cooldown := 0.
var coolup := 0.
var charge_clock := 0.
func _start_charge() -> void:
charge_clock = 0.
enemy.default_movement = false
enemy.velocity = global_position.direction_to(Player.instance.global_position)
enemy.velocity *= CHARGE_SPEED
enemy.set_rotation_to_velocity()
func _end_charge() -> void:
charge_clock = 0.
cooldown = CHARGE_COOLDOWN
enemy.default_movement = true
enemy.set_collision_mask_value(4, true)
%KnockUpArea.monitoring = false
%Meshes.position = Vector3.ZERO
func _not_charging_process(delta: float) -> void:
cooldown -= delta
if cooldown > 0.: return
var player_pos := Player.instance.global_position
if global_position.distance_to(player_pos) > 15.:
print("too far")
coolup = 0.
return
var params := PhysicsRayQueryParameters3D.create(
global_position, player_pos, 4294967295, [enemy]
)
var raycast := get_world_3d().direct_space_state.intersect_ray(params)
if not raycast.is_empty() and raycast.collider is Player:
coolup += delta
if coolup > CHARGE_COOLUP:
_start_charge()
else:
print("raycast failed")
coolup = 0.
func _charging_process(delta: float) -> void:
charge_clock += delta
if charge_clock > HOLD_TIME + CHARGE_TIME:
_end_charge()
return
if charge_clock < HOLD_TIME:
var x := noise.get_noise_1d(charge_clock * 10000)
var y := noise.get_noise_1d(-charge_clock * 10000)
%Meshes.position = Vector3(x, 0, y)
else:
%KnockUpArea.monitoring = true
enemy.set_collision_mask_value(4, false)
enemy.move_and_slide()
func _process(delta: float) -> void:
if enemy.default_movement:
_not_charging_process(delta)
else:
_charging_process(delta)
func _on_knock_up_area_body_entered(body: Node3D) -> void:
if body is PoliceCar and body != enemy and body.default_movement:
var e := body as PoliceCar
e.stunned = true
var t := e.create_tween()
t.set_trans(Tween.TRANS_QUAD)
t.tween_property(e, "position:y", e.position.y + 7.5, .6).set_ease(Tween.EASE_OUT)
t.tween_property(e, "position:y", e.position.y, .6).set_ease(Tween.EASE_IN)
await t.finished
e.stunned = false

View file

@ -0,0 +1 @@
uid://d0ciymxj47qbc

View file

@ -0,0 +1,77 @@
[gd_scene format=3 uid="uid://b8bqsk60jlnew"]
[ext_resource type="PackedScene" uid="uid://oyqyvj5xo5mf" path="res://enemies/base_enemy.tscn" id="1_ovkbs"]
[ext_resource type="Script" uid="uid://d0ciymxj47qbc" path="res://enemies/charging_car/charger_behavior.gd" id="2_ovkbs"]
[sub_resource type="BoxShape3D" id="BoxShape3D_8s2ff"]
size = Vector3(2.8337402, 1.0512085, 1.2189941)
[sub_resource type="BoxShape3D" id="BoxShape3D_16nkq"]
size = Vector3(2.1784668, 0.83740234, 1)
[sub_resource type="PrismMesh" id="PrismMesh_16nkq"]
[sub_resource type="BoxMesh" id="BoxMesh_idkrf"]
[sub_resource type="BoxMesh" id="BoxMesh_8s2ff"]
size = Vector3(0.1, 0.05, 0.2)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ovkbs"]
albedo_color = Color(1, 0.32, 0.32, 1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_gtwxk"]
albedo_color = Color(0.26, 0.45733315, 1, 1)
[sub_resource type="FastNoiseLite" id="FastNoiseLite_ovkbs"]
[sub_resource type="BoxShape3D" id="BoxShape3D_ovkbs"]
size = Vector3(1.8274536, 1.0043945, 1.3088379)
[node name="ChargingCar" unique_id=206023291 instance=ExtResource("1_ovkbs")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="Hurtbox" parent_id_path=PackedInt32Array(688205599) index="0" unique_id=1037862249]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.15533447, 0.41860962, 0)
shape = SubResource("BoxShape3D_8s2ff")
debug_color = Color(0.99742216, 0, 0.17616406, 0.41960785)
[node name="CollisionShape3D" type="CollisionShape3D" parent="." index="2" unique_id=1443830094]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.16711426, 0.4411621, 0)
shape = SubResource("BoxShape3D_16nkq")
[node name="Meshes" type="Node3D" parent="." index="3" unique_id=1589501183]
unique_name_in_owner = true
[node name="MeshInstance3D" type="MeshInstance3D" parent="Meshes" index="0" unique_id=1428296358]
transform = Transform3D(-4.0897394e-08, 0.9356233, 0, -0.9356233, -4.0897394e-08, 0, 0, 0, 0.9356233, 0.79208755, 0.39598227, 0)
mesh = SubResource("PrismMesh_16nkq")
[node name="MeshInstance3D2" type="MeshInstance3D" parent="Meshes" index="1" unique_id=1095305852]
transform = Transform3D(1.2590417, 0, 0, 0, 0.6540867, 0, 0, 0, 0.6540867, -0.2952547, 0.36984542, 0)
mesh = SubResource("BoxMesh_idkrf")
[node name="MeshInstance3D7" type="MeshInstance3D" parent="Meshes" index="2" unique_id=2040240859]
transform = Transform3D(1.7975575, 0.87680507, 0, -0.87680507, 1.7975575, 0, 0, 0, 2, 0.5758674, 0.7817617, 0.24429089)
mesh = SubResource("BoxMesh_8s2ff")
surface_material_override/0 = SubResource("StandardMaterial3D_ovkbs")
[node name="MeshInstance3D8" type="MeshInstance3D" parent="Meshes" index="3" unique_id=2068949320]
transform = Transform3D(1.7975575, 0.87680507, 0, -0.87680507, 1.7975575, 0, 0, 0, 2, 0.58287287, 0.7783446, -0.23176795)
mesh = SubResource("BoxMesh_8s2ff")
surface_material_override/0 = SubResource("StandardMaterial3D_gtwxk")
[node name="ChargerBehavior" type="Node3D" parent="." index="4" unique_id=520454998]
script = ExtResource("2_ovkbs")
noise = SubResource("FastNoiseLite_ovkbs")
[node name="KnockUpArea" type="Area3D" parent="." index="5" unique_id=74486428]
unique_name_in_owner = true
collision_layer = 0
collision_mask = 8
monitoring = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="KnockUpArea" index="0" unique_id=1991351917]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.1195984, 0.44458008, 0)
shape = SubResource("BoxShape3D_ovkbs")
debug_color = Color(0.84, 0.65799993, 0, 0.41960785)
[connection signal="body_entered" from="KnockUpArea" to="ChargerBehavior" method="_on_knock_up_area_body_entered"]

View file

@ -13,6 +13,12 @@ var frame_count := 0
var knockback := Vector3.ZERO var knockback := Vector3.ZERO
var default_movement := true
var stunned := false
func set_rotation_to_velocity() -> void:
rotation.y = Vector2(velocity.x, -velocity.z).angle()
func exp_lerp(a: Variant, b: Variant, decay: float, dt: float) -> Variant: func exp_lerp(a: Variant, b: Variant, decay: float, dt: float) -> Variant:
return lerp(a, b, 1 - exp(-decay * dt)) return lerp(a, b, 1 - exp(-decay * dt))
@ -32,13 +38,16 @@ func _process_movement(delta: float) -> void:
velocity = velocity.limit_length(max_speed) velocity = velocity.limit_length(max_speed)
func _process(delta: float) -> void: func _process(delta: float) -> void:
if not default_movement: return
if stunned: return
frame_count = (frame_count + 1) % FRAME_IDXS frame_count = (frame_count + 1) % FRAME_IDXS
if frame_count == frame_idx: if frame_count == frame_idx:
_update_nav_agent() _update_nav_agent()
if knockback.length() < 0.1: if knockback.length() < 0.1:
_process_movement(delta) _process_movement(delta)
rotation.y = Vector2(velocity.x, -velocity.z).angle() set_rotation_to_velocity()
position.y = 0.01 position.y = 0.01
else: else:
velocity = knockback velocity = knockback
@ -61,4 +70,3 @@ func hit(proj: Node3D, damage: float) -> bool:
func _on_hurtbox_body_entered(body: Node3D) -> void: func _on_hurtbox_body_entered(body: Node3D) -> void:
if body is Player: if body is Player:
body.damage(self) body.damage(self)

File diff suppressed because one or more lines are too long