From 2e48941220a10189f7c75366b9a3660ecff7e7b0 Mon Sep 17 00:00:00 2001 From: Sara Date: Sat, 20 Jun 2026 22:12:57 +0200 Subject: [PATCH] feat: implemented eye orb enemy --- modules/viscosity/enemy_orb.cpp | 18 ++++++++- modules/viscosity/enemy_orb.h | 3 +- modules/viscosity/player_body.cpp | 10 +++++ modules/viscosity/player_body.h | 11 ++++- project/assets/character/player/player.tscn | 3 +- project/objects/enemy_orb.tscn | 11 +++++ project/objects/projectiles/projectile.tscn | 45 +++++++++++++++++++++ 7 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 project/objects/projectiles/projectile.tscn diff --git a/modules/viscosity/enemy_orb.cpp b/modules/viscosity/enemy_orb.cpp index 6046921a..3fb24f77 100644 --- a/modules/viscosity/enemy_orb.cpp +++ b/modules/viscosity/enemy_orb.cpp @@ -8,6 +8,12 @@ void EnemyOrb::_bind_methods() { BIND_HPROPERTY(Variant::OBJECT, projectile, PROPERTY_HINT_RESOURCE_TYPE, "PackedScene"); } +void EnemyOrb::process() { + if (this->player) { + this->look_at(this->player->get_global_position()); + } +} + void EnemyOrb::shoot() { if (!this->player || this->projectile.is_null()) { return; @@ -20,15 +26,17 @@ void EnemyOrb::shoot() { } void EnemyOrb::body_entered(Node3D *body) { - if (PlayerBody * player{ cast_to(body) }) { - this->player = player; + if (PlayerBody * found_player{ cast_to(body) }) { + this->player = found_player; get_tree()->create_timer(this->shoot_delay)->connect("timeout", callable_mp(this, &EnemyOrb::shoot)); + set_process(true); } } void EnemyOrb::body_exited(Node3D *body) { if (this->player == body) { this->player = nullptr; + set_process(false); } } @@ -42,7 +50,13 @@ void EnemyOrb::_notification(int what) { case NOTIFICATION_READY: if ((this->detection_area = cast_to(get_node(NodePath("AwarenessArea"))))) { this->detection_area->connect("body_entered", callable_mp(this, &self_type::body_entered)); + this->detection_area->connect("body_exited", callable_mp(this, &self_type::body_exited)); + } else { + ERR_FAIL_EDMSG("Failed to find detection area"); } return; + case NOTIFICATION_PROCESS: + process(); + return; } } diff --git a/modules/viscosity/enemy_orb.h b/modules/viscosity/enemy_orb.h index 4a39d315..65a1a9a7 100644 --- a/modules/viscosity/enemy_orb.h +++ b/modules/viscosity/enemy_orb.h @@ -8,6 +8,7 @@ class EnemyOrb : public Node3D { GDCLASS(EnemyOrb, Node3D); + void process(); void shoot(); void body_entered(Node3D *body); void body_exited(Node3D *body); @@ -20,7 +21,7 @@ private: Ref projectile{}; Area3D *detection_area{ nullptr }; PlayerBody *player{ nullptr }; - double shoot_delay{}; + double shoot_delay{ 0.25 }; public: GET_SET_FNS(Ref, projectile); diff --git a/modules/viscosity/player_body.cpp b/modules/viscosity/player_body.cpp index af8b06b0..d216675a 100644 --- a/modules/viscosity/player_body.cpp +++ b/modules/viscosity/player_body.cpp @@ -1,5 +1,11 @@ #include "player_body.h" #include "core/config/engine.h" +#include "core/object/class_db.h" + +void PlayerBody::_bind_methods() { + BIND_PROPERTY(Variant::FLOAT, health); + ClassDB::bind_method(D_METHOD("damage"), &self_type::damage); +} void PlayerBody::update_movement() { move_and_slide(); @@ -20,3 +26,7 @@ void PlayerBody::_notification(int what) { return; } } + +void PlayerBody::damage() { + this->health -= 0.25; +} diff --git a/modules/viscosity/player_body.h b/modules/viscosity/player_body.h index 44c5b9db..6f29f571 100644 --- a/modules/viscosity/player_body.h +++ b/modules/viscosity/player_body.h @@ -5,9 +5,18 @@ class PlayerBody : public CharacterBody3D { GDCLASS(PlayerBody, CharacterBody3D); - static void _bind_methods() {} + static void _bind_methods(); void update_movement(); protected: void _notification(int what); + +public: + void damage(); + +private: + double health{ 1.0 }; + +public: + GET_SET_FNS(double, health); }; diff --git a/project/assets/character/player/player.tscn b/project/assets/character/player/player.tscn index 214eec9f..0dee5526 100644 --- a/project/assets/character/player/player.tscn +++ b/project/assets/character/player/player.tscn @@ -9,10 +9,11 @@ transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0, 0, 0) [node name="BlankCharacterMesh" parent="HumanArmature/Skeleton3D" parent_id_path=PackedInt32Array(1295955268) index="0" unique_id=1294452068] +unique_name_in_owner = true transform = Transform3D(0.99992746, 0, 0, 0, 0.99992746, 0, 0, 0, 0.99992746, 0, 0, 0) layers = 3 material_override = ExtResource("2_0o6ap") -instance_shader_parameters/health = 0.674000032015 +instance_shader_parameters/health = 1.0 [node name="Eyes" parent="HumanArmature/Skeleton3D" parent_id_path=PackedInt32Array(1295955268) index="4" unique_id=332871592] layers = 3 diff --git a/project/objects/enemy_orb.tscn b/project/objects/enemy_orb.tscn index e14e2b78..1b9b6c14 100644 --- a/project/objects/enemy_orb.tscn +++ b/project/objects/enemy_orb.tscn @@ -1,7 +1,18 @@ [gd_scene format=3 uid="uid://dgpnywswyjguf"] +[ext_resource type="PackedScene" uid="uid://bmibf31n8lo2l" path="res://objects/projectiles/projectile.tscn" id="1_sf38o"] [ext_resource type="PackedScene" uid="uid://c2sddj48b7fw1" path="res://assets/enemies/orb.tscn" id="1_sixut"] +[sub_resource type="CylinderShape3D" id="CylinderShape3D_vsqsw"] +height = 26.0 +radius = 10.89209 + [node name="EnemyOrb" type="EnemyOrb" unique_id=856275320] +projectile = ExtResource("1_sf38o") [node name="orb" parent="." unique_id=1503011283 instance=ExtResource("1_sixut")] + +[node name="AwarenessArea" type="Area3D" parent="." unique_id=255601634] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="AwarenessArea" unique_id=1737452274] +shape = SubResource("CylinderShape3D_vsqsw") diff --git a/project/objects/projectiles/projectile.tscn b/project/objects/projectiles/projectile.tscn new file mode 100644 index 00000000..236d65cb --- /dev/null +++ b/project/objects/projectiles/projectile.tscn @@ -0,0 +1,45 @@ +[gd_scene format=3 uid="uid://bmibf31n8lo2l"] + +[ext_resource type="Material" uid="uid://6ton7xdddycw" path="res://assets/materials/kaleidoscope_mosaic.tres" id="1_c1bky"] + +[sub_resource type="GDScript" id="GDScript_exgcw"] +resource_name = "Projectile" +script/source = "extends Area3D + +@export var speed : float = 50.0 + +func _physics_process(delta : float): + global_position += -global_basis.z * speed * delta + $MeshInstance3D.global_rotation = global_position * 10.0 + + +func _on_body_entered(body: Node3D) -> void: + if is_queued_for_deletion(): + return + queue_free() + var player := body as PlayerBody + if not player: + return + player.damage() +" + +[sub_resource type="BoxMesh" id="BoxMesh_exgcw"] +material = ExtResource("1_c1bky") + +[sub_resource type="SphereShape3D" id="SphereShape3D_exgcw"] +radius = 0.18299815 + +[node name="Projectile" type="Area3D" unique_id=1928044182] +collision_mask = 15 +script = SubResource("GDScript_exgcw") +speed = 25.0 + +[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=447127444] +transform = Transform3D(0.14096427, -0.024876386, -0.10913402, -0.045904536, 0.14721328, -0.09284944, 0.10208744, 0.10054556, 0.108943745, 0, 0, 0) +mesh = SubResource("BoxMesh_exgcw") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1174190454] +shape = SubResource("SphereShape3D_exgcw") +debug_color = Color(0.97529346, 0, 0.42398593, 0.41960785) + +[connection signal="body_entered" from="." to="." method="_on_body_entered"]