19 Commits

Author SHA1 Message Date
4e525642a0 v1.09 2025-03-01 09:15:08 +01:00
c7db6aeaa3 canvi de pc 2025-03-01 08:11:00 +01:00
5ff04daf20 gonna fer un commit per si reventa algo: estic a meitat implementar surfaces 2025-02-28 22:58:01 +01:00
5bb2b5e7c4 fix: les notificacions ja no embruten la pantalla de càrrega 2025-02-28 14:00:59 +01:00
7a685c0cc8 fix: no pintava el efecte de carrega del borde en LoadingScreen 2025-02-28 13:40:30 +01:00
07e83fc811 Tornada a posar la musica de Title i el attract mode 2025-02-28 13:25:21 +01:00
3167251eae Eliminat el alpha de les notificacions 2025-02-28 13:13:36 +01:00
4efbb61fbc Arreglat aixina sense massa ganes Scoreboard::render() 2025-02-28 13:11:02 +01:00
3992fc08bf Afegides comprobacions de valors per al fitxer de configuració 2025-02-28 11:34:51 +01:00
366fe404ca Modes de video aclarits (sembla)
La finestra manté la posició al canviar de tamany o activar el borde
La finestra ja pot creixer mentres donde de si el escriptori
2025-02-28 09:46:55 +01:00
217781c621 lo mateix 2025-02-27 23:18:16 +01:00
212b2b481c Treballant en els modes de video 2025-02-27 21:05:01 +01:00
59e766f5c3 Nou engine de notificacions 2025-02-27 19:03:57 +01:00
2e11fec2cb canvi de pc 2025-02-27 16:51:20 +01:00
0d7ab830c9 Modificada la barra de progres de carrega de recursos per a que s'actualitze cada 5 items. Aixina ja va rapidet encara que estiga el vsync 2025-02-27 14:21:53 +01:00
0cec9f8556 Solventat bug amb el punter a ScoreboardData 2025-02-27 14:17:00 +01:00
c6474cb2da canvi de pc 2025-02-27 07:37:39 +01:00
e6fd4225a2 Ja torna a deixar jugar
Encara queden bugs per corregir
Trencat el sistema de triar la paleta, de moment
2025-02-26 20:37:29 +01:00
85ab5ea03f Singleton de ItemTracker
Arreglos menors
2025-02-26 13:07:41 +01:00
55 changed files with 2965 additions and 2422 deletions

BIN
data/test.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

View File

@@ -8,7 +8,7 @@
#include "utils.h" // Para printWithDots
// Carga las animaciones en un vector(Animations) desde un fichero
AnimationsFileBuffer loadAnimationsFromFile(const std::string &file_path)
Animations loadAnimationsFromFile(const std::string &file_path)
{
std::ifstream file(file_path);
if (!file)
@@ -37,18 +37,18 @@ AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::stri
// Carga las animaciones
if (!file_path.empty())
{
AnimationsFileBuffer v = loadAnimationsFromFile(file_path);
loadFromAnimationsFileBuffer(v);
Animations v = loadAnimationsFromFile(file_path);
setAnimations(v);
}
}
// Constructor
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer &animations)
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const Animations &animations)
: MovingSprite(texture)
{
if (!animations.empty())
{
loadFromAnimationsFileBuffer(animations);
setAnimations(animations);
}
}
@@ -122,6 +122,7 @@ void AnimatedSprite::setCurrentAnimation(const std::string &name)
animations_[current_animation_].current_frame = 0;
animations_[current_animation_].counter = 0;
animations_[current_animation_].completed = false;
setClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
}
}
@@ -135,6 +136,7 @@ void AnimatedSprite::setCurrentAnimation(int index)
animations_[current_animation_].current_frame = 0;
animations_[current_animation_].counter = 0;
animations_[current_animation_].completed = false;
setClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
}
}
@@ -154,7 +156,7 @@ void AnimatedSprite::resetAnimation()
}
// Carga la animación desde un vector de cadenas
void AnimatedSprite::loadFromAnimationsFileBuffer(const AnimationsFileBuffer &source)
void AnimatedSprite::setAnimations(const Animations &animations)
{
int frame_width = 1;
int frame_height = 1;
@@ -162,9 +164,9 @@ void AnimatedSprite::loadFromAnimationsFileBuffer(const AnimationsFileBuffer &so
int max_tiles = 1;
size_t index = 0;
while (index < source.size())
while (index < animations.size())
{
std::string line = source.at(index);
std::string line = animations.at(index);
// Parsea el fichero para buscar variables y valores
if (line != "[animation]")
@@ -194,11 +196,11 @@ void AnimatedSprite::loadFromAnimationsFileBuffer(const AnimationsFileBuffer &so
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
Animation animation;
AnimationData animation;
do
{
index++;
line = source.at(index);
line = animations.at(index);
size_t pos = line.find("=");
if (pos != std::string::npos)

View File

@@ -7,7 +7,7 @@
#include "moving_sprite.h" // Para MovingSprite
class Texture; // lines 9-9
struct Animation
struct AnimationData
{
std::string name; // Nombre de la animacion
std::vector<SDL_Rect> frames; // Cada uno de los frames que componen la animación
@@ -17,31 +17,31 @@ struct Animation
int current_frame; // Frame actual
int counter; // Contador para las animaciones
Animation() : name(std::string()), speed(5), loop(0), completed(false), current_frame(0), counter(0) {}
AnimationData() : name(std::string()), speed(5), loop(0), completed(false), current_frame(0), counter(0) {}
};
using AnimationsFileBuffer = std::vector<std::string>;
using Animations = std::vector<std::string>;
// Carga las animaciones en un vector(Animations) desde un fichero
AnimationsFileBuffer loadAnimationsFromFile(const std::string &file_path);
Animations loadAnimationsFromFile(const std::string &file_path);
class AnimatedSprite : public MovingSprite
{
protected:
// Variables
std::vector<Animation> animations_; // Vector con las diferentes animaciones
int current_animation_ = 0; // Animacion activa
std::vector<AnimationData> animations_; // Vector con las diferentes animaciones
int current_animation_ = 0; // Animacion activa
// Calcula el frame correspondiente a la animación actual
void animate();
// Carga la animación desde un vector de cadenas
void loadFromAnimationsFileBuffer(const AnimationsFileBuffer &source);
void setAnimations(const Animations &animations);
public:
// Constructor
AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path);
AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer &animations);
AnimatedSprite(std::shared_ptr<Texture> texture, const Animations &animations);
explicit AnimatedSprite(std::shared_ptr<Texture> texture)
: MovingSprite(texture) {}

View File

@@ -88,7 +88,7 @@ void Cheevos::unlock(int id)
// Marcar el logro como completado
cheevos_list_.at(index).completed = true;
// Mostrar notificación en la pantalla
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", cheevos_list_.at(index).caption}, cheevos_list_.at(index).icon);
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", cheevos_list_.at(index).caption}, NotificationText::LEFT, cheevos_list_.at(index).icon);
// Guardar el estado de los logros
saveToFile();
}

View File

@@ -1,22 +1,22 @@
#include "credits.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_error.h> // for SDL_GetError
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <algorithm> // for min
#include <iostream> // for basic_ostream, operator<<, cout, endl
#include "animated_sprite.h" // for AnimatedSprite
#include "asset.h" // for Asset
#include "defines.h" // for GAMECANVAS_HEIGHT, GAMECANVAS_WIDTH
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "options.h" // for Options, options, OptionsVideo, Sect...
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_error.h> // for SDL_GetError
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <algorithm> // for min
#include <iostream> // for basic_ostream, operator<<, cout, endl
#include "animated_sprite.h" // for AnimatedSprite
#include "asset.h" // for Asset
#include "defines.h" // for GAMECANVAS_HEIGHT, GAMECANVAS_WIDTH
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "options.h" // for Options, options, OptionsVideo, Sect...
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR
// Constructor
Credits::Credits()
@@ -28,7 +28,7 @@ Credits::Credits()
{
// Reserva memoria para los punteros
text_ = resource_->getText("smb2");
sprite_ = std::make_shared<AnimatedSprite>(resource_->getTexture("shine.png"), resource_->getAnimation("shine.ani"));
sprite_ = std::make_shared<AnimatedSprite>(resource_->getTexture("shine.png"), resource_->getAnimations("shine.ani"));
// Inicializa variables
options.section.section = Section::CREDITS;
@@ -255,7 +255,7 @@ void Credits::updateCounter()
void Credits::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks_ > ticks_speed_)
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();

View File

@@ -38,7 +38,6 @@ private:
bool counter_enabled_ = true; // Indica si esta activo el contador
int sub_counter_ = 0; // Contador secundario
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticks_speed_ = 15; // Velocidad a la que se repiten los bucles del programa
std::vector<captions_t> texts_; // Vector con los textos
// Actualiza las variables

View File

@@ -7,7 +7,10 @@
// Textos
constexpr const char *WINDOW_CAPTION = "JailDoctor's Dilemma";
constexpr const char *TEXT_COPYRIGHT = "@2022 JailDesigner";
constexpr const char *VERSION = "0.7";
constexpr const char *VERSION = "1.09";
// Velocidad del juego
constexpr Uint32 GAME_SPEED = 1000 / 60;
// Tamaño de bloque
constexpr int BLOCK = 8;

View File

@@ -1,67 +1,73 @@
#include "demo.h"
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <iostream> // for basic_ostream, operator<<, cout, endl
#include "asset.h" // for Asset
#include "debug.h" // for Debug
#include "defines.h" // for BLOCK, PLAY_AREA_WIDTH, GAMECANVAS_CENT...
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "item_tracker.h" // for ItemTracker
#include "options.h" // for Options, options, OptionsVideo, Section...
#include "resource.h" // for Resource
#include "room.h" // for Room
#include "screen.h" // for Screen
#include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR
#include "utils.h" // for Color, stringToColor, colorAreEqual
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <iostream> // for basic_ostream, operator<<, cout, endl
#include "asset.h" // for Asset
#include "debug.h" // for Debug
#include "defines.h" // for BLOCK, PLAY_AREA_WIDTH, GAMECANVAS_CENT...
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "item_tracker.h" // for ItemTracker
#include "options.h" // for Options, options, OptionsVideo, Section...
#include "resource.h" // for Resource
#include "room.h" // for Room
#include "screen.h" // for Screen
#include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR
#include "utils.h" // for Color, stringToColor, colorAreEqual
// Constructor
Demo::Demo()
: screen(Screen::get()),
renderer(Screen::get()->getRenderer()),
resource(Resource::get()),
asset(Asset::get()),
input(Input::get()),
debug(Debug::get())
: screen_(Screen::get()),
renderer_(Screen::get()->getRenderer()),
resource_(Resource::get()),
asset_(Asset::get()),
input_(Input::get()),
debug_(Debug::get())
{
// Inicia algunas variables
board.iniClock = SDL_GetTicks();
rooms.push_back("04.room");
rooms.push_back("54.room");
rooms.push_back("20.room");
rooms.push_back("09.room");
rooms.push_back("05.room");
rooms.push_back("11.room");
rooms.push_back("31.room");
rooms.push_back("44.room");
board_ = std::make_shared<ScoreboardData>();
board_->ini_clock = SDL_GetTicks();
rooms_.push_back("04.room");
rooms_.push_back("54.room");
rooms_.push_back("20.room");
rooms_.push_back("09.room");
rooms_.push_back("05.room");
rooms_.push_back("11.room");
rooms_.push_back("31.room");
rooms_.push_back("44.room");
roomIndex = 0;
currentRoom = rooms[roomIndex];
room_index_ = 0;
current_room_ = rooms_[room_index_];
// Crea los objetos
itemTracker = std::make_shared<ItemTracker>();
scoreboard = std::make_shared<Scoreboard>(&board);
room = std::make_shared<Room>(resource->getRoom(currentRoom), itemTracker, &board.items, false);
text = resource->getText("smb2");
ItemTracker::init();
scoreboard_ = std::make_shared<Scoreboard>(board_);
room_ = std::make_shared<Room>(resource_->getRoom(current_room_), board_);
text_ = resource_->getText("smb2");
// Inicializa el resto de variables
counter = 0;
roomTime = 400;
ticks = 0;
ticksSpeed = 15;
board.lives = 9;
board.items = 0;
board.rooms = 1;
board.jail_is_open = false;
board.music = true;
counter_ = 0;
room_time_ = 400;
ticks_ = 0;
board_->lives = 9;
board_->items = 0;
board_->rooms = 1;
board_->jail_is_open = false;
board_->music = true;
setScoreBoardColor();
options.section.section = Section::DEMO;
options.section.subsection = Subsection::NONE;
}
// Destructor
Demo::~Demo()
{
ItemTracker::destroy();
}
// Comprueba los eventos de la cola
void Demo::checkEvents()
{
@@ -93,21 +99,20 @@ void Demo::run()
void Demo::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks > ticksSpeed)
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
{
// Actualiza el contador de ticks
ticks = SDL_GetTicks();
ticks_ = SDL_GetTicks();
// Comprueba las entradas
checkInput();
// Actualiza los objetos
room->update();
scoreboard->update();
screen->updateFX();
room_->update();
scoreboard_->update();
checkRoomChange();
screen->update();
screen_->update();
}
}
@@ -115,18 +120,17 @@ void Demo::update()
void Demo::render()
{
// Prepara para dibujar el frame
screen->start();
screen_->start();
// Dibuja los elementos del juego en orden
room->renderMap();
room->renderEnemies();
room->renderItems();
room_->renderMap();
room_->renderEnemies();
room_->renderItems();
renderRoomName();
scoreboard->render();
screen->renderFX();
scoreboard_->render();
// Actualiza la pantalla
screen->render();
screen_->render();
}
// Escribe el nombre de la pantalla
@@ -135,10 +139,10 @@ void Demo::renderRoomName()
// Texto en el centro de la pantalla
SDL_Rect rect = {0, 16 * BLOCK, PLAY_AREA_WIDTH, BLOCK * 2};
Color color = stringToColor(options.video.palette, "white");
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 0xFF);
SDL_RenderFillRect(renderer, &rect);
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 0xFF);
SDL_RenderFillRect(renderer_, &rect);
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, 16 * 8 + 4, room->getName(), 1, room->getBGColor());
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, 16 * 8 + 4, room_->getName(), 1, room_->getBGColor());
}
// Recarga todas las texturas
@@ -148,9 +152,9 @@ void Demo::reLoadTextures()
{
std::cout << "** RELOAD REQUESTED" << std::endl;
}
room->reLoadTexture();
scoreboard->reLoadTexture();
text->reLoadTexture();
room_->reLoadTexture();
scoreboard_->reLoadTexture();
text_->reLoadTexture();
}
// Cambia la paleta
@@ -166,8 +170,8 @@ void Demo::switchPalette()
options.video.palette = Palette::ZXSPECTRUM;
}
room->reLoadPalette();
scoreboard->reLoadPalette();
room_->reLoadPalette();
scoreboard_->reLoadPalette();
// Pone el color del marcador en función del color del borde de la habitación
setScoreBoardColor();
@@ -180,10 +184,10 @@ bool Demo::changeRoom(std::string file)
if (file != "0")
{
// Verifica que exista el fichero que se va a cargar
if (asset->get(file) != "")
if (asset_->get(file) != "")
{
// Crea un objeto habitación a partir del fichero
room = std::make_shared<Room>(resource->getRoom(file), itemTracker, &board.items, false);
room_ = std::make_shared<Room>(resource_->getRoom(file), board_);
// Pone el color del marcador en función del color del borde de la habitación
setScoreBoardColor();
@@ -198,19 +202,19 @@ bool Demo::changeRoom(std::string file)
// Comprueba si se ha de cambiar de habitación
void Demo::checkRoomChange()
{
counter++;
if (counter == roomTime)
counter_++;
if (counter_ == room_time_)
{
counter = 0;
roomIndex++;
if (roomIndex == (int)rooms.size())
counter_ = 0;
room_index_++;
if (room_index_ == (int)rooms_.size())
{
options.section.section = Section::LOGO;
options.section.subsection = Subsection::LOGO_TO_TITLE;
}
else
{
changeRoom(rooms[roomIndex]);
changeRoom(rooms_[room_index_]);
}
}
}
@@ -219,13 +223,13 @@ void Demo::checkRoomChange()
void Demo::setScoreBoardColor()
{
// Obtiene el color del borde
const Color color = room->getBorderColor();
const Color color = room_->getBorderColor();
// Si el color es negro lo cambia a blanco
const Color black_color = stringToColor(options.video.palette, "black");
board.color = colorAreEqual(color, black_color) ? stringToColor(options.video.palette, "white") : color;
board_->color = colorAreEqual(color, black_color) ? stringToColor(options.video.palette, "white") : color;
// Si el color es negro brillante lo cambia a blanco
const Color bright_blac_color = stringToColor(options.video.palette, "bright_black");
board.color = colorAreEqual(color, bright_blac_color) ? stringToColor(options.video.palette, "white") : color;
board_->color = colorAreEqual(color, bright_blac_color) ? stringToColor(options.video.palette, "white") : color;
}

View File

@@ -1,44 +1,42 @@
#pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "scoreboard.h" // for board_t
class Asset; // lines 11-11
class Debug; // lines 12-12
class Input; // lines 13-13
class ItemTracker; // lines 14-14
class Resource; // lines 15-15
class Room; // lines 16-16
class Screen; // lines 17-17
class Text; // lines 18-18
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "scoreboard.h" // for board_t
class Asset; // lines 11-11
class Debug; // lines 12-12
class Input; // lines 13-13
class ItemTracker; // lines 14-14
class Resource; // lines 15-15
class Room; // lines 16-16
class Screen; // lines 17-17
class Text; // lines 18-18
class Demo
{
private:
// Objetos y punteros
Screen *screen; // Objeto encargado de manejar el renderizador
SDL_Renderer *renderer; // El renderizador de la ventana
Resource *resource; // Objeto con los recursos
Asset *asset; // Objeto con la ruta a todos los ficheros de recursos
Input *input; // Objeto pata gestionar la entrada
Debug *debug; // Objeto para gestionar la información de debug
std::shared_ptr<Room> room; // Objeto encargado de gestionar cada habitación del juego
std::shared_ptr<Text> text; // Objeto para los textos del juego
std::shared_ptr<Scoreboard> scoreboard; // Objeto encargado de gestionar el marcador
std::shared_ptr<ItemTracker> itemTracker; // Lleva el control de los objetos recogidos
Screen *screen_; // Objeto encargado de manejar el renderizador
SDL_Renderer *renderer_; // El renderizador de la ventana
Resource *resource_; // Objeto con los recursos
Asset *asset_; // Objeto con la ruta a todos los ficheros de recursos
Input *input_; // Objeto pata gestionar la entrada
Debug *debug_; // Objeto para gestionar la información de debug
std::shared_ptr<Room> room_; // Objeto encargado de gestionar cada habitación del juego
std::shared_ptr<Text> text_; // Objeto para los textos del juego
std::shared_ptr<Scoreboard> scoreboard_; // Objeto encargado de gestionar el marcador
// Variables
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa
std::string currentRoom; // Fichero de la habitación actual
board_t board; // Estructura con los datos del marcador
int counter; // Contador para el modo demo
int roomTime; // Tiempo que se muestra cada habitacion
int roomIndex; // Indice para el vector de habitaciones
std::vector<std::string> rooms; // Listado con los mapas de la demo
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
std::string current_room_; // Fichero de la habitación actual
std::shared_ptr<ScoreboardData> board_; // Estructura con los datos del marcador
int counter_; // Contador para el modo demo
int room_time_; // Tiempo que se muestra cada habitacion
int room_index_; // Indice para el vector de habitaciones
std::vector<std::string> rooms_; // Listado con los mapas de la demo
// Actualiza el juego, las variables, comprueba la entrada, etc.
void update();
@@ -75,7 +73,7 @@ public:
Demo();
// Destructor
~Demo() = default;
~Demo();
// Bucle para el juego
void run();

View File

@@ -79,11 +79,10 @@ Director::Director(int argc, const char *argv[])
Screen::init(window_, renderer_);
Screen::get()->setBorderColor(borderColor);
Resource::init();
Notifier::init(Asset::get()->get("notify.png"), Resource::get()->getText("smb2"));
Notifier::init("notify.png", "8bithud");
Input::init(Asset::get()->get("gamecontrollerdb.txt"));
initInput();
Debug::init();
title_music_ = JA_LoadMusic(Asset::get()->get("title.ogg").c_str());
Cheevos::init(Asset::get()->get("cheevos.bin"));
}
@@ -101,8 +100,6 @@ Director::~Director()
Resource::destroy();
Cheevos::destroy();
JA_DeleteMusic(title_music_);
SDL_DestroyRenderer(renderer_);
SDL_DestroyWindow(window_);
SDL_Quit();
@@ -280,6 +277,16 @@ void Director::initInput()
void Director::initJailAudio()
{
JA_Init(48000, AUDIO_S16, 2);
if (options.audio.enabled)
{
JA_SetMusicVolume(options.audio.music.volume);
JA_SetSoundVolume(options.audio.sound.volume);
}
else
{
JA_SetMusicVolume(0);
JA_SetSoundVolume(0);
}
}
// Arranca SDL y crea la ventana
@@ -353,8 +360,10 @@ bool Director::initSDL()
// Inicializa el color de renderizado
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
// Establece el tamaño del buffer de renderizado
SDL_RenderSetLogicalSize(renderer_, options.game.width, options.game.height);
// Modifica el tamaño del renderizador
const int extra_width = options.video.border.enabled ? options.video.border.width * 2 : 0;
const int extra_height = options.video.border.enabled ? options.video.border.height * 2 : 0;
SDL_RenderSetLogicalSize(renderer_, options.game.width + extra_width, options.game.height + extra_height);
// Establece el modo de mezcla
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
@@ -397,6 +406,9 @@ bool Director::setFileList()
// Datos
Asset::get()->add(prefix + "/data/input/gamecontrollerdb.txt", AssetType::DATA);
// Test
Asset::get()->add(prefix + "/data/test.gif", AssetType::DATA);
// Ficheros de sistema
Asset::get()->add(system_folder_ + "/config.txt", AssetType::DATA, false, true);
Asset::get()->add(system_folder_ + "/stats_buffer.csv", AssetType::DATA, false, true);
@@ -748,10 +760,6 @@ void Director::runLoadingScreen()
// Ejecuta la seccion de juego con el titulo y los menus
void Director::runTitle()
{
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{
JA_PlayMusic(title_music_);
}
auto title = std::make_unique<Title>();
title->run();
}

View File

@@ -13,7 +13,6 @@ private:
SDL_Renderer *renderer_; // El renderizador de la ventana
// Variables
JA_Music_t *title_music_; // Musica del titulo
std::string executable_path_; // Path del ejecutable
std::string system_folder_; // Carpeta del sistema donde guardar datos

View File

@@ -1,47 +1,46 @@
#include "ending.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_error.h> // for SDL_GetError
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <algorithm> // for min
#include <iostream> // for basic_ostream, operator<<, cout, endl
#include "asset.h" // for Asset
#include "defines.h" // for GAMECANVAS_HEIGHT, GAMECANVAS_WIDTH
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_SetVolume, JA_PlayMusic, JA_StopM...
#include "options.h" // for Options, options, OptionsVideo, Sect...
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "sprite.h" // for Sprite
#include "text.h" // for Text, TEXT_STROKE
#include "texture.h" // for Texture
#include "utils.h" // for Color, stringToColor, Palette
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_error.h> // for SDL_GetError
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <algorithm> // for min
#include <iostream> // for basic_ostream, operator<<, cout, endl
#include "asset.h" // for Asset
#include "defines.h" // for GAMECANVAS_HEIGHT, GAMECANVAS_WIDTH
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_SetVolume, JA_PlayMusic, JA_StopM...
#include "options.h" // for Options, options, OptionsVideo, Sect...
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "sprite.h" // for Sprite
#include "text.h" // for Text, TEXT_STROKE
#include "texture.h" // for Texture
#include "utils.h" // for Color, stringToColor, Palette
// Constructor
Ending::Ending()
: screen(Screen::get()),
renderer(Screen::get()->getRenderer()),
resource(Resource::get()),
asset(Asset::get()),
input(Input::get())
: screen_(Screen::get()),
renderer_(Screen::get()->getRenderer()),
resource_(Resource::get()),
asset_(Asset::get()),
input_(Input::get())
{
// Reserva memoria para los punteros a objetos
text = resource->getText("smb2");
music = resource->getMusic("ending1.ogg");
text_ = resource_->getText("smb2");
music = resource_->getMusic("ending1.ogg");
// Inicializa variables
counter = -1;
preCounter = 0;
coverCounter = 0;
counter_ = -1;
pre_counter_ = 0;
cover_counter_ = 0;
options.section.section = Section::ENDING;
options.section.subsection = Subsection::NONE;
ticks = 0;
ticksSpeed = 15;
scene = 0;
ticks_ = 0;
current_scene_ = 0;
// Inicializa los textos
iniTexts();
@@ -53,18 +52,18 @@ Ending::Ending()
iniScenes();
// Cambia el color del borde
screen->setBorderColor(stringToColor(options.video.palette, "black"));
screen_->setBorderColor(stringToColor(options.video.palette, "black"));
// Crea la textura para cubrir el rexto
coverTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT + 8);
if (coverTexture == nullptr)
cover_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT + 8);
if (cover_texture_ == nullptr)
{
if (options.console)
{
std::cout << "Error: canvasTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
SDL_SetTextureBlendMode(coverTexture, SDL_BLENDMODE_BLEND);
SDL_SetTextureBlendMode(cover_texture_, SDL_BLENDMODE_BLEND);
// Rellena la textura para la cortinilla
fillCoverTexture();
@@ -74,17 +73,17 @@ Ending::Ending()
Ending::~Ending()
{
// Libera la memoria de los objetos
SDL_DestroyTexture(coverTexture);
SDL_DestroyTexture(cover_texture_);
}
// Actualiza el objeto
void Ending::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks > ticksSpeed)
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
{
// Actualiza el contador de ticks
ticks = SDL_GetTicks();
ticks_ = SDL_GetTicks();
// Comprueba las entradas
checkInput();
@@ -101,7 +100,7 @@ void Ending::update()
// Actualiza el volumen de la musica
updateMusicVolume();
screen->update();
screen_->update();
}
}
@@ -109,22 +108,22 @@ void Ending::update()
void Ending::render()
{
// Prepara para empezar a dibujar en la textura de juego
screen->start();
screen_->start();
// Limpia la pantalla
screen->clean(stringToColor(options.video.palette, "black"));
screen_->clean(stringToColor(options.video.palette, "black"));
// Dibuja las imagenes de la escena
spritePics[scene].sprite->render();
spritePics[scene].coverSprite->render();
sprite_pics_[current_scene_].sprite->render();
sprite_pics_[current_scene_].cover_sprite->render();
// Dibuja los textos de la escena
for (auto ti : scenes[scene].textIndex)
for (auto ti : scenes_[current_scene_].text_index)
{
if (counter > ti.trigger)
if (counter_ > ti.trigger)
{
spriteTexts[ti.index].sprite->render();
spriteTexts[ti.index].coverSprite->render();
sprite_texts_[ti.index].sprite->render();
sprite_texts_[ti.index].cover_sprite->render();
}
}
@@ -132,7 +131,7 @@ void Ending::render()
renderCoverTexture();
// Vuelca el contenido del renderizador en pantalla
screen->render();
screen_->render();
}
// Comprueba el manejador de eventos
@@ -155,7 +154,7 @@ void Ending::checkInput()
void Ending::iniTexts()
{
// Vector con los textos
std::vector<textAndPos_t> texts;
std::vector<TextAndPosition> texts;
// Escena #0
texts.push_back({"HE FINALLY MANAGED", 32});
@@ -187,66 +186,66 @@ void Ending::iniTexts()
texts.push_back({"WERE BORN...", 158});
// Crea los sprites
spriteTexts.clear();
sprite_texts_.clear();
for (auto t : texts)
{
endingTexture_t st;
const int width = text->lenght(t.caption, 1) + 2 + 2;
const int height = text->getCharacterSize() + 2 + 2;
EndingTexture st;
const int width = text_->lenght(t.caption, 1) + 2 + 2;
const int height = text_->getCharacterSize() + 2 + 2;
Color c = stringToColor(options.video.palette, "black");
// Crea la texture
st.texture = std::make_shared<Texture>(renderer);
st.texture = std::make_shared<Texture>(renderer_);
st.texture->createBlank(width, height);
st.texture->setAsRenderTarget(renderer);
st.texture->setAsRenderTarget(renderer_);
st.texture->setBlendMode(SDL_BLENDMODE_BLEND);
text->writeDX(TEXT_STROKE, 2, 2, t.caption, 1, c, 2, c);
text_->writeDX(TEXT_STROKE, 2, 2, t.caption, 1, c, 2, c);
// Crea el sprite
st.sprite = std::make_shared<Sprite>(st.texture, 0, 0, st.texture->getWidth(), st.texture->getHeight());
st.sprite->setPosition((GAMECANVAS_WIDTH - st.texture->getWidth()) / 2, t.pos);
// Crea la coverTexture
st.coverTexture = std::make_shared<Texture>(renderer);
st.coverTexture->createBlank(width, height + 8);
st.coverTexture->setAsRenderTarget(renderer);
st.coverTexture->setBlendMode(SDL_BLENDMODE_BLEND);
st.cover_texture = std::make_shared<Texture>(renderer_);
st.cover_texture->createBlank(width, height + 8);
st.cover_texture->setAsRenderTarget(renderer_);
st.cover_texture->setBlendMode(SDL_BLENDMODE_BLEND);
// Rellena la coverTexture con color transparente
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
SDL_RenderClear(renderer_);
// Los primeros 8 pixels crea una malla
c = stringToColor(options.video.palette, "black");
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, 0xFF);
SDL_SetRenderDrawColor(renderer_, c.r, c.g, c.b, 0xFF);
for (int i = 0; i < width; i += 2)
{
SDL_RenderDrawPoint(renderer, i, 0);
SDL_RenderDrawPoint(renderer, i, 2);
SDL_RenderDrawPoint(renderer, i, 4);
SDL_RenderDrawPoint(renderer, i, 6);
SDL_RenderDrawPoint(renderer_, i, 0);
SDL_RenderDrawPoint(renderer_, i, 2);
SDL_RenderDrawPoint(renderer_, i, 4);
SDL_RenderDrawPoint(renderer_, i, 6);
SDL_RenderDrawPoint(renderer, i + 1, 5);
SDL_RenderDrawPoint(renderer, i + 1, 7);
SDL_RenderDrawPoint(renderer_, i + 1, 5);
SDL_RenderDrawPoint(renderer_, i + 1, 7);
}
// El resto se rellena de color sólido
SDL_Rect rect = {0, 8, width, height};
c = stringToColor(options.video.palette, "black");
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, 0xFF);
SDL_RenderFillRect(renderer, &rect);
SDL_SetRenderDrawColor(renderer_, c.r, c.g, c.b, 0xFF);
SDL_RenderFillRect(renderer_, &rect);
// Crea el sprite
st.coverSprite = std::make_shared<Sprite>(st.coverTexture, 0, 0, st.coverTexture->getWidth(), st.coverTexture->getHeight() - 8);
st.coverSprite->setPosition((GAMECANVAS_WIDTH - st.coverTexture->getWidth()) / 2, t.pos);
st.coverSprite->setClip(0, 8, -1, -1);
st.cover_sprite = std::make_shared<Sprite>(st.cover_texture, 0, 0, st.cover_texture->getWidth(), st.cover_texture->getHeight() - 8);
st.cover_sprite->setPosition((GAMECANVAS_WIDTH - st.cover_texture->getWidth()) / 2, t.pos);
st.cover_sprite->setClip(0, 8, -1, -1);
// Inicializa variables
st.clipDesp = 8;
st.clipHeight = height;
st.clip_desp = 8;
st.clip_height = height;
spriteTexts.push_back(st);
sprite_texts_.push_back(st);
}
}
@@ -254,7 +253,7 @@ void Ending::iniTexts()
void Ending::iniPics()
{
// Vector con las rutas y la posición
std::vector<textAndPos_t> pics;
std::vector<TextAndPosition> pics;
if (options.video.palette == Palette::ZXSPECTRUM)
{
@@ -274,14 +273,14 @@ void Ending::iniPics()
}
// Crea los sprites
spritePics.clear();
sprite_pics_.clear();
for (auto p : pics)
{
endingTexture_t sp;
EndingTexture sp;
// Crea la texture
sp.texture = resource->getTexture(p.caption);
sp.texture = resource_->getTexture(p.caption);
const int width = sp.texture->getWidth();
const int height = sp.texture->getHeight();
@@ -290,45 +289,45 @@ void Ending::iniPics()
sp.sprite->setPosition((GAMECANVAS_WIDTH - width) / 2, p.pos);
// Crea la coverTexture
sp.coverTexture = std::make_shared<Texture>(renderer);
sp.coverTexture->createBlank(width, height + 8);
sp.coverTexture->setAsRenderTarget(renderer);
sp.coverTexture->setBlendMode(SDL_BLENDMODE_BLEND);
sp.cover_texture = std::make_shared<Texture>(renderer_);
sp.cover_texture->createBlank(width, height + 8);
sp.cover_texture->setAsRenderTarget(renderer_);
sp.cover_texture->setBlendMode(SDL_BLENDMODE_BLEND);
// Rellena la coverTexture con color transparente
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
SDL_RenderClear(renderer_);
// Los primeros 8 pixels crea una malla
Color c = stringToColor(options.video.palette, "black");
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, 0xFF);
SDL_SetRenderDrawColor(renderer_, c.r, c.g, c.b, 0xFF);
for (int i = 0; i < width; i += 2)
{
SDL_RenderDrawPoint(renderer, i, 0);
SDL_RenderDrawPoint(renderer, i, 2);
SDL_RenderDrawPoint(renderer, i, 4);
SDL_RenderDrawPoint(renderer, i, 6);
SDL_RenderDrawPoint(renderer_, i, 0);
SDL_RenderDrawPoint(renderer_, i, 2);
SDL_RenderDrawPoint(renderer_, i, 4);
SDL_RenderDrawPoint(renderer_, i, 6);
SDL_RenderDrawPoint(renderer, i + 1, 5);
SDL_RenderDrawPoint(renderer, i + 1, 7);
SDL_RenderDrawPoint(renderer_, i + 1, 5);
SDL_RenderDrawPoint(renderer_, i + 1, 7);
}
// El resto se rellena de color sólido
SDL_Rect rect = {0, 8, width, height};
c = stringToColor(options.video.palette, "black");
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, 0xFF);
SDL_RenderFillRect(renderer, &rect);
SDL_SetRenderDrawColor(renderer_, c.r, c.g, c.b, 0xFF);
SDL_RenderFillRect(renderer_, &rect);
// Crea el sprite
sp.coverSprite = std::make_shared<Sprite>(sp.coverTexture, 0, 0, sp.coverTexture->getWidth(), sp.coverTexture->getHeight() - 8);
sp.coverSprite->setPosition((GAMECANVAS_WIDTH - sp.coverTexture->getWidth()) / 2, p.pos);
sp.coverSprite->setClip(0, 8, -1, -1);
sp.cover_sprite = std::make_shared<Sprite>(sp.cover_texture, 0, 0, sp.cover_texture->getWidth(), sp.cover_texture->getHeight() - 8);
sp.cover_sprite->setPosition((GAMECANVAS_WIDTH - sp.cover_texture->getWidth()) / 2, p.pos);
sp.cover_sprite->setClip(0, 8, -1, -1);
// Inicializa variables
sp.clipDesp = 8;
sp.clipHeight = height;
sp.clip_desp = 8;
sp.clip_height = height;
spritePics.push_back(sp);
sprite_pics_.push_back(sp);
}
}
@@ -340,79 +339,79 @@ void Ending::iniScenes()
const int lapse = 80;
// Crea el contenedor
scene_t sc;
SceneData sc;
// Inicializa el vector
scenes.clear();
scenes_.clear();
// Crea la escena #0
sc.counterEnd = 1000;
sc.pictureIndex = 0;
sc.textIndex.clear();
sc.counter_end = 1000;
sc.picture_index = 0;
sc.text_index.clear();
trigger = 85 * 2;
trigger += lapse;
sc.textIndex.push_back({0, trigger});
sc.text_index.push_back({0, trigger});
trigger += lapse;
sc.textIndex.push_back({1, trigger});
sc.text_index.push_back({1, trigger});
trigger += lapse * 3;
sc.textIndex.push_back({2, trigger});
sc.text_index.push_back({2, trigger});
trigger += lapse;
sc.textIndex.push_back({3, trigger});
scenes.push_back(sc);
sc.text_index.push_back({3, trigger});
scenes_.push_back(sc);
// Crea la escena #1
sc.counterEnd = 1400;
sc.pictureIndex = 1;
sc.textIndex.clear();
sc.counter_end = 1400;
sc.picture_index = 1;
sc.text_index.clear();
trigger = 140 * 2;
trigger += lapse;
sc.textIndex.push_back({4, trigger});
sc.text_index.push_back({4, trigger});
trigger += lapse;
sc.textIndex.push_back({5, trigger});
sc.text_index.push_back({5, trigger});
trigger += lapse;
sc.textIndex.push_back({6, trigger});
sc.text_index.push_back({6, trigger});
trigger += lapse * 3;
sc.textIndex.push_back({7, trigger});
sc.text_index.push_back({7, trigger});
trigger += lapse;
sc.textIndex.push_back({8, trigger});
sc.text_index.push_back({8, trigger});
trigger += lapse * 3;
sc.textIndex.push_back({9, trigger});
scenes.push_back(sc);
sc.text_index.push_back({9, trigger});
scenes_.push_back(sc);
// Crea la escena #2
sc.counterEnd = 1000;
sc.pictureIndex = 2;
sc.textIndex.clear();
sc.counter_end = 1000;
sc.picture_index = 2;
sc.text_index.clear();
trigger = 148 / 2;
trigger += lapse;
sc.textIndex.push_back({10, trigger});
sc.text_index.push_back({10, trigger});
trigger += lapse;
sc.textIndex.push_back({11, trigger});
scenes.push_back(sc);
sc.text_index.push_back({11, trigger});
scenes_.push_back(sc);
// Crea la escena #3
sc.counterEnd = 800;
sc.pictureIndex = 3;
sc.textIndex.clear();
sc.counter_end = 800;
sc.picture_index = 3;
sc.text_index.clear();
trigger = 87 / 2;
trigger += lapse;
sc.textIndex.push_back({12, trigger});
sc.text_index.push_back({12, trigger});
trigger += lapse / 2;
sc.textIndex.push_back({13, trigger});
scenes.push_back(sc);
sc.text_index.push_back({13, trigger});
scenes_.push_back(sc);
// Crea la escena #4
sc.counterEnd = 1000;
sc.pictureIndex = 4;
sc.textIndex.clear();
sc.counter_end = 1000;
sc.picture_index = 4;
sc.text_index.clear();
trigger = 91 * 2;
trigger += lapse;
sc.textIndex.push_back({14, trigger});
sc.text_index.push_back({14, trigger});
trigger += lapse * 2;
sc.textIndex.push_back({15, trigger});
sc.text_index.push_back({15, trigger});
trigger += lapse * 3;
sc.textIndex.push_back({16, trigger});
scenes.push_back(sc);
sc.text_index.push_back({16, trigger});
scenes_.push_back(sc);
}
// Bucle principal
@@ -435,80 +434,80 @@ void Ending::run()
void Ending::updateCounters()
{
// Incrementa el contador
if (preCounter < 200)
if (pre_counter_ < 200)
{
preCounter++;
pre_counter_++;
}
else
{
counter++;
counter_++;
}
if (counter > scenes[scene].counterEnd - 100)
if (counter_ > scenes_[current_scene_].counter_end - 100)
{
coverCounter++;
cover_counter_++;
}
}
// Actualiza las cortinillas de los elementos
void Ending::updateSpriteCovers()
{ // Actualiza la cortinilla de los textos
if (counter % 4 == 0)
if (counter_ % 4 == 0)
{
for (auto ti : scenes[scene].textIndex)
for (auto ti : scenes_[current_scene_].text_index)
{
if (counter > ti.trigger)
if (counter_ > ti.trigger)
{
if (spriteTexts[ti.index].clipDesp > 0)
if (sprite_texts_[ti.index].clip_desp > 0)
{
spriteTexts[ti.index].clipDesp -= 2;
sprite_texts_[ti.index].clip_desp -= 2;
}
else if (spriteTexts[ti.index].clipHeight > 0)
else if (sprite_texts_[ti.index].clip_height > 0)
{
spriteTexts[ti.index].clipHeight -= 2;
spriteTexts[ti.index].coverSprite->setY(spriteTexts[ti.index].coverSprite->getY() + 2);
sprite_texts_[ti.index].clip_height -= 2;
sprite_texts_[ti.index].cover_sprite->setY(sprite_texts_[ti.index].cover_sprite->getY() + 2);
}
spriteTexts[ti.index].coverSprite->setClip(0, spriteTexts[ti.index].clipDesp, spriteTexts[ti.index].coverSprite->getWidth(), spriteTexts[ti.index].clipHeight);
sprite_texts_[ti.index].cover_sprite->setClip(0, sprite_texts_[ti.index].clip_desp, sprite_texts_[ti.index].cover_sprite->getWidth(), sprite_texts_[ti.index].clip_height);
}
}
}
// Actualiza la cortinilla de las imagenes
if (counter % 2 == 0)
if (counter_ % 2 == 0)
{
if (spritePics[scene].clipDesp > 0)
if (sprite_pics_[current_scene_].clip_desp > 0)
{
spritePics[scene].clipDesp -= 2;
sprite_pics_[current_scene_].clip_desp -= 2;
}
else if (spritePics[scene].clipHeight > 0)
else if (sprite_pics_[current_scene_].clip_height > 0)
{
spritePics[scene].clipHeight -= 2;
if (spritePics[scene].clipHeight < 0)
sprite_pics_[current_scene_].clip_height -= 2;
if (sprite_pics_[current_scene_].clip_height < 0)
{
spritePics[scene].clipHeight = 0;
sprite_pics_[current_scene_].clip_height = 0;
}
spritePics[scene].coverSprite->setY(spritePics[scene].coverSprite->getY() + 2);
sprite_pics_[current_scene_].cover_sprite->setY(sprite_pics_[current_scene_].cover_sprite->getY() + 2);
}
spritePics[scene].coverSprite->setClip(0, spritePics[scene].clipDesp, spritePics[scene].coverSprite->getWidth(), spritePics[scene].clipHeight);
sprite_pics_[current_scene_].cover_sprite->setClip(0, sprite_pics_[current_scene_].clip_desp, sprite_pics_[current_scene_].cover_sprite->getWidth(), sprite_pics_[current_scene_].clip_height);
}
}
// Comprueba si se ha de cambiar de escena
void Ending::checkChangeScene()
{
if (counter > scenes[scene].counterEnd)
if (counter_ > scenes_[current_scene_].counter_end)
{
scene++;
counter = 0;
coverCounter = 0;
if (scene == 5)
current_scene_++;
counter_ = 0;
cover_counter_ = 0;
if (current_scene_ == 5)
{
// Termina el bucle
options.section.section = Section::ENDING2;
// Mantiene los valores anteriores
scene = 4;
coverCounter = 100;
current_scene_ = 4;
cover_counter_ = 100;
}
}
}
@@ -517,49 +516,49 @@ void Ending::checkChangeScene()
void Ending::fillCoverTexture()
{
// Rellena la textura que cubre el texto con color transparente
SDL_SetRenderTarget(renderer, coverTexture);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
SDL_SetRenderTarget(renderer_, cover_texture_);
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
SDL_RenderClear(renderer_);
// Los primeros 8 pixels crea una malla
const Color color = stringToColor(options.video.palette, "black");
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 0xFF);
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 0xFF);
for (int i = 0; i < 256; i += 2)
{
SDL_RenderDrawPoint(renderer, i + 0, GAMECANVAS_HEIGHT + 0);
SDL_RenderDrawPoint(renderer, i + 1, GAMECANVAS_HEIGHT + 1);
SDL_RenderDrawPoint(renderer, i + 0, GAMECANVAS_HEIGHT + 2);
SDL_RenderDrawPoint(renderer, i + 1, GAMECANVAS_HEIGHT + 3);
SDL_RenderDrawPoint(renderer_, i + 0, GAMECANVAS_HEIGHT + 0);
SDL_RenderDrawPoint(renderer_, i + 1, GAMECANVAS_HEIGHT + 1);
SDL_RenderDrawPoint(renderer_, i + 0, GAMECANVAS_HEIGHT + 2);
SDL_RenderDrawPoint(renderer_, i + 1, GAMECANVAS_HEIGHT + 3);
SDL_RenderDrawPoint(renderer, i, GAMECANVAS_HEIGHT + 4);
SDL_RenderDrawPoint(renderer, i, GAMECANVAS_HEIGHT + 6);
SDL_RenderDrawPoint(renderer_, i, GAMECANVAS_HEIGHT + 4);
SDL_RenderDrawPoint(renderer_, i, GAMECANVAS_HEIGHT + 6);
}
// El resto se rellena de color sólido
SDL_Rect rect = {0, 0, 256, GAMECANVAS_HEIGHT};
SDL_RenderFillRect(renderer, &rect);
SDL_RenderFillRect(renderer_, &rect);
SDL_SetRenderTarget(renderer, nullptr);
SDL_SetRenderTarget(renderer_, nullptr);
}
// Dibuja la cortinilla de cambio de escena
void Ending::renderCoverTexture()
{
if (coverCounter > 0)
if (cover_counter_ > 0)
{ // Dibuja la textura que cubre el texto
const int offset = std::min(coverCounter, 100);
SDL_Rect srcRect = {0, 200 - (coverCounter * 2), 256, offset * 2};
const int offset = std::min(cover_counter_, 100);
SDL_Rect srcRect = {0, 200 - (cover_counter_ * 2), 256, offset * 2};
SDL_Rect dstRect = {0, 0, 256, offset * 2};
SDL_RenderCopy(renderer, coverTexture, &srcRect, &dstRect);
SDL_RenderCopy(renderer_, cover_texture_, &srcRect, &dstRect);
}
}
// Actualiza el volumen de la musica
void Ending::updateMusicVolume()
{
if (scene == 4 && coverCounter > 0)
if (current_scene_ == 4 && cover_counter_ > 0)
{
const float step = (100.0f - coverCounter) / 100.0f;
const float step = (100.0f - cover_counter_) / 100.0f;
const int volume = 128 * step;
JA_SetVolume(volume);
}

View File

@@ -1,34 +1,34 @@
#pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector
class Asset; // lines 9-9
class Input; // lines 10-10
class Resource; // lines 11-11
class Screen; // lines 12-12
class Sprite; // lines 13-13
class Text; // lines 14-14
class Texture; // lines 15-15
struct JA_Music_t; // lines 16-16
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector
class Asset; // lines 9-9
class Input; // lines 10-10
class Resource; // lines 11-11
class Screen; // lines 12-12
class Sprite; // lines 13-13
class Text; // lines 14-14
class Texture; // lines 15-15
struct JA_Music_t; // lines 16-16
class Ending
{
private:
// Estructuras
struct endingTexture_t // Estructura con dos texturas y sprites, uno para mostrar y el otro hace de cortinilla
struct EndingTexture // Estructura con dos texturas y sprites, uno para mostrar y el otro hace de cortinilla
{
std::shared_ptr<Texture> texture; // Textura a mostrar
std::shared_ptr<Sprite> sprite; // Sprite para mostrar la textura
std::shared_ptr<Texture> coverTexture; // Textura que cubre a la otra textura
std::shared_ptr<Sprite> coverSprite; // Sprite para mostrar la textura que cubre a la otra textura
int clipDesp; // Desplazamiento del spriteClip de la textura de cobertura
int clipHeight; // Altura del spriteClip de la textura de cobertura
std::shared_ptr<Texture> texture; // Textura a mostrar
std::shared_ptr<Sprite> sprite; // Sprite para mostrar la textura
std::shared_ptr<Texture> cover_texture; // Textura que cubre a la otra textura
std::shared_ptr<Sprite> cover_sprite; // Sprite para mostrar la textura que cubre a la otra textura
int clip_desp; // Desplazamiento del spriteClip de la textura de cobertura
int clip_height; // Altura del spriteClip de la textura de cobertura
};
struct textAndPos_t // Estructura con un texto y su posición en el eje Y
struct TextAndPosition // Estructura con un texto y su posición en el eje Y
{
std::string caption; // Texto
int pos; // Posición
@@ -40,32 +40,31 @@ private:
int trigger;
};
struct scene_t // Estructura para crear cada una de las escenas del final
struct SceneData // Estructura para crear cada una de las escenas del final
{
std::vector<asdhk> textIndex; // Indices del vector de textos a mostrar y su disparador
int pictureIndex; // Indice del vector de imagenes a mostrar
int counterEnd; // Valor del contador en el que finaliza la escena
std::vector<asdhk> text_index; // Indices del vector de textos a mostrar y su disparador
int picture_index; // Indice del vector de imagenes a mostrar
int counter_end; // Valor del contador en el que finaliza la escena
};
// Objetos y punteros
Screen *screen; // Objeto encargado de dibujar en pantalla
SDL_Renderer *renderer; // El renderizador de la ventana
Resource *resource; // Objeto con los recursos
Asset *asset; // Objeto con los ficheros de recursos
Input *input; // Objeto pata gestionar la entrada
std::shared_ptr<Text> text; // Objeto para escribir texto en pantalla
SDL_Texture *coverTexture; // Textura para cubrir el texto
Screen *screen_; // Objeto encargado de dibujar en pantalla
SDL_Renderer *renderer_; // El renderizador de la ventana
Resource *resource_; // Objeto con los recursos
Asset *asset_; // Objeto con los ficheros de recursos
Input *input_; // Objeto pata gestionar la entrada
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
SDL_Texture *cover_texture_; // Textura para cubrir el texto
// Variables
int counter; // Contador
int preCounter; // Contador previo
int coverCounter; // Contador para la cortinilla
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa
std::vector<endingTexture_t> spriteTexts; // Vector con los sprites de texto con su cortinilla
std::vector<endingTexture_t> spritePics; // Vector con los sprites de texto con su cortinilla
int scene; // Escena actual
std::vector<scene_t> scenes; // Vector con los textos e imagenes de cada escena
int counter_; // Contador
int pre_counter_; // Contador previo
int cover_counter_; // Contador para la cortinilla
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
std::vector<EndingTexture> sprite_texts_; // Vector con los sprites de texto con su cortinilla
std::vector<EndingTexture> sprite_pics_; // Vector con los sprites de texto con su cortinilla
int current_scene_; // Escena actual
std::vector<SceneData> scenes_; // Vector con los textos e imagenes de cada escena
JA_Music_t *music; // Musica que suena durante el final
// Actualiza el objeto

View File

@@ -1,60 +1,57 @@
#include "ending2.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <algorithm> // for max, min, replace
#include "animated_sprite.h" // for AnimatedSprite
#include "asset.h" // for Asset
#include "defines.h" // for GAMECANVAS_HEIGHT, GAMECANVAS_CENTER_X
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_SetVolume, JA_PlayMusic, JA_StopM...
#include "moving_sprite.h" // for MovingSprite
#include "options.h" // for Options, options, OptionsVideo, Sect...
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "text.h" // for Text
#include "texture.h" // for Texture
#include "utils.h" // for Color, stringToColor
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <algorithm> // for max, min, replace
#include "animated_sprite.h" // for AnimatedSprite
#include "asset.h" // for Asset
#include "defines.h" // for GAMECANVAS_HEIGHT, GAMECANVAS_CENTER_X
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_SetVolume, JA_PlayMusic, JA_StopM...
#include "moving_sprite.h" // for MovingSprite
#include "options.h" // for Options, options, OptionsVideo, Sect...
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "text.h" // for Text
#include "texture.h" // for Texture
#include "utils.h" // for Color, stringToColor
// Constructor
Ending2::Ending2()
: screen(Screen::get()),
renderer(Screen::get()->getRenderer()),
resource(Resource::get()),
asset(Asset::get()),
input(Input::get())
: screen_(Screen::get()),
renderer_(Screen::get()->getRenderer()),
resource_(Resource::get()),
asset_(Asset::get()),
input_(Input::get())
{
// Reserva memoria para los punteros a objetos
text = resource->getText("smb2");
music = resource->getMusic("ending2.ogg");
text_ = resource_->getText("smb2");
music_ = resource_->getMusic("ending2.ogg");
// Inicializa variables
counterEnabled = false;
preCounter = 0;
postCounter = 0;
postCounterEnabled = false;
counter_enabled_ = false;
pre_counter_ = 0;
post_counter_ = 0;
post_counter_enabled_ = false;
options.section.section = Section::ENDING2;
options.section.subsection = Subsection::NONE;
ticks = 0;
ticksSpeed = 15;
distSpriteText = 8;
distSpriteSprite = 0;
despSpeed = -0.2f;
firstCol = GAMECANVAS_FIRST_QUARTER_X + (GAMECANVAS_WIDTH / 16);
secondCol = GAMECANVAS_THIRD_QUARTER_X - (GAMECANVAS_WIDTH / 16);
ticks_ = 0;
dist_sprite_text_ = 8;
dist_sprite_sprite_ = 0;
sprite_desp_speed_ = -0.2f;
// Inicializa el vector de colores
const std::vector<std::string> color_list = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"};
for (auto color : color_list)
{
colors.push_back(stringToColor(options.video.palette, color));
colors_.push_back(stringToColor(options.video.palette, color));
}
// Cambia el color del borde
screen->setBorderColor(stringToColor(options.video.palette, "black"));
screen_->setBorderColor(stringToColor(options.video.palette, "black"));
// Inicializa la lista de sprites
iniSpriteList();
@@ -76,10 +73,10 @@ Ending2::Ending2()
void Ending2::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks > ticksSpeed)
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
{
// Actualiza el contador de ticks
ticks = SDL_GetTicks();
ticks_ = SDL_GetTicks();
// Comprueba las entradas
checkInput();
@@ -87,7 +84,7 @@ void Ending2::update()
// Actualiza los contadores
updateCounters();
if (counterEnabled)
if (counter_enabled_)
{
// Actualiza los sprites
updateSprites();
@@ -105,7 +102,7 @@ void Ending2::update()
// Actualiza el volumen de la musica
updateMusicVolume();
screen->update();
screen_->update();
}
}
@@ -113,10 +110,10 @@ void Ending2::update()
void Ending2::render()
{
// Prepara para empezar a dibujar en la textura de juego
screen->start();
screen_->start();
// Limpia la pantalla
screen->clean(stringToColor(options.video.palette, "black"));
screen_->clean(stringToColor(options.video.palette, "black"));
// Dibuja los sprites
renderSprites();
@@ -127,7 +124,7 @@ void Ending2::render()
// Dibuja los sprites con el texto del final
renderTexts();
const std::string txt = std::to_string(postCounter);
const std::string txt = std::to_string(post_counter_);
// text->write(0, 192 - 8, txt);
// Dibuja la cuadricula
@@ -147,24 +144,24 @@ void Ending2::render()
{
// Dibuja una trama arriba y abajo
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF);
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0xFF);
for (int i = 0; i < 256; i += 2)
{
SDL_RenderDrawPoint(renderer, i + 0, 0);
SDL_RenderDrawPoint(renderer, i + 1, 1);
SDL_RenderDrawPoint(renderer, i + 0, 2);
SDL_RenderDrawPoint(renderer, i + 1, 3);
SDL_RenderDrawPoint(renderer_, i + 0, 0);
SDL_RenderDrawPoint(renderer_, i + 1, 1);
SDL_RenderDrawPoint(renderer_, i + 0, 2);
SDL_RenderDrawPoint(renderer_, i + 1, 3);
SDL_RenderDrawPoint(renderer, i, 4);
SDL_RenderDrawPoint(renderer, i, 6);
SDL_RenderDrawPoint(renderer_, i, 4);
SDL_RenderDrawPoint(renderer_, i, 6);
SDL_RenderDrawPoint(renderer, i + 0, 191);
SDL_RenderDrawPoint(renderer, i + 1, 190);
SDL_RenderDrawPoint(renderer, i + 0, 189);
SDL_RenderDrawPoint(renderer, i + 1, 188);
SDL_RenderDrawPoint(renderer_, i + 0, 191);
SDL_RenderDrawPoint(renderer_, i + 1, 190);
SDL_RenderDrawPoint(renderer_, i + 0, 189);
SDL_RenderDrawPoint(renderer_, i + 1, 188);
SDL_RenderDrawPoint(renderer, i, 187);
SDL_RenderDrawPoint(renderer, i, 185);
SDL_RenderDrawPoint(renderer_, i, 187);
SDL_RenderDrawPoint(renderer_, i, 185);
}
// SDL_RenderDrawLine(renderer, 0, 1, 255, 1);
// SDL_RenderDrawLine(renderer, 0, 3, 255, 3);
@@ -173,7 +170,7 @@ void Ending2::render()
}
// Vuelca el contenido del renderizador en pantalla
screen->render();
screen_->render();
}
// Comprueba el manejador de eventos
@@ -195,7 +192,7 @@ void Ending2::checkInput()
// Bucle principal
void Ending2::run()
{
JA_PlayMusic(music);
JA_PlayMusic(music_);
while (options.section.section == Section::ENDING2)
{
@@ -212,21 +209,21 @@ void Ending2::run()
void Ending2::updateCounters()
{
// Incrementa el contador
if (preCounter < 200)
if (pre_counter_ < 200)
{
preCounter++;
pre_counter_++;
}
else
{
counterEnabled = true;
counter_enabled_ = true;
}
if (postCounterEnabled)
if (post_counter_enabled_)
{
postCounter++;
post_counter_++;
}
if (postCounter > 600)
if (post_counter_ > 600)
{
options.section.section = Section::LOGO;
options.section.subsection = Subsection::LOGO_TO_INTRO;
@@ -237,100 +234,100 @@ void Ending2::updateCounters()
void Ending2::iniSpriteList()
{
// Reinicia el vector
spriteList.clear();
sprite_list_.clear();
// Añade los valores
spriteList.push_back("bin");
spriteList.push_back("floppy");
spriteList.push_back("bird");
spriteList.push_back("chip");
spriteList.push_back("jeannine");
spriteList.push_back("spark");
spriteList.push_back("code");
spriteList.push_back("paco");
spriteList.push_back("elsa");
spriteList.push_back("z80");
sprite_list_.push_back("bin");
sprite_list_.push_back("floppy");
sprite_list_.push_back("bird");
sprite_list_.push_back("chip");
sprite_list_.push_back("jeannine");
sprite_list_.push_back("spark");
sprite_list_.push_back("code");
sprite_list_.push_back("paco");
sprite_list_.push_back("elsa");
sprite_list_.push_back("z80");
spriteList.push_back("bell");
spriteList.push_back("dong");
sprite_list_.push_back("bell");
sprite_list_.push_back("dong");
spriteList.push_back("amstrad_cs");
spriteList.push_back("breakout");
sprite_list_.push_back("amstrad_cs");
sprite_list_.push_back("breakout");
spriteList.push_back("flying_arounder");
spriteList.push_back("stopped_arounder");
spriteList.push_back("walking_arounder");
spriteList.push_back("arounders_door");
spriteList.push_back("arounders_machine");
sprite_list_.push_back("flying_arounder");
sprite_list_.push_back("stopped_arounder");
sprite_list_.push_back("walking_arounder");
sprite_list_.push_back("arounders_door");
sprite_list_.push_back("arounders_machine");
spriteList.push_back("abad");
spriteList.push_back("abad_bell");
spriteList.push_back("lord_abad");
sprite_list_.push_back("abad");
sprite_list_.push_back("abad_bell");
sprite_list_.push_back("lord_abad");
spriteList.push_back("bat");
spriteList.push_back("batman_bell");
spriteList.push_back("batman_fire");
spriteList.push_back("batman");
sprite_list_.push_back("bat");
sprite_list_.push_back("batman_bell");
sprite_list_.push_back("batman_fire");
sprite_list_.push_back("batman");
spriteList.push_back("demon");
spriteList.push_back("heavy");
spriteList.push_back("dimallas");
spriteList.push_back("guitar");
sprite_list_.push_back("demon");
sprite_list_.push_back("heavy");
sprite_list_.push_back("dimallas");
sprite_list_.push_back("guitar");
spriteList.push_back("jailbattle_alien");
spriteList.push_back("jailbattle_human");
sprite_list_.push_back("jailbattle_alien");
sprite_list_.push_back("jailbattle_human");
spriteList.push_back("jailer_#1");
spriteList.push_back("jailer_#2");
spriteList.push_back("jailer_#3");
spriteList.push_back("bry");
spriteList.push_back("upv_student");
sprite_list_.push_back("jailer_#1");
sprite_list_.push_back("jailer_#2");
sprite_list_.push_back("jailer_#3");
sprite_list_.push_back("bry");
sprite_list_.push_back("upv_student");
spriteList.push_back("lamp");
spriteList.push_back("robot");
spriteList.push_back("congo");
spriteList.push_back("crosshair");
spriteList.push_back("tree_thing");
sprite_list_.push_back("lamp");
sprite_list_.push_back("robot");
sprite_list_.push_back("congo");
sprite_list_.push_back("crosshair");
sprite_list_.push_back("tree_thing");
spriteList.push_back("matatunos");
spriteList.push_back("tuno");
sprite_list_.push_back("matatunos");
sprite_list_.push_back("tuno");
spriteList.push_back("mummy");
spriteList.push_back("sam");
sprite_list_.push_back("mummy");
sprite_list_.push_back("sam");
spriteList.push_back("qvoid");
spriteList.push_back("sigmasua");
sprite_list_.push_back("qvoid");
sprite_list_.push_back("sigmasua");
spriteList.push_back("tv_panel");
spriteList.push_back("tv");
sprite_list_.push_back("tv_panel");
sprite_list_.push_back("tv");
spriteList.push_back("spider");
spriteList.push_back("shock");
spriteList.push_back("wave");
sprite_list_.push_back("spider");
sprite_list_.push_back("shock");
sprite_list_.push_back("wave");
spriteList.push_back("player");
sprite_list_.push_back("player");
}
// Carga todos los sprites desde una lista
void Ending2::loadSprites()
{
// Inicializa variables
maxSpriteWidth = 0;
maxSpriteHeight = 0;
sprite_max_width_ = 0;
sprite_max_height_ = 0;
// Carga los sprites
for (auto sl : spriteList)
for (auto sl : sprite_list_)
{
sprites.emplace_back(std::make_shared<AnimatedSprite>(resource->getTexture(sl + ".png"), resource->getAnimation(sl + ".ani")));
maxSpriteWidth = std::max(sprites.back()->getWidth(), maxSpriteWidth);
maxSpriteHeight = std::max(sprites.back()->getHeight(), maxSpriteHeight);
sprites_.emplace_back(std::make_shared<AnimatedSprite>(resource_->getTexture(sl + ".png"), resource_->getAnimations(sl + ".ani")));
sprite_max_width_ = std::max(sprites_.back()->getWidth(), sprite_max_width_);
sprite_max_height_ = std::max(sprites_.back()->getHeight(), sprite_max_height_);
}
}
// Actualiza los sprites
void Ending2::updateSprites()
{
for (auto sprite : sprites)
for (auto sprite : sprites_)
{
sprite->update();
}
@@ -339,7 +336,7 @@ void Ending2::updateSprites()
// Actualiza los sprites de texto
void Ending2::updateTextSprites()
{
for (auto sprite : spriteTexts)
for (auto sprite : sprite_texts_)
{
sprite->update();
}
@@ -348,16 +345,16 @@ void Ending2::updateTextSprites()
// Actualiza los sprites de texto del final
void Ending2::updateTexts()
{
if (texts.back()->getPosY() > GAMECANVAS_CENTER_Y)
if (texts_.back()->getPosY() > GAMECANVAS_CENTER_Y)
{
for (auto sprite : texts)
for (auto sprite : texts_)
{
sprite->update();
}
}
else
{
postCounterEnabled = true;
post_counter_enabled_ = true;
}
}
@@ -365,7 +362,7 @@ void Ending2::updateTexts()
void Ending2::renderSprites()
{
const Color color = stringToColor(options.video.palette, "red");
for (auto sprite : sprites)
for (auto sprite : sprites_)
{
const bool a = sprite->getRect().y + sprite->getRect().h > 0;
const bool b = sprite->getRect().y < GAMECANVAS_HEIGHT;
@@ -378,15 +375,15 @@ void Ending2::renderSprites()
// Pinta el ultimo elemento de otro color
const Color c = stringToColor(options.video.palette, "white");
sprites.back()->getTexture()->setColor(c.r, c.g, c.b);
sprites.back()->render();
sprites_.back()->getTexture()->setColor(c.r, c.g, c.b);
sprites_.back()->render();
}
// Dibuja los sprites con el texto
void Ending2::renderSpriteTexts()
{
const Color color = stringToColor(options.video.palette, "white");
for (auto sprite : spriteTexts)
for (auto sprite : sprite_texts_)
{
const bool a = sprite->getRect().y + sprite->getRect().h > 0;
const bool b = sprite->getRect().y < GAMECANVAS_HEIGHT;
@@ -401,7 +398,7 @@ void Ending2::renderSpriteTexts()
// Dibuja los sprites con el texto del final
void Ending2::renderTexts()
{
for (auto sprite : texts)
for (auto sprite : texts_)
{
const bool a = sprite->getRect().y + sprite->getRect().h > 0;
const bool b = sprite->getRect().y < GAMECANVAS_HEIGHT;
@@ -415,58 +412,58 @@ void Ending2::renderTexts()
// Coloca los sprites en su sito
void Ending2::placeSprites()
{
for (int i = 0; i < (int)sprites.size(); ++i)
for (int i = 0; i < (int)sprites_.size(); ++i)
{
const int x = i % 2 == 0 ? firstCol : secondCol;
const int y = (i / 1) * (maxSpriteHeight + distSpriteText + text->getCharacterSize() + distSpriteSprite) + GAMECANVAS_HEIGHT + 40;
const int w = sprites[i]->getWidth();
const int h = sprites[i]->getHeight();
const int x = i % 2 == 0 ? FIRST_COL_ : SECOND_COL_;
const int y = (i / 1) * (sprite_max_height_ + dist_sprite_text_ + text_->getCharacterSize() + dist_sprite_sprite_) + GAMECANVAS_HEIGHT + 40;
const int w = sprites_[i]->getWidth();
const int h = sprites_[i]->getHeight();
const int dx = -(w / 2);
const int dy = i % 1 == 0 ? maxSpriteHeight - h : (int)(maxSpriteHeight * 1.5f) - h;
const int dy = i % 1 == 0 ? sprite_max_height_ - h : (int)(sprite_max_height_ * 1.5f) - h;
sprites[i]->setPosition({x + dx, y + dy, w, h});
sprites[i]->setVelY(despSpeed);
sprites_[i]->setPosition({x + dx, y + dy, w, h});
sprites_[i]->setVelY(sprite_desp_speed_);
}
// Recoloca el último sprite, que es el del jugador
const int w = sprites.back()->getWidth();
const int w = sprites_.back()->getWidth();
const int x = GAMECANVAS_CENTER_X - (w / 2);
const int y = sprites.back()->getPosY() + maxSpriteHeight * 2;
sprites.back()->setPosX(x);
sprites.back()->setPosY(y);
sprites.back()->setCurrentAnimation("walk");
const int y = sprites_.back()->getPosY() + sprite_max_height_ * 2;
sprites_.back()->setPosX(x);
sprites_.back()->setPosY(y);
sprites_.back()->setCurrentAnimation("walk");
}
// Crea los sprites con las texturas con los textos
void Ending2::createSpriteTexts()
{
// Crea los sprites de texto a partir de la lista
for (int i = 0; i < (int)spriteList.size(); ++i)
for (int i = 0; i < (int)sprite_list_.size(); ++i)
{
// Calcula constantes
std::string txt = spriteList[i];
std::string txt = sprite_list_[i];
std::replace(txt.begin(), txt.end(), '_', ' ');
txt = txt == "player" ? "JAILDOCTOR" : txt; // Reemplaza el texto
const int w = text->lenght(txt, 1);
const int h = text->getCharacterSize();
const int x = i % 2 == 0 ? firstCol : secondCol;
const int w = text_->lenght(txt, 1);
const int h = text_->getCharacterSize();
const int x = i % 2 == 0 ? FIRST_COL_ : SECOND_COL_;
const int dx = -(w / 2);
const int y = sprites[i]->getPosY() + sprites[i]->getHeight() + distSpriteText;
const int y = sprites_[i]->getPosY() + sprites_[i]->getHeight() + dist_sprite_text_;
// Cambia la posición del último sprite
const int X = (i == (int)spriteList.size() - 1) ? GAMECANVAS_CENTER_X - (w / 2) : x + dx;
const int X = (i == (int)sprite_list_.size() - 1) ? GAMECANVAS_CENTER_X - (w / 2) : x + dx;
// Crea la textura
auto texture = std::make_shared<Texture>(renderer);
auto texture = std::make_shared<Texture>(renderer_);
texture->createBlank(w, h);
texture->setAsRenderTarget(renderer);
texture->setAsRenderTarget(renderer_);
texture->setBlendMode(SDL_BLENDMODE_BLEND);
text->write(0, 0, txt);
text_->write(0, 0, txt);
// Crea el sprite
SDL_Rect pos = {X, y, w, h};
spriteTexts.emplace_back(std::make_shared<MovingSprite>(texture, pos));
spriteTexts.back()->setVelY(despSpeed);
sprite_texts_.emplace_back(std::make_shared<MovingSprite>(texture, pos));
sprite_texts_.back()->setVelY(sprite_desp_speed_);
}
}
@@ -481,28 +478,28 @@ void Ending2::createTexts()
for (int i = 0; i < (int)list.size(); ++i)
{
// Calcula constantes
const int w = text->lenght(list[i], 1);
const int h = text->getCharacterSize();
const int w = text_->lenght(list[i], 1);
const int h = text_->getCharacterSize();
const int x = GAMECANVAS_CENTER_X;
const int dx = -(w / 2);
const int y = GAMECANVAS_HEIGHT + (text->getCharacterSize() * (i * 2));
const int y = GAMECANVAS_HEIGHT + (text_->getCharacterSize() * (i * 2));
// Crea la textura
auto texture = std::make_shared<Texture>(renderer);
auto texture = std::make_shared<Texture>(renderer_);
texture->createBlank(w, h);
texture->setAsRenderTarget(renderer);
texture->setAsRenderTarget(renderer_);
texture->setBlendMode(SDL_BLENDMODE_BLEND);
text->write(0, 0, list[i]);
text_->write(0, 0, list[i]);
// Crea el sprite
SDL_Rect pos = {x + dx, y, w, h};
texts.emplace_back(std::make_shared<MovingSprite>(texture, pos));
texts.back()->setVelY(despSpeed);
texts_.emplace_back(std::make_shared<MovingSprite>(texture, pos));
texts_.back()->setVelY(sprite_desp_speed_);
}
// Crea los últimos textos
// El primer texto va a continuación del ultimo spriteText
const int start = spriteTexts.back()->getPosY() + text->getCharacterSize() * 15;
const int start = sprite_texts_.back()->getPosY() + text_->getCharacterSize() * 15;
list.clear();
list.push_back("THANK YOU");
list.push_back("FOR PLAYING!");
@@ -511,23 +508,23 @@ void Ending2::createTexts()
for (int i = 0; i < (int)list.size(); ++i)
{
// Calcula constantes
const int w = text->lenght(list[i], 1);
const int h = text->getCharacterSize();
const int w = text_->lenght(list[i], 1);
const int h = text_->getCharacterSize();
const int x = GAMECANVAS_CENTER_X;
const int dx = -(w / 2);
const int y = start + (text->getCharacterSize() * (i * 2));
const int y = start + (text_->getCharacterSize() * (i * 2));
// Crea la textura
auto texture = std::make_shared<Texture>(renderer);
auto texture = std::make_shared<Texture>(renderer_);
texture->createBlank(w, h);
texture->setAsRenderTarget(renderer);
texture->setAsRenderTarget(renderer_);
texture->setBlendMode(SDL_BLENDMODE_BLEND);
text->write(0, 0, list[i]);
text_->write(0, 0, list[i]);
// Crea el sprite
SDL_Rect pos = {x + dx, y, w, h};
texts.emplace_back(std::make_shared<MovingSprite>(texture, pos));
texts.back()->setVelY(despSpeed);
texts_.emplace_back(std::make_shared<MovingSprite>(texture, pos));
texts_.back()->setVelY(sprite_desp_speed_);
}
}
@@ -535,21 +532,21 @@ void Ending2::createTexts()
void Ending2::updateFinalFade()
{
// La variable step va de 0 a 40 en el tramo de postCounter que va de 500 a 540. Al dividirlo por 40, va de 0.0f a 1.0f
const float step = std::min(std::max(postCounter, 500) - 500, 40) / 40.0f;
const int index = (colors.size() - 1) * step;
const float step = std::min(std::max(post_counter_, 500) - 500, 40) / 40.0f;
const int index = (colors_.size() - 1) * step;
for (auto t : texts)
for (auto t : texts_)
{
t->getTexture()->setColor(colors[index].r, colors[index].g, colors[index].b);
t->getTexture()->setColor(colors_[index].r, colors_[index].g, colors_[index].b);
}
}
// Actualiza el volumen de la musica
void Ending2::updateMusicVolume()
{
if (postCounter > 0)
if (post_counter_ > 0)
{
const float step = (600.0f - postCounter) / 600.0f;
const float step = (600.0f - post_counter_) / 600.0f;
const int volume = 128 * step;
JA_SetVolume(volume);
}

View File

@@ -1,51 +1,53 @@
#pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "utils.h" // for Color
class AnimatedSprite; // lines 9-9
class Asset; // lines 10-10
class Input; // lines 11-11
class MovingSprite; // lines 12-12
class Resource; // lines 13-13
class Screen; // lines 14-14
class Text; // lines 15-15
struct JA_Music_t; // lines 16-16
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "utils.h" // for Color
#include "defines.h" // for GAMECANVAS_FIRST_QUARTER_X, GAMECANVAS_THIRD_QUARTER_X, GAMECANVAS_WIDTH
class AnimatedSprite; // lines 9-9
class Asset; // lines 10-10
class Input; // lines 11-11
class MovingSprite; // lines 12-12
class Resource; // lines 13-13
class Screen; // lines 14-14
class Text; // lines 15-15
struct JA_Music_t; // lines 16-16
class Ending2
{
private:
// Constantes
static constexpr int FIRST_COL_ = GAMECANVAS_FIRST_QUARTER_X + (GAMECANVAS_WIDTH / 16); // Primera columna por donde desfilan los sprites
static constexpr int SECOND_COL_ = GAMECANVAS_THIRD_QUARTER_X - (GAMECANVAS_WIDTH / 16); // Segunda columna por donde desfilan los sprites
// Objetos y punteros
Screen *screen; // Objeto encargado de dibujar en pantalla
SDL_Renderer *renderer; // El renderizador de la ventana
Resource *resource; // Objeto con los recursos
Asset *asset; // Objeto con los ficheros de recursos
Input *input; // Objeto pata gestionar la entrada
std::shared_ptr<Text> text; // Objeto para escribir texto en pantalla
std::vector<std::shared_ptr<AnimatedSprite>> sprites; // Vector con todos los sprites a dibujar
std::vector<std::shared_ptr<MovingSprite>> spriteTexts; // Vector con los sprites de texto de los sprites
std::vector<std::shared_ptr<MovingSprite>> texts; // Vector con los sprites de texto
Screen *screen_; // Objeto encargado de dibujar en pantalla
SDL_Renderer *renderer_; // El renderizador de la ventana
Resource *resource_; // Objeto con los recursos
Asset *asset_; // Objeto con los ficheros de recursos
Input *input_; // Objeto pata gestionar la entrada
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
std::vector<std::shared_ptr<AnimatedSprite>> sprites_; // Vector con todos los sprites a dibujar
std::vector<std::shared_ptr<MovingSprite>> sprite_texts_; // Vector con los sprites de texto de los sprites
std::vector<std::shared_ptr<MovingSprite>> texts_; // Vector con los sprites de texto
// Variables
bool counterEnabled; // Indica si está el contador habilitado
int preCounter; // Contador previo
int postCounter; // Contador posterior
bool postCounterEnabled; // Indica si está habilitado el contador
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa
JA_Music_t *music; // Musica que suena durante el final
std::vector<std::string> spriteList; // Lista con todos los sprites a dibujar
std::vector<Color> colors; // Vector con los colores para el fade
int maxSpriteWidth; // El valor de ancho del sprite mas ancho
int maxSpriteHeight; // El valor de alto del sprite mas alto
int distSpriteText; // Distancia entre el sprite y el texto que lo acompaña
int distSpriteSprite; // Distancia entre dos sprites de la misma columna
float despSpeed; // Velocidad de desplazamiento de los sprites
int firstCol; // Primera columna por donde desfilan los sprites
int secondCol; // Segunda columna por donde desfilan los sprites
bool counter_enabled_; // Indica si está el contador habilitado
int pre_counter_; // Contador previo
int post_counter_; // Contador posterior
bool post_counter_enabled_; // Indica si está habilitado el contador
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
JA_Music_t *music_; // Musica que suena durante el final
std::vector<std::string> sprite_list_; // Lista con todos los sprites a dibujar
std::vector<Color> colors_; // Vector con los colores para el fade
int sprite_max_width_; // El valor de ancho del sprite mas ancho
int sprite_max_height_; // El valor de alto del sprite mas alto
int dist_sprite_text_; // Distancia entre el sprite y el texto que lo acompaña
int dist_sprite_sprite_; // Distancia entre dos sprites de la misma columna
float sprite_desp_speed_; // Velocidad de desplazamiento de los sprites
// Actualiza el objeto
void update();

View File

@@ -1,16 +1,16 @@
#include "enemy.h"
#include <SDL2/SDL_render.h> // for SDL_RendererFlip, SDL_FLIP_NONE, SDL_FL...
#include <stdlib.h> // for rand
#include "animated_sprite.h" // for AnimatedSprite
#include "options.h" // for Options, OptionsVideo, options
#include "resource.h" // for Resource
#include "texture.h" // for Texture
#include <SDL2/SDL_render.h> // for SDL_RendererFlip, SDL_FLIP_NONE, SDL_FL...
#include <stdlib.h> // for rand
#include "animated_sprite.h" // for AnimatedSprite
#include "options.h" // for Options, OptionsVideo, options
#include "resource.h" // for Resource
#include "texture.h" // for Texture
// Constructor
Enemy::Enemy(EnemyData enemy)
{
// Crea objetos
sprite_ = std::make_shared<AnimatedSprite>(Resource::get()->getTexture(enemy.texture_path), Resource::get()->getAnimation(enemy.animation_path));
sprite_ = std::make_shared<AnimatedSprite>(Resource::get()->getTexture(enemy.texture_path), Resource::get()->getAnimations(enemy.animation_path));
// Obten el resto de valores
x1_ = enemy.x1;

View File

@@ -24,6 +24,7 @@
#include "notifier.h"
#include "global_inputs.h"
#include "global_events.h"
//#include "surface.h"
// Constructor
Game::Game()
@@ -36,32 +37,34 @@ Game::Game()
cheevos_(Cheevos::get())
{
// Inicia algunas variables
board_.iniClock = SDL_GetTicks();
//test_surface_ = std::make_shared<Surface>(Screen::get()->getSurface(), "test.gif");
board_ = std::make_shared<ScoreboardData>();
board_->ini_clock = SDL_GetTicks();
#ifdef DEBUG
current_room_ = "03.room";
const int x = 25;
const int y = 13;
spawn_point_ = {x * 8, y * 8, 0, 0, 0, s_standing, SDL_FLIP_HORIZONTAL};
constexpr int X = 25;
constexpr int Y = 13;
spawn_point_ = PlayerSpawn(X * 8, Y * 8, 0, 0, 0, PlayerState::STANDING, SDL_FLIP_HORIZONTAL);
debug_->setEnabled(false);
#else
current_room_ = "03.room";
const int x = 25;
const int y = 13;
spawn_point_ = {x * 8, y * 8, 0, 0, 0, s_standing, SDL_FLIP_HORIZONTAL};
constexpr int X = 25;
constexpr int Y = 13;
spawn_point_ = PlayerSpawn(X * 8, Y * 8, 0, 0, 0, PlayerState::STANDING, SDL_FLIP_HORIZONTAL);
#endif
// Crea los objetos
scoreboard_ = std::make_shared<Scoreboard>(&board_);
item_tracker_ = std::make_shared<ItemTracker>();
ItemTracker::init();
scoreboard_ = std::make_shared<Scoreboard>(board_);
room_tracker_ = std::make_shared<RoomTracker>();
room_ = std::make_shared<Room>(resource_->getRoom(current_room_), item_tracker_, &board_.items, false);
const std::string playerPNG = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.png" : "player.png";
const std::string playerANI = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.ani" : "player.ani";
const player_t player = {spawn_point_, playerPNG, playerANI, room_};
room_ = std::make_shared<Room>(resource_->getRoom(current_room_), board_);
std::string player_texture = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.png" : "player.png";
std::string player_animations = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.ani" : "player.ani";
const PlayerData player(spawn_point_, player_texture, player_animations, room_);
player_ = std::make_shared<Player>(player);
text_ = resource_->getText("smb2");
music_ = resource_->getMusic("game.ogg");
death_sound_ = JA_LoadSound(asset_->get("death.wav").c_str());
death_sound_ = resource_->getSound("death.wav");
stats_ = std::make_shared<Stats>(asset_->get("stats.csv"), asset_->get("stats_buffer.csv"));
// Crea la textura para poner el nombre de la habitación
@@ -85,15 +88,14 @@ Game::Game()
// Inicializa el resto de variables
ticks_ = 0;
ticks_speed_ = 15;
board_.lives = 9;
board_->lives = 9;
#ifdef DEBUG
board_.lives = 9;
board_->lives = 9;
#endif
board_.items = 0;
board_.rooms = 1;
board_.music = true;
board_.jail_is_open = options.cheats.jail_is_open == Cheat::CheatState::ENABLED;
board_->items = 0;
board_->rooms = 1;
board_->music = true;
board_->jail_is_open = options.cheats.jail_is_open == Cheat::CheatState::ENABLED;
setScoreBoardColor();
room_tracker_->addRoom(current_room_);
paused_ = false;
@@ -110,7 +112,7 @@ Game::Game()
Game::~Game()
{
// Libera la memoria de los objetos
ItemTracker::destroy();
SDL_DestroyTexture(room_name_texture_);
}
@@ -130,8 +132,8 @@ void Game::checkEvents()
case SDL_SCANCODE_G:
debug_->switchEnabled();
options.cheats.invincible = static_cast<Cheat::CheatState>(debug_->getEnabled());
board_.music = !debug_->getEnabled();
board_.music ? JA_ResumeMusic() : JA_PauseMusic();
board_->music = !debug_->getEnabled();
board_->music ? JA_ResumeMusic() : JA_PauseMusic();
break;
case SDL_SCANCODE_R:
@@ -155,19 +157,19 @@ void Game::checkEvents()
break;
case SDL_SCANCODE_F6:
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, 2);
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, NotificationText::LEFT, 2, false, "F6");
break;
case SDL_SCANCODE_F7:
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, 3);
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, NotificationText::LEFT, 3, false, "F7");
break;
case SDL_SCANCODE_F8:
Notifier::get()->show({"JAILDESIGNER IS LOGGED IN", ""}, 4);
Notifier::get()->show({"JAILDESIGNER", "IS LOGGED IN"}, NotificationText::LEFT, 4, false);
break;
case SDL_SCANCODE_F9:
Notifier::get()->show({"JAILDESIGNER IS LOGGED IN", ""}, 5);
Notifier::get()->show({"JAILDESIGNER", "IS LOGGED IN"}, NotificationText::LEFT, 5, false);
break;
default:
break;
@@ -182,13 +184,15 @@ void Game::checkInput()
{
if (input_->checkInput(input_toggle_music, REPEAT_FALSE))
{
board_.music = !board_.music;
board_.music ? JA_ResumeMusic() : JA_PauseMusic();
board_->music = !board_->music;
board_->music ? JA_ResumeMusic() : JA_PauseMusic();
Notifier::get()->show({"MUSIC " + std::string(board_->music ? "ENABLED" : "DISABLED")}, NotificationText::CENTER);
}
else if (input_->checkInput(input_pause, REPEAT_FALSE))
{
switchPause();
Notifier::get()->show({std::string(paused_ ? "GAME PAUSED" : "GAME RUNNING")}, NotificationText::CENTER);
}
globalInputs::check();
@@ -198,7 +202,7 @@ void Game::checkInput()
void Game::run()
{
JA_PlayMusic(music_);
if (!board_.music)
if (!board_->music)
{
JA_PauseMusic();
}
@@ -217,7 +221,7 @@ void Game::run()
void Game::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks_ > ticks_speed_)
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();
@@ -258,6 +262,7 @@ void Game::render()
{
// Prepara para dibujar el frame
screen_->start();
//test_surface_->render(0, 0, 10, 10, 64, 64);
// Dibuja los elementos del juego en orden
room_->renderMap();
@@ -283,7 +288,7 @@ void Game::updateDebugInfo()
{
debug_->add("X = " + std::to_string(static_cast<int>(player_->x_)) + ", Y = " + std::to_string(static_cast<int>(player_->y_)));
debug_->add("VX = " + std::to_string(player_->vx_).substr(0, 4) + ", VY = " + std::to_string(player_->vy_).substr(0, 4));
debug_->add("STATE = " + std::to_string(player_->state_));
debug_->add("STATE = " + std::to_string(static_cast<int>(player_->state_)));
}
// Pone la información de debug en pantalla
@@ -336,7 +341,7 @@ bool Game::changeRoom(std::string file)
if (asset_->get(file) != "")
{
// Crea un objeto habitación nuevo a partir del fichero
room_ = std::make_shared<Room>(resource_->getRoom(file), item_tracker_, &board_.items, board_.jail_is_open);
room_ = std::make_shared<Room>(resource_->getRoom(file), board_);
// Pone el nombre de la habitación en la textura
fillRoomNameTexture();
@@ -347,8 +352,8 @@ bool Game::changeRoom(std::string file)
if (room_tracker_->addRoom(file))
{
// Incrementa el contador de habitaciones visitadas
board_.rooms++;
options.stats.rooms = board_.rooms;
board_->rooms++;
options.stats.rooms = board_->rooms;
// Actualiza las estadisticas
stats_->addVisit(room_->getName());
@@ -407,7 +412,7 @@ void Game::checkIfPlayerIsAlive()
// Comprueba si ha terminado la partida
void Game::checkGameOver()
{
if (board_.lives < 0 && black_screen_counter_ > 17)
if (board_->lives < 0 && black_screen_counter_ > 17)
{
options.section.section = Section::GAME_OVER;
}
@@ -424,7 +429,7 @@ void Game::killPlayer()
// Resta una vida al jugador
if (options.cheats.infinite_lives == Cheat::CheatState::DISABLED)
{
--board_.lives;
--board_->lives;
}
// Actualiza las estadisticas
@@ -440,10 +445,10 @@ void Game::killPlayer()
setBlackScreen();
// Crea la nueva habitación y el nuevo jugador
room_ = std::make_shared<Room>(resource_->getRoom(current_room_), item_tracker_, &board_.items, board_.jail_is_open);
const std::string playerPNG = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.png" : "player.png";
const std::string playerANI = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.ani" : "player.ani";
const player_t player = {spawn_point_, playerPNG, playerANI, room_};
room_ = std::make_shared<Room>(resource_->getRoom(current_room_), board_);
std::string player_texture = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.png" : "player.png";
std::string player_animations = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.ani" : "player.ani";
const PlayerData player(spawn_point_, player_texture, player_animations, room_);
player_ = std::make_shared<Player>(player);
// Pone los objetos en pausa mientras esta la habitación en negro
@@ -508,19 +513,19 @@ void Game::setScoreBoardColor()
const bool isBrightBlack = colorAreEqual(colorBorder, stringToColor(options.video.palette, "bright_black"));
// Si el color del borde es negro o negro brillante cambia el texto del marcador a blanco
board_.color = isBlack || isBrightBlack ? stringToColor(options.video.palette, "white") : colorBorder;
board_->color = isBlack || isBrightBlack ? stringToColor(options.video.palette, "white") : colorBorder;
}
// Comprueba si ha finalizado el juego
bool Game::checkEndGame()
{
const bool isOnTheRoom = room_->getName() == "THE JAIL"; // Estar en la habitación que toca
const bool haveTheItems = board_.items >= int(total_items_ * 0.9f) || options.cheats.jail_is_open == Cheat::CheatState::ENABLED; // Con mas del 90% de los items recogidos
const bool isOnTheDoor = player_->getRect().x <= 128; // Y en la ubicación que toca (En la puerta)
const bool isOnTheRoom = room_->getName() == "THE JAIL"; // Estar en la habitación que toca
const bool haveTheItems = board_->items >= int(total_items_ * 0.9f) || options.cheats.jail_is_open == Cheat::CheatState::ENABLED; // Con mas del 90% de los items recogidos
const bool isOnTheDoor = player_->getRect().x <= 128; // Y en la ubicación que toca (En la puerta)
if (haveTheItems)
{
board_.jail_is_open = true;
board_->jail_is_open = true;
}
if (haveTheItems && isOnTheRoom && isOnTheDoor)
@@ -581,7 +586,7 @@ void Game::switchPause()
// Da vidas al jugador cuando está en la Jail
void Game::checkRestoringJail()
{
if (room_->getName() != "THE JAIL" || board_.lives == 9)
if (room_->getName() != "THE JAIL" || board_->lives == 9)
{
return;
}
@@ -597,11 +602,11 @@ void Game::checkRestoringJail()
if (counter == 100)
{
counter = 0;
board_.lives++;
board_->lives++;
JA_PlaySound(death_sound_);
// Invalida el logro de completar el juego sin entrar a la jail
const bool haveTheItems = board_.items >= int(total_items_ * 0.9f);
const bool haveTheItems = board_->items >= int(total_items_ * 0.9f);
if (!haveTheItems)
{
cheevos_->invalidate(9);
@@ -644,42 +649,42 @@ void Game::fillRoomNameTexture()
void Game::checkSomeCheevos()
{
// Logros sobre la cantidad de items
if (board_.items == total_items_)
if (board_->items == total_items_)
{
cheevos_->unlock(4);
cheevos_->unlock(3);
cheevos_->unlock(2);
cheevos_->unlock(1);
}
else if (board_.items >= total_items_ * 0.75f)
else if (board_->items >= total_items_ * 0.75f)
{
cheevos_->unlock(3);
cheevos_->unlock(2);
cheevos_->unlock(1);
}
else if (board_.items >= total_items_ * 0.5f)
else if (board_->items >= total_items_ * 0.5f)
{
cheevos_->unlock(2);
cheevos_->unlock(1);
}
else if (board_.items >= total_items_ * 0.25f)
else if (board_->items >= total_items_ * 0.25f)
{
cheevos_->unlock(1);
}
// Logros sobre las habitaciones visitadas
if (board_.rooms >= 60)
if (board_->rooms >= 60)
{
cheevos_->unlock(7);
cheevos_->unlock(6);
cheevos_->unlock(5);
}
else if (board_.rooms >= 40)
else if (board_->rooms >= 40)
{
cheevos_->unlock(6);
cheevos_->unlock(5);
}
else if (board_.rooms >= 20)
else if (board_->rooms >= 20)
{
cheevos_->unlock(5);
}
@@ -695,7 +700,7 @@ void Game::checkEndGameCheevos()
cheevos_->unlock(9);
// "Complete the game with all items"
if (board_.items == total_items_)
if (board_->items == total_items_)
{
cheevos_->unlock(10);
}

View File

@@ -8,6 +8,7 @@
#include "player.h" // Para playerSpawn_t
#include "scoreboard.h" // Para board_t
#include "room.h"
//#include "surface.h"
class Asset;
class Cheevos;
class Debug;
@@ -37,26 +38,25 @@ private:
Cheevos *cheevos_; // Objeto encargado de gestionar los logros del juego
std::shared_ptr<Room> room_; // Objeto encargado de gestionar cada habitación del juego
std::shared_ptr<Player> player_; // Objeto con el jugador
std::shared_ptr<ItemTracker> item_tracker_; // Lleva el control de los objetos recogidos
std::shared_ptr<RoomTracker> room_tracker_; // Lleva el control de las habitaciones visitadas
std::shared_ptr<Text> text_; // Objeto para los textos del juego
std::shared_ptr<Scoreboard> scoreboard_; // Objeto encargado de gestionar el marcador
std::shared_ptr<Stats> stats_; // Objeto encargado de gestionar las estadísticas
SDL_Texture *room_name_texture_; // Textura para escribir el nombre de la habitación
//std::shared_ptr<Surface> test_surface_;
// Variables
JA_Music_t *music_; // Musica que suena durante el juego
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
std::string current_room_; // Fichero de la habitación actual
playerSpawn_t spawn_point_; // Lugar de la habitación donde aparece el jugador
JA_Sound_t *death_sound_; // Sonido a reproducir cuando muere el jugador
board_t board_; // Estructura con los datos del marcador
bool paused_; // Indica si el juego se encuentra en pausa
bool black_screen_; // Indica si la pantalla está en negro. Se utiliza para la muerte del jugador
int black_screen_counter_; // Contador para temporizar la pantalla en negro
int total_items_; // Cantidad total de items que hay en el mapeado del juego
SDL_Rect room_name_rect_; // Rectangulo donde pintar la textura con el nombre de la habitación
JA_Music_t *music_; // Musica que suena durante el juego
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
std::string current_room_; // Fichero de la habitación actual
PlayerSpawn spawn_point_; // Lugar de la habitación donde aparece el jugador
JA_Sound_t *death_sound_; // Sonido a reproducir cuando muere el jugador
std::shared_ptr<ScoreboardData> board_; // Estructura con los datos del marcador
bool paused_; // Indica si el juego se encuentra en pausa
bool black_screen_; // Indica si la pantalla está en negro. Se utiliza para la muerte del jugador
int black_screen_counter_; // Contador para temporizar la pantalla en negro
int total_items_; // Cantidad total de items que hay en el mapeado del juego
SDL_Rect room_name_rect_; // Rectangulo donde pintar la textura con el nombre de la habitación
// Actualiza el juego, las variables, comprueba la entrada, etc.
void update();

View File

@@ -1,67 +1,63 @@
#include "game_over.h"
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <algorithm> // for min, max
#include <string> // for basic_string, operator+, to_string, cha...
#include "animated_sprite.h" // for AnimatedSprite
#include "asset.h" // for Asset
#include "defines.h" // for GAMECANVAS_CENTER_X
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_PlayMusic
#include "options.h" // for Options, options, OptionsStats, Section...
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "text.h" // for TEXT_CENTER, TEXT_COLOR, Text
#include "texture.h" // for Texture
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <algorithm> // for min, max
#include <string> // for basic_string, operator+, to_string, cha...
#include "animated_sprite.h" // for AnimatedSprite
#include "asset.h" // for Asset
#include "defines.h" // for GAMECANVAS_CENTER_X
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_PlayMusic
#include "options.h" // for Options, options, OptionsStats, Section...
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "text.h" // for TEXT_CENTER, TEXT_COLOR, Text
#include "texture.h" // for Texture
// Constructor
GameOver::GameOver()
: screen(Screen::get()),
renderer(Screen::get()->getRenderer()),
resource(Resource::get()),
asset(Asset::get()),
input(Input::get())
: screen_(Screen::get()),
renderer_(Screen::get()->getRenderer()),
resource_(Resource::get()),
asset_(Asset::get()),
input_(Input::get())
{
// Reserva memoria para los punteros a objetos
text = resource->getText("smb2");
playerSprite = std::make_shared<AnimatedSprite>(resource->getTexture("player_game_over.png"), resource->getAnimation("player_game_over.ani"));
tvSprite = std::make_shared<AnimatedSprite>(resource->getTexture("tv.png"), resource->getAnimation("tv.ani"));
music = resource->getMusic("game_over.ogg");
text_ = resource_->getText("smb2");
player_sprite_ = std::make_shared<AnimatedSprite>(resource_->getTexture("player_game_over.png"), resource_->getAnimations("player_game_over.ani"));
tv_sprite_ = std::make_shared<AnimatedSprite>(resource_->getTexture("tv.png"), resource_->getAnimations("tv.ani"));
music_ = resource_->getMusic("game_over.ogg");
// Inicializa variables
preCounter = 0;
counter = 0;
pre_counter_ = 0;
counter_ = 0;
options.section.section = Section::GAME_OVER;
options.section.subsection = Subsection::NONE;
ticks = 0;
ticksSpeed = 15;
endSection = 400;
iniFade = 310;
fadeLenght = 20;
playerSprite->setPosX(GAMECANVAS_CENTER_X + 10);
playerSprite->setPosY(30);
tvSprite->setPosX(GAMECANVAS_CENTER_X - tvSprite->getWidth() - 10);
tvSprite->setPosY(30);
ticks_ = 0;
player_sprite_->setPosX(GAMECANVAS_CENTER_X + 10);
player_sprite_->setPosY(30);
tv_sprite_->setPosX(GAMECANVAS_CENTER_X - tv_sprite_->getWidth() - 10);
tv_sprite_->setPosY(30);
// Inicializa el vector de colores
const std::vector<std::string> colorList = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"};
for (auto cl : colorList)
{
colors.push_back(stringToColor(options.video.palette, cl));
colors_.push_back(stringToColor(options.video.palette, cl));
}
color = colors.back();
color_ = colors_.back();
}
// Actualiza el objeto
void GameOver::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks > ticksSpeed)
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
{
// Actualiza el contador de ticks
ticks = SDL_GetTicks();
ticks_ = SDL_GetTicks();
// Comprueba las entradas
checkInput();
@@ -73,44 +69,41 @@ void GameOver::update()
updateCounters();
// Actualiza los dos sprites
playerSprite->update();
tvSprite->update();
player_sprite_->update();
tv_sprite_->update();
screen->update();
screen_->update();
}
}
// Dibuja el final en pantalla
void GameOver::render()
{
const int y = 32;
constexpr int Y = 32;
// Prepara para empezar a dibujar en la textura de juego
screen->start();
// Limpia la pantalla
screen->clean();
screen_->start();
screen_->clean();
// Escribe el texto de GAME OVER
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, y, "G A M E O V E R", 1, color);
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y, "G A M E O V E R", 1, color_);
// Dibuja los sprites
playerSprite->setPosY(y + 30);
tvSprite->setPosY(y + 30);
player_sprite_->setPosY(Y + 30);
tv_sprite_->setPosY(Y + 30);
renderSprites();
// Escribe el texto con las habitaciones y los items
const std::string itemsTxt = std::to_string(options.stats.items / 100) + std::to_string((options.stats.items % 100) / 10) + std::to_string(options.stats.items % 10);
const std::string roomsTxt = std::to_string(options.stats.rooms / 100) + std::to_string((options.stats.rooms % 100) / 10) + std::to_string(options.stats.rooms % 10);
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, y + 80, "ITEMS: " + itemsTxt, 1, color);
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, y + 90, "ROOMS: " + roomsTxt, 1, color);
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 80, "ITEMS: " + itemsTxt, 1, color_);
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 90, "ROOMS: " + roomsTxt, 1, color_);
// Escribe el texto con "Tu peor pesadilla"
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, y + 110, "YOUR WORST NIGHTMARE IS", 1, color);
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, y + 120, options.stats.worst_nightmare, 1, color);
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 110, "YOUR WORST NIGHTMARE IS", 1, color_);
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 120, options.stats.worst_nightmare, 1, color_);
// Vuelca el contenido del renderizador en pantalla
screen->render();
screen_->render();
}
// Comprueba el manejador de eventos
@@ -143,53 +136,53 @@ void GameOver::run()
// Actualiza el color usado para renderizar los textos e imagenes
void GameOver::updateColor()
{
const int half = endSection / 2;
const int half = COUNTER_SECTION_END_ / 2;
if (counter < half)
if (counter_ < half)
{
const float step = std::min(counter, fadeLenght) / (float)fadeLenght;
const int index = (colors.size() - 1) - int((colors.size() - 1) * step);
color = colors[index];
const float step = std::min(counter_, COUNTER_FADE_LENGHT_) / (float)COUNTER_FADE_LENGHT_;
const int index = (colors_.size() - 1) - int((colors_.size() - 1) * step);
color_ = colors_[index];
}
else
{
const float step = std::min(std::max(counter, iniFade) - iniFade, fadeLenght) / (float)fadeLenght;
const int index = (colors.size() - 1) * step;
color = colors[index];
const float step = std::min(std::max(counter_, COUNTER_INIT_FADE_) - COUNTER_INIT_FADE_, COUNTER_FADE_LENGHT_) / (float)COUNTER_FADE_LENGHT_;
const int index = (colors_.size() - 1) * step;
color_ = colors_[index];
}
}
// Dibuja los sprites
void GameOver::renderSprites()
{
playerSprite->getTexture()->setColor(color.r, color.g, color.b);
playerSprite->render();
player_sprite_->getTexture()->setColor(color_.r, color_.g, color_.b);
player_sprite_->render();
tvSprite->getTexture()->setColor(color.r, color.g, color.b);
tvSprite->render();
tv_sprite_->getTexture()->setColor(color_.r, color_.g, color_.b);
tv_sprite_->render();
}
// Actualiza los contadores
void GameOver::updateCounters()
{
// Actualiza el contador
if (preCounter < 50)
if (pre_counter_ < 50)
{
preCounter++;
pre_counter_++;
}
else
{
counter++;
counter_++;
}
// Hace sonar la música
if (counter == 1)
if (counter_ == 1)
{
JA_PlayMusic(music, 0);
JA_PlayMusic(music_, 0);
}
// Comprueba si ha terminado la sección
else if (counter == endSection)
else if (counter_ == COUNTER_SECTION_END_)
{
options.section.section = Section::LOGO;
options.section.subsection = Subsection::LOGO_TO_TITLE;

View File

@@ -1,42 +1,43 @@
#pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
#include <vector> // for vector
#include "utils.h" // for Color
class AnimatedSprite; // lines 9-9
class Asset; // lines 10-10
class Input; // lines 11-11
class Resource; // lines 12-12
class Screen; // lines 13-13
class Text; // lines 14-14
struct JA_Music_t; // lines 15-15
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
#include <vector> // for vector
#include "utils.h" // for Color
class AnimatedSprite; // lines 9-9
class Asset; // lines 10-10
class Input; // lines 11-11
class Resource; // lines 12-12
class Screen; // lines 13-13
class Text; // lines 14-14
struct JA_Music_t; // lines 15-15
class GameOver
{
private:
// Constantes
static constexpr int COUNTER_SECTION_END_ = 400; // Contador: cuando acaba la sección
static constexpr int COUNTER_INIT_FADE_ = 310; // Contador: cuando emiepza el fade
static constexpr int COUNTER_FADE_LENGHT_ = 20; // Contador: duración del fade
// Objetos y punteros
Screen *screen; // Objeto encargado de dibujar en pantalla
SDL_Renderer *renderer; // El renderizador de la ventana
Resource *resource; // Objeto con los recursos
Asset *asset; // Objeto con los ficheros de recursos
Input *input; // Objeto pata gestionar la entrada
std::shared_ptr<Text> text; // Objeto para escribir texto en pantalla
std::shared_ptr<AnimatedSprite> playerSprite; // Sprite con el jugador
std::shared_ptr<AnimatedSprite> tvSprite; // Sprite con el televisor
Screen *screen_; // Objeto encargado de dibujar en pantalla
SDL_Renderer *renderer_; // El renderizador de la ventana
Resource *resource_; // Objeto con los recursos
Asset *asset_; // Objeto con los ficheros de recursos
Input *input_; // Objeto pata gestionar la entrada
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
std::shared_ptr<AnimatedSprite> player_sprite_; // Sprite con el jugador
std::shared_ptr<AnimatedSprite> tv_sprite_; // Sprite con el televisor
// Variables
int preCounter; // Contador previo
int counter; // Contador
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa
std::vector<Color> colors; // Vector con los colores para el fade
Color color; // Color usado para el texto y los sprites
int endSection; // Contador: cuando acaba la sección
int iniFade; // Contador: cuando emiepza el fade
int fadeLenght; // Contador: duración del fade
JA_Music_t *music; // Musica que suena durante el juego
int pre_counter_ = 0; // Contador previo
int counter_ = 0; // Contador
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
std::vector<Color> colors_; // Vector con los colores para el fade
Color color_; // Color usado para el texto y los sprites
JA_Music_t *music_; // Musica que suena durante el juego
// Actualiza el objeto
void update();

View File

@@ -1,94 +1,9 @@
#include "gif.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#define EXTENSION_INTRODUCER 0x21
#define IMAGE_DESCRIPTOR 0x2C
#define TRAILER 0x3B
#define GRAPHIC_CONTROL 0xF9
#define APPLICATION_EXTENSION 0xFF
#define COMMENT_EXTENSION 0xFE
#define PLAINTEXT_EXTENSION 0x01
#define READ(dst, size) memcpy(dst, buffer, size); buffer += size
typedef struct
{
unsigned short width;
unsigned short height;
unsigned char fields;
unsigned char background_color_index;
unsigned char pixel_aspect_ratio;
}
screen_descriptor_t;
typedef struct
{
unsigned char r;
unsigned char g;
unsigned char b;
}
rgb;
typedef struct
{
unsigned short image_left_position;
unsigned short image_top_position;
unsigned short image_width;
unsigned short image_height;
unsigned char fields;
}
image_descriptor_t;
typedef struct
{
unsigned char byte;
int prev;
int len;
}
dictionary_entry_t;
typedef struct
{
unsigned char extension_code;
unsigned char block_size;
}
extension_t;
typedef struct
{
unsigned char fields;
unsigned short delay_time;
unsigned char transparent_color_index;
}
graphic_control_extension_t;
typedef struct
{
unsigned char application_id[ 8 ];
unsigned char version[ 3 ];
}
application_extension_t;
typedef struct
{
unsigned short left;
unsigned short top;
unsigned short width;
unsigned short height;
unsigned char cell_width;
unsigned char cell_height;
unsigned char foreground_color;
unsigned char background_color;
}
plaintext_extension_t;
//static unsigned short width = 0;
//static unsigned short height = 0;
//static unsigned char* uncompressed_data = NULL;
void uncompress( int code_length,
const unsigned char *input,
int input_length,

65
source/gif.h Normal file
View File

@@ -0,0 +1,65 @@
#pragma once
#include <stdint.h>
#define EXTENSION_INTRODUCER 0x21
#define IMAGE_DESCRIPTOR 0x2C
#define TRAILER 0x3B
#define GRAPHIC_CONTROL 0xF9
#define APPLICATION_EXTENSION 0xFF
#define COMMENT_EXTENSION 0xFE
#define PLAINTEXT_EXTENSION 0x01
#define READ(dst, size) memcpy(dst, buffer, size); buffer += size
typedef struct {
unsigned short width;
unsigned short height;
unsigned char fields;
unsigned char background_color_index;
unsigned char pixel_aspect_ratio;
} screen_descriptor_t;
typedef struct {
unsigned char r, g, b;
} rgb;
typedef struct {
unsigned short image_left_position;
unsigned short image_top_position;
unsigned short image_width;
unsigned short image_height;
unsigned char fields;
} image_descriptor_t;
typedef struct {
unsigned char byte;
int prev;
int len;
} dictionary_entry_t;
typedef struct {
unsigned char extension_code;
unsigned char block_size;
} extension_t;
typedef struct {
unsigned char fields;
unsigned short delay_time;
unsigned char transparent_color_index;
} graphic_control_extension_t;
typedef struct {
unsigned char application_id[8];
unsigned char version[3];
} application_extension_t;
typedef struct {
unsigned short left, top, width, height;
unsigned char cell_width, cell_height;
unsigned char foreground_color, background_color;
} plaintext_extension_t;
void uncompress(int code_length, const unsigned char *input, int input_length, unsigned char *out);
uint32_t* LoadPalette(unsigned char *buffer);
unsigned char* LoadGif(unsigned char *buffer, unsigned short* w, unsigned short* h);

View File

@@ -1,15 +1,30 @@
#include "global_inputs.h"
#include <string> // for basic_string
#include <vector> // for vector
#include "input.h" // for Input, REPEAT_FALSE, inputs_e
#include "notifier.h" // for Notifier
#include "options.h" // for Section, Options, options, SectionState, Optio...
#include "screen.h" // for Screen
#include "utils.h" // for Palette
#include <string> // for basic_string
#include <vector> // for vector
#include "input.h" // for Input, REPEAT_FALSE, inputs_e
#include "notifier.h" // for Notifier
#include "options.h" // for Section, Options, options, SectionState, Optio...
#include "screen.h" // for Screen
#include "utils.h" // for Palette
namespace globalInputs
{
// Cambia la paleta
void quit()
{
const std::string code = options.section.section == Section::GAME ? "PRESS AGAIN TO RETURN TO MENU" : "PRESS AGAIN TO EXIT";
auto code_found = stringInVector(Notifier::get()->getCodes(), code);
if (code_found)
{
// Si la notificación de salir está activa, cambia de sección
options.section.section = options.section.section == Section::GAME ? Section::TITLE : Section::QUIT;
}
else
{
// Si la notificación de salir no está activa, muestra la notificación
Notifier::get()->show({code}, NotificationText::CENTER, -1, true, code);
}
}
// Cambia la paleta de colores
void switchPalette()
{
options.video.palette = options.video.palette == Palette::ZXSPECTRUM ? Palette::ZXARNE : Palette::ZXSPECTRUM;
@@ -41,7 +56,7 @@ namespace globalInputs
{
if (Input::get()->checkInput(input_exit, REPEAT_FALSE))
{
options.section.section = Section::QUIT;
quit();
}
else if (Input::get()->checkInput(input_accept, REPEAT_FALSE))
@@ -52,32 +67,41 @@ namespace globalInputs
else if (Input::get()->checkInput(input_toggle_border, REPEAT_FALSE))
{
Screen::get()->toggleBorder();
Notifier::get()->show({"BORDER " + std::string(options.video.border.enabled ? "ENABLED" : "DISABLED")}, NotificationText::CENTER);
}
else if (Input::get()->checkInput(input_toggle_videomode, REPEAT_FALSE))
{
Screen::get()->toggleVideoMode();
Notifier::get()->show({"FULLSCREEN " + std::string(options.video.mode == 0 ? "DISABLED" : "ENABLED")}, NotificationText::CENTER);
}
else if (Input::get()->checkInput(input_window_dec_size, REPEAT_FALSE))
{
Screen::get()->decWindowZoom();
if (Screen::get()->decWindowZoom())
{
Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(options.window.zoom)}, NotificationText::CENTER);
}
}
else if (Input::get()->checkInput(input_window_inc_size, REPEAT_FALSE))
{
Screen::get()->incWindowZoom();
if (Screen::get()->incWindowZoom())
{
Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(options.window.zoom)}, NotificationText::CENTER);
}
}
else if (Input::get()->checkInput(input_toggle_shaders, REPEAT_FALSE))
{
Screen::get()->toggleShaders();
Notifier::get()->show({"HOLA"});
Notifier::get()->show({"SHADERS " + std::string(options.video.shaders ? "ENABLED" : "DISABLED")}, NotificationText::CENTER);
}
else if (Input::get()->checkInput(input_toggle_palette, REPEAT_FALSE))
{
switchPalette();
Notifier::get()->show({"PALETTE " + std::string(options.video.palette == Palette::ZXSPECTRUM ? "ZX SPECTRUM" : "ZX ARNE")}, NotificationText::CENTER);
}
}
}

View File

@@ -76,9 +76,9 @@ private:
std::vector<std::string> controller_names_; // Vector con los nombres de los mandos
int num_gamepads_; // Numero de mandos conectados
std::string db_path_; // Ruta al archivo gamecontrollerdb.txt
bool verbose_ = true; // Indica si ha de mostrar mensajes
bool verbose_ = true; // Indica si ha de mostrar mensajes
i_disable_e disabled_until_; // Tiempo que esta deshabilitado
bool enabled_ = true; // Indica si está habilitado
bool enabled_ = true; // Indica si está habilitado
// Constructor
explicit Input(const std::string &game_controller_db_path);

View File

@@ -1,59 +1,57 @@
#include "item.h"
#include "resource.h"
#include "sprite.h" // Para Sprite
#include "texture.h" // Para Texture
// Constructor
Item::Item(item_t item)
Item::Item(ItemData item)
{
constexpr int ITEMSIZE = 8;
// Crea objetos;
sprite = std::make_shared<Sprite>(item.texture, item.x, item.y, ITEMSIZE, ITEMSIZE);
sprite_ = std::make_shared<Sprite>(Resource::get()->getTexture(item.tile_set_file), item.x, item.y, ITEMSIZE, ITEMSIZE);
// Inicia variables
sprite->setClip((item.tile % 10) * ITEMSIZE, (item.tile / 10) * ITEMSIZE, ITEMSIZE, ITEMSIZE);
collider = sprite->getRect();
colorChangeSpeed = 4;
counter = item.counter * colorChangeSpeed;
sprite_->setClip((item.tile % 10) * ITEMSIZE, (item.tile / 10) * ITEMSIZE, ITEMSIZE, ITEMSIZE);
collider_ = sprite_->getRect();
change_color_speed = 4;
counter_ = item.counter * change_color_speed;
// Inicializa los colores
Color c = item.color1;
color.push_back(c);
color.push_back(c);
color_.push_back(item.color1);
color_.push_back(item.color1);
c = item.color2;
color.push_back(c);
color.push_back(c);
color_.push_back(item.color2);
color_.push_back(item.color2);
}
// Pinta el objeto en pantalla
void Item::render()
{
const int index = (counter / colorChangeSpeed) % color.size();
sprite->getTexture()->setColor(color[index].r, color[index].g, color[index].b);
sprite->render();
sprite->getTexture()->setColor(255, 255, 255);
const int index = (counter_ / change_color_speed) % color_.size();
sprite_->getTexture()->setColor(color_[index].r, color_[index].g, color_[index].b);
sprite_->render();
sprite_->getTexture()->setColor(255, 255, 255);
}
// Obtiene su ubicación
SDL_Point Item::getPos()
{
const SDL_Point p = {sprite->getX(), sprite->getY()};
const SDL_Point p = {sprite_->getX(), sprite_->getY()};
return p;
}
// Asigna los colores del objeto
void Item::setColors(Color col1, Color col2)
{
// Reinicializa el vector de colores
color.clear();
color_.clear();
// Añade el primer color
color.push_back(col1);
color.push_back(col1);
color_.push_back(col1);
color_.push_back(col1);
// Añade el segundo color
color.push_back(col2);
color.push_back(col2);
color_.push_back(col2);
color_.push_back(col2);
}

View File

@@ -1,45 +1,43 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <memory> // for shared_ptr, __shared_ptr_access
#include <string> // for string
#include <vector> // for vector
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include "utils.h" // for Color
#include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <memory> // for shared_ptr, __shared_ptr_access
#include <string> // for string
#include <vector> // for vector
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include "utils.h" // for Color
struct item_t
struct ItemData
{
SDL_Renderer *renderer; // El renderizador de la ventana
std::shared_ptr<Texture> texture; // Textura con los gráficos del item
std::string tileSetFile; // Ruta al fichero con los gráficos del item
int x; // Posición del item en pantalla
int y; // Posición del item en pantalla
int tile; // Número de tile dentro de la textura
int counter; // Contador inicial. Es el que lo hace cambiar de color
Color color1; // Uno de los dos colores que se utiliza para el item
Color color2; // Uno de los dos colores que se utiliza para el item
std::string tile_set_file; // Ruta al fichero con los gráficos del item
int x; // Posición del item en pantalla
int y; // Posición del item en pantalla
int tile; // Número de tile dentro de la textura
int counter; // Contador inicial. Es el que lo hace cambiar de color
Color color1; // Uno de los dos colores que se utiliza para el item
Color color2; // Uno de los dos colores que se utiliza para el item
// Constructor por defecto
item_t() : renderer(nullptr), texture(nullptr), x(0), y(0), tile(0), counter(0), color1(), color2() {}
// Constructor
ItemData() : x(0), y(0), tile(0), counter(0), color1(), color2() {}
};
class Item
{
private:
// Objetos y punteros
std::shared_ptr<Sprite> sprite; // Sprite del objeto
std::shared_ptr<Sprite> sprite_; // Sprite del objeto
// Variables
std::vector<Color> color; // Vector con los colores del objeto
int counter; // Contador interno
SDL_Rect collider; // Rectangulo de colisión
int colorChangeSpeed; // Cuanto mas alto, mas tarda en cambiar de color
std::vector<Color> color_; // Vector con los colores del objeto
int counter_; // Contador interno
SDL_Rect collider_; // Rectangulo de colisión
int change_color_speed; // Cuanto mas alto, mas tarda en cambiar de color
public:
// Constructor
Item(item_t item);
Item(ItemData item);
// Destructor
~Item() = default;
@@ -48,18 +46,17 @@ public:
void render();
// Actualiza las variables del objeto
void update() { counter++; }
void update() { counter_++; }
// Obtiene el rectangulo de colision del objeto
SDL_Rect &getCollider() { return collider; }
SDL_Rect &getCollider() { return collider_; }
// Obtiene su ubicación
SDL_Point getPos();
// Recarga la textura
void reLoadTexture() { sprite->getTexture()->reLoad(); }
void reLoadTexture() { sprite_->getTexture()->reLoad(); }
// Asigna los colores del objeto
void setColors(Color col1, Color col2);
};

View File

@@ -1,50 +1,57 @@
#include "item_tracker.h"
// Destructor
ItemTracker::~ItemTracker()
// [SINGLETON]
ItemTracker *ItemTracker::item_tracker_ = nullptr;
// [SINGLETON] Crearemos el objeto con esta función estática
void ItemTracker::init()
{
list.clear();
ItemTracker::item_tracker_ = new ItemTracker();
}
// [SINGLETON] Destruiremos el objeto con esta función estática
void ItemTracker::destroy()
{
delete ItemTracker::item_tracker_;
}
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
ItemTracker *ItemTracker::get()
{
return ItemTracker::item_tracker_;
}
// Comprueba si el objeto ya ha sido cogido
bool ItemTracker::hasBeenPicked(std::string name, SDL_Point pos)
bool ItemTracker::hasBeenPicked(const std::string &name, SDL_Point pos)
{
bool success = false;
// Primero busca si ya hay una entrada con ese nombre
const int index = findByName(name);
if (index != -1)
if (const int index = findByName(name); index != -1)
{
// Luego busca si existe ya una entrada con esa posición
if (findByPos(index, pos) != -1)
{
success = true;
return true;
}
}
return success;
return false;
}
// Añade el objeto a la lista de objetos cogidos
void ItemTracker::addItem(std::string name, SDL_Point pos)
void ItemTracker::addItem(const std::string &name, SDL_Point pos)
{
// Comprueba si el objeto no ha sido recogido con anterioridad
if (!hasBeenPicked(name, pos))
{
// Primero busca si ya hay una entrada con ese nombre
const int index = findByName(name);
if (index != -1)
if (const int index = findByName(name); index != -1)
{
list[index].pos.push_back(pos);
item_list_.at(index).pos.push_back(pos);
}
// En caso contrario crea la entrada
else
{
item_tracker_t item;
item.name = name;
item.pos.push_back(pos);
list.push_back(item);
item_list_.emplace_back(name, pos);
}
}
}
@@ -54,7 +61,7 @@ int ItemTracker::findByName(std::string name)
{
int i = 0;
for (auto l : list)
for (const auto &l : item_list_)
{
if (l.name == name)
{
@@ -71,7 +78,7 @@ int ItemTracker::findByPos(int index, SDL_Point pos)
{
int i = 0;
for (auto l : list[index].pos)
for (const auto &l : item_list_[index].pos)
{
if ((l.x == pos.x) && (l.y == pos.y))
{

View File

@@ -4,17 +4,27 @@
#include <string> // Para string, basic_string
#include <vector> // Para vector
struct item_tracker_t
struct ItemTrackerData
{
std::string name; // Nombre de la habitación donde se encuentra el objeto
std::vector<SDL_Point> pos; // Lista de objetos cogidos de la habitación
// Constructor
ItemTrackerData(const std::string &name, const SDL_Point &position)
: name(name)
{
pos.push_back(position);
}
};
class ItemTracker
{
private:
// [SINGLETON] Objeto privado
static ItemTracker *item_tracker_;
// Variables
std::vector<item_tracker_t> list; // Lista con todos los objetos recogidos
std::vector<ItemTrackerData> item_list_; // Lista con todos los objetos recogidos
// Busca una entrada en la lista por nombre
int findByName(std::string name);
@@ -22,13 +32,25 @@ private:
// Busca una entrada en la lista por posición
int findByPos(int index, SDL_Point pos);
public:
// Constructor
ItemTracker() = default;
// Destructor
~ItemTracker();
~ItemTracker() = default;
public:
// [SINGLETON] Crearemos el objeto con esta función estática
static void init();
// [SINGLETON] Destruiremos el objeto con esta función estática
static void destroy();
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
static ItemTracker *get();
// Comprueba si el objeto ya ha sido cogido
bool hasBeenPicked(std::string name, SDL_Point pos);
bool hasBeenPicked(const std::string &name, SDL_Point pos);
// Añade el objeto a la lista de objetos cogidos
void addItem(std::string name, SDL_Point pos);
void addItem(const std::string &name, SDL_Point pos);
};

View File

@@ -14,6 +14,7 @@
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include "utils.h" // for Color, stringToColor, Palette
#include <iostream>
// Constructor
LoadingScreen::LoadingScreen()
@@ -40,6 +41,16 @@ LoadingScreen::LoadingScreen()
loading_sound2_ = resource_->getMusic("loading_sound2.ogg");
loading_sound3_ = resource_->getMusic("loading_sound3.ogg");
texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, options.game.width, options.game.height);
if (texture_ == nullptr)
{
if (options.console)
{
std::cout << "LoadingScreen::texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
clearTexture();
// Inicializa variables
options.section.section = Section::LOADING_SCREEN;
options.section.subsection = Subsection::NONE;
@@ -71,6 +82,7 @@ LoadingScreen::LoadingScreen()
LoadingScreen::~LoadingScreen()
{
JA_StopMusic();
SDL_DestroyTexture(texture_);
}
// Comprueba el manejador de eventos
@@ -165,8 +177,8 @@ void LoadingScreen::renderBorder()
// Añade lineas amarillas
color = stringToColor(options.video.palette, "yellow");
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 0xFF);
const int width = GAMECANVAS_WIDTH + (options.video.border.width * 2);
const int height = GAMECANVAS_HEIGHT + (options.video.border.height * 2);
const int width = options.game.width + (options.video.border.width * 2);
const int height = options.game.height + (options.video.border.height * 2);
bool drawEnabled = rand() % 2 == 0 ? true : false;
int row = 0;
int rowSize = 1;
@@ -187,12 +199,13 @@ void LoadingScreen::renderBorder()
void LoadingScreen::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks_ > ticks_speed_)
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
{
ticks_ = SDL_GetTicks();
checkInput();
updateCounter();
updateLoad();
fillTexture();
screen_->update();
}
}
@@ -212,8 +225,8 @@ void LoadingScreen::render()
// Prepara para empezar a dibujar en la textura de juego
screen_->start();
// Dibuja la pantalla de carga
renderLoad();
// Copila la textura a la pantalla
SDL_RenderCopy(renderer_, texture_, nullptr, nullptr);
// Vuelca el contenido del renderizador en pantalla
screen_->render();
@@ -279,3 +292,32 @@ void LoadingScreen::recreateLoadingScreen()
// Vuelca el contenido del renderizador en pantalla
screen_->render();
}
// Dibuja sobre la textura
void LoadingScreen::fillTexture()
{
// Empieza a dibujar en la textura
auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, texture_);
// Dibuja la pantalla de carga
renderLoad();
// Deja el renderizador como estaba
SDL_SetRenderTarget(renderer_, temp);
}
// Limpia la textura
void LoadingScreen::clearTexture()
{
// Empieza a dibujar en la textura
auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, texture_);
// Limpia
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
SDL_RenderClear(renderer_);
// Deja el renderizador como estaba
SDL_SetRenderTarget(renderer_, temp);
}

View File

@@ -1,16 +1,16 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
class Asset; // lines 8-8
class Input; // lines 9-9
class Resource; // lines 10-10
class Screen; // lines 11-11
class Sprite; // lines 12-12
class Texture; // lines 13-13
struct JA_Music_t; // lines 14-14
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
class Asset; // lines 8-8
class Input; // lines 9-9
class Resource; // lines 10-10
class Screen; // lines 11-11
class Sprite; // lines 12-12
class Texture; // lines 13-13
struct JA_Music_t; // lines 14-14
class LoadingScreen
{
@@ -30,7 +30,6 @@ private:
int pre_counter_ = 0; // Contador previo para realizar una pausa inicial
int counter_ = 0; // Contador
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticks_speed_ = 15; // Velocidad a la que se repiten los bucles del programa
int load_counter_ = 0; // Contador para controlar las cargas
bool loading_first_part_ = true; // Para saber en que parte de la carga se encuentra
JA_Music_t *loading_sound1_; // Sonidos para imitar la carga tipo spectrum
@@ -38,6 +37,7 @@ private:
JA_Music_t *loading_sound3_; // Sonidos para imitar la carga tipo spectrum
int line_index_[192]; // El orden en el que se procesan las 192 lineas de la pantalla de carga
SDL_Rect load_rect_ = {0, 0, 51, 1}; // Rectangulo para dibujar la pantalla de carga
SDL_Texture *texture_; // Textura para dibujar la pantalla de carga
// Actualiza las variables
void update();
@@ -66,6 +66,12 @@ private:
// Reconstruye la pantalla de carga
void recreateLoadingScreen();
// Dibuja sobre la textura
void fillTexture();
// Limpia la textura
void clearTexture();
public:
// Constructor
LoadingScreen();

View File

@@ -1,18 +1,19 @@
#include "logo.h"
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <string> // for basic_string, string
#include "asset.h" // for Asset
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_StopMusic
#include "options.h" // for Options, options, SectionState, Section
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include "utils.h" // for Color, stringToColor
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <string> // for basic_string, string
#include "asset.h" // for Asset
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_StopMusic
#include "options.h" // for Options, options, SectionState, Section
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include "utils.h" // for Color, stringToColor
#include "defines.h"
// Constructor
Logo::Logo()
@@ -153,43 +154,43 @@ void Logo::updateTextureColors()
since_1998_texture_->setColor(color_[7].r, color_[7].g, color_[7].b);
}
else if (counter_ == init_fade_ + inc * 0)
else if (counter_ == INIT_FADE_ + inc * 0)
{
jailgames_texture_->setColor(color_[6].r, color_[6].g, color_[6].b);
since_1998_texture_->setColor(color_[6].r, color_[6].g, color_[6].b);
}
else if (counter_ == init_fade_ + inc * 1)
else if (counter_ == INIT_FADE_ + inc * 1)
{
jailgames_texture_->setColor(color_[5].r, color_[5].g, color_[5].b);
since_1998_texture_->setColor(color_[5].r, color_[5].g, color_[5].b);
}
else if (counter_ == init_fade_ + inc * 2)
else if (counter_ == INIT_FADE_ + inc * 2)
{
jailgames_texture_->setColor(color_[4].r, color_[4].g, color_[4].b);
since_1998_texture_->setColor(color_[4].r, color_[4].g, color_[4].b);
}
else if (counter_ == init_fade_ + inc * 3)
else if (counter_ == INIT_FADE_ + inc * 3)
{
jailgames_texture_->setColor(color_[3].r, color_[3].g, color_[3].b);
since_1998_texture_->setColor(color_[3].r, color_[3].g, color_[3].b);
}
else if (counter_ == init_fade_ + inc * 4)
else if (counter_ == INIT_FADE_ + inc * 4)
{
jailgames_texture_->setColor(color_[2].r, color_[2].g, color_[2].b);
since_1998_texture_->setColor(color_[2].r, color_[2].g, color_[2].b);
}
else if (counter_ == init_fade_ + inc * 5)
else if (counter_ == INIT_FADE_ + inc * 5)
{
jailgames_texture_->setColor(color_[1].r, color_[1].g, color_[1].b);
since_1998_texture_->setColor(color_[1].r, color_[1].g, color_[1].b);
}
else if (counter_ == init_fade_ + inc * 6)
else if (counter_ == INIT_FADE_ + inc * 6)
{
jailgames_texture_->setColor(color_[0].r, color_[0].g, color_[0].b);
since_1998_texture_->setColor(color_[0].r, color_[0].g, color_[0].b);
@@ -200,7 +201,7 @@ void Logo::updateTextureColors()
void Logo::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks_ > ticks_speed_)
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();
@@ -220,7 +221,7 @@ void Logo::update()
screen_->update();
// Comprueba si ha terminado el logo
if (counter_ == end_logo_ + post_logo_)
if (counter_ == END_LOGO_ + POST_LOGO_)
{
endSection();
}

View File

@@ -1,20 +1,25 @@
#pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
#include <vector> // for vector
#include "utils.h" // for Color
class Asset; // lines 8-8
class Input; // lines 9-9
class Resource; // lines 10-10
class Screen; // lines 11-11
class Sprite; // lines 12-12
class Texture; // lines 13-13
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
#include <vector> // for vector
#include "utils.h" // for Color
class Asset; // lines 8-8
class Input; // lines 9-9
class Resource; // lines 10-10
class Screen; // lines 11-11
class Sprite; // lines 12-12
class Texture; // lines 13-13
class Logo
{
private:
// Constantes
static constexpr int INIT_FADE_ = 300; // Tiempo del contador cuando inicia el fade a negro
static constexpr int END_LOGO_ = 400; // Tiempo del contador para terminar el logo
static constexpr int POST_LOGO_ = 20; // Tiempo que dura el logo con el fade al maximo
// Objetos y punteros
Screen *screen_; // Objeto encargado de dibujar en pantalla
SDL_Renderer *renderer_; // El renderizador de la ventana
@@ -30,10 +35,6 @@ private:
std::vector<Color> color_; // Vector con los colores para el fade
int counter_ = 0; // Contador
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticks_speed_ = 15; // Velocidad a la que se repiten los bucles del programa
int init_fade_ = 300; // Tiempo del contador cuando inicia el fade a negro
int end_logo_ = 400; // Tiempo del contador para terminar el logo
int post_logo_ = 20; // Tiempo que dura el logo con el fade al maximo
// Actualiza las variables
void update();

View File

@@ -16,7 +16,7 @@
Notifier *Notifier::notifier_ = nullptr;
// [SINGLETON] Crearemos el objeto con esta función estática
void Notifier::init(const std::string &icon_file, std::shared_ptr<Text> text)
void Notifier::init(const std::string &icon_file, const std::string &text)
{
Notifier::notifier_ = new Notifier(icon_file, text);
}
@@ -34,10 +34,10 @@ Notifier *Notifier::get()
}
// Constructor
Notifier::Notifier(std::string icon_file, std::shared_ptr<Text> text)
Notifier::Notifier(const std::string &icon_file, const std::string &text)
: renderer_(Screen::get()->getRenderer()),
icon_texture_(!icon_file.empty() ? std::make_unique<Texture>(renderer_, icon_file) : nullptr),
text_(text),
icon_texture_(!icon_file.empty() ? Resource::get()->getTexture(icon_file) : nullptr),
text_(Resource::get()->getText(text)),
bg_color_(options.notifications.color),
wait_time_(150),
stack_(false),
@@ -84,18 +84,19 @@ void Notifier::update()
// Comprueba los estados
if (notifications_[i].state == NotificationStatus::RISING)
{
const float step = ((float)notifications_[i].counter / notifications_[i].travel_dist);
const int alpha = 255 * step;
//const float step = ((float)notifications_[i].counter / notifications_[i].travel_dist);
//const int alpha = 255 * step;
constexpr int ALPHA = 255;
if (options.notifications.getVerticalPosition() == "TOP")
if (options.notifications.getVerticalPosition() == NotificationPosition::TOP)
{
notifications_[i].rect.y++;
}
else
else if (options.notifications.getVerticalPosition() == NotificationPosition::BOTTOM)
{
notifications_[i].rect.y--;
}
notifications_[i].texture->setAlpha(alpha);
notifications_[i].texture->setAlpha(ALPHA);
if (notifications_[i].rect.y == notifications_[i].y)
{
@@ -116,18 +117,20 @@ void Notifier::update()
else if (notifications_[i].state == NotificationStatus::VANISHING)
{
const float step = (notifications_[i].counter / (float)notifications_[i].travel_dist);
const int alpha = 255 * (1 - step);
//const float step = (notifications_[i].counter / (float)notifications_[i].travel_dist);
//const int ALPHA = 255 * (1 - step);
constexpr int ALPHA = 255;
if (options.notifications.getVerticalPosition() == "TOP")
if (options.notifications.getVerticalPosition() == NotificationPosition::TOP)
{
notifications_[i].rect.y--;
}
else
else if (options.notifications.getVerticalPosition() == NotificationPosition::BOTTOM)
{
notifications_[i].rect.y++;
}
notifications_[i].texture->setAlpha(alpha);
notifications_[i].texture->setAlpha(ALPHA);
if (notifications_[i].rect.y == notifications_[i].y - notifications_[i].travel_dist)
{
@@ -153,7 +156,7 @@ void Notifier::clearFinishedNotifications()
}
}
void Notifier::show(std::vector<std::string> texts, int icon, const std::string &code)
void Notifier::show(std::vector<std::string> texts, NotificationText text_is, int icon, bool can_be_removed, const std::string &code)
{
// Si no hay texto, acaba
if (texts.empty())
@@ -181,43 +184,41 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string
}
// Inicializa variables
constexpr int icon_size = 16;
constexpr int padding_out = 1;
const auto padding_in_h = text_->getCharacterSize();
const auto padding_in_v = text_->getCharacterSize() / 2;
const int icon_space = icon >= 0 ? icon_size + padding_in_h : 0;
const int width = text_->lenght(longest) + (padding_in_h * 2) + icon_space;
const int icon_space = icon >= 0 ? ICON_SIZE_ + padding_in_h : 0;
text_is = icon_space > 0 ? NotificationText::LEFT : text_is;
const int width = options.game.width - (PADDING_OUT_ * 2);
const int height = (text_->getCharacterSize() * texts.size()) + (padding_in_v * 2);
const auto shape = NotificationShape::SQUARED;
// Posición horizontal
auto desp_h = 0;
if (options.notifications.getHorizontalPosition() == "LEFT")
if (options.notifications.getHorizontalPosition() == NotificationPosition::LEFT)
{
desp_h = padding_out;
desp_h = PADDING_OUT_;
}
else if (options.notifications.getHorizontalPosition() == "CENTER")
else if (options.notifications.getHorizontalPosition() == NotificationPosition::CENTER)
{
desp_h = ((options.game.width / 2) - (width / 2));
}
else
else if (options.notifications.getHorizontalPosition() == NotificationPosition::RIGHT)
{
desp_h = options.game.width - width - padding_out;
desp_h = options.game.width - width - PADDING_OUT_;
}
// Posición vertical
const int desp_v = (options.notifications.getVerticalPosition() == "TOP") ? padding_out : (options.game.height - height - padding_out);
const int desp_v = (options.notifications.getVerticalPosition() == NotificationPosition::TOP) ? PADDING_OUT_ : options.game.height - height - PADDING_OUT_;
// Offset
const auto travel_dist = height + padding_out;
const auto travel_dist = height + PADDING_OUT_;
auto offset = 0;
if (options.notifications.getVerticalPosition() == "TOP")
if (options.notifications.getVerticalPosition() == NotificationPosition::TOP)
{
offset = !notifications_.empty() ? notifications_.back().y + travel_dist : desp_v;
offset = !notifications_.empty() ? notifications_.back().y + notifications_.back().travel_dist : desp_v;
}
else
else if (options.notifications.getVerticalPosition() == NotificationPosition::BOTTOM)
{
offset = !notifications_.empty() ? notifications_.back().y - travel_dist : desp_v;
offset = !notifications_.empty() ? notifications_.back().y - notifications_.back().travel_dist : desp_v;
}
// Crea la notificacion
@@ -225,11 +226,12 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string
// Inicializa variables
n.code = code;
n.can_be_removed = can_be_removed;
n.y = offset;
n.travel_dist = travel_dist;
n.texts = texts;
n.shape = shape;
int y_pos = offset + ((options.notifications.getVerticalPosition() == "TOP") ? -travel_dist : travel_dist);
int y_pos = offset + ((options.notifications.getVerticalPosition() == NotificationPosition::TOP) ? -travel_dist : travel_dist);
n.rect = {desp_h, y_pos, width, height};
// Crea la textura
@@ -266,9 +268,9 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string
// Dibuja el icono de la notificación
if (has_icons_ && icon >= 0 && texts.size() >= 2)
{
auto sp = std::make_unique<Sprite>(icon_texture_, (SDL_Rect){0, 0, icon_size, icon_size});
sp->setPosition({padding_in_h, padding_in_v, icon_size, icon_size});
sp->setClip({icon_size * (icon % 10), icon_size * (icon / 10), icon_size, icon_size});
auto sp = std::make_unique<Sprite>(icon_texture_, (SDL_Rect){0, 0, ICON_SIZE_, ICON_SIZE_});
sp->setPosition({padding_in_h, padding_in_v, ICON_SIZE_, ICON_SIZE_});
sp->setClip({ICON_SIZE_ * (icon % 10), ICON_SIZE_ * (icon / 10), ICON_SIZE_, ICON_SIZE_});
sp->render();
}
@@ -277,7 +279,14 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string
int iterator = 0;
for (const auto &text : texts)
{
text_->writeColored(padding_in_h + icon_space, padding_in_v + iterator * (text_->getCharacterSize() + 1), text, color);
if (text_is == NotificationText::LEFT)
{
text_->writeColored(padding_in_h + icon_space, padding_in_v + iterator * (text_->getCharacterSize() + 1), text, color);
}
else if (text_is == NotificationText::CENTER)
{
text_->writeDX(TEXT_CENTER | TEXT_COLOR, width / 2, padding_in_v + iterator * (text_->getCharacterSize() + 1), text, 1, color);
}
++iterator;
}
@@ -302,7 +311,10 @@ void Notifier::clearNotifications()
{
for (auto &notification : notifications_)
{
notification.state = NotificationStatus::FINISHED;
if (notification.can_be_removed)
{
notification.state = NotificationStatus::FINISHED;
}
}
clearFinishedNotifications();

View File

@@ -10,9 +10,19 @@ class Sprite; // lines 9-9
class Text; // lines 10-10
class Texture; // lines 11-11
enum class NotificationText
{
LEFT,
CENTER,
};
class Notifier
{
private:
// Constantes
static constexpr int ICON_SIZE_ = 16;
static constexpr int PADDING_OUT_ = 0;
// [SINGLETON] Objeto notifier
static Notifier *notifier_;
@@ -42,11 +52,14 @@ private:
int y;
int travel_dist;
std::string code; // Permite asignar un código a la notificación
bool can_be_removed;
int height;
// Constructor
explicit Notification()
: texture(nullptr), sprite(nullptr), texts(), counter(0), state(NotificationStatus::RISING),
shape(NotificationShape::SQUARED), rect{0, 0, 0, 0}, y(0), travel_dist(0), code("") {}
shape(NotificationShape::SQUARED), rect{0, 0, 0, 0}, y(0), travel_dist(0), code(""),
can_be_removed(true), height(0) {}
};
// Objetos y punteros
@@ -71,14 +84,14 @@ private:
// [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos notifier desde fuera
// Constructor
Notifier(std::string icon_file, std::shared_ptr<Text> text);
Notifier(const std::string &icon_file, const std::string &text);
// Destructor
~Notifier() = default;
public:
// [SINGLETON] Crearemos el objeto con esta función estática
static void init(const std::string &icon_file, std::shared_ptr<Text> text);
static void init(const std::string &icon_file, const std::string &text);
// [SINGLETON] Destruiremos el objeto con esta función estática
static void destroy();
@@ -93,7 +106,7 @@ public:
void update();
// Muestra una notificación de texto por pantalla
void show(std::vector<std::string> texts, int icon = -1, const std::string &code = std::string());
void show(std::vector<std::string> texts, NotificationText text_is = NotificationText::LEFT, int icon = -1, bool can_be_removed = true, const std::string &code = std::string());
// Indica si hay notificaciones activas
bool isActive();

View File

@@ -53,8 +53,13 @@ bool loadOptionsFromFile(const std::string &file_path)
while (std::getline(file, line))
{
// Elimina espacios en blanco iniciales y finales
line = std::string(std::find_if(line.begin(), line.end(), [](int ch) { return !std::isspace(ch); }), line.end());
line.erase(std::find_if(line.rbegin(), line.rend(), [](int ch) { return !std::isspace(ch); }).base(), line.end());
line = std::string(std::find_if(line.begin(), line.end(), [](int ch)
{ return !std::isspace(ch); }),
line.end());
line.erase(std::find_if(line.rbegin(), line.rend(), [](int ch)
{ return !std::isspace(ch); })
.base(),
line.end());
// Ignora líneas vacías o comentarios
if (line.empty() || line[0] == '#')
@@ -107,7 +112,6 @@ bool loadOptionsFromFile(const std::string &file_path)
return success;
}
// Guarda las opciones en un fichero
bool saveOptionsToFile(const std::string &file_path)
{
@@ -169,36 +173,105 @@ bool saveOptionsToFile(const std::string &file_path)
return success;
}
// Establece las opciones
bool setOptions(const std::string &var, const std::string &value)
{
static const std::unordered_map<std::string, std::function<void(std::string)>> optionHandlers = {
{"version", [](std::string v)
static const std::unordered_map<std::string, std::function<void(const std::string &)>> optionHandlers = {
{"version", [](const std::string &v)
{ options.version = v; }},
{"keys", [](std::string v)
{ options.keys = static_cast<ControlScheme>(safeStoi(v, static_cast<int>(ControlScheme::CURSOR))); }},
{"window.zoom", [](std::string v)
{ options.window.zoom = safeStoi(v, 1); }},
{"video.mode", [](std::string v)
{ options.video.mode = safeStoi(v, 0); }},
{"video.filter", [](std::string v)
{ options.video.filter = static_cast<ScreenFilter>(safeStoi(v, static_cast<int>(DEFAULT_VIDEO_FILTER))); }},
{"video.shaders", [](std::string v)
{"keys", [](const std::string &v)
{
int val = safeStoi(v, static_cast<int>(DEFAULT_CONTROL_SCHEME));
if (val == static_cast<int>(ControlScheme::CURSOR) || val == static_cast<int>(ControlScheme::OPQA) || val == static_cast<int>(ControlScheme::WASD))
{
options.keys = static_cast<ControlScheme>(val);
}
else
{
options.keys = DEFAULT_CONTROL_SCHEME;
}
}},
{"window.zoom", [](const std::string &v)
{
int val = safeStoi(v, DEFAULT_WINDOW_ZOOM);
if (val > 0)
{
options.window.zoom = val;
}
else
{
options.window.zoom = DEFAULT_WINDOW_ZOOM;
}
}},
{"video.mode", [](const std::string &v)
{
int val = safeStoi(v, 0);
if (val == 0 || val == SDL_WINDOW_FULLSCREEN_DESKTOP)
{
options.video.mode = val;
}
else
{
options.video.mode = 0;
}
}},
{"video.filter", [](const std::string &v)
{
int val = safeStoi(v, static_cast<int>(DEFAULT_VIDEO_FILTER));
if (val == static_cast<int>(ScreenFilter::NEAREST) || val == static_cast<int>(ScreenFilter::LINEAR))
{
options.video.filter = static_cast<ScreenFilter>(val);
}
else
{
options.video.filter = DEFAULT_VIDEO_FILTER;
}
}},
{"video.shaders", [](const std::string &v)
{ options.video.shaders = stringToBool(v); }},
{"video.vertical_sync", [](std::string v)
{"video.vertical_sync", [](const std::string &v)
{ options.video.vertical_sync = stringToBool(v); }},
{"video.integer_scale", [](std::string v)
{"video.integer_scale", [](const std::string &v)
{ options.video.integer_scale = stringToBool(v); }},
{"video.keep_aspect", [](std::string v)
{"video.keep_aspect", [](const std::string &v)
{ options.video.keep_aspect = stringToBool(v); }},
{"video.border.enabled", [](std::string v)
{"video.border.enabled", [](const std::string &v)
{ options.video.border.enabled = stringToBool(v); }},
{"video.border.width", [](std::string v)
{ options.video.border.width = safeStoi(v, 32); }},
{"video.border.height", [](std::string v)
{ options.video.border.height = safeStoi(v, 24); }},
{"video.palette", [](std::string v)
{ options.video.palette = static_cast<Palette>(safeStoi(v, static_cast<int>(DEFAULT_PALETTE))); }}};
{"video.border.width", [](const std::string &v)
{
int val = safeStoi(v, DEFAULT_BORDER_WIDTH);
if (val > 0)
{
options.video.border.width = val;
}
else
{
options.video.border.width = DEFAULT_BORDER_WIDTH;
}
}},
{"video.border.height", [](const std::string &v)
{
int val = safeStoi(v, DEFAULT_BORDER_HEIGHT);
if (val > 0)
{
options.video.border.height = val;
}
else
{
options.video.border.height = DEFAULT_BORDER_HEIGHT;
}
}},
{"video.palette", [](const std::string &v)
{
int val = safeStoi(v, static_cast<int>(DEFAULT_PALETTE));
if (val == static_cast<int>(Palette::ZXSPECTRUM) || val == static_cast<int>(Palette::ZXARNE))
{
options.video.palette = static_cast<Palette>(val);
}
else
{
options.video.palette = DEFAULT_PALETTE;
}
}}};
auto it = optionHandlers.find(var);
if (it != optionHandlers.end())

View File

@@ -1,9 +1,10 @@
#pragma once
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <string> // for string, basic_string
#include "screen.h" // for ScreenFilter
#include "utils.h" // for Color, Palette
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <string> // for string, basic_string
#include "screen.h" // for ScreenFilter
#include "utils.h" // for Color, Palette
#include <algorithm>
// Secciones del programa
enum class Section
@@ -36,11 +37,15 @@ enum class NotificationPosition
UPPER_LEFT,
UPPER_CENTER,
UPPER_RIGHT,
MIDDLE_LEFT,
MIDDLE_RIGHT,
BOTTOM_LEFT,
BOTTOM_CENTER,
BOTTOM_RIGHT
BOTTOM_RIGHT,
TOP,
BOTTOM,
LEFT,
RIGHT,
CENTER,
UNKNOWN,
};
// Tipos de control de teclado
@@ -64,6 +69,12 @@ constexpr bool DEFAULT_VIDEO_KEEP_ASPECT = true;
constexpr bool DEFAULT_BORDER_ENABLED = true; // Borde activado por defecto
constexpr int DEFAULT_BORDER_WIDTH = 32; // Ancho del borde por defecto
constexpr int DEFAULT_BORDER_HEIGHT = 24; // Alto del borde por defecto
constexpr int DEFAULT_SOUND_VOLUME = 100; // Volumen por defecto de los efectos de sonido
constexpr bool DEFAULT_SOUND_ENABLED = true; // Sonido habilitado por defecto
constexpr int DEFAULT_MUSIC_VOLUME = 80; // Volumen por defecto de la musica
constexpr bool DEFAULT_MUSIC_ENABLED = true; // Musica habilitada por defecto
constexpr int DEFAULT_AUDIO_VOLUME = 100; // Volumen por defecto
constexpr bool DEFAULT_AUDIO_ENABLED = true; // Audio por defecto
constexpr Palette DEFAULT_PALETTE = Palette::ZXSPECTRUM; // Paleta por defecto
constexpr Section DEFAULT_SECTION = Section::LOGO; // Sección por defecto
constexpr Subsection DEFAULT_SUBSECTION = Subsection::LOGO_TO_INTRO; // Subsección por defecto
@@ -72,7 +83,7 @@ constexpr NotificationPosition DEFAULT_NOTIFICATION_POSITION = NotificationPosit
constexpr bool DEFAULT_NOTIFICATION_SOUND = true; // Sonido de las notificaciones por defecto
const Color DEFAULT_NOTIFICATION_COLOR = Color(48, 48, 48); // Color de las notificaciones por defecto
constexpr bool DEFAULT_CONSOLE = false; // Consola desactivada por defecto
constexpr std::string DEFAULT_VERSION = "1.09"; // Versión por defecto
constexpr const char *DEFAULT_VERSION = "1.09"; // Versión por defecto
// Estructura para las opciones de las notificaciones
struct OptionsNotification
@@ -94,43 +105,42 @@ struct OptionsNotification
color(c) {}
// Método que devuelve la posición horizontal
std::string getHorizontalPosition() const
NotificationPosition getHorizontalPosition() const
{
switch (pos)
{
case NotificationPosition::UPPER_LEFT:
case NotificationPosition::MIDDLE_LEFT:
case NotificationPosition::BOTTOM_LEFT:
return "LEFT";
return NotificationPosition::LEFT;
case NotificationPosition::UPPER_CENTER:
case NotificationPosition::BOTTOM_CENTER:
return "CENTER";
return NotificationPosition::CENTER;
case NotificationPosition::UPPER_RIGHT:
case NotificationPosition::MIDDLE_RIGHT:
case NotificationPosition::BOTTOM_RIGHT:
return "RIGHT";
return NotificationPosition::RIGHT;
default:
return NotificationPosition::UNKNOWN;
}
return "UNKNOWN";
return NotificationPosition::UNKNOWN;
}
// Método que devuelve la posición vertical
std::string getVerticalPosition() const
NotificationPosition getVerticalPosition() const
{
switch (pos)
{
case NotificationPosition::UPPER_LEFT:
case NotificationPosition::UPPER_CENTER:
case NotificationPosition::UPPER_RIGHT:
return "UPPER";
case NotificationPosition::MIDDLE_LEFT:
case NotificationPosition::MIDDLE_RIGHT:
return "MIDDLE";
return NotificationPosition::TOP;
case NotificationPosition::BOTTOM_LEFT:
case NotificationPosition::BOTTOM_CENTER:
case NotificationPosition::BOTTOM_RIGHT:
return "BOTTOM";
return NotificationPosition::BOTTOM;
default:
return NotificationPosition::UNKNOWN;
}
return "UNKNOWN";
return NotificationPosition::UNKNOWN;
}
};
@@ -211,15 +221,18 @@ struct OptionsStats
// Estructura con opciones de la ventana
struct OptionsWindow
{
int zoom; // Zoom de la ventana
int zoom; // Zoom de la ventana
int max_zoom; // Máximo tamaño de zoom para la ventana
// Constructor por defecto
OptionsWindow()
: zoom(DEFAULT_WINDOW_ZOOM) {}
: zoom(DEFAULT_WINDOW_ZOOM),
max_zoom(DEFAULT_WINDOW_ZOOM) {}
// Constructor
OptionsWindow(int z)
: zoom(z) {}
OptionsWindow(int z, int mz)
: zoom(z),
max_zoom(mz) {}
};
// Estructura para gestionar el borde de la pantalla
@@ -277,6 +290,89 @@ struct OptionsVideo
palette(p) {}
};
// Estructura para las opciones de musica
struct OptionsMusic
{
bool enabled; // Indica si la música suena o no
int volume; // Volumen al que suena la música (0 a 128 internamente)
// Constructor por defecto
OptionsMusic()
: enabled(DEFAULT_MUSIC_ENABLED),
volume(convertVolume(DEFAULT_MUSIC_VOLUME)) {} // Usa el método estático para la conversión
// Constructor con parámetros
OptionsMusic(bool e, int v)
: enabled(e),
volume(convertVolume(v)) {} // Convierte el volumen usando el método estático
// Método para establecer el volumen
void setVolume(int v)
{
v = std::clamp(v, 0, 100); // Ajusta v al rango [0, 100]
volume = convertVolume(v); // Convierte al rango interno
}
// Método estático para convertir de 0-100 a 0-128
static int convertVolume(int v)
{
return (v * 128) / 100;
}
};
// Estructura para las opciones de sonido
struct OptionsSound
{
bool enabled; // Indica si los sonidos suenan o no
int volume; // Volumen al que suenan los sonidos (0 a 128 internamente)
// Constructor por defecto
OptionsSound()
: enabled(DEFAULT_SOUND_ENABLED),
volume(convertVolume(DEFAULT_SOUND_VOLUME)) {} // Usa el método estático para la conversión
// Constructor con parámetros
OptionsSound(bool e, int v)
: enabled(e),
volume(convertVolume(v)) {} // También lo integra aquí
// Método para establecer el volumen
void setVolume(int v)
{
v = std::clamp(v, 0, 100); // Ajusta v al rango [0, 100]
volume = convertVolume(v); // Convierte al rango interno
}
// Método estático para convertir de 0-100 a 0-128
static int convertVolume(int v)
{
return (v * 128) / 100;
}
};
// Estructura para las opciones de audio
struct OptionsAudio
{
OptionsMusic music; // Opciones para la música
OptionsSound sound; // Opciones para los efectos de sonido
bool enabled; // Indica si el audio está activo o no
int volume; // Volumen al que suenan el audio
// Constructor por defecto
OptionsAudio()
: music(OptionsMusic()),
sound(OptionsSound()),
enabled(DEFAULT_AUDIO_ENABLED),
volume(DEFAULT_AUDIO_VOLUME) {}
// Constructor
OptionsAudio(OptionsMusic m, OptionsSound s, bool e, int v)
: music(m),
sound(s),
enabled(e),
volume(v) {}
};
// Estructura para las opciones de juego
struct OptionsGame
{
@@ -305,6 +401,7 @@ struct Options
OptionsStats stats; // Datos con las estadisticas de juego
OptionsNotification notifications; // Opciones relativas a las notificaciones;
OptionsWindow window; // Opciones relativas a la ventana
OptionsAudio audio; // Opciones relativas al audio
ControlScheme keys; // Teclas usadas para jugar
SectionState section; // Sección actual del programa
@@ -318,11 +415,12 @@ struct Options
stats(OptionsStats()),
notifications(OptionsNotification()),
window(OptionsWindow()),
audio(OptionsAudio()),
keys(DEFAULT_CONTROL_SCHEME),
section(SectionState()) {}
// Constructor
Options(std::string cv, bool c, Cheat ch, OptionsGame g, OptionsVideo v, OptionsStats s, OptionsNotification n, OptionsWindow sw, ControlScheme k, SectionState sec)
Options(std::string cv, bool c, Cheat ch, OptionsGame g, OptionsVideo v, OptionsStats s, OptionsNotification n, OptionsWindow sw, OptionsAudio a, ControlScheme k, SectionState sec)
: version(cv),
console(c),
cheats(ch),
@@ -331,6 +429,7 @@ struct Options
stats(s),
notifications(n),
window(sw),
audio(a),
keys(k),
section(sec) {}
};

View File

@@ -4,7 +4,7 @@
#include <fcntl.h> // Para SEEK_END, SEEK_SET
#include <stdio.h> // Para NULL, fseek, fclose, fopen, fread, ftell
#include <stdlib.h> // Para malloc, free
#include "gif.c" // Para LoadGif, LoadPalette
#include "gif.h" // Para LoadGif, LoadPalette
struct jSurface_s
{

View File

@@ -16,99 +16,32 @@
#include "screen.h"
// Constructor
Player::Player(player_t player)
Player::Player(PlayerData player)
: renderer_(Screen::get()->getRenderer()),
input_(Input::get()),
resource_(Resource::get()),
asset_(Asset::get()),
debug_(Debug::get()),
room_(player.room)
{
// Crea objetos
sprite_ = std::make_shared<AnimatedSprite>(resource_->getTexture(player.png), resource_->getAnimation(player.animation));
// Inicializa algunas variables
initSprite(player.texture_path, player.animations_path);
setColor();
applySpawnValues(player.spawn);
placeSprite();
initSounds();
// Inicializa variables
reLoadPalette();
is_on_border_ = false;
border_ = BORDER_TOP;
auto_movement_ = false;
is_alive_ = true;
is_paused_ = false;
jump_init_pos_ = player.spawn.jump_init_pos;
state_ = player.spawn.state;
previous_state_ = state_;
x_ = player.spawn.x;
y_ = player.spawn.y;
vx_ = player.spawn.vx;
vy_ = player.spawn.vy;
w_ = 8;
h_ = 16;
sprite_->setPosX(player.spawn.x);
sprite_->setPosY(player.spawn.y);
sprite_->setWidth(8);
sprite_->setHeight(16);
sprite_->setFlip(player.spawn.flip);
sprite_->setCurrentAnimation("walk");
sprite_->update();
last_position_ = getRect();
collider_box_ = getRect();
const SDL_Point p = {0, 0};
collider_points_.insert(collider_points_.end(), {p, p, p, p, p, p, p, p});
under_feet_.insert(under_feet_.end(), {p, p});
feet_.insert(feet_.end(), {p, p});
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump1.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump2.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump3.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump4.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump5.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump6.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump7.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump8.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump9.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump10.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump11.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump12.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump13.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump14.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump15.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump16.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump17.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump18.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump19.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump20.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump21.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump22.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump23.wav").c_str()));
jumping_sound_.push_back(JA_LoadSound(asset_->get("jump24.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump11.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump12.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump13.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump14.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump15.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump16.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump17.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump18.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump19.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump20.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump21.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump22.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump23.wav").c_str()));
falling_sound_.push_back(JA_LoadSound(asset_->get("jump24.wav").c_str()));
jumping_counter_ = 0;
falling_counter_ = 0;
collider_points_.resize(collider_points_.size() + 8, {0, 0});
under_feet_.resize(under_feet_.size() + 2, {0, 0});
feet_.resize(feet_.size() + 2, {0, 0});
#ifdef DEBUG
rx = {0, 0, 0, 0};
ry = {0, 0, 0, 0};
debugColor = {0, 255, 0};
debugPoint = {0, 0};
debug_rect_x_ = {0, 0, 0, 0};
debug_rect_y_ = {0, 0, 0, 0};
debug_color_ = {0, 255, 0};
debug_point_ = {0, 0};
#endif
}
@@ -119,59 +52,29 @@ void Player::render()
sprite_->render();
#ifdef DEBUG
if (debug_->getEnabled())
{
// Pinta los underfeet
SDL_SetRenderDrawColor(renderer_, 255, 0, 255, 255);
SDL_RenderDrawPoint(renderer_, under_feet_[0].x, under_feet_[0].y);
SDL_RenderDrawPoint(renderer_, under_feet_[1].x, under_feet_[1].y);
// Pinta rectangulo del jugador
SDL_SetRenderDrawColor(renderer_, debugColor.r, debugColor.g, debugColor.b, 192);
SDL_Rect rect = getRect();
SDL_RenderFillRect(renderer_, &rect);
SDL_SetRenderDrawColor(renderer_, 0, 255, 255, 255);
SDL_RenderDrawRect(renderer_, &rect);
// Pinta el rectangulo de movimiento
SDL_SetRenderDrawColor(renderer_, 255, 0, 0, 255);
if (vx_ != 0.0f)
{
SDL_RenderFillRect(renderer_, &rx);
}
if (vy_ != 0.0f)
{
SDL_RenderFillRect(renderer_, &ry);
}
// Pinta el punto de debug
SDL_SetRenderDrawColor(renderer_, rand() % 256, rand() % 256, rand() % 256, 255);
SDL_RenderDrawPoint(renderer_, debugPoint.x, debugPoint.y);
}
renderDebugInfo();
#endif
}
// Actualiza las variables del objeto
void Player::update()
{
if (is_paused_)
{ // Si está en modo pausa no se actualiza nada
return;
if (!is_paused_)
{
checkInput(); // Comprueba las entradas y modifica variables
move(); // Recalcula la posición del jugador
animate(); // Establece la animación del jugador
checkBorders(); // Comprueba si está situado en alguno de los cuatro bordes de la habitación
checkJumpEnd(); // Comprueba si ha finalizado el salto al alcanzar la altura de inicio
checkKillingTiles(); // Comprueba que el jugador no toque ningun tile de los que matan}
}
checkInput(); // Comprueba las entradas y modifica variables
move(); // Recalcula la posición del jugador
animate(); // Establece la animación del jugador
checkBorders(); // Comprueba si está situado en alguno de los cuatro bordes de la habitación
checkJumpEnd(); // Comprueba si ha finalizado el salto al alcanzar la altura de inicio
checkKillingTiles(); // Comprueba que el jugador no toque ningun tile de los que matan
}
// Comprueba las entradas y modifica variables
void Player::checkInput()
{
// Solo comprueba las entradas de dirección cuando está sobre una superficie
if (state_ != s_standing)
if (state_ != PlayerState::STANDING)
{
return;
}
@@ -192,10 +95,12 @@ void Player::checkInput()
}
else
{ // No se pulsa ninguna dirección
{
// No se pulsa ninguna dirección
vx_ = 0.0f;
if (isOnAutoSurface())
{ // Si deja de moverse sobre una superficie se engancha
{
// Si deja de moverse sobre una superficie se engancha
auto_movement_ = true;
}
}
@@ -223,7 +128,7 @@ void Player::checkInput()
if (isOnFloor() || isOnAutoSurface())
{
setState(s_jumping);
setState(PlayerState::JUMPING);
vy_ = -MAX_VY_;
jump_init_pos_ = y_;
jumping_counter_ = 0;
@@ -231,18 +136,6 @@ void Player::checkInput()
}
}
// Indica si el jugador esta en uno de los cuatro bordes de la pantalla
bool Player::getOnBorder()
{
return is_on_border_;
}
// Indica en cual de los cuatro bordes se encuentra
int Player::getBorder()
{
return border_;
}
// Comprueba si está situado en alguno de los cuatro bordes de la habitación
void Player::checkBorders()
{
@@ -252,7 +145,7 @@ void Player::checkBorders()
is_on_border_ = true;
}
else if (x_ + w_ > PLAY_AREA_RIGHT)
else if (x_ + WIDTH_ > PLAY_AREA_RIGHT)
{
border_ = BORDER_RIGHT;
is_on_border_ = true;
@@ -264,7 +157,7 @@ void Player::checkBorders()
is_on_border_ = true;
}
else if (y_ + h_ > PLAY_AREA_BOTTOM)
else if (y_ + HEIGHT_ > PLAY_AREA_BOTTOM)
{
border_ = BORDER_BOTTOM;
is_on_border_ = true;
@@ -280,7 +173,7 @@ void Player::checkBorders()
void Player::checkState()
{
// Actualiza las variables en función del estado
if (state_ == s_falling)
if (state_ == PlayerState::FALLING)
{
vx_ = 0.0f;
vy_ = MAX_VY_;
@@ -288,9 +181,9 @@ void Player::checkState()
playFallSound();
}
else if (state_ == s_standing)
else if (state_ == PlayerState::STANDING)
{
if (previous_state_ == s_falling && falling_counter_ > MAX_FALLING_HEIGHT_)
if (previous_state_ == PlayerState::FALLING && falling_counter_ > MAX_FALLING_HEIGHT_)
{ // Si cae de muy alto, el jugador muere
is_alive_ = false;
}
@@ -299,7 +192,7 @@ void Player::checkState()
falling_counter_ = 0;
if (!isOnFloor() && !isOnAutoSurface() && !isOnDownSlope())
{
setState(s_falling);
setState(PlayerState::FALLING);
vx_ = 0.0f;
vy_ = MAX_VY_;
falling_counter_++;
@@ -307,7 +200,7 @@ void Player::checkState()
}
}
else if (state_ == s_jumping)
else if (state_ == PlayerState::JUMPING)
{
falling_counter_ = 0;
jumping_counter_++;
@@ -320,13 +213,13 @@ void Player::switchBorders()
{
if (border_ == BORDER_TOP)
{
y_ = PLAY_AREA_BOTTOM - h_ - 0 - BLOCK;
setState(s_standing);
y_ = PLAY_AREA_BOTTOM - HEIGHT_ - 0 - BLOCK;
setState(PlayerState::STANDING);
}
else if (border_ == BORDER_BOTTOM)
{
y_ = PLAY_AREA_TOP + 0;
setState(s_standing);
setState(PlayerState::STANDING);
}
else if (border_ == BORDER_RIGHT)
{
@@ -334,7 +227,7 @@ void Player::switchBorders()
}
if (border_ == BORDER_LEFT)
{
x_ = PLAY_AREA_RIGHT - w_ - 0;
x_ = PLAY_AREA_RIGHT - WIDTH_ - 0;
}
is_on_border_ = false;
@@ -347,7 +240,7 @@ void Player::applyGravity()
// La gravedad solo se aplica cuando el jugador esta saltando
// Nunca mientras cae o esta de pie
if (state_ == s_jumping)
if (state_ == PlayerState::JUMPING)
{
vy_ += GF;
if (vy_ > MAX_VY_)
@@ -357,19 +250,6 @@ void Player::applyGravity()
}
}
// Obtiene el rectangulo que delimita al jugador
SDL_Rect Player::getRect()
{
return {static_cast<int>(x_), static_cast<int>(y_), w_, h_};
}
// Obtiene el rectangulo de colision del jugador
SDL_Rect &Player::getCollider()
{
collider_box_ = getRect();
return collider_box_;
}
// Recalcula la posición del jugador y su animación
void Player::move()
{
@@ -378,7 +258,7 @@ void Player::move()
checkState(); // Comprueba el estado del jugador
#ifdef DEBUG
debugColor = {0, 255, 0};
debug_color_ = {0, 255, 0};
#endif
// Se mueve hacia la izquierda
@@ -388,11 +268,11 @@ void Player::move()
SDL_Rect proj;
proj.x = static_cast<int>(x_ + vx_);
proj.y = static_cast<int>(y_);
proj.h = h_;
proj.h = HEIGHT_;
proj.w = ceil(abs(vx_)); // Para evitar que tenga un ancho de 0 pixels
#ifdef DEBUG
rx = proj;
debug_rect_x_ = proj;
#endif
// Comprueba la colisión con las superficies
@@ -411,18 +291,18 @@ void Player::move()
}
// Si ha tocado alguna rampa mientras camina (sin saltar), asciende
if (state_ != s_jumping)
if (state_ != PlayerState::JUMPING)
{
v_line_t leftSide = {static_cast<int>(x_), static_cast<int>(y_) + h_ - 2, static_cast<int>(y_) + h_ - 1}; // Comprueba solo los dos pixels de abajo
v_line_t leftSide = {static_cast<int>(x_), static_cast<int>(y_) + HEIGHT_ - 2, static_cast<int>(y_) + HEIGHT_ - 1}; // Comprueba solo los dos pixels de abajo
const int ly = room_->checkLeftSlopes(&leftSide);
if (ly > -1)
{
y_ = ly - h_;
y_ = ly - HEIGHT_;
}
}
// Si está bajando la rampa, recoloca al jugador
if (isOnDownSlope() && state_ != s_jumping)
if (isOnDownSlope() && state_ != PlayerState::JUMPING)
{
y_ += 1;
}
@@ -433,13 +313,13 @@ void Player::move()
{
// Crea el rectangulo de proyección en el eje X para ver si colisiona
SDL_Rect proj;
proj.x = static_cast<int>(x_) + w_;
proj.x = static_cast<int>(x_) + WIDTH_;
proj.y = static_cast<int>(y_);
proj.h = h_;
proj.h = HEIGHT_;
proj.w = ceil(vx_); // Para evitar que tenga un ancho de 0 pixels
#ifdef DEBUG
rx = proj;
debug_rect_x_ = proj;
#endif
// Comprueba la colisión
@@ -454,38 +334,38 @@ void Player::move()
else
{
// Si hay colisión lo mueve hasta donde no colisiona
x_ = pos - w_;
x_ = pos - WIDTH_;
}
// Si ha tocado alguna rampa mientras camina (sin saltar), asciende
if (state_ != s_jumping)
if (state_ != PlayerState::JUMPING)
{
v_line_t rightSide = {static_cast<int>(x_) + w_ - 1, static_cast<int>(y_) + h_ - 2, static_cast<int>(y_) + h_ - 1}; // Comprueba solo los dos pixels de abajo
v_line_t rightSide = {static_cast<int>(x_) + WIDTH_ - 1, static_cast<int>(y_) + HEIGHT_ - 2, static_cast<int>(y_) + HEIGHT_ - 1}; // Comprueba solo los dos pixels de abajo
const int ry = room_->checkRightSlopes(&rightSide);
if (ry > -1)
{
y_ = ry - h_;
y_ = ry - HEIGHT_;
}
}
// Si está bajando la rampa, recoloca al jugador
if (isOnDownSlope() && state_ != s_jumping)
if (isOnDownSlope() && state_ != PlayerState::JUMPING)
{
y_ += 1;
}
}
// Si ha salido del suelo, el jugador cae
if (state_ == s_standing && !isOnFloor())
if (state_ == PlayerState::STANDING && !isOnFloor())
{
setState(s_falling);
setState(PlayerState::FALLING);
// Deja de estar enganchado a la superficie automatica
auto_movement_ = false;
}
// Si ha salido de una superficie automatica, detiene el movimiento automatico
if (state_ == s_standing && isOnFloor() && !isOnAutoSurface())
if (state_ == PlayerState::STANDING && isOnFloor() && !isOnAutoSurface())
{
// Deja de estar enganchado a la superficie automatica
auto_movement_ = false;
@@ -499,10 +379,10 @@ void Player::move()
proj.x = static_cast<int>(x_);
proj.y = static_cast<int>(y_ + vy_);
proj.h = ceil(abs(vy_)); // Para evitar que tenga una altura de 0 pixels
proj.w = w_;
proj.w = WIDTH_;
#ifdef DEBUG
ry = proj;
debug_rect_y_ = proj;
#endif
// Comprueba la colisión
@@ -518,7 +398,7 @@ void Player::move()
{
// Si hay colisión lo mueve hasta donde no colisiona y entra en caída
y_ = pos + 1;
setState(s_falling);
setState(PlayerState::FALLING);
}
}
@@ -528,12 +408,12 @@ void Player::move()
// Crea el rectangulo de proyección en el eje Y para ver si colisiona
SDL_Rect proj;
proj.x = static_cast<int>(x_);
proj.y = static_cast<int>(y_) + h_;
proj.y = static_cast<int>(y_) + HEIGHT_;
proj.h = ceil(vy_); // Para evitar que tenga una altura de 0 pixels
proj.w = w_;
proj.w = WIDTH_;
#ifdef DEBUG
ry = proj;
debug_rect_y_ = proj;
#endif
// Comprueba la colisión con las superficies normales y las automáticas
@@ -541,8 +421,8 @@ void Player::move()
if (pos > -1)
{
// Si hay colisión lo mueve hasta donde no colisiona y pasa a estar sobre la superficie
y_ = pos - h_;
setState(s_standing);
y_ = pos - HEIGHT_;
setState(PlayerState::STANDING);
// Deja de estar enganchado a la superficie automatica
auto_movement_ = false;
@@ -550,7 +430,7 @@ void Player::move()
else
{
// Si no hay colisión con los muros, comprueba la colisión con las rampas
if (state_ != s_jumping)
if (state_ != PlayerState::JUMPING)
{ // Las rampas no se miran si se está saltando
v_line_t leftSide = {proj.x, proj.y, proj.y + proj.h - 1};
v_line_t rightSide = {proj.x + proj.w - 1, proj.y, proj.y + proj.h - 1};
@@ -559,11 +439,11 @@ void Player::move()
{
// No está saltando y hay colisión con una rampa
// Calcula la nueva posición
y_ = p - h_;
setState(s_standing);
y_ = p - HEIGHT_;
setState(PlayerState::STANDING);
#ifdef DEBUG
debugColor = {255, 255, 0};
debugPoint = {(int)x_ + (w_ / 2), p};
debug_color_ = {255, 255, 0};
debug_point_ = {(int)x_ + (WIDTH_ / 2), p};
#endif
}
else
@@ -572,7 +452,7 @@ void Player::move()
// Calcula la nueva posición
y_ += vy_;
#ifdef DEBUG
debugColor = {255, 0, 0};
debug_color_ = {255, 0, 0};
#endif
}
}
@@ -585,13 +465,12 @@ void Player::move()
}
}
// Actualiza la posición del sprite
sprite_->setPosX(x_);
sprite_->setPosY(y_);
placeSprite(); // Coloca el sprite en la nueva posición
collider_box_ = getRect(); // Actualiza el rectangulo de colisión
#ifdef DEBUG
debug_->add("RECT_X: " + std::to_string(rx.x) + "," + std::to_string(rx.y) + "," + std::to_string(rx.w) + "," + std::to_string(rx.h));
debug_->add("RECT_Y: " + std::to_string(ry.x) + "," + std::to_string(ry.y) + "," + std::to_string(ry.w) + "," + std::to_string(ry.h));
debug_->add("RECT_X: " + std::to_string(debug_rect_x_.x) + "," + std::to_string(debug_rect_x_.y) + "," + std::to_string(debug_rect_x_.w) + "," + std::to_string(debug_rect_x_.h));
debug_->add("RECT_Y: " + std::to_string(debug_rect_y_.x) + "," + std::to_string(debug_rect_y_.y) + "," + std::to_string(debug_rect_y_.w) + "," + std::to_string(debug_rect_y_.h));
#endif
}
@@ -607,14 +486,14 @@ void Player::animate()
// Comprueba si ha finalizado el salto al alcanzar la altura de inicio
void Player::checkJumpEnd()
{
if (state_ == s_jumping)
if (state_ == PlayerState::JUMPING)
{
if (vy_ > 0)
{
if (y_ >= jump_init_pos_)
{
// Si alcanza la altura de salto inicial, pasa al estado de caída
setState(s_falling);
setState(PlayerState::FALLING);
vy_ = MAX_VY_;
jumping_counter_ = 0;
}
@@ -760,46 +639,21 @@ bool Player::checkKillingTiles()
return check;
}
// Obtiene algunos parametros del jugador
playerSpawn_t Player::getSpawnParams()
// Establece el color del jugador
void Player::setColor()
{
playerSpawn_t params;
params.x = x_;
params.y = y_;
params.vx = vx_;
params.vy = vy_;
params.jump_init_pos = jump_init_pos_;
params.state = state_;
params.flip = sprite_->getFlip();
return params;
}
// Recarga la textura
void Player::reLoadTexture()
{
sprite_->getTexture()->reLoad();
}
// Recarga la paleta
void Player::reLoadPalette()
{
color_ = stringToColor(options.video.palette, "white");
if (options.cheats.infinite_lives == Cheat::CheatState::ENABLED)
{
color_ = stringToColor(options.video.palette, "yellow");
}
if (options.cheats.invincible == Cheat::CheatState::ENABLED)
{
color_ = stringToColor(options.video.palette, "cyan");
}
}
// Establece el valor de la variable
void Player::setRoom(std::shared_ptr<Room> room)
{
room_ = room;
else if (options.cheats.infinite_lives == Cheat::CheatState::ENABLED)
{
color_ = stringToColor(options.video.palette, "yellow");
}
else
{
color_ = stringToColor(options.video.palette, "white");
}
}
// Actualiza los puntos de colisión
@@ -821,15 +675,15 @@ void Player::updateFeet()
{
const SDL_Point p = {static_cast<int>(x_), static_cast<int>(y_)};
under_feet_[0] = {p.x, p.y + h_};
under_feet_[1] = {p.x + 7, p.y + h_};
under_feet_[0] = {p.x, p.y + HEIGHT_};
under_feet_[1] = {p.x + 7, p.y + HEIGHT_};
feet_[0] = {p.x, p.y + h_ - 1};
feet_[1] = {p.x + 7, p.y + h_ - 1};
feet_[0] = {p.x, p.y + HEIGHT_ - 1};
feet_[1] = {p.x + 7, p.y + HEIGHT_ - 1};
}
// Cambia el estado del jugador
void Player::setState(state_e value)
void Player::setState(PlayerState value)
{
previous_state_ = state_;
state_ = value;
@@ -837,20 +691,87 @@ void Player::setState(state_e value)
checkState();
}
// Comprueba si el jugador esta vivo
bool Player::isAlive()
// Inicializa los sonidos de salto y caida
void Player::initSounds()
{
return is_alive_;
jumping_sound_.clear();
falling_sound_.clear();
for (int i = 1; i <= 24; ++i)
{
std::string soundFile = "jump" + std::to_string(i) + ".wav";
jumping_sound_.push_back(Resource::get()->getSound(soundFile));
if (i >= 11)
{
falling_sound_.push_back(Resource::get()->getSound(soundFile));
}
}
}
// Pone el jugador en modo pausa
void Player::pause()
// Coloca el sprite en la posición del jugador
void Player::placeSprite()
{
is_paused_ = true;
sprite_->setPosX(x_);
sprite_->setPosY(y_);
}
// Quita el modo pausa del jugador
void Player::resume()
// Aplica los valores de spawn al jugador
void Player::applySpawnValues(const PlayerSpawn &spawn)
{
is_paused_ = false;
x_ = spawn.x;
y_ = spawn.y;
vx_ = spawn.vx;
vy_ = spawn.vy;
jump_init_pos_ = spawn.jump_init_pos;
state_ = spawn.state;
sprite_->setFlip(spawn.flip);
}
// Inicializa el sprite del jugador
void Player::initSprite(const std::string &texture_path, const std::string &animations_path)
{
auto texture = Resource::get()->getTexture(texture_path);
auto animations = Resource::get()->getAnimations(animations_path);
sprite_ = std::make_shared<AnimatedSprite>(texture, animations);
sprite_->setWidth(WIDTH_);
sprite_->setHeight(HEIGHT_);
sprite_->setCurrentAnimation("walk");
}
#ifdef DEBUG
// Pinta la información de debug del jugador
void Player::renderDebugInfo()
{
if (debug_->getEnabled())
{
// Pinta los underfeet
SDL_SetRenderDrawColor(renderer_, 255, 0, 255, 255);
SDL_RenderDrawPoint(renderer_, under_feet_[0].x, under_feet_[0].y);
SDL_RenderDrawPoint(renderer_, under_feet_[1].x, under_feet_[1].y);
// Pinta rectangulo del jugador
SDL_SetRenderDrawColor(renderer_, debug_color_.r, debug_color_.g, debug_color_.b, 192);
SDL_Rect rect = getRect();
SDL_RenderFillRect(renderer_, &rect);
SDL_SetRenderDrawColor(renderer_, 0, 255, 255, 255);
SDL_RenderDrawRect(renderer_, &rect);
// Pinta el rectangulo de movimiento
SDL_SetRenderDrawColor(renderer_, 255, 0, 0, 255);
if (vx_ != 0.0f)
{
SDL_RenderFillRect(renderer_, &debug_rect_x_);
}
if (vy_ != 0.0f)
{
SDL_RenderFillRect(renderer_, &debug_rect_y_);
}
// Pinta el punto de debug
SDL_SetRenderDrawColor(renderer_, rand() % 256, rand() % 256, rand() % 256, 255);
SDL_RenderDrawPoint(renderer_, debug_point_.x, debug_point_.y);
}
}
#endif

View File

@@ -8,7 +8,7 @@
#include "utils.h" // Para color_t
#include "defines.h" // Para BLOCK
#include "room.h"
class AnimatedSprite;
#include "animated_sprite.h"
class Asset;
class Debug;
class Input;
@@ -16,43 +16,55 @@ class Resource;
class Room;
struct JA_Sound_t;
enum state_e
enum class PlayerState
{
s_standing,
s_jumping,
s_falling
STANDING,
JUMPING,
FALLING,
};
struct playerSpawn_t
struct PlayerSpawn
{
float x;
float y;
float vx;
float vy;
int jump_init_pos;
state_e state;
PlayerState state;
SDL_RendererFlip flip;
// Constructor por defecto
PlayerSpawn() : x(0), y(0), vx(0), vy(0), jump_init_pos(0), state(PlayerState::STANDING), flip(SDL_FLIP_NONE) {}
// Constructor
PlayerSpawn(float x, float y, float vx, float vy, int jump_init_pos, PlayerState state, SDL_RendererFlip flip)
: x(x), y(y), vx(vx), vy(vy), jump_init_pos(jump_init_pos), state(state), flip(flip) {}
};
struct player_t
struct PlayerData
{
playerSpawn_t spawn;
std::string png;
std::string animation;
PlayerSpawn spawn;
std::string texture_path;
std::string animations_path;
std::shared_ptr<Room> room;
// Constructor
PlayerData(PlayerSpawn spawn, std::string texture_path, std::string animations_path, std::shared_ptr<Room> room)
: spawn(spawn), texture_path(texture_path), animations_path(animations_path), room(room) {}
};
class Player
{
public:
// Constantes
static constexpr int WIDTH_ = 8; // Ancho del jugador
static constexpr int HEIGHT_ = 16; // ALto del jugador
static constexpr int MAX_FALLING_HEIGHT_ = BLOCK * 4; // Altura maxima permitida de caída.
static constexpr float MAX_VY_ = 1.2f; // Velocidad máxima que puede alcanzar al desplazarse en vertical
// Objetos y punteros
SDL_Renderer *renderer_; // El renderizador de la ventana
Input *input_; // Objeto para gestionar la entrada
Resource *resource_; // Objeto con los recursos
Asset *asset_; // Objeto con la ruta a todos los ficheros de recursos
Debug *debug_; // Objeto para gestionar la información de debug
std::shared_ptr<Room> room_; // Objeto encargado de gestionar cada habitación del juego
@@ -63,32 +75,30 @@ public:
float y_; // Posición del jugador en el eje Y
float vx_; // Velocidad/desplazamiento del jugador en el eje X
float vy_; // Velocidad/desplazamiento del jugador en el eje Y
int w_; // Ancho del jugador
int h_; // ALto del jugador
Color color_; // Color del jugador
SDL_Rect collider_box_; // Caja de colisión con los enemigos u objetos
std::vector<SDL_Point> collider_points_; // Puntos de colisión con el mapa
std::vector<SDL_Point> under_feet_; // Contiene los puntos que hay bajo cada pie del jugador
std::vector<SDL_Point> feet_; // Contiene los puntos que hay en el pie del jugador
state_e state_; // Estado en el que se encuentra el jugador. Util apara saber si está saltando o cayendo
state_e previous_state_; // Estado previo en el que se encontraba el jugador
bool is_on_border_; // Indica si el jugador esta en uno de los cuatro bordes de la pantalla
int border_; // Indica en cual de los cuatro bordes se encuentra
bool auto_movement_; // Indica si esta siendo arrastrado por una superficie automatica
bool is_paused_; // Indica si el jugador esta en modo pausa
PlayerState state_; // Estado en el que se encuentra el jugador. Util apara saber si está saltando o cayendo
PlayerState previous_state_; // Estado previo en el que se encontraba el jugador
bool is_on_border_ = false; // Indica si el jugador esta en uno de los cuatro bordes de la pantalla
bool is_alive_ = true; // Indica si el jugador esta vivo o no
bool is_paused_ = false; // Indica si el jugador esta en modo pausa
bool auto_movement_ = false; // Indica si esta siendo arrastrado por una superficie automatica
int border_ = BORDER_TOP; // Indica en cual de los cuatro bordes se encuentra
SDL_Rect last_position_; // Contiene la ultima posición del jugador, por si hay que deshacer algun movimiento
int jump_init_pos_; // Valor del eje Y en el que se inicia el salto
std::vector<JA_Sound_t *> jumping_sound_; // Vecor con todos los sonidos del salto
std::vector<JA_Sound_t *> falling_sound_; // Vecor con todos los sonidos de la caída
int jumping_counter_; // Cuenta el tiempo de salto
int falling_counter_; // Cuenta el tiempo de caida
bool is_alive_; // Indica si el jugador esta vivo o no
int jumping_counter_ = 0; // Cuenta el tiempo de salto
int falling_counter_ = 0; // Cuenta el tiempo de caida
#ifdef DEBUG
SDL_Rect rx; // Rectangulo de desplazamiento para el modo debug
SDL_Rect ry; // Rectangulo de desplazamiento para el modo debug
Color debugColor; // Color del recuadro de debug del jugador
SDL_Point debugPoint; // Punto para debug
SDL_Rect debug_rect_x_; // Rectangulo de desplazamiento para el modo debug
SDL_Rect debug_rect_y_; // Rectangulo de desplazamiento para el modo debug
Color debug_color_; // Color del recuadro de debug del jugador
SDL_Point debug_point_; // Punto para debug
#endif
// Comprueba las entradas y modifica variables
@@ -100,9 +110,6 @@ public:
// Comprueba el estado del jugador
void checkState();
// Asigna velocidad negativa en el eje Y al jugador
void jump();
// Aplica gravedad al jugador
void applyGravity();
@@ -140,11 +147,28 @@ public:
void updateFeet();
// Cambia el estado del jugador
void setState(state_e value);
void setState(PlayerState value);
// Inicializa los sonidos de salto y caida
void initSounds();
// Coloca el sprite en la posición del jugador
void placeSprite();
// Aplica los valores de spawn al jugador
void applySpawnValues(const PlayerSpawn &spawn);
// Inicializa el sprite del jugador
void initSprite(const std::string &texture_path, const std::string &animations_path);
#ifdef DEBUG
// Pinta la información de debug del jugador
void renderDebugInfo();
#endif
public:
// Constructor
Player(player_t player);
Player(PlayerData player);
// Destructor
~Player() = default;
@@ -156,38 +180,38 @@ public:
void update();
// Indica si el jugador esta en uno de los cuatro bordes de la pantalla
bool getOnBorder();
bool getOnBorder() { return is_on_border_; }
// Indica en cual de los cuatro bordes se encuentra
int getBorder();
int getBorder() { return border_; }
// Cambia al jugador de un borde al opuesto. Util para el cambio de pantalla
void switchBorders();
// Obtiene el rectangulo que delimita al jugador
SDL_Rect getRect();
SDL_Rect getRect() { return {static_cast<int>(x_), static_cast<int>(y_), WIDTH_, HEIGHT_}; }
// Obtiene el rectangulo de colision del jugador
SDL_Rect &getCollider();
SDL_Rect &getCollider() { return collider_box_; }
// Obtiene algunos parametros del jugador
playerSpawn_t getSpawnParams();
// Obtiene el estado de reaparición del jugador
PlayerSpawn getSpawnParams() { return {x_, y_, vx_, vy_, jump_init_pos_, state_, sprite_->getFlip()}; }
// Recarga la textura
void reLoadTexture();
void reLoadTexture() { sprite_->getTexture()->reLoad(); }
// Recarga la paleta
void reLoadPalette();
// Establece el color del jugador
void setColor();
// Establece el valor de la variable
void setRoom(std::shared_ptr<Room> room);
// Establece la habitación en la que se encuentra el jugador
void setRoom(std::shared_ptr<Room> room) { room_ = room; }
// Comprueba si el jugador esta vivo
bool isAlive();
bool isAlive() { return is_alive_; }
// Pone el jugador en modo pausa
void pause();
void pause() { is_paused_ = true; }
// Quita el modo pausa del jugador
void resume();
void resume() { is_paused_ = false; }
};

View File

@@ -151,7 +151,7 @@ std::shared_ptr<Text> Resource::getText(const std::string &name)
}
// Obtiene la animación a partir de un nombre
AnimationsFileBuffer &Resource::getAnimation(const std::string &name)
Animations &Resource::getAnimations(const std::string &name)
{
auto it = std::find_if(animations_.begin(), animations_.end(), [&name](const auto &a)
{ return a.name == name; });
@@ -181,7 +181,7 @@ std::vector<int> &Resource::getTileMap(const std::string &name)
}
// Obtiene la habitación a partir de un nombre
std::shared_ptr<room_t> Resource::getRoom(const std::string &name)
std::shared_ptr<RoomData> Resource::getRoom(const std::string &name)
{
auto it = std::find_if(rooms_.begin(), rooms_.end(), [&name](const auto &r)
{ return r.name == name; });
@@ -304,7 +304,7 @@ void Resource::loadRooms()
for (const auto &l : list)
{
auto name = getFileName(l);
rooms_.emplace_back(ResourceRoom(name, std::make_shared<room_t>(loadRoomFile(l))));
rooms_.emplace_back(ResourceRoom(name, std::make_shared<RoomData>(loadRoomFile(l))));
printWithDots("Room : ", name, "[ LOADED ]");
updateLoadingProgress();
}
@@ -440,6 +440,9 @@ void Resource::checkEvents()
void Resource::updateLoadingProgress()
{
count_.add(1);
renderProgress();
if (count_.loaded % 5 == 0 || count_.loaded == count_.total)
{
renderProgress();
}
checkEvents();
}

View File

@@ -68,11 +68,11 @@ struct ResourceText
// Estructura para almacenar ficheros animaciones y su nombre
struct ResourceAnimation
{
std::string name; // Nombre del fichero
AnimationsFileBuffer animation; // Objeto con las animaciones
std::string name; // Nombre del fichero
Animations animation; // Objeto con las animaciones
// Constructor
ResourceAnimation(const std::string &name, const AnimationsFileBuffer &animation)
ResourceAnimation(const std::string &name, const Animations &animation)
: name(name), animation(animation) {}
};
@@ -90,11 +90,11 @@ struct ResourceTileMap
// Estructura para almacenar habitaciones y su nombre
struct ResourceRoom
{
std::string name; // Nombre de la habitación
std::shared_ptr<room_t> room; // Habitación
std::string name; // Nombre de la habitación
std::shared_ptr<RoomData> room; // Habitación
// Constructor
ResourceRoom(const std::string &name, std::shared_ptr<room_t> room)
ResourceRoom(const std::string &name, std::shared_ptr<RoomData> room)
: name(name), room(room) {}
};
@@ -232,13 +232,13 @@ public:
std::shared_ptr<Text> getText(const std::string &name);
// Obtiene la animación a partir de un nombre
AnimationsFileBuffer &getAnimation(const std::string &name);
Animations &getAnimations(const std::string &name);
// Obtiene el mapa de tiles a partir de un nombre
std::vector<int> &getTileMap(const std::string &name);
// Obtiene la habitación a partir de un nombre
std::shared_ptr<room_t> getRoom(const std::string &name);
std::shared_ptr<RoomData> getRoom(const std::string &name);
// Obtiene todas las habitaciones
std::vector<ResourceRoom> &getRooms();

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,21 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "enemy.h" // for EnemyData
#include "item.h" // for item_t
#include "utils.h" // for Color
class Asset; // lines 12-12
class Debug; // lines 13-13
#include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "enemy.h" // for EnemyData
#include "item.h" // for item_t
#include "utils.h" // for Color
#include "scoreboard.h"
class Asset; // lines 12-12
class Debug; // lines 13-13
class ItemTracker;
class Screen; // lines 14-14
class Sprite; // lines 15-15
class Texture; // lines 16-16
struct JA_Sound_t; // lines 17-17
class Screen; // lines 14-14
class Sprite; // lines 15-15
class Texture; // lines 16-16
struct JA_Sound_t; // lines 17-17
enum tile_e
{
@@ -30,94 +31,90 @@ enum tile_e
struct aTile_t
{
std::shared_ptr<Sprite> sprite; // Sprite para dibujar el tile
int xcOrig; // Poicion X donde se encuentra el primer tile de la animacion en la tilesheet
int x_orig; // Poicion X donde se encuentra el primer tile de la animacion en la tilesheet
};
struct room_t
struct RoomData
{
std::string number; // Numero de la habitación
std::string name; // Nombre de la habitación
std::string bgColor; // Color de fondo de la habitación
std::string borderColor; // Color del borde de la pantalla
std::string itemColor1; // Color 1 para los items de la habitación
std::string itemColor2; // Color 2 para los items de la habitación
std::string roomUp; // Identificador de la habitación que se encuentra arriba
std::string roomDown; // Identificador de la habitación que se encuentra abajp
std::string roomLeft; // Identificador de la habitación que se encuentra a la izquierda
std::string roomRight; // Identificador de la habitación que se encuentra a la derecha
std::string tileSetFile; // Imagen con los graficos para la habitación
std::string tileMapFile; // Fichero con el mapa de indices de tile
std::vector<int> tileMap; // Indice de los tiles a dibujar en la habitación
int autoSurfaceDirection; // Sentido en el que arrastran las superficies automáticas de la habitación
std::vector<EnemyData> enemies; // Listado con los enemigos de la habitación
std::vector<item_t> items; // Listado con los items que hay en la habitación
std::shared_ptr<Texture> textureA; // Textura con los graficos de la habitación
std::shared_ptr<Texture> textureB; // Textura con los graficos de la habitación
std::string number; // Numero de la habitación
std::string name; // Nombre de la habitación
std::string bg_color; // Color de fondo de la habitación
std::string border_color; // Color del borde de la pantalla
std::string item_color1; // Color 1 para los items de la habitación
std::string item_color2; // Color 2 para los items de la habitación
std::string room_top; // Identificador de la habitación que se encuentra arriba
std::string room_bottom; // Identificador de la habitación que se encuentra abajp
std::string room_left; // Identificador de la habitación que se encuentra a la izquierda
std::string room_right; // Identificador de la habitación que se encuentra a la derecha
std::string tile_set_file; // Imagen con los graficos para la habitación
std::string tile_map_file; // Fichero con el mapa de indices de tile
std::vector<int> tile_map; // Indice de los tiles a dibujar en la habitación
int auto_surface_direction; // Sentido en el que arrastran las superficies automáticas de la habitación
std::vector<EnemyData> enemies; // Listado con los enemigos de la habitación
std::vector<ItemData> items; // Listado con los items que hay en la habitación
};
// Carga las variables desde un fichero de mapa
room_t loadRoomFile(std::string file, bool verbose = false);
RoomData loadRoomFile(const std::string &file_path, bool verbose = false);
// Carga las variables y texturas desde un fichero de mapa de tiles
std::vector<int> loadRoomTileFile(std::string file_path, bool verbose = false);
std::vector<int> loadRoomTileFile(const std::string &file_path, bool verbose = false);
// Asigna variables a partir de dos cadenas
bool setVars(room_t *room, std::string var, std::string value);
// Asigna variables a una estructura RoomData
bool setRoom(RoomData *room, const std::string &key, const std::string &value);
// Asigna variables a una estructura enemy_t
bool setEnemy(EnemyData *enemy, std::string var, std::string value);
// Asigna variables a una estructura EnemyData
bool setEnemy(EnemyData *enemy, const std::string &key, const std::string &value);
// Asigna variables a una estructura item_t
bool setItem(item_t *item, std::string var, std::string value);
// Asigna variables a una estructura ItemData
bool setItem(ItemData *item, const std::string &key, const std::string &value);
class Room
{
private:
// Constantes
static constexpr int TILE_SIZE_ = 8; // Ancho del tile en pixels
static constexpr int MAP_WIDTH_ = 32; // Ancho del mapa en tiles
static constexpr int MAP_HEIGHT_ = 16; // Alto del mapa en tiles
// Objetos y punteros
Screen *screen; // Objeto encargado de dibujar en pantalla
SDL_Renderer *renderer; // El renderizador de la ventana
Asset *asset; // Objeto con la ruta a todos los ficheros de recursos
Debug *debug; // Objeto para gestionar la información de debug
std::vector<std::shared_ptr<Enemy>> enemies; // Listado con los enemigos de la habitación
std::vector<std::shared_ptr<Item>> items; // Listado con los items que hay en la habitación
std::shared_ptr<Texture> texture; // Textura con los graficos de la habitación
std::shared_ptr<Texture> textureA; // Textura con los graficos de la habitación
std::shared_ptr<Texture> textureB; // Textura con los graficos de la habitación
std::shared_ptr<ItemTracker> itemTracker; // Lleva el control de los objetos recogidos
SDL_Texture *mapTexture; // Textura para dibujar el mapa de la habitación
int *itemsPicked; // Puntero a la cantidad de items recogidos que lleva el juego
Screen *screen_; // Objeto encargado de dibujar en pantalla
SDL_Renderer *renderer_; // El renderizador de la ventana
Asset *asset_; // Objeto con la ruta a todos los ficheros de recursos
Debug *debug_; // Objeto para gestionar la información de debug
std::vector<std::shared_ptr<Enemy>> enemies_; // Listado con los enemigos de la habitación
std::vector<std::shared_ptr<Item>> items_; // Listado con los items que hay en la habitación
std::shared_ptr<Texture> texture_; // Textura con los graficos de la habitación
SDL_Texture *map_texture_; // Textura para dibujar el mapa de la habitación
std::shared_ptr<ScoreboardData> data_; // Puntero a los datos del marcador
// Variables
std::string number; // Numero de la habitación
std::string name; // Nombre de la habitación
std::string bgColor; // Color de fondo de la habitación
std::string borderColor; // Color del borde de la pantalla
std::string itemColor1; // Color 1 para los items de la habitación
std::string itemColor2; // Color 2 para los items de la habitación
std::string roomUp; // Identificador de la habitación que se encuentra arriba
std::string roomDown; // Identificador de la habitación que se encuentra abajp
std::string roomLeft; // Identificador de la habitación que se encuentra a la izquierda
std::string roomRight; // Identificador de la habitación que se encuentra a la derecha
std::string tileSetFile; // Imagen con los graficos para la habitación
std::string tileMapFile; // Fichero con el mapa de indices de tile
std::vector<int> tileMap; // Indice de los tiles a dibujar en la habitación
int autoSurfaceDirection; // Sentido en el que arrastran las superficies automáticas de la habitación
JA_Sound_t *itemSound; // Sonido producido al coger un objeto
std::vector<h_line_t> bottomSurfaces; // Lista con las superficies inferiores de la habitación
std::vector<h_line_t> topSurfaces; // Lista con las superficies superiores de la habitación
std::vector<v_line_t> leftSurfaces; // Lista con las superficies laterales de la parte izquierda de la habitación
std::vector<v_line_t> rightSurfaces; // Lista con las superficies laterales de la parte derecha de la habitación
std::vector<d_line_t> leftSlopes; // Lista con todas las rampas que suben hacia la izquierda
std::vector<d_line_t> rightSlopes; // Lista con todas las rampas que suben hacia la derecha
int counter; // Contador para lo que haga falta
bool paused; // Indica si el mapa esta en modo pausa
std::vector<aTile_t> aTile; // Vector con los indices de tiles animados
std::vector<h_line_t> autoSurfaces; // Lista con las superficies automaticas de la habitación
int tileSize; // Ancho del tile en pixels
int mapWidth; // Ancho del mapa en tiles
int mapHeight; // Alto del mapa en tiles
int tileSetWidth; // Ancho del tileset en tiles
bool jailEnabled; // Indica si hay acceso a la Jail
std::string number_; // Numero de la habitación
std::string name_; // Nombre de la habitación
std::string bg_color_; // Color de fondo de la habitación
std::string border_color_; // Color del borde de la pantalla
std::string item_color1_; // Color 1 para los items de la habitación
std::string item_color2_; // Color 2 para los items de la habitación
std::string room_top_; // Identificador de la habitación que se encuentra arriba
std::string room_bottom_; // Identificador de la habitación que se encuentra abajp
std::string room_left_; // Identificador de la habitación que se encuentra a la izquierda
std::string room_right_; // Identificador de la habitación que se encuentra a la derecha
std::string tile_set_file_; // Imagen con los graficos para la habitación
std::string tile_map_file_; // Fichero con el mapa de indices de tile
std::vector<int> tile_map_; // Indice de los tiles a dibujar en la habitación
int auto_surface_direction_; // Sentido en el que arrastran las superficies automáticas de la habitación
JA_Sound_t *item_sound_; // Sonido producido al coger un objeto
std::vector<h_line_t> bottom_surfaces_; // Lista con las superficies inferiores de la habitación
std::vector<h_line_t> top_surfaces_; // Lista con las superficies superiores de la habitación
std::vector<v_line_t> left_surfaces_; // Lista con las superficies laterales de la parte izquierda de la habitación
std::vector<v_line_t> right_surfaces_; // Lista con las superficies laterales de la parte derecha de la habitación
std::vector<d_line_t> left_slopes_; // Lista con todas las rampas que suben hacia la izquierda
std::vector<d_line_t> right_slopes_; // Lista con todas las rampas que suben hacia la derecha
int counter_; // Contador para lo que haga falta
bool paused_; // Indica si el mapa esta en modo pausa
std::vector<aTile_t> animated_tiles_; // Vector con los indices de tiles animados
std::vector<h_line_t> auto_surfaces_; // Lista con las superficies automaticas de la habitación
int tile_set_width_; // Ancho del tileset en tiles
// Pinta el mapa de la habitación en la textura
void fillMapTexture();
@@ -160,7 +157,7 @@ private:
public:
// Constructor
Room(std::shared_ptr<room_t> room, std::shared_ptr<ItemTracker> itemTracker, int *itemsPicked, bool jailEnabled);
Room(std::shared_ptr<RoomData> room, std::shared_ptr<ScoreboardData> data);
// Destructor
~Room();

View File

@@ -1,115 +1,97 @@
#include "scoreboard.h"
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include "animated_sprite.h" // for AnimatedSprite
#include "asset.h" // for Asset
#include "defines.h" // for BLOCK, GAMECANVAS_HEIGHT, PLAY_AREA_HEIGHT
#include "options.h" // for Options, options, OptionsVideo, Cheat
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "text.h" // for Text
#include "texture.h" // for Texture
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include "animated_sprite.h" // for AnimatedSprite
#include "asset.h" // for Asset
#include "defines.h" // for BLOCK, GAMECANVAS_HEIGHT, PLAY_AREA_HEIGHT
#include "options.h" // for Options, options, OptionsVideo, Cheat
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "text.h" // for Text
#include "texture.h" // for Texture
#include <iostream>
// Constructor
Scoreboard::Scoreboard(board_t *board)
: renderer(Screen::get()->getRenderer()),
resource(Resource::get()),
asset(Asset::get()),
board(board)
Scoreboard::Scoreboard(std::shared_ptr<ScoreboardData> data)
: renderer_(Screen::get()->getRenderer()),
resource_(Resource::get()),
asset_(Asset::get()),
data_(data)
{
const int TEXTURE_WIDTH_ = options.game.width;
constexpr int TEXTURE_HEIGHT_ = 6 * BLOCK;
// Reserva memoria para los objetos
itemTexture = resource->getTexture("items.png");
const std::string playerPNG = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.png" : "player.png";
const std::string playerANI = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.ani" : "player.ani";
sprite = std::make_shared<AnimatedSprite>(resource->getTexture(playerPNG), resource->getAnimation(playerANI));
sprite->setCurrentAnimation("walk_menu");
text = resource->getText("smb2");
item_texture_ = resource_->getTexture("items.png");
auto player_texture = resource_->getTexture(options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.png" : "player.png");
auto player_animations = resource_->getAnimations(options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.ani" : "player.ani");
player_sprite_ = std::make_shared<AnimatedSprite>(player_texture, player_animations);
player_sprite_->setCurrentAnimation("walk_menu");
text_ = resource_->getText("smb2");
texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, TEXTURE_WIDTH_, TEXTURE_HEIGHT_);
if (texture_ == nullptr)
{
if (options.console)
{
std::cout << "Scorebard::texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
texture_dest_ = {0, options.game.height - TEXTURE_HEIGHT_, TEXTURE_WIDTH_, TEXTURE_HEIGHT_};
// Inicializa las variables
counter = 0;
colorChangeSpeed = 4;
paused = false;
timePaused = 0;
totalTimePaused = 0;
itemsColor = stringToColor(options.video.palette, "white");
counter_ = 0;
change_color_speed_ = 4;
is_paused_ = false;
paused_time_ = 0;
paused_time_elapsed_ = 0;
items_color_ = stringToColor(options.video.palette, "white");
// Inicializa el vector de colores
const std::vector<std::string> vColors = {"blue", "magenta", "green", "cyan", "yellow", "white", "bright_blue", "bright_magenta", "bright_green", "bright_cyan", "bright_yellow", "bright_white"};
for (auto v : vColors)
{
color.push_back(stringToColor(options.video.palette, v));
color_.push_back(stringToColor(options.video.palette, v));
}
}
// Destructor
Scoreboard::~Scoreboard()
{
SDL_DestroyTexture(texture_);
}
// Pinta el objeto en pantalla
void Scoreboard::render()
{
// Anclas
const int line1 = 19 * BLOCK;
const int line2 = line1 + (2 * BLOCK);
// Dibuja el fondo del marcador
const SDL_Rect rect = {0, 18 * BLOCK, PLAY_AREA_WIDTH, GAMECANVAS_HEIGHT - PLAY_AREA_HEIGHT};
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderFillRect(renderer, &rect);
// Dibuja las vidas
const int desp = (counter / 40) % 8;
const int frame = desp % 4;
sprite->setCurrentAnimationFrame(frame);
sprite->setPosY(line2);
for (int i = 0; i < board->lives; ++i)
{
sprite->setPosX(8 + (16 * i) + desp);
const int index = i % color.size();
sprite->getTexture()->setColor(color[index].r, color[index].g, color[index].b);
sprite->render();
}
// Muestra si suena la música
if (board->music)
{
const Color c = board->color;
SDL_Rect clip = {0, 8, 8, 8};
itemTexture->setColor(c.r, c.g, c.b);
itemTexture->render(20 * BLOCK, line2, &clip);
}
// Escribe los textos
const std::string timeTxt = std::to_string((clock.minutes % 100) / 10) + std::to_string(clock.minutes % 10) + clock.separator + std::to_string((clock.seconds % 60) / 10) + std::to_string(clock.seconds % 10);
const std::string itemsTxt = std::to_string(board->items / 100) + std::to_string((board->items % 100) / 10) + std::to_string(board->items % 10);
this->text->writeColored(BLOCK, line1, "Items collected ", board->color);
this->text->writeColored(17 * BLOCK, line1, itemsTxt, itemsColor);
this->text->writeColored(20 * BLOCK, line1, " Time ", board->color);
this->text->writeColored(26 * BLOCK, line1, timeTxt, stringToColor(options.video.palette, "white"));
const std::string roomsTxt = std::to_string(board->rooms / 100) + std::to_string((board->rooms % 100) / 10) + std::to_string(board->rooms % 10);
this->text->writeColored(22 * BLOCK, line2, "Rooms", stringToColor(options.video.palette, "white"));
this->text->writeColored(28 * BLOCK, line2, roomsTxt, stringToColor(options.video.palette, "white"));
SDL_RenderCopy(renderer_, texture_, nullptr, &texture_dest_);
}
// Actualiza las variables del objeto
void Scoreboard::update()
{
counter++;
sprite->update();
counter_++;
player_sprite_->update();
// Actualiza el color de la cantidad de items recogidos
updateItemsColor();
if (!paused)
// Dibuja la textura
fillTexture();
if (!is_paused_)
{
// Si está en pausa no se actualiza el reloj
clock = getTime();
clock_ = getTime();
}
}
// Obtiene el tiempo transcurrido de partida
Scoreboard::clock_t Scoreboard::getTime()
Scoreboard::ClockData Scoreboard::getTime()
{
const Uint32 timeElapsed = SDL_GetTicks() - board->iniClock - totalTimePaused;
const Uint32 timeElapsed = SDL_GetTicks() - data_->ini_clock - paused_time_elapsed_;
clock_t time;
ClockData time;
time.hours = timeElapsed / 3600000;
time.minutes = timeElapsed / 60000;
time.seconds = timeElapsed / 1000;
@@ -121,10 +103,10 @@ Scoreboard::clock_t Scoreboard::getTime()
// Recarga la textura
void Scoreboard::reLoadTexture()
{
sprite->getTexture()->reLoad();
player_sprite_->getTexture()->reLoad();
// playerTexture->reLoad();
itemTexture->reLoad();
text->reLoadTexture();
item_texture_->reLoad();
text_->reLoadTexture();
}
// Recarga la paleta
@@ -132,42 +114,42 @@ void Scoreboard::reLoadPalette()
{
// Reinicia el vector de colores
const std::vector<std::string> vColors = {"blue", "magenta", "green", "cyan", "yellow", "white", "bright_blue", "bright_magenta", "bright_green", "bright_cyan", "bright_yellow", "bright_white"};
color.clear();
color_.clear();
for (auto v : vColors)
{
color.push_back(stringToColor(options.video.palette, v));
color_.push_back(stringToColor(options.video.palette, v));
}
}
// Pone el marcador en modo pausa
void Scoreboard::pause()
{
paused = true;
timePaused = SDL_GetTicks();
is_paused_ = true;
paused_time_ = SDL_GetTicks();
}
// Quita el modo pausa del marcador
void Scoreboard::resume()
{
paused = false;
totalTimePaused += SDL_GetTicks() - timePaused;
is_paused_ = false;
paused_time_elapsed_ += SDL_GetTicks() - paused_time_;
}
// Actualiza el color de la cantidad de items recogidos
void Scoreboard::updateItemsColor()
{
if (!board->jail_is_open)
if (!data_->jail_is_open)
{
return;
}
if (counter % 20 < 10)
if (counter_ % 20 < 10)
{
itemsColor = stringToColor(options.video.palette, "white");
items_color_ = stringToColor(options.video.palette, "white");
}
else
{
itemsColor = stringToColor(options.video.palette, "magenta");
items_color_ = stringToColor(options.video.palette, "magenta");
}
}
@@ -176,3 +158,56 @@ int Scoreboard::getMinutes()
{
return getTime().minutes;
}
// Dibuja los elementos del marcador en la textura
void Scoreboard::fillTexture()
{
// Empieza a dibujar en la textura
auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, texture_);
// Limpia la textura
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255);
SDL_RenderFillRect(renderer_, nullptr);
// Anclas
constexpr int LINE1 = BLOCK;
constexpr int LINE2 = 3 * BLOCK;
// Dibuja las vidas
const int desp = (counter_ / 40) % 8;
const int frame = desp % 4;
player_sprite_->setCurrentAnimationFrame(frame);
player_sprite_->setPosY(LINE2);
for (int i = 0; i < data_->lives; ++i)
{
player_sprite_->setPosX(8 + (16 * i) + desp);
const int index = i % color_.size();
player_sprite_->getTexture()->setColor(color_[index].r, color_[index].g, color_[index].b);
player_sprite_->render();
}
// Muestra si suena la música
if (data_->music)
{
const Color c = data_->color;
SDL_Rect clip = {0, 8, 8, 8};
item_texture_->setColor(c.r, c.g, c.b);
item_texture_->render(20 * BLOCK, LINE2, &clip);
}
// Escribe los textos
const std::string timeTxt = std::to_string((clock_.minutes % 100) / 10) + std::to_string(clock_.minutes % 10) + clock_.separator + std::to_string((clock_.seconds % 60) / 10) + std::to_string(clock_.seconds % 10);
const std::string itemsTxt = std::to_string(data_->items / 100) + std::to_string((data_->items % 100) / 10) + std::to_string(data_->items % 10);
text_->writeColored(BLOCK, LINE1, "Items collected ", data_->color);
text_->writeColored(17 * BLOCK, LINE1, itemsTxt, items_color_);
text_->writeColored(20 * BLOCK, LINE1, " Time ", data_->color);
text_->writeColored(26 * BLOCK, LINE1, timeTxt, stringToColor(options.video.palette, "white"));
const std::string roomsTxt = std::to_string(data_->rooms / 100) + std::to_string((data_->rooms % 100) / 10) + std::to_string(data_->rooms % 10);
text_->writeColored(22 * BLOCK, LINE2, "Rooms", stringToColor(options.video.palette, "white"));
text_->writeColored(28 * BLOCK, LINE2, roomsTxt, stringToColor(options.video.palette, "white"));
// Deja el renderizador como estaba
SDL_SetRenderTarget(renderer_, temp);
}

View File

@@ -12,21 +12,25 @@ class Resource;
class Text;
class Texture;
struct board_t
struct ScoreboardData
{
int items; // Lleva la cuenta de los objetos recogidos
int lives; // Lleva la cuenta de ls vidas restantes del jugador
int rooms; // Lleva la cuenta de las habitaciones visitadas
bool music; // Indica si ha de sonar la musica durante el juego
Color color; // Color para escribir el texto del marcador
Uint32 iniClock; // Tiempo inicial para calcular el tiempo transcurrido
Uint32 ini_clock; // Tiempo inicial para calcular el tiempo transcurrido
bool jail_is_open; // Indica si se puede entrar a la Jail
// Constructor
ScoreboardData()
: items(0), lives(3), rooms(0), music(true), color({0, 0, 0}), ini_clock(0), jail_is_open(false) {}
};
class Scoreboard
{
private:
struct clock_t
struct ClockData
{
int hours;
int minutes;
@@ -35,36 +39,41 @@ private:
};
// Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana
Resource *resource; // Objeto con los recursos
Asset *asset; // Objeto con la ruta a todos los ficheros de recursos
std::shared_ptr<Text> text; // Objeto para escribir texto
std::shared_ptr<AnimatedSprite> sprite; // Sprite para mostrar las vidas en el marcador
std::shared_ptr<Texture> itemTexture; // Textura con los graficos para las vidas
std::shared_ptr<board_t> board; // Contiene las variables a mostrar en el marcador
SDL_Renderer *renderer_; // El renderizador de la ventana
Resource *resource_; // Objeto con los recursos
Asset *asset_; // Objeto con la ruta a todos los ficheros de recursos
std::shared_ptr<Text> text_; // Objeto para escribir texto
std::shared_ptr<AnimatedSprite> player_sprite_; // Sprite para mostrar las vidas en el marcador
std::shared_ptr<Texture> item_texture_; // Textura con los graficos para las vidas
std::shared_ptr<ScoreboardData> data_; // Contiene las variables a mostrar en el marcador
SDL_Texture *texture_; // Textura donde dibujar el marcador;
// Variables
std::vector<Color> color; // Vector con los colores del objeto
int counter; // Contador interno
int colorChangeSpeed; // Cuanto mas alto, mas tarda en cambiar de color
bool paused; // Indica si el marcador esta en modo pausa
Uint32 timePaused; // Milisegundos que ha estado el marcador en pausa
Uint32 totalTimePaused; // Tiempo acumulado en pausa
clock_t clock; // Contiene las horas, minutos y segundos transcurridos desde el inicio de la partida
Color itemsColor; // Color de la cantidad de items recogidos
std::vector<Color> color_; // Vector con los colores del objeto
int counter_; // Contador interno
int change_color_speed_; // Cuanto mas alto, mas tarda en cambiar de color
bool is_paused_; // Indica si el marcador esta en modo pausa
Uint32 paused_time_; // Milisegundos que ha estado el marcador en pausa
Uint32 paused_time_elapsed_; // Tiempo acumulado en pausa
ClockData clock_; // Contiene las horas, minutos y segundos transcurridos desde el inicio de la partida
Color items_color_; // Color de la cantidad de items recogidos
SDL_Rect texture_dest_; // Rectangulo donde dibujar la textura del marcador
// Obtiene el tiempo transcurrido de partida
clock_t getTime();
ClockData getTime();
// Actualiza el color de la cantidad de items recogidos
void updateItemsColor();
// Dibuja los elementos del marcador en la textura
void fillTexture();
public:
// Constructor
Scoreboard(board_t *board);
Scoreboard(std::shared_ptr<ScoreboardData> data);
// Destructor
~Scoreboard() = default;
~Scoreboard();
// Pinta el objeto en pantalla
void render();

View File

@@ -13,6 +13,7 @@
#include "notifier.h" // Para Notify
#include "options.h"
#include "mouse.h"
//#include "surface.h"
// [SINGLETON]
Screen *Screen::screen_ = nullptr;
@@ -40,50 +41,66 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer)
: window_(window),
renderer_(renderer)
{
game_canvas_width_ = options.game.width;
game_canvas_height_ = options.game.height;
notification_logical_width_ = game_canvas_width_;
notification_logical_height_ = game_canvas_height_;
iniFade();
iniSpectrumFade();
// Ajusta los tamaños
adjustGameCanvasRect();
adjustWindowSize();
// Define el color del borde para el modo de pantalla completa
border_color_ = {0x00, 0x00, 0x00};
// Crea la textura donde se dibujan los graficos del juego
game_canvas_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, game_canvas_width_, game_canvas_height_);
if (game_canvas_ == nullptr)
// Establece el modo de escalado
SDL_RenderSetIntegerScale(renderer_, options.video.integer_scale ? SDL_TRUE : SDL_FALSE);
// Crea la textura donde se vuelcan las surfaces
surface_texture_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, options.game.width, options.game.height);
if (surface_texture_ == nullptr)
{
if (options.console)
{
std::cout << "gameCanvas could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
std::cout << "surface_texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
//SDL_SetTextureBlendMode(surface_texture_, SDL_BLENDMODE_BLEND);
// Crea la textura donde se dibujan los graficos del juego
game_texture_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, options.game.width, options.game.height);
if (game_texture_ == nullptr)
{
if (options.console)
{
std::cout << "game_texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
// Crea la textura donde se dibuja el borde que rodea el area de juego
border_canvas_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, game_canvas_width_ + options.video.border.width * 2, game_canvas_height_ + options.video.border.height * 2);
if (border_canvas_ == nullptr)
border_texture_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, options.game.width + options.video.border.width * 2, options.game.height + options.video.border.height * 2);
if (border_texture_ == nullptr)
{
if (options.console)
{
std::cout << "borderCanvas could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
std::cout << "border_texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
setBorderColor(border_color_);
// Crea la surface donde se pinta el juego
//surface_ = std::make_shared<Surface>(nullptr, options.game.width, options.game.height);
//surface_->loadPalette(Asset::get()->get("test.gif"));
// Establece el modo de video
setVideoMode(options.video.mode);
// Muestra la ventana
SDL_SetWindowPosition(window_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
show();
}
// Destructor
Screen::~Screen()
{
SDL_DestroyTexture(game_canvas_);
SDL_DestroyTexture(border_canvas_);
SDL_DestroyTexture(surface_texture_);
SDL_DestroyTexture(game_texture_);
SDL_DestroyTexture(border_texture_);
}
// Limpia la pantalla
@@ -96,13 +113,14 @@ void Screen::clean(Color color)
// Prepara para empezar a dibujar en la textura de juego
void Screen::start()
{
SDL_SetRenderTarget(renderer_, game_canvas_);
//surface_->clear(surface_->getSurface(), surface_->getTransparentColor());
SDL_SetRenderTarget(renderer_, game_texture_);
}
// Prepara para empezar a dibujar en la textura del borde
void Screen::startDrawOnBorder()
{
SDL_SetRenderTarget(renderer_, border_canvas_);
SDL_SetRenderTarget(renderer_, border_texture_);
}
// Vuelca el contenido del renderizador en pantalla
@@ -111,6 +129,10 @@ void Screen::render()
// Renderiza sobre gameCanvas los overlays
renderNotifications();
//fillTextureWithColor(renderer_, surface_texture_, 0xFF, 0x00, 0xFF, 0xFF);
//surface_->copyToTexture(renderer_, surface_texture_);
//SDL_RenderCopy(renderer_, surface_texture_, nullptr, nullptr);
// Si está el borde activo, vuelca gameCanvas sobre borderCanvas
if (options.video.border.enabled)
{
@@ -121,7 +143,6 @@ void Screen::render()
renderPresent();
}
// Vuelca el contenido del renderizador en pantalla
void Screen::renderWithoutNotifier()
{
@@ -139,7 +160,6 @@ void Screen::renderWithoutNotifier()
void Screen::setVideoMode(int videoMode)
{
// Aplica el modo de video
SDL_SetWindowFullscreen(window_, videoMode);
// Modo ventana
if (videoMode == 0)
@@ -147,79 +167,23 @@ void Screen::setVideoMode(int videoMode)
// Muestra el puntero
SDL_ShowCursor(SDL_ENABLE);
// Modifica el tamaño de la ventana en función del borde
if (options.video.border.enabled)
{
window_width_ = game_canvas_width_ + options.video.border.width * 2;
window_height_ = game_canvas_height_ + options.video.border.height * 2;
dest_ = {options.video.border.width, options.video.border.height, game_canvas_width_, game_canvas_height_};
}
else
{
window_width_ = game_canvas_width_;
window_height_ = game_canvas_height_;
dest_ = {0, 0, game_canvas_width_, game_canvas_height_};
}
// Modifica el tamaño de la ventana
SDL_SetWindowSize(window_, window_width_ * options.window.zoom, window_height_ * options.window.zoom);
SDL_SetWindowPosition(window_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_SetWindowFullscreen(window_, videoMode);
adjustWindowSize();
adjustGameCanvasRect();
adjustRenderLogicalSize();
}
// Si está activo el modo de pantalla completa añade el borde
else if (videoMode == SDL_WINDOW_FULLSCREEN_DESKTOP)
// Modo pantalla completa
else
{
// Oculta el puntero
SDL_ShowCursor(SDL_DISABLE);
adjustWindowSize();
// Obten el alto y el ancho de la ventana
SDL_GetWindowSize(window_, &window_width_, &window_height_);
// Aplica el escalado al rectangulo donde se pinta la textura del juego
if (options.video.integer_scale)
{
// Calcula el tamaño de la escala máxima
int scale = 0;
while (((game_canvas_width_ * (scale + 1)) <= window_width_) && ((game_canvas_height_ * (scale + 1)) <= window_height_))
{
scale++;
}
dest_.w = game_canvas_width_ * scale;
dest_.h = game_canvas_height_ * scale;
dest_.x = (window_width_ - dest_.w) / 2;
dest_.y = (window_height_ - dest_.h) / 2;
}
else if (options.video.keep_aspect)
{
float ratio = (float)game_canvas_width_ / (float)game_canvas_height_;
if ((window_width_ - game_canvas_width_) >= (window_height_ - game_canvas_height_))
{
dest_.h = window_height_;
dest_.w = (int)((window_height_ * ratio) + 0.5f);
dest_.x = (window_width_ - dest_.w) / 2;
dest_.y = (window_height_ - dest_.h) / 2;
}
else
{
dest_.w = window_width_;
dest_.h = (int)((window_width_ / ratio) + 0.5f);
dest_.x = (window_width_ - dest_.w) / 2;
dest_.y = (window_height_ - dest_.h) / 2;
}
}
else
{
dest_.w = window_width_;
dest_.h = window_height_;
dest_.x = dest_.y = 0;
}
adjustGameCanvasRect();
SDL_SetWindowFullscreen(window_, videoMode);
}
// Modifica el tamaño del renderizador
SDL_RenderSetLogicalSize(renderer_, window_width_, window_height_);
// Actualiza las opciones
options.video.mode = videoMode;
@@ -232,11 +196,11 @@ void Screen::setVideoMode(int videoMode)
if (options.video.border.enabled)
{
shader::init(window_, border_canvas_, source.c_str());
shader::init(window_, border_texture_, source.c_str());
}
else
{
shader::init(window_, game_canvas_, source.c_str());
shader::init(window_, game_texture_, source.c_str());
}
}
}
@@ -248,27 +212,42 @@ void Screen::toggleVideoMode()
setVideoMode(options.video.mode);
}
// Cambia el tamaño de la ventana
void Screen::setWindowZoom(int size)
{
options.window.zoom = size;
setVideoMode(0);
}
// Reduce el tamaño de la ventana
void Screen::decWindowZoom()
bool Screen::decWindowZoom()
{
--options.window.zoom;
options.window.zoom = std::max(options.window.zoom, 1);
setVideoMode(0);
if (options.video.mode == 0)
{
int previous_zoom = options.window.zoom;
--options.window.zoom;
options.window.zoom = std::max(options.window.zoom, 1);
if (options.window.zoom != previous_zoom)
{
adjustWindowSize();
return true;
}
}
return false;
}
// Aumenta el tamaño de la ventana
void Screen::incWindowZoom()
bool Screen::incWindowZoom()
{
++options.window.zoom;
options.window.zoom = std::min(options.window.zoom, 4);
setVideoMode(0);
if (options.video.mode == 0)
{
int previous_zoom = options.window.zoom;
++options.window.zoom;
options.window.zoom = std::min(options.window.zoom, options.window.max_zoom);
if (options.window.zoom != previous_zoom)
{
adjustWindowSize();
return true;
}
}
return false;
}
// Cambia el color del borde
@@ -276,7 +255,7 @@ void Screen::setBorderColor(Color color)
{
border_color_ = color;
auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, border_canvas_);
SDL_SetRenderTarget(renderer_, border_texture_);
SDL_SetRenderDrawColor(renderer_, border_color_.r, border_color_.g, border_color_.b, 0xFF);
SDL_RenderClear(renderer_);
SDL_SetRenderTarget(renderer_, temp);
@@ -307,139 +286,9 @@ void Screen::setBorderEnabled(bool value) { options.video.border.enabled = value
void Screen::toggleBorder()
{
options.video.border.enabled = !options.video.border.enabled;
setVideoMode(0);
}
// Activa el fade
void Screen::setFade() { fade_ = true; }
// Comprueba si ha terminado el fade
bool Screen::fadeEnded()
{
if (fade_ || fade_counter_ > 0)
{
return false;
}
return true;
}
// Activa el spectrum fade
void Screen::setspectrumFade()
{
spectrum_fade_ = true;
}
// Comprueba si ha terminado el spectrum fade
bool Screen::spectrumFadeEnded()
{
if (spectrum_fade_ || spectrum_fade_counter_ > 0)
{
return false;
}
return true;
}
// Inicializa las variables para el fade
void Screen::iniFade()
{
fade_ = false;
fade_counter_ = 0;
fade_lenght_ = 200;
}
// Actualiza el fade
void Screen::updateFade()
{
if (!fade_)
{
return;
}
fade_counter_++;
if (fade_counter_ > fade_lenght_)
{
iniFade();
}
}
// Dibuja el fade
void Screen::renderFade()
{
if (!fade_)
{
return;
}
const SDL_Rect rect = {0, 0, game_canvas_width_, game_canvas_height_};
Color color = {0, 0, 0};
const float step = (float)fade_counter_ / (float)fade_lenght_;
const int alpha = 0 + (255 - 0) * step;
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, alpha);
SDL_RenderFillRect(renderer_, &rect);
}
// Inicializa las variables para el fade spectrum
void Screen::iniSpectrumFade()
{
spectrum_fade_ = false;
spectrum_fade_counter_ = 0;
spectrum_fade_lenght_ = 50;
spectrum_color_.clear();
// Inicializa el vector de colores
const std::vector<std::string> vColors = {"black", "blue", "red", "magenta", "green", "cyan", "yellow", "bright_white"};
for (auto v : vColors)
{
spectrum_color_.push_back(stringToColor(options.video.palette, v));
}
}
// Actualiza el spectrum fade
void Screen::updateSpectrumFade()
{
if (!spectrum_fade_)
{
return;
}
spectrum_fade_counter_++;
if (spectrum_fade_counter_ > spectrum_fade_lenght_)
{
iniSpectrumFade();
SDL_SetTextureColorMod(game_canvas_, 255, 255, 255);
}
}
// Dibuja el spectrum fade
void Screen::renderSpectrumFade()
{
if (!spectrum_fade_)
{
return;
}
const float step = (float)spectrum_fade_counter_ / (float)spectrum_fade_lenght_;
const int max = spectrum_color_.size() - 1;
const int index = max + (0 - max) * step;
const Color c = spectrum_color_[index];
SDL_SetTextureColorMod(game_canvas_, c.r, c.g, c.b);
}
// Actualiza los efectos
void Screen::updateFX()
{
updateFade();
updateSpectrumFade();
}
// Dibuja los efectos
void Screen::renderFX()
{
renderFade();
renderSpectrumFade();
adjustWindowSize();
adjustGameCanvasRect();
adjustRenderLogicalSize();
}
// Dibuja las notificaciones
@@ -452,10 +301,8 @@ void Screen::renderNotifications()
void Screen::gameCanvasToBorderCanvas()
{
auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, border_canvas_);
SDL_SetRenderDrawColor(renderer_, border_color_.r, border_color_.g, border_color_.b, 0xFF);
SDL_RenderClear(renderer_);
SDL_RenderCopy(renderer_, game_canvas_, nullptr, &dest_);
SDL_SetRenderTarget(renderer_, border_texture_);
SDL_RenderCopy(renderer_, game_texture_, nullptr, &game_texture_rect_);
SDL_SetRenderTarget(renderer_, temp);
}
@@ -463,7 +310,7 @@ void Screen::gameCanvasToBorderCanvas()
void Screen::renderPresent()
{
SDL_SetRenderTarget(renderer_, nullptr);
SDL_SetRenderDrawColor(renderer_, border_color_.r, border_color_.g, border_color_.b, 0xFF);
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
SDL_RenderClear(renderer_);
if (options.video.shaders)
@@ -475,11 +322,11 @@ void Screen::renderPresent()
{
if (options.video.border.enabled)
{
SDL_RenderCopy(renderer_, border_canvas_, nullptr, nullptr);
SDL_RenderCopy(renderer_, border_texture_, nullptr, nullptr);
}
else
{
SDL_RenderCopy(renderer_, game_canvas_, nullptr, &dest_);
SDL_RenderCopy(renderer_, game_texture_, nullptr, &game_texture_rect_);
}
SDL_RenderPresent(renderer_);
}
@@ -510,3 +357,71 @@ void Screen::hide()
{
SDL_HideWindow(window_);
}
// Calcula el tamaño de la ventana
void Screen::adjustWindowSize()
{
window_width_ = options.game.width + (options.video.border.enabled ? options.video.border.width * 2 : 0);
window_height_ = options.game.height + (options.video.border.enabled ? options.video.border.height * 2 : 0);
options.window.max_zoom = getMaxZoom();
// Establece el nuevo tamaño
if (options.video.mode == 0)
{
int old_width, old_height;
SDL_GetWindowSize(window_, &old_width, &old_height);
int old_pos_x, old_pos_y;
SDL_GetWindowPosition(window_, &old_pos_x, &old_pos_y);
int new_pos_x = old_pos_x + (old_width - (window_width_ * options.window.zoom)) / 2;
int new_pos_y = old_pos_y + (old_height - (window_height_ * options.window.zoom)) / 2;
SDL_SetWindowSize(window_, window_width_ * options.window.zoom, window_height_ * options.window.zoom);
SDL_SetWindowPosition(window_, std::max(new_pos_x, WINDOWS_DECORATIONS_), std::max(new_pos_y, 0));
}
}
// Ajusta game_canvas_rect_
void Screen::adjustGameCanvasRect()
{
game_texture_rect_ = {
options.video.border.enabled ? options.video.border.width : 0,
options.video.border.enabled ? options.video.border.height : 0,
options.game.width,
options.game.height};
}
// Ajusta el tamaño lógico del renderizador
void Screen::adjustRenderLogicalSize()
{
const int extra_width = options.video.border.enabled ? options.video.border.width * 2 : 0;
const int extra_height = options.video.border.enabled ? options.video.border.height * 2 : 0;
SDL_RenderSetLogicalSize(renderer_, options.game.width + extra_width, options.game.height + extra_height);
}
// Obtiene el tamaño máximo de zoom posible para la ventana
int Screen::getMaxZoom()
{
// Obtiene información sobre la pantalla
SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode(0, &DM);
// Calcula el máximo factor de zoom que se puede aplicar a la pantalla
const int max_zoom = std::min(DM.w / window_width_, (DM.h - WINDOWS_DECORATIONS_) / window_height_);
// Normaliza los valores de zoom
options.window.zoom = std::min(options.window.zoom, max_zoom);
return max_zoom;
}
// Renderiza un frame negro
void Screen::renderBlackFrame()
{
SDL_SetRenderTarget(renderer_, nullptr);
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
SDL_RenderClear(renderer_);
SDL_RenderPresent(renderer_);
}

View File

@@ -6,7 +6,9 @@
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <SDL2/SDL_video.h> // for SDL_Window
#include <vector> // for vector
#include <memory> // for shared_ptr
#include "utils.h" // for Color
//#include "surface.h"
// Tipos de filtro
enum class ScreenFilter : Uint32
@@ -18,51 +20,25 @@ enum class ScreenFilter : Uint32
class Screen
{
private:
// Constantes
static constexpr int WINDOWS_DECORATIONS_ = 35;
// [SINGLETON] Objeto privado
static Screen *screen_;
// Objetos y punteros
SDL_Window *window_; // Ventana de la aplicación
SDL_Renderer *renderer_; // El renderizador de la ventana
SDL_Texture *game_canvas_; // Textura donde se dibuja el juego
SDL_Texture *border_canvas_; // Textura donde se dibuja el borde del juego
SDL_Window *window_; // Ventana de la aplicación
SDL_Renderer *renderer_; // El renderizador de la ventana
SDL_Texture *surface_texture_; // Textura donde se dibuja el juego
SDL_Texture *game_texture_; // Textura donde se dibuja el juego
SDL_Texture *border_texture_; // Textura donde se dibuja el borde del juego
//std::shared_ptr<Surface> surface_; // Objeto para trabajar con surfaces
// Variables
int window_width_; // Ancho de la pantalla o ventana
int window_height_; // Alto de la pantalla o ventana
int game_canvas_width_; // Resolución interna del juego. Es el ancho de la textura donde se dibuja el juego
int game_canvas_height_; // Resolución interna del juego. Es el alto de la textura donde se dibuja el juego
SDL_Rect dest_; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
Color border_color_; // Color del borde añadido a la textura de juego para rellenar la pantalla
int notification_logical_width_; // Ancho lógico de las notificaciones en relación al tamaño de pantalla
int notification_logical_height_; // Alto lógico de las notificaciones en relación al tamaño de pantalla
// Variables - Efectos
bool fade_; // Indica si esta activo el efecto de fade
int fade_counter_; // Temporizador para el efecto de fade
int fade_lenght_; // Duración del fade
bool spectrum_fade_; // Indica si esta activo el efecto de fade spectrum
int spectrum_fade_counter_; // Temporizador para el efecto de fade spectrum
int spectrum_fade_lenght_; // Duración del fade spectrum
std::vector<Color> spectrum_color_; // Colores para el fade spectrum
// Inicializa las variables para el fade
void iniFade();
// Actualiza el fade
void updateFade();
// Dibuja el fade
void renderFade();
// Inicializa las variables para el fade spectrum
void iniSpectrumFade();
// Actualiza el spectrum fade
void updateSpectrumFade();
// Dibuja el spectrum fade
void renderSpectrumFade();
int window_width_; // Ancho de la pantalla o ventana
int window_height_; // Alto de la pantalla o ventana
SDL_Rect game_texture_rect_; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
Color border_color_; // Color del borde añadido a la textura de juego para rellenar la pantalla
// Dibuja las notificaciones
void renderNotifications();
@@ -73,6 +49,18 @@ private:
// Muestra el contenido de Screen por pantalla
void renderPresent();
// Calcula el tamaño de la ventana
void adjustWindowSize();
// Ajusta game_canvas_rect_
void adjustGameCanvasRect();
// Ajusta el tamaño lógico del renderizador
void adjustRenderLogicalSize();
// Renderiza un frame negro
void renderBlackFrame();
// Constructor
Screen(SDL_Window *window, SDL_Renderer *renderer);
@@ -111,14 +99,11 @@ public:
// Camibia entre pantalla completa y ventana
void toggleVideoMode();
// Cambia el tamaño de la ventana
void setWindowZoom(int size);
// Reduce el tamaño de la ventana
void decWindowZoom();
bool decWindowZoom();
// Aumenta el tamaño de la ventana
void incWindowZoom();
bool incWindowZoom();
// Cambia el color del borde
void setBorderColor(Color color);
@@ -136,24 +121,6 @@ public:
// Cambia entre borde visible y no visible
void toggleBorder();
// Activa el fade
void setFade();
// Comprueba si ha terminado el fade
bool fadeEnded();
// Activa el spectrum fade
void setspectrumFade();
// Comprueba si ha terminado el spectrum fade
bool spectrumFadeEnded();
// Actualiza los efectos
void updateFX();
// Dibuja los efectos
void renderFX();
// Cambia el estado de los shaders
void toggleShaders();
@@ -163,6 +130,12 @@ public:
// Oculta la ventana
void hide();
// Obtiene el tamaño máximo de zoom posible para la ventana
int getMaxZoom();
// Getters
SDL_Renderer *getRenderer() { return renderer_; }
//std::shared_ptr<SurfaceData> getSurface() { return surface_->getSurface(); }
SDL_Texture *getGameTexture() { return game_texture_; };
SDL_Texture *getBorderTexture() { return border_texture_; }
};

243
source/surface.cpp Normal file
View File

@@ -0,0 +1,243 @@
#include "surface.h"
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_ARGB8888
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <fstream> // Para std::ifstream
#include <iostream> // Para std::cerr
#include <vector> // Para std::vector
#include <stdexcept> // For exceptions
#include "gif.h" // Para LoadGif, LoadPalette
#include <memory> // Para std::shared_ptr
#include <algorithm> // Para std::copy
#include "asset.h"
Surface::Surface(std::shared_ptr<SurfaceData> surface_dest, int w, int h)
: surface_dest_(surface_dest),
surface_(std::make_shared<SurfaceData>(w, h)),
transparent_color_(0) {}
Surface::Surface(std::shared_ptr<SurfaceData> surface_dest, std::string file_path)
: surface_dest_(surface_dest),
surface_(std::make_shared<SurfaceData>(loadSurface(Asset::get()->get(file_path)))),
transparent_color_(0) {
std::cout << "surface loaded: "<< surface_->width << "x" << surface_->height << std::endl;
}
Surface::~Surface() {}
// Carga una superficie desde un archivo
SurfaceData Surface::loadSurface(const std::string &file_path)
{
std::ifstream file(file_path, std::ios::binary | std::ios::ate);
if (!file.is_open())
{
std::cerr << "Error opening file: " << file_path << std::endl;
throw std::runtime_error("Error opening file");
}
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<Uint8> buffer(size);
if (!file.read((char *)buffer.data(), size))
{
std::cerr << "Error reading file: " << file_path << std::endl;
throw std::runtime_error("Error reading file");
}
Uint16 w, h;
Uint8 *pixels = LoadGif(buffer.data(), &w, &h);
if (pixels == nullptr)
{
std::cerr << "Error loading GIF from file: " << file_path << std::endl;
throw std::runtime_error("Error loading GIF");
}
// Crear y devolver directamente el objeto SurfaceData
return SurfaceData(w, h, pixels);
}
// Carga una paleta desde un archivo
void Surface::loadPalette(const std::string &file_path)
{
// Abrir el archivo en modo binario
std::ifstream file(file_path, std::ios::binary | std::ios::ate);
if (!file.is_open())
{
throw std::runtime_error("Error opening file: " + file_path);
}
// Leer el contenido del archivo en un buffer
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<Uint8> buffer(size);
if (!file.read(reinterpret_cast<char *>(buffer.data()), size))
{
throw std::runtime_error("Error reading file: " + file_path);
}
// Cargar la paleta usando los datos del buffer
std::unique_ptr<Uint32[]> pal(LoadPalette(buffer.data()));
if (pal == nullptr)
{
throw std::runtime_error("Error loading palette from file: " + file_path);
}
// Copiar los datos de la paleta al std::array
std::copy(pal.get(), pal.get() + palette_.size(), palette_.begin());
for (auto p : palette_)
{
std::cout << std::hex << p << " ";
}
std::cout << std::endl;
}
// Establece un color en la paleta
void Surface::setColor(int index, Uint32 color)
{
palette_.at(index) = color;
}
// Limpia la superficie de destino con un color
void Surface::clear(std::shared_ptr<SurfaceData> surface, Uint8 color)
{
const size_t total_pixels = surface->width * surface->height;
std::fill(surface->data, surface->data + total_pixels, color);
}
// Pone un pixel en la superficie de destino
void Surface::putPixel(int x, int y, Uint8 color)
{
if (color == transparent_color_)
{
return; // Color transparente, no dibujar
}
if (x < 0 || y < 0 || x >= surface_dest_->width || y >= surface_dest_->height)
{
return; // Coordenadas fuera de rango
}
const int index = x + y * surface_dest_->width;
surface_dest_->data[index] = color;
}
// Obtiene el color de un pixel de la superficie de origen
Uint8 Surface::getPixel(int x, int y)
{
return surface_->data[x + y * surface_->width];
}
// Copia una región de la superficie de origen a la de destino
void Surface::render(int dx, int dy, int sx, int sy, int w, int h)
{
if (!surface_ || !surface_dest_)
{
throw std::runtime_error("Surface source or destination is null.");
}
// Limitar la región para evitar accesos fuera de rango
w = std::min(w, surface_->width - sx);
h = std::min(h, surface_->height - sy);
w = std::min(w, surface_dest_->width - dx);
h = std::min(h, surface_dest_->height - dy);
for (int iy = 0; iy < h; ++iy)
{
for (int ix = 0; ix < w; ++ix)
{
Uint8 color = surface_->data[(sx + ix) + (sy + iy) * surface_->width];
if (color != transparent_color_) // Opcional: Ignorar píxeles transparentes
{
surface_dest_->data[(dx + ix) + (dy + iy) * surface_dest_->width] = color;
}
}
}
}
/*
// Vuelca la superficie a una textura
void Surface::flip(SDL_Renderer *renderer, SDL_Texture *texture)
{
Uint32 *pixels;
int pitch;
SDL_LockTexture(texture, nullptr, (void **)&pixels, &pitch);
for (int i = 0; i < surface_.width * surface_.height; ++i)
{
pixels[i] = palette_[surface_.data[i]];
}
SDL_UnlockTexture(texture);
SDL_RenderCopy(renderer, texture, nullptr, nullptr);
}
*/
// Vuelca la superficie a una textura
void Surface::copyToTexture(SDL_Renderer *renderer, SDL_Texture *texture)
{
if (!renderer || !texture)
{
throw std::runtime_error("Renderer or texture is null.");
}
if (surface_->width <= 0 || surface_->height <= 0 || !surface_->data)
{
throw std::runtime_error("Invalid surface dimensions or data.");
}
Uint32 *pixels = nullptr;
int pitch = 0;
// Bloquea la textura para modificar los píxeles directamente
if (SDL_LockTexture(texture, nullptr, (void **)&pixels, &pitch) != 0)
{
throw std::runtime_error("Failed to lock texture: " + std::string(SDL_GetError()));
}
// Convertir `pitch` de bytes a Uint32 (asegurando alineación correcta en hardware)
int row_stride = pitch / sizeof(Uint32);
for (int y = 0; y < surface_->height; ++y)
{
for (int x = 0; x < surface_->width; ++x)
{
// Calcular la posición correcta en la textura teniendo en cuenta el stride
int texture_index = y * row_stride + x;
int surface_index = y * surface_->width + x;
pixels[texture_index] = palette_[surface_->data[surface_index]];
}
}
SDL_UnlockTexture(texture); // Desbloquea la textura
// Renderiza la textura en la pantalla completa
if (SDL_RenderCopy(renderer, texture, nullptr, nullptr) != 0)
{
throw std::runtime_error("Failed to copy texture to renderer: " + std::string(SDL_GetError()));
}
}
// Realiza un efecto de fundido en la paleta
bool Surface::fadePalette()
{
// Verificar que el tamaño mínimo de palette_ sea adecuado
static constexpr int palette_size = 19;
if (sizeof(palette_) / sizeof(palette_[0]) < palette_size)
{
throw std::runtime_error("Palette size is insufficient for fadePalette operation.");
}
// Desplazar colores (pares e impares)
for (int i = 18; i > 1; --i)
{
palette_[i] = palette_[i - 2];
}
// Ajustar el primer color
palette_[1] = palette_[0];
// Devolver si el índice 15 coincide con el índice 0
return palette_[15] == palette_[0];
}

108
source/surface.h Normal file
View File

@@ -0,0 +1,108 @@
#pragma once
#include <SDL2/SDL_render.h> // Para SDL_Renderer
#include <SDL2/SDL_stdinc.h> // Para Uint8, Uint32
#include <array>
#include <memory>
#include <string>
struct SurfaceData
{
Uint8 *data;
Uint16 width;
Uint16 height;
// Constructor por defecto
SurfaceData() : data(nullptr), width(0), height(0) {}
// Constructor que inicializa dimensiones y asigna memoria
SurfaceData(Uint16 w, Uint16 h)
: data(new Uint8[w * h]()), width(w), height(h) {}
// Constructor para inicializar directamente con datos
SurfaceData(Uint16 w, Uint16 h, Uint8 *pixels)
: data(pixels), width(w), height(h) {}
// Destructor para liberar memoria
~SurfaceData() { delete[] data; }
// Evita copias accidentales (opcional para mayor seguridad)
SurfaceData(const SurfaceData &) = delete;
SurfaceData &operator=(const SurfaceData &) = delete;
// Permite movimiento para evitar copias costosas
SurfaceData(SurfaceData &&other) noexcept
: data(other.data), width(other.width), height(other.height)
{
other.data = nullptr;
other.width = 0;
other.height = 0;
}
SurfaceData &operator=(SurfaceData &&other) noexcept
{
if (this != &other)
{
delete[] data;
data = other.data;
width = other.width;
height = other.height;
other.data = nullptr;
other.width = 0;
other.height = 0;
}
return *this;
}
};
class Surface
{
private:
std::shared_ptr<SurfaceData> surface_dest_;
std::shared_ptr<SurfaceData> surface_;
std::array<Uint32, 256> palette_;
int transparent_color_;
// Pone un pixel en la superficie de destino
void putPixel(int x, int y, Uint8 color);
// Obtiene el color de un pixel de la superficie de origen
Uint8 getPixel(int x, int y);
public:
// Constructor
Surface(std::shared_ptr<SurfaceData> surface_dest, int w, int h);
Surface(std::shared_ptr<SurfaceData> surface_dest, std::string file_path);
// Destructor
~Surface();
// Carga una superficie desde un archivo
SurfaceData loadSurface(const std::string &file_path);
// Carga una paleta desde un archivo
void loadPalette(const std::string &file_path);
// Copia una región de la superficie de origen a la de destino
void render(int dx, int dy, int sx, int sy, int w, int h);
// Establece un color en la paleta
void setColor(int index, Uint32 color);
// Limpia la superficie de destino con un color
void clear(std::shared_ptr<SurfaceData> surface, Uint8 color);
// Vuelca la superficie a una textura
void copyToTexture(SDL_Renderer *renderer, SDL_Texture *texture);
// Realiza un efecto de fundido en la paleta
bool fadePalette();
// Getters
std::shared_ptr<SurfaceData> getSurface() const { return surface_; }
// std::shared_ptr<SurfaceData> getSurfaceDest() const { return surface_dest_; }
// std::array<Uint32, 256> getPalette() const { return palette_; }
int getTransparentColor() const { return transparent_color_; }
};

View File

@@ -52,7 +52,7 @@ Texture::Texture(SDL_Renderer *renderer, const std::string &path)
Texture::~Texture()
{
unloadTexture();
//unloadSurface();
// unloadSurface();
palettes_.clear();
}

View File

@@ -11,7 +11,7 @@
struct Color;
// Definiciones de tipos
struct Surface
/*struct Surface
{
std::shared_ptr<Uint8[]> data;
Uint16 w, h;
@@ -19,7 +19,7 @@ struct Surface
// Constructor
Surface(Uint16 width, Uint16 height, std::shared_ptr<Uint8[]> pixels)
: data(pixels), w(width), h(height) {}
};
};*/
class Texture
{
@@ -27,7 +27,7 @@ private:
// Objetos y punteros
SDL_Renderer *renderer_; // Renderizador donde dibujar la textura
SDL_Texture *texture_ = nullptr; // La textura
std::shared_ptr<Surface> surface_ = nullptr; // Surface para usar imagenes en formato gif con paleta
//std::shared_ptr<Surface> surface_ = nullptr; // Surface para usar imagenes en formato gif con paleta
// Variables
std::string path_; // Ruta de la imagen de la textura
@@ -37,19 +37,19 @@ private:
int current_palette_ = 0; // Indice de la paleta en uso
// Crea una surface desde un fichero .gif
//std::shared_ptr<Surface> loadSurface(const std::string &file_name);
// std::shared_ptr<Surface> loadSurface(const std::string &file_name);
// Vuelca la surface en la textura
//void flipSurface();
// void flipSurface();
// Carga una paleta desde un fichero
//std::vector<Uint32> loadPaletteFromFile(const std::string &file_name);
// std::vector<Uint32> loadPaletteFromFile(const std::string &file_name);
// Libera la memoria de la textura
void unloadTexture();
// Desencadenar la superficie actual
//void unloadSurface();
// void unloadSurface();
public:
// Constructor
@@ -93,13 +93,13 @@ public:
SDL_Texture *getSDLTexture();
// Añade una paleta a la lista
//void addPaletteFromFile(const std::string &path);
// void addPaletteFromFile(const std::string &path);
// Establece un color de la paleta
//void setPaletteColor(int palette, int index, Uint32 color);
// void setPaletteColor(int palette, int index, Uint32 color);
// Cambia la paleta de la textura
//void setPalette(int palette);
// void setPalette(int palette);
// Obtiene el renderizador
SDL_Renderer *getRenderer();

View File

@@ -1,24 +1,25 @@
#include "title.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_error.h> // for SDL_GetError
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_scancode.h> // for SDL_SCANCODE_1, SDL_SCANCODE_2
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <iostream> // for basic_ostream, operator<<, cout, endl
#include "asset.h" // for Asset
#include "cheevos.h" // for Achievement, Cheevos
#include "defines.h" // for PLAY_AREA_CENTER_X, GAMECANVAS_WIDTH
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input, inputs_e, REPEAT_FALSE, REPEA...
#include "options.h" // for Options, options, OptionsVideo, Sect...
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "sprite.h" // for Sprite
#include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR
#include "texture.h" // for Texture
#include "utils.h" // for Color, stringToColor, Palette
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_error.h> // for SDL_GetError
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_scancode.h> // for SDL_SCANCODE_1, SDL_SCANCODE_2
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <iostream> // for basic_ostream, operator<<, cout, endl
#include "asset.h" // for Asset
#include "cheevos.h" // for Achievement, Cheevos
#include "defines.h" // for PLAY_AREA_CENTER_X, GAMECANVAS_WIDTH
#include "global_events.h" // for check
#include "global_inputs.h" // for check
#include "input.h" // for Input, inputs_e, REPEAT_FALSE, REPEA...
#include "options.h" // for Options, options, OptionsVideo, Sect...
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "sprite.h" // for Sprite
#include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR
#include "texture.h" // for Texture
#include "utils.h" // for Color, stringToColor, Palette
#include "paleta.h"
// Constructor
Title::Title()
@@ -71,6 +72,9 @@ Title::Title()
// Rellena la textura de fondo con todos los gráficos
fillTexture();
// Inicia la musica
playMusic("title.ogg");
}
// Destructor
@@ -213,7 +217,7 @@ void Title::renderInfo()
void Title::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks_ > ticks_speed_)
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();

View File

@@ -1,18 +1,18 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "paleta.h" // for jSurface
class Input; // lines 13-13
class Resource; // lines 14-14
class Screen; // lines 15-15
class Sprite; // lines 16-16
class Text; // lines 17-17
class Texture; // lines 18-18
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "paleta.h" // for jSurface
class Input; // lines 13-13
class Resource; // lines 14-14
class Screen; // lines 15-15
class Sprite; // lines 16-16
class Text; // lines 17-17
class Texture; // lines 18-18
class Title
{
@@ -32,13 +32,13 @@ private:
};
// Objetos y punteros
Screen *screen_; // Objeto encargado de dibujar en pantalla
SDL_Renderer *renderer_; // El renderizador de la ventana
Resource *resource_; // Objeto con los recursos
Input *input_; // Objeto pata gestionar la entrada
Screen *screen_; // Objeto encargado de dibujar en pantalla
SDL_Renderer *renderer_; // El renderizador de la ventana
Resource *resource_; // Objeto con los recursos
Input *input_; // Objeto pata gestionar la entrada
std::shared_ptr<Texture> texture_; // Textura con los graficos
std::shared_ptr<Sprite> sprite_; // Sprite para manejar la textura
SDL_Texture *bg_texture_; // Textura para dibujar el fondo de la pantalla
SDL_Texture *bg_texture_; // Textura para dibujar el fondo de la pantalla
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
std::shared_ptr<Text> info_text_; // Objeto para escribir texto en pantalla
std::shared_ptr<Texture> cheevos_texture_; // Textura con la lista de logros
@@ -48,13 +48,12 @@ private:
int counter_ = 0; // Contador
std::string long_text_; // Texto que aparece en la parte inferior del titulo
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticks_speed_ = 15; // Velocidad a la que se repiten los bucles del programa
std::vector<letter_t> letters_; // Vector con las letras de la marquesina
int marquee_speed_ = 3; // Velocidad de desplazamiento de la marquesina
bool show_cheevos_ = false; // Indica si se muestra por pantalla el listado de logros
SDL_Rect cheevos_texture_view_; // Zona visible de la textura con el listado de logros
states_e state_; // Estado en el que se encuentra el bucle principal
jSurface loading_screen_; // Surface con los gráficos de la pantalla de carga
jSurface loading_screen_; // Surface con los gráficos de la pantalla de carga
// Actualiza las variables
void update();

View File

@@ -8,6 +8,8 @@
#include <iostream> // for basic_ostream, cout, basic_ios, ios, endl
#include <unordered_map> // for unordered_map
#include <string> // for string
#include "jail_audio.h"
#include "resource.h"
// Calcula el cuadrado de la distancia entre dos puntos
double distanceSquared(int x1, int y1, int x2, int y2)
@@ -519,3 +521,38 @@ void printWithDots(const std::string &text1, const std::string &text2, const std
std::cout << text3 << std::endl;
}
// Comprueba si una vector contiene una cadena
bool stringInVector(const std::vector<std::string> &vec, const std::string &str)
{
return std::find(vec.begin(), vec.end(), str) != vec.end();
}
// Hace sonar la música
void playMusic(const std::string &music_path)
{
// Si la música no está sonando
if (JA_GetMusicState() == JA_MUSIC_INVALID || JA_GetMusicState() == JA_MUSIC_STOPPED)
{
JA_PlayMusic(Resource::get()->getMusic(music_path));
}
}
// Rellena una textura de un color
void fillTextureWithColor(SDL_Renderer* renderer, SDL_Texture* texture, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
// Guardar el render target actual
SDL_Texture* previous_target = SDL_GetRenderTarget(renderer);
// Establecer la textura como el render target
SDL_SetRenderTarget(renderer, texture);
// Establecer el color deseado
SDL_SetRenderDrawColor(renderer, r, g, b, a);
// Pintar toda el área
SDL_RenderClear(renderer);
// Restaurar el render target previo
SDL_SetRenderTarget(renderer, previous_target);
}

View File

@@ -3,6 +3,10 @@
#include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point
#include <SDL2/SDL_stdinc.h> // for Uint8
#include <string> // for string
#include <vector>
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL.h> // for SDL_Texture
// Tipos de paleta
enum class Palette : int
@@ -123,3 +127,12 @@ std::string getPath(const std::string &full_path);
// Imprime por pantalla una linea de texto de tamaño fijo rellena con puntos
void printWithDots(const std::string &text1, const std::string &text2, const std::string &text3);
// Comprueba si una vector contiene una cadena
bool stringInVector(const std::vector<std::string> &vec, const std::string &str);
// Hace sonar la música
void playMusic(const std::string &music_path);
// Rellena una textura de un color
void fillTextureWithColor(SDL_Renderer* renderer, SDL_Texture* texture, Uint8 r, Uint8 g, Uint8 b, Uint8 a);