#include "title.h" #include "common/jscore.h" // Constructor Title::Title(SDL_Renderer *renderer, Screen *screen, Input *input, Asset *asset, options_t *options, Lang *lang, section_t section) { // Copia las direcciones de los punteros this->renderer = renderer; this->screen = screen; this->input = input; this->asset = asset; this->options = options; this->lang = lang; this->section = section; // Reserva memoria para los punteros eventHandler = new SDL_Event(); fade = new Fade(renderer); dustTexture = new Texture(renderer, asset->get("title_dust.png")); coffeeTexture = new Texture(renderer, asset->get("title_coffee.png")); crisisTexture = new Texture(renderer, asset->get("title_crisis.png")); gradientTexture = new Texture(renderer, asset->get("title_gradient.png")); coffeeBitmap = new SmartSprite(coffeeTexture, renderer); crisisBitmap = new SmartSprite(crisisTexture, renderer); dustBitmapL = new AnimatedSprite(dustTexture, renderer, asset->get("title_dust.ani")); dustBitmapR = new AnimatedSprite(dustTexture, renderer, asset->get("title_dust.ani")); gradient = new Sprite({0, 0, 256, 192}, gradientTexture, renderer); text1 = new Text(asset->get("smb2.png"), asset->get("smb2.txt"), renderer); text2 = new Text(asset->get("8bithud.png"), asset->get("8bithud.txt"), renderer); menu.title = new Menu(renderer, asset, input, asset->get("title.men")); menu.options = new Menu(renderer, asset, input, asset->get("options.men")); menu.playerSelect = new Menu(renderer, asset, input, asset->get("player_select.men")); // Sonidos crashSound = JA_LoadSound(asset->get("title.wav").c_str()); // Musicas titleMusic = JA_LoadMusic(asset->get("title.ogg").c_str()); // Inicializa los valores init(); } // Destructor Title::~Title() { delete eventHandler; delete fade; dustTexture->unload(); delete dustTexture; coffeeTexture->unload(); delete coffeeTexture; crisisTexture->unload(); delete crisisTexture; gradientTexture->unload(); delete gradientTexture; delete coffeeBitmap; delete crisisBitmap; delete dustBitmapL; delete dustBitmapR; delete gradient; delete text1; delete text2; delete menu.title; delete menu.options; delete menu.playerSelect; JA_DeleteSound(crashSound); JA_DeleteMusic(titleMusic); SDL_DestroyTexture(background); } // Inicializa los valores void Title::init() { // Inicializa variables section.subsection = TITLE_SECTION_1; counter = TITLE_COUNTER; backgroundCounter = 0; backgroundMode = rand() % 2; menuVisible = false; menu.active = menu.title; nextSection.name = PROG_SECTION_GAME; postFade = 0; ticks = 0; ticksSpeed = 15; fade->init(0x17, 0x17, 0x26); demo = true; // Pone valores por defecto a las opciones de control options->input.clear(); input_t i; i.id = 0; i.name = "KEYBOARD"; i.deviceType = INPUT_USE_KEYBOARD; options->input.push_back(i); i.id = 0; i.name = "GAME CONTROLLER"; i.deviceType = INPUT_USE_GAMECONTROLLER; options->input.push_back(i); // Comprueba si hay mandos conectados checkInputDevices(); // Pone valores por defecto. El primer jugador el teclado. El segundo jugador el primer mando deviceIndex.clear(); deviceIndex.push_back(availableInputDevices.size() - 1); // El último dispositivo encontrado es el teclado deviceIndex.push_back(0); // El primer mando encontrado. Si no ha encontrado ninguno es el teclado // Si ha encontrado un mando se lo asigna al segundo jugador if (input->gameControllerFound()) { options->input[1].id = availableInputDevices[deviceIndex[1]].id; options->input[1].name = availableInputDevices[deviceIndex[1]].name; options->input[1].deviceType = availableInputDevices[deviceIndex[1]].deviceType; } // Inicializa el bitmap de Coffee coffeeBitmap->init(); coffeeBitmap->setPosX(45); coffeeBitmap->setPosY(11 - 200); coffeeBitmap->setWidth(167); coffeeBitmap->setHeight(46); coffeeBitmap->setVelX(0.0f); coffeeBitmap->setVelY(2.5f); coffeeBitmap->setAccelX(0.0f); coffeeBitmap->setAccelY(0.1f); coffeeBitmap->setSpriteClip(0, 0, 167, 46); coffeeBitmap->setEnabled(true); coffeeBitmap->setEnabledCounter(0); coffeeBitmap->setDestX(45); coffeeBitmap->setDestY(11); // Inicializa el bitmap de Crisis crisisBitmap->init(); crisisBitmap->setPosX(60); crisisBitmap->setPosY(57 + 200); crisisBitmap->setWidth(137); crisisBitmap->setHeight(46); crisisBitmap->setVelX(0.0f); crisisBitmap->setVelY(-2.5f); crisisBitmap->setAccelX(0.0f); crisisBitmap->setAccelY(-0.1f); crisisBitmap->setSpriteClip(0, 0, 137, 46); crisisBitmap->setEnabled(true); crisisBitmap->setEnabledCounter(0); crisisBitmap->setDestX(60); crisisBitmap->setDestY(57); // Inicializa el bitmap de DustRight dustBitmapR->resetAnimation(); dustBitmapR->setPosX(218); dustBitmapR->setPosY(47); dustBitmapR->setWidth(16); dustBitmapR->setHeight(16); dustBitmapR->setFlip(SDL_FLIP_HORIZONTAL); // Inicializa el bitmap de DustLeft dustBitmapL->resetAnimation(); dustBitmapL->setPosX(33); dustBitmapL->setPosY(47); dustBitmapL->setWidth(16); dustBitmapL->setHeight(16); // Inicializa el sprite con el degradado gradient->setSpriteClip(0, 96, 256, 192); // Crea el mosaico de fondo del titulo createTiledBackground(); // Coloca la ventana que recorre el mosaico de fondo de manera que coincida con el mosaico que hay pintado en el titulo al iniciar backgroundWindow.x = 128; backgroundWindow.y = 96; backgroundWindow.w = GAMECANVAS_WIDTH; backgroundWindow.h = GAMECANVAS_HEIGHT; // Inicializa los valores del vector con los valores del seno for (int i = 0; i < 360; ++i) { sin[i] = SDL_sinf((float)i * 3.14f / 180.0f); } // Actualiza los textos de los menus updateMenuLabels(); } // Actualiza las variables del objeto void Title::update() { // Comprueba los eventos checkEventHandler(); // Comprueba las entradas checkInput(); // Calcula la lógica de los objetos if (SDL_GetTicks() - ticks > ticksSpeed) { // Actualiza el contador de ticks ticks = SDL_GetTicks(); // Actualiza las notificaciones screen->updateNotifier(); switch (section.subsection) { // Sección 1 - Titulo desplazandose case TITLE_SECTION_1: { // Actualiza los objetos coffeeBitmap->update(); crisisBitmap->update(); // Si los objetos han llegado a su destino, cambiamos de Sección if (coffeeBitmap->hasFinished() && crisisBitmap->hasFinished()) { section.subsection = TITLE_SECTION_2; // Pantallazo blanco SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); SDL_RenderClear(renderer); SDL_RenderPresent(renderer); // Reproduce el efecto sonoro JA_PlaySound(crashSound); } } break; // Sección 2 - Titulo vibrando case TITLE_SECTION_2: { // Agita la pantalla static const int v[] = {-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 0}; static const int a = coffeeBitmap->getPosX(); static const int b = crisisBitmap->getPosX(); static int step = 0; coffeeBitmap->setPosX(a + v[step / 3]); crisisBitmap->setPosX(b + v[step / 3]); dustBitmapR->update(); dustBitmapL->update(); step++; if (step == 33) { section.subsection = TITLE_SECTION_3; } } break; // Sección 3 - La pantalla de titulo con el menú y la música case TITLE_SECTION_3: { if (counter > 0) { // Reproduce la música if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) { JA_PlayMusic(titleMusic); } dustBitmapR->update(); dustBitmapL->update(); // Actualiza la lógica del titulo fade->update(); if (fade->hasEnded()) { switch (postFade) { case 0: // 1 PLAYER section.name = PROG_SECTION_GAME; section.subsection = GAME_SECTION_PLAY_1P; JA_StopMusic(); break; case 1: // 2 PLAYERS section.name = PROG_SECTION_GAME; section.subsection = GAME_SECTION_PLAY_2P; JA_StopMusic(); break; case 2: // QUIT section.name = PROG_SECTION_QUIT; JA_StopMusic(); break; case 3: // TIME OUT counter = TITLE_COUNTER; menu.active->reset(); if (demo) { runDemoGame(); if (section.name != PROG_SECTION_QUIT) { runInstructions(m_auto); } if (section.name != PROG_SECTION_QUIT) { runHiScoreTable(mhst_auto); } } else section.name = PROG_SECTION_LOGO; break; default: break; } } // Actualiza el tileado de fondo updateBG(); // Comprueba las entradas para el menu if (menuVisible == true) { menu.active->update(); } // Comprueba si se ha seleccionado algún item del menú de titulo if (menu.active->getName() == "TITLE") { switch (menu.active->getItemSelected()) { case 0: // 1 PLAYER -> Cambia al manu de selección de jugador menu.active = menu.playerSelect; break; case 1: // 2 PLAYERS postFade = 1; fade->activateFade(); break; case 2: // OPTIONS menu.active = menu.options; optionsPrevious = *options; break; case 3: // QUIT postFade = 2; fade->activateFade(); break; default: break; } } // Comprueba si se ha seleccionado algún item del menú de selección de jugador if (menu.active->getName() == "PLAYER_SELECT") { switch (menu.active->getItemSelected()) { case 0: // Este item no se puede seleccionar y actua de titulo break; case 1: // BAL1 postFade = 0; options->playerSelected = 0; fade->activateFade(); break; case 2: // AROUNDER postFade = 0; options->playerSelected = 1; fade->activateFade(); break; case 3: // BACK menu.active = menu.title; menu.playerSelect->reset(); break; default: break; } } // Comprueba si se ha seleccionado algún item de opciones if (menu.active->getName() == "OPTIONS") { switch (menu.active->getItemSelected()) { case 0: // Difficulty if (options->difficulty == DIFFICULTY_EASY) options->difficulty = DIFFICULTY_NORMAL; else if (options->difficulty == DIFFICULTY_NORMAL) options->difficulty = DIFFICULTY_HARD; else options->difficulty = DIFFICULTY_EASY; updateMenuLabels(); break; case 1: // PLAYER 1 CONTROLS updatePlayerInputs(0); updateMenuLabels(); break; case 3: // PLAYER 2 CONTROLS updatePlayerInputs(1); updateMenuLabels(); break; case 5: // Language options->language++; if (options->language == 3) options->language = 0; updateMenuLabels(); break; case 6: // Display mode switchFullScreenModeVar(); if (options->videoMode != 0) { menu.options->setSelectable(8, false); menu.options->setGreyed(8, true); } else { menu.options->setSelectable(8, true); menu.options->setGreyed(8, false); } updateMenuLabels(); break; case 8: // Windows size options->windowSize++; if (options->windowSize == 5) options->windowSize = 1; updateMenuLabels(); break; case 9: // FILTER if (options->filter == FILTER_LINEAL) options->filter = FILTER_NEAREST; else options->filter = FILTER_LINEAL; updateMenuLabels(); break; case 10: // VSYNC if (options->vSync) options->vSync = false; else options->vSync = true; updateMenuLabels(); break; case 11: // HOW TO PLAY runInstructions(m_manual); break; case 12: // ACCEPT applyOptions(); menu.active->reset(); menu.active = menu.title; break; case 13: // CANCEL options = &optionsPrevious; updateMenuLabels(); menu.active->reset(); menu.active = menu.title; break; default: break; } } if (menu.active->getName() == "TITLE") { counter--; } } else if (counter == 0) { if (demo) { runDemoGame(); if (section.name != PROG_SECTION_QUIT) { runInstructions(m_auto); } if (section.name != PROG_SECTION_QUIT) { runHiScoreTable(mhst_auto); } init(); demo = false; counter = TITLE_COUNTER; } else { section.name = PROG_SECTION_LOGO; } } // Sección Instrucciones if (section.subsection == TITLE_SECTION_INSTRUCTIONS) { runInstructions(m_auto); counter = TITLE_COUNTER; demo = true; } } break; default: break; } } } // Dibuja el objeto en pantalla void Title::render() { switch (section.subsection) { // Sección 1 - Titulo desplazandose case TITLE_SECTION_1: { // Prepara para empezar a dibujar en la textura de juego screen->start(); // Limpia la pantalla screen->clean(bgColor); // Dibuja el tileado de fondo SDL_RenderCopy(renderer, background, &backgroundWindow, nullptr); // Dibuja el degradado gradient->render(); // Dibuja los objetos coffeeBitmap->render(); crisisBitmap->render(); // Vuelca el contenido del renderizador en pantalla screen->blit(); } break; // Sección 2 - Titulo vibrando case TITLE_SECTION_2: { // Reproduce el efecto sonoro JA_PlaySound(crashSound); // Agita la pantalla const int v[] = {-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 0}; const int a = coffeeBitmap->getPosX(); const int b = crisisBitmap->getPosX(); for (int n = 0; n < 11 * 3; ++n) { // Prepara para empezar a dibujar en la textura de juego screen->start(); // Limpia la pantalla screen->clean(bgColor); // Dibuja el tileado de fondo SDL_RenderCopy(renderer, background, &backgroundWindow, nullptr); // Dibuja el degradado gradient->render(); // Dibuja los objetos coffeeBitmap->setPosX(a + v[n / 3]); crisisBitmap->setPosX(b + v[n / 3]); coffeeBitmap->render(); crisisBitmap->render(); dustBitmapR->update(); dustBitmapL->update(); dustBitmapR->render(); dustBitmapL->render(); // Vuelca el contenido del renderizador en pantalla screen->blit(); } section.subsection = TITLE_SECTION_3; } break; // Sección 3 - La pantalla de titulo con el menú y la música case TITLE_SECTION_3: { // Prepara para empezar a dibujar en la textura de juego screen->start(); // Limpia la pantalla screen->clean(bgColor); // Dibuja el tileado de fondo SDL_RenderCopy(renderer, background, &backgroundWindow, nullptr); // Dibuja el degradado gradient->render(); // Dibuja los objetos if (menu.active->getName() != "OPTIONS") { // Bitmaps con el logo/titulo del juego coffeeBitmap->render(); crisisBitmap->render(); // Texto con el copyright y versión text2->writeDX(TXT_CENTER | TXT_SHADOW, GAMECANVAS_CENTER_X, GAMECANVAS_HEIGHT - (BLOCK * 2), TEXT_COPYRIGHT, 1, noColor, 1, shdwTxtColor); } if (menuVisible == true) { menu.active->render(); } dustBitmapR->render(); dustBitmapL->render(); // PRESS ANY KEY! if ((counter % 50 > 14) && (menuVisible == false)) { text1->writeDX(TXT_CENTER | TXT_SHADOW, GAMECANVAS_CENTER_X, PLAY_AREA_THIRD_QUARTER_Y + BLOCK, lang->getText(23), 1, noColor, 1, shdwTxtColor); } // Fade fade->render(); // Vuelca el contenido del renderizador en pantalla screen->blit(); } break; default: break; } } // Comprueba los eventos void Title::checkEventHandler() { // 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) { section.name = PROG_SECTION_QUIT; break; } else if (eventHandler->type == SDL_RENDER_DEVICE_RESET || eventHandler->type == SDL_RENDER_TARGETS_RESET) { reLoadTextures(); } if (section.subsection == TITLE_SECTION_3) { // Si se pulsa alguna tecla durante la tercera sección del titulo if ((eventHandler->type == SDL_KEYUP) || (eventHandler->type == SDL_JOYBUTTONUP)) { // Muestra el menu menuVisible = true; // Reinicia el contador counter = TITLE_COUNTER; } } } } // Comprueba las entradas void Title::checkInput() { if (input->checkInput(input_exit, REPEAT_FALSE)) { section.name = PROG_SECTION_QUIT; } else if (input->checkInput(input_window_fullscreen, REPEAT_FALSE)) { screen->switchVideoMode(); } else if (input->checkInput(input_window_dec_size, REPEAT_FALSE)) { screen->decWindowSize(); } else if (input->checkInput(input_window_inc_size, REPEAT_FALSE)) { screen->incWindowSize(); } else if (input->checkInput(input_pause, REPEAT_FALSE) || input->checkInput(input_accept, REPEAT_FALSE) || input->checkInput(input_fire_left, REPEAT_FALSE) || input->checkInput(input_fire_center, REPEAT_FALSE) || input->checkInput(input_fire_right, REPEAT_FALSE)) { section.name = PROG_SECTION_TITLE; section.subsection = TITLE_SECTION_1; } } // Actualiza el tileado de fondo void Title::updateBG() { if (backgroundMode == 0) { // El tileado de fondo se desplaza en diagonal ++backgroundWindow.x %= 64; ++backgroundWindow.y %= 64; } else { // El tileado de fondo se desplaza en circulo ++backgroundCounter %= 360; backgroundWindow.x = 128 + (int(sin[(backgroundCounter + 270) % 360] * 128)); backgroundWindow.y = 96 + (int(sin[(360 - backgroundCounter) % 360] * 96)); } } // Cambia el valor de la variable de modo de pantalla completa void Title::switchFullScreenModeVar() { switch (options->videoMode) { case 0: options->videoMode = SDL_WINDOW_FULLSCREEN; break; case SDL_WINDOW_FULLSCREEN: options->videoMode = SDL_WINDOW_FULLSCREEN_DESKTOP; break; case SDL_WINDOW_FULLSCREEN_DESKTOP: options->videoMode = 0; break; default: options->videoMode = 0; break; } } // Actualiza los elementos de los menus void Title::updateMenuLabels() { int i = 0; // DIFFICULTY switch (options->difficulty) { case DIFFICULTY_EASY: menu.options->setItemCaption(i, lang->getText(59) + ": " + lang->getText(66)); // EASY break; case DIFFICULTY_NORMAL: menu.options->setItemCaption(i, lang->getText(59) + ": " + lang->getText(67)); // NORMAL break; case DIFFICULTY_HARD: menu.options->setItemCaption(i, lang->getText(59) + ": " + lang->getText(68)); // HARD break; default: menu.options->setItemCaption(i, lang->getText(59) + ": " + lang->getText(67)); // NORMAL break; } i++; // PLAYER 1 CONTROLS menu.options->setItemCaption(i, lang->getText(62)); i++; // PLAYER 1 CONTROLS - OPTIONS switch (options->input[0].deviceType) { case INPUT_USE_KEYBOARD: menu.options->setItemCaption(i, lang->getText(69)); // KEYBOARD menu.options->setGreyed(i, false); break; case INPUT_USE_GAMECONTROLLER: menu.options->setItemCaption(i, lang->getText(70)); // GAME CONTROLLER if (!input->gameControllerFound()) menu.options->setGreyed(i, true); else { menu.options->setGreyed(i, false); menu.options->setItemCaption(i, options->input[0].name); } break; default: menu.options->setItemCaption(i, lang->getText(69)); // KEYBOARD break; } i++; // PLAYER 2 CONTROLS menu.options->setItemCaption(i, lang->getText(63)); i++; // PLAYER 2 CONTROLS - OPTIONS switch (options->input[1].deviceType) { case INPUT_USE_KEYBOARD: menu.options->setItemCaption(i, lang->getText(69)); // KEYBOARD menu.options->setGreyed(i, false); break; case INPUT_USE_GAMECONTROLLER: menu.options->setItemCaption(i, lang->getText(70)); // GAME CONTROLLER if (!input->gameControllerFound()) menu.options->setGreyed(i, true); else { menu.options->setGreyed(i, false); menu.options->setItemCaption(i, options->input[1].name); } break; default: menu.options->setItemCaption(i, lang->getText(69)); // KEYBOARD break; } i++; // LANGUAGE switch (options->language) { case es_ES: menu.options->setItemCaption(i, lang->getText(8) + ": " + lang->getText(24)); // SPANISH break; case ba_BA: menu.options->setItemCaption(i, lang->getText(8) + ": " + lang->getText(25)); // VALENCIAN break; case en_UK: menu.options->setItemCaption(i, lang->getText(8) + ": " + lang->getText(26)); // ENGLISH break; default: menu.options->setItemCaption(i, lang->getText(8) + ": " + lang->getText(26)); // ENGLISH break; } i++; // DISPLAY MODE menu.options->setItemCaption(i, lang->getText(58)); i++; // DISPLAY MODE - OPTIONS switch (options->videoMode) { case 0: menu.options->setItemCaption(i, lang->getText(4)); // WINDOW break; case SDL_WINDOW_FULLSCREEN: menu.options->setItemCaption(i, lang->getText(5)); // FULLSCREEN break; case SDL_WINDOW_FULLSCREEN_DESKTOP: menu.options->setItemCaption(i, lang->getText(6)); // FAKE FULLSCREEN break; default: menu.options->setItemCaption(i, lang->getText(4)); // WINDOW break; } i++; // WINDOW SIZE menu.options->setItemCaption(i, lang->getText(7) + " x" + std::to_string(options->windowSize)); // WINDOW SIZE i++; // FILTER if (options->filter == FILTER_LINEAL) menu.options->setItemCaption(i, lang->getText(60) + ": " + lang->getText(71)); // BILINEAL else menu.options->setItemCaption(i, lang->getText(60) + ": " + lang->getText(72)); // LINEAL i++; // VSYNC if (options->vSync) menu.options->setItemCaption(i, lang->getText(61) + ": " + lang->getText(73)); // ON else menu.options->setItemCaption(i, lang->getText(61) + ": " + lang->getText(74)); // OFF i++; // HOW TO PLAY menu.options->setItemCaption(i, lang->getText(2)); i++; // ACCEPT menu.options->setItemCaption(i, lang->getText(9)); // ACCEPT i++; // CANCEL menu.options->setItemCaption(i, lang->getText(10)); // CANCEL // Recoloca el menu de opciones menu.options->centerMenuOnX(GAMECANVAS_CENTER_X); menu.options->centerMenuOnY(GAMECANVAS_CENTER_Y); menu.options->centerMenuElementsOnX(); // Establece las etiquetas del menu de titulo menu.title->setItemCaption(0, lang->getText(51)); // 1 PLAYER menu.title->setItemCaption(1, lang->getText(52)); // 2 PLAYERS menu.title->setItemCaption(2, lang->getText(1)); // OPTIONS menu.title->setItemCaption(3, lang->getText(3)); // QUIT // Recoloca el menu de titulo menu.title->centerMenuOnX(GAMECANVAS_CENTER_X); menu.title->centerMenuElementsOnX(); // Establece las etiquetas del menu de seleccion de jugador menu.playerSelect->setItemCaption(0, lang->getText(39)); // SELECT PLAYER menu.playerSelect->setItemCaption(3, lang->getText(40)); // BACK // Recoloca el menu de selección de jugador menu.playerSelect->centerMenuOnX(GAMECANVAS_CENTER_X); menu.playerSelect->centerMenuElementsOnX(); } // Aplica las opciones de menu seleccionadas void Title::applyOptions() { screen->setVideoMode(options->videoMode); lang->setLang(options->language); updateMenuLabels(); createTiledBackground(); } // Bucle para el titulo del juego section_t Title::run() { while (section.name == PROG_SECTION_TITLE) { update(); render(); } return section; } // Ejecuta la parte donde se muestran las instrucciones section_t Title::runInstructions(mode_e mode) { instructions = new Instructions(renderer, screen, asset, lang); section = instructions->run(mode); delete instructions; return section; } // Ejecuta la parte donde se muestra la tabla de puntuaciones section_t Title::runHiScoreTable(mode_hiScoreTable_e mode) { if (!options->online.enabled) { section.name = PROG_SECTION_TITLE; section.subsection = TITLE_SECTION_1; return section; } hiScoreTable = new HiScoreTable(renderer, screen, asset, lang, options); section = hiScoreTable->run(mode); delete hiScoreTable; return section; } // Ejecuta el juego en modo demo section_t Title::runDemoGame() { demoGame = new Game(1, 0, renderer, screen, asset, lang, input, true, options); section = demoGame->run(); delete demoGame; return section; } // Modifica las opciones para los controles de los jugadores bool Title::updatePlayerInputs(int numPlayer) { const int numDevices = availableInputDevices.size(); if (!input->gameControllerFound()) { // Si no hay mandos se deja todo de manera prefijada deviceIndex[0] = 0; deviceIndex[1] = 0; options->input[0].id = -1; options->input[0].name = "KEYBOARD"; options->input[0].deviceType = INPUT_USE_KEYBOARD; options->input[1].id = 0; options->input[1].name = "GAME CONTROLLER"; options->input[1].deviceType = INPUT_USE_GAMECONTROLLER; return true; } else { // Si hay mas de un dispositivo, se recorre el vector if (options->console) { std::cout << "numplayer:" << numPlayer << std::endl; std::cout << "deviceindex:" << deviceIndex[numPlayer] << std::endl; } // Incrementa el indice if (deviceIndex[numPlayer] < numDevices - 1) { deviceIndex[numPlayer]++; } else { deviceIndex[numPlayer] = 0; } if (options->console) { std::cout << "deviceindex:" << deviceIndex[numPlayer] << std::endl; } // Si coincide con el del otro jugador, se lo intercambian if (deviceIndex[0] == deviceIndex[1]) { const int theOtherPlayer = (numPlayer + 1) % 2; deviceIndex[theOtherPlayer]--; if (deviceIndex[theOtherPlayer] < 0) { deviceIndex[theOtherPlayer] = numDevices - 1; } } // Copia el dispositivo marcado por el indice a la variable de opciones de cada jugador options->input[0] = availableInputDevices[deviceIndex[0]]; options->input[1] = availableInputDevices[deviceIndex[1]]; return true; } } // Crea el mosaico de fondo del titulo void Title::createTiledBackground() { // Crea la textura para el mosaico de fondo background = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH * 2, GAMECANVAS_HEIGHT * 2); if (background == nullptr) { if (options->console) { std::cout << "TitleSurface could not be created!\nSDL Error: " << SDL_GetError() << std::endl; } } // Crea los objetos para pintar en la textura de fondo Texture *bgTileTexture = new Texture(renderer, asset->get("title_bg_tile.png")); Sprite *tile = new Sprite({0, 0, 64, 64}, bgTileTexture, renderer); // Prepara para dibujar sobre la textura SDL_SetRenderTarget(renderer, background); SDL_SetRenderDrawColor(renderer, 0x43, 0x43, 0x4F, 0xFF); SDL_RenderClear(renderer); // Rellena la textura con el tile tile->setSpriteClip(0, 0, 64, 64); for (int i = 0; i < 8; ++i) { for (int j = 0; j < 6; ++j) { tile->setPosX(i * 64); tile->setPosY(j * 64); tile->render(); } } // Vuelve a colocar el renderizador apuntando a la pantalla SDL_SetRenderTarget(renderer, nullptr); // Libera la memoria utilizada por los objetos bgTileTexture->unload(); delete bgTileTexture; delete tile; } // Comprueba cuantos mandos hay conectados para gestionar el menu de opciones void Title::checkInputDevices() { if (options->console) { std::cout << "Filling devices for options menu..." << std::endl; } input->discoverGameController(); const int numControllers = input->getNumControllers(); availableInputDevices.clear(); input_t temp; // Añade todos los mandos if (numControllers > 0) for (int i = 0; i < numControllers; ++i) { temp.id = i; temp.name = input->getControllerName(i); temp.deviceType = INPUT_USE_GAMECONTROLLER; availableInputDevices.push_back(temp); if (options->console) { std::cout << "Device " << (int)availableInputDevices.size() << " - " << temp.name.c_str() << std::endl; } } // Añade el teclado al final temp.id = -1; temp.name = "KEYBOARD"; temp.deviceType = INPUT_USE_KEYBOARD; availableInputDevices.push_back(temp); if (options->console) { std::cout << "Device " << (int)availableInputDevices.size() << " - " << temp.name.c_str() << std::endl; std::cout << std::endl; } } // Recarga las texturas void Title::reLoadTextures() { dustTexture->reLoad(); coffeeTexture->reLoad(); crisisTexture->reLoad(); gradientTexture->reLoad(); createTiledBackground(); }