Skip to content

Commit

Permalink
implemented a fire rate in projectile spawner
Browse files Browse the repository at this point in the history
  • Loading branch information
vorlac committed Sep 23, 2023
1 parent 66fc3d7 commit f8c0a56
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 21 deletions.
23 changes: 14 additions & 9 deletions src/nodes/level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ namespace rl::inline node
if (this->active()) [[likely]]
{
godot::Point2 mouse_pos{ this->get_global_mouse_position() };
this->draw_circle(mouse_pos, 10, { "DARK_CYAN" });
this->draw_circle(mouse_pos, 5, { "DARK_CYAN" });
}
}

Expand All @@ -70,16 +70,21 @@ namespace rl::inline node
void Level::on_character_spawn_projectile(godot::Node* obj)
{
godot::Node2D* node{ gdcast<godot::Node2D>(obj) };
rl::Projectile* proj{ m_projectile_spawner->spawn_projectile() };

proj->set_position(node->get_global_position());
proj->set_rotation(node->get_rotation() - godot::Math::deg_to_rad(45.0));
Projectile* projectile{ m_projectile_spawner->spawn_projectile() };
if (projectile != nullptr)
{
projectile->set_position(node->get_global_position());
projectile->set_rotation(node->get_rotation() - godot::Math::deg_to_rad(45.0));

rl::Character* character{ gdcast<rl::Character>(node) };
if (character != nullptr)
proj->set_velocity(godot::Vector2{ 0, -1 }.rotated(character->get_global_rotation()));
Character* character{ gdcast<Character>(node) };
if (character != nullptr)
{
projectile->set_velocity(
godot::Vector2(0, -1).rotated(character->get_global_rotation()));
}

this->add_child(proj);
this->add_child(projectile);
}
}

[[signal_slot]]
Expand Down
43 changes: 37 additions & 6 deletions src/nodes/projectile_spawner.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,47 @@
#include "nodes/projectile_spawner.hpp"

#include "util/bind.hpp"

namespace rl::inline node
{
void ProjectileSpawner::_ready()
[[nodiscard]]
Projectile* ProjectileSpawner::spawn_projectile()
{
m_scene.set_path(path::scene::Bullet);
auto elapsed{ clock_t::now() - m_prev_spawn_time };
if (elapsed < m_spawn_delay)
return nullptr;
else
{
Projectile* projectile{ m_scene.instantiate() };
m_prev_spawn_time = clock_t::now();
return projectile;
}
}

[[nodiscard]]
Projectile* ProjectileSpawner::spawn_projectile()
[[property]]
double ProjectileSpawner::get_fire_rate() const
{
return m_fire_rate;
}

[[property]]
void ProjectileSpawner::set_fire_rate(double fire_rate)
{
m_fire_rate = fire_rate;
m_spawn_delay = ProjectileSpawner::calculate_spawn_delay(m_fire_rate);
}

ProjectileSpawner::millisec_t ProjectileSpawner::calculate_spawn_delay(double fire_rate)
{
// converts fire rate (shots per second) to the time delay between shots in ms.
// the multiplication by 100 is just to offset the rounding errors by shifting
// the decimal place to the right a few places before dividing.
return (1000ms * 100) / static_cast<uint64_t>(fire_rate * 100);
}

void ProjectileSpawner::_bind_methods()
{
Projectile* projectile{ m_scene.instantiate() };
return projectile;
bind_member_function(ProjectileSpawner, get_fire_rate);
bind_member_function(ProjectileSpawner, set_fire_rate);
}
}
29 changes: 23 additions & 6 deletions src/nodes/projectile_spawner.hpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
#pragma once

#include "nodes/projectile.hpp"
#include "util/bind.hpp"
#include "util/constants.hpp"
#include "util/scene.hpp"

#include <chrono>

#include <godot_cpp/classes/node2d.hpp>
#include <godot_cpp/variant/typed_array.hpp>

namespace rl::inline node
{
using namespace std::chrono_literals;

class ProjectileSpawner : public godot::Node2D
{
GDCLASS(ProjectileSpawner, godot::Node2D);
Expand All @@ -17,15 +22,27 @@ namespace rl::inline node
ProjectileSpawner() = default;
~ProjectileSpawner() = default;

void _ready() override;
Projectile* spawn_projectile();

protected:
static void _bind_methods()
{
}
[[property]] double get_fire_rate() const;
[[property]] void set_fire_rate(double fire_rate);

protected:
resource::preload::scene<Projectile> m_scene;
static void _bind_methods();

private:
using clock_t = std::chrono::high_resolution_clock;
using millisec_t = std::chrono::milliseconds;
static millisec_t calculate_spawn_delay(double fire_rate);

private:
// number of prjectiles per second
double m_fire_rate{ 10.0 };
// time delay between shots (ms). multiplication by 100 is just to offset rounding errors.
millisec_t m_spawn_delay{ ProjectileSpawner::calculate_spawn_delay(m_fire_rate) };
// the time point that keeps track of when the last projectile was spawned.
clock_t::time_point m_prev_spawn_time{ clock_t::now() };
// preloaded packed scene that will be instantiated per spawn
resource::preload::scene<Projectile> m_scene{ path::scene::Bullet };
};
}

0 comments on commit f8c0a56

Please sign in to comment.