Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "bullet_spawner.h"
- #include <cmath>
- #include <godot_cpp/classes/node2d.hpp>
- #include <godot_cpp/core/class_db.hpp>
- #include <godot_cpp/variant/utility_functions.hpp>
- #include <godot_cpp/classes/engine.hpp>
- #include <godot_cpp/core/math.hpp>
- using namespace godot;
- BulletSpawner::BulletSpawner() {
- // Constructor de la clase
- // Se deja vacío porque las variables de miembro ya tienen valores por defecto
- // o se inicializarán en el _ready()
- }
- BulletSpawner::~BulletSpawner() {
- // Destructor de la clase
- // El Array bullet_pool y sus contenidos serán liberados automáticamente
- // por el sistema de gestión de memoria de Godot.
- }
- void BulletSpawner::_bind_methods() {
- // Vinculación de propiedades de la clase para el editor de Godot
- ClassDB::bind_method(D_METHOD("set_bullet_scene", "p_bullet_scene"), &BulletSpawner::set_bullet_scene);
- ClassDB::bind_method(D_METHOD("get_bullet_scene"), &BulletSpawner::get_bullet_scene);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "bullet_scene", PROPERTY_HINT_RESOURCE_TYPE, "PackedScene"), "set_bullet_scene", "get_bullet_scene");
- ClassDB::bind_method(D_METHOD("set_pool_size", "p_pool_size"), &BulletSpawner::set_pool_size);
- ClassDB::bind_method(D_METHOD("get_pool_size"), &BulletSpawner::get_pool_size);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "pool_size"), "set_pool_size", "get_pool_size");
- // Vinculación de las propiedades del patrón de disparo
- ClassDB::bind_method(D_METHOD("set_angular_division", "p_angular_division"), &BulletSpawner::set_angular_division);
- ClassDB::bind_method(D_METHOD("get_angular_division"), &BulletSpawner::get_angular_division);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_division"), "set_angular_division", "get_angular_division");
- ClassDB::bind_method(D_METHOD("set_speed", "p_speed"), &BulletSpawner::set_speed);
- ClassDB::bind_method(D_METHOD("get_speed"), &BulletSpawner::get_speed);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "speed"), "set_speed", "get_speed");
- ClassDB::bind_method(D_METHOD("set_radio", "p_radio"), &BulletSpawner::set_radio);
- ClassDB::bind_method(D_METHOD("get_radio"), &BulletSpawner::get_radio);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "radio"), "set_radio", "get_radio");
- ClassDB::bind_method(D_METHOD("set_rotation_speed", "p_rotation_speed"), &BulletSpawner::set_rotation_speed);
- ClassDB::bind_method(D_METHOD("get_rotation_speed"), &BulletSpawner::get_rotation_speed);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation_speed"), "set_rotation_speed", "get_rotation_speed");
- ClassDB::bind_method(D_METHOD("set_invert_rotation", "p_invert_rotation"), &BulletSpawner::set_invert_rotation);
- ClassDB::bind_method(D_METHOD("get_invert_rotation"), &BulletSpawner::get_invert_rotation);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_rotation"), "set_invert_rotation", "get_invert_rotation");
- ClassDB::bind_method(D_METHOD("set_bullet_creation_time", "p_time"), &BulletSpawner::set_bullet_creation_time);
- ClassDB::bind_method(D_METHOD("get_bullet_creation_time"), &BulletSpawner::get_bullet_creation_time);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bullet_creation_time"), "set_bullet_creation_time", "get_bullet_creation_time");
- // Vinculación de los métodos de lógica de la clase
- ClassDB::bind_method(D_METHOD("spawn_bullets"), &BulletSpawner::spawn_bullets);
- ClassDB::bind_method(D_METHOD("recycle_bullet", "bullet_to_recycle"), &BulletSpawner::recycle_bullet);
- ClassDB::bind_method(D_METHOD("set_target_entity", "p_target_entity"), &BulletSpawner::set_target_entity);
- ClassDB::bind_method(D_METHOD("get_target_entity"), &BulletSpawner::get_target_entity);
- //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "target_entity", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), "set_target_entity", "get_target_entity");
- ClassDB::bind_method(D_METHOD("get_active_bullets"), &BulletSpawner::get_active_bullets);
- }
- void BulletSpawner::_ready() {
- // 2. Pre-instanciar todas las balas al inicio (Object Pooling)
- bullets.reserve(pool_size);
- for (int i = 0; i < pool_size; i++) {
- Bullet* new_bullet = Object::cast_to<Bullet>(bullet_scene->instantiate());
- bullet_pool.push(new_bullet);
- bullets.emplace_back(new_bullet);
- add_child(new_bullet);
- }
- active_bullets = 0;
- UtilityFunctions::print("Piscina de balas de ", bullet_pool.size(), " objetos creada.");
- // 3. Lógica de inicialización del patrón de disparo (desde tu GDScript)
- if (rotation_speed != 0.0f) {
- rotation_speed_rad = (2 * Math_PI / rotation_speed);
- }
- if (invert_rotation) {
- rotation_speed_rad *= -1.0f;
- }
- // Angle between each bullet
- angulo_div = (2 * Math_PI) / angular_division;
- // Viewport dimensions for OOB checks
- origin = get_position(); // not used
- vp_rect = get_viewport()->get_visible_rect();
- w = vp_rect.size.x;
- h = vp_rect.size.y;
- }
- void BulletSpawner::_process(double delta) {
- // Lógica de rotación del spawner
- // Doesnt actually rotate the spawner, just the direction of the bullets
- spawner_rotation += rotation_speed_rad * delta;
- // Gets the position of the player node for collisions
- Vector2 target_entity_position = target_entity->get_global_position();
- Variant result = target_entity->call("get_radio");
- int target_entity_radio = result.operator int();
- // Iterates each bullet
- for(const auto bullet : bullets)
- {
- if(!bullet->is_active()) continue;
- Vector2 pos = bullet->get_bullet_position();
- Vector2 dir = bullet->get_direction_vector();
- // Moves the bullet
- pos.x += dir.x * delta;
- pos.y += dir.y * delta;
- bullet->set_bullet_position(pos);
- // Good old Pythagoras for collision detection
- float dx = pos.x - target_entity_position.x;
- float dy = pos.y - target_entity_position.y;
- float distance = (dx * dx) + (dy * dy);
- float combined_radios = radio + bullet->get_radio();
- if(distance <= (combined_radios * combined_radios))
- target_entity->call("die");
- // Checks out of bounds
- if(pos.x >= 0 && pos.x <= w && pos.y >= 0 && pos.y <= h){;}
- else recycle_bullet(bullet);
- }
- // Lógica del temporizador de disparo
- time_since_last_bullet += delta;
- float diff = time_since_last_bullet - bullet_creation_time;
- if (diff >= 0.0f) {
- time_since_last_bullet = diff;
- // UtilityFunctions::print("Spawning bullets at position: ", get_global_position());
- spawn_bullets();
- }
- }
- void BulletSpawner::spawn_bullets() {
- // Z_INDEX goes from -4096 to 4096, so to always draw in spawn order
- // I manually manage that, leaving 1096 free for the rest of the scene.
- if(z_index_count > 3000) z_index_count = -4096;
- for (int i = 0; i < angular_division; i++) {
- // Obtenemos una bala de la piscina
- if(bullet_pool.empty()) {
- UtilityFunctions::print("Error: No hay balas disponibles en la piscina.");
- return;
- }
- active_bullets++;
- //UtilityFunctions::print("Bullet #", i);
- Bullet* new_bullet = bullet_pool.front();
- bullet_pool.pop();
- // This gets the initial direction vector
- float inc = angulo_div * i;
- float x = std::cos(inc), y = std::sin(inc);
- // This rotates it if needed
- float cosr = std::cos(spawner_rotation);
- float sinr = std::sin(spawner_rotation);
- Vector2 direction = Vector2((x * cosr) - (y * sinr),(x * sinr) + (y * cosr));
- new_bullet->initialize(get_global_position(), direction, radio, speed, z_index_count);
- //UtilityFunctions::print("Spawned bullet at position: ", get_global_position(), " with direction: ", direction);
- }
- // All bullets in the same "batch" have the same z_index
- z_index_count += 1;
- }
- void BulletSpawner::recycle_bullet(Bullet* bullet_to_recycle) {
- // Ocultar la bala y desactivar su procesamiento
- bullet_to_recycle->disable();
- bullet_pool.push(bullet_to_recycle);
- active_bullets--;
- }
- void BulletSpawner::set_target_entity(const CharacterBody2D *p_target) {
- target_entity = const_cast<CharacterBody2D*>(p_target);
- }
- Node2D* BulletSpawner::get_target_entity() const {
- return target_entity;
- }
- // Métodos set/get
- void BulletSpawner::set_bullet_scene(const Ref<PackedScene>& p_bullet_scene) {
- bullet_scene = p_bullet_scene;
- }
- Ref<PackedScene> BulletSpawner::get_bullet_scene() const {
- return bullet_scene;
- }
- void BulletSpawner::set_pool_size(int p_pool_size) {
- pool_size = p_pool_size;
- }
- int BulletSpawner::get_pool_size() const {
- return pool_size;
- }
- void BulletSpawner::set_angular_division(int p_angular_division) {
- angular_division = p_angular_division;
- }
- int BulletSpawner::get_angular_division() const {
- return angular_division;
- }
- void BulletSpawner::set_speed(int p_speed) {
- speed = p_speed;
- }
- int BulletSpawner::get_speed() const {
- return speed;
- }
- void BulletSpawner::set_radio(const int p_radio) {
- radio = p_radio;
- }
- int BulletSpawner::get_radio() const {
- return radio;
- }
- void BulletSpawner::set_rotation_speed(float p_rotation_speed) {
- rotation_speed = p_rotation_speed;
- }
- float BulletSpawner::get_rotation_speed() const {
- return rotation_speed;
- }
- void BulletSpawner::set_invert_rotation(bool p_invert_rotation) {
- invert_rotation = p_invert_rotation;
- }
- bool BulletSpawner::get_invert_rotation() const {
- return invert_rotation;
- }
- void BulletSpawner::set_bullet_creation_time(float p_time) {
- bullet_creation_time = p_time;
- }
- float BulletSpawner::get_bullet_creation_time() const {
- return bullet_creation_time;
- }
- int BulletSpawner::get_active_bullets() {
- return active_bullets;
- }
Advertisement
Add Comment
Please, Sign In to add comment