diff --git a/source/menu.cpp b/source/menu.cpp index cf7e9b6..717fd87 100644 --- a/source/menu.cpp +++ b/source/menu.cpp @@ -2,12 +2,15 @@ #include "menu.h" // Constructor -Menu::Menu(SDL_Renderer *renderer, Text *text, Input *input, Asset *asset) +Menu::Menu(SDL_Renderer *renderer, Text *text, Input *input) { this->renderer = renderer; this->text = text; this->input = input; - this->asset = asset; + + soundMove = nullptr; + soundAccept = nullptr; + soundCancel = nullptr; } Menu::~Menu() @@ -15,21 +18,26 @@ Menu::~Menu() renderer = nullptr; text = nullptr; input = nullptr; - asset = nullptr; - JA_DeleteSound(soundAccept); - JA_DeleteSound(soundCancel); - JA_DeleteSound(soundMove); + if (soundMove) + { + JA_DeleteSound(soundMove); + } + + if (soundAccept) + { + JA_DeleteSound(soundAccept); + } + + if (soundCancel) + { + JA_DeleteSound(soundCancel); + } } // Inicializador void Menu::init(std::string name, int x, int y, int backgroundType) { - // Sonidos - soundMove = JA_LoadSound(asset->get("sound_menu_move.wav").c_str()); - soundAccept = JA_LoadSound(asset->get("sound_menu_select.wav").c_str()); - soundCancel = JA_LoadSound(asset->get("sound_menu_cancel.wav").c_str()); - // Inicia variables this->name = name; selector.index = 0; @@ -66,6 +74,28 @@ void Menu::init(std::string name, int x, int y, int backgroundType) selector.a = 255; } +// Carga los ficheros de audio +void Menu::loadAudioFile(std::string file, int sound) +{ + switch (sound) + { + case SOUND_ACCEPT: + soundAccept = JA_LoadSound(file.c_str()); + break; + + case SOUND_CANCEL: + soundCancel = JA_LoadSound(file.c_str()); + break; + + case SOUND_MOVE: + soundMove = JA_LoadSound(file.c_str()); + break; + + default: + break; + } +} + // Obtiene el nombre del menu std::string Menu::getName() { @@ -185,19 +215,26 @@ void Menu::reset() void Menu::reorganize() { setRectSize(); + if (isCenteredOnX) + { centerMenuOnX(centerX); + } + if (isCenteredOnY) + { centerMenuOnY(centerY); + } + if (areElementsCenteredOnX) + { centerMenuElementsOnX(); + } } // Deja el menu apuntando al siguiente elemento bool Menu::increaseSelectorIndex() { - bool success = false; - // Obten las coordenadas del elemento actual selector.y = selector.originY = item[selector.index].rect.y; selector.h = selector.originH = getSelectorHeight(selector.index); @@ -208,30 +245,26 @@ bool Menu::increaseSelectorIndex() { ++selector.index %= item.size(); } - success = true; // Establece las coordenadas y altura de destino - if (success) + selector.targetY = item[selector.index].rect.y; + selector.despY = (selector.targetY - selector.originY) / selector.numJumps; + + selector.targetH = getSelectorHeight(selector.index); + selector.incH = (selector.targetH - selector.originH) / selector.numJumps; + + selector.moving = true; + if (selector.incH != 0) { - selector.targetY = item[selector.index].rect.y; - selector.despY = (selector.targetY - selector.originY) / selector.numJumps; - - selector.targetH = getSelectorHeight(selector.index); - selector.incH = (selector.targetH - selector.originH) / selector.numJumps; - - selector.moving = true; - if (selector.incH != 0) - selector.resizing = true; + selector.resizing = true; } - return success; + return true; } // Deja el menu apuntando al elemento anterior bool Menu::decreaseSelectorIndex() { - bool success = false; - // Obten las coordenadas del elemento actual selector.y = selector.originY = item[selector.index].rect.y; selector.h = selector.originH = getSelectorHeight(selector.index); @@ -245,35 +278,39 @@ bool Menu::decreaseSelectorIndex() { selector.index--; } + while (!item[selector.index].selectable) { if (selector.index == 0) + { selector.index = item.size(); + } else + { selector.index--; + } } - success = true; // Establece las coordenadas y altura de destino - if (success) + selector.targetY = item[selector.index].rect.y; + selector.despY = (selector.targetY - selector.originY) / selector.numJumps; + + selector.targetH = getSelectorHeight(selector.index); + selector.incH = (selector.targetH - selector.originH) / selector.numJumps; + + selector.moving = true; + if (selector.incH != 0) { - selector.targetY = item[selector.index].rect.y; - selector.despY = (selector.targetY - selector.originY) / selector.numJumps; - - selector.targetH = getSelectorHeight(selector.index); - selector.incH = (selector.targetH - selector.originH) / selector.numJumps; - - selector.moving = true; - if (selector.incH != 0) - selector.resizing = true; + selector.resizing = true; } - return success; + return true; } // Actualiza la logica del menu void Menu::update() { + checkInput(); updateSelector(); } @@ -288,9 +325,9 @@ void Menu::render() } // Renderiza el rectangulo del selector - SDL_Rect temp = selector.rect; - temp.y--; - temp.h++; + const SDL_Rect temp = {selector.rect.x, selector.rect.y - 1, selector.rect.w, selector.rect.h + 1}; + // temp.y--; + // temp.h++; SDL_SetRenderDrawColor(renderer, selector.color.r, selector.color.g, selector.color.b, selector.a); SDL_RenderFillRect(renderer, &temp); @@ -317,7 +354,8 @@ void Menu::render() { text->writeColored(item[i].rect.x, item[i].rect.y, item[i].label, colorGreyed); } - else // No seleccionable + else + // No seleccionable { if ((item[i].linkedUp) && (i == selector.index + 1)) { @@ -436,11 +474,15 @@ void Menu::addItem(std::string text, int hPaddingDown, bool selectable, bool gre temp.linkedDown = linkedDown; item.push_back(temp); - setItemCaption(item.size(), text); + setItemCaption(item.size() - 1, text); if (item.size() > 0) + { if (item[item.size() - 1].linkedDown) + { item[item.size()].linkedUp = true; + } + } centerX = x + (findWidth() / 2); reorganize(); @@ -465,23 +507,43 @@ void Menu::setDefaultActionWhenCancel(int item) void Menu::checkInput() { if (input->checkInput(INPUT_UP, REPEAT_FALSE)) + { if (decreaseSelectorIndex()) - JA_PlaySound(soundMove); + { + if (soundMove) + { + JA_PlaySound(soundMove); + } + } + } if (input->checkInput(INPUT_DOWN, REPEAT_FALSE)) + { if (increaseSelectorIndex()) - JA_PlaySound(soundMove); + { + if (soundMove) + { + JA_PlaySound(soundMove); + } + } + } if (input->checkInput(INPUT_ACCEPT, REPEAT_FALSE)) { itemSelected = selector.index; - JA_PlaySound(soundAccept); + if (soundAccept) + { + JA_PlaySound(soundAccept); + } } if (input->checkInput(INPUT_CANCEL, REPEAT_FALSE)) { itemSelected = defaultActionWhenCancel; - JA_PlaySound(soundCancel); + if (soundCancel) + { + JA_PlaySound(soundCancel); + } } } @@ -511,7 +573,9 @@ void Menu::replaceElementsOnY() item[0].rect.y = y; for (int i = 1; i < item.size(); i++) + { item[i].rect.y = item[i - 1].rect.y + item[i - 1].rect.h + item[i - 1].hPaddingDown; + } } // Establece el estado seleccionable de un item @@ -536,7 +600,11 @@ void Menu::setLinkedDown(int index, bool value) int Menu::getSelectorHeight(int value) { if (item[value].linkedDown) + { return item[value].rect.h + item[value].hPaddingDown + item[value + 1].rect.h; + } else + { return item[value].rect.h; + } } \ No newline at end of file diff --git a/source/menu.h b/source/menu.h index c3ff945..c0731e6 100644 --- a/source/menu.h +++ b/source/menu.h @@ -5,7 +5,6 @@ #include "sprite.h" #include "text.h" #include "input.h" -#include "asset.h" #include "utils.h" #include "jail_audio.h" @@ -16,6 +15,11 @@ #define MENU_BACKGROUND_TRANSPARENT 0 #define MENU_BACKGROUND_SOLID 1 +// Tipos de archivos de audio +#define SOUND_ACCEPT 0 +#define SOUND_MOVE 1 +#define SOUND_CANCEL 2 + // Opciones de menu #define MENU_NO_OPTION -1 @@ -23,36 +27,12 @@ class Menu { private: - std::string name; // Nombre del menu - int x; // Posición en el eje X de la primera letra del primer elemento - int y; // Posición en el eje Y de la primera letra del primer elemento - int h; // Altura del menu - int w; // Anchura del menu - int itemSelected; // Índice del item del menu que ha sido seleccionado - int defaultActionWhenCancel; // Indice del item del menu que se selecciona cuando se cancela el menu - int backgroundType; // Tipo de fondo para el menu - int centerX; // Centro del menu en el eje X - int centerY; // Centro del menu en el eje Y - bool isCenteredOnX; // Variable para saber si el menu debe estar centrado respecto a un punto en el eje X - bool isCenteredOnY; // Variable para saber si el menu debe estar centrado respecto a un punto en el eje Y - bool areElementsCenteredOnX; // Variable para saber si los elementos van centrados en el eje X - int widestItem; // Anchura del elemento más ancho - JA_Sound soundAccept; // Sonido al aceptar o elegir una opción del menu - JA_Sound soundCancel; // Sonido al cancelar el menu - JA_Sound soundMove; // Sonido al mover el selector - SDL_Renderer *renderer; // Puntero al renderizador de la ventana - Asset *asset; // Objeto encargado de gestionar los ficheros de recursos - Text *text; // Texto para poder escribir los items del menu - Input *input; // Gestor de eventos de entrada de teclado o gamepad - color_t colorGreyed; // Color para los elementos agrisados - struct rectangle_t { SDL_Rect rect; // Rectangulo color_t color; // Color int a; // Transparencia }; - rectangle_t rectBG; // Rectangulo de fondo del menu struct item_t { @@ -64,7 +44,6 @@ private: bool linkedDown; // Indica si el elemento actual y el siguiente se tratan como uno solo. Afecta al selector bool linkedUp; // Indica si el elemento actual y el anterior se tratan como uno solo. Afecta al selector }; - std::vector item; // Estructura para cada elemento del menu struct selector_t { @@ -85,7 +64,31 @@ private: color_t itemColor; // Color del item int a; // Cantidad de transparencia para el rectangulo del selector }; - selector_t selector; // Variables para pintar el selector del menu + + std::string name; // Nombre del menu + int x; // Posición en el eje X de la primera letra del primer elemento + int y; // Posición en el eje Y de la primera letra del primer elemento + int h; // Altura del menu + int w; // Anchura del menu + int itemSelected; // Índice del item del menu que ha sido seleccionado + int defaultActionWhenCancel; // Indice del item del menu que se selecciona cuando se cancela el menu + int backgroundType; // Tipo de fondo para el menu + int centerX; // Centro del menu en el eje X + int centerY; // Centro del menu en el eje Y + bool isCenteredOnX; // Variable para saber si el menu debe estar centrado respecto a un punto en el eje X + bool isCenteredOnY; // Variable para saber si el menu debe estar centrado respecto a un punto en el eje Y + bool areElementsCenteredOnX; // Variable para saber si los elementos van centrados en el eje X + int widestItem; // Anchura del elemento más ancho + JA_Sound soundAccept; // Sonido al aceptar o elegir una opción del menu + JA_Sound soundCancel; // Sonido al cancelar el menu + JA_Sound soundMove; // Sonido al mover el selector + SDL_Renderer *renderer; // Puntero al renderizador de la ventana + Text *text; // Texto para poder escribir los items del menu + Input *input; // Gestor de eventos de entrada de teclado o gamepad + color_t colorGreyed; // Color para los elementos agrisados + rectangle_t rectBG; // Rectangulo de fondo del menu + std::vector item; // Estructura para cada elemento del menu + selector_t selector; // Variables para pintar el selector del menu // Establece el rectangulo de fondo del menu void setRectSize(); @@ -122,7 +125,7 @@ private: public: // Constructor - Menu(SDL_Renderer *renderer, Text *text, Input *input, Asset *asset); + Menu(SDL_Renderer *renderer, Text *text, Input *input); // Destructor ~Menu(); @@ -130,6 +133,9 @@ public: // Inicializador void init(std::string name, int x, int y, int backgroundType); + // Carga los ficheros de audio + void loadAudioFile(std::string file, int sound); + // Obtiene el nombre del menu std::string getName(); diff --git a/source/title.cpp b/source/title.cpp index f7f470a..7025f31 100644 --- a/source/title.cpp +++ b/source/title.cpp @@ -15,8 +15,10 @@ Title::Title(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input) loadTextureFromFile(texture, asset->get("intro.png"), renderer); sprite = new AnimatedSprite(texture, renderer, asset->get("intro.ani")); sprite->setCurrentAnimation("menu"); - text = new Text(asset->get("debug.png"), asset->get("debug.txt"), renderer); + text = new Text(asset->get("dogica.png"), asset->get("dogica.txt"), renderer); music = JA_LoadMusic(asset->get("music_title.ogg").c_str()); + menu = new Menu(renderer, text, input); + initMenu(); // Inicializa variables section = {SECTION_PROG_TITLE, 0}; @@ -44,9 +46,31 @@ Title::~Title() delete text; text = nullptr; + delete menu; + menu = nullptr; + JA_DeleteMusic(music); } +// Crea el menu +void Title::initMenu() +{ + menu->loadAudioFile(asset->get("sound_menu_cancel.wav"), SOUND_CANCEL); + menu->loadAudioFile(asset->get("sound_menu_select.wav"), SOUND_ACCEPT); + menu->loadAudioFile(asset->get("sound_menu_move.wav"), SOUND_MOVE); + + menu->init("TITLE", 0, 0, MENU_BACKGROUND_SOLID); + menu->addItem("START",2); + menu->addItem("OPTIONS", 5); + menu->addItem("EXIT"); + menu->setDefaultActionWhenCancel(2); + menu->setBackgroundColor({0x30, 0x30, 0x40}, 192); + menu->setSelectorColor({0xe5, 0x1c, 0x23}, 0); + menu->setSelectorTextColor({0xFF, 0xB4, 0x00}); + menu->centerMenuOnX(160); + menu->centerMenuElementsOnX(); +} + // Actualiza las variables void Title::update() { @@ -74,6 +98,7 @@ void Title::update() } } sprite->animate(); + menu->update(); } } @@ -89,6 +114,7 @@ void Title::render() // Dibuja los objetos sprite->render(); text->writeDX(TXT_CENTER | TXT_COLOR, 160, 200, "@2016,2022 JAILDESIGNER & JAILBROTHER (v0.6)", -1, {255, 93, 4}); + menu->render(); // Vuelca el contenido del renderizador en pantalla screen->blit(); diff --git a/source/title.h b/source/title.h index 53e5719..d477c76 100644 --- a/source/title.h +++ b/source/title.h @@ -7,6 +7,7 @@ #include "input.h" #include "screen.h" #include "text.h" +#include "menu.h" #include "animatedsprite.h" #include "jail_audio.h" @@ -24,6 +25,7 @@ private: Asset *asset; // Objeto con los ficheros de recurso Input *input; // Objeto para gestionar las entradas Text *text; // Objeto para escribir texto en pantalla + Menu *menu; // Objeto para gestionar el menu del titulo AnimatedSprite *sprite; // Sprite para dibujar los graficos de la intro JA_Music music; // Musica del titulo del juego section_t section; // Estado del bucle principal para saber si continua o se sale @@ -36,6 +38,9 @@ private: // Dibuja en pantalla void render(); + // Crea el menu + void initMenu(); + public: // Constructor Title(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input);