police car weak point

This commit is contained in:
Michael Campbell 2026-02-18 16:46:00 -05:00
parent 324e7d437b
commit 8a173b968d
15 changed files with 203 additions and 9 deletions

View file

@ -15,8 +15,9 @@ func _physics_process(delta: float) -> void:
rotation.y = Vector2(velocity.x, -velocity.z).angle() rotation.y = Vector2(velocity.x, -velocity.z).angle()
func hit(_proj: PlayerProjectile): func hit(_proj: PlayerProjectile) -> bool:
queue_free() queue_free()
return true
func _on_hurtbox_body_entered(body: Node3D) -> void: func _on_hurtbox_body_entered(body: Node3D) -> void:

View file

@ -1,6 +1,7 @@
[gd_scene format=3 uid="uid://dusfu1hidkmsk"] [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="Script" uid="uid://c6xr2j0g1ep7j" path="res://enemies/police_car/police_car.gd" id="1_spw8y"]
[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"] [sub_resource type="Curve" id="Curve_spw8y"]
_limits = [1.0, 20.0, -1.0, 1.0] _limits = [1.0, 20.0, -1.0, 1.0]
@ -30,6 +31,9 @@ height = 0.5
[sub_resource type="BoxShape3D" id="BoxShape3D_8364l"] [sub_resource type="BoxShape3D" id="BoxShape3D_8364l"]
size = Vector3(1.7734375, 0.5839844, 1.1367188) size = Vector3(1.7734375, 0.5839844, 1.1367188)
[sub_resource type="BoxShape3D" id="BoxShape3D_s5uvd"]
size = Vector3(0.6993408, 1, 0.88671875)
[node name="PoliceCar" type="CharacterBody3D" unique_id=206023291] [node name="PoliceCar" type="CharacterBody3D" unique_id=206023291]
collision_layer = 8 collision_layer = 8
collision_mask = 15 collision_mask = 15
@ -74,4 +78,13 @@ transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, -0.122092836, 0.34972915, -0.
shape = SubResource("BoxShape3D_8364l") shape = SubResource("BoxShape3D_8364l")
debug_color = Color(0.9913104, 0, 0.27320355, 0.41960785) debug_color = Color(0.9913104, 0, 0.27320355, 0.41960785)
[node name="WeakPoint" type="Area3D" parent="." unique_id=1032610086]
collision_layer = 8
collision_mask = 0
script = ExtResource("2_8ru0n")
[node name="CollisionShape3D" type="CollisionShape3D" parent="WeakPoint" unique_id=950314743]
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"] [connection signal="body_entered" from="Hurtbox" to="." method="_on_hurtbox_body_entered"]

View file

@ -0,0 +1,26 @@
extends Area3D
var parent: PoliceCar
func _ready() -> void:
assert(get_parent() is PoliceCar)
parent = get_parent()
func hit(projectile: PlayerProjectile) -> bool:
if projectile == null: return false
var angle := projectile.velocity.angle_to(-parent.velocity)
var weak_point_hit := rad_to_deg(angle) < 25.
if weak_point_hit:
var explosion := preload("res://player/explosion/explosion.tscn").instantiate()
explosion.position = parent.position
parent.add_sibling(explosion)
var label_vfx := preload("res://utils/label_vfx/label_vfx.tscn").instantiate()
label_vfx.position = parent.position
parent.add_sibling(label_vfx)
parent.queue_free()
return weak_point_hit

View file

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

View file

@ -0,0 +1,91 @@
[gd_scene format=3 uid="uid://dwayva0yscri8"]
[ext_resource type="Script" uid="uid://br3jskryab3if" path="res://player/explosion/hit_area.gd" id="1_yr3g8"]
[sub_resource type="SphereMesh" id="SphereMesh_5mksp"]
height = 0.5
radial_segments = 8
rings = 8
is_hemisphere = true
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_xpyis"]
transparency = 1
blend_mode = 1
shading_mode = 0
albedo_color = Color(1, 0, 0, 0.48235294)
[sub_resource type="SphereShape3D" id="SphereShape3D_xpyis"]
radius = 4.0949817
[sub_resource type="Animation" id="Animation_yr3g8"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Container:scale")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector3(1, 1, 1)]
}
[sub_resource type="Animation" id="Animation_xpyis"]
resource_name = "explode"
length = 0.5
step = 0.5
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Container:scale")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.2, 0.5),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector3(0, 0, 0), Vector3(1, 1, 1), Vector3(0, 0, 0)]
}
tracks/1/type = "method"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0.5),
"transitions": PackedFloat32Array(1),
"values": [{
"args": [],
"method": &"queue_free"
}]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_120gr"]
_data = {
&"RESET": SubResource("Animation_yr3g8"),
&"explode": SubResource("Animation_xpyis")
}
[node name="Explosion" type="Node3D" unique_id=702514359]
[node name="Container" type="Node3D" parent="." unique_id=1035655414]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Container" unique_id=509955843]
transform = Transform3D(7.6891003, 0, 0, 0, 7.6891003, 0, 0, 0, 7.6891003, 0, 0, 0)
mesh = SubResource("SphereMesh_5mksp")
surface_material_override/0 = SubResource("StandardMaterial3D_xpyis")
[node name="HitArea" type="Area3D" parent="Container" unique_id=468568433]
collision_layer = 0
collision_mask = 12
script = ExtResource("1_yr3g8")
[node name="CollisionShape3D" type="CollisionShape3D" parent="Container/HitArea" unique_id=837356976]
shape = SubResource("SphereShape3D_xpyis")
[node name="AnimationPlayer" type="AnimationPlayer" parent="." unique_id=893547695]
libraries/ = SubResource("AnimationLibrary_120gr")
autoplay = &"explode"

View file

@ -0,0 +1,10 @@
extends Area3D
func _on_collision(node: Node3D):
if node.has_method("hit"):
node.hit(null)
func _ready() -> void:
body_entered.connect(_on_collision)
area_entered.connect(_on_collision)

View file

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

View file

@ -87,7 +87,7 @@ func _process_shoot(delta: float) -> void:
fire_clock -= delta * clock_mul fire_clock -= delta * clock_mul
if Input.is_action_pressed("fire") and fire_clock <= 0.: if Input.is_action_pressed("fire") and fire_clock <= 0.:
var dir := Vector3.RIGHT.rotated(Vector3.UP, aim_angle) var dir := Vector3.RIGHT.rotated(Vector3.UP, aim_angle)
var player_projectile: PlayerProjectile = preload("player_projectile.tscn").instantiate() var player_projectile: PlayerProjectile = preload("res://player/projectile/player_projectile.tscn").instantiate()
player_projectile.init(dir) player_projectile.init(dir)
player_projectile.global_position = global_position + Vector3.UP * 0.5 player_projectile.global_position = global_position + Vector3.UP * 0.5
add_sibling(player_projectile) add_sibling(player_projectile)

View file

@ -63,3 +63,26 @@ size_flags_horizontal = 10
theme_override_font_sizes/font_size = 48 theme_override_font_sizes/font_size = 48
text = "Health: 2" text = "Health: 2"
horizontal_alignment = 2 horizontal_alignment = 2
[node name="StaminaBar" type="ProgressBar" parent="CanvasLayer" unique_id=961689130]
unique_name_in_owner = true
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -162.0
offset_top = -27.0
offset_right = 162.0
grow_horizontal = 2
grow_vertical = 0
max_value = 1.0
show_percentage = false
[node name="Label" type="Label" parent="CanvasLayer/StaminaBar" unique_id=1238654404]
layout_mode = 0
offset_left = 132.0
offset_top = -27.0
offset_right = 196.0
offset_bottom = -4.0
text = "Stamina"

View file

@ -10,12 +10,14 @@ var health: int = 1:
if v == 0: if v == 0:
queue_free() queue_free()
func _ready() -> void: func _on_collision(node: Node3D):
body_entered.connect(func(body: Node3D): if node.has_method("hit"):
if body.has_method("hit"): if node.hit(self):
body.hit(self)
health -= 1 health -= 1
)
func _ready() -> void:
body_entered.connect(_on_collision)
area_entered.connect(_on_collision)
func init(dir: Vector3) -> void: func init(dir: Vector3) -> void:
_initialized = true _initialized = true

View file

@ -0,0 +1,12 @@
class_name LabelVFX
extends Label3D
func _ready() -> void:
create_tween().tween_property(self, "position:y", position.y + 10, 2.)
create_tween().tween_method((func(alpha: float):
modulate.a = alpha
outline_modulate.a = alpha
), 1., 0., 1.).set_delay(.5) \
.finished.connect(queue_free)

View file

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

View file

@ -0,0 +1,12 @@
[gd_scene format=3 uid="uid://cfgfg410c6qtc"]
[ext_resource type="Script" uid="uid://cgu05sn2klmf2" path="res://utils/label_vfx/label_vfx.gd" id="1_6m140"]
[node name="LabelVFX" type="Label3D" unique_id=1366577296]
billboard = 1
double_sided = false
no_depth_test = true
text = "Perfect!"
font_size = 256
outline_size = 96
script = ExtResource("1_6m140")

View file

@ -4,7 +4,7 @@ extends CollisionObject3D
func _ready() -> void: func _ready() -> void:
scale.y = randf_range(.5, 1.25) scale.y = randf_range(.5, 1.25)
func hit(_proj: PlayerProjectile) -> void: func hit(_proj: PlayerProjectile) -> bool:
print("boom!") print("boom!")
SignalBus.building_destroyed.emit(self) SignalBus.building_destroyed.emit(self)
collision_layer = 1 # World collision only collision_layer = 1 # World collision only
@ -13,3 +13,4 @@ func hit(_proj: PlayerProjectile) -> void:
%DestroyedMesh.show() %DestroyedMesh.show()
%GPUParticles3D.preprocess = randf() %GPUParticles3D.preprocess = randf()
return true

View file

@ -7,7 +7,7 @@ func _get_spawn_pos() -> Vector3:
return curve.samplef(randf_range(0, curve.point_count)) return curve.samplef(randf_range(0, curve.point_count))
func _spawn_police_car(p: Vector3) -> void: func _spawn_police_car(p: Vector3) -> void:
var car: Node3D = preload("police_car.tscn").instantiate() var car: Node3D = preload("res://enemies/police_car/police_car.tscn").instantiate()
car.position = p + Vector3.UP * 0.1 car.position = p + Vector3.UP * 0.1
add_sibling(car) add_sibling(car)