#include // Para SDL_GetError #include // Para SDL_EventType, SDL_PollEvent, SDL_Event #include // Para SDL_Init, SDL_Quit, SDL_INIT_VIDEO #include // Para SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5 #include // Para SDL_FPoint #include // Para SDL_SetRenderDrawColor, SDL_CreateRend... #include // Para Uint64 #include // Para SDL_GetTicks #include // Para SDL_CreateWindow, SDL_DestroyWindow #include // Para rand, srand #include // Para time #include // Para basic_ostream, char_traits, operator<< #include // Para operator+, string, to_string #include "dbgtxt.h" // Para dbg_init, dbg_print #include "defines.h" // Para WIDTH, MAX_DOTS, Color, HEIGHT, ZOOM #include "dot.h" // Para DotData, ini, modVel, update // Ventana y renderizador SDL_Window *window = nullptr; SDL_Renderer *renderer = nullptr; // Datos de los puntos y su representación gráfica Dot::DotData dots[MAX_DOTS]; SDL_FPoint dot_points[MAX_DOTS]; // Escenarios y configuración int test[8] = {1, 10, 100, 500, 1000, 10000, 50000, MAX_DOTS}; int scenario = 0; std::string text = ""; int text_pos = 0; bool show_text = true; Uint64 text_init_time; bool should_exit = false; Uint64 ticks = 0; // Actualiza el texto a mostrar en pantalla void setText() { const std::string TEXT2 = test[scenario] == 1 ? " PIXEL" : " PIXELES"; text = std::to_string(test[scenario]) + TEXT2; const int SIZE = text.size() * 8; text_pos = WIDTH / 2 - SIZE / 2; text_init_time = SDL_GetTicks(); show_text = true; } // Inicializa los puntos para el escenario actual void initDots() { for (int i = 0; i < test[scenario]; ++i) { const int SIGN = ((rand() % 2) * 2) - 1; const float X = (rand() % (WIDTH / 2)) + (WIDTH / 4); const float VX = (((rand() % 20) + 10) * 0.1f) * SIGN; const float VY = ((rand() % 60) - 30) * 0.1f; const Color COLOR = {(rand() % 192) + 32, (rand() % 192) + 32, (rand() % 192) + 32}; dots[i] = Dot::ini(X, VX, VY, COLOR); } setText(); } // Empuja los puntos hacia arriba con una fuerza aleatoria void pushUpDots() { for (int i = 0; i < test[scenario]; ++i) { const int SIGN = ((rand() % 2) * 2) - 1; const float VX = (((rand() % 20) + 10) * 0.1f) * SIGN; const float VY = ((rand() % 40) * 0.1f) + 5; Dot::modVel(dots[i], VX, -VY); } } // Inicializa SDL y configura la ventana y el renderizador bool init() { bool success = true; // Inicializar 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 window = SDL_CreateWindow(WINDOW_CAPTION, WIDTH * ZOOM, HEIGHT * ZOOM, 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 { // Inicializar el color del renderizador SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); // Establecer el tamaño lógico del renderizador SDL_SetRenderLogicalPresentation(renderer, WIDTH, HEIGHT, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE); } } } ticks = SDL_GetTicks(); srand(time(nullptr)); dbg_init(renderer); initDots(); setText(); return success; } // Libera los recursos y cierra SDL void close() { SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); // Finalizar SDL SDL_Quit(); } // Maneja los eventos del teclado y del sistema void checkEvents() { SDL_Event event; while (SDL_PollEvent(&event) != 0) { // Evento de salida if (event.type == SDL_EVENT_QUIT) { should_exit = true; break; } // 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: pushUpDots(); break; case SDLK_1: scenario = 0; initDots(); break; case SDLK_2: scenario = 1; initDots(); break; case SDLK_3: scenario = 2; initDots(); break; case SDLK_4: scenario = 3; initDots(); break; case SDLK_5: scenario = 4; initDots(); break; case SDLK_6: scenario = 5; initDots(); break; case SDLK_7: scenario = 6; initDots(); break; case SDLK_8: scenario = 7; initDots(); break; default: break; } } } } // Actualiza la posición de los puntos y gestiona el temporizador del texto void update() { if (SDL_GetTicks() - ticks > DEMO_SPEED) { ticks = SDL_GetTicks(); for (int i = 0; i < test[scenario]; ++i) { dot_points[i] = Dot::update(dots[i]); } 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); SDL_SetRenderDrawColor(renderer, 224, 224, 224, 255); SDL_RenderPoints(renderer, dot_points, test[scenario]); if (show_text) { dbg_print(text_pos, 8, text.c_str(), 255, 32, 32); } SDL_RenderPresent(renderer); } // Función principal int main(int argc, char *args[]) { if (!init()) { return -1; } while (!should_exit) { update(); checkEvents(); render(); } close(); return 0; }