#include "const.h" #include "director.h" #include const Uint8 *keystates; // Constructor Director::Director(std::string path) { // Arranca SDL y crea la ventana initSDL(); // Crea todos los objetos del juego eventHandler = new SDL_Event(); // text.white = new Text("", nullptr, nullptr); screen = new Screen(window, renderer); asset = new Asset(path.substr(0, path.find_last_of("\\/"))); setFileList(); // Inicializa todas las variables section = NONE; gameControllerFound = false; for (int i = 0; i < 360; i++) sen[i] = sin(i * 3.14 / 180); for (int i = 0; i < TOTAL_SCORE_DATA; i++) scoreData[i] = 0; initOptions(); initGame(); quit = false; } Director::~Director() { quitGame(); // Borra todos los objetos del juego delete eventHandler; eventHandler = nullptr; // delete text.white; // text.white = nullptr; delete screen; screen = nullptr; delete asset; asset = nullptr; // Destruye la ventana SDL_DestroyRenderer(renderer); SDL_DestroyTexture(backbuffer); SDL_DestroyWindow(window); backbuffer = nullptr; renderer = nullptr; window = nullptr; // Sal del subsistema SDL SDL_Quit(); } // Inicializa las variables de las opciones void Director::initOptions() { options.fullScreenMode = 0; options.fullScreenModePrevious = 0; options.windowSize = 0; options.windowSizePrevious = 0; } // Inicializa las variables y crea los objetos del juego void Director::initGame() { // Variables game.score = 0; game.section = 0; game.paused = false; game.ticks = 0; game.ticksSpeed = GAME_SPEED; game.counter = 0; // Player player = new Player(renderer, asset); // Map map = new Map(renderer, asset->get("volcano.map"), asset); } // Destruye los objetos del juego void Director::quitGame() { // Player delete player; player = nullptr; // Map delete map; map = nullptr; } // Arranca SDL y crea la ventana bool Director::initSDL() { // Indicador de inicialización bool success = true; // Inicializa SDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_HAPTIC) < 0) { printf("SDL could not initialize!\nSDL Error: %s\n", SDL_GetError()); success = false; } else { // Establece el filtro de la textura a nearest if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0")) { printf("Warning: Nearest texture filtering not enabled!\n"); } // Inicializa jail_audio JA_Init(48000, AUDIO_S16, 2); // Comprueba si hay algun mando conectado if (SDL_NumJoysticks() < 1) { printf("Warning: No joysticks connected!\n"); gameControllerFound = false; } else { // Carga el mando gameController = SDL_JoystickOpen(0); gameControllerFound = true; if (gameController == NULL) { printf("Warning: Unable to open game controller!\nSDL Error: %s\n", SDL_GetError()); gameControllerFound = false; } else { printf("%i joysticks were found.\n", SDL_NumJoysticks()); std::cout << SDL_JoystickNumButtons(gameController) << " buttons\n"; // Get controller haptic device controllerHaptic = SDL_HapticOpenFromJoystick(gameController); if (controllerHaptic == NULL) { printf("Warning: Controller does not support haptics!\nSDL Error: %s\n", SDL_GetError()); } else { printf("Haptics detected\n"); // Get initialize rumble if (SDL_HapticRumbleInit(controllerHaptic) < 0) { printf("Warning: Unable to initialize rumble!\nSDL Error: %s\n", SDL_GetError()); } } } } // Crea la ventana window = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, VIEW_WIDTH, VIEW_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); if (window == NULL) { printf("Window could not be created!\nSDL Error: %s\n", SDL_GetError()); success = false; } else { // Crea un renderizador para la ventana con vsync renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (renderer == NULL) { printf("Renderer could not be created!\nSDL Error: %s\n", SDL_GetError()); success = false; } else { // Inicializa el color de renderizado SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); // Establece el tamaño del buffer de renderizado SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT); // Establece el modo de mezcla SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); } // Crea un backbuffer para el renderizador backbuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT); if (backbuffer == NULL) { printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError()); success = false; } } } printf("\n"); return success; } // Crea el indice de ficheros de recursos bool Director::setFileList() { // Ficheros binarios asset->add("/data/volcano.map", data); asset->add("/data/config.bin", data, false); // Texturas asset->add("/media/gfx/actors.png", bitmap); asset->add("/media/gfx/bkg_surface.png", bitmap); asset->add("/media/gfx/filter.png", bitmap); asset->add("/media/gfx/hud.png", bitmap); asset->add("/media/gfx/menu_animation.png", bitmap); asset->add("/media/gfx/menu.png", bitmap); asset->add("/media/gfx/player.png", bitmap); asset->add("/media/gfx/tiles_surface.png", bitmap); asset->add("/media/gfx/tiles_volcano.png", bitmap); // Sonidos asset->add("/media/sound/sound_player_coin.wav", sound); asset->add("/media/sound/sound_player_death.wav", sound); asset->add("/media/sound/sound_drop_enemy.wav", sound); asset->add("/media/sound/sound_drop_splat.wav", sound); asset->add("/media/sound/sound_player_jump.wav", sound); asset->add("/media/sound/sound_menu_logo.wav", sound); asset->add("/media/sound/sound_menu_start.wav", sound); // Musicas asset->add("/media/music/music_menu.ogg", music); asset->add("/media/music/music_surface.ogg", music); asset->add("/media/music/music_volcano.ogg", music); return asset->check(); } // Carga el fichero de configuración bool Director::loadConfig() { // Indicador de éxito en la carga bool success = true; const std::string p = asset->get("config.bin").c_str(); const std::string filename = p.substr(p.find_last_of("\\/") + 1); // Abre el fichero con la configuracion de las opciones para leer en binario SDL_RWops *file = SDL_RWFromFile(p.c_str(), "r+b"); // El fichero no existe if (file == NULL) { printf("Warning: Unable to open %s file\n", filename.c_str()); // Crea el fichero para escribir file = SDL_RWFromFile(p.c_str(), "w+b"); if (file != NULL) { printf("New file (%s) created!\n", filename.c_str()); // Inicializa los datos options.fullScreenMode = 0; SDL_RWwrite(file, &options.fullScreenMode, sizeof(options.fullScreenMode), 1); options.windowSize = 3; SDL_RWwrite(file, &options.windowSize, sizeof(options.windowSize), 1); // Cierra el fichero SDL_RWclose(file); } else { printf("Error: Unable to create file %s\n", filename.c_str()); success = false; } } // El fichero existe else { // Carga los datos printf("Reading file %s\n", filename.c_str()); SDL_RWread(file, &options.fullScreenMode, sizeof(options.fullScreenMode), 1); SDL_SetWindowFullscreen(window, options.fullScreenMode); SDL_RWread(file, &options.windowSize, sizeof(options.windowSize), 1); SDL_SetWindowSize(window, SCREEN_WIDTH * options.windowSize, SCREEN_HEIGHT * options.windowSize); // Cierra el fichero SDL_RWclose(file); } printf("\n"); return success; } // Guarda el fichero de configuración bool Director::saveConfig() { // Indicador de éxito en la carga bool success = true; const std::string p = asset->get("config.bin"); const std::string filename = p.substr(p.find_last_of("\\/") + 1); // Abre el fichero de puntuación para escribir SDL_RWops *file = SDL_RWFromFile(p.c_str(), "w+b"); if (file != NULL) { // Guardamos los datos SDL_RWwrite(file, &options.fullScreenMode, sizeof(Uint32), 1); SDL_RWwrite(file, &options.windowSize, sizeof(Uint8), 1); printf("Writing file %s\n", filename.c_str()); // Cerramos el fichero SDL_RWclose(file); } else { printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError()); } return success; } // Obtiene el valor de la variable Uint8 Director::getGameSection() { return game.section; } // Establece el valor de la variable void Director::changeGameSection(_section sectionPrevious, _section sectionNext) { switch (sectionPrevious) { case GAME: quitGame(); break; default: break; } switch (sectionNext) { case GAME: initGame(); break; default: break; } game.section = sectionNext; } // Cambia el valor de la variable de modo de pantalla completa void Director::changeFullScreenMode() { switch (options.fullScreenMode) { case 0: options.fullScreenMode = SDL_WINDOW_FULLSCREEN; break; case SDL_WINDOW_FULLSCREEN: options.fullScreenMode = SDL_WINDOW_FULLSCREEN_DESKTOP; break; case SDL_WINDOW_FULLSCREEN_DESKTOP: options.fullScreenMode = 0; break; default: options.fullScreenMode = 0; break; } } // Comprueba si hay que salir bool Director::isRunning() { return !quit; } // Bucle para el logo del juego void Director::runLogo() { } // Bucle para la intro del juego void Director::runIntro() { } // Bucle para el titulo del juego void Director::runTitle() { } // Bucle para el juego void Director::runGame() { // Actualiza la lógica del juego updateGame(); // Pinta la sección de juego renderGame(); } // Actualiza la lógica del juego void Director::updateGame() { // Comprueba que la diferencia de ticks sea mayor a la velocidad del juego if (SDL_GetTicks() - game.ticks > game.ticksSpeed) { // Actualiza el contador de ticks game.ticks = SDL_GetTicks(); // Comprueba los eventos que hay en la cola while (SDL_PollEvent(eventHandler) != 0) { // Evento de salida de la aplicación if (eventHandler->type == SDL_QUIT) { quit = true; break; } } game.counter++; map->update(); player->update(); } } // Pinta la sección de juego void Director::renderGame() { // Prepara para empezar a dibujar el frame screen->start(); // Limpia la pantalla screen->clean(); // Dibuja los objetos map->render(); player->render(); // Vuelca el contenido del renderizador en pantalla screen->blit(); } // Bucle principal void Director::run() { while (isRunning()) { runGame(); } }