231 lines
7.3 KiB
C++
231 lines
7.3 KiB
C++
#include "on_screen_help.h"
|
|
#include "screen.h"
|
|
#include "asset.h"
|
|
#include "input.h"
|
|
#include "sprite.h"
|
|
#include "texture.h"
|
|
#include "lang.h"
|
|
#include "param.h"
|
|
#include <memory> // Para std::unique_ptr
|
|
|
|
// [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()
|
|
{
|
|
OnScreenHelp::onScreenHelp = new OnScreenHelp();
|
|
}
|
|
|
|
// [SINGLETON] Destruiremos el objeto onScreenHelp con esta función estática
|
|
void OnScreenHelp::destroy()
|
|
{
|
|
delete OnScreenHelp::onScreenHelp;
|
|
}
|
|
|
|
// [SINGLETON] Con este método obtenemos el objeto onScreenHelp y podemos trabajar con él
|
|
OnScreenHelp *OnScreenHelp::get()
|
|
{
|
|
return OnScreenHelp::onScreenHelp;
|
|
}
|
|
|
|
// Constructor
|
|
OnScreenHelp::OnScreenHelp() : state(OnScreenHelpStatus::hidden)
|
|
{
|
|
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()
|
|
{
|
|
// Actualiza la posición
|
|
updatePosition();
|
|
}
|
|
|
|
// 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
|
|
std::unique_ptr<Text> text(new Text(Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), Screen::get()->getRenderer()));
|
|
|
|
// Crea la textura con los gráficos
|
|
std::unique_ptr<Texture> controllersTexture(new Texture(Screen::get()->getRenderer(), Asset::get()->get("controllers.png")));
|
|
|
|
// Crea el sprite para dibujar los gráficos
|
|
std::unique_ptr<Sprite> sprite(new Sprite({0, 0, 16, 16}, controllersTexture.get()));
|
|
|
|
// 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);
|
|
|
|
rect = {0, 0, dest.w / 2, dest.h};
|
|
SDL_RenderFillRect(Screen::get()->getRenderer(), &rect);
|
|
|
|
// Renderiza los botones y el texto
|
|
renderButton(sprite.get(), text.get(), CONTROLLER_UP, CONTROLLER_UP_POS, 107);
|
|
renderButton(sprite.get(), text.get(), CONTROLLER_DOWN, CONTROLLER_DOWN_POS, 108);
|
|
renderButton(sprite.get(), text.get(), CONTROLLER_LEFT, CONTROLLER_LEFT_POS, 109);
|
|
renderButton(sprite.get(), text.get(), LEFT_BUTTON, LEFT_BUTTON_POS, 110);
|
|
renderButton(sprite.get(), text.get(), TOP_BUTTON, TOP_BUTTON_POS, 111);
|
|
renderButton(sprite.get(), text.get(), RIGHT_BUTTON, RIGHT_BUTTON_POS, 112);
|
|
renderButton(sprite.get(), text.get(), START_BUTTON, START_BUTTON_POS, 113);
|
|
|
|
// Restaura el destino de renderizado
|
|
SDL_SetRenderTarget(Screen::get()->getRenderer(), temp);
|
|
}
|
|
|
|
// Define el ancho y alto de la textura
|
|
void OnScreenHelp::setSize()
|
|
{
|
|
const int textSize = getLargestStringSize();
|
|
const int width = PADDING.x + DESP.x + textSize + PADDING.x;
|
|
const int height = PADDING.y + (7 * 18) + PADDING.y;
|
|
const int x = 0;
|
|
const int y = (param.game.height - height) / 2;
|
|
|
|
dest = (SDL_Rect){x, y, width, height};
|
|
|
|
hiddenPos = -width;
|
|
showingPos = 0;
|
|
}
|
|
|
|
// Activa o desactiva el objeto
|
|
void OnScreenHelp::toggleState()
|
|
{
|
|
if (state == OnScreenHelpStatus::showing || state == OnScreenHelpStatus::entering)
|
|
{
|
|
state = OnScreenHelpStatus::exitting;
|
|
}
|
|
|
|
if (state == OnScreenHelpStatus::hidden || state == OnScreenHelpStatus::exitting)
|
|
{
|
|
state = OnScreenHelpStatus::entering;
|
|
}
|
|
}
|
|
|
|
// Calcula la longitud en pixels del texto más largo
|
|
int OnScreenHelp::getLargestStringSize() const
|
|
{
|
|
std::unique_ptr<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;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
// Renderizara el boton y el texto
|
|
void OnScreenHelp::renderButton(Sprite *sprite, Text *text, const SDL_Rect &buttonClip, const SDL_Rect &buttonPos, int textId)
|
|
{
|
|
sprite->setSpriteClip(buttonClip);
|
|
sprite->setPos(buttonPos);
|
|
sprite->render();
|
|
text->write(buttonPos.x + DESP.x, buttonPos.y + DESP.y, lang::getText(textId));
|
|
}
|
|
|
|
// Actualiza la posición
|
|
void OnScreenHelp::updatePosition()
|
|
{
|
|
switch (state)
|
|
{
|
|
case OnScreenHelpStatus::hidden:
|
|
dest.x = hiddenPos;
|
|
break;
|
|
|
|
case OnScreenHelpStatus::showing:
|
|
dest.x = showingPos;
|
|
break;
|
|
|
|
case OnScreenHelpStatus::exitting:
|
|
if (dest.x > hiddenPos)
|
|
{
|
|
dest.x -= 8;
|
|
}
|
|
else
|
|
{
|
|
state = OnScreenHelpStatus::hidden;
|
|
}
|
|
break;
|
|
|
|
case OnScreenHelpStatus::entering:
|
|
if (dest.x < showingPos)
|
|
{
|
|
dest.x += 8;
|
|
}
|
|
else
|
|
{
|
|
state = OnScreenHelpStatus::showing;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
dest.x = std::max(hiddenPos, dest.x);
|
|
dest.x = std::min(showingPos, dest.x);
|
|
} |