feat: implemented projectile pool
This commit is contained in:
parent
96d557a0f7
commit
1fbba7b665
70
src/projectile_pool.cpp
Normal file
70
src/projectile_pool.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include "projectile_pool.hpp"
|
||||
#include "projectile.hpp"
|
||||
#include <godot_cpp/classes/scene_state.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
namespace godot {
|
||||
void ProjectilePool::_bind_methods() {
|
||||
#define CLASSNAME ProjectilePool
|
||||
}
|
||||
|
||||
void ProjectilePool::_exit_tree() {
|
||||
if(this->data.is_valid()) {
|
||||
for(Node3D *node : this->inactive) {
|
||||
node->queue_free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectilePool::set_data(Ref<PackedScene> data) {
|
||||
if(!this->data.is_null()) {
|
||||
this->active.clear();
|
||||
for(Node3D *node : this->inactive) {
|
||||
node->queue_free();
|
||||
}
|
||||
}
|
||||
this->data = data;
|
||||
if(!data.is_valid())
|
||||
return;
|
||||
this->count = this->data->get_projectile_count() * this->data->get_rounds_per_second() * 2;
|
||||
for(size_t i{0}; i < this->count; ++i)
|
||||
this->inactive.push_back(this->instantiate_new());
|
||||
}
|
||||
|
||||
Node3D *ProjectilePool::claim_projectile() {
|
||||
if(inactive.is_empty()) {
|
||||
size_t const new_count = this->count + this->data->get_projectile_count() * this->data->get_rounds_per_second() * 2;
|
||||
for(size_t i{this->count}; i < new_count; ++i)
|
||||
this->inactive.push_back(this->instantiate_new());
|
||||
}
|
||||
Node3D *const ret{this->inactive[0]};
|
||||
this->inactive.remove_at(0);
|
||||
this->active.push_back(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ProjectilePool::return_projectile(Node3D *node) {
|
||||
if(this->active.has(node)) {
|
||||
this->active.erase(node);
|
||||
this->inactive.push_back(node);
|
||||
node->get_parent()->remove_child(node);
|
||||
} else {
|
||||
// leftover from previous weapon, free
|
||||
node->queue_free();
|
||||
}
|
||||
}
|
||||
|
||||
Node3D *ProjectilePool::instantiate_new() const {
|
||||
Ref<PackedScene> scene = this->data->get_projectile_scene();
|
||||
if(!scene.is_valid() || !ClassDB::is_parent_class("Node3D", scene->get_state()->get_node_type(0)))
|
||||
return nullptr;
|
||||
Node3D *node = Object::cast_to<Node3D>(this->data->get_projectile_scene()->instantiate());
|
||||
IProjectile *projectile = dynamic_cast<IProjectile*>(node);
|
||||
if(projectile != nullptr) {
|
||||
projectile->set_weapon_data(this->data);
|
||||
} else {
|
||||
UtilityFunctions::push_warning("Projectile scene ", scene->get_path(), "' root node does not implement IProjectile");
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}
|
30
src/projectile_pool.hpp
Normal file
30
src/projectile_pool.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef PROJECTILE_POOL_HPP
|
||||
#define PROJECTILE_POOL_HPP
|
||||
|
||||
#include "weapon_data.hpp"
|
||||
#include <godot_cpp/classes/node3d.hpp>
|
||||
#include <godot_cpp/templates/vector.hpp>
|
||||
|
||||
namespace godot {
|
||||
class ProjectilePool : public Node {
|
||||
GDCLASS(ProjectilePool, Node);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
virtual void _exit_tree() override;
|
||||
void set_data(Ref<PackedScene> data);
|
||||
Ref<WeaponData> get_data() const;
|
||||
|
||||
Node3D *claim_projectile();
|
||||
void return_projectile(Node3D *node);
|
||||
|
||||
protected:
|
||||
Node3D *instantiate_new() const;
|
||||
private:
|
||||
Ref<WeaponData> data;
|
||||
size_t count;
|
||||
Vector<Node3D*> active{};
|
||||
Vector<Node3D*> inactive{};
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !PROJECTILE_POOL_HPP
|
Loading…
Reference in a new issue