diff --git a/enemies/police_car/police_car.gd b/enemies/police_car/police_car.gd index ce724ad..848d98b 100644 --- a/enemies/police_car/police_car.gd +++ b/enemies/police_car/police_car.gd @@ -15,8 +15,9 @@ func _physics_process(delta: float) -> void: rotation.y = Vector2(velocity.x, -velocity.z).angle() -func hit(_proj: PlayerProjectile): +func hit(_proj: PlayerProjectile) -> bool: queue_free() + return true func _on_hurtbox_body_entered(body: Node3D) -> void: diff --git a/enemies/police_car/police_car.tscn b/enemies/police_car/police_car.tscn index 2737f26..af54cf5 100644 --- a/enemies/police_car/police_car.tscn +++ b/enemies/police_car/police_car.tscn @@ -1,6 +1,7 @@ [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://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] @@ -30,6 +31,9 @@ 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(0.6993408, 1, 0.88671875) + [node name="PoliceCar" type="CharacterBody3D" unique_id=206023291] collision_layer = 8 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") 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"] diff --git a/enemies/police_car/weak_point.gd b/enemies/police_car/weak_point.gd new file mode 100644 index 0000000..381d210 --- /dev/null +++ b/enemies/police_car/weak_point.gd @@ -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 diff --git a/enemies/police_car/weak_point.gd.uid b/enemies/police_car/weak_point.gd.uid new file mode 100644 index 0000000..4719ecf --- /dev/null +++ b/enemies/police_car/weak_point.gd.uid @@ -0,0 +1 @@ +uid://c14x24qxx1wc3 diff --git a/player/explosion/explosion.tscn b/player/explosion/explosion.tscn new file mode 100644 index 0000000..e26dbec --- /dev/null +++ b/player/explosion/explosion.tscn @@ -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" diff --git a/player/explosion/hit_area.gd b/player/explosion/hit_area.gd new file mode 100644 index 0000000..a62ca1a --- /dev/null +++ b/player/explosion/hit_area.gd @@ -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) + diff --git a/player/explosion/hit_area.gd.uid b/player/explosion/hit_area.gd.uid new file mode 100644 index 0000000..c7c2a24 --- /dev/null +++ b/player/explosion/hit_area.gd.uid @@ -0,0 +1 @@ +uid://br3jskryab3if diff --git a/player/player.gd b/player/player.gd index 9a59b0b..79fb3f2 100644 --- a/player/player.gd +++ b/player/player.gd @@ -87,7 +87,7 @@ func _process_shoot(delta: float) -> void: fire_clock -= delta * clock_mul if Input.is_action_pressed("fire") and fire_clock <= 0.: 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.global_position = global_position + Vector3.UP * 0.5 add_sibling(player_projectile) diff --git a/player/player.tscn b/player/player.tscn index 1e8d165..a7f44b8 100644 --- a/player/player.tscn +++ b/player/player.tscn @@ -63,3 +63,26 @@ size_flags_horizontal = 10 theme_override_font_sizes/font_size = 48 text = "Health: 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" diff --git a/player/projectile/player_projectile.gd b/player/projectile/player_projectile.gd index d2efe9a..7efdf93 100644 --- a/player/projectile/player_projectile.gd +++ b/player/projectile/player_projectile.gd @@ -10,12 +10,14 @@ var health: int = 1: if v == 0: queue_free() +func _on_collision(node: Node3D): + if node.has_method("hit"): + if node.hit(self): + health -= 1 + func _ready() -> void: - body_entered.connect(func(body: Node3D): - if body.has_method("hit"): - body.hit(self) - health -= 1 - ) + body_entered.connect(_on_collision) + area_entered.connect(_on_collision) func init(dir: Vector3) -> void: _initialized = true diff --git a/utils/label_vfx/label_vfx.gd b/utils/label_vfx/label_vfx.gd new file mode 100644 index 0000000..4757be1 --- /dev/null +++ b/utils/label_vfx/label_vfx.gd @@ -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) + + diff --git a/utils/label_vfx/label_vfx.gd.uid b/utils/label_vfx/label_vfx.gd.uid new file mode 100644 index 0000000..048eaae --- /dev/null +++ b/utils/label_vfx/label_vfx.gd.uid @@ -0,0 +1 @@ +uid://cgu05sn2klmf2 diff --git a/utils/label_vfx/label_vfx.tscn b/utils/label_vfx/label_vfx.tscn new file mode 100644 index 0000000..c791209 --- /dev/null +++ b/utils/label_vfx/label_vfx.tscn @@ -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") diff --git a/world/building/building.gd b/world/building/building.gd index 8436ac2..5e5d13f 100644 --- a/world/building/building.gd +++ b/world/building/building.gd @@ -4,7 +4,7 @@ extends CollisionObject3D func _ready() -> void: scale.y = randf_range(.5, 1.25) -func hit(_proj: PlayerProjectile) -> void: +func hit(_proj: PlayerProjectile) -> bool: print("boom!") SignalBus.building_destroyed.emit(self) collision_layer = 1 # World collision only @@ -13,3 +13,4 @@ func hit(_proj: PlayerProjectile) -> void: %DestroyedMesh.show() %GPUParticles3D.preprocess = randf() + return true diff --git a/world/enemy_spawner.gd b/world/enemy_spawner.gd index f309865..b90443e 100644 --- a/world/enemy_spawner.gd +++ b/world/enemy_spawner.gd @@ -7,7 +7,7 @@ func _get_spawn_pos() -> Vector3: return curve.samplef(randf_range(0, curve.point_count)) 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 add_sibling(car)