gabeee3ee

BulletSpawner2.cpp

Aug 8th, 2025
249
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.22 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.  
  28.     ClassDB::bind_method(D_METHOD("set_bullet_texture", "p_bullet_texture"), &BulletSpawner::set_bullet_texture);
  29.     ClassDB::bind_method(D_METHOD("get_bullet_texture"), &BulletSpawner::get_bullet_texture);
  30.     ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "bullet_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_bullet_texture", "get_bullet_texture");
  31.  
  32.  
  33.     ClassDB::bind_method(D_METHOD("set_pool_size", "p_pool_size"), &BulletSpawner::set_pool_size);
  34.     ClassDB::bind_method(D_METHOD("get_pool_size"), &BulletSpawner::get_pool_size);
  35.     ADD_PROPERTY(PropertyInfo(Variant::INT, "pool_size"), "set_pool_size", "get_pool_size");
  36.  
  37.     // Vinculación de las propiedades del patrón de disparo
  38.     ClassDB::bind_method(D_METHOD("set_angular_division", "p_angular_division"), &BulletSpawner::set_angular_division);
  39.     ClassDB::bind_method(D_METHOD("get_angular_division"), &BulletSpawner::get_angular_division);
  40.     ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_division"), "set_angular_division", "get_angular_division");
  41.    
  42.     ClassDB::bind_method(D_METHOD("set_speed", "p_speed"), &BulletSpawner::set_speed);
  43.     ClassDB::bind_method(D_METHOD("get_speed"), &BulletSpawner::get_speed);
  44.     ADD_PROPERTY(PropertyInfo(Variant::INT, "speed"), "set_speed", "get_speed");
  45.    
  46.     ClassDB::bind_method(D_METHOD("set_radio", "p_radio"), &BulletSpawner::set_radio);
  47.     ClassDB::bind_method(D_METHOD("get_radio"), &BulletSpawner::get_radio);
  48.     ADD_PROPERTY(PropertyInfo(Variant::INT, "radio"), "set_radio", "get_radio");
  49.  
  50.     ClassDB::bind_method(D_METHOD("set_rotation_speed", "p_rotation_speed"), &BulletSpawner::set_rotation_speed);
  51.     ClassDB::bind_method(D_METHOD("get_rotation_speed"), &BulletSpawner::get_rotation_speed);
  52.     ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation_speed"), "set_rotation_speed", "get_rotation_speed");
  53.    
  54.     ClassDB::bind_method(D_METHOD("set_invert_rotation", "p_invert_rotation"), &BulletSpawner::set_invert_rotation);
  55.     ClassDB::bind_method(D_METHOD("get_invert_rotation"), &BulletSpawner::get_invert_rotation);
  56.     ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_rotation"), "set_invert_rotation", "get_invert_rotation");
  57.    
  58.     ClassDB::bind_method(D_METHOD("set_bullet_creation_time", "p_time"), &BulletSpawner::set_bullet_creation_time);
  59.     ClassDB::bind_method(D_METHOD("get_bullet_creation_time"), &BulletSpawner::get_bullet_creation_time);
  60.     ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bullet_creation_time"), "set_bullet_creation_time", "get_bullet_creation_time");
  61.    
  62.     // Vinculación de los métodos de lógica de la clase
  63.     ClassDB::bind_method(D_METHOD("spawn_bullets"), &BulletSpawner::spawn_bullets);
  64.     //ClassDB::bind_method(D_METHOD("recycle_bullet", "bullet_to_recycle"), &BulletSpawner::recycle_bullet);
  65.  
  66.     ClassDB::bind_method(D_METHOD("set_target_entity", "p_target_entity"), &BulletSpawner::set_target_entity);
  67.     ClassDB::bind_method(D_METHOD("get_target_entity"), &BulletSpawner::get_target_entity);
  68.     //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "target_entity", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), "set_target_entity", "get_target_entity");
  69.  
  70.     ClassDB::bind_method(D_METHOD("get_active_bullets"), &BulletSpawner::get_active_bullets);
  71.  
  72.     ClassDB::bind_method(D_METHOD("recycle_bullet", "bullet_index"), &BulletSpawner::recycle_bullet);
  73.     ClassDB::bind_method(D_METHOD("set_texture_scale", "p_scale"), &BulletSpawner::set_texture_scale);
  74.     ClassDB::bind_method(D_METHOD("get_texture_scale"), &BulletSpawner::get_texture_scale);
  75.     ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texture_scale"), "set_texture_scale", "get_texture_scale");
  76. }
  77.  
  78. void BulletSpawner::_ready() {
  79.     // 2. Pre-instanciar todas las balas al inicio (Object Pooling)
  80.     bullets.resize(pool_size);
  81.     for (int i = 0; i < pool_size; i++) {
  82.         bullet_pool.push(i);
  83.     }
  84.     active_bullets = 0;
  85.     UtilityFunctions::print("Piscina de balas de ", bullet_pool.size(), " objetos creada.");
  86.  
  87.     // 3. Lógica de inicialización del patrón de disparo (desde tu GDScript)
  88.     if (rotation_speed != 0.0f) {
  89.         rotation_speed_rad = (2 * Math_PI / rotation_speed);
  90.     }
  91.     if (invert_rotation) {
  92.         rotation_speed_rad *= -1.0f;
  93.     }
  94.    
  95.     // Angle between each bullet
  96.     angulo_div = (2 * Math_PI) / angular_division;
  97.  
  98.  
  99.     // Viewport dimensions for OOB checks
  100.     origin = get_position(); // not used
  101.     vp_rect = get_viewport()->get_visible_rect();
  102.     w = vp_rect.size.x;
  103.     h = vp_rect.size.y;
  104.  
  105.     rs = RenderingServer::get_singleton();
  106.     canvas = get_canvas_item(); // Usar get_canvas_item() en lugar de get_canvas()
  107.     texture_size = bullet_texture->get_size() * texture_scale;
  108.    
  109. }
  110.  
  111. void::BulletSpawner::_draw() {
  112.     for (const auto &bullet : bullets) {
  113.         if (bullet.active) {
  114.             rs->canvas_item_add_texture_rect(
  115.                 canvas,
  116.                 Rect2(bullet.position - get_position() - texture_size / 2.0, texture_size),
  117.                 bullet_texture_rid
  118.             );
  119.         }
  120.     }
  121. }
  122.  
  123. void BulletSpawner::_process(double delta) {
  124.     // Lógica de rotación del spawner
  125.     // Doesnt actually rotate the spawner, just the direction of the bullets
  126.     spawner_rotation += rotation_speed_rad * delta;
  127.  
  128.     // Gets the position of the player node for collisions
  129.     Vector2 target_entity_position = target_entity->get_global_position();
  130.     Variant result = target_entity->call("get_radio");
  131.     int target_entity_radio = result.operator int();
  132.  
  133.     // Iterates each bullet
  134.     for(int i = 0; i < pool_size; i++)
  135.     {
  136.         Bullet &bullet = bullets[i];
  137.         if(!bullet.active) continue;
  138.  
  139.         Vector2 pos = bullet.position;
  140.         Vector2 dir = bullet.direction_vector;
  141.  
  142.  
  143.         // Moves the bullet
  144.         pos.x += dir.x * delta;
  145.         pos.y += dir.y * delta;
  146.         bullet.position = pos;
  147.  
  148.         // Good old Pythagoras for collision detection
  149.         float dx = pos.x - target_entity_position.x;
  150.         float dy = pos.y - target_entity_position.y;
  151.         float distance = (dx * dx) + (dy * dy);
  152.         float combined_radios = radio + bullet.radio;
  153.         if(distance <= (combined_radios * combined_radios))
  154.             target_entity->call("die");
  155.  
  156.         // Checks out of bounds
  157.         if(pos.x >= 0 && pos.x <= w && pos.y >= 0 && pos.y <= h){;}
  158.         else recycle_bullet(i);
  159.     }
  160.  
  161.     // Lógica del temporizador de disparo
  162.     time_since_last_bullet += delta;
  163.     float diff = time_since_last_bullet - bullet_creation_time;
  164.     if (diff >= 0.0f) {
  165.         time_since_last_bullet = diff;
  166.         // UtilityFunctions::print("Spawning bullets at position: ", get_global_position());
  167.         spawn_bullets();
  168.     }
  169.     queue_redraw();
  170. }
  171.  
  172. void BulletSpawner::spawn_bullets() {
  173.     // Z_INDEX goes from -4096 to 4096, so to always draw in spawn order
  174.     // I manually manage that, leaving 1096 free for the rest of the scene.
  175.     if(z_index_count > 3000) z_index_count = -4096;
  176.     for (int i = 0; i < angular_division; i++) {
  177.         // Obtenemos una bala de la piscina
  178.         if(bullet_pool.empty()) {
  179.             UtilityFunctions::print("Error: No hay balas disponibles en la piscina.");
  180.             return;
  181.         }
  182.         active_bullets++;
  183.         //UtilityFunctions::print("Bullet #", i);
  184.         Bullet &new_bullet = bullets[bullet_pool.front()];
  185.         bullet_pool.pop();
  186.  
  187.         // This gets the initial direction vector
  188.         float inc = angulo_div * i;
  189.         float x = std::cos(inc), y = std::sin(inc);
  190.  
  191.         // This rotates it if needed
  192.         float cosr = std::cos(spawner_rotation);
  193.         float sinr = std::sin(spawner_rotation);
  194.         Vector2 direction = Vector2((x * cosr) - (y * sinr),(x * sinr) + (y * cosr));
  195.  
  196.         new_bullet.position = get_global_position();
  197.         new_bullet.direction_vector = direction * speed;;
  198.         new_bullet.radio = radio;
  199.         new_bullet.speed = speed;
  200.         new_bullet.active = true;
  201.         new_bullet.z_index = z_index_count;
  202.         //UtilityFunctions::print("Spawned bullet at position: ", get_global_position(), " with direction: ", direction);
  203.     }
  204.     // All bullets in the same "batch" have the same z_index
  205.     z_index_count += 1;
  206. }
  207.  
  208. void BulletSpawner::recycle_bullet(int bullet_index) {
  209.     // Ocultar la bala y desactivar su procesamiento
  210.     //bullet_to_recycle->disable();
  211.     bullets[bullet_index].active = false;
  212.     bullet_pool.push(bullet_index);
  213.     active_bullets--;
  214. }
  215.  
  216. void BulletSpawner::set_bullet_texture(const Ref<Texture2D>& p_bullet_texture) {
  217.     bullet_texture = p_bullet_texture;
  218.     if (bullet_texture.is_valid()) {
  219.         bullet_texture_rid = bullet_texture->get_rid();
  220.     } else {
  221.         bullet_texture_rid = RID();
  222.     }
  223. }
  224.  
  225. Ref<Texture2D> BulletSpawner::get_bullet_texture() const {
  226.     return bullet_texture;
  227. }
  228. void BulletSpawner::set_texture_scale(float p_scale) {
  229.     texture_scale = p_scale;
  230. }
  231.  
  232. float BulletSpawner::get_texture_scale() const {
  233.     return texture_scale;
  234. }
  235.  
  236. void BulletSpawner::set_target_entity(const Node2D *p_target) {
  237.     target_entity = const_cast<Node2D*>(p_target);
  238. }
  239.  
  240. Node2D* BulletSpawner::get_target_entity() const {
  241.     return target_entity;
  242. }
  243.  
  244.  
  245. void BulletSpawner::set_pool_size(int p_pool_size) {
  246.     pool_size = p_pool_size;
  247. }
  248.  
  249. int BulletSpawner::get_pool_size() const {
  250.     return pool_size;
  251. }
  252.  
  253. void BulletSpawner::set_angular_division(int p_angular_division) {
  254.     angular_division = p_angular_division;
  255. }
  256.  
  257. int BulletSpawner::get_angular_division() const {
  258.     return angular_division;
  259. }
  260.  
  261. void BulletSpawner::set_speed(int p_speed) {
  262.     speed = p_speed;
  263. }
  264.  
  265. int BulletSpawner::get_speed() const {
  266.     return speed;
  267. }
  268.  
  269. void BulletSpawner::set_radio(const int p_radio) {
  270.     radio = p_radio;
  271. }
  272.  
  273. int BulletSpawner::get_radio() const {
  274.     return radio;
  275. }
  276.  
  277. void BulletSpawner::set_rotation_speed(float p_rotation_speed) {
  278.     rotation_speed = p_rotation_speed;
  279. }
  280.  
  281. float BulletSpawner::get_rotation_speed() const {
  282.     return rotation_speed;
  283. }
  284.  
  285. void BulletSpawner::set_invert_rotation(bool p_invert_rotation) {
  286.     invert_rotation = p_invert_rotation;
  287. }
  288.  
  289. bool BulletSpawner::get_invert_rotation() const {
  290.     return invert_rotation;
  291. }
  292.  
  293. void BulletSpawner::set_bullet_creation_time(float p_time) {
  294.     bullet_creation_time = p_time;
  295. }
  296.  
  297. float BulletSpawner::get_bullet_creation_time() const {
  298.     return bullet_creation_time;
  299. }
  300.  
  301. int BulletSpawner::get_active_bullets() {
  302.     return active_bullets;
  303. }
Advertisement
Add Comment
Please, Sign In to add comment