#include "const.h" #include "struct.h" #include "director.h" #include const Uint8 *keystates; // Constructor Director::Director(std::string _path) { // Crea todos los objetos del juego initObjects(); // Inicializa todas las variables init(_path); } Director::~Director() { // Borra todos los objetos del juego deleteObjects(); // 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 todas las variables void Director::init(std::string _path) { setPath(_path); 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(); quit = false; } // Inicializa las variables de las opciones void Director::initOptions() { options.fullScreenMode = 0; options.fullScreenModePrevious = 0; options.windowSize = 0; options.windowSizePrevious = 0; } // Inicializa las variables 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 resource.texture[TEXTURE_PLAYER].texture = new LTexture(); loadTextureFromFile(resource.texture[TEXTURE_PLAYER].texture, resource.texture[TEXTURE_PLAYER].file, renderer); player = new Player(renderer, resource.texture[TEXTURE_PLAYER].texture); // Map resource.texture[TEXTURE_ACTORS].texture = new LTexture(); loadTextureFromFile(resource.texture[TEXTURE_ACTORS].texture, resource.texture[TEXTURE_ACTORS].file, renderer); resource.texture[TEXTURE_BKG_SURFACE].texture = new LTexture(); loadTextureFromFile(resource.texture[TEXTURE_BKG_SURFACE].texture, resource.texture[TEXTURE_BKG_SURFACE].file, renderer); resource.texture[TEXTURE_TILES_VOLCANO].texture = new LTexture(); loadTextureFromFile(resource.texture[TEXTURE_TILES_VOLCANO].texture, resource.texture[TEXTURE_TILES_VOLCANO].file, renderer); map = new Map(renderer, resource.texture[TEXTURE_TILES_VOLCANO].texture, resource.texture[TEXTURE_ACTORS].texture, resource.texture[TEXTURE_BKG_SURFACE].texture, resource.file[FILE_MAP_VOLCANO].file); } // Limpia las variables del juego void Director::quitGame() { // Player delete player; player = nullptr; delete resource.texture[TEXTURE_PLAYER].texture; resource.texture[TEXTURE_PLAYER].texture = nullptr; // Map delete map; map = nullptr; delete resource.texture[TEXTURE_TILES_VOLCANO].texture; resource.texture[TEXTURE_TILES_VOLCANO].texture = nullptr; delete resource.texture[TEXTURE_ACTORS].texture; resource.texture[TEXTURE_ACTORS].texture = nullptr; delete resource.texture[TEXTURE_BKG_SURFACE].texture; resource.texture[TEXTURE_BKG_SURFACE].texture = 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 los objetos del programa void Director::initObjects() { eventHandler = new SDL_Event(); text.white = new Text(); } // Borra los objetos del programa void Director::deleteObjects() { delete eventHandler; delete text.white; eventHandler = nullptr; text.white = nullptr; } // Crea el indice de ficheros de recursos void Director::setResourceList() { // Ficheros binarios resource.file[FILE_MAP_VOLCANO].file = path + "/" + "../data/volcano.map"; resource.file[FILE_CONFIG].file = path + "/" + "../data/config.bin"; // Texturas resource.texture[TEXTURE_ACTORS].file = path + "/" + "../media/gfx/actors.png"; resource.texture[TEXTURE_BKG_SURFACE].file = path + "/" + "../media/gfx/bkg_surface.png"; resource.texture[TEXTURE_FILTER].file = path + "/" + "../media/gfx/filter.png"; resource.texture[TEXTURE_HUD].file = path + "/" + "../media/gfx/hud.png"; resource.texture[TEXTURE_MENU_ANIMATION].file = path + "/" + "../media/gfx/menu_animation.png"; resource.texture[TEXTURE_MENU].file = path + "/" + "../media/gfx/menu.png"; resource.texture[TEXTURE_PLAYER].file = path + "/" + "../media/gfx/player.png"; resource.texture[TEXTURE_TILES_SURFACE].file = path + "/" + "../media/gfx/tiles_surface.png"; resource.texture[TEXTURE_TILES_VOLCANO].file = path + "/" + "../media/gfx/tiles_volcano.png"; for (Uint8 i = 0; i < TOTAL_TEXTURE; i++) resource.texture[i].texture = nullptr; // Sonidos resource.sound[SOUND_COIN].file = path + "/" + "../media/sound/sound_player_coin.wav"; resource.sound[SOUND_DEATH].file = path + "/" + "../media/sound/sound_player_death.wav"; resource.sound[SOUND_DROP_ENEMY].file = path + "/" + "../media/sound/sound_drop_enemy.wav"; resource.sound[SOUND_DROP_SPLAT].file = path + "/" + "../media/sound/sound_drop_splat.wav"; resource.sound[SOUND_JUMP].file = path + "/" + "../media/sound/sound_player_jump.wav"; resource.sound[SOUND_MENU_LOGO].file = path + "/" + "../media/sound/sound_menu_logo.wav"; resource.sound[SOUND_MENU_START].file = path + "/" + "../media/sound/sound_menu_start.wav"; for (Uint8 i = 0; i < TOTAL_SOUND; i++) resource.sound[i].sound = nullptr; // Musicas resource.music[MUSIC_MENU].file = path + "/" + "../media/music/music_menu.ogg"; resource.music[MUSIC_SURFACE].file = path + "/" + "../media/music/music_surface.ogg"; resource.music[MUSIC_VOLCANO].file = path + "/" + "../media/music/music_volcano.ogg"; for (Uint8 i = 0; i < TOTAL_TEXTURE; i++) resource.music[i].music = nullptr; } // Comprueba que todos los ficheros de recursos existen bool Director::checkResourceList() { bool success = true; std::string p; std::string filename; SDL_RWops *file; // Comprueba los ficheros de musica printf("\n>> MUSIC FILES\n"); for (Uint8 i = 0; i < TOTAL_MUSIC; i++) { p = resource.music[i].file.c_str(); filename = p.substr(p.find_last_of("\\/") + 1); file = SDL_RWFromFile(p.c_str(), "r+b"); if (file != NULL) { printf("Checking file %-20s [OK]\n", filename.c_str()); } else { success = false; printf("Checking file %-20s [ERROR]\n", filename.c_str()); } SDL_RWclose(file); } // Comprueba los ficheros de sonidos printf("\n>> SOUND FILES\n"); for (Uint8 i = 0; i < TOTAL_SOUND; i++) { p = resource.sound[i].file.c_str(); filename = p.substr(p.find_last_of("\\/") + 1); file = SDL_RWFromFile(p.c_str(), "r+b"); if (file != NULL) { printf("Checking file %-20s [OK]\n", filename.c_str()); } else { success = false; printf("Checking file %-20s [ERROR]\n", filename.c_str()); } SDL_RWclose(file); } // Comprueba los ficheros con texturas printf("\n>> TEXTURE FILES\n"); for (Uint8 i = 0; i < TOTAL_TEXTURE; i++) { p = resource.texture[i].file.c_str(); filename = p.substr(p.find_last_of("\\/") + 1); file = SDL_RWFromFile(p.c_str(), "r+b"); if (file != NULL) { printf("Checking file %-20s [OK]\n", filename.c_str()); } else { success = false; printf("Checking file %-20s [ERROR]\n", filename.c_str()); } SDL_RWclose(file); } // Resultado if (success) { printf("\n** All files OK.\n\n"); } else { printf("\n** File is missing. Exiting.\n\n"); } return success; } // Inicializa la variable con los ficheros de recursos bool Director::initResourceList() { setResourceList(); return checkResourceList(); } // Carga un archivo de imagen en una textura bool Director::loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer) { bool success = true; if (!texture->loadFromFile(path, renderer)) { printf("Failed to load %s texture!\n", path.c_str()); success = false; } return success; } // Carga los recursos necesarios bool Director::loadMedia(Uint8 section) { // Indicador de éxito en la carga bool success = true; std::string p; switch (section) { case GAME_SECTION_INIT: { p = resource.file[FILE_CONFIG].file.c_str(); std::string filename = p.substr(p.find_last_of("\\/") + 1); 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"); // Texturas // Sonidos // Musicas } break; case GAME_SECTION_TITLE: { } break; case GAME_SECTION_PLAYING: { } break; case GAME_SECTION_GAME_OVER_SCREEN: { } break; case GAME_SECTION_INTRO: { } break; case GAME_SECTION_DEMO: { } break; case GAME_SECTION_INSTRUCTIONS: { } break; case GAME_SECTION_LOGO: { } break; default: { } break; } return success; } // Descrga los recursos necesarios bool Director::unLoadMedia(Uint8 section) { // Indicador de éxito en la carga bool success = true; std::string p; switch (section) { case GAME_SECTION_INIT: { p = resource.file[FILE_CONFIG].file; 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()); } } break; case GAME_SECTION_TITLE: { } break; case GAME_SECTION_PLAYING: { } break; case GAME_SECTION_GAME_OVER_SCREEN: { } break; case GAME_SECTION_INTRO: { } break; case GAME_SECTION_DEMO: { } break; case GAME_SECTION_INSTRUCTIONS: { } break; case GAME_SECTION_LOGO: { } break; default: { } break; } return success; } // Establece el valor de la variable void Director::setPath(std::string _path) { path = _path.substr(0, _path.find_last_of("\\/")); } // 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() { // Limpia la pantalla SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); SDL_RenderClear(renderer); // Dibuja los objetos map->render(); player->render(); // Muestra el backbuffer en pantalla SDL_RenderPresent(renderer); }