From 68d3cec08aa474a268b663405a729b9dfb0c981a Mon Sep 17 00:00:00 2001 From: Morph01 <145839520+Morph01@users.noreply.github.com> Date: Sun, 25 Aug 2024 18:25:22 +0200 Subject: [PATCH] simple dynamic crosshair --- .../Characters/first_person_player.tscn | 39 ++++++++++++ src/BoneCollisionShape.cpp | 7 ++- src/BoneCollisionShape.h | 10 ++-- src/Bullet.cpp | 3 + src/Bullet.h | 2 + src/Crosshair.cpp | 59 +++++++++++++++++++ src/Crosshair.h | 35 +++++++++++ src/register_types.cpp | 2 + 8 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 src/Crosshair.cpp create mode 100644 src/Crosshair.h diff --git a/godot/Scenes/Characters/first_person_player.tscn b/godot/Scenes/Characters/first_person_player.tscn index 3fa2bd9..ebab489 100644 --- a/godot/Scenes/Characters/first_person_player.tscn +++ b/godot/Scenes/Characters/first_person_player.tscn @@ -24,3 +24,42 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0) [node name="Steampunk Rifle" parent="Head/Camera" instance=ExtResource("1_i6keg")] transform = Transform3D(1, 0, 0, 0, 0.998135, -0.0610485, 0, 0.0610485, 0.998135, 0.19, -0.18, -0.55) + +[node name="UserInterface" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 1 + +[node name="Crosshair" type="Crosshair" parent="UserInterface"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -20.0 +offset_top = -20.0 +offset_right = 20.0 +offset_bottom = 20.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Top" type="Line2D" parent="UserInterface/Crosshair"] +points = PackedVector2Array(0, -5, 0, -15) +width = 2.0 + +[node name="Right" type="Line2D" parent="UserInterface/Crosshair"] +points = PackedVector2Array(5, 0, 15, 0) +width = 2.0 + +[node name="Bottom" type="Line2D" parent="UserInterface/Crosshair"] +points = PackedVector2Array(0, 5, 0, 15) +width = 2.0 + +[node name="Left" type="Line2D" parent="UserInterface/Crosshair"] +points = PackedVector2Array(-5, 0, -15, 0) +width = 2.0 diff --git a/src/BoneCollisionShape.cpp b/src/BoneCollisionShape.cpp index 879a3d8..2322cab 100644 --- a/src/BoneCollisionShape.cpp +++ b/src/BoneCollisionShape.cpp @@ -24,7 +24,10 @@ BoneCollisionShape::BoneCollisionShape() {} BoneCollisionShape::~BoneCollisionShape() {} -void BoneCollisionShape::_ready() {} +void BoneCollisionShape::_ready() { + m_Crosshair = Object::cast_to(get_parent()->get_parent()->get_parent()->get_parent()->get_parent()->get_parent()->get_parent()->find_child("Crosshair")); + DEV_ASSERT(m_Crosshair); +} void BoneCollisionShape::set_head_damage(int a_D) { m_HeadDamage = a_D; @@ -44,11 +47,13 @@ int BoneCollisionShape::get_body_damage() const { void BoneCollisionShape::headshot_hit() { ERR_PRINT("zombie headshot hit"); + m_Crosshair->set_dot_color(Color(1,0,0,1)); emit_signal("a_ZombieHeadShotHit", m_HeadDamage); } void BoneCollisionShape::bodyshot_hit() { ERR_PRINT("zombie body hit"); + m_Crosshair->set_dot_color(Color(0,0,1,1)); emit_signal("a_ZombieBodyShotHit", m_BodyDamage); } diff --git a/src/BoneCollisionShape.h b/src/BoneCollisionShape.h index 86bbe43..56fe1fa 100644 --- a/src/BoneCollisionShape.h +++ b/src/BoneCollisionShape.h @@ -1,5 +1,6 @@ #pragma once +#include "Crosshair.h" #include namespace blitz { @@ -15,16 +16,17 @@ class BoneCollisionShape : public godot::Area3D { ~BoneCollisionShape(); void _ready(); - void headshot_hit(); + void headshot_hit(); void bodyshot_hit(); private: int m_HeadDamage = 2; int m_BodyDamage = 1; - void set_head_damage(int d); - int get_head_damage() const; + void set_head_damage(int d); + int get_head_damage() const; void set_body_damage(int d); - int get_body_damage() const; + int get_body_damage() const; + Crosshair* m_Crosshair; }; } // namespace blitz \ No newline at end of file diff --git a/src/Bullet.cpp b/src/Bullet.cpp index 8431e44..2cbaf41 100644 --- a/src/Bullet.cpp +++ b/src/Bullet.cpp @@ -25,6 +25,8 @@ void Bullet::_ready() { m_Timer = memnew(Timer); add_child(m_Timer); m_Timer->connect("timeout", callable_mp(this, &Bullet::_on_timer_timeout)); + m_Crosshair = Object::cast_to(get_parent()->find_child("Crosshair")); + DEV_ASSERT(m_Crosshair); } void Bullet::_physics_process(float a_Delta) { @@ -53,6 +55,7 @@ void Bullet::_physics_process(float a_Delta) { } void Bullet::_on_timer_timeout() { + m_Crosshair->set_dot_color(Color(1, 1, 1, 1)); queue_free(); } diff --git a/src/Bullet.h b/src/Bullet.h index cc668e7..56412fd 100644 --- a/src/Bullet.h +++ b/src/Bullet.h @@ -1,5 +1,6 @@ #pragma once +#include "Crosshair.h" #include #include #include @@ -24,6 +25,7 @@ class Bullet : public godot::Node3D { godot::RayCast3D* m_Ray; godot::MeshInstance3D* m_Mesh; godot::Timer* m_Timer; + Crosshair* m_Crosshair; void _on_timer_timeout(); }; diff --git a/src/Crosshair.cpp b/src/Crosshair.cpp new file mode 100644 index 0000000..2f23961 --- /dev/null +++ b/src/Crosshair.cpp @@ -0,0 +1,59 @@ +#include "Crosshair.h" + +using namespace godot; + +namespace blitz { +void Crosshair::_bind_methods() {} + +Crosshair::Crosshair() : + m_DotRadius(1.0f), + m_DotColor(Color(1, 1, 1, 1)), + m_CrosshairSpeed(0.25f), + m_CrosshairDistance(2.0f), + m_Origin(Vector3(0, 0, 0)), + m_Pos(Vector2(0, 0)) {} +Crosshair::~Crosshair() {} + +void Crosshair::_ready() { + m_Player = Object::cast_to(get_parent()->get_parent()->get_parent()->find_child("FirstPersonPlayer")); + DEV_ASSERT(m_Player); + m_CrosshairLines = {Object::cast_to(find_child("Top")), Object::cast_to(find_child("Right")), + Object::cast_to(find_child("Bottom")), Object::cast_to(find_child("Left"))}; + for (size_t i = 0; i < m_CrosshairLines.size(); i++) { + DEV_ASSERT(m_CrosshairLines[i]); + } + queue_redraw(); +} + +void Crosshair::_process(float a_Delta) { + adjust_crosshair_lines(); +} + +void Crosshair::_draw() { + draw_circle(Vector2(0, 0), m_DotRadius, m_DotColor); +} + +void Crosshair::adjust_crosshair_lines() { + Vector3 vel = m_Player->get_real_velocity(); + + float speed = m_Origin.distance_to(vel); + + m_CrosshairLines[0]->set_position( + m_CrosshairLines[0]->get_position().lerp(m_Pos + Vector2(0, -speed * m_CrosshairDistance), m_CrosshairSpeed)); + + m_CrosshairLines[1]->set_position( + m_CrosshairLines[1]->get_position().lerp(m_Pos + Vector2(speed * m_CrosshairDistance, 0), m_CrosshairSpeed)); + + m_CrosshairLines[2]->set_position( + m_CrosshairLines[2]->get_position().lerp(m_Pos + Vector2(0, speed * m_CrosshairDistance), m_CrosshairSpeed)); + + m_CrosshairLines[3]->set_position( + m_CrosshairLines[3]->get_position().lerp(m_Pos + Vector2(-speed * m_CrosshairDistance, 0), m_CrosshairSpeed)); +} + +void Crosshair::set_dot_color(Color a_Color) { + m_DotColor = a_Color; + queue_redraw(); +} + +} // namespace blitz \ No newline at end of file diff --git a/src/Crosshair.h b/src/Crosshair.h new file mode 100644 index 0000000..4fd3d1d --- /dev/null +++ b/src/Crosshair.h @@ -0,0 +1,35 @@ +#pragma once + +#include "FirstPersonPlayer.h" +#include +#include + +namespace blitz { +class Crosshair : public godot::CenterContainer { + GDCLASS(Crosshair, godot::CenterContainer) + protected: + static void _bind_methods(); + + public: + Crosshair(); + ~Crosshair(); + + void _ready(); + void _process(float delta); + void _draw(); + void set_dot_color(godot::Color col); + + private: + godot::Color m_DotColor; + float m_DotRadius; + std::array m_CrosshairLines; + FirstPersonPlayer* m_Player; + float m_CrosshairSpeed; + float m_CrosshairDistance; + godot::Vector3 m_Origin; + godot::Vector2 m_Pos; + + void adjust_crosshair_lines(); +}; + +} // namespace blitz \ No newline at end of file diff --git a/src/register_types.cpp b/src/register_types.cpp index 016a421..d6711be 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -7,6 +7,7 @@ #include "SpringArmPivot.h" #include "World.h" #include "Zombie.h" +#include "Crosshair.h" #include #include @@ -26,6 +27,7 @@ void initialize_example_module(ModuleInitializationLevel p_level) { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); } void uninitialize_example_module(ModuleInitializationLevel p_level) {