diff --git a/source/director.cpp b/source/director.cpp index 556fa48..d0d4f98 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -154,6 +154,7 @@ void Director::initInput() input->bindKey(input_start, SDL_SCANCODE_RETURN); // Teclado - Control del programa + input->bindKey(input_service, SDL_SCANCODE_0); input->bindKey(input_exit, SDL_SCANCODE_ESCAPE); input->bindKey(input_pause, SDL_SCANCODE_P); input->bindKey(input_window_dec_size, SDL_SCANCODE_F1); @@ -380,6 +381,8 @@ bool Director::setFileList() asset->add(prefix + "/data/shaders/crtpi.glsl", t_data); // Texturas + asset->add(prefix + "/data/gfx/controllers/controllers.png", t_bitmap); + asset->add(prefix + "/data/gfx/balloon/balloon1.png", t_bitmap); asset->add(prefix + "/data/gfx/balloon/balloon1.ani", t_animation); asset->add(prefix + "/data/gfx/balloon/balloon2.png", t_bitmap); diff --git a/source/global_inputs.cpp b/source/global_inputs.cpp index 2030340..04cde0b 100644 --- a/source/global_inputs.cpp +++ b/source/global_inputs.cpp @@ -1,12 +1,13 @@ #include "global_inputs.h" -#include // for basic_string, operator+ -#include "input.h" // for Input, inputs_e, INPUT_DO_NOT_ALLOW_REPEAT -#include "jail_audio.h" // for JA_EnableMusic, JA_EnableSound -#include "lang.h" // for getText -#include "options.h" // for options -#include "screen.h" // for Screen -#include "section.h" // for options_e, name, name_e, options -#include "utils.h" // for op_audio_t, options_t, op_music_t, boolToOnOff +#include // for basic_string, operator+ +#include "input.h" // for Input, inputs_e, INPUT_DO_NOT_ALLOW_REPEAT +#include "jail_audio.h" // for JA_EnableMusic, JA_EnableSound +#include "lang.h" // for getText +#include "options.h" // for options +#include "on_screen_help.h" +#include "screen.h" // for Screen +#include "section.h" // for options_e, name, name_e, options +#include "utils.h" // for op_audio_t, options_t, op_music_t, boolToOnOff // Termina void quit(section::options_e code) @@ -61,6 +62,12 @@ void checkGlobalInputs() return; } + else if (Input::get()->checkInput(input_service, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) + { + OnScreenHelp::get()->toggleState(); + return; + } + for (int i = 0; i < Input::get()->getNumControllers(); ++i) { // Comprueba si se sale con el mando diff --git a/source/on_screen_help.cpp b/source/on_screen_help.cpp index 0a2e79c..2798144 100644 --- a/source/on_screen_help.cpp +++ b/source/on_screen_help.cpp @@ -1,8 +1,36 @@ #include "on_screen_help.h" +#include "screen.h" +#include "asset.h" +#include "input.h" +#include "text.h" +#include "sprite.h" +#include "texture.h" +#include "lang.h" // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado OnScreenHelp *OnScreenHelp::onScreenHelp = nullptr; +// Constantes evaluables en tiempo de compilación +constexpr int ICONSIZE = 16; +constexpr SDL_Point PADDING = {8, 8}; +constexpr SDL_Point DESP = {ICONSIZE + 4, 5}; + +constexpr SDL_Rect CONTROLLER_UP = {16, 16, ICONSIZE, ICONSIZE}; +constexpr SDL_Rect CONTROLLER_DOWN = {48, 16, ICONSIZE, ICONSIZE}; +constexpr SDL_Rect CONTROLLER_LEFT = {64, 16, ICONSIZE, ICONSIZE}; +constexpr SDL_Rect LEFT_BUTTON = {48, 144, ICONSIZE, ICONSIZE}; +constexpr SDL_Rect TOP_BUTTON = {0, 144, ICONSIZE, ICONSIZE}; +constexpr SDL_Rect RIGHT_BUTTON = {16, 144, ICONSIZE, ICONSIZE}; +constexpr SDL_Rect START_BUTTON = {128, 320, ICONSIZE, ICONSIZE}; + +constexpr SDL_Rect CONTROLLER_UP_POS = {PADDING.x, PADDING.y + 18 * 0, ICONSIZE, ICONSIZE}; +constexpr SDL_Rect CONTROLLER_DOWN_POS = {PADDING.x, PADDING.y + 18 * 1, ICONSIZE, ICONSIZE}; +constexpr SDL_Rect CONTROLLER_LEFT_POS = {PADDING.x, PADDING.y + 18 * 2, ICONSIZE, ICONSIZE}; +constexpr SDL_Rect LEFT_BUTTON_POS = {PADDING.x, PADDING.y + 18 * 3, ICONSIZE, ICONSIZE}; +constexpr SDL_Rect TOP_BUTTON_POS = {PADDING.x, PADDING.y + 18 * 4, ICONSIZE, ICONSIZE}; +constexpr SDL_Rect RIGHT_BUTTON_POS = {PADDING.x, PADDING.y + 18 * 5, ICONSIZE, ICONSIZE}; +constexpr SDL_Rect START_BUTTON_POS = {PADDING.x, PADDING.y + 18 * 6, ICONSIZE, ICONSIZE}; + // [SINGLETON] Crearemos el objeto onScreenHelp con esta función estática void OnScreenHelp::init() { @@ -22,11 +50,143 @@ OnScreenHelp *OnScreenHelp::get() } // Constructor -OnScreenHelp::OnScreenHelp() +OnScreenHelp::OnScreenHelp() : state(OnScreenHelpStatus::showing) { + setSize(); + + texture = SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, dest.w, dest.h); + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + + fillTexture(); } // Destructor OnScreenHelp::~OnScreenHelp() { + SDL_DestroyTexture(texture); +} + +// Actualiza la lógica interna +void OnScreenHelp::update() +{ +} + +// Muestra el objeto en pantalla +void OnScreenHelp::render() +{ + if (state != OnScreenHelpStatus::hidden) + { + SDL_RenderCopy(Screen::get()->getRenderer(), texture, nullptr, &dest); + } +} + +// Rellena la textura con los gráficos y texto +void OnScreenHelp::fillTexture() +{ + // Cambia el renderizador a la textura + SDL_Texture *temp = SDL_GetRenderTarget(Screen::get()->getRenderer()); + SDL_SetRenderTarget(Screen::get()->getRenderer(), texture); + + // Crea el objeto para el texto + Text *text = new Text(Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), Screen::get()->getRenderer()); + + // Crea la textura con los gráficos + Texture *controllersTexture = new Texture(Screen::get()->getRenderer(), Asset::get()->get("controllers.png")); + + // Crea el sprite para dibujar los gráficos + Sprite *sprite = new Sprite({0, 0, 16, 16}, controllersTexture); + + // Borra la textura + SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 0); + SDL_RenderClear(Screen::get()->getRenderer()); + + // Pon el color de fondo con el bisel + SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0x55, 0x5D, 0x77, 255); + SDL_Rect rect; + rect = {4, 0, dest.w - (4 * 2), dest.h}; + SDL_RenderFillRect(Screen::get()->getRenderer(), &rect); + + rect = {4 / 2, 1, dest.w - 4, dest.h - 2}; + SDL_RenderFillRect(Screen::get()->getRenderer(), &rect); + + rect = {1, 4 / 2, dest.w - 2, dest.h - 4}; + SDL_RenderFillRect(Screen::get()->getRenderer(), &rect); + + rect = {0, 4, dest.w, dest.h - (4 * 2)}; + SDL_RenderFillRect(Screen::get()->getRenderer(), &rect); + + // Dibuja los iconos y el texto + sprite->setSpriteClip(CONTROLLER_UP); + sprite->setPos(CONTROLLER_UP_POS); + sprite->render(); + text->write(CONTROLLER_UP_POS.x + DESP.x, CONTROLLER_UP_POS.y + DESP.y, lang::getText(107)); + + sprite->setSpriteClip(CONTROLLER_DOWN); + sprite->setPos(CONTROLLER_DOWN_POS); + sprite->render(); + text->write(CONTROLLER_DOWN_POS.x + DESP.x, CONTROLLER_DOWN_POS.y + DESP.y, lang::getText(108)); + + sprite->setSpriteClip(CONTROLLER_LEFT); + sprite->setPos(CONTROLLER_LEFT_POS); + sprite->render(); + text->write(CONTROLLER_LEFT_POS.x + DESP.x, CONTROLLER_LEFT_POS.y + DESP.y, lang::getText(109)); + + sprite->setSpriteClip(LEFT_BUTTON); + sprite->setPos(LEFT_BUTTON_POS); + sprite->render(); + text->write(LEFT_BUTTON_POS.x + DESP.x, LEFT_BUTTON_POS.y + DESP.y, lang::getText(110)); + + sprite->setSpriteClip(TOP_BUTTON); + sprite->setPos(TOP_BUTTON_POS); + sprite->render(); + text->write(TOP_BUTTON_POS.x + DESP.x, TOP_BUTTON_POS.y + DESP.y, lang::getText(111)); + + sprite->setSpriteClip(RIGHT_BUTTON); + sprite->setPos(RIGHT_BUTTON_POS); + sprite->render(); + text->write(RIGHT_BUTTON_POS.x + DESP.x, RIGHT_BUTTON_POS.y + DESP.y, lang::getText(112)); + + sprite->setSpriteClip(START_BUTTON); + sprite->setPos(START_BUTTON_POS); + sprite->render(); + text->write(START_BUTTON_POS.x + DESP.x, START_BUTTON_POS.y + DESP.y, lang::getText(113)); + + // text->write(0, 0, "hola"); + + // Restaura el destino de renderizado + SDL_SetRenderTarget(Screen::get()->getRenderer(), temp); + + // Elimina los objetos + delete text; + delete controllersTexture; + delete sprite; +} + +// Define el ancho y alto de la textura +void OnScreenHelp::setSize() +{ + const int textSize = getLargestStringSize(); + dest = (SDL_Rect){8, 8, PADDING.x + DESP.x + textSize + PADDING.x, PADDING.y + (7 * 18) + PADDING.y}; +} + +// Activa o desactiva el objeto +void OnScreenHelp::toggleState() +{ + state = state == OnScreenHelpStatus::showing ? OnScreenHelpStatus::hidden : OnScreenHelpStatus::showing; +} + +// Calcula la longitud en pixels del texto más largo +int OnScreenHelp::getLargestStringSize() const +{ + Text *text = new Text(Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), Screen::get()->getRenderer()); + int size = 0; + + for (int i = 107; i <= 113; ++i) + { + const int textSize = text->lenght(lang::getText(i)); + size = textSize > size ? textSize : size; + } + + delete text; + return size; } \ No newline at end of file diff --git a/source/on_screen_help.h b/source/on_screen_help.h index 8971ebc..a272d2f 100644 --- a/source/on_screen_help.h +++ b/source/on_screen_help.h @@ -27,6 +27,9 @@ private: Input *input; // Objeto pata gestionar la entrada SDL_Texture *texture; // Textura donde dibujar + SDL_Rect dest; // Posición donde dibujar la textura; + + OnScreenHelpStatus state; // Estado del objeto // [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos screen desde fuera @@ -36,6 +39,15 @@ private: // Destructor ~OnScreenHelp(); + // Rellena la textura con los gráficos y texto + void fillTexture(); + + // Define el ancho y alto de la textura + void setSize(); + + // Calcula la longitud en pixels del texto más largo + int getLargestStringSize() const; + public: // [SINGLETON] Crearemos el objeto screen con esta función estática static void init(); @@ -45,4 +57,13 @@ public: // [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él static OnScreenHelp *get(); + + // Actualiza la lógica interna + void update(); + + // Muestra el objeto en pantalla + void render(); + + // Activa o desactiva el objeto + void toggleState(); }; \ No newline at end of file diff --git a/source/screen.cpp b/source/screen.cpp index ce8d3f7..5403277 100644 --- a/source/screen.cpp +++ b/source/screen.cpp @@ -1,20 +1,21 @@ #include "screen.h" -#include // for SDL_DISABLE, SDL_ENABLE -#include // for SDL_ShowCursor -#include // for SDL_PIXELFORMAT_RGBA8888 -#include // for SDL_GetTicks -#include // for max, min -#include // for basic_ifstream, ifstream -#include // for istreambuf_iterator, operator!= -#include // for basic_string, operator+, to_string, cha... -#include "asset.h" // for Asset -#include "dbgtxt.h" // for dbg_print -#include "input.h" // for Input, inputs_e, INPUT_DO_NOT_ALLOW_REPEAT -#include "notify.h" // for Notify -#include "options.h" // for options +#include // for SDL_DISABLE, SDL_ENABLE +#include // for SDL_ShowCursor +#include // for SDL_PIXELFORMAT_RGBA8888 +#include // for SDL_GetTicks +#include // for max, min +#include // for basic_ifstream, ifstream +#include // for istreambuf_iterator, operator!= +#include // for basic_string, operator+, to_string, cha... +#include "asset.h" // for Asset +#include "dbgtxt.h" // for dbg_print +#include "input.h" // for Input, inputs_e, INPUT_DO_NOT_ALLOW_REPEAT +#include "notify.h" // for Notify +#include "options.h" // for options +#include "on_screen_help.h" #ifndef NO_SHADERS -#include "jail_shader.h" // for init, render +#include "jail_shader.h" // for init, render #endif // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado @@ -39,11 +40,9 @@ Screen *Screen::get() } // Constructor -Screen::Screen(SDL_Window *window, SDL_Renderer *renderer) +Screen::Screen(SDL_Window *window, SDL_Renderer *renderer) : window(window), renderer(renderer) { // Copia punteros - this->window = window; - this->renderer = renderer; input = Input::get(); asset = Asset::get(); @@ -68,7 +67,7 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer) fpsCounter = 0; fps = 0; #ifdef DEBUG - showInfo = true; + showInfo = false; #else showInfo = false; #endif @@ -115,14 +114,17 @@ void Screen::start() // Vuelca el contenido del renderizador en pantalla void Screen::blit() { + // Actualiza el contador de FPS + fpsCounter++; + // Actualiza y dibuja el efecto de flash en la pantalla doFlash(); // Atenua la pantalla doAttenuate(); - // Actualiza el contador de FPS - fpsCounter++; + // Muestra la ayuda por pantalla + OnScreenHelp::get()->render(); // Muestra información por pantalla displayInfo();