diff --git a/data/config/balloon_formations.txt b/data/config/balloon_formations.txt new file mode 100644 index 0000000..cdf0078 --- /dev/null +++ b/data/config/balloon_formations.txt @@ -0,0 +1,277 @@ +# Archivo de configuración de formaciones de globos +# Formato por línea: x, y, vel_x, tipo, tamaño, tiempo_creacion +# Variables disponibles: +# X1_0, X1_50, X1_100, X2_0, X2_100, X3_0, X3_100, X4_0, X4_100 +# QUARTER1_X4, QUARTER3_X4, Y_BASE +# BALLOON_SIZE_0, BALLOON_SIZE_1, BALLOON_SIZE_2, BALLOON_SIZE_3 +# VEL_POSITIVE, VEL_NEGATIVE + +formation: 0 +# Dos enemigos BALLOON4 uno a cada extremo +X4_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE4, 300 +X4_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE4, 300 + +formation: 1 +# Dos enemigos BALLOON4 uno a cada cuarto. Ambos van hacia el centro +QUARTER1_X4, Y_BASE, VEL_POSITIVE, BALLOON, SIZE4, 300 +QUARTER3_X4, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE4, 300 + +formation: 2 +# Cuatro enemigos BALLOON2 uno detrás del otro. A la izquierda y hacia el centro +X2_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 300 +X2_0 + BALLOON_SIZE_1 + 1, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 290 +X2_0 + (BALLOON_SIZE_1 + 1) * 2, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 280 +X2_0 + (BALLOON_SIZE_1 + 1) * 3, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 270 + +formation: 3 +# Cuatro enemigos BALLOON2 uno detrás del otro. A la derecha y hacia el centro +X2_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 300 +X2_100 - BALLOON_SIZE_1 - 1, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 290 +X2_100 - (BALLOON_SIZE_1 + 1) * 2, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 280 +X2_100 - (BALLOON_SIZE_1 + 1) * 3, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 270 + +formation: 4 +# Tres enemigos BALLOON3. 0, 25, 50. Hacia la derecha +X3_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 300 +X3_0 + BALLOON_SIZE_2 * 2, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 290 +X3_0 + BALLOON_SIZE_2 * 4, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 280 + +formation: 5 +# Tres enemigos BALLOON3. 50, 75, 100. Hacia la izquierda +X3_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 300 +X3_100 - BALLOON_SIZE_2 * 2, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 290 +X3_100 - BALLOON_SIZE_2 * 4, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 280 + +formation: 6 +# Tres enemigos BALLOON3. 0, 0, 0. Hacia la derecha +X3_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 300 +X3_0 + BALLOON_SIZE_2 + 1, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 290 +X3_0 + (BALLOON_SIZE_2 + 1) * 2, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 280 + +formation: 7 +# Tres enemigos BALLOON3. 100, 100, 100. Hacia la izquierda +X3_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 300 +X3_100 - BALLOON_SIZE_2 - 1, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 290 +X3_100 - (BALLOON_SIZE_2 + 1) * 2, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 280 + +formation: 8 +# Seis enemigos BALLOON1. 0, 0, 0, 0, 0, 0. Hacia la derecha +X1_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 300 +X1_0 + BALLOON_SIZE_0 + 1, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 290 +X1_0 + (BALLOON_SIZE_0 + 1) * 2, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 280 +X1_0 + (BALLOON_SIZE_0 + 1) * 3, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 270 +X1_0 + (BALLOON_SIZE_0 + 1) * 4, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 260 +X1_0 + (BALLOON_SIZE_0 + 1) * 5, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 250 + +formation: 9 +# Seis enemigos BALLOON1. 100, 100, 100, 100, 100, 100. Hacia la izquierda +X1_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 300 +X1_100 - BALLOON_SIZE_0 - 1, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 290 +X1_100 - (BALLOON_SIZE_0 + 1) * 2, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 280 +X1_100 - (BALLOON_SIZE_0 + 1) * 3, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 270 +X1_100 - (BALLOON_SIZE_0 + 1) * 4, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 260 +X1_100 - (BALLOON_SIZE_0 + 1) * 5, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 250 + +formation: 10 +# Tres enemigos BALLOON4 seguidos desde la izquierda. Hacia la derecha +X4_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE4, 300 +X4_0 + BALLOON_SIZE_3 + 1, Y_BASE, VEL_POSITIVE, BALLOON, SIZE4, 285 +X4_0 + (BALLOON_SIZE_3 + 1) * 2, Y_BASE, VEL_POSITIVE, BALLOON, SIZE4, 270 + +formation: 11 +# Tres enemigos BALLOON4 seguidos desde la derecha. Hacia la izquierda +X4_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE4, 300 +X4_100 - BALLOON_SIZE_3 - 1, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE4, 285 +X4_100 - (BALLOON_SIZE_3 + 1) * 2, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE4, 270 + +formation: 12 +# Seis enemigos BALLOON2 uno detrás del otro. A la izquierda y hacia el centro +X2_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 300 +X2_0 + BALLOON_SIZE_1 + 1, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 290 +X2_0 + (BALLOON_SIZE_1 + 1) * 2, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 280 +X2_0 + (BALLOON_SIZE_1 + 1) * 3, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 270 +X2_0 + (BALLOON_SIZE_1 + 1) * 4, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 260 +X2_0 + (BALLOON_SIZE_1 + 1) * 5, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 250 + +formation: 13 +# Seis enemigos BALLOON2 uno detrás del otro. A la derecha y hacia el centro +X2_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 300 +X2_100 - BALLOON_SIZE_1 - 1, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 290 +X2_100 - (BALLOON_SIZE_1 + 1) * 2, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 280 +X2_100 - (BALLOON_SIZE_1 + 1) * 3, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 270 +X2_100 - (BALLOON_SIZE_1 + 1) * 4, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 260 +X2_100 - (BALLOON_SIZE_1 + 1) * 5, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 250 + +formation: 14 +# Cinco enemigos BALLOON3. Hacia la derecha. Separados +X3_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 300 +X3_0 + BALLOON_SIZE_2 * 2, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 290 +X3_0 + BALLOON_SIZE_2 * 4, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 280 +X3_0 + BALLOON_SIZE_2 * 6, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 270 +X3_0 + BALLOON_SIZE_2 * 8, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 260 + +formation: 15 +# Cinco enemigos BALLOON3. Hacia la izquierda. Separados +X3_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 300 +X3_100 - BALLOON_SIZE_2 * 2, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 290 +X3_100 - BALLOON_SIZE_2 * 4, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 280 +X3_100 - BALLOON_SIZE_2 * 6, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 270 +X3_100 - BALLOON_SIZE_2 * 8, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 260 + +formation: 16 +# Cinco enemigos BALLOON3. Hacia la derecha. Juntos +X3_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 300 +X3_0 + BALLOON_SIZE_2 + 1, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 290 +X3_0 + (BALLOON_SIZE_2 + 1) * 2, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 280 +X3_0 + (BALLOON_SIZE_2 + 1) * 3, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 270 +X3_0 + (BALLOON_SIZE_2 + 1) * 4, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 260 + +formation: 17 +# Cinco enemigos BALLOON3. Hacia la izquierda. Juntos +X3_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 300 +X3_100 - BALLOON_SIZE_2 - 1, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 290 +X3_100 - (BALLOON_SIZE_2 + 1) * 2, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 280 +X3_100 - (BALLOON_SIZE_2 + 1) * 3, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 270 +X3_100 - (BALLOON_SIZE_2 + 1) * 4, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 260 + +formation: 18 +# Doce enemigos BALLOON1. Hacia la derecha. Juntos +X1_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 300 +X1_0 + BALLOON_SIZE_0 + 1, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 290 +X1_0 + (BALLOON_SIZE_0 + 1) * 2, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 280 +X1_0 + (BALLOON_SIZE_0 + 1) * 3, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 270 +X1_0 + (BALLOON_SIZE_0 + 1) * 4, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 260 +X1_0 + (BALLOON_SIZE_0 + 1) * 5, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 250 +X1_0 + (BALLOON_SIZE_0 + 1) * 6, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 240 +X1_0 + (BALLOON_SIZE_0 + 1) * 7, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 230 +X1_0 + (BALLOON_SIZE_0 + 1) * 8, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 220 +X1_0 + (BALLOON_SIZE_0 + 1) * 9, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 210 +X1_0 + (BALLOON_SIZE_0 + 1) * 10, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 200 +X1_0 + (BALLOON_SIZE_0 + 1) * 11, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 190 + +formation: 19 +# Doce enemigos BALLOON1. Hacia la izquierda. Juntos +X1_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 300 +X1_100 - BALLOON_SIZE_0 - 1, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 290 +X1_100 - (BALLOON_SIZE_0 + 1) * 2, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 280 +X1_100 - (BALLOON_SIZE_0 + 1) * 3, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 270 +X1_100 - (BALLOON_SIZE_0 + 1) * 4, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 260 +X1_100 - (BALLOON_SIZE_0 + 1) * 5, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 250 +X1_100 - (BALLOON_SIZE_0 + 1) * 6, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 240 +X1_100 - (BALLOON_SIZE_0 + 1) * 7, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 230 +X1_100 - (BALLOON_SIZE_0 + 1) * 8, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 220 +X1_100 - (BALLOON_SIZE_0 + 1) * 9, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 210 +X1_100 - (BALLOON_SIZE_0 + 1) * 10, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 200 +X1_100 - (BALLOON_SIZE_0 + 1) * 11, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 190 + +formation: 20 +# Cuatro enemigos BALLOON4 seguidos desde la izquierda/derecha. Simétricos +X4_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE4, 300 +X4_0 + BALLOON_SIZE_3 + 1, Y_BASE, VEL_POSITIVE, BALLOON, SIZE4, 300 +X4_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE4, 300 +X4_100 - BALLOON_SIZE_3 - 1, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE4, 300 + +formation: 21 +# Diez enemigos BALLOON2 uno detrás del otro. Izquierda/derecha. Simétricos +X2_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 300 +X2_0 + BALLOON_SIZE_1 + 1, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 297 +X2_0 + (BALLOON_SIZE_1 + 1) * 2, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 294 +X2_0 + (BALLOON_SIZE_1 + 1) * 3, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 291 +X2_0 + (BALLOON_SIZE_1 + 1) * 4, Y_BASE, VEL_POSITIVE, BALLOON, SIZE2, 288 +X2_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 300 +X2_100 - BALLOON_SIZE_1 - 1, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 297 +X2_100 - (BALLOON_SIZE_1 + 1) * 2, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 294 +X2_100 - (BALLOON_SIZE_1 + 1) * 3, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 291 +X2_100 - (BALLOON_SIZE_1 + 1) * 4, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE2, 288 + +formation: 22 +# Diez enemigos BALLOON3. Hacia la derecha/izquierda. Separados. Simétricos +X3_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 300 +X3_0 + BALLOON_SIZE_2 * 2, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 290 +X3_0 + BALLOON_SIZE_2 * 4, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 280 +X3_0 + BALLOON_SIZE_2 * 6, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 270 +X3_0 + BALLOON_SIZE_2 * 8, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 260 +X3_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 300 +X3_100 - BALLOON_SIZE_2 * 2, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 290 +X3_100 - BALLOON_SIZE_2 * 4, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 280 +X3_100 - BALLOON_SIZE_2 * 6, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 270 +X3_100 - BALLOON_SIZE_2 * 8, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 260 + +formation: 23 +# Diez enemigos BALLOON3. Hacia la derecha. Juntos. Simétricos +X3_0, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 300 +X3_0 + BALLOON_SIZE_2 + 1, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 290 +X3_0 + (BALLOON_SIZE_2 + 1) * 2, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 280 +X3_0 + (BALLOON_SIZE_2 + 1) * 3, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 270 +X3_0 + (BALLOON_SIZE_2 + 1) * 4, Y_BASE, VEL_POSITIVE, BALLOON, SIZE3, 260 +X3_100, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 300 +X3_100 - BALLOON_SIZE_2 - 1, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 290 +X3_100 - (BALLOON_SIZE_2 + 1) * 2, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 280 +X3_100 - (BALLOON_SIZE_2 + 1) * 3, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 270 +X3_100 - (BALLOON_SIZE_2 + 1) * 4, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE3, 260 + +formation: 24 +# Treinta enemigos BALLOON1. Del centro hacia los extremos. Juntos. Simétricos +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 300 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 305 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 310 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 315 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 320 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 325 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 330 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 335 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 340 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 345 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 350 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 355 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 300 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 305 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 310 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 315 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 320 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 325 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 330 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 335 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 340 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 345 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 350 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 355 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 360 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 360 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 365 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 365 +X1_50, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 370 +X1_50, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 370 + +formation: 25 +# Treinta enemigos BALLOON1. Del centro hacia adentro. Juntos. Simétricos +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 300 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 295 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 290 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 285 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 280 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 275 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 270 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 265 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 260 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 255 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 250 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 245 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 300 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 295 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 290 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 285 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 280 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 275 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 270 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 265 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 260 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 255 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 250 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 245 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 240 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 240 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 235 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 235 +X1_50 + 20, Y_BASE, VEL_NEGATIVE, BALLOON, SIZE1, 230 +X1_50 - 20, Y_BASE, VEL_POSITIVE, BALLOON, SIZE1, 230 diff --git a/source/balloon_formations.cpp b/source/balloon_formations.cpp index a380508..3808953 100644 --- a/source/balloon_formations.cpp +++ b/source/balloon_formations.cpp @@ -1,335 +1,256 @@ -#include "balloon_formations.h" - -#include // Para array - +#include "asset.h" #include "balloon.h" // Para BalloonType, BalloonSize, BALLOON_SIZE, BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE -#include "param.h" // Para Param, ParamGame, param -#include "utils.h" // Para Zone, BLOCK +#include "balloon_formations.h" +#include "param.h" // Para Param, ParamGame, param +#include "utils.h" // Para Zone, BLOCK +#include // Para array +#include +#include +#include +#include void BalloonFormations::initBalloonFormations() { - constexpr int Y4 = -BLOCK; + // Calcular posiciones base + constexpr int Y_BASE = -BLOCK; + const int X4_0 = param.game.play_area.rect.x; const int X4_100 = param.game.play_area.rect.w - BALLOON_SIZE[3]; - - constexpr int Y3 = -BLOCK; const int X3_0 = param.game.play_area.rect.x; const int X3_100 = param.game.play_area.rect.w - BALLOON_SIZE[2]; - - constexpr int Y2 = -BLOCK; const int X2_0 = param.game.play_area.rect.x; const int X2_100 = param.game.play_area.rect.w - BALLOON_SIZE[1]; - - constexpr int Y1 = -BLOCK; const int X1_0 = param.game.play_area.rect.x; const int X1_50 = param.game.play_area.center_x - (BALLOON_SIZE[0] / 2); const int X1_100 = param.game.play_area.rect.w - BALLOON_SIZE[0]; + // Variables calculadas para posiciones especiales + const int QUARTER1_X4 = param.game.play_area.first_quarter_x - (BALLOON_SIZE[3] / 2); + const int QUARTER3_X4 = param.game.play_area.third_quarter_x - (BALLOON_SIZE[3] / 2); + + // Mapa de variables para reemplazar en el archivo + std::map variables = { + {"X1_0", X1_0}, + {"X1_50", X1_50}, + {"X1_100", X1_100}, + {"X2_0", X2_0}, + {"X2_100", X2_100}, + {"X3_0", X3_0}, + {"X3_100", X3_100}, + {"X4_0", X4_0}, + {"X4_100", X4_100}, + {"QUARTER1_X4", QUARTER1_X4}, + {"QUARTER3_X4", QUARTER3_X4}, + {"Y_BASE", Y_BASE}, + {"BALLOON_SIZE_0", BALLOON_SIZE[0]}, + {"BALLOON_SIZE_1", BALLOON_SIZE[1]}, + {"BALLOON_SIZE_2", BALLOON_SIZE[2]}, + {"BALLOON_SIZE_3", BALLOON_SIZE[3]}, + {"VEL_POSITIVE", BALLOON_VELX_POSITIVE}, + {"VEL_NEGATIVE", BALLOON_VELX_NEGATIVE}}; + balloon_formation_.reserve(NUMBER_OF_BALLOON_FORMATIONS); - constexpr int CREATION_TIME = 300; + if (!loadFormationsFromFile(Asset::get()->get("balloon_formations.txt"), variables)) { + // Fallback: cargar formaciones por defecto si falla la carga del archivo + loadDefaultFormations(); + } +} - // #00 - Dos enemigos BALLOON4 uno a cada extremo - { - std::vector init_params = { - BalloonFormationParams(X4_0, Y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME), - BalloonFormationParams(X4_100, Y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME)}; - balloon_formation_.emplace_back(2, init_params); +auto BalloonFormations::loadFormationsFromFile(const std::string& filename, const std::map& variables) -> bool { + std::ifstream file(filename); + if (!file.is_open()) { + return false; } - // #01 - Dos enemigos BALLOON4 uno a cada cuarto. Ambos van hacia el centro - { - std::vector init_params = { - BalloonFormationParams(param.game.play_area.first_quarter_x - (BALLOON_SIZE[3] / 2), Y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME), - BalloonFormationParams(param.game.play_area.third_quarter_x - (BALLOON_SIZE[3] / 2), Y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME)}; - balloon_formation_.emplace_back(2, init_params); - } + std::string line; + int current_formation = -1; + std::vector current_params; - // #02 - Cuatro enemigos BALLOON2 uno detrás del otro. A la izquierda y hacia el centro - { - std::vector init_params; - for (int i = 0; i < 4; ++i) { - init_params.emplace_back(X2_0 + (i * (BALLOON_SIZE[1] + 1)), Y2, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (10 * i)); + while (std::getline(file, line)) { + // Eliminar espacios en blanco al inicio y final + line = trim(line); + + // Saltar líneas vacías y comentarios + if (line.empty() || line[0] == '#') { + continue; } - balloon_formation_.emplace_back(4, init_params); - } - // #03 - Cuatro enemigos BALLOON2 uno detrás del otro. A la derecha y hacia el centro - { - std::vector init_params; - for (int i = 0; i < 4; ++i) { - init_params.emplace_back(X2_100 - (i * (BALLOON_SIZE[1] + 1)), Y2, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (10 * i)); + // Verificar si es una nueva formación + if (line.substr(0, 10) == "formation:") { + // Guardar formación anterior si existe + if (current_formation >= 0 && !current_params.empty()) { + balloon_formation_.emplace_back(current_params.size(), current_params); + } + + // Iniciar nueva formación + current_formation = std::stoi(line.substr(10)); + current_params.clear(); + continue; } - balloon_formation_.emplace_back(4, init_params); - } - // #04 - Tres enemigos BALLOON3. 0, 25, 50. Hacia la derecha - { - std::vector init_params; - for (int i = 0; i < 3; ++i) { - init_params.emplace_back(X3_0 + (i * (BALLOON_SIZE[2] * 2)), Y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(3, init_params); - } - - // #05 - Tres enemigos BALLOON3. 50, 75, 100. Hacia la izquierda - { - std::vector init_params; - for (int i = 0; i < 3; ++i) { - init_params.emplace_back(X3_100 - (i * (BALLOON_SIZE[2] * 2)), Y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(3, init_params); - } - - // #06 - Tres enemigos BALLOON3. 0, 0, 0. Hacia la derecha - { - std::vector init_params; - for (int i = 0; i < 3; ++i) { - init_params.emplace_back(X3_0 + (i * (BALLOON_SIZE[2] + 1)), Y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(3, init_params); - } - - // #07 - Tres enemigos BALLOON3. 100, 100, 100. Hacia la izquierda - { - std::vector init_params; - for (int i = 0; i < 3; ++i) { - init_params.emplace_back(X3_100 - (i * (BALLOON_SIZE[2] + 1)), Y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(3, init_params); - } - - // #08 - Seis enemigos BALLOON1. 0, 0, 0, 0, 0, 0. Hacia la derecha - { - std::vector init_params; - for (int i = 0; i < 6; ++i) { - init_params.emplace_back(X1_0 + (i * (BALLOON_SIZE[0] + 1)), Y1, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(6, init_params); - } - - // #09 - Seis enemigos BALLOON1. 100, 100, 100, 100, 100, 100. Hacia la izquierda - { - std::vector init_params; - for (int i = 0; i < 6; ++i) { - init_params.emplace_back(X1_100 - (i * (BALLOON_SIZE[0] + 1)), Y1, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(6, init_params); - } - - // #10 - Tres enemigos BALLOON4 seguidos desde la izquierda. Hacia la derecha - { - std::vector init_params; - for (int i = 0; i < 3; ++i) { - init_params.emplace_back(X4_0 + (i * (BALLOON_SIZE[3] + 1)), Y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME - (15 * i)); - } - balloon_formation_.emplace_back(3, init_params); - } - - // #11 - Tres enemigos BALLOON4 seguidos desde la derecha. Hacia la izquierda - { - std::vector init_params; - for (int i = 0; i < 3; ++i) { - init_params.emplace_back(X4_100 - (i * (BALLOON_SIZE[3] + 1)), Y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME - (15 * i)); - } - balloon_formation_.emplace_back(3, init_params); - } - - // #12 - Seis enemigos BALLOON2 uno detrás del otro. A la izquierda y hacia el centro - { - std::vector init_params; - for (int i = 0; i < 6; ++i) { - init_params.emplace_back(X2_0 + (i * (BALLOON_SIZE[1] + 1)), Y2, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(6, init_params); - } - - // #13 - Seis enemigos BALLOON2 uno detrás del otro. A la derecha y hacia el centro - { - std::vector init_params; - for (int i = 0; i < 6; ++i) { - init_params.emplace_back(X2_100 - (i * (BALLOON_SIZE[1] + 1)), Y2, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(6, init_params); - } - - // #14 - Cinco enemigos BALLOON3. Hacia la derecha. Separados - { - std::vector init_params; - for (int i = 0; i < 5; ++i) { - init_params.emplace_back(X3_0 + (i * (BALLOON_SIZE[2] * 2)), Y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(5, init_params); - } - - // #15 - Cinco enemigos BALLOON3. Hacia la izquierda. Separados - { - std::vector init_params; - for (int i = 0; i < 5; ++i) { - init_params.emplace_back(X3_100 - (i * (BALLOON_SIZE[2] * 2)), Y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(5, init_params); - } - - // #16 - Cinco enemigos BALLOON3. Hacia la derecha. Juntos - { - std::vector init_params; - for (int i = 0; i < 5; ++i) { - init_params.emplace_back(X3_0 + (i * (BALLOON_SIZE[2] + 1)), Y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(5, init_params); - } - - // #17 - Cinco enemigos BALLOON3. Hacia la izquierda. Juntos - { - std::vector init_params; - for (int i = 0; i < 5; ++i) { - init_params.emplace_back(X3_100 - (i * (BALLOON_SIZE[2] + 1)), Y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(5, init_params); - } - - // #18 - Doce enemigos BALLOON1. Hacia la derecha. Juntos - { - std::vector init_params; - for (int i = 0; i < 12; ++i) { - init_params.emplace_back(X1_0 + (i * (BALLOON_SIZE[0] + 1)), Y1, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(12, init_params); - } - - // #19 - Doce enemigos BALLOON1. Hacia la izquierda. Juntos - { - std::vector init_params; - for (int i = 0; i < 12; ++i) { - init_params.emplace_back(X1_100 - (i * (BALLOON_SIZE[0] + 1)), Y1, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (10 * i)); - } - balloon_formation_.emplace_back(12, init_params); - } - - // #20 - Dos enemigos BALLOON4 seguidos desde la izquierda/derecha. Simétricos - { - std::vector init_params; - const int HALF = 4 / 2; - for (int i = 0; i < 4; ++i) { - if (i < HALF) { - init_params.emplace_back(X4_0 + (i * (BALLOON_SIZE[3] + 1)), Y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME + (0 * i)); - } else { - init_params.emplace_back(X4_100 - ((i - HALF) * (BALLOON_SIZE[3] + 1)), Y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME + (0 * i)); + // Procesar línea de parámetros de balloon + if (current_formation >= 0) { + auto params = parseBalloonLine(line, variables); + if (params.has_value()) { + current_params.push_back(params.value()); } } - balloon_formation_.emplace_back(4, init_params); } - // #20 - Dos enemigos BALLOON4 seguidos desde la izquierda/derecha. Simétricos - { - std::vector init_params; - const int HALF = 4 / 2; - for (int i = 0; i < 4; ++i) { - if (i < HALF) { - init_params.emplace_back(X4_0 + (i * (BALLOON_SIZE[3] + 1)), Y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME + (0 * i)); - } else { - init_params.emplace_back(X4_100 - ((i - HALF) * (BALLOON_SIZE[3] + 1)), Y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME + (0 * i)); + // Guardar última formación + if (current_formation >= 0 && !current_params.empty()) { + balloon_formation_.emplace_back(current_params.size(), current_params); + } + + // Crear variantes flotantes (formaciones 50-99) + createFloaterVariants(); + + // Añadir formación de prueba + addTestFormation(); + + file.close(); + return true; +} + +auto BalloonFormations::parseBalloonLine(const std::string& line, const std::map& variables) -> std::optional { + std::istringstream iss(line); + std::string token; + std::vector tokens; + + // Dividir por comas + while (std::getline(iss, token, ',')) { + tokens.push_back(trim(token)); + } + + if (tokens.size() != 6) { + return std::nullopt; + } + + try { + int x = evaluateExpression(tokens[0], variables); + int y = evaluateExpression(tokens[1], variables); + int vel_x = evaluateExpression(tokens[2], variables); + + BalloonType type = (tokens[3] == "BALLOON") ? BalloonType::BALLOON : BalloonType::FLOATER; + + BalloonSize size; + if (tokens[4] == "SIZE1") { + size = BalloonSize::SIZE1; + } else if (tokens[4] == "SIZE2") { + size = BalloonSize::SIZE2; + } else if (tokens[4] == "SIZE3") { + size = BalloonSize::SIZE3; + } else if (tokens[4] == "SIZE4") { + size = BalloonSize::SIZE4; + } else { + return std::nullopt; + } + + int creation_time = evaluateExpression(tokens[5], variables); + + return BalloonFormationParams(x, y, vel_x, type, size, creation_time); + } catch (const std::exception&) { + return std::nullopt; + } +} + +auto BalloonFormations::evaluateExpression(const std::string& expr, const std::map& variables) -> int { + std::string trimmed_expr = trim(expr); + + // Si es un número directo + if ((std::isdigit(trimmed_expr[0]) != 0) || (trimmed_expr[0] == '-' && trimmed_expr.length() > 1)) { + return std::stoi(trimmed_expr); + } + + // Si es una variable simple + if (variables.find(trimmed_expr) != variables.end()) { + return variables.at(trimmed_expr); + } + + // Evaluación de expresiones simples (suma, resta, multiplicación) + return evaluateSimpleExpression(trimmed_expr, variables); +} + +auto BalloonFormations::evaluateSimpleExpression(const std::string& expr, const std::map& variables) -> int { + // Buscar operadores (+, -, *, /) + for (size_t i = 1; i < expr.length(); ++i) { + char op = expr[i]; + if (op == '+' || op == '-' || op == '*' || op == '/') { + std::string left = trim(expr.substr(0, i)); + std::string right = trim(expr.substr(i + 1)); + + int left_val = evaluateExpression(left, variables); + int right_val = evaluateExpression(right, variables); + + switch (op) { + case '+': + return left_val + right_val; + case '-': + return left_val - right_val; + case '*': + return left_val * right_val; + case '/': + return right_val != 0 ? left_val / right_val : 0; } } - balloon_formation_.emplace_back(4, init_params); } - // #21 - Diez enemigos BALLOON2 uno detrás del otro. Izquierda/derecha. Simétricos - { - std::vector init_params; - const int HALF = 10 / 2; - for (int i = 0; i < 10; ++i) { - if (i < HALF) { - init_params.emplace_back(X2_0 + (i * (BALLOON_SIZE[1] + 1)), Y2, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (3 * i)); - } else { - init_params.emplace_back(X2_100 - ((i - HALF) * (BALLOON_SIZE[1] + 1)), Y2, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (3 * (i - HALF))); - } - } - balloon_formation_.emplace_back(10, init_params); - } + // Si no se encuentra operador, intentar como variable o número + return variables.find(expr) != variables.end() ? variables.at(expr) : std::stoi(expr); +} - // #22 - Diez enemigos BALLOON3. Hacia la derecha/izquierda. Separados. Simétricos - { - std::vector init_params; - const int HALF = 10 / 2; - for (int i = 0; i < 10; ++i) { - if (i < HALF) { - init_params.emplace_back(X3_0 + (i * (BALLOON_SIZE[2] * 2)), Y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i)); - } else { - init_params.emplace_back(X3_100 - ((i - HALF) * (BALLOON_SIZE[2] * 2)), Y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * (i - HALF))); - } - } - balloon_formation_.emplace_back(10, init_params); +auto BalloonFormations::trim(const std::string& str) -> std::string { + size_t start = str.find_first_not_of(" \t\r\n"); + if (start == std::string::npos) { + return ""; } + size_t end = str.find_last_not_of(" \t\r\n"); + return str.substr(start, end - start + 1); +} - // #23 - Diez enemigos BALLOON3. Hacia la derecha. Juntos. Simétricos - { - std::vector init_params; - const int HALF = 10 / 2; - for (int i = 0; i < 10; ++i) { - if (i < HALF) { - init_params.emplace_back(X3_0 + (i * (BALLOON_SIZE[2] + 1)), Y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i)); - } else { - init_params.emplace_back(X3_100 - ((i - HALF) * (BALLOON_SIZE[2] + 1)), Y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * (i - HALF))); - } - } - balloon_formation_.emplace_back(10, init_params); - } - - // #24 - Treinta enemigos BALLOON1. Del centro hacia los extremos. Juntos. Simétricos - { - std::vector init_params; - const int HALF = 30 / 2; - for (int i = 0; i < 30; ++i) { - if (i < HALF) { - init_params.emplace_back(X1_50, Y1, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME + (5 * i)); - } else { - init_params.emplace_back(X1_50, Y1, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME + (5 * (i - HALF))); - } - } - balloon_formation_.emplace_back(30, init_params); - } - - // #25 - Treinta enemigos BALLOON1. Del centro hacia adentro. Juntos. Simétricos - { - std::vector init_params; - const int HALF = 30 / 2; - for (int i = 0; i < 30; ++i) { - if (i < HALF) { - init_params.emplace_back(X1_50 + 20, Y1, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (5 * i)); - } else { - init_params.emplace_back(X1_50 - 20, Y1, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (5 * (i - HALF))); - } - } - balloon_formation_.emplace_back(30, init_params); - } - - // Reservar espacio para el vector +void BalloonFormations::createFloaterVariants() { balloon_formation_.resize(100); - // Crea las mismas formaciones pero con hexágonos a partir de la posición 50 del vector - for (int k = 0; k < 50; k++) { - std::vector init_params; - for (int i = 0; i < balloon_formation_.at(k).number_of_balloons; i++) { - init_params.emplace_back( - balloon_formation_.at(k).init.at(i).x, - balloon_formation_.at(k).init.at(i).y, - balloon_formation_.at(k).init.at(i).vel_x, - BalloonType::FLOATER, - balloon_formation_.at(k).init.at(i).size, - balloon_formation_.at(k).init.at(i).creation_counter); + // Crear variantes flotantes de las primeras 50 formaciones + for (size_t k = 0; k < 50 && k < balloon_formation_.size(); k++) { + std::vector floater_params; + floater_params.reserve(balloon_formation_[k].number_of_balloons); + + for (int i = 0; i < balloon_formation_[k].number_of_balloons; i++) { + const auto& original = balloon_formation_[k].init[i]; + floater_params.emplace_back( + original.x, original.y, original.vel_x, BalloonType::FLOATER, original.size, original.creation_counter); } - balloon_formation_.at(k + 50) = BalloonFormationUnit(balloon_formation_.at(k).number_of_balloons, init_params); + + balloon_formation_[k + 50] = BalloonFormationUnit( + balloon_formation_[k].number_of_balloons, floater_params); } +} - // TEST +void BalloonFormations::addTestFormation() { std::vector test_params = { - {10, Y1, 0, BalloonType::FLOATER, BalloonSize::SIZE1, 200}, - {50, Y1, 0, BalloonType::FLOATER, BalloonSize::SIZE2, 200}, - {90, Y1, 0, BalloonType::FLOATER, BalloonSize::SIZE3, 200}, - {140, Y1, 0, BalloonType::FLOATER, BalloonSize::SIZE4, 200}}; + {10, -BLOCK, 0, BalloonType::FLOATER, BalloonSize::SIZE1, 200}, + {50, -BLOCK, 0, BalloonType::FLOATER, BalloonSize::SIZE2, 200}, + {90, -BLOCK, 0, BalloonType::FLOATER, BalloonSize::SIZE3, 200}, + {140, -BLOCK, 0, BalloonType::FLOATER, BalloonSize::SIZE4, 200}}; - balloon_formation_.at(99) = BalloonFormationUnit(4, test_params); + balloon_formation_[99] = BalloonFormationUnit(4, test_params); +} + +void BalloonFormations::loadDefaultFormations() { + // Código de fallback con algunas formaciones básicas hardcodeadas + // para que el juego funcione aunque falle la carga del archivo + + const int Y_BASE = -BLOCK; + const int X4_0 = param.game.play_area.rect.x; + const int X4_100 = param.game.play_area.rect.w - BALLOON_SIZE[3]; + constexpr int CREATION_TIME = 300; + + // Formación básica #00 + std::vector basic_formation = { + BalloonFormationParams(X4_0, Y_BASE, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME), + BalloonFormationParams(X4_100, Y_BASE, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME)}; + balloon_formation_.emplace_back(2, basic_formation); } // Inicializa los conjuntos de formaciones @@ -339,41 +260,131 @@ void BalloonFormations::initBalloonFormationPools() { // Set #0 balloon_formation_pool_.at(0) = { - &balloon_formation_.at(0), &balloon_formation_.at(1), &balloon_formation_.at(2), &balloon_formation_.at(3), &balloon_formation_.at(4), &balloon_formation_.at(5), &balloon_formation_.at(6), &balloon_formation_.at(7), &balloon_formation_.at(8), &balloon_formation_.at(9)}; + &balloon_formation_.at(0), + &balloon_formation_.at(1), + &balloon_formation_.at(2), + &balloon_formation_.at(3), + &balloon_formation_.at(4), + &balloon_formation_.at(5), + &balloon_formation_.at(6), + &balloon_formation_.at(7), + &balloon_formation_.at(8), + &balloon_formation_.at(9)}; // Set #1 balloon_formation_pool_.at(1) = { - &balloon_formation_.at(10), &balloon_formation_.at(11), &balloon_formation_.at(12), &balloon_formation_.at(13), &balloon_formation_.at(14), &balloon_formation_.at(15), &balloon_formation_.at(16), &balloon_formation_.at(17), &balloon_formation_.at(18), &balloon_formation_.at(19)}; + &balloon_formation_.at(10), + &balloon_formation_.at(11), + &balloon_formation_.at(12), + &balloon_formation_.at(13), + &balloon_formation_.at(14), + &balloon_formation_.at(15), + &balloon_formation_.at(16), + &balloon_formation_.at(17), + &balloon_formation_.at(18), + &balloon_formation_.at(19)}; // Set #2 balloon_formation_pool_.at(2) = { - &balloon_formation_.at(0), &balloon_formation_.at(1), &balloon_formation_.at(2), &balloon_formation_.at(3), &balloon_formation_.at(4), &balloon_formation_.at(55), &balloon_formation_.at(56), &balloon_formation_.at(57), &balloon_formation_.at(58), &balloon_formation_.at(59)}; + &balloon_formation_.at(0), + &balloon_formation_.at(1), + &balloon_formation_.at(2), + &balloon_formation_.at(3), + &balloon_formation_.at(4), + &balloon_formation_.at(55), + &balloon_formation_.at(56), + &balloon_formation_.at(57), + &balloon_formation_.at(58), + &balloon_formation_.at(59)}; // Set #3 balloon_formation_pool_.at(3) = { - &balloon_formation_.at(50), &balloon_formation_.at(51), &balloon_formation_.at(52), &balloon_formation_.at(53), &balloon_formation_.at(54), &balloon_formation_.at(5), &balloon_formation_.at(6), &balloon_formation_.at(7), &balloon_formation_.at(8), &balloon_formation_.at(9)}; + &balloon_formation_.at(50), + &balloon_formation_.at(51), + &balloon_formation_.at(52), + &balloon_formation_.at(53), + &balloon_formation_.at(54), + &balloon_formation_.at(5), + &balloon_formation_.at(6), + &balloon_formation_.at(7), + &balloon_formation_.at(8), + &balloon_formation_.at(9)}; // Set #4 balloon_formation_pool_.at(4) = { - &balloon_formation_.at(60), &balloon_formation_.at(61), &balloon_formation_.at(62), &balloon_formation_.at(63), &balloon_formation_.at(64), &balloon_formation_.at(65), &balloon_formation_.at(66), &balloon_formation_.at(67), &balloon_formation_.at(68), &balloon_formation_.at(69)}; + &balloon_formation_.at(60), + &balloon_formation_.at(61), + &balloon_formation_.at(62), + &balloon_formation_.at(63), + &balloon_formation_.at(64), + &balloon_formation_.at(65), + &balloon_formation_.at(66), + &balloon_formation_.at(67), + &balloon_formation_.at(68), + &balloon_formation_.at(69)}; // Set #5 balloon_formation_pool_.at(5) = { - &balloon_formation_.at(10), &balloon_formation_.at(61), &balloon_formation_.at(12), &balloon_formation_.at(63), &balloon_formation_.at(14), &balloon_formation_.at(65), &balloon_formation_.at(16), &balloon_formation_.at(67), &balloon_formation_.at(18), &balloon_formation_.at(69)}; + &balloon_formation_.at(10), + &balloon_formation_.at(61), + &balloon_formation_.at(12), + &balloon_formation_.at(63), + &balloon_formation_.at(14), + &balloon_formation_.at(65), + &balloon_formation_.at(16), + &balloon_formation_.at(67), + &balloon_formation_.at(18), + &balloon_formation_.at(69)}; // Set #6 balloon_formation_pool_.at(6) = { - &balloon_formation_.at(60), &balloon_formation_.at(11), &balloon_formation_.at(62), &balloon_formation_.at(13), &balloon_formation_.at(64), &balloon_formation_.at(15), &balloon_formation_.at(66), &balloon_formation_.at(17), &balloon_formation_.at(68), &balloon_formation_.at(19)}; + &balloon_formation_.at(60), + &balloon_formation_.at(11), + &balloon_formation_.at(62), + &balloon_formation_.at(13), + &balloon_formation_.at(64), + &balloon_formation_.at(15), + &balloon_formation_.at(66), + &balloon_formation_.at(17), + &balloon_formation_.at(68), + &balloon_formation_.at(19)}; // Set #7 balloon_formation_pool_.at(7) = { - &balloon_formation_.at(20), &balloon_formation_.at(21), &balloon_formation_.at(22), &balloon_formation_.at(23), &balloon_formation_.at(24), &balloon_formation_.at(65), &balloon_formation_.at(66), &balloon_formation_.at(67), &balloon_formation_.at(68), &balloon_formation_.at(69)}; + &balloon_formation_.at(20), + &balloon_formation_.at(21), + &balloon_formation_.at(22), + &balloon_formation_.at(23), + &balloon_formation_.at(24), + &balloon_formation_.at(65), + &balloon_formation_.at(66), + &balloon_formation_.at(67), + &balloon_formation_.at(68), + &balloon_formation_.at(69)}; // Set #8 balloon_formation_pool_.at(8) = { - &balloon_formation_.at(70), &balloon_formation_.at(71), &balloon_formation_.at(72), &balloon_formation_.at(73), &balloon_formation_.at(74), &balloon_formation_.at(15), &balloon_formation_.at(16), &balloon_formation_.at(17), &balloon_formation_.at(18), &balloon_formation_.at(19)}; + &balloon_formation_.at(70), + &balloon_formation_.at(71), + &balloon_formation_.at(72), + &balloon_formation_.at(73), + &balloon_formation_.at(74), + &balloon_formation_.at(15), + &balloon_formation_.at(16), + &balloon_formation_.at(17), + &balloon_formation_.at(18), + &balloon_formation_.at(19)}; // Set #9 balloon_formation_pool_.at(9) = { - &balloon_formation_.at(20), &balloon_formation_.at(21), &balloon_formation_.at(22), &balloon_formation_.at(23), &balloon_formation_.at(24), &balloon_formation_.at(70), &balloon_formation_.at(71), &balloon_formation_.at(72), &balloon_formation_.at(73), &balloon_formation_.at(74)}; + &balloon_formation_.at(20), + &balloon_formation_.at(21), + &balloon_formation_.at(22), + &balloon_formation_.at(23), + &balloon_formation_.at(24), + &balloon_formation_.at(70), + &balloon_formation_.at(71), + &balloon_formation_.at(72), + &balloon_formation_.at(73), + &balloon_formation_.at(74)}; } diff --git a/source/balloon_formations.h b/source/balloon_formations.h index a6048c1..04eec56 100644 --- a/source/balloon_formations.h +++ b/source/balloon_formations.h @@ -1,8 +1,12 @@ #pragma once -#include - #include "balloon.h" // Para BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE +#include +#include +#include +#include +#include +#include // --- Constantes de configuración --- constexpr int NUMBER_OF_BALLOON_FORMATIONS = 100; @@ -32,14 +36,14 @@ struct BalloonFormationUnit { std::vector init; // Vector con todas las inicializaciones de los globos de la formación // Constructor con parámetros - BalloonFormationUnit(int num_balloons, const std::vector &init_params) + BalloonFormationUnit(int num_balloons, const std::vector& init_params) : number_of_balloons(num_balloons), init(init_params) {} // Constructor por defecto BalloonFormationUnit() : number_of_balloons(0) {} }; -using BalloonFormationPool = std::vector; +using BalloonFormationPool = std::vector; // --- Clase BalloonFormations --- class BalloonFormations { @@ -52,9 +56,9 @@ class BalloonFormations { ~BalloonFormations() = default; // --- Getters --- - auto getPool(int pool) -> const BalloonFormationPool & { return balloon_formation_pool_.at(pool); } - auto getSet(int pool, int set) -> const BalloonFormationUnit & { return *balloon_formation_pool_.at(pool).at(set); } - [[nodiscard]] auto getSet(int set) const -> const BalloonFormationUnit & { return balloon_formation_.at(set); } + auto getPool(int pool) -> const BalloonFormationPool& { return balloon_formation_pool_.at(pool); } + auto getSet(int pool, int set) -> const BalloonFormationUnit& { return *balloon_formation_pool_.at(pool).at(set); } + [[nodiscard]] auto getSet(int set) const -> const BalloonFormationUnit& { return balloon_formation_.at(set); } private: // --- Datos --- @@ -62,6 +66,14 @@ class BalloonFormations { std::vector balloon_formation_pool_; // Conjuntos de formaciones enemigas // --- Métodos internos de inicialización --- - void initBalloonFormations(); - void initBalloonFormationPools(); + void initBalloonFormations(); // Inicializa la lista principal de formaciones de globos disponibles + void initBalloonFormationPools(); // Prepara las estructuras de agrupamiento o reutilización de formaciones (pools) + auto loadFormationsFromFile(const std::string& filename, const std::map& variables) -> bool; // Carga las formaciones desde un archivo, evaluando variables dinámicas + auto parseBalloonLine(const std::string& line, const std::map& variables) -> std::optional; // Parsea una línea individual del archivo y genera parámetros de formación + auto evaluateExpression(const std::string& expr, const std::map& variables) -> int; // Evalúa expresiones matemáticas con variables definidas (complejas) + auto evaluateSimpleExpression(const std::string& expr, const std::map& variables) -> int; // Evalúa expresiones más sencillas (sin paréntesis o operadores avanzados) + static auto trim(const std::string& str) -> std::string; // Elimina espacios en blanco al inicio y fin de una cadena + void createFloaterVariants(); // Genera variantes de globos flotantes según configuración o aleatoriedad + void addTestFormation(); // Añade una formación de prueba para debug o validación en tiempo de desarrollo + void loadDefaultFormations(); // Carga las formaciones por defecto incluidas en el juego si no hay archivo externo }; diff --git a/source/director.cpp b/source/director.cpp index 2aad2e6..05450ad 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -258,6 +258,7 @@ void Director::setFileList() { Asset::get()->add(PREFIX + "/data/config/demo1.bin", AssetType::DEMODATA); Asset::get()->add(PREFIX + "/data/config/demo2.bin", AssetType::DEMODATA); Asset::get()->add(PREFIX + "/data/config/gamecontrollerdb.txt", AssetType::DATA); + Asset::get()->add(PREFIX + "/data/config/balloon_formations.txt", AssetType::DATA); // Musicas Asset::get()->add(PREFIX + "/data/music/intro.ogg", AssetType::MUSIC); diff --git a/source/director.h b/source/director.h index afbe1f9..1da239e 100644 --- a/source/director.h +++ b/source/director.h @@ -14,7 +14,7 @@ class Director { ~Director(); // --- Bucle principal --- - auto run() -> int; + static auto run() -> int; private: // --- Variables internas --- diff --git a/source/item.cpp b/source/item.cpp index 385e4ee..f627868 100644 --- a/source/item.cpp +++ b/source/item.cpp @@ -192,15 +192,13 @@ auto Item::getCoffeeMachineSpawn(int player_x, int item_width, int area_width, i if (can_spawn_right) { // Solo lado derecho disponible return rand() % (RIGHT_BOUND - exclude_right) + exclude_right; - } else { - // No hay espacio suficiente lejos del jugador - // Por ahora, intentar spawn en el extremo más lejano posible - int distance_to_left = abs(player_x - LEFT_BOUND); - int distance_to_right = abs(RIGHT_BOUND - player_x); + } // No hay espacio suficiente lejos del jugador + // Por ahora, intentar spawn en el extremo más lejano posible + int distance_to_left = abs(player_x - LEFT_BOUND); + int distance_to_right = abs(RIGHT_BOUND - player_x); - if (distance_to_left > distance_to_right) { - return LEFT_BOUND; - } - return RIGHT_BOUND - item_width; + if (distance_to_left > distance_to_right) { + return LEFT_BOUND; } + return RIGHT_BOUND - item_width; } diff --git a/source/notifier.cpp b/source/notifier.cpp index 4a8c55d..bcf6e95 100644 --- a/source/notifier.cpp +++ b/source/notifier.cpp @@ -58,7 +58,7 @@ void Notifier::update() { auto Notifier::shouldProcessNotification(int index) const -> bool { // Si la notificación anterior está "saliendo", no hagas nada - return !(index > 0 && notifications_[index - 1].state == NotificationStatus::RISING); + return index <= 0 || notifications_[index - 1].state != NotificationStatus::RISING; } void Notifier::processNotification(int index) {