gabeee3ee

Bulletspawner.cpp

Aug 8th, 2025
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.94 KB | Source Code | 0 0
  1. #include "bullet_spawner.h"
  2.  
  3. #include <cmath>
  4.  
  5. #include <godot_cpp/classes/node2d.hpp>
  6. #include <godot_cpp/core/class_db.hpp>
  7. #include <godot_cpp/variant/utility_functions.hpp>
  8. #include <godot_cpp/classes/engine.hpp>
  9. #include <godot_cpp/core/math.hpp>
  10.  
  11. using namespace godot;
  12.  
  13. BulletSpawner::BulletSpawner() {
  14.     // Constructor de la clase
  15.     // Se deja vacío porque las variables de miembro ya tienen valores por defecto
  16.     // o se inicializarán en el _ready()
  17. }
  18.  
  19. BulletSpawner::~BulletSpawner() {
  20.     // Destructor de la clase
  21.     // El Array bullet_pool y sus contenidos serán liberados automáticamente
  22.     // por el sistema de gestión de memoria de Godot.
  23. }
  24.  
  25. void BulletSpawner::_bind_methods() {
  26.     // Vinculación de propiedades de la clase para el editor de Godot
  27.     ClassDB::bind_method(D_METHOD("set_bullet_scene", "p_bullet_scene"), &BulletSpawner::set_bullet_scene);
  28.     ClassDB::bind_method(D_METHOD("get_bullet_scene"), &BulletSpawner::get_bullet_scene);
  29.     ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "bullet_scene", PROPERTY_HINT_RESOURCE_TYPE, "PackedScene"), "set_bullet_scene", "get_bullet_scene");
  30.  
  31.     ClassDB::bind_method(D_METHOD("set_pool_size", "p_pool_size"), &BulletSpawner::set_pool_size);
  32.     ClassDB::bind_method(D_METHOD("get_pool_size"), &BulletSpawner::get_pool_size);
  33.     ADD_PROPERTY(PropertyInfo(Variant::INT, "pool_size"), "set_pool_size", "get_pool_size");
  34.  
  35.     // Vinculación de las propiedades del patrón de disparo
  36.     ClassDB::bind_method(D_METHOD("set_angular_division", "p_angular_division"), &BulletSpawner::set_angular_division);
  37.     ClassDB::bind_method(D_METHOD("get_angular_division"), &BulletSpawner::get_angular_division);
  38.     ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_division"), "set_angular_division", "get_angular_division");
  39.    
  40.     ClassDB::bind_method(D_METHOD("set_speed", "p_speed"), &BulletSpawner::set_speed);
  41.     ClassDB::bind_method(D_METHOD("get_speed"), &BulletSpawner::get_speed);
  42.     ADD_PROPERTY(PropertyInfo(Variant::INT, "speed"), "set_speed", "get_speed");
  43.    
  44.     ClassDB::bind_method(D_METHOD("set_radio", "p_radio"), &BulletSpawner::set_radio);
  45.     ClassDB::bind_method(D_METHOD("get_radio"), &BulletSpawner::get_radio);
  46.     ADD_PROPERTY(PropertyInfo(Variant::INT, "radio"), "set_radio", "get_radio");
  47.  
  48.     ClassDB::bind_method(D_METHOD("set_rotation_speed", "p_rotation_speed"), &BulletSpawner::set_rotation_speed);
  49.     ClassDB::bind_method(D_METHOD("get_rotation_speed"), &BulletSpawner::get_rotation_speed);
  50.     ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation_speed"), "set_rotation_speed", "get_rotation_speed");
  51.    
  52.     ClassDB::bind_method(D_METHOD("set_invert_rotation", "p_invert_rotation"), &BulletSpawner::set_invert_rotation);
  53.     ClassDB::bind_method(D_METHOD("get_invert_rotation"), &BulletSpawner::get_invert_rotation);
  54.     ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_rotation"), "set_invert_rotation", "get_invert_rotation");
  55.    
  56.     ClassDB::bind_method(D_METHOD("set_bullet_creation_time", "p_time"), &BulletSpawner::set_bullet_creation_time);
  57.     ClassDB::bind_method(D_METHOD("get_bullet_creation_time"), &BulletSpawner::get_bullet_creation_time);
  58.     ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bullet_creation_time"), "set_bullet_creation_time", "get_bullet_creation_time");
  59.    
  60.     // Vinculación de los métodos de lógica de la clase
  61.     ClassDB::bind_method(D_METHOD("spawn_bullets"), &BulletSpawner::spawn_bullets);
  62.     ClassDB::bind_method(D_METHOD("recycle_bullet", "bullet_to_recycle"), &BulletSpawner::recycle_bullet);
  63.  
  64.     ClassDB::bind_method(D_METHOD("set_target_entity", "p_target_entity"), &BulletSpawner::set_target_entity);
  65.     ClassDB::bind_method(D_METHOD("get_target_entity"), &BulletSpawner::get_target_entity);
  66.     //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "target_entity", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), "set_target_entity", "get_target_entity");
  67.  
  68.     ClassDB::bind_method(D_METHOD("get_active_bullets"), &BulletSpawner::get_active_bullets);
  69. }
  70.  
  71. void BulletSpawner::_ready() {
  72.     // 2. Pre-instanciar todas las balas al inicio (Object Pooling)
  73.     bullets.reserve(pool_size);
  74.     for (int i = 0; i < pool_size; i++) {
  75.         Bullet* new_bullet = Object::cast_to<Bullet>(bullet_scene->instantiate());
  76.         bullet_pool.push(new_bullet);
  77.         bullets.emplace_back(new_bullet);
  78.         add_child(new_bullet);
  79.     }
  80.     active_bullets = 0;
  81.     UtilityFunctions::print("Piscina de balas de ", bullet_pool.size(), " objetos creada.");
  82.  
  83.     // 3. Lógica de inicialización del patrón de disparo (desde tu GDScript)
  84.     if (rotation_speed != 0.0f) {
  85.         rotation_speed_rad = (2 * Math_PI / rotation_speed);
  86.     }
  87.     if (invert_rotation) {
  88.         rotation_speed_rad *= -1.0f;
  89.     }
  90.    
  91.     // Angle between each bullet
  92.     angulo_div = (2 * Math_PI) / angular_division;
  93.  
  94.  
  95.     // Viewport dimensions for OOB checks
  96.     origin = get_position(); // not used
  97.     vp_rect = get_viewport()->get_visible_rect();
  98.     w = vp_rect.size.x;
  99.     h = vp_rect.size.y;
  100.    
  101. }
  102.  
  103. void BulletSpawner::_process(double delta) {
  104.     // Lógica de rotación del spawner
  105.     // Doesnt actually rotate the spawner, just the direction of the bullets
  106.     spawner_rotation += rotation_speed_rad * delta;
  107.  
  108.     // Gets the position of the player node for collisions
  109.     Vector2 target_entity_position = target_entity->get_global_position();
  110.     Variant result = target_entity->call("get_radio");
  111.     int target_entity_radio = result.operator int();
  112.  
  113.     // Iterates each bullet
  114.     for(const auto bullet : bullets)
  115.     {
  116.         if(!bullet->is_active()) continue;
  117.  
  118.         Vector2 pos = bullet->get_bullet_position();
  119.         Vector2 dir = bullet->get_direction_vector();
  120.  
  121.  
  122.         // Moves the bullet
  123.         pos.x += dir.x * delta;
  124.         pos.y += dir.y * delta;
  125.         bullet->set_bullet_position(pos);
  126.  
  127.         // Good old Pythagoras for collision detection
  128.         float dx = pos.x - target_entity_position.x;
  129.         float dy = pos.y - target_entity_position.y;
  130.         float distance = (dx * dx) + (dy * dy);
  131.         float combined_radios = radio + bullet->get_radio();
  132.         if(distance <= (combined_radios * combined_radios))
  133.             target_entity->call("die");
  134.  
  135.         // Checks out of bounds
  136.         if(pos.x >= 0 && pos.x <= w && pos.y >= 0 && pos.y <= h){;}
  137.         else recycle_bullet(bullet);
  138.     }
  139.  
  140.     // Lógica del temporizador de disparo
  141.     time_since_last_bullet += delta;
  142.     float diff = time_since_last_bullet - bullet_creation_time;
  143.     if (diff >= 0.0f) {
  144.         time_since_last_bullet = diff;
  145.         // UtilityFunctions::print("Spawning bullets at position: ", get_global_position());
  146.         spawn_bullets();
  147.     }
  148. }
  149.  
  150. void BulletSpawner::spawn_bullets() {
  151.     // Z_INDEX goes from -4096 to 4096, so to always draw in spawn order
  152.     // I manually manage that, leaving 1096 free for the rest of the scene.
  153.     if(z_index_count > 3000) z_index_count = -4096;
  154.     for (int i = 0; i < angular_division; i++) {
  155.         // Obtenemos una bala de la piscina
  156.         if(bullet_pool.empty()) {
  157.             UtilityFunctions::print("Error: No hay balas disponibles en la piscina.");
  158.             return;
  159.         }
  160.         active_bullets++;
  161.         //UtilityFunctions::print("Bullet #", i);
  162.         Bullet* new_bullet = bullet_pool.front();
  163.         bullet_pool.pop();
  164.  
  165.         // This gets the initial direction vector
  166.         float inc = angulo_div * i;
  167.         float x = std::cos(inc), y = std::sin(inc);
  168.  
  169.         // This rotates it if needed
  170.         float cosr = std::cos(spawner_rotation);
  171.         float sinr = std::sin(spawner_rotation);
  172.         Vector2 direction = Vector2((x * cosr) - (y * sinr),(x * sinr) + (y * cosr));
  173.  
  174.         new_bullet->initialize(get_global_position(), direction, radio, speed, z_index_count);
  175.         //UtilityFunctions::print("Spawned bullet at position: ", get_global_position(), " with direction: ", direction);
  176.     }
  177.     // All bullets in the same "batch" have the same z_index
  178.     z_index_count += 1;
  179. }
  180.  
  181. void BulletSpawner::recycle_bullet(Bullet* bullet_to_recycle) {
  182.     // Ocultar la bala y desactivar su procesamiento
  183.     bullet_to_recycle->disable();
  184.     bullet_pool.push(bullet_to_recycle);
  185.     active_bullets--;
  186. }
  187.  
  188. void BulletSpawner::set_target_entity(const CharacterBody2D *p_target) {
  189.     target_entity = const_cast<CharacterBody2D*>(p_target);
  190. }
  191.  
  192. Node2D* BulletSpawner::get_target_entity() const {
  193.     return target_entity;
  194. }
  195.  
  196. // Métodos set/get
  197. void BulletSpawner::set_bullet_scene(const Ref<PackedScene>& p_bullet_scene) {
  198.     bullet_scene = p_bullet_scene;
  199. }
  200.  
  201. Ref<PackedScene> BulletSpawner::get_bullet_scene() const {
  202.     return bullet_scene;
  203. }
  204.  
  205. void BulletSpawner::set_pool_size(int p_pool_size) {
  206.     pool_size = p_pool_size;
  207. }
  208.  
  209. int BulletSpawner::get_pool_size() const {
  210.     return pool_size;
  211. }
  212.  
  213. void BulletSpawner::set_angular_division(int p_angular_division) {
  214.     angular_division = p_angular_division;
  215. }
  216.  
  217. int BulletSpawner::get_angular_division() const {
  218.     return angular_division;
  219. }
  220.  
  221. void BulletSpawner::set_speed(int p_speed) {
  222.     speed = p_speed;
  223. }
  224.  
  225. int BulletSpawner::get_speed() const {
  226.     return speed;
  227. }
  228.  
  229. void BulletSpawner::set_radio(const int p_radio) {
  230.     radio = p_radio;
  231. }
  232.  
  233. int BulletSpawner::get_radio() const {
  234.     return radio;
  235. }
  236.  
  237. void BulletSpawner::set_rotation_speed(float p_rotation_speed) {
  238.     rotation_speed = p_rotation_speed;
  239. }
  240.  
  241. float BulletSpawner::get_rotation_speed() const {
  242.     return rotation_speed;
  243. }
  244.  
  245. void BulletSpawner::set_invert_rotation(bool p_invert_rotation) {
  246.     invert_rotation = p_invert_rotation;
  247. }
  248.  
  249. bool BulletSpawner::get_invert_rotation() const {
  250.     return invert_rotation;
  251. }
  252.  
  253. void BulletSpawner::set_bullet_creation_time(float p_time) {
  254.     bullet_creation_time = p_time;
  255. }
  256.  
  257. float BulletSpawner::get_bullet_creation_time() const {
  258.     return bullet_creation_time;
  259. }
  260.  
  261. int BulletSpawner::get_active_bullets() {
  262.     return active_bullets;
  263. }
Advertisement
Add Comment
Please, Sign In to add comment