#include #include "texture.h" #include "ball.h" #include "defines.h" #include "dbgtxt.h" #include #include #include #include #include #include // Variables globales SDL_Window *window = nullptr; SDL_Renderer *renderer = nullptr; std::shared_ptr texture = nullptr; std::vector> balls; std::array test = {1, 10, 100, 500, 1000, 10000, 50000, 100000}; bool should_exit = false; // Controla si la aplicación debe cerrarse Uint64 ticks = 0; // Tiempo en milisegundos para controlar la actualización int scenario = 0; // Escenario actual basado en el número de bolas std::string text; // Texto a mostrar en pantalla int text_pos = 0; // Posición del texto en la pantalla bool show_text = true; // Determina si el texto se debe mostrar Uint64 text_init_time = 0; // Temporizador para mostrar el texto // Establece el texto en pantalla mostrando el número de bolas actuales void setText() { const std::string TEXT_NUMBER = test[scenario] == 1 ? " PELOTA" : " PELOTAS"; text = std::to_string(test[scenario]) + TEXT_NUMBER; const int TEXT_SIZE = static_cast(text.size() * 8); text_pos = SCREEN_WIDTH / 2 - TEXT_SIZE / 2; text_init_time = SDL_GetTicks(); show_text = true; } // Inicializa las bolas según el escenario seleccionado void initBalls(int value) { balls.clear(); for (int i = 0; i < test.at(value); ++i) { const int SIGN = ((rand() % 2) * 2) - 1; // Genera un signo aleatorio (+ o -) const float X = (rand() % (SCREEN_WIDTH / 2)) + (SCREEN_WIDTH / 4); // Posición inicial en X const float VX = (((rand() % 20) + 10) * 0.1f) * SIGN; // Velocidad en X const float VY = ((rand() % 60) - 30) * 0.1f; // Velocidad en Y const Color COLOR = {(rand() % 192) + 32, (rand() % 192) + 32, (rand() % 192) + 32}; // Color aleatorio balls.emplace_back(std::make_unique(X, VX, VY, COLOR, texture)); } setText(); // Actualiza el texto } // Aumenta la velocidad vertical de las bolas "hacia arriba" void pushUpBalls() { for (auto &ball : balls) { const int SIGNO = ((rand() % 2) * 2) - 1; const float VX = (((rand() % 20) + 10) * 0.1f) * SIGNO; const float VY = ((rand() % 40) * 0.1f) + 5; ball->modVel(VX, -VY); // Modifica la velocidad de la bola } } // Cambia la gravedad de todas las bolas void switchBallsGravity() { for (auto &ball : balls) { ball->switchGravity(); } } // Inicializa SDL y configura los componentes principales bool init() { bool success = true; // Inicializa SDL if (!SDL_Init(SDL_INIT_VIDEO)) { std::cout << "¡SDL no se pudo inicializar! Error de SDL: " << SDL_GetError() << std::endl; success = false; } else { // Crear ventana principal window = SDL_CreateWindow(WINDOW_CAPTION, SCREEN_WIDTH * WINDOW_SIZE, SCREEN_HEIGHT * WINDOW_SIZE, SDL_WINDOW_OPENGL); if (window == nullptr) { std::cout << "¡No se pudo crear la ventana! Error de SDL: " << SDL_GetError() << std::endl; success = false; } else { // Crear renderizador renderer = SDL_CreateRenderer(window, nullptr); if (renderer == nullptr) { std::cout << "¡No se pudo crear el renderizador! Error de SDL: " << SDL_GetError() << std::endl; success = false; } else { // Establecer color inicial del renderizador SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); // Establecer tamaño lógico para el renderizado SDL_SetRenderLogicalPresentation(renderer, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE); } } } // Inicializar otros componentes texture = std::make_shared(renderer, "resources/ball.png"); ticks = SDL_GetTicks(); srand(static_cast(time(nullptr))); dbg_init(renderer); initBalls(scenario); return success; } // Limpia todos los recursos y cierra SDL void close() { SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); } // Verifica los eventos en la cola void checkEvents() { SDL_Event event; while (SDL_PollEvent(&event) != 0) { // Evento de salida if (event.type == SDL_EVENT_QUIT) { should_exit = true; break; } // Procesar eventos de teclado if (event.type == SDL_EVENT_KEY_DOWN && event.key.repeat == 0) { switch (event.key.key) { case SDLK_ESCAPE: should_exit = true; break; case SDLK_SPACE: pushUpBalls(); break; case SDLK_G: switchBallsGravity(); break; case SDLK_1: scenario = 0; initBalls(scenario); break; case SDLK_2: scenario = 1; initBalls(scenario); break; case SDLK_3: scenario = 2; initBalls(scenario); break; case SDLK_4: scenario = 3; initBalls(scenario); break; case SDLK_5: scenario = 4; initBalls(scenario); break; case SDLK_6: scenario = 5; initBalls(scenario); break; case SDLK_7: scenario = 6; initBalls(scenario); break; case SDLK_8: scenario = 7; initBalls(scenario); break; } } } } // Actualiza la lógica del juego void update() { if (SDL_GetTicks() - ticks > DEMO_SPEED) { ticks = SDL_GetTicks(); for (auto &ball : balls) { ball->update(); } if (show_text) { show_text = !(SDL_GetTicks() - text_init_time > TEXT_DURATION); } } } // Renderiza el contenido en la pantalla void render() { SDL_SetRenderDrawColor(renderer, 32, 32, 32, 255); SDL_RenderClear(renderer); for (auto &ball : balls) { ball->render(); } if (show_text) { dbg_print(text_pos, 8, text.c_str(), 255, 255, 255); } SDL_RenderPresent(renderer); } // Función principal int main(int argc, char *args[]) { if (!init()) { std::cout << "Ocurrió un error durante la inicialización." << std::endl; return 1; } while (!should_exit) { update(); checkEvents(); render(); } close(); return 0; }