forked from jaildesigner-jailgames/jaildoctors_dilemma
redistribuida la carpeta source
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,4 +1,4 @@
|
|||||||
.vscode
|
.vscode/
|
||||||
*data/config/config.txt
|
*data/config/config.txt
|
||||||
*stats.txt
|
*stats.txt
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
@@ -11,8 +11,8 @@ thumbs.db
|
|||||||
*.zip
|
*.zip
|
||||||
*.app
|
*.app
|
||||||
*_debug*
|
*_debug*
|
||||||
sync_jail_engine.sh
|
|
||||||
jaildoctors_dilemma*
|
jaildoctors_dilemma*
|
||||||
todo
|
todo
|
||||||
build/
|
build/
|
||||||
linux_utils/
|
linux_utils/
|
||||||
|
.claude/
|
||||||
@@ -33,46 +33,62 @@ configure_file(${CMAKE_SOURCE_DIR}/source/version.h.in ${CMAKE_BINARY_DIR}/versi
|
|||||||
|
|
||||||
# --- 1. LISTA EXPLÍCITA DE FUENTES ---
|
# --- 1. LISTA EXPLÍCITA DE FUENTES ---
|
||||||
set(APP_SOURCES
|
set(APP_SOURCES
|
||||||
source/asset.cpp
|
# Core - Input
|
||||||
source/cheevos.cpp
|
source/core/input/global_inputs.cpp
|
||||||
source/debug.cpp
|
source/core/input/input.cpp
|
||||||
source/director.cpp
|
source/core/input/mouse.cpp
|
||||||
source/enemy.cpp
|
|
||||||
source/gif.cpp
|
|
||||||
source/global_events.cpp
|
|
||||||
source/global_inputs.cpp
|
|
||||||
source/input.cpp
|
|
||||||
source/item_tracker.cpp
|
|
||||||
source/item.cpp
|
|
||||||
source/main.cpp
|
|
||||||
source/mouse.cpp
|
|
||||||
source/options.cpp
|
|
||||||
source/player.cpp
|
|
||||||
source/resource.cpp
|
|
||||||
source/room_tracker.cpp
|
|
||||||
source/room.cpp
|
|
||||||
source/scoreboard.cpp
|
|
||||||
source/screen.cpp
|
|
||||||
source/stats.cpp
|
|
||||||
source/surface.cpp
|
|
||||||
source/text.cpp
|
|
||||||
source/texture.cpp
|
|
||||||
source/utils.cpp
|
|
||||||
|
|
||||||
source/ui/notifier.cpp
|
|
||||||
|
|
||||||
source/sections/credits.cpp
|
|
||||||
source/sections/ending.cpp
|
|
||||||
source/sections/ending2.cpp
|
|
||||||
source/sections/game_over.cpp
|
|
||||||
source/sections/game.cpp
|
|
||||||
source/sections/loading_screen.cpp
|
|
||||||
source/sections/logo.cpp
|
|
||||||
source/sections/title.cpp
|
|
||||||
|
|
||||||
source/sprite/surface_animated_sprite.cpp
|
# Core - Rendering
|
||||||
source/sprite/surface_moving_sprite.cpp
|
source/core/rendering/gif.cpp
|
||||||
source/sprite/surface_sprite.cpp
|
source/core/rendering/screen.cpp
|
||||||
|
source/core/rendering/surface.cpp
|
||||||
|
source/core/rendering/surface_animated_sprite.cpp
|
||||||
|
source/core/rendering/surface_moving_sprite.cpp
|
||||||
|
source/core/rendering/surface_sprite.cpp
|
||||||
|
source/core/rendering/text.cpp
|
||||||
|
source/core/rendering/texture.cpp
|
||||||
|
|
||||||
|
# Core - Resources
|
||||||
|
source/core/resources/asset.cpp
|
||||||
|
source/core/resources/resource.cpp
|
||||||
|
|
||||||
|
# Core - System
|
||||||
|
source/core/system/debug.cpp
|
||||||
|
source/core/system/director.cpp
|
||||||
|
|
||||||
|
# Game - Entities
|
||||||
|
source/game/entities/enemy.cpp
|
||||||
|
source/game/entities/item.cpp
|
||||||
|
source/game/entities/player.cpp
|
||||||
|
|
||||||
|
# Game - Gameplay
|
||||||
|
source/game/gameplay/cheevos.cpp
|
||||||
|
source/game/gameplay/item_tracker.cpp
|
||||||
|
source/game/gameplay/options.cpp
|
||||||
|
source/game/gameplay/room.cpp
|
||||||
|
source/game/gameplay/room_tracker.cpp
|
||||||
|
source/game/gameplay/scoreboard.cpp
|
||||||
|
source/game/gameplay/stats.cpp
|
||||||
|
|
||||||
|
# Game - Scenes
|
||||||
|
source/game/scenes/credits.cpp
|
||||||
|
source/game/scenes/ending.cpp
|
||||||
|
source/game/scenes/ending2.cpp
|
||||||
|
source/game/scenes/game.cpp
|
||||||
|
source/game/scenes/game_over.cpp
|
||||||
|
source/game/scenes/loading_screen.cpp
|
||||||
|
source/game/scenes/logo.cpp
|
||||||
|
source/game/scenes/title.cpp
|
||||||
|
|
||||||
|
# Game - UI
|
||||||
|
source/game/ui/notifier.cpp
|
||||||
|
|
||||||
|
# Utils
|
||||||
|
source/utils/global_events.cpp
|
||||||
|
source/utils/utils.cpp
|
||||||
|
|
||||||
|
# Main
|
||||||
|
source/main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Fuentes de librerías de terceros
|
# Fuentes de librerías de terceros
|
||||||
@@ -82,7 +98,7 @@ set(EXTERNAL_SOURCES
|
|||||||
|
|
||||||
# Fuentes del sistema de renderizado
|
# Fuentes del sistema de renderizado
|
||||||
set(RENDERING_SOURCES
|
set(RENDERING_SOURCES
|
||||||
source/rendering/opengl/opengl_shader.cpp
|
source/core/rendering/opengl/opengl_shader.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configuración de SDL3
|
# Configuración de SDL3
|
||||||
|
|||||||
108
organizar.sh
108
organizar.sh
@@ -1,108 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# Script para reorganizar la carpeta 'source' a una nueva estructura en 'source2'
|
|
||||||
# ==============================================================================
|
|
||||||
#
|
|
||||||
# INSTRUCCIONES:
|
|
||||||
# 1. Guarda este archivo como 'organizar.sh' en el directorio padre de 'source'.
|
|
||||||
# 2. Abre una terminal en ese directorio.
|
|
||||||
# 3. Dale permisos de ejecución con: chmod +x organizar.sh
|
|
||||||
# 4. Ejecútalo con: ./organizar.sh
|
|
||||||
#
|
|
||||||
|
|
||||||
# --- Configuración ---
|
|
||||||
SRC_DIR="source"
|
|
||||||
DEST_DIR="source2"
|
|
||||||
|
|
||||||
# --- Comprobaciones Previas ---
|
|
||||||
if [ ! -d "$SRC_DIR" ]; then
|
|
||||||
echo "❌ Error: El directorio '$SRC_DIR' no se encuentra."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "🚀 Iniciando la reorganización de '$SRC_DIR' a '$DEST_DIR'..."
|
|
||||||
|
|
||||||
# --- Limpieza y Creación de la Estructura Base ---
|
|
||||||
rm -rf "$DEST_DIR"
|
|
||||||
mkdir -p "$DEST_DIR"
|
|
||||||
echo " - Creado directorio raíz '$DEST_DIR'."
|
|
||||||
|
|
||||||
# Creando directorios principales
|
|
||||||
mkdir -p "$DEST_DIR/Core/Input"
|
|
||||||
mkdir -p "$DEST_DIR/Core/Rendering"
|
|
||||||
mkdir -p "$DEST_DIR/Core/Resources"
|
|
||||||
mkdir -p "$DEST_DIR/Core/System"
|
|
||||||
mkdir -p "$DEST_DIR/Game/Entities"
|
|
||||||
mkdir -p "$DEST_DIR/Game/Gameplay"
|
|
||||||
mkdir -p "$DEST_DIR/Game/Scenes"
|
|
||||||
mkdir -p "$DEST_DIR/Game/UI"
|
|
||||||
mkdir -p "$DEST_DIR/Utils"
|
|
||||||
echo " - Creada la estructura de carpetas principal."
|
|
||||||
|
|
||||||
# --- Función para copiar archivos ---
|
|
||||||
copy_file() {
|
|
||||||
local dest_sub_dir="$1"
|
|
||||||
shift
|
|
||||||
for file in "$@"; do
|
|
||||||
if [ -f "$SRC_DIR/$file" ]; then
|
|
||||||
cp "$SRC_DIR/$file" "$DEST_DIR/$dest_sub_dir/"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Advertencia: No se encontró el archivo '$file' en '$SRC_DIR/'."
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- Copiando Archivos a su Nueva Ubicación ---
|
|
||||||
|
|
||||||
echo " - Copiando archivos del motor (Core)..."
|
|
||||||
# Core/Input
|
|
||||||
copy_file "Core/Input" "input.h" "input.cpp" "global_inputs.h" "global_inputs.cpp" "mouse.h" "mouse.cpp"
|
|
||||||
|
|
||||||
# Core/Rendering
|
|
||||||
copy_file "Core/Rendering" "texture.h" "texture.cpp" "surface.h" "surface.cpp" "screen.h" "screen.cpp" "text.h" "text.cpp" "gif.h" "gif.cpp"
|
|
||||||
# Mover carpetas de rendering existentes
|
|
||||||
if [ -d "$SRC_DIR/sprite" ]; then cp -r "$SRC_DIR/sprite/"* "$DEST_DIR/Core/Rendering/"; fi
|
|
||||||
if [ -d "$SRC_DIR/rendering" ]; then cp -r "$SRC_DIR/rendering" "$DEST_DIR/Core/"; fi
|
|
||||||
|
|
||||||
# Core/Resources
|
|
||||||
copy_file "Core/Resources" "resource.h" "resource.cpp" "asset.h" "asset.cpp"
|
|
||||||
|
|
||||||
# Core/System
|
|
||||||
copy_file "Core/System" "director.h" "director.cpp" "debug.h" "debug.cpp"
|
|
||||||
|
|
||||||
echo " - Copiando archivos de lógica de juego (Game)..."
|
|
||||||
# Game/Entities
|
|
||||||
copy_file "Game/Entities" "player.h" "player.cpp" "enemy.h" "enemy.cpp" "item.h" "item.cpp"
|
|
||||||
|
|
||||||
# Game/Gameplay
|
|
||||||
copy_file "Game/Gameplay" "room.h" "room.cpp" "room_tracker.h" "room_tracker.cpp" "item_tracker.h" "item_tracker.cpp" "stats.h" "stats.cpp" "scoreboard.h" "scoreboard.cpp" "cheevos.h" "cheevos.cpp" "options.h" "options.cpp"
|
|
||||||
|
|
||||||
# Game/Scenes (tu antigua 'sections')
|
|
||||||
if [ -d "$SRC_DIR/sections" ]; then
|
|
||||||
cp -r "$SRC_DIR/sections/"* "$DEST_DIR/Game/Scenes/"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Game/UI (tu antigua 'ui')
|
|
||||||
if [ -d "$SRC_DIR/ui" ]; then
|
|
||||||
cp -r "$SRC_DIR/ui/"* "$DEST_DIR/Game/UI/"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo " - Copiando utilidades y ficheros externos..."
|
|
||||||
# Utils
|
|
||||||
copy_file "Utils" "utils.h" "utils.cpp" "defines.h" "global_events.h" "global_events.cpp"
|
|
||||||
|
|
||||||
# External (copia la carpeta entera)
|
|
||||||
if [ -d "$SRC_DIR/external" ]; then
|
|
||||||
cp -r "$SRC_DIR/external" "$DEST_DIR/"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Archivos de la raíz del proyecto
|
|
||||||
copy_file "" "main.cpp" "version.h.in"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "✅ ¡Proceso completado!"
|
|
||||||
echo "Tu proyecto ha sido reorganizado en la carpeta '$DEST_DIR'."
|
|
||||||
echo "La carpeta original '$SRC_DIR' no ha sido modificada."
|
|
||||||
|
|
||||||
echo "🧠 Recuerda: El siguiente paso crucial es actualizar tus '#includes' y tu sistema de compilación (CMake, Makefile, etc.) para que apunten a las nuevas rutas."
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
#include "cheevos.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
#include <stddef.h> // Para NULL
|
|
||||||
|
|
||||||
#include <fstream> // Para basic_ostream, operator<<, basic_ofstream
|
|
||||||
#include <iostream> // Para cout, cerr
|
|
||||||
|
|
||||||
#include "options.h" // Para Options, options
|
|
||||||
#include "ui/notifier.h" // Para Notifier
|
|
||||||
|
|
||||||
// [SINGLETON]
|
|
||||||
Cheevos* Cheevos::cheevos_ = nullptr;
|
|
||||||
|
|
||||||
// [SINGLETON] Crearemos el objeto con esta función estática
|
|
||||||
void Cheevos::init(const std::string& file) {
|
|
||||||
Cheevos::cheevos_ = new Cheevos(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// [SINGLETON] Destruiremos el objeto con esta función estática
|
|
||||||
void Cheevos::destroy() {
|
|
||||||
delete Cheevos::cheevos_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
|
|
||||||
Cheevos* Cheevos::get() {
|
|
||||||
return Cheevos::cheevos_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Cheevos::Cheevos(const std::string& file)
|
|
||||||
: file_(file) {
|
|
||||||
init();
|
|
||||||
loadFromFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
Cheevos::~Cheevos() {
|
|
||||||
saveToFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa los logros
|
|
||||||
void Cheevos::init() {
|
|
||||||
cheevos_list_.clear();
|
|
||||||
cheevos_list_.emplace_back(1, "SHINY THINGS", "Get 25% of the items", 2);
|
|
||||||
cheevos_list_.emplace_back(2, "HALF THE WORK", "Get 50% of the items", 2);
|
|
||||||
cheevos_list_.emplace_back(3, "GETTING THERE", "Get 75% of the items", 2);
|
|
||||||
cheevos_list_.emplace_back(4, "THE COLLECTOR", "Get 100% of the items", 2);
|
|
||||||
cheevos_list_.emplace_back(5, "WANDERING AROUND", "Visit 20 rooms", 2);
|
|
||||||
cheevos_list_.emplace_back(6, "I GOT LOST", "Visit 40 rooms", 2);
|
|
||||||
cheevos_list_.emplace_back(7, "I LIKE TO EXPLORE", "Visit all rooms", 2);
|
|
||||||
cheevos_list_.emplace_back(8, "FINISH THE GAME", "Complete the game", 2);
|
|
||||||
cheevos_list_.emplace_back(9, "I WAS SUCKED BY A HOLE", "Complete the game without entering the jail", 2);
|
|
||||||
cheevos_list_.emplace_back(10, "MY LITTLE PROJECTS", "Complete the game with all items", 2);
|
|
||||||
cheevos_list_.emplace_back(11, "I LIKE MY MULTICOLOURED FRIENDS", "Complete the game without dying", 2);
|
|
||||||
cheevos_list_.emplace_back(12, "SHIT PROJECTS DONE FAST", "Complete the game in under 30 minutes", 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Busca un logro por id y devuelve el indice
|
|
||||||
int Cheevos::find(int id) {
|
|
||||||
for (int i = 0; i < (int)cheevos_list_.size(); ++i) {
|
|
||||||
if (cheevos_list_[i].id == id) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Desbloquea un logro
|
|
||||||
void Cheevos::unlock(int id) {
|
|
||||||
const int INDEX = find(id);
|
|
||||||
|
|
||||||
// Si el índice es inválido, el logro no es válido, ya está completado o el sistema de logros no está habilitado, no hacemos nada
|
|
||||||
if (INDEX == -1 || !cheevos_list_.at(INDEX).obtainable || cheevos_list_.at(INDEX).completed || !enabled_) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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}, NotificationText::CENTER, CHEEVO_NOTIFICATION_DURATION /*, cheevos_list_.at(INDEX).icon*/);
|
|
||||||
|
|
||||||
// Guardar el estado de los logros
|
|
||||||
saveToFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invalida un logro
|
|
||||||
void Cheevos::setUnobtainable(int id) {
|
|
||||||
const int index = find(id);
|
|
||||||
|
|
||||||
// Si el índice es válido, se invalida el logro
|
|
||||||
if (index != -1) {
|
|
||||||
cheevos_list_.at(index).obtainable = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carga el estado de los logros desde un fichero
|
|
||||||
void Cheevos::loadFromFile() {
|
|
||||||
std::ifstream file(file_, std::ios::binary);
|
|
||||||
|
|
||||||
// El fichero no existe
|
|
||||||
if (!file) {
|
|
||||||
if (options.console) {
|
|
||||||
std::cout << "Warning: Unable to open " << file_ << "! Creating new file..." << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crea el fichero en modo escritura (binario)
|
|
||||||
std::ofstream newFile(file_, std::ios::binary);
|
|
||||||
|
|
||||||
if (newFile) {
|
|
||||||
if (options.console) {
|
|
||||||
std::cout << "New " << file_ << " created!" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Guarda la información
|
|
||||||
for (const auto& cheevo : cheevos_list_) {
|
|
||||||
newFile.write(reinterpret_cast<const char*>(&cheevo.completed), sizeof(bool));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (options.console) {
|
|
||||||
std::cerr << "Error: Unable to create " << file_ << "!" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// El fichero existe
|
|
||||||
else {
|
|
||||||
if (options.console) {
|
|
||||||
std::cout << "Reading " << file_ << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carga los datos
|
|
||||||
for (auto& cheevo : cheevos_list_) {
|
|
||||||
file.read(reinterpret_cast<char*>(&cheevo.completed), sizeof(bool));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Guarda el estado de los logros en un fichero
|
|
||||||
void Cheevos::saveToFile() {
|
|
||||||
// Abre el fichero en modo escritura (binario)
|
|
||||||
SDL_IOStream* file = SDL_IOFromFile(this->file_.c_str(), "w+b");
|
|
||||||
if (file != nullptr) {
|
|
||||||
// Guarda la información
|
|
||||||
for (int i = 0; i < (int)cheevos_list_.size(); ++i) {
|
|
||||||
SDL_WriteIO(file, &cheevos_list_[i].completed, sizeof(bool));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cierra el fichero
|
|
||||||
SDL_CloseIO(file);
|
|
||||||
} else {
|
|
||||||
if (options.console) {
|
|
||||||
std::cout << "Error: Unable to save file! " << SDL_GetError() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Devuelve el número total de logros desbloqueados
|
|
||||||
int Cheevos::getTotalUnlockedAchievements() {
|
|
||||||
int count = 0;
|
|
||||||
for (const auto& cheevo : cheevos_list_) {
|
|
||||||
if (cheevo.completed) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Elimina el estado "no obtenible"
|
|
||||||
void Cheevos::clearUnobtainableState() {
|
|
||||||
for (auto& cheevo : cheevos_list_) {
|
|
||||||
cheevo.obtainable = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
#include "global_inputs.h"
|
#include "core/input/global_inputs.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <string> // Para allocator, operator+, char_traits, string
|
#include <string> // Para allocator, operator+, char_traits, string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "input.h" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT
|
#include "core/input/input.hpp" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT
|
||||||
#include "options.h" // Para Options, options, OptionsVideo, Section
|
#include "game/gameplay/options.hpp" // Para Options, options, OptionsVideo, Section
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "ui/notifier.h" // Para Notifier, NotificationText
|
#include "game/ui/notifier.hpp" // Para Notifier, NotificationText
|
||||||
#include "utils.h" // Para stringInVector
|
#include "utils/utils.hpp" // Para stringInVector
|
||||||
|
|
||||||
namespace globalInputs {
|
namespace globalInputs {
|
||||||
void quit() {
|
void quit() {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "input.h"
|
#include "core/input/input.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "mouse.h"
|
#include "core/input/mouse.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace Mouse {
|
namespace Mouse {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "gif.h"
|
#include "core/rendering/gif.hpp"
|
||||||
#include <iostream> // Para std::cout
|
#include <iostream> // Para std::cout
|
||||||
#include <cstring> // Para memcpy, size_t
|
#include <cstring> // Para memcpy, size_t
|
||||||
#include <stdexcept> // Para runtime_error
|
#include <stdexcept> // Para runtime_error
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "opengl_shader.h"
|
#include "core/rendering/opengl/opengl_shader.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../shader_backend.h"
|
#include "core/rendering/shader_backend.hpp"
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <OpenGL/gl3.h>
|
#include <OpenGL/gl3.h>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "screen.h"
|
#include "core/rendering/screen.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <ctype.h> // Para toupper
|
#include <ctype.h> // Para toupper
|
||||||
@@ -9,14 +9,14 @@
|
|||||||
#include <iterator> // Para istreambuf_iterator, operator==
|
#include <iterator> // Para istreambuf_iterator, operator==
|
||||||
#include <string> // Para char_traits, string, operator+, operator==
|
#include <string> // Para char_traits, string, operator+, operator==
|
||||||
|
|
||||||
#include "asset.h" // Para Asset, AssetType
|
#include "core/resources/asset.hpp" // Para Asset, AssetType
|
||||||
#include "mouse.h" // Para updateCursorVisibility
|
#include "core/input/mouse.hpp" // Para updateCursorVisibility
|
||||||
#include "options.h" // Para Options, options, OptionsVideo, Border
|
#include "game/gameplay/options.hpp" // Para Options, options, OptionsVideo, Border
|
||||||
#include "rendering/opengl/opengl_shader.h" // Para OpenGLShader
|
#include "core/rendering/opengl/opengl_shader.hpp" // Para OpenGLShader
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "surface.h" // Para Surface, readPalFile
|
#include "core/rendering/surface.hpp" // Para Surface, readPalFile
|
||||||
#include "text.h" // Para Text
|
#include "core/rendering/text.hpp" // Para Text
|
||||||
#include "ui/notifier.h" // Para Notifier
|
#include "game/ui/notifier.hpp" // Para Notifier
|
||||||
|
|
||||||
// [SINGLETON]
|
// [SINGLETON]
|
||||||
Screen* Screen::screen_ = nullptr;
|
Screen* Screen::screen_ = nullptr;
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "utils.h" // Para Color
|
#include "utils/utils.hpp" // Para Color
|
||||||
struct Surface;
|
struct Surface;
|
||||||
namespace Rendering {
|
namespace Rendering {
|
||||||
class ShaderBackend;
|
class ShaderBackend;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// IWYU pragma: no_include <bits/std_abs.h>
|
// IWYU pragma: no_include <bits/std_abs.h>
|
||||||
#include "surface.h"
|
#include "core/rendering/surface.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
#include <stdexcept> // Para runtime_error
|
#include <stdexcept> // Para runtime_error
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "gif.h" // Para Gif
|
#include "core/rendering/gif.hpp" // Para Gif
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
|
|
||||||
// Carga una paleta desde un archivo .gif
|
// Carga una paleta desde un archivo .gif
|
||||||
Palette loadPalette(const std::string& file_path) {
|
Palette loadPalette(const std::string& file_path) {
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <utility> // Para move
|
#include <utility> // Para move
|
||||||
|
|
||||||
#include "utils.h" // Para PaletteColor
|
#include "utils/utils.hpp" // Para PaletteColor
|
||||||
|
|
||||||
// Alias
|
// Alias
|
||||||
using Palette = std::array<Uint32, 256>;
|
using Palette = std::array<Uint32, 256>;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "sprite/surface_animated_sprite.h"
|
#include "core/rendering/surface_animated_sprite.hpp"
|
||||||
|
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
|
|
||||||
@@ -7,8 +7,8 @@
|
|||||||
#include <sstream> // Para basic_stringstream
|
#include <sstream> // Para basic_stringstream
|
||||||
#include <stdexcept> // Para runtime_error
|
#include <stdexcept> // Para runtime_error
|
||||||
|
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "utils.h" // Para printWithDots
|
#include "utils/utils.hpp" // Para printWithDots
|
||||||
|
|
||||||
// Carga las animaciones en un vector(Animations) desde un fichero
|
// Carga las animaciones en un vector(Animations) desde un fichero
|
||||||
Animations loadAnimationsFromFile(const std::string& file_path) {
|
Animations loadAnimationsFromFile(const std::string& file_path) {
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "sprite/surface_moving_sprite.h" // Para SMovingSprite
|
#include "core/rendering/surface_moving_sprite.hpp" // Para SMovingSprite
|
||||||
class Surface; // lines 9-9
|
class Surface; // lines 9-9
|
||||||
|
|
||||||
struct AnimationData {
|
struct AnimationData {
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "sprite/surface_moving_sprite.h"
|
#include "core/rendering/surface_moving_sprite.hpp"
|
||||||
|
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
SMovingSprite::SMovingSprite(std::shared_ptr<Surface> surface, SDL_FRect pos, SDL_FlipMode flip)
|
SMovingSprite::SMovingSprite(std::shared_ptr<Surface> surface, SDL_FRect pos, SDL_FlipMode flip)
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <memory> // Para shared_ptr
|
#include <memory> // Para shared_ptr
|
||||||
|
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||||
class Surface; // lines 8-8
|
class Surface; // lines 8-8
|
||||||
|
|
||||||
// Clase SMovingSprite. Añade movimiento y flip al sprite
|
// Clase SMovingSprite. Añade movimiento y flip al sprite
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "sprite/surface_sprite.h"
|
#include "core/rendering/surface_sprite.hpp"
|
||||||
|
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
SSprite::SSprite(std::shared_ptr<Surface> surface, float x, float y, float w, float h)
|
SSprite::SSprite(std::shared_ptr<Surface> surface, float x, float y, float w, float h)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "text.h"
|
#include "core/rendering/text.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
@@ -7,10 +7,10 @@
|
|||||||
#include <iostream> // Para cerr
|
#include <iostream> // Para cerr
|
||||||
#include <stdexcept> // Para runtime_error
|
#include <stdexcept> // Para runtime_error
|
||||||
|
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "utils.h" // Para getFileName, stringToColor, printWithDots
|
#include "utils/utils.hpp" // Para getFileName, stringToColor, printWithDots
|
||||||
|
|
||||||
// Llena una estructuta TextFile desde un fichero
|
// Llena una estructuta TextFile desde un fichero
|
||||||
std::shared_ptr<TextFile> loadTextFile(const std::string& file_path) {
|
std::shared_ptr<TextFile> loadTextFile(const std::string& file_path) {
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <memory> // Para shared_ptr, unique_ptr
|
#include <memory> // Para shared_ptr, unique_ptr
|
||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
|
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||||
class Surface; // lines 8-8
|
class Surface; // lines 8-8
|
||||||
|
|
||||||
constexpr int TEXT_COLOR = 1;
|
constexpr int TEXT_COLOR = 1;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#include "texture.h"
|
#include "core/rendering/texture.hpp"
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
#include <string> // Para char_traits, operator<<, string, opera...
|
#include <string> // Para char_traits, operator<<, string, opera...
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "utils.h" // Para getFileName, Color, printWithDots
|
#include "utils/utils.hpp" // Para getFileName, Color, printWithDots
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include "external/stb_image.h" // para stbi_failure_reason, stbi_image_free
|
#include "external/stb_image.h" // para stbi_failure_reason, stbi_image_free
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
#include "asset.h"
|
#include "core/resources/asset.hpp"
|
||||||
#include <algorithm> // Para find_if, max
|
#include <algorithm> // Para find_if, max
|
||||||
#include <fstream> // Para basic_ostream, operator<<, basic_ifstream, endl
|
#include <fstream> // Para basic_ostream, operator<<, basic_ifstream, endl
|
||||||
#include <iostream> // Para cout
|
#include <iostream> // Para cout
|
||||||
#include <string> // Para allocator, char_traits, string, operator+, oper...
|
#include <string> // Para allocator, char_traits, string, operator+, oper...
|
||||||
#include "utils.h" // Para getFileName, printWithDots
|
#include "utils/utils.hpp" // Para getFileName, printWithDots
|
||||||
|
|
||||||
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
|
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
|
||||||
Asset *Asset::asset_ = nullptr;
|
Asset *Asset::asset_ = nullptr;
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <string> // para string, basic_string
|
#include <string> // para string, basic_string
|
||||||
#include <vector> // para vector
|
#include <vector> // para vector
|
||||||
#include "utils.h"
|
#include "utils/utils.hpp"
|
||||||
|
|
||||||
enum class AssetType : int
|
enum class AssetType : int
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "resource.h"
|
#include "core/resources/resource.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <stdlib.h> // Para exit, size_t
|
#include <stdlib.h> // Para exit, size_t
|
||||||
@@ -7,13 +7,13 @@
|
|||||||
#include <iostream> // Para basic_ostream, operator<<, endl, cout
|
#include <iostream> // Para basic_ostream, operator<<, endl, cout
|
||||||
#include <stdexcept> // Para runtime_error
|
#include <stdexcept> // Para runtime_error
|
||||||
|
|
||||||
#include "asset.h" // Para AssetType, Asset
|
#include "core/resources/asset.hpp" // Para AssetType, Asset
|
||||||
#include "external/jail_audio.h" // Para JA_DeleteMusic, JA_DeleteSound, JA_Loa...
|
#include "external/jail_audio.h" // Para JA_DeleteMusic, JA_DeleteSound, JA_Loa...
|
||||||
#include "options.h" // Para Options, OptionsGame, options
|
#include "game/gameplay/options.hpp" // Para Options, OptionsGame, options
|
||||||
#include "room.h" // Para RoomData, loadRoomFile, loadRoomTileFile
|
#include "game/gameplay/room.hpp" // Para RoomData, loadRoomFile, loadRoomTileFile
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "text.h" // Para Text, loadTextFile
|
#include "core/rendering/text.hpp" // Para Text, loadTextFile
|
||||||
#include "utils.h" // Para getFileName, printWithDots, PaletteColor
|
#include "utils/utils.hpp" // Para getFileName, printWithDots, PaletteColor
|
||||||
struct JA_Music_t; // lines 17-17
|
struct JA_Music_t; // lines 17-17
|
||||||
struct JA_Sound_t; // lines 18-18
|
struct JA_Sound_t; // lines 18-18
|
||||||
|
|
||||||
@@ -4,10 +4,10 @@
|
|||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "room.h" // Para room_t
|
#include "game/gameplay/room.hpp" // Para room_t
|
||||||
#include "sprite/surface_animated_sprite.h" // Para AnimationsFileBuffer
|
#include "core/rendering/surface_animated_sprite.hpp" // Para AnimationsFileBuffer
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "text.h" // Para Text, TextFile
|
#include "core/rendering/text.hpp" // Para Text, TextFile
|
||||||
struct JA_Music_t; // lines 11-11
|
struct JA_Music_t; // lines 11-11
|
||||||
struct JA_Sound_t; // lines 12-12
|
struct JA_Sound_t; // lines 12-12
|
||||||
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
#include "debug.h"
|
#include "core/system/debug.hpp"
|
||||||
|
|
||||||
#include <algorithm> // Para max
|
#include <algorithm> // Para max
|
||||||
#include <memory> // Para __shared_ptr_access, shared_ptr
|
#include <memory> // Para __shared_ptr_access, shared_ptr
|
||||||
|
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "text.h" // Para Text
|
#include "core/rendering/text.hpp" // Para Text
|
||||||
#include "utils.h" // Para Color
|
#include "utils/utils.hpp" // Para Color
|
||||||
|
|
||||||
// [SINGLETON]
|
// [SINGLETON]
|
||||||
Debug* Debug::debug_ = nullptr;
|
Debug* Debug::debug_ = nullptr;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "director.h"
|
#include "core/system/director.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <errno.h> // Para errno, EEXIST, EACCES, ENAMETOO...
|
#include <errno.h> // Para errno, EEXIST, EACCES, ENAMETOO...
|
||||||
@@ -11,24 +11,24 @@
|
|||||||
#include <memory> // Para make_unique, unique_ptr
|
#include <memory> // Para make_unique, unique_ptr
|
||||||
#include <string> // Para operator+, allocator, char_traits
|
#include <string> // Para operator+, allocator, char_traits
|
||||||
|
|
||||||
#include "asset.h" // Para Asset, AssetType
|
#include "core/resources/asset.hpp" // Para Asset, AssetType
|
||||||
#include "cheevos.h" // Para Cheevos
|
#include "game/gameplay/cheevos.hpp" // Para Cheevos
|
||||||
#include "debug.h" // Para Debug
|
#include "core/system/debug.hpp" // Para Debug
|
||||||
#include "defines.h" // Para WINDOW_CAPTION
|
#include "utils/defines.hpp" // Para WINDOW_CAPTION
|
||||||
#include "external/jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundV...
|
#include "external/jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundV...
|
||||||
#include "input.h" // Para Input, InputAction
|
#include "core/input/input.hpp" // Para Input, InputAction
|
||||||
#include "options.h" // Para Options, options, OptionsVideo
|
#include "game/gameplay/options.hpp" // Para Options, options, OptionsVideo
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "sections/credits.h" // Para Credits
|
#include "game/scenes/credits.hpp" // Para Credits
|
||||||
#include "sections/ending.h" // Para Ending
|
#include "game/scenes/ending.hpp" // Para Ending
|
||||||
#include "sections/ending2.h" // Para Ending2
|
#include "game/scenes/ending2.hpp" // Para Ending2
|
||||||
#include "sections/game.h" // Para Game, GameMode
|
#include "game/scenes/game.hpp" // Para Game, GameMode
|
||||||
#include "sections/game_over.h" // Para GameOver
|
#include "game/scenes/game_over.hpp" // Para GameOver
|
||||||
#include "sections/loading_screen.h" // Para LoadingScreen
|
#include "game/scenes/loading_screen.hpp" // Para LoadingScreen
|
||||||
#include "sections/logo.h" // Para Logo
|
#include "game/scenes/logo.hpp" // Para Logo
|
||||||
#include "sections/title.h" // Para Title
|
#include "game/scenes/title.hpp" // Para Title
|
||||||
#include "ui/notifier.h" // Para Notifier
|
#include "game/ui/notifier.hpp" // Para Notifier
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
#include "enemy.h"
|
#include "game/entities/enemy.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <stdlib.h> // Para rand
|
#include <stdlib.h> // Para rand
|
||||||
|
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "sprite/surface_animated_sprite.h" // Para SAnimatedSprite
|
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||||
#include "utils.h" // Para stringToColor
|
#include "utils/utils.hpp" // Para stringToColor
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Enemy::Enemy(const EnemyData& enemy)
|
Enemy::Enemy(const EnemyData& enemy)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "item.h"
|
#include "game/entities/item.hpp"
|
||||||
|
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Item::Item(ItemData item)
|
Item::Item(ItemData item)
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
// IWYU pragma: no_include <bits/std_abs.h>
|
// IWYU pragma: no_include <bits/std_abs.h>
|
||||||
#include "player.h"
|
#include "game/entities/player.hpp"
|
||||||
|
|
||||||
#include <algorithm> // Para max, min
|
#include <algorithm> // Para max, min
|
||||||
#include <cmath> // Para ceil, abs
|
#include <cmath> // Para ceil, abs
|
||||||
|
|
||||||
#include "debug.h" // Para Debug
|
#include "core/system/debug.hpp" // Para Debug
|
||||||
#include "defines.h" // Para RoomBorder::BOTTOM, RoomBorder::LEFT, RoomBorder::RIGHT
|
#include "utils/defines.hpp" // Para RoomBorder::BOTTOM, RoomBorder::LEFT, RoomBorder::RIGHT
|
||||||
#include "external/jail_audio.h" // Para JA_PlaySound
|
#include "external/jail_audio.h" // Para JA_PlaySound
|
||||||
#include "input.h" // Para Input, InputAction
|
#include "core/input/input.hpp" // Para Input, InputAction
|
||||||
#include "options.h" // Para Cheat, Options, options
|
#include "game/gameplay/options.hpp" // Para Cheat, Options, options
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "room.h" // Para Room, TileType
|
#include "game/gameplay/room.hpp" // Para Room, TileType
|
||||||
#include "sprite/surface_animated_sprite.h" // Para SAnimatedSprite
|
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Player::Player(const PlayerData& player)
|
Player::Player(const PlayerData& player)
|
||||||
@@ -6,10 +6,10 @@
|
|||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "defines.h" // Para BORDER_TOP, BLOCK
|
#include "utils/defines.hpp" // Para BORDER_TOP, BLOCK
|
||||||
#include "room.h"
|
#include "game/gameplay/room.hpp"
|
||||||
#include "sprite/surface_animated_sprite.h" // Para SAnimatedSprite
|
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||||
#include "utils.h" // Para Color
|
#include "utils/utils.hpp" // Para Color
|
||||||
struct JA_Sound_t; // lines 13-13
|
struct JA_Sound_t; // lines 13-13
|
||||||
|
|
||||||
enum class PlayerState {
|
enum class PlayerState {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "cheevos.h"
|
#include "game/gameplay/cheevos.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <stddef.h> // Para NULL
|
#include <stddef.h> // Para NULL
|
||||||
@@ -6,8 +6,8 @@
|
|||||||
#include <fstream> // Para basic_ostream, operator<<, basic_ofstream
|
#include <fstream> // Para basic_ostream, operator<<, basic_ofstream
|
||||||
#include <iostream> // Para cout, cerr
|
#include <iostream> // Para cout, cerr
|
||||||
|
|
||||||
#include "options.h" // Para Options, options
|
#include "game/gameplay/options.hpp" // Para Options, options
|
||||||
#include "ui/notifier.h" // Para Notifier
|
#include "game/ui/notifier.hpp" // Para Notifier
|
||||||
|
|
||||||
// [SINGLETON]
|
// [SINGLETON]
|
||||||
Cheevos* Cheevos::cheevos_ = nullptr;
|
Cheevos* Cheevos::cheevos_ = nullptr;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "item_tracker.h"
|
#include "game/gameplay/item_tracker.hpp"
|
||||||
|
|
||||||
// [SINGLETON]
|
// [SINGLETON]
|
||||||
ItemTracker* ItemTracker::item_tracker_ = nullptr;
|
ItemTracker* ItemTracker::item_tracker_ = nullptr;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "options.h"
|
#include "game/gameplay/options.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string> // Para string, basic_string
|
#include <string> // Para string, basic_string
|
||||||
|
|
||||||
#include "screen.h" // Para ScreenFilter
|
#include "core/rendering/screen.hpp" // Para ScreenFilter
|
||||||
#include "utils.h" // Para Color, Palette
|
#include "utils/utils.hpp" // Para Color, Palette
|
||||||
|
|
||||||
// Secciones del programa
|
// Secciones del programa
|
||||||
enum class Section {
|
enum class Section {
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
#include "room.h"
|
#include "game/gameplay/room.hpp"
|
||||||
|
|
||||||
#include <exception> // Para exception
|
#include <exception> // Para exception
|
||||||
#include <fstream> // Para basic_ostream, operator<<, basic_istream
|
#include <fstream> // Para basic_ostream, operator<<, basic_istream
|
||||||
#include <iostream> // Para cout, cerr
|
#include <iostream> // Para cout, cerr
|
||||||
#include <sstream> // Para basic_stringstream
|
#include <sstream> // Para basic_stringstream
|
||||||
|
|
||||||
#include "debug.h" // Para Debug
|
#include "core/system/debug.hpp" // Para Debug
|
||||||
#include "defines.h" // Para BLOCK, PLAY_AREA_HEIGHT, PLAY_AREA_WIDTH
|
#include "utils/defines.hpp" // Para BLOCK, PLAY_AREA_HEIGHT, PLAY_AREA_WIDTH
|
||||||
#include "external/jail_audio.h" // Para JA_PlaySound
|
#include "external/jail_audio.h" // Para JA_PlaySound
|
||||||
#include "item_tracker.h" // Para ItemTracker
|
#include "game/gameplay/item_tracker.hpp" // Para ItemTracker
|
||||||
#include "options.h" // Para Options, OptionsStats, options
|
#include "game/gameplay/options.hpp" // Para Options, OptionsStats, options
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "scoreboard.h" // Para ScoreboardData
|
#include "game/gameplay/scoreboard.hpp" // Para ScoreboardData
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "utils.h" // Para LineHorizontal, LineDiagonal, LineVertical
|
#include "utils/utils.hpp" // Para LineHorizontal, LineDiagonal, LineVertical
|
||||||
|
|
||||||
// Carga las variables y texturas desde un fichero de mapa de tiles
|
// Carga las variables y texturas desde un fichero de mapa de tiles
|
||||||
std::vector<int> loadRoomTileFile(const std::string& file_path, bool verbose) {
|
std::vector<int> loadRoomTileFile(const std::string& file_path, bool verbose) {
|
||||||
@@ -6,9 +6,9 @@
|
|||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "enemy.h" // Para EnemyData
|
#include "game/entities/enemy.hpp" // Para EnemyData
|
||||||
#include "item.h" // Para ItemData
|
#include "game/entities/item.hpp" // Para ItemData
|
||||||
#include "utils.h" // Para LineHorizontal, LineDiagonal, LineVertical
|
#include "utils/utils.hpp" // Para LineHorizontal, LineDiagonal, LineVertical
|
||||||
class SSprite; // lines 12-12
|
class SSprite; // lines 12-12
|
||||||
class Surface; // lines 13-13
|
class Surface; // lines 13-13
|
||||||
struct ScoreboardData; // lines 15-15
|
struct ScoreboardData; // lines 15-15
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "room_tracker.h"
|
#include "game/gameplay/room_tracker.hpp"
|
||||||
|
|
||||||
// Comprueba si la habitación ya ha sido visitada
|
// Comprueba si la habitación ya ha sido visitada
|
||||||
bool RoomTracker::hasBeenVisited(const std::string &name)
|
bool RoomTracker::hasBeenVisited(const std::string &name)
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
#include "scoreboard.h"
|
#include "game/gameplay/scoreboard.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include "defines.h" // Para BLOCK
|
#include "utils/defines.hpp" // Para BLOCK
|
||||||
#include "options.h" // Para Options, options, Cheat, OptionsGame
|
#include "game/gameplay/options.hpp" // Para Options, options, Cheat, OptionsGame
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "sprite/surface_animated_sprite.h" // Para SAnimatedSprite
|
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "text.h" // Para Text
|
#include "core/rendering/text.hpp" // Para Text
|
||||||
#include "utils.h" // Para stringToColor
|
#include "utils/utils.hpp" // Para stringToColor
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Scoreboard::Scoreboard(std::shared_ptr<ScoreboardData> data)
|
Scoreboard::Scoreboard(std::shared_ptr<ScoreboardData> data)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "stats.h"
|
#include "game/gameplay/stats.hpp"
|
||||||
#include <fstream> // Para basic_ostream, basic_ifstream, basic_istream
|
#include <fstream> // Para basic_ostream, basic_ifstream, basic_istream
|
||||||
#include <sstream> // Para basic_stringstream
|
#include <sstream> // Para basic_stringstream
|
||||||
#include "options.h" // Para Options, OptionsStats, options
|
#include "game/gameplay/options.hpp" // Para Options, OptionsStats, options
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Stats::Stats(const std::string &file, const std::string &buffer)
|
Stats::Stats(const std::string &file, const std::string &buffer)
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
#include "credits.h"
|
#include "game/scenes/credits.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <algorithm> // Para min
|
#include <algorithm> // Para min
|
||||||
|
|
||||||
#include "defines.h" // Para GAME_SPEED, PLAY_AREA_CENTER_X, PLAY_...
|
#include "utils/defines.hpp" // Para GAME_SPEED, PLAY_AREA_CENTER_X, PLAY_...
|
||||||
#include "global_events.h" // Para check
|
#include "utils/global_events.hpp" // Para check
|
||||||
#include "global_inputs.h" // Para check
|
#include "core/input/global_inputs.hpp" // Para check
|
||||||
#include "options.h" // Para Options, options, OptionsGame, Sectio...
|
#include "game/gameplay/options.hpp" // Para Options, options, OptionsGame, Sectio...
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "sprite/surface_animated_sprite.h" // Para SAnimatedSprite
|
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR
|
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
|
||||||
#include "utils.h" // Para PaletteColor
|
#include "utils/utils.hpp" // Para PaletteColor
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Credits::Credits()
|
Credits::Credits()
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
#include "ending.h"
|
#include "game/scenes/ending.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <algorithm> // Para min
|
#include <algorithm> // Para min
|
||||||
|
|
||||||
#include "defines.h" // Para GAME_SPEED
|
#include "utils/defines.hpp" // Para GAME_SPEED
|
||||||
#include "external/jail_audio.h" // Para JA_SetVolume, JA_PlayMusic, JA_StopMusic
|
#include "external/jail_audio.h" // Para JA_SetVolume, JA_PlayMusic, JA_StopMusic
|
||||||
#include "global_events.h" // Para check
|
#include "utils/global_events.hpp" // Para check
|
||||||
#include "global_inputs.h" // Para check
|
#include "core/input/global_inputs.hpp" // Para check
|
||||||
#include "options.h" // Para Options, options, OptionsGame, SectionS...
|
#include "game/gameplay/options.hpp" // Para Options, options, OptionsGame, SectionS...
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "text.h" // Para Text, TEXT_STROKE
|
#include "core/rendering/text.hpp" // Para Text, TEXT_STROKE
|
||||||
#include "utils.h" // Para PaletteColor
|
#include "utils/utils.hpp" // Para PaletteColor
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Ending::Ending()
|
Ending::Ending()
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
#include "ending2.h"
|
#include "game/scenes/ending2.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <algorithm> // Para max, replace
|
#include <algorithm> // Para max, replace
|
||||||
|
|
||||||
#include "defines.h" // Para GAMECANVAS_CENTER_X, GAMECANVAS_CENTER_Y
|
#include "utils/defines.hpp" // Para GAMECANVAS_CENTER_X, GAMECANVAS_CENTER_Y
|
||||||
#include "external/jail_audio.h" // Para JA_SetVolume, JA_PlayMusic, JA_StopMusic
|
#include "external/jail_audio.h" // Para JA_SetVolume, JA_PlayMusic, JA_StopMusic
|
||||||
#include "global_events.h" // Para check
|
#include "utils/global_events.hpp" // Para check
|
||||||
#include "global_inputs.h" // Para check
|
#include "core/input/global_inputs.hpp" // Para check
|
||||||
#include "options.h" // Para Options, options, OptionsGame, Sectio...
|
#include "game/gameplay/options.hpp" // Para Options, options, OptionsGame, Sectio...
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "sprite/surface_animated_sprite.h" // Para SAnimatedSprite
|
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||||
#include "sprite/surface_moving_sprite.h" // Para SMovingSprite
|
#include "core/rendering/surface_moving_sprite.hpp" // Para SMovingSprite
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "text.h" // Para Text
|
#include "core/rendering/text.hpp" // Para Text
|
||||||
#include "utils.h" // Para PaletteColor, stringToColor
|
#include "utils/utils.hpp" // Para PaletteColor, stringToColor
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Ending2::Ending2()
|
Ending2::Ending2()
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "defines.h" // Para GAMECANVAS_WIDTH, GAMECANVAS_FIRST_QUAR...
|
#include "utils/defines.hpp" // Para GAMECANVAS_WIDTH, GAMECANVAS_FIRST_QUAR...
|
||||||
class SAnimatedSprite; // lines 9-9
|
class SAnimatedSprite; // lines 9-9
|
||||||
class SMovingSprite; // lines 10-10
|
class SMovingSprite; // lines 10-10
|
||||||
|
|
||||||
@@ -1,29 +1,29 @@
|
|||||||
#include "game.h"
|
#include "game/scenes/game.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "asset.h" // Para Asset
|
#include "core/resources/asset.hpp" // Para Asset
|
||||||
#include "cheevos.h" // Para Cheevos
|
#include "game/gameplay/cheevos.hpp" // Para Cheevos
|
||||||
#include "debug.h" // Para Debug
|
#include "core/system/debug.hpp" // Para Debug
|
||||||
#include "defines.h" // Para BLOCK, PLAY_AREA_HEIGHT, RoomBorder::BOTTOM
|
#include "utils/defines.hpp" // Para BLOCK, PLAY_AREA_HEIGHT, RoomBorder::BOTTOM
|
||||||
#include "external/jail_audio.h" // Para JA_PauseMusic, JA_GetMusicState, JA_P...
|
#include "external/jail_audio.h" // Para JA_PauseMusic, JA_GetMusicState, JA_P...
|
||||||
#include "global_events.h" // Para check
|
#include "utils/global_events.hpp" // Para check
|
||||||
#include "global_inputs.h" // Para check
|
#include "core/input/global_inputs.hpp" // Para check
|
||||||
#include "input.h" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT
|
#include "core/input/input.hpp" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT
|
||||||
#include "item_tracker.h" // Para ItemTracker
|
#include "game/gameplay/item_tracker.hpp" // Para ItemTracker
|
||||||
#include "options.h" // Para Options, options, Cheat, SectionState
|
#include "game/gameplay/options.hpp" // Para Options, options, Cheat, SectionState
|
||||||
#include "resource.h" // Para ResourceRoom, Resource
|
#include "core/resources/resource.hpp" // Para ResourceRoom, Resource
|
||||||
#include "room.h" // Para Room, RoomData
|
#include "game/gameplay/room.hpp" // Para Room, RoomData
|
||||||
#include "room_tracker.h" // Para RoomTracker
|
#include "game/gameplay/room_tracker.hpp" // Para RoomTracker
|
||||||
#include "scoreboard.h" // Para ScoreboardData, Scoreboard
|
#include "game/gameplay/scoreboard.hpp" // Para ScoreboardData, Scoreboard
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "stats.h" // Para Stats
|
#include "game/gameplay/stats.hpp" // Para Stats
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR
|
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
|
||||||
#include "ui/notifier.h" // Para Notifier, NotificationText, CHEEVO_NO...
|
#include "game/ui/notifier.hpp" // Para Notifier, NotificationText, CHEEVO_NO...
|
||||||
#include "utils.h" // Para PaletteColor, stringToColor
|
#include "utils/utils.hpp" // Para PaletteColor, stringToColor
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Game::Game(GameMode mode)
|
Game::Game(GameMode mode)
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "player.h" // Para PlayerSpawn
|
#include "game/entities/player.hpp" // Para PlayerSpawn
|
||||||
class Room; // lines 12-12
|
class Room; // lines 12-12
|
||||||
class RoomTracker; // lines 13-13
|
class RoomTracker; // lines 13-13
|
||||||
class Scoreboard; // lines 14-14
|
class Scoreboard; // lines 14-14
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
#include "game_over.h"
|
#include "game/scenes/game_over.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <algorithm> // Para min, max
|
#include <algorithm> // Para min, max
|
||||||
#include <string> // Para basic_string, operator+, to_string
|
#include <string> // Para basic_string, operator+, to_string
|
||||||
|
|
||||||
#include "defines.h" // Para GAMECANVAS_CENTER_X, GAME_SPEED
|
#include "utils/defines.hpp" // Para GAMECANVAS_CENTER_X, GAME_SPEED
|
||||||
#include "external/jail_audio.h" // Para JA_PlayMusic
|
#include "external/jail_audio.h" // Para JA_PlayMusic
|
||||||
#include "global_events.h" // Para check
|
#include "utils/global_events.hpp" // Para check
|
||||||
#include "global_inputs.h" // Para check
|
#include "core/input/global_inputs.hpp" // Para check
|
||||||
#include "options.h" // Para Options, options, OptionsStats, Secti...
|
#include "game/gameplay/options.hpp" // Para Options, options, OptionsStats, Secti...
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "sprite/surface_animated_sprite.h" // Para SAnimatedSprite
|
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||||
#include "text.h" // Para TEXT_CENTER, TEXT_COLOR, Text
|
#include "core/rendering/text.hpp" // Para TEXT_CENTER, TEXT_COLOR, Text
|
||||||
#include "utils.h" // Para PaletteColor, stringToColor
|
#include "utils/utils.hpp" // Para PaletteColor, stringToColor
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
GameOver::GameOver()
|
GameOver::GameOver()
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
#include "loading_screen.h"
|
#include "game/scenes/loading_screen.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <stdlib.h> // Para rand
|
#include <stdlib.h> // Para rand
|
||||||
|
|
||||||
#include "defines.h" // Para GAME_SPEED
|
#include "utils/defines.hpp" // Para GAME_SPEED
|
||||||
#include "external/jail_audio.h" // Para JA_PlayMusic, JA_SetVolume, JA_StopMusic
|
#include "external/jail_audio.h" // Para JA_PlayMusic, JA_SetVolume, JA_StopMusic
|
||||||
#include "global_events.h" // Para check
|
#include "utils/global_events.hpp" // Para check
|
||||||
#include "global_inputs.h" // Para check
|
#include "core/input/global_inputs.hpp" // Para check
|
||||||
#include "options.h" // Para Options, options, SectionState, Options...
|
#include "game/gameplay/options.hpp" // Para Options, options, SectionState, Options...
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "utils.h" // Para stringToColor, PaletteColor
|
#include "utils/utils.hpp" // Para stringToColor, PaletteColor
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
LoadingScreen::LoadingScreen()
|
LoadingScreen::LoadingScreen()
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
#include "logo.h"
|
#include "game/scenes/logo.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include "defines.h" // Para GAME_SPEED
|
#include "utils/defines.hpp" // Para GAME_SPEED
|
||||||
#include "global_events.h" // Para check
|
#include "utils/global_events.hpp" // Para check
|
||||||
#include "global_inputs.h" // Para check
|
#include "core/input/global_inputs.hpp" // Para check
|
||||||
#include "options.h" // Para Options, SectionState, options, Section
|
#include "game/gameplay/options.hpp" // Para Options, SectionState, options, Section
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "utils.h" // Para PaletteColor
|
#include "utils/utils.hpp" // Para PaletteColor
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Logo::Logo()
|
Logo::Logo()
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
#include "title.h"
|
#include "game/scenes/title.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <algorithm> // Para clamp
|
#include <algorithm> // Para clamp
|
||||||
|
|
||||||
#include "cheevos.h" // Para Cheevos, Achievement
|
#include "game/gameplay/cheevos.hpp" // Para Cheevos, Achievement
|
||||||
#include "defines.h" // Para PLAY_AREA_CENTER_X, GAMECANVAS_WIDTH
|
#include "utils/defines.hpp" // Para PLAY_AREA_CENTER_X, GAMECANVAS_WIDTH
|
||||||
#include "global_events.h" // Para check
|
#include "utils/global_events.hpp" // Para check
|
||||||
#include "global_inputs.h" // Para check
|
#include "core/input/global_inputs.hpp" // Para check
|
||||||
#include "input.h" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT, REP...
|
#include "core/input/input.hpp" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT, REP...
|
||||||
#include "options.h" // Para Options, options, SectionState, Section
|
#include "game/gameplay/options.hpp" // Para Options, options, SectionState, Section
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR
|
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
|
||||||
#include "utils.h" // Para stringToColor, PaletteColor, playMusic
|
#include "utils/utils.hpp" // Para stringToColor, PaletteColor, playMusic
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Title::Title()
|
Title::Title()
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "ui/notifier.h"
|
#include "game/ui/notifier.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
@@ -8,13 +8,13 @@
|
|||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "external/jail_audio.h" // Para JA_PlaySound
|
#include "external/jail_audio.h" // Para JA_PlaySound
|
||||||
#include "options.h" // Para Options, options, NotificationPosition
|
#include "game/gameplay/options.hpp" // Para Options, options, NotificationPosition
|
||||||
#include "resource.h" // Para Resource
|
#include "core/resources/resource.hpp" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "core/rendering/screen.hpp" // Para Screen
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||||
#include "surface.h" // Para Surface
|
#include "core/rendering/surface.hpp" // Para Surface
|
||||||
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR
|
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
|
||||||
#include "utils.h" // Para PaletteColor
|
#include "utils/utils.hpp" // Para PaletteColor
|
||||||
|
|
||||||
// [SINGLETON]
|
// [SINGLETON]
|
||||||
Notifier* Notifier::notifier_ = nullptr;
|
Notifier* Notifier::notifier_ = nullptr;
|
||||||
289
source/input.cpp
289
source/input.cpp
@@ -1,289 +0,0 @@
|
|||||||
#include "input.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include <algorithm> // Para find
|
|
||||||
#include <iostream> // Para basic_ostream, operator<<, cout, endl
|
|
||||||
#include <iterator> // Para distance
|
|
||||||
#include <unordered_map> // Para unordered_map, operator==, _Node_cons...
|
|
||||||
#include <utility> // Para pair
|
|
||||||
|
|
||||||
// [SINGLETON]
|
|
||||||
Input* Input::input_ = nullptr;
|
|
||||||
|
|
||||||
// [SINGLETON] Crearemos el objeto con esta función estática
|
|
||||||
void Input::init(const std::string& game_controller_db_path) {
|
|
||||||
Input::input_ = new Input(game_controller_db_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// [SINGLETON] Destruiremos el objeto con esta función estática
|
|
||||||
void Input::destroy() {
|
|
||||||
delete Input::input_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
|
|
||||||
Input* Input::get() {
|
|
||||||
return Input::input_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Input::Input(const std::string& game_controller_db_path)
|
|
||||||
: game_controller_db_path_(game_controller_db_path) {
|
|
||||||
// Busca si hay mandos conectados
|
|
||||||
discoverGameControllers();
|
|
||||||
|
|
||||||
// Inicializa los vectores
|
|
||||||
key_bindings_.resize(static_cast<int>(InputAction::SIZE), KeyBindings());
|
|
||||||
controller_bindings_.resize(num_gamepads_, std::vector<ControllerBindings>(static_cast<int>(InputAction::SIZE), ControllerBindings()));
|
|
||||||
|
|
||||||
// Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
|
|
||||||
button_inputs_ = {InputAction::JUMP};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Asigna inputs a teclas
|
|
||||||
void Input::bindKey(InputAction input, SDL_Scancode code) {
|
|
||||||
key_bindings_.at(static_cast<int>(input)).scancode = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Asigna inputs a botones del mando
|
|
||||||
void Input::bindGameControllerButton(int controller_index, InputAction input, SDL_GamepadButton button) {
|
|
||||||
if (controller_index < num_gamepads_) {
|
|
||||||
controller_bindings_.at(controller_index).at(static_cast<int>(input)).button = button;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Asigna inputs a botones del mando
|
|
||||||
void Input::bindGameControllerButton(int controller_index, InputAction input_target, InputAction input_source) {
|
|
||||||
if (controller_index < num_gamepads_) {
|
|
||||||
controller_bindings_.at(controller_index).at(static_cast<int>(input_target)).button = controller_bindings_.at(controller_index).at(static_cast<int>(input_source)).button;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si un input esta activo
|
|
||||||
bool Input::checkInput(InputAction input, bool repeat, InputDeviceToUse device, int controller_index) {
|
|
||||||
bool success_keyboard = false;
|
|
||||||
bool success_controller = false;
|
|
||||||
const int input_index = static_cast<int>(input);
|
|
||||||
|
|
||||||
if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY) {
|
|
||||||
auto key_states = SDL_GetKeyboardState(nullptr);
|
|
||||||
|
|
||||||
if (repeat) {
|
|
||||||
success_keyboard = key_states[key_bindings_[input_index].scancode] != 0;
|
|
||||||
} else {
|
|
||||||
if (!key_bindings_[input_index].active) {
|
|
||||||
if (key_states[key_bindings_[input_index].scancode] != 0) {
|
|
||||||
key_bindings_[input_index].active = true;
|
|
||||||
success_keyboard = true;
|
|
||||||
} else {
|
|
||||||
success_keyboard = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (key_states[key_bindings_[input_index].scancode] == 0) {
|
|
||||||
key_bindings_[input_index].active = false;
|
|
||||||
}
|
|
||||||
success_keyboard = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_) {
|
|
||||||
if ((device == InputDeviceToUse::CONTROLLER) || (device == InputDeviceToUse::ANY)) {
|
|
||||||
success_controller = checkAxisInput(input, controller_index, repeat);
|
|
||||||
|
|
||||||
if (!success_controller) {
|
|
||||||
if (repeat) {
|
|
||||||
success_controller = SDL_GetGamepadButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) != 0;
|
|
||||||
} else {
|
|
||||||
if (!controller_bindings_.at(controller_index).at(input_index).active) {
|
|
||||||
if (SDL_GetGamepadButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) != 0) {
|
|
||||||
controller_bindings_.at(controller_index).at(input_index).active = true;
|
|
||||||
success_controller = true;
|
|
||||||
} else {
|
|
||||||
success_controller = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (SDL_GetGamepadButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) == 0) {
|
|
||||||
controller_bindings_.at(controller_index).at(input_index).active = false;
|
|
||||||
}
|
|
||||||
success_controller = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (success_keyboard || success_controller);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si hay almenos un input activo
|
|
||||||
bool Input::checkAnyInput(InputDeviceToUse device, int controller_index) {
|
|
||||||
if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY) {
|
|
||||||
const bool *key_states = SDL_GetKeyboardState(nullptr);
|
|
||||||
|
|
||||||
for (int i = 0; i < (int)key_bindings_.size(); ++i) {
|
|
||||||
if (key_states[key_bindings_[i].scancode] != 0 && !key_bindings_[i].active) {
|
|
||||||
key_bindings_[i].active = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gameControllerFound()) {
|
|
||||||
if (device == InputDeviceToUse::CONTROLLER || device == InputDeviceToUse::ANY) {
|
|
||||||
for (int i = 0; i < (int)controller_bindings_.size(); ++i) {
|
|
||||||
if (SDL_GetGamepadButton(connected_controllers_[controller_index], controller_bindings_[controller_index][i].button) != 0 && !controller_bindings_[controller_index][i].active) {
|
|
||||||
controller_bindings_[controller_index][i].active = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Busca si hay mandos conectados
|
|
||||||
bool Input::discoverGameControllers() {
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
// Asegúrate de que el subsistema de gamepads está inicializado
|
|
||||||
if (SDL_WasInit(SDL_INIT_GAMEPAD) != 1) {
|
|
||||||
SDL_InitSubSystem(SDL_INIT_GAMEPAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carga el mapping de mandos desde archivo
|
|
||||||
if (SDL_AddGamepadMappingsFromFile(game_controller_db_path_.c_str()) < 0) {
|
|
||||||
std::cout << "Error, could not load " << game_controller_db_path_.c_str()
|
|
||||||
<< " file: " << SDL_GetError() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// En SDL3 ya no existe SDL_NumJoysticks()
|
|
||||||
// Ahora se obtiene un array dinámico de IDs
|
|
||||||
int num_joysticks = 0;
|
|
||||||
SDL_JoystickID* joystick_ids = SDL_GetJoysticks(&num_joysticks);
|
|
||||||
|
|
||||||
num_joysticks_ = num_joysticks;
|
|
||||||
num_gamepads_ = 0;
|
|
||||||
joysticks_.clear();
|
|
||||||
|
|
||||||
// Recorremos todos los joysticks detectados
|
|
||||||
for (int i = 0; i < num_joysticks_; ++i) {
|
|
||||||
SDL_Joystick* joy = SDL_OpenJoystick(joystick_ids[i]);
|
|
||||||
joysticks_.push_back(joy);
|
|
||||||
|
|
||||||
if (SDL_IsGamepad(joystick_ids[i])) {
|
|
||||||
num_gamepads_++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "\n** LOOKING FOR GAME CONTROLLERS" << std::endl;
|
|
||||||
if (num_joysticks_ != num_gamepads_) {
|
|
||||||
std::cout << "Joysticks found: " << num_joysticks_ << std::endl;
|
|
||||||
std::cout << "Gamepads found : " << num_gamepads_ << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "Gamepads found: " << num_gamepads_ << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_gamepads_ > 0) {
|
|
||||||
found = true;
|
|
||||||
|
|
||||||
for (int i = 0; i < num_joysticks_; i++) {
|
|
||||||
if (SDL_IsGamepad(joystick_ids[i])) {
|
|
||||||
SDL_Gamepad* pad = SDL_OpenGamepad(joystick_ids[i]);
|
|
||||||
if (pad && SDL_GamepadConnected(pad)) {
|
|
||||||
connected_controllers_.push_back(pad);
|
|
||||||
|
|
||||||
const char* name = SDL_GetGamepadName(pad);
|
|
||||||
std::cout << "#" << i << ": " << (name ? name : "Unknown") << std::endl;
|
|
||||||
controller_names_.push_back(name ? name : "Unknown");
|
|
||||||
} else {
|
|
||||||
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// En SDL3 ya no hace falta SDL_GameControllerEventState()
|
|
||||||
// Los eventos de gamepad están siempre habilitados
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_free(joystick_ids);
|
|
||||||
|
|
||||||
std::cout << "\n** FINISHED LOOKING FOR GAME CONTROLLERS" << std::endl;
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Comprueba si hay algun mando conectado
|
|
||||||
bool Input::gameControllerFound() { return num_gamepads_ > 0 ? true : false; }
|
|
||||||
|
|
||||||
// Obten el nombre de un mando de juego
|
|
||||||
std::string Input::getControllerName(int controller_index) const { return num_gamepads_ > 0 ? controller_names_.at(controller_index) : std::string(); }
|
|
||||||
|
|
||||||
// Obten el número de mandos conectados
|
|
||||||
int Input::getNumControllers() const { return num_gamepads_; }
|
|
||||||
|
|
||||||
// Obtiene el indice del controlador a partir de un event.id
|
|
||||||
int Input::getJoyIndex(SDL_JoystickID id) const {
|
|
||||||
for (int i = 0; i < num_joysticks_; ++i) {
|
|
||||||
if (SDL_GetJoystickID(joysticks_[i]) == id) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtiene el SDL_GamepadButton asignado a un input
|
|
||||||
SDL_GamepadButton Input::getControllerBinding(int controller_index, InputAction input) const {
|
|
||||||
return controller_bindings_[controller_index][static_cast<int>(input)].button;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtiene el indice a partir del nombre del mando
|
|
||||||
int Input::getIndexByName(const std::string& name) const {
|
|
||||||
auto it = std::find(controller_names_.begin(), controller_names_.end(), name);
|
|
||||||
return it != controller_names_.end() ? std::distance(controller_names_.begin(), it) : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba el eje del mando
|
|
||||||
bool Input::checkAxisInput(InputAction input, int controller_index, bool repeat) {
|
|
||||||
// Umbral para considerar el eje como activo
|
|
||||||
const Sint16 threshold = 30000;
|
|
||||||
bool axis_active_now = false;
|
|
||||||
|
|
||||||
switch (input) {
|
|
||||||
case InputAction::LEFT:
|
|
||||||
axis_active_now = SDL_GetGamepadAxis(connected_controllers_[controller_index], SDL_GAMEPAD_AXIS_LEFTX) < -threshold;
|
|
||||||
break;
|
|
||||||
case InputAction::RIGHT:
|
|
||||||
axis_active_now = SDL_GetGamepadAxis(connected_controllers_[controller_index], SDL_GAMEPAD_AXIS_LEFTX) > threshold;
|
|
||||||
break;
|
|
||||||
case InputAction::UP:
|
|
||||||
axis_active_now = SDL_GetGamepadAxis(connected_controllers_[controller_index], SDL_GAMEPAD_AXIS_LEFTY) < -threshold;
|
|
||||||
break;
|
|
||||||
case InputAction::DOWN:
|
|
||||||
axis_active_now = SDL_GetGamepadAxis(connected_controllers_[controller_index], SDL_GAMEPAD_AXIS_LEFTY) > threshold;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Referencia al binding correspondiente
|
|
||||||
auto& binding = controller_bindings_.at(controller_index).at(static_cast<int>(input));
|
|
||||||
|
|
||||||
if (repeat) {
|
|
||||||
// Si se permite repetir, simplemente devolvemos el estado actual
|
|
||||||
return axis_active_now;
|
|
||||||
} else {
|
|
||||||
// Si no se permite repetir, aplicamos la lógica de transición
|
|
||||||
if (axis_active_now && !binding.axis_active) {
|
|
||||||
// Transición de inactivo a activo
|
|
||||||
binding.axis_active = true;
|
|
||||||
return true;
|
|
||||||
} else if (!axis_active_now && binding.axis_active) {
|
|
||||||
// Transición de activo a inactivo
|
|
||||||
binding.axis_active = false;
|
|
||||||
}
|
|
||||||
// Mantener el estado actual
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#include "item.h"
|
|
||||||
|
|
||||||
#include "resource.h" // Para Resource
|
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Item::Item(ItemData item)
|
|
||||||
: sprite_(std::make_shared<SSprite>(Resource::get()->getSurface(item.tile_set_file), item.x, item.y, ITEM_SIZE_, ITEM_SIZE_)),
|
|
||||||
change_color_speed(4) {
|
|
||||||
// Inicia variables
|
|
||||||
sprite_->setClip((item.tile % 10) * ITEM_SIZE_, (item.tile / 10) * ITEM_SIZE_, ITEM_SIZE_, ITEM_SIZE_);
|
|
||||||
collider_ = sprite_->getRect();
|
|
||||||
counter_ = item.counter * change_color_speed;
|
|
||||||
|
|
||||||
// Inicializa los colores
|
|
||||||
color_.push_back(item.color1);
|
|
||||||
color_.push_back(item.color1);
|
|
||||||
|
|
||||||
color_.push_back(item.color2);
|
|
||||||
color_.push_back(item.color2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pinta el objeto en pantalla
|
|
||||||
void Item::render() {
|
|
||||||
const int INDEX = (counter_ / change_color_speed) % color_.size();
|
|
||||||
sprite_->render(1, color_.at(INDEX));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtiene su ubicación
|
|
||||||
SDL_FPoint Item::getPos() {
|
|
||||||
const SDL_FPoint p = {sprite_->getX(), sprite_->getY()};
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Asigna los colores del objeto
|
|
||||||
void Item::setColors(Uint8 col1, Uint8 col2) {
|
|
||||||
// Reinicializa el vector de colores
|
|
||||||
color_.clear();
|
|
||||||
|
|
||||||
// Añade el primer color
|
|
||||||
color_.push_back(col1);
|
|
||||||
color_.push_back(col1);
|
|
||||||
|
|
||||||
// Añade el segundo color
|
|
||||||
color_.push_back(col2);
|
|
||||||
color_.push_back(col2);
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
#include "item_tracker.h"
|
|
||||||
|
|
||||||
// [SINGLETON]
|
|
||||||
ItemTracker* ItemTracker::item_tracker_ = nullptr;
|
|
||||||
|
|
||||||
// [SINGLETON] Crearemos el objeto con esta función estática
|
|
||||||
void ItemTracker::init() {
|
|
||||||
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(const std::string& name, SDL_FPoint pos) {
|
|
||||||
// Primero busca si ya hay una entrada con ese nombre
|
|
||||||
if (const int index = findByName(name); index != -1) {
|
|
||||||
// Luego busca si existe ya una entrada con esa posición
|
|
||||||
if (findByPos(index, pos) != -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Añade el objeto a la lista de objetos cogidos
|
|
||||||
void ItemTracker::addItem(const std::string& name, SDL_FPoint 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
|
|
||||||
if (const int index = findByName(name); index != -1) {
|
|
||||||
item_list_.at(index).pos.push_back(pos);
|
|
||||||
}
|
|
||||||
// En caso contrario crea la entrada
|
|
||||||
else {
|
|
||||||
item_list_.emplace_back(name, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Busca una entrada en la lista por nombre
|
|
||||||
int ItemTracker::findByName(const std::string& name) {
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (const auto& l : item_list_) {
|
|
||||||
if (l.name == name) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Busca una entrada en la lista por posición
|
|
||||||
int ItemTracker::findByPos(int index, SDL_FPoint pos) {
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (const auto& l : item_list_[index].pos) {
|
|
||||||
if ((l.x == pos.x) && (l.y == pos.y)) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,7 @@ Empezado en Castalla el 01/07/2022.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "director.h"
|
#include "core/system/director.hpp"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
#include "mouse.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Mouse {
|
|
||||||
Uint32 cursor_hide_time = 3000; // Tiempo en milisegundos para ocultar el cursor
|
|
||||||
Uint32 last_mouse_move_time = 0; // Última vez que el ratón se movió
|
|
||||||
bool cursor_visible = true; // Estado del cursor
|
|
||||||
|
|
||||||
void handleEvent(const SDL_Event& event) {
|
|
||||||
if (event.type == SDL_EVENT_MOUSE_MOTION) {
|
|
||||||
last_mouse_move_time = SDL_GetTicks();
|
|
||||||
if (!cursor_visible) {
|
|
||||||
SDL_ShowCursor();
|
|
||||||
cursor_visible = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateCursorVisibility() {
|
|
||||||
Uint32 current_time = SDL_GetTicks();
|
|
||||||
if (cursor_visible && (current_time - last_mouse_move_time > cursor_hide_time)) {
|
|
||||||
SDL_HideCursor();
|
|
||||||
cursor_visible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace Mouse
|
|
||||||
424
source/options.h
424
source/options.h
@@ -1,424 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string> // Para string, basic_string
|
|
||||||
|
|
||||||
#include "screen.h" // Para ScreenFilter
|
|
||||||
#include "utils.h" // Para Color, Palette
|
|
||||||
|
|
||||||
// Secciones del programa
|
|
||||||
enum class Section {
|
|
||||||
LOGO,
|
|
||||||
LOADING_SCREEN,
|
|
||||||
TITLE,
|
|
||||||
CREDITS,
|
|
||||||
GAME,
|
|
||||||
DEMO,
|
|
||||||
GAME_OVER,
|
|
||||||
ENDING,
|
|
||||||
ENDING2,
|
|
||||||
QUIT
|
|
||||||
};
|
|
||||||
|
|
||||||
// Subsecciones
|
|
||||||
enum class Subsection {
|
|
||||||
NONE,
|
|
||||||
LOGO_TO_INTRO,
|
|
||||||
LOGO_TO_TITLE,
|
|
||||||
TITLE_WITH_LOADING_SCREEN,
|
|
||||||
TITLE_WITHOUT_LOADING_SCREEN
|
|
||||||
};
|
|
||||||
|
|
||||||
// Posiciones de las notificaciones
|
|
||||||
enum class NotificationPosition {
|
|
||||||
UPPER_LEFT,
|
|
||||||
UPPER_CENTER,
|
|
||||||
UPPER_RIGHT,
|
|
||||||
BOTTOM_LEFT,
|
|
||||||
BOTTOM_CENTER,
|
|
||||||
BOTTOM_RIGHT,
|
|
||||||
TOP,
|
|
||||||
BOTTOM,
|
|
||||||
LEFT,
|
|
||||||
RIGHT,
|
|
||||||
CENTER,
|
|
||||||
UNKNOWN,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Tipos de control de teclado
|
|
||||||
enum class ControlScheme {
|
|
||||||
CURSOR,
|
|
||||||
OPQA,
|
|
||||||
WASD
|
|
||||||
};
|
|
||||||
|
|
||||||
// Constantes
|
|
||||||
constexpr int DEFAULT_GAME_WIDTH = 256; // Ancho de la ventana por defecto
|
|
||||||
constexpr int DEFAULT_GAME_HEIGHT = 192; // Alto de la ventana por defecto
|
|
||||||
constexpr int DEFAULT_WINDOW_ZOOM = 2; // Zoom de la ventana por defecto
|
|
||||||
constexpr bool DEFAULT_VIDEO_MODE = false; // Modo de pantalla completa por defecto
|
|
||||||
constexpr ScreenFilter DEFAULT_VIDEO_FILTER = ScreenFilter::NEAREST; // Filtro por defecto
|
|
||||||
constexpr bool DEFAULT_VIDEO_VERTICAL_SYNC = true; // Vsync activado por defecto
|
|
||||||
constexpr bool DEFAULT_VIDEO_SHADERS = false; // Shaders desactivados por defecto
|
|
||||||
constexpr bool DEFAULT_VIDEO_INTEGER_SCALE = true; // Escalado entero activado por defecto
|
|
||||||
constexpr bool DEFAULT_VIDEO_KEEP_ASPECT = true; // Mantener aspecto activado por defecto
|
|
||||||
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 const char* DEFAULT_PALETTE = "zx-spectrum"; // 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
|
|
||||||
constexpr ControlScheme DEFAULT_CONTROL_SCHEME = ControlScheme::CURSOR; // Control por defecto
|
|
||||||
constexpr NotificationPosition DEFAULT_NOTIFICATION_POSITION = NotificationPosition::UPPER_LEFT; // Posición de las notificaciones por defecto
|
|
||||||
constexpr bool DEFAULT_NOTIFICATION_SOUND = true; // Sonido de las notificaciones por defecto
|
|
||||||
const Uint8 DEFAULT_NOTIFICATION_COLOR = static_cast<Uint8>(PaletteColor::BLUE); // Color de las notificaciones por defecto
|
|
||||||
constexpr bool DEFAULT_CONSOLE = false; // Consola desactivada por defecto
|
|
||||||
constexpr const char* DEFAULT_VERSION = "1.10"; // Versión por defecto
|
|
||||||
|
|
||||||
// Estructura para las opciones de las notificaciones
|
|
||||||
struct OptionsNotification {
|
|
||||||
NotificationPosition pos; // Ubicación de las notificaciones en pantalla
|
|
||||||
bool sound; // Indica si las notificaciones suenan
|
|
||||||
Uint8 color; // Color de las notificaciones
|
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
OptionsNotification()
|
|
||||||
: pos(DEFAULT_NOTIFICATION_POSITION),
|
|
||||||
sound(DEFAULT_NOTIFICATION_SOUND),
|
|
||||||
color(DEFAULT_NOTIFICATION_COLOR) {}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
OptionsNotification(NotificationPosition p, bool s, Uint8 c)
|
|
||||||
: pos(p),
|
|
||||||
sound(s),
|
|
||||||
color(c) {}
|
|
||||||
|
|
||||||
// Método que devuelve la posición horizontal
|
|
||||||
NotificationPosition getHorizontalPosition() const {
|
|
||||||
switch (pos) {
|
|
||||||
case NotificationPosition::UPPER_LEFT:
|
|
||||||
case NotificationPosition::BOTTOM_LEFT:
|
|
||||||
return NotificationPosition::LEFT;
|
|
||||||
case NotificationPosition::UPPER_CENTER:
|
|
||||||
case NotificationPosition::BOTTOM_CENTER:
|
|
||||||
return NotificationPosition::CENTER;
|
|
||||||
case NotificationPosition::UPPER_RIGHT:
|
|
||||||
case NotificationPosition::BOTTOM_RIGHT:
|
|
||||||
return NotificationPosition::RIGHT;
|
|
||||||
default:
|
|
||||||
return NotificationPosition::UNKNOWN;
|
|
||||||
}
|
|
||||||
return NotificationPosition::UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Método que devuelve la posición vertical
|
|
||||||
NotificationPosition getVerticalPosition() const {
|
|
||||||
switch (pos) {
|
|
||||||
case NotificationPosition::UPPER_LEFT:
|
|
||||||
case NotificationPosition::UPPER_CENTER:
|
|
||||||
case NotificationPosition::UPPER_RIGHT:
|
|
||||||
return NotificationPosition::TOP;
|
|
||||||
case NotificationPosition::BOTTOM_LEFT:
|
|
||||||
case NotificationPosition::BOTTOM_CENTER:
|
|
||||||
case NotificationPosition::BOTTOM_RIGHT:
|
|
||||||
return NotificationPosition::BOTTOM;
|
|
||||||
default:
|
|
||||||
return NotificationPosition::UNKNOWN;
|
|
||||||
}
|
|
||||||
return NotificationPosition::UNKNOWN;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para saber la seccion y subseccion del programa
|
|
||||||
struct SectionState {
|
|
||||||
Section section;
|
|
||||||
Subsection subsection;
|
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
SectionState()
|
|
||||||
: section(DEFAULT_SECTION),
|
|
||||||
subsection(DEFAULT_SUBSECTION) {}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
SectionState(Section s, Subsection ss)
|
|
||||||
: section(s),
|
|
||||||
subsection(ss) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para albergar trucos
|
|
||||||
struct Cheat {
|
|
||||||
enum class CheatState : bool {
|
|
||||||
DISABLED = false,
|
|
||||||
ENABLED = true
|
|
||||||
};
|
|
||||||
|
|
||||||
CheatState infinite_lives; // Indica si el jugador dispone de vidas infinitas
|
|
||||||
CheatState invincible; // Indica si el jugador puede morir
|
|
||||||
CheatState jail_is_open; // Indica si la Jail está abierta
|
|
||||||
CheatState alternate_skin; // Indica si se usa una skin diferente para el jugador
|
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
Cheat()
|
|
||||||
: infinite_lives(CheatState::DISABLED),
|
|
||||||
invincible(CheatState::DISABLED),
|
|
||||||
jail_is_open(CheatState::DISABLED),
|
|
||||||
alternate_skin(CheatState::DISABLED) {}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Cheat(CheatState il, CheatState i, CheatState je, CheatState as)
|
|
||||||
: infinite_lives(il),
|
|
||||||
invincible(i),
|
|
||||||
jail_is_open(je),
|
|
||||||
alternate_skin(as) {}
|
|
||||||
|
|
||||||
// Método para comprobar si alguno de los tres primeros trucos está activo
|
|
||||||
bool enabled() const {
|
|
||||||
return infinite_lives == CheatState::ENABLED ||
|
|
||||||
invincible == CheatState::ENABLED ||
|
|
||||||
jail_is_open == CheatState::ENABLED;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para almacenar estadísticas
|
|
||||||
struct OptionsStats {
|
|
||||||
int rooms; // Cantidad de habitaciones visitadas
|
|
||||||
int items; // Cantidad de items obtenidos
|
|
||||||
std::string worst_nightmare; // Habitación con más muertes acumuladas
|
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
OptionsStats()
|
|
||||||
: rooms(0),
|
|
||||||
items(0),
|
|
||||||
worst_nightmare("") {}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
OptionsStats(int r, int i, const std::string& wn)
|
|
||||||
: rooms(r),
|
|
||||||
items(i),
|
|
||||||
worst_nightmare(wn) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura con opciones de la ventana
|
|
||||||
struct OptionsWindow {
|
|
||||||
std::string caption = "JailDoctor's Dilemma"; // Texto que aparece en la barra de título 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),
|
|
||||||
max_zoom(DEFAULT_WINDOW_ZOOM) {}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
OptionsWindow(int z, int mz)
|
|
||||||
: zoom(z),
|
|
||||||
max_zoom(mz) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para gestionar el borde de la pantalla
|
|
||||||
struct Border {
|
|
||||||
bool enabled; // Indica si se ha de mostrar el borde
|
|
||||||
float width; // Ancho del borde
|
|
||||||
float height; // Alto del borde
|
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
Border()
|
|
||||||
: enabled(DEFAULT_BORDER_ENABLED),
|
|
||||||
width(DEFAULT_BORDER_WIDTH),
|
|
||||||
height(DEFAULT_BORDER_HEIGHT) {}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Border(bool e, float w, float h)
|
|
||||||
: enabled(e),
|
|
||||||
width(w),
|
|
||||||
height(h) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para las opciones de video
|
|
||||||
struct OptionsVideo {
|
|
||||||
bool fullscreen; // Contiene el valor del modo de pantalla completa
|
|
||||||
ScreenFilter filter; // Filtro usado para el escalado de la imagen
|
|
||||||
bool vertical_sync; // Indica si se quiere usar vsync o no
|
|
||||||
bool shaders; // Indica si se van a usar shaders o no
|
|
||||||
bool integer_scale; // Indica si el escalado de la imagen ha de ser entero en el modo a pantalla completa
|
|
||||||
bool keep_aspect; // Indica si se ha de mantener la relación de aspecto al poner el modo a pantalla completa
|
|
||||||
Border border; // Borde de la pantalla
|
|
||||||
std::string palette; // Paleta de colores a usar en el juego
|
|
||||||
std::string info; // Información sobre el modo de vídeo
|
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
OptionsVideo()
|
|
||||||
: fullscreen(DEFAULT_VIDEO_MODE),
|
|
||||||
filter(DEFAULT_VIDEO_FILTER),
|
|
||||||
vertical_sync(DEFAULT_VIDEO_VERTICAL_SYNC),
|
|
||||||
shaders(DEFAULT_VIDEO_SHADERS),
|
|
||||||
integer_scale(DEFAULT_VIDEO_INTEGER_SCALE),
|
|
||||||
keep_aspect(DEFAULT_VIDEO_KEEP_ASPECT),
|
|
||||||
border(Border()),
|
|
||||||
palette(DEFAULT_PALETTE) {}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
OptionsVideo(Uint32 m, ScreenFilter f, bool vs, bool s, bool is, bool ka, Border b, const std::string& p)
|
|
||||||
: fullscreen(m),
|
|
||||||
filter(f),
|
|
||||||
vertical_sync(vs),
|
|
||||||
shaders(s),
|
|
||||||
integer_scale(is),
|
|
||||||
keep_aspect(ka),
|
|
||||||
border(b),
|
|
||||||
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 {
|
|
||||||
float width; // Ancho de la resolucion del juego
|
|
||||||
float height; // Alto de la resolucion del juego
|
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
OptionsGame()
|
|
||||||
: width(DEFAULT_GAME_WIDTH),
|
|
||||||
height(DEFAULT_GAME_HEIGHT) {}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
OptionsGame(float w, float h)
|
|
||||||
: width(w),
|
|
||||||
height(h) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura con todas las opciones de configuración del programa
|
|
||||||
struct Options {
|
|
||||||
std::string version; // Versión del fichero de configuración. Sirve para saber si las opciones son compatibles
|
|
||||||
bool console; // Indica si ha de mostrar información por la consola de texto
|
|
||||||
Cheat cheats; // Contiene trucos y ventajas para el juego
|
|
||||||
OptionsGame game; // Opciones de juego
|
|
||||||
OptionsVideo video; // Opciones de video
|
|
||||||
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
|
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
Options()
|
|
||||||
: version(DEFAULT_VERSION),
|
|
||||||
console(DEFAULT_CONSOLE),
|
|
||||||
cheats(Cheat()),
|
|
||||||
game(OptionsGame()),
|
|
||||||
video(OptionsVideo()),
|
|
||||||
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, OptionsAudio a, ControlScheme k, SectionState sec)
|
|
||||||
: version(cv),
|
|
||||||
console(c),
|
|
||||||
cheats(ch),
|
|
||||||
game(g),
|
|
||||||
video(v),
|
|
||||||
stats(s),
|
|
||||||
notifications(n),
|
|
||||||
window(sw),
|
|
||||||
audio(a),
|
|
||||||
keys(k),
|
|
||||||
section(sec) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
extern Options options;
|
|
||||||
|
|
||||||
// Crea e inicializa las opciones del programa
|
|
||||||
void initOptions();
|
|
||||||
|
|
||||||
// Carga las opciones desde un fichero
|
|
||||||
bool loadOptionsFromFile(const std::string& file_path);
|
|
||||||
|
|
||||||
// Guarda las opciones a un fichero
|
|
||||||
bool saveOptionsToFile(const std::string& file_path);
|
|
||||||
@@ -1,656 +0,0 @@
|
|||||||
// IWYU pragma: no_include <bits/std_abs.h>
|
|
||||||
#include "player.h"
|
|
||||||
|
|
||||||
#include <algorithm> // Para max, min
|
|
||||||
#include <cmath> // Para ceil, abs
|
|
||||||
|
|
||||||
#include "debug.h" // Para Debug
|
|
||||||
#include "defines.h" // Para RoomBorder::BOTTOM, RoomBorder::LEFT, RoomBorder::RIGHT
|
|
||||||
#include "external/jail_audio.h" // Para JA_PlaySound
|
|
||||||
#include "input.h" // Para Input, InputAction
|
|
||||||
#include "options.h" // Para Cheat, Options, options
|
|
||||||
#include "resource.h" // Para Resource
|
|
||||||
#include "room.h" // Para Room, TileType
|
|
||||||
#include "sprite/surface_animated_sprite.h" // Para SAnimatedSprite
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Player::Player(const PlayerData& player)
|
|
||||||
: room_(player.room) {
|
|
||||||
// Inicializa algunas variables
|
|
||||||
initSprite(player.texture_path, player.animations_path);
|
|
||||||
setColor();
|
|
||||||
applySpawnValues(player.spawn);
|
|
||||||
placeSprite();
|
|
||||||
initSounds();
|
|
||||||
|
|
||||||
previous_state_ = state_;
|
|
||||||
last_position_ = getRect();
|
|
||||||
collider_box_ = getRect();
|
|
||||||
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
|
|
||||||
debug_rect_x_ = {0, 0, 0, 0};
|
|
||||||
debug_rect_y_ = {0, 0, 0, 0};
|
|
||||||
debug_color_ = static_cast<Uint8>(PaletteColor::GREEN);
|
|
||||||
debug_point_ = {0, 0};
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pinta el jugador en pantalla
|
|
||||||
void Player::render() {
|
|
||||||
sprite_->render(1, color_);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
renderDebugInfo();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza las variables del objeto
|
|
||||||
void Player::update() {
|
|
||||||
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}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba las entradas y modifica variables
|
|
||||||
void Player::checkInput() {
|
|
||||||
// Solo comprueba las entradas de dirección cuando está sobre una superficie
|
|
||||||
if (state_ != PlayerState::STANDING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!auto_movement_) {
|
|
||||||
// Comprueba las entradas de desplazamiento lateral solo en el caso de no estar enganchado a una superficie automatica
|
|
||||||
if (Input::get()->checkInput(InputAction::LEFT)) {
|
|
||||||
vx_ = -0.6f;
|
|
||||||
sprite_->setFlip(SDL_FLIP_HORIZONTAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (Input::get()->checkInput(InputAction::RIGHT)) {
|
|
||||||
vx_ = 0.6f;
|
|
||||||
sprite_->setFlip(SDL_FLIP_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
// No se pulsa ninguna dirección
|
|
||||||
vx_ = 0.0f;
|
|
||||||
if (isOnAutoSurface()) {
|
|
||||||
// Si deja de moverse sobre una superficie se engancha
|
|
||||||
auto_movement_ = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { // El movimiento lo proporciona la superficie
|
|
||||||
vx_ = 0.6f * room_->getAutoSurfaceDirection();
|
|
||||||
|
|
||||||
if (vx_ > 0.0f) {
|
|
||||||
sprite_->setFlip(SDL_FLIP_NONE);
|
|
||||||
} else {
|
|
||||||
sprite_->setFlip(SDL_FLIP_HORIZONTAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Input::get()->checkInput(InputAction::JUMP)) {
|
|
||||||
// Solo puede saltar si ademas de estar (state == s_standing)
|
|
||||||
// Esta sobre el suelo, rampa o suelo que se mueve
|
|
||||||
// Esto es para evitar el salto desde el vacio al cambiar de pantalla verticalmente
|
|
||||||
// Ya que se coloca el estado s_standing al cambiar de pantalla
|
|
||||||
|
|
||||||
if (isOnFloor() || isOnAutoSurface()) {
|
|
||||||
setState(PlayerState::JUMPING);
|
|
||||||
vy_ = -MAX_VY_;
|
|
||||||
jump_init_pos_ = y_;
|
|
||||||
jumping_counter_ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si está situado en alguno de los cuatro bordes de la habitación
|
|
||||||
void Player::checkBorders() {
|
|
||||||
if (x_ < PLAY_AREA_LEFT) {
|
|
||||||
border_ = RoomBorder::LEFT;
|
|
||||||
is_on_border_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (x_ + WIDTH_ > PLAY_AREA_RIGHT) {
|
|
||||||
border_ = RoomBorder::RIGHT;
|
|
||||||
is_on_border_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (y_ < PLAY_AREA_TOP) {
|
|
||||||
border_ = RoomBorder::TOP;
|
|
||||||
is_on_border_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (y_ + HEIGHT_ > PLAY_AREA_BOTTOM) {
|
|
||||||
border_ = RoomBorder::BOTTOM;
|
|
||||||
is_on_border_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
is_on_border_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba el estado del jugador
|
|
||||||
void Player::checkState() {
|
|
||||||
// Actualiza las variables en función del estado
|
|
||||||
if (state_ == PlayerState::FALLING) {
|
|
||||||
vx_ = 0.0f;
|
|
||||||
vy_ = MAX_VY_;
|
|
||||||
falling_counter_++;
|
|
||||||
playFallSound();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (state_ == PlayerState::STANDING) {
|
|
||||||
if (previous_state_ == PlayerState::FALLING && falling_counter_ > MAX_FALLING_HEIGHT_) { // Si cae de muy alto, el jugador muere
|
|
||||||
is_alive_ = false;
|
|
||||||
}
|
|
||||||
vy_ = 0.0f;
|
|
||||||
jumping_counter_ = 0;
|
|
||||||
falling_counter_ = 0;
|
|
||||||
if (!isOnFloor() && !isOnAutoSurface() && !isOnDownSlope()) {
|
|
||||||
setState(PlayerState::FALLING);
|
|
||||||
vx_ = 0.0f;
|
|
||||||
vy_ = MAX_VY_;
|
|
||||||
falling_counter_++;
|
|
||||||
playFallSound();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (state_ == PlayerState::JUMPING) {
|
|
||||||
falling_counter_ = 0;
|
|
||||||
jumping_counter_++;
|
|
||||||
playJumpSound();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cambia al jugador de un borde al opuesto. Util para el cambio de pantalla
|
|
||||||
void Player::switchBorders() {
|
|
||||||
switch (border_) {
|
|
||||||
case RoomBorder::TOP:
|
|
||||||
y_ = PLAY_AREA_BOTTOM - HEIGHT_ - BLOCK;
|
|
||||||
setState(PlayerState::STANDING);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RoomBorder::BOTTOM:
|
|
||||||
y_ = PLAY_AREA_TOP;
|
|
||||||
setState(PlayerState::STANDING);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RoomBorder::RIGHT:
|
|
||||||
x_ = PLAY_AREA_LEFT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RoomBorder::LEFT:
|
|
||||||
x_ = PLAY_AREA_RIGHT - WIDTH_;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_on_border_ = false;
|
|
||||||
placeSprite();
|
|
||||||
collider_box_ = getRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aplica gravedad al jugador
|
|
||||||
void Player::applyGravity() {
|
|
||||||
constexpr float GRAVITY_FORCE = 0.035f;
|
|
||||||
|
|
||||||
// La gravedad solo se aplica cuando el jugador esta saltando
|
|
||||||
// Nunca mientras cae o esta de pie
|
|
||||||
if (state_ == PlayerState::JUMPING) {
|
|
||||||
vy_ += GRAVITY_FORCE;
|
|
||||||
if (vy_ > MAX_VY_) {
|
|
||||||
vy_ = MAX_VY_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recalcula la posición del jugador y su animación
|
|
||||||
void Player::move() {
|
|
||||||
last_position_ = {x_, y_}; // Guarda la posicion actual antes de modificarla
|
|
||||||
applyGravity(); // Aplica gravedad al jugador
|
|
||||||
checkState(); // Comprueba el estado del jugador
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
debug_color_ = static_cast<Uint8>(PaletteColor::GREEN);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Se mueve hacia la izquierda
|
|
||||||
if (vx_ < 0.0f) {
|
|
||||||
// Crea el rectangulo de proyección en el eje X para ver si colisiona
|
|
||||||
SDL_FRect proj;
|
|
||||||
proj.x = static_cast<int>(x_ + vx_);
|
|
||||||
proj.y = static_cast<int>(y_);
|
|
||||||
proj.h = HEIGHT_;
|
|
||||||
proj.w = static_cast<int>(std::ceil(std::fabs(vx_))); // Para evitar que tenga un ancho de 0 pixels
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
debug_rect_x_ = proj;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Comprueba la colisión con las superficies
|
|
||||||
const int POS = room_->checkRightSurfaces(&proj);
|
|
||||||
|
|
||||||
// Calcula la nueva posición
|
|
||||||
if (POS == -1) {
|
|
||||||
// Si no hay colisión
|
|
||||||
x_ += vx_;
|
|
||||||
} else {
|
|
||||||
// Si hay colisión lo mueve hasta donde no colisiona
|
|
||||||
x_ = POS + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si ha tocado alguna rampa mientras camina (sin saltar), asciende
|
|
||||||
if (state_ != PlayerState::JUMPING) {
|
|
||||||
const LineVertical LEFT_SIDE = {static_cast<int>(x_), static_cast<int>(y_) + static_cast<int>(HEIGHT_) - 2, static_cast<int>(y_) + static_cast<int>(HEIGHT_) - 1}; // Comprueba solo los dos pixels de abajo
|
|
||||||
const int LY = room_->checkLeftSlopes(&LEFT_SIDE);
|
|
||||||
if (LY > -1) {
|
|
||||||
y_ = LY - HEIGHT_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si está bajando la rampa, recoloca al jugador
|
|
||||||
if (isOnDownSlope() && state_ != PlayerState::JUMPING) {
|
|
||||||
y_ += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Se mueve hacia la derecha
|
|
||||||
else if (vx_ > 0.0f) {
|
|
||||||
// Crea el rectangulo de proyección en el eje X para ver si colisiona
|
|
||||||
SDL_FRect proj;
|
|
||||||
proj.x = x_ + WIDTH_;
|
|
||||||
proj.y = y_;
|
|
||||||
proj.h = HEIGHT_;
|
|
||||||
proj.w = ceil(vx_); // Para evitar que tenga un ancho de 0 pixels
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
debug_rect_x_ = proj;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Comprueba la colisión
|
|
||||||
const int POS = room_->checkLeftSurfaces(&proj);
|
|
||||||
|
|
||||||
// Calcula la nueva posición
|
|
||||||
if (POS == -1) {
|
|
||||||
// Si no hay colisión
|
|
||||||
x_ += vx_;
|
|
||||||
} else {
|
|
||||||
// Si hay colisión lo mueve hasta donde no colisiona
|
|
||||||
x_ = POS - WIDTH_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si ha tocado alguna rampa mientras camina (sin saltar), asciende
|
|
||||||
if (state_ != PlayerState::JUMPING) {
|
|
||||||
const LineVertical RIGHT_SIDE = {static_cast<int>(x_) + static_cast<int>(WIDTH_) - 1, static_cast<int>(y_) + static_cast<int>(HEIGHT_) - 2, static_cast<int>(y_) + static_cast<int>(HEIGHT_) - 1}; // Comprueba solo los dos pixels de abajo
|
|
||||||
const int RY = room_->checkRightSlopes(&RIGHT_SIDE);
|
|
||||||
if (RY > -1) {
|
|
||||||
y_ = RY - HEIGHT_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si está bajando la rampa, recoloca al jugador
|
|
||||||
if (isOnDownSlope() && state_ != PlayerState::JUMPING) {
|
|
||||||
y_ += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si ha salido del suelo, el jugador cae
|
|
||||||
if (state_ == PlayerState::STANDING && !isOnFloor()) {
|
|
||||||
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_ == PlayerState::STANDING && isOnFloor() && !isOnAutoSurface()) {
|
|
||||||
// Deja de estar enganchado a la superficie automatica
|
|
||||||
auto_movement_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Se mueve hacia arriba
|
|
||||||
if (vy_ < 0.0f) {
|
|
||||||
// Crea el rectangulo de proyección en el eje Y para ver si colisiona
|
|
||||||
SDL_FRect proj;
|
|
||||||
proj.x = static_cast<int>(x_);
|
|
||||||
proj.y = static_cast<int>(y_ + vy_);
|
|
||||||
proj.h = static_cast<int>(std::ceil(std::fabs(vy_))); // Para evitar que tenga una altura de 0 pixels
|
|
||||||
proj.w = WIDTH_;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
debug_rect_y_ = proj;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Comprueba la colisión
|
|
||||||
const int POS = room_->checkBottomSurfaces(&proj);
|
|
||||||
|
|
||||||
// Calcula la nueva posición
|
|
||||||
if (POS == -1) {
|
|
||||||
// Si no hay colisión
|
|
||||||
y_ += vy_;
|
|
||||||
} else {
|
|
||||||
// Si hay colisión lo mueve hasta donde no colisiona y entra en caída
|
|
||||||
y_ = POS + 1;
|
|
||||||
setState(PlayerState::FALLING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Se mueve hacia abajo
|
|
||||||
else if (vy_ > 0.0f) {
|
|
||||||
// Crea el rectangulo de proyección en el eje Y para ver si colisiona
|
|
||||||
SDL_FRect proj;
|
|
||||||
proj.x = x_;
|
|
||||||
proj.y = y_ + HEIGHT_;
|
|
||||||
proj.h = ceil(vy_); // Para evitar que tenga una altura de 0 pixels
|
|
||||||
proj.w = WIDTH_;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
debug_rect_y_ = proj;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Comprueba la colisión con las superficies normales y las automáticas
|
|
||||||
const float POS = std::max(room_->checkTopSurfaces(&proj), room_->checkAutoSurfaces(&proj));
|
|
||||||
if (POS > -1) {
|
|
||||||
// Si hay colisión lo mueve hasta donde no colisiona y pasa a estar sobre la superficie
|
|
||||||
y_ = POS - HEIGHT_;
|
|
||||||
setState(PlayerState::STANDING);
|
|
||||||
|
|
||||||
// Deja de estar enganchado a la superficie automatica
|
|
||||||
auto_movement_ = false;
|
|
||||||
} else {
|
|
||||||
// Si no hay colisión con los muros, comprueba la colisión con las rampas
|
|
||||||
if (state_ != PlayerState::JUMPING) { // Las rampas no se miran si se está saltando
|
|
||||||
auto rect = toSDLRect(proj);
|
|
||||||
const LineVertical LEFT_SIDE = {rect.x, rect.y, rect.y + rect.h - 1};
|
|
||||||
const LineVertical RIGHT_SIDE = {rect.x + rect.w - 1, rect.y, rect.y + rect.h - 1};
|
|
||||||
const float POINT = std::max(room_->checkRightSlopes(&RIGHT_SIDE), room_->checkLeftSlopes(&LEFT_SIDE));
|
|
||||||
if (POINT > -1) {
|
|
||||||
// No está saltando y hay colisión con una rampa
|
|
||||||
// Calcula la nueva posición
|
|
||||||
y_ = POINT - HEIGHT_;
|
|
||||||
setState(PlayerState::STANDING);
|
|
||||||
#ifdef DEBUG
|
|
||||||
debug_color_ = static_cast<Uint8>(PaletteColor::YELLOW);
|
|
||||||
debug_point_ = {x_ + (WIDTH_ / 2), POINT};
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
// No está saltando y no hay colisón con una rampa
|
|
||||||
// Calcula la nueva posición
|
|
||||||
y_ += vy_;
|
|
||||||
#ifdef DEBUG
|
|
||||||
debug_color_ = static_cast<Uint8>(PaletteColor::RED);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Esta saltando y no hay colisión con los muros
|
|
||||||
// Calcula la nueva posición
|
|
||||||
y_ += vy_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
placeSprite(); // Coloca el sprite en la nueva posición
|
|
||||||
collider_box_ = getRect(); // Actualiza el rectangulo de colisión
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
Debug::get()->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::get()->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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Establece la animación del jugador
|
|
||||||
void Player::animate() {
|
|
||||||
if (vx_ != 0) {
|
|
||||||
sprite_->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si ha finalizado el salto al alcanzar la altura de inicio
|
|
||||||
void Player::checkJumpEnd() {
|
|
||||||
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(PlayerState::FALLING);
|
|
||||||
vy_ = MAX_VY_;
|
|
||||||
jumping_counter_ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calcula y reproduce el sonido de salto
|
|
||||||
void Player::playJumpSound() {
|
|
||||||
if (jumping_counter_ % 4 == 0) {
|
|
||||||
JA_PlaySound(jumping_sound_[jumping_counter_ / 4]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
Debug::get()->add("JUMP: " + std::to_string(jumping_counter_ / 4));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calcula y reproduce el sonido de caer
|
|
||||||
void Player::playFallSound() {
|
|
||||||
if (falling_counter_ % 4 == 0) {
|
|
||||||
JA_PlaySound(falling_sound_[std::min((falling_counter_ / 4), (int)falling_sound_.size() - 1)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
Debug::get()->add("FALL: " + std::to_string(falling_counter_ / 4));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si el jugador tiene suelo debajo de los pies
|
|
||||||
bool Player::isOnFloor() {
|
|
||||||
bool on_floor = false;
|
|
||||||
bool on_slope_l = false;
|
|
||||||
bool on_slope_r = false;
|
|
||||||
|
|
||||||
updateFeet();
|
|
||||||
|
|
||||||
// Comprueba las superficies
|
|
||||||
for (auto f : under_feet_) {
|
|
||||||
on_floor |= room_->checkTopSurfaces(&f);
|
|
||||||
on_floor |= room_->checkAutoSurfaces(&f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba las rampas
|
|
||||||
on_slope_l = room_->checkLeftSlopes(&under_feet_[0]);
|
|
||||||
on_slope_r = room_->checkRightSlopes(&under_feet_[1]);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (on_floor) {
|
|
||||||
Debug::get()->add("ON_FLOOR");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (on_slope_l) {
|
|
||||||
Debug::get()->add("ON_SLOPE_L: " + std::to_string(under_feet_[0].x) + "," + std::to_string(under_feet_[0].y));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (on_slope_r) {
|
|
||||||
Debug::get()->add("ON_SLOPE_R: " + std::to_string(under_feet_[1].x) + "," + std::to_string(under_feet_[1].y));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return on_floor || on_slope_l || on_slope_r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si el jugador esta sobre una superficie automática
|
|
||||||
bool Player::isOnAutoSurface() {
|
|
||||||
bool on_auto_surface = false;
|
|
||||||
|
|
||||||
updateFeet();
|
|
||||||
|
|
||||||
// Comprueba las superficies
|
|
||||||
for (auto f : under_feet_) {
|
|
||||||
on_auto_surface |= room_->checkAutoSurfaces(&f);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (on_auto_surface) {
|
|
||||||
Debug::get()->add("ON_AUTO_SURFACE");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return on_auto_surface;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si el jugador está sobre una rampa hacia abajo
|
|
||||||
bool Player::isOnDownSlope() {
|
|
||||||
bool on_slope = false;
|
|
||||||
|
|
||||||
updateFeet();
|
|
||||||
|
|
||||||
// Cuando el jugador baja una escalera, se queda volando
|
|
||||||
// Hay que mirar otro pixel más por debajo
|
|
||||||
under_feet_[0].y += 1;
|
|
||||||
under_feet_[1].y += 1;
|
|
||||||
|
|
||||||
// Comprueba las rampas
|
|
||||||
on_slope |= room_->checkLeftSlopes(&under_feet_[0]);
|
|
||||||
on_slope |= room_->checkRightSlopes(&under_feet_[1]);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (on_slope) {
|
|
||||||
Debug::get()->add("ON_DOWN_SLOPE");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return on_slope;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba que el jugador no toque ningun tile de los que matan
|
|
||||||
bool Player::checkKillingTiles() {
|
|
||||||
// Actualiza los puntos de colisión
|
|
||||||
updateColliderPoints();
|
|
||||||
|
|
||||||
// Comprueba si hay contacto y retorna en cuanto se encuentra colisión
|
|
||||||
for (const auto& c : collider_points_) {
|
|
||||||
if (room_->getTile(c) == TileType::KILL) {
|
|
||||||
is_alive_ = false; // Mata al jugador inmediatamente
|
|
||||||
return true; // Retorna en cuanto se detecta una colisión
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // No se encontró ninguna colisión
|
|
||||||
}
|
|
||||||
|
|
||||||
// Establece el color del jugador
|
|
||||||
void Player::setColor() {
|
|
||||||
if (options.cheats.invincible == Cheat::CheatState::ENABLED) {
|
|
||||||
color_ = static_cast<Uint8>(PaletteColor::CYAN);
|
|
||||||
} else if (options.cheats.infinite_lives == Cheat::CheatState::ENABLED) {
|
|
||||||
color_ = static_cast<Uint8>(PaletteColor::YELLOW);
|
|
||||||
} else {
|
|
||||||
color_ = static_cast<Uint8>(PaletteColor::WHITE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza los puntos de colisión
|
|
||||||
void Player::updateColliderPoints() {
|
|
||||||
const SDL_FRect rect = getRect();
|
|
||||||
collider_points_[0] = {rect.x, rect.y};
|
|
||||||
collider_points_[1] = {rect.x + 7, rect.y};
|
|
||||||
collider_points_[2] = {rect.x + 7, rect.y + 7};
|
|
||||||
collider_points_[3] = {rect.x, rect.y + 7};
|
|
||||||
collider_points_[4] = {rect.x, rect.y + 8};
|
|
||||||
collider_points_[5] = {rect.x + 7, rect.y + 8};
|
|
||||||
collider_points_[6] = {rect.x + 7, rect.y + 15};
|
|
||||||
collider_points_[7] = {rect.x, rect.y + 15};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza los puntos de los pies
|
|
||||||
void Player::updateFeet() {
|
|
||||||
const SDL_FPoint p = {x_, y_};
|
|
||||||
|
|
||||||
under_feet_[0] = {p.x, p.y + HEIGHT_};
|
|
||||||
under_feet_[1] = {p.x + 7, p.y + HEIGHT_};
|
|
||||||
|
|
||||||
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(PlayerState value) {
|
|
||||||
previous_state_ = state_;
|
|
||||||
state_ = value;
|
|
||||||
|
|
||||||
checkState();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa los sonidos de salto y caida
|
|
||||||
void Player::initSounds() {
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aplica los valores de spawn al jugador
|
|
||||||
void Player::applySpawnValues(const PlayerSpawn& spawn) {
|
|
||||||
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& surface_path, const std::string& animations_path) {
|
|
||||||
auto surface = Resource::get()->getSurface(surface_path);
|
|
||||||
auto animations = Resource::get()->getAnimations(animations_path);
|
|
||||||
|
|
||||||
sprite_ = std::make_shared<SAnimatedSprite>(surface, 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::get()->getEnabled()) {
|
|
||||||
auto surface = Screen::get()->getRendererSurface();
|
|
||||||
|
|
||||||
// Pinta los underfeet
|
|
||||||
surface->putPixel(under_feet_[0].x, under_feet_[0].y, static_cast<Uint8>(PaletteColor::BRIGHT_MAGENTA));
|
|
||||||
surface->putPixel(under_feet_[1].x, under_feet_[1].y, static_cast<Uint8>(PaletteColor::BRIGHT_MAGENTA));
|
|
||||||
|
|
||||||
// Pinta rectangulo del jugador
|
|
||||||
SDL_FRect rect = getRect();
|
|
||||||
surface->drawRectBorder(&rect, static_cast<Uint8>(PaletteColor::BRIGHT_CYAN));
|
|
||||||
|
|
||||||
// Pinta el rectangulo de movimiento
|
|
||||||
if (vx_ != 0.0f) {
|
|
||||||
surface->fillRect(&debug_rect_x_, static_cast<Uint8>(PaletteColor::BRIGHT_RED));
|
|
||||||
}
|
|
||||||
if (vy_ != 0.0f) {
|
|
||||||
surface->fillRect(&debug_rect_y_, static_cast<Uint8>(PaletteColor::BRIGHT_RED));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pinta el punto de debug
|
|
||||||
surface->putPixel(debug_point_.x, debug_point_.y, rand() % 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // DEBUG
|
|
||||||
@@ -1,462 +0,0 @@
|
|||||||
#include "opengl_shader.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
#include <cstring>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Rendering {
|
|
||||||
|
|
||||||
OpenGLShader::~OpenGLShader() {
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef __APPLE__
|
|
||||||
bool OpenGLShader::initGLExtensions() {
|
|
||||||
glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader");
|
|
||||||
glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource");
|
|
||||||
glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader");
|
|
||||||
glGetShaderiv = (PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv");
|
|
||||||
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog");
|
|
||||||
glDeleteShader = (PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader");
|
|
||||||
glAttachShader = (PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader");
|
|
||||||
glCreateProgram = (PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram");
|
|
||||||
glLinkProgram = (PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram");
|
|
||||||
glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)SDL_GL_GetProcAddress("glValidateProgram");
|
|
||||||
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv");
|
|
||||||
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)SDL_GL_GetProcAddress("glGetProgramInfoLog");
|
|
||||||
glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram");
|
|
||||||
glDeleteProgram = (PFNGLDELETEPROGRAMPROC)SDL_GL_GetProcAddress("glDeleteProgram");
|
|
||||||
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)SDL_GL_GetProcAddress("glGetUniformLocation");
|
|
||||||
glUniform2f = (PFNGLUNIFORM2FPROC)SDL_GL_GetProcAddress("glUniform2f");
|
|
||||||
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)SDL_GL_GetProcAddress("glGenVertexArrays");
|
|
||||||
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)SDL_GL_GetProcAddress("glBindVertexArray");
|
|
||||||
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)SDL_GL_GetProcAddress("glDeleteVertexArrays");
|
|
||||||
glGenBuffers = (PFNGLGENBUFFERSPROC)SDL_GL_GetProcAddress("glGenBuffers");
|
|
||||||
glBindBuffer = (PFNGLBINDBUFFERPROC)SDL_GL_GetProcAddress("glBindBuffer");
|
|
||||||
glBufferData = (PFNGLBUFFERDATAPROC)SDL_GL_GetProcAddress("glBufferData");
|
|
||||||
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)SDL_GL_GetProcAddress("glDeleteBuffers");
|
|
||||||
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer");
|
|
||||||
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray");
|
|
||||||
|
|
||||||
return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv &&
|
|
||||||
glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram &&
|
|
||||||
glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog &&
|
|
||||||
glUseProgram && glDeleteProgram && glGetUniformLocation && glUniform2f &&
|
|
||||||
glGenVertexArrays && glBindVertexArray && glDeleteVertexArrays &&
|
|
||||||
glGenBuffers && glBindBuffer && glBufferData && glDeleteBuffers &&
|
|
||||||
glVertexAttribPointer && glEnableVertexAttribArray;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void OpenGLShader::checkGLError(const char* operation) {
|
|
||||||
GLenum error = glGetError();
|
|
||||||
if (error != GL_NO_ERROR) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Error OpenGL en %s: 0x%x", operation, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint OpenGLShader::compileShader(const std::string& source, GLenum shader_type) {
|
|
||||||
if (source.empty()) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"ERROR: El código fuente del shader está vacío");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint shader_id = glCreateShader(shader_type);
|
|
||||||
if (shader_id == 0) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error al crear shader");
|
|
||||||
checkGLError("glCreateShader");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* sources[1] = {source.c_str()};
|
|
||||||
glShaderSource(shader_id, 1, sources, nullptr);
|
|
||||||
checkGLError("glShaderSource");
|
|
||||||
|
|
||||||
glCompileShader(shader_id);
|
|
||||||
checkGLError("glCompileShader");
|
|
||||||
|
|
||||||
// Verificar compilación
|
|
||||||
GLint compiled = GL_FALSE;
|
|
||||||
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &compiled);
|
|
||||||
if (compiled != GL_TRUE) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Error en compilación del shader");
|
|
||||||
GLint log_length;
|
|
||||||
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
|
|
||||||
if (log_length > 0) {
|
|
||||||
std::vector<char> log(log_length);
|
|
||||||
glGetShaderInfoLog(shader_id, log_length, &log_length, log.data());
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Log de compilación: %s", log.data());
|
|
||||||
}
|
|
||||||
glDeleteShader(shader_id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shader_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint OpenGLShader::linkProgram(GLuint vertex_shader, GLuint fragment_shader) {
|
|
||||||
GLuint program = glCreateProgram();
|
|
||||||
if (program == 0) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Error al crear programa de shaders");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
glAttachShader(program, vertex_shader);
|
|
||||||
checkGLError("glAttachShader(vertex)");
|
|
||||||
glAttachShader(program, fragment_shader);
|
|
||||||
checkGLError("glAttachShader(fragment)");
|
|
||||||
|
|
||||||
glLinkProgram(program);
|
|
||||||
checkGLError("glLinkProgram");
|
|
||||||
|
|
||||||
// Verificar enlace
|
|
||||||
GLint linked = GL_FALSE;
|
|
||||||
glGetProgramiv(program, GL_LINK_STATUS, &linked);
|
|
||||||
if (linked != GL_TRUE) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Error al enlazar programa");
|
|
||||||
GLint log_length;
|
|
||||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
|
|
||||||
if (log_length > 0) {
|
|
||||||
std::vector<char> log(log_length);
|
|
||||||
glGetProgramInfoLog(program, log_length, &log_length, log.data());
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Log de enlace: %s", log.data());
|
|
||||||
}
|
|
||||||
glDeleteProgram(program);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
glValidateProgram(program);
|
|
||||||
checkGLError("glValidateProgram");
|
|
||||||
|
|
||||||
return program;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLShader::createQuadGeometry() {
|
|
||||||
// Datos del quad: posición (x, y) + coordenadas de textura (u, v)
|
|
||||||
// Formato: x, y, u, v
|
|
||||||
float vertices[] = {
|
|
||||||
// Posición // TexCoords
|
|
||||||
-1.0f, -1.0f, 0.0f, 0.0f, // Inferior izquierda
|
|
||||||
1.0f, -1.0f, 1.0f, 0.0f, // Inferior derecha
|
|
||||||
1.0f, 1.0f, 1.0f, 1.0f, // Superior derecha
|
|
||||||
-1.0f, 1.0f, 0.0f, 1.0f // Superior izquierda
|
|
||||||
};
|
|
||||||
|
|
||||||
// Índices para dibujar el quad con dos triángulos
|
|
||||||
unsigned int indices[] = {
|
|
||||||
0, 1, 2, // Primer triángulo
|
|
||||||
2, 3, 0 // Segundo triángulo
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generar y configurar VAO
|
|
||||||
glGenVertexArrays(1, &vao_);
|
|
||||||
glBindVertexArray(vao_);
|
|
||||||
checkGLError("glBindVertexArray");
|
|
||||||
|
|
||||||
// Generar y configurar VBO
|
|
||||||
glGenBuffers(1, &vbo_);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
|
||||||
checkGLError("glBufferData(VBO)");
|
|
||||||
|
|
||||||
// Generar y configurar EBO
|
|
||||||
glGenBuffers(1, &ebo_);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
|
||||||
checkGLError("glBufferData(EBO)");
|
|
||||||
|
|
||||||
// Atributo 0: Posición (2 floats)
|
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
checkGLError("glVertexAttribPointer(position)");
|
|
||||||
|
|
||||||
// Atributo 1: Coordenadas de textura (2 floats)
|
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
|
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
checkGLError("glVertexAttribPointer(texcoord)");
|
|
||||||
|
|
||||||
// Desvincular
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint OpenGLShader::getTextureID(SDL_Texture* texture) {
|
|
||||||
if (!texture) return 1;
|
|
||||||
|
|
||||||
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
|
|
||||||
GLuint texture_id = 0;
|
|
||||||
|
|
||||||
// Intentar obtener ID de textura OpenGL
|
|
||||||
texture_id = (GLuint)(uintptr_t)SDL_GetPointerProperty(props, "SDL.texture.opengl.texture", nullptr);
|
|
||||||
|
|
||||||
if (texture_id == 0) {
|
|
||||||
texture_id = (GLuint)(uintptr_t)SDL_GetPointerProperty(props, "texture.opengl.texture", nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture_id == 0) {
|
|
||||||
texture_id = (GLuint)SDL_GetNumberProperty(props, "SDL.texture.opengl.texture", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture_id == 0) {
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"No se pudo obtener ID de textura OpenGL, usando 1 por defecto");
|
|
||||||
texture_id = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return texture_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OpenGLShader::init(SDL_Window* window,
|
|
||||||
SDL_Texture* texture,
|
|
||||||
const std::string& vertex_source,
|
|
||||||
const std::string& fragment_source) {
|
|
||||||
window_ = window;
|
|
||||||
back_buffer_ = texture;
|
|
||||||
renderer_ = SDL_GetRenderer(window);
|
|
||||||
|
|
||||||
if (!renderer_) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Error: No se pudo obtener el renderer");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtener tamaños
|
|
||||||
SDL_GetWindowSize(window_, &window_width_, &window_height_);
|
|
||||||
SDL_GetTextureSize(back_buffer_, &texture_width_, &texture_height_);
|
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Inicializando shaders: ventana=%dx%d, textura=%.0fx%.0f",
|
|
||||||
window_width_, window_height_, texture_width_, texture_height_);
|
|
||||||
|
|
||||||
// Verificar que es OpenGL
|
|
||||||
const char* renderer_name = SDL_GetRendererName(renderer_);
|
|
||||||
if (!renderer_name || strncmp(renderer_name, "opengl", 6) != 0) {
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Renderer no es OpenGL: %s", renderer_name ? renderer_name : "unknown");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef __APPLE__
|
|
||||||
// Inicializar extensiones OpenGL en Windows/Linux
|
|
||||||
if (!initGLExtensions()) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Error al inicializar extensiones OpenGL");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Limpiar shader anterior si existe
|
|
||||||
if (program_id_ != 0) {
|
|
||||||
glDeleteProgram(program_id_);
|
|
||||||
program_id_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compilar shaders
|
|
||||||
GLuint vertex_shader = compileShader(vertex_source, GL_VERTEX_SHADER);
|
|
||||||
GLuint fragment_shader = compileShader(fragment_source, GL_FRAGMENT_SHADER);
|
|
||||||
|
|
||||||
if (vertex_shader == 0 || fragment_shader == 0) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Error al compilar shaders");
|
|
||||||
if (vertex_shader != 0) glDeleteShader(vertex_shader);
|
|
||||||
if (fragment_shader != 0) glDeleteShader(fragment_shader);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enlazar programa
|
|
||||||
program_id_ = linkProgram(vertex_shader, fragment_shader);
|
|
||||||
|
|
||||||
// Limpiar shaders (ya no necesarios tras el enlace)
|
|
||||||
glDeleteShader(vertex_shader);
|
|
||||||
glDeleteShader(fragment_shader);
|
|
||||||
|
|
||||||
if (program_id_ == 0) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Error al crear programa de shaders");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crear geometría del quad
|
|
||||||
createQuadGeometry();
|
|
||||||
|
|
||||||
// Obtener ubicación del uniform TextureSize
|
|
||||||
glUseProgram(program_id_);
|
|
||||||
texture_size_location_ = glGetUniformLocation(program_id_, "TextureSize");
|
|
||||||
if (texture_size_location_ != -1) {
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Configurando TextureSize uniform: %.0fx%.0f",
|
|
||||||
texture_width_, texture_height_);
|
|
||||||
glUniform2f(texture_size_location_, texture_width_, texture_height_);
|
|
||||||
checkGLError("glUniform2f(TextureSize)");
|
|
||||||
} else {
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Uniform 'TextureSize' no encontrado en shader");
|
|
||||||
}
|
|
||||||
glUseProgram(0);
|
|
||||||
|
|
||||||
is_initialized_ = true;
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"** OpenGL 3.3 Shader Backend inicializado correctamente");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLShader::render() {
|
|
||||||
if (!is_initialized_ || program_id_ == 0) {
|
|
||||||
// Fallback: renderizado SDL normal
|
|
||||||
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255);
|
|
||||||
SDL_SetRenderTarget(renderer_, nullptr);
|
|
||||||
SDL_RenderClear(renderer_);
|
|
||||||
SDL_RenderTexture(renderer_, back_buffer_, nullptr, nullptr);
|
|
||||||
SDL_RenderPresent(renderer_);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtener tamaño actual de ventana (puede haber cambiado)
|
|
||||||
int current_width, current_height;
|
|
||||||
SDL_GetWindowSize(window_, ¤t_width, ¤t_height);
|
|
||||||
|
|
||||||
// Guardar estados OpenGL
|
|
||||||
GLint old_program;
|
|
||||||
glGetIntegerv(GL_CURRENT_PROGRAM, &old_program);
|
|
||||||
|
|
||||||
GLint old_viewport[4];
|
|
||||||
glGetIntegerv(GL_VIEWPORT, old_viewport);
|
|
||||||
|
|
||||||
GLboolean was_texture_enabled = glIsEnabled(GL_TEXTURE_2D);
|
|
||||||
GLint old_texture;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_texture);
|
|
||||||
|
|
||||||
GLint old_vao;
|
|
||||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &old_vao);
|
|
||||||
|
|
||||||
// Preparar renderizado
|
|
||||||
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255);
|
|
||||||
SDL_SetRenderTarget(renderer_, nullptr);
|
|
||||||
SDL_RenderClear(renderer_);
|
|
||||||
|
|
||||||
// Obtener y bindear textura
|
|
||||||
GLuint texture_id = getTextureID(back_buffer_);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
|
||||||
checkGLError("glBindTexture");
|
|
||||||
|
|
||||||
// Usar nuestro programa
|
|
||||||
glUseProgram(program_id_);
|
|
||||||
checkGLError("glUseProgram");
|
|
||||||
|
|
||||||
// Configurar viewport (obtener tamaño lógico de SDL)
|
|
||||||
int logical_w, logical_h;
|
|
||||||
SDL_RendererLogicalPresentation mode;
|
|
||||||
SDL_GetRenderLogicalPresentation(renderer_, &logical_w, &logical_h, &mode);
|
|
||||||
|
|
||||||
if (logical_w == 0 || logical_h == 0) {
|
|
||||||
logical_w = current_width;
|
|
||||||
logical_h = current_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calcular viewport considerando aspect ratio
|
|
||||||
int viewport_x = 0, viewport_y = 0;
|
|
||||||
int viewport_w = current_width, viewport_h = current_height;
|
|
||||||
|
|
||||||
if (mode == SDL_LOGICAL_PRESENTATION_INTEGER_SCALE) {
|
|
||||||
int scale_x = current_width / logical_w;
|
|
||||||
int scale_y = current_height / logical_h;
|
|
||||||
int scale = (scale_x < scale_y) ? scale_x : scale_y;
|
|
||||||
if (scale < 1) scale = 1;
|
|
||||||
|
|
||||||
viewport_w = logical_w * scale;
|
|
||||||
viewport_h = logical_h * scale;
|
|
||||||
viewport_x = (current_width - viewport_w) / 2;
|
|
||||||
viewport_y = (current_height - viewport_h) / 2;
|
|
||||||
} else {
|
|
||||||
float window_aspect = static_cast<float>(current_width) / current_height;
|
|
||||||
float logical_aspect = static_cast<float>(logical_w) / logical_h;
|
|
||||||
|
|
||||||
if (window_aspect > logical_aspect) {
|
|
||||||
viewport_w = static_cast<int>(logical_aspect * current_height);
|
|
||||||
viewport_x = (current_width - viewport_w) / 2;
|
|
||||||
} else {
|
|
||||||
viewport_h = static_cast<int>(current_width / logical_aspect);
|
|
||||||
viewport_y = (current_height - viewport_h) / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glViewport(viewport_x, viewport_y, viewport_w, viewport_h);
|
|
||||||
checkGLError("glViewport");
|
|
||||||
|
|
||||||
// Dibujar quad usando VAO
|
|
||||||
glBindVertexArray(vao_);
|
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
|
||||||
checkGLError("glDrawElements");
|
|
||||||
|
|
||||||
// Presentar
|
|
||||||
SDL_GL_SwapWindow(window_);
|
|
||||||
|
|
||||||
// Restaurar estados OpenGL
|
|
||||||
glUseProgram(old_program);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, old_texture);
|
|
||||||
if (!was_texture_enabled) {
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
}
|
|
||||||
glBindVertexArray(old_vao);
|
|
||||||
glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLShader::setTextureSize(float width, float height) {
|
|
||||||
if (!is_initialized_ || program_id_ == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
texture_width_ = width;
|
|
||||||
texture_height_ = height;
|
|
||||||
|
|
||||||
GLint old_program;
|
|
||||||
glGetIntegerv(GL_CURRENT_PROGRAM, &old_program);
|
|
||||||
|
|
||||||
glUseProgram(program_id_);
|
|
||||||
|
|
||||||
if (texture_size_location_ != -1) {
|
|
||||||
glUniform2f(texture_size_location_, width, height);
|
|
||||||
checkGLError("glUniform2f(TextureSize)");
|
|
||||||
}
|
|
||||||
|
|
||||||
glUseProgram(old_program);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLShader::cleanup() {
|
|
||||||
if (vao_ != 0) {
|
|
||||||
glDeleteVertexArrays(1, &vao_);
|
|
||||||
vao_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vbo_ != 0) {
|
|
||||||
glDeleteBuffers(1, &vbo_);
|
|
||||||
vbo_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ebo_ != 0) {
|
|
||||||
glDeleteBuffers(1, &ebo_);
|
|
||||||
ebo_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (program_id_ != 0) {
|
|
||||||
glDeleteProgram(program_id_);
|
|
||||||
program_id_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_initialized_ = false;
|
|
||||||
window_ = nullptr;
|
|
||||||
renderer_ = nullptr;
|
|
||||||
back_buffer_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Rendering
|
|
||||||
@@ -1,257 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory> // Para shared_ptr
|
|
||||||
#include <string> // Para string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "room.h" // Para room_t
|
|
||||||
#include "sprite/surface_animated_sprite.h" // Para AnimationsFileBuffer
|
|
||||||
#include "surface.h" // Para Surface
|
|
||||||
#include "text.h" // Para Text, TextFile
|
|
||||||
struct JA_Music_t; // lines 11-11
|
|
||||||
struct JA_Sound_t; // lines 12-12
|
|
||||||
|
|
||||||
// Estructura para almacenar ficheros de sonido y su nombre
|
|
||||||
struct ResourceSound {
|
|
||||||
std::string name; // Nombre del sonido
|
|
||||||
JA_Sound_t* sound; // Objeto con el sonido
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
ResourceSound(const std::string& name, JA_Sound_t* sound)
|
|
||||||
: name(name),
|
|
||||||
sound(sound) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para almacenar ficheros musicales y su nombre
|
|
||||||
struct ResourceMusic {
|
|
||||||
std::string name; // Nombre de la musica
|
|
||||||
JA_Music_t* music; // Objeto con la música
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
ResourceMusic(const std::string& name, JA_Music_t* music)
|
|
||||||
: name(name),
|
|
||||||
music(music) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para almacenar objetos Surface y su nombre
|
|
||||||
struct ResourceSurface {
|
|
||||||
std::string name; // Nombre de la surface
|
|
||||||
std::shared_ptr<Surface> surface; // Objeto con la surface
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
ResourceSurface(const std::string& name, std::shared_ptr<Surface> surface)
|
|
||||||
: name(name),
|
|
||||||
surface(surface) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para almacenar objetos Palette y su nombre
|
|
||||||
struct ResourcePalette {
|
|
||||||
std::string name; // Nombre de la surface
|
|
||||||
Palette palette; // Paleta
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
ResourcePalette(const std::string& name, Palette palette)
|
|
||||||
: name(name),
|
|
||||||
palette(palette) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para almacenar ficheros TextFile y su nombre
|
|
||||||
struct ResourceTextFile {
|
|
||||||
std::string name; // Nombre del fichero
|
|
||||||
std::shared_ptr<TextFile> text_file; // Objeto con los descriptores de la fuente de texto
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
ResourceTextFile(const std::string& name, std::shared_ptr<TextFile> text_file)
|
|
||||||
: name(name),
|
|
||||||
text_file(text_file) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para almacenar objetos Text y su nombre
|
|
||||||
struct ResourceText {
|
|
||||||
std::string name; // Nombre del objeto
|
|
||||||
std::shared_ptr<Text> text; // Objeto
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
ResourceText(const std::string& name, std::shared_ptr<Text> text)
|
|
||||||
: name(name),
|
|
||||||
text(text) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para almacenar ficheros animaciones y su nombre
|
|
||||||
struct ResourceAnimation {
|
|
||||||
std::string name; // Nombre del fichero
|
|
||||||
Animations animation; // Objeto con las animaciones
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
ResourceAnimation(const std::string& name, const Animations& animation)
|
|
||||||
: name(name),
|
|
||||||
animation(animation) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para almacenar ficheros con el mapa de tiles de una habitación y su nombre
|
|
||||||
struct ResourceTileMap {
|
|
||||||
std::string name; // Nombre del mapa de tiles
|
|
||||||
std::vector<int> tileMap; // Vector con los indices del mapa de tiles
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
ResourceTileMap(const std::string& name, const std::vector<int>& tileMap)
|
|
||||||
: name(name),
|
|
||||||
tileMap(tileMap) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para almacenar habitaciones y su nombre
|
|
||||||
struct ResourceRoom {
|
|
||||||
std::string name; // Nombre de la habitación
|
|
||||||
std::shared_ptr<RoomData> room; // Habitación
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
ResourceRoom(const std::string& name, std::shared_ptr<RoomData> room)
|
|
||||||
: name(name),
|
|
||||||
room(room) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para llevar la cuenta de los recursos cargados
|
|
||||||
struct ResourceCount {
|
|
||||||
int total; // Número total de recursos
|
|
||||||
int loaded; // Número de recursos cargados
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
ResourceCount()
|
|
||||||
: total(0),
|
|
||||||
loaded(0) {}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
ResourceCount(int total, int loaded)
|
|
||||||
: total(total),
|
|
||||||
loaded(loaded) {}
|
|
||||||
|
|
||||||
// Añade una cantidad a los recursos cargados
|
|
||||||
void add(int amount) {
|
|
||||||
loaded += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtiene el porcentaje de recursos cargados
|
|
||||||
float getPercentage() {
|
|
||||||
return static_cast<float>(loaded) / static_cast<float>(total);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class Resource {
|
|
||||||
private:
|
|
||||||
// [SINGLETON] Objeto resource privado para Don Melitón
|
|
||||||
static Resource* resource_;
|
|
||||||
|
|
||||||
std::vector<ResourceSound> sounds_; // Vector con los sonidos
|
|
||||||
std::vector<ResourceMusic> musics_; // Vector con las musicas
|
|
||||||
std::vector<ResourceSurface> surfaces_; // Vector con las surfaces
|
|
||||||
std::vector<ResourcePalette> palettes_; // Vector con las paletas
|
|
||||||
std::vector<ResourceTextFile> text_files_; // Vector con los ficheros de texto
|
|
||||||
std::vector<ResourceText> texts_; // Vector con los objetos de texto
|
|
||||||
std::vector<ResourceAnimation> animations_; // Vector con las animaciones
|
|
||||||
std::vector<ResourceTileMap> tile_maps_; // Vector con los mapas de tiles
|
|
||||||
std::vector<ResourceRoom> rooms_; // Vector con las habitaciones
|
|
||||||
|
|
||||||
ResourceCount count_; // Contador de recursos
|
|
||||||
|
|
||||||
// Carga los sonidos
|
|
||||||
void loadSounds();
|
|
||||||
|
|
||||||
// Carga las musicas
|
|
||||||
void loadMusics();
|
|
||||||
|
|
||||||
// Carga las surfaces
|
|
||||||
void loadSurfaces();
|
|
||||||
|
|
||||||
// Carga las paletas
|
|
||||||
void loadPalettes();
|
|
||||||
|
|
||||||
// Carga los ficheros de texto
|
|
||||||
void loadTextFiles();
|
|
||||||
|
|
||||||
// Carga las animaciones
|
|
||||||
void loadAnimations();
|
|
||||||
|
|
||||||
// Carga los mapas de tiles
|
|
||||||
void loadTileMaps();
|
|
||||||
|
|
||||||
// Carga las habitaciones
|
|
||||||
void loadRooms();
|
|
||||||
|
|
||||||
// Crea los objetos de texto
|
|
||||||
void createText();
|
|
||||||
|
|
||||||
// Vacia todos los vectores de recursos
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
// Carga todos los recursos
|
|
||||||
void load();
|
|
||||||
|
|
||||||
// Vacía el vector de sonidos
|
|
||||||
void clearSounds();
|
|
||||||
|
|
||||||
// Vacía el vector de musicas
|
|
||||||
void clearMusics();
|
|
||||||
|
|
||||||
// Calcula el numero de recursos para cargar
|
|
||||||
void calculateTotal();
|
|
||||||
|
|
||||||
// Muestra el progreso de carga
|
|
||||||
void renderProgress();
|
|
||||||
|
|
||||||
// Comprueba los eventos
|
|
||||||
void checkEvents();
|
|
||||||
|
|
||||||
// Actualiza el progreso de carga
|
|
||||||
void updateLoadingProgress(int steps = 5);
|
|
||||||
|
|
||||||
// [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos resource desde fuera
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Resource();
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~Resource() = default;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// [SINGLETON] Crearemos el objeto resource con esta función estática
|
|
||||||
static void init();
|
|
||||||
|
|
||||||
// [SINGLETON] Destruiremos el objeto resource con esta función estática
|
|
||||||
static void destroy();
|
|
||||||
|
|
||||||
// [SINGLETON] Con este método obtenemos el objeto resource y podemos trabajar con él
|
|
||||||
static Resource* get();
|
|
||||||
|
|
||||||
// Obtiene el sonido a partir de un nombre
|
|
||||||
JA_Sound_t* getSound(const std::string& name);
|
|
||||||
|
|
||||||
// Obtiene la música a partir de un nombre
|
|
||||||
JA_Music_t* getMusic(const std::string& name);
|
|
||||||
|
|
||||||
// Obtiene la surface a partir de un nombre
|
|
||||||
std::shared_ptr<Surface> getSurface(const std::string& name);
|
|
||||||
|
|
||||||
// Obtiene la paleta a partir de un nombre
|
|
||||||
Palette getPalette(const std::string& name);
|
|
||||||
|
|
||||||
// Obtiene el fichero de texto a partir de un nombre
|
|
||||||
std::shared_ptr<TextFile> getTextFile(const std::string& name);
|
|
||||||
|
|
||||||
// Obtiene el objeto de texto a partir de un nombre
|
|
||||||
std::shared_ptr<Text> getText(const std::string& name);
|
|
||||||
|
|
||||||
// Obtiene la animación a partir de un nombre
|
|
||||||
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<RoomData> getRoom(const std::string& name);
|
|
||||||
|
|
||||||
// Obtiene todas las habitaciones
|
|
||||||
std::vector<ResourceRoom>& getRooms();
|
|
||||||
|
|
||||||
// Recarga todos los recursos
|
|
||||||
void reload();
|
|
||||||
};
|
|
||||||
1118
source/room.cpp
1118
source/room.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,29 +0,0 @@
|
|||||||
#include "room_tracker.h"
|
|
||||||
|
|
||||||
// Comprueba si la habitación ya ha sido visitada
|
|
||||||
bool RoomTracker::hasBeenVisited(const std::string &name)
|
|
||||||
{
|
|
||||||
for (const auto &l : list)
|
|
||||||
{
|
|
||||||
if (l == name)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Añade la habitación a la lista
|
|
||||||
bool RoomTracker::addRoom(const std::string &name)
|
|
||||||
{
|
|
||||||
// Comprueba si la habitación ya ha sido visitada
|
|
||||||
if (!hasBeenVisited(name))
|
|
||||||
{
|
|
||||||
// En caso contrario añádela a la lista
|
|
||||||
list.push_back(name);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
#include "scoreboard.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include "defines.h" // Para BLOCK
|
|
||||||
#include "options.h" // Para Options, options, Cheat, OptionsGame
|
|
||||||
#include "resource.h" // Para Resource
|
|
||||||
#include "screen.h" // Para Screen
|
|
||||||
#include "sprite/surface_animated_sprite.h" // Para SAnimatedSprite
|
|
||||||
#include "surface.h" // Para Surface
|
|
||||||
#include "text.h" // Para Text
|
|
||||||
#include "utils.h" // Para stringToColor
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Scoreboard::Scoreboard(std::shared_ptr<ScoreboardData> data)
|
|
||||||
: item_surface_(Resource::get()->getSurface("items.gif")),
|
|
||||||
data_(data),
|
|
||||||
clock_(ClockData()) {
|
|
||||||
const float SURFACE_WIDTH_ = options.game.width;
|
|
||||||
constexpr float SURFACE_HEIGHT_ = 6.0F * BLOCK;
|
|
||||||
|
|
||||||
// Reserva memoria para los objetos
|
|
||||||
auto player_texture = Resource::get()->getSurface(options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.gif" : "player.gif");
|
|
||||||
auto player_animations = Resource::get()->getAnimations(options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.ani" : "player.ani");
|
|
||||||
player_sprite_ = std::make_shared<SAnimatedSprite>(player_texture, player_animations);
|
|
||||||
player_sprite_->setCurrentAnimation("walk_menu");
|
|
||||||
|
|
||||||
surface_ = std::make_shared<Surface>(SURFACE_WIDTH_, SURFACE_HEIGHT_);
|
|
||||||
surface_dest_ = {0, options.game.height - SURFACE_HEIGHT_, SURFACE_WIDTH_, SURFACE_HEIGHT_};
|
|
||||||
|
|
||||||
// Inicializa las variables
|
|
||||||
counter_ = 0;
|
|
||||||
change_color_speed_ = 4;
|
|
||||||
is_paused_ = false;
|
|
||||||
paused_time_ = 0;
|
|
||||||
paused_time_elapsed_ = 0;
|
|
||||||
items_color_ = stringToColor("white");
|
|
||||||
|
|
||||||
// Inicializa el vector de colores
|
|
||||||
const std::vector<std::string> COLORS = {"blue", "magenta", "green", "cyan", "yellow", "white", "bright_blue", "bright_magenta", "bright_green", "bright_cyan", "bright_yellow", "bright_white"};
|
|
||||||
for (const auto& color : COLORS) {
|
|
||||||
color_.push_back(stringToColor(color));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pinta el objeto en pantalla
|
|
||||||
void Scoreboard::render() {
|
|
||||||
surface_->render(nullptr, &surface_dest_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza las variables del objeto
|
|
||||||
void Scoreboard::update() {
|
|
||||||
counter_++;
|
|
||||||
player_sprite_->update();
|
|
||||||
|
|
||||||
// Actualiza el color de la cantidad de items recogidos
|
|
||||||
updateItemsColor();
|
|
||||||
|
|
||||||
// Dibuja la textura
|
|
||||||
fillTexture();
|
|
||||||
|
|
||||||
if (!is_paused_) {
|
|
||||||
// Si está en pausa no se actualiza el reloj
|
|
||||||
clock_ = getTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtiene el tiempo transcurrido de partida
|
|
||||||
Scoreboard::ClockData Scoreboard::getTime() {
|
|
||||||
const Uint32 timeElapsed = SDL_GetTicks() - data_->ini_clock - paused_time_elapsed_;
|
|
||||||
|
|
||||||
ClockData time;
|
|
||||||
time.hours = timeElapsed / 3600000;
|
|
||||||
time.minutes = timeElapsed / 60000;
|
|
||||||
time.seconds = timeElapsed / 1000;
|
|
||||||
time.separator = (timeElapsed % 1000 <= 500) ? ":" : " ";
|
|
||||||
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pone el marcador en modo pausa
|
|
||||||
void Scoreboard::setPaused(bool value) {
|
|
||||||
if (is_paused_ == value) {
|
|
||||||
// Evita ejecutar lógica si el estado no cambia
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_paused_ = value;
|
|
||||||
|
|
||||||
if (is_paused_) {
|
|
||||||
// Guarda el tiempo actual al pausar
|
|
||||||
paused_time_ = SDL_GetTicks();
|
|
||||||
} else {
|
|
||||||
// Calcula el tiempo pausado acumulado al reanudar
|
|
||||||
paused_time_elapsed_ += SDL_GetTicks() - paused_time_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el color de la cantidad de items recogidos
|
|
||||||
void Scoreboard::updateItemsColor() {
|
|
||||||
if (!data_->jail_is_open) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (counter_ % 20 < 10) {
|
|
||||||
items_color_ = stringToColor("white");
|
|
||||||
} else {
|
|
||||||
items_color_ = stringToColor("magenta");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Devuelve la cantidad de minutos de juego transcurridos
|
|
||||||
int Scoreboard::getMinutes() {
|
|
||||||
return getTime().minutes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja los elementos del marcador en la textura
|
|
||||||
void Scoreboard::fillTexture() {
|
|
||||||
// Empieza a dibujar en la textura
|
|
||||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
||||||
Screen::get()->setRendererSurface(surface_);
|
|
||||||
|
|
||||||
// Limpia la textura
|
|
||||||
surface_->clear(stringToColor("black"));
|
|
||||||
|
|
||||||
// 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_->render(1, color_.at(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Muestra si suena la música
|
|
||||||
if (data_->music) {
|
|
||||||
const Uint8 c = data_->color;
|
|
||||||
SDL_FRect clip = {0, 8, 8, 8};
|
|
||||||
item_surface_->renderWithColorReplace(20 * BLOCK, LINE2, 1, c, &clip);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escribe los textos
|
|
||||||
auto text = Resource::get()->getText("smb2");
|
|
||||||
const std::string TIME_TEXT = 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 ITEMS_TEXT = 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, ITEMS_TEXT, items_color_);
|
|
||||||
text->writeColored(20 * BLOCK, LINE1, " Time ", data_->color);
|
|
||||||
text->writeColored(26 * BLOCK, LINE1, TIME_TEXT, stringToColor("white"));
|
|
||||||
|
|
||||||
const std::string ROOMS_TEXT = 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("white"));
|
|
||||||
text->writeColored(28 * BLOCK, LINE2, ROOMS_TEXT, stringToColor("white"));
|
|
||||||
|
|
||||||
// Deja el renderizador como estaba
|
|
||||||
Screen::get()->setRendererSurface(previuos_renderer);
|
|
||||||
}
|
|
||||||
@@ -1,480 +0,0 @@
|
|||||||
#include "ending.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include <algorithm> // Para min
|
|
||||||
|
|
||||||
#include "defines.h" // Para GAME_SPEED
|
|
||||||
#include "external/jail_audio.h" // Para JA_SetVolume, JA_PlayMusic, JA_StopMusic
|
|
||||||
#include "global_events.h" // Para check
|
|
||||||
#include "global_inputs.h" // Para check
|
|
||||||
#include "options.h" // Para Options, options, OptionsGame, SectionS...
|
|
||||||
#include "resource.h" // Para Resource
|
|
||||||
#include "screen.h" // Para Screen
|
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
|
||||||
#include "surface.h" // Para Surface
|
|
||||||
#include "text.h" // Para Text, TEXT_STROKE
|
|
||||||
#include "utils.h" // Para PaletteColor
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Ending::Ending()
|
|
||||||
: counter_(-1),
|
|
||||||
pre_counter_(0),
|
|
||||||
cover_counter_(0),
|
|
||||||
ticks_(0),
|
|
||||||
current_scene_(0) {
|
|
||||||
options.section.section = Section::ENDING;
|
|
||||||
options.section.subsection = Subsection::NONE;
|
|
||||||
|
|
||||||
// Inicializa los textos
|
|
||||||
iniTexts();
|
|
||||||
|
|
||||||
// Inicializa las imagenes
|
|
||||||
iniPics();
|
|
||||||
|
|
||||||
// Inicializa las escenas
|
|
||||||
iniScenes();
|
|
||||||
|
|
||||||
// Cambia el color del borde
|
|
||||||
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK));
|
|
||||||
|
|
||||||
// Crea la textura para cubrir el texto
|
|
||||||
cover_surface_ = std::make_shared<Surface>(options.game.width, options.game.height + 8);
|
|
||||||
|
|
||||||
// Rellena la textura para la cortinilla
|
|
||||||
fillCoverTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el objeto
|
|
||||||
void Ending::update() {
|
|
||||||
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
|
||||||
if (SDL_GetTicks() - ticks_ > GAME_SPEED) {
|
|
||||||
// Actualiza el contador de ticks
|
|
||||||
ticks_ = SDL_GetTicks();
|
|
||||||
|
|
||||||
// Comprueba las entradas
|
|
||||||
checkInput();
|
|
||||||
|
|
||||||
// Actualiza el contador
|
|
||||||
updateCounters();
|
|
||||||
|
|
||||||
// Actualiza las cortinillas de los elementos
|
|
||||||
updateSpriteCovers();
|
|
||||||
|
|
||||||
// Comprueba si se ha de cambiar de escena
|
|
||||||
checkChangeScene();
|
|
||||||
|
|
||||||
// Actualiza el volumen de la musica
|
|
||||||
updateMusicVolume();
|
|
||||||
|
|
||||||
// Actualiza el objeto Screen
|
|
||||||
Screen::get()->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja el final en pantalla
|
|
||||||
void Ending::render() {
|
|
||||||
// Prepara para empezar a dibujar en la textura de juego
|
|
||||||
Screen::get()->start();
|
|
||||||
|
|
||||||
// Limpia la pantalla
|
|
||||||
Screen::get()->clearSurface(static_cast<Uint8>(PaletteColor::BLACK));
|
|
||||||
|
|
||||||
// Dibuja las imagenes de la escena
|
|
||||||
sprite_pics_.at(current_scene_).image_sprite->render();
|
|
||||||
sprite_pics_.at(current_scene_).cover_sprite->render();
|
|
||||||
|
|
||||||
// Dibuja los textos de la escena
|
|
||||||
for (const auto& ti : scenes_.at(current_scene_).text_index) {
|
|
||||||
if (counter_ > ti.trigger) {
|
|
||||||
sprite_texts_.at(ti.index).image_sprite->render();
|
|
||||||
sprite_texts_.at(ti.index).cover_sprite->render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja la cortinilla de cambio de escena
|
|
||||||
renderCoverTexture();
|
|
||||||
|
|
||||||
// Vuelca el contenido del renderizador en pantalla
|
|
||||||
Screen::get()->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba el manejador de eventos
|
|
||||||
void Ending::checkEvents() {
|
|
||||||
SDL_Event event;
|
|
||||||
while (SDL_PollEvent(&event)) {
|
|
||||||
globalEvents::check(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba las entradas
|
|
||||||
void Ending::checkInput() {
|
|
||||||
globalInputs::check();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa los textos
|
|
||||||
void Ending::iniTexts() {
|
|
||||||
// Vector con los textos
|
|
||||||
std::vector<TextAndPosition> texts;
|
|
||||||
|
|
||||||
// Escena #0
|
|
||||||
texts.push_back({"HE FINALLY MANAGED", 32});
|
|
||||||
texts.push_back({"TO GET TO THE JAIL", 42});
|
|
||||||
texts.push_back({"WITH ALL HIS PROJECTS", 142});
|
|
||||||
texts.push_back({"READY TO BE FREED", 152});
|
|
||||||
|
|
||||||
// Escena #1
|
|
||||||
texts.push_back({"ALL THE JAILERS WERE THERE", 1});
|
|
||||||
texts.push_back({"WAITING FOR THE JAILGAMES", 11});
|
|
||||||
texts.push_back({"TO BE RELEASED", 21});
|
|
||||||
|
|
||||||
texts.push_back({"THERE WERE EVEN BARRULLS AND", 161});
|
|
||||||
texts.push_back({"BEGINNERS AMONG THE CROWD", 171});
|
|
||||||
|
|
||||||
texts.push_back({"BRY WAS CRYING...", 181});
|
|
||||||
|
|
||||||
// Escena #2
|
|
||||||
texts.push_back({"BUT SUDDENLY SOMETHING", 19});
|
|
||||||
texts.push_back({"CAUGHT HIS ATTENTION", 29});
|
|
||||||
|
|
||||||
// Escena #3
|
|
||||||
texts.push_back({"A PILE OF JUNK!", 36});
|
|
||||||
texts.push_back({"FULL OF NON WORKING TRASH!!", 46});
|
|
||||||
|
|
||||||
// Escena #4
|
|
||||||
texts.push_back({"AND THEN,", 36});
|
|
||||||
texts.push_back({"FOURTY NEW PROJECTS", 46});
|
|
||||||
texts.push_back({"WERE BORN...", 158});
|
|
||||||
|
|
||||||
// Crea los sprites
|
|
||||||
sprite_texts_.clear();
|
|
||||||
|
|
||||||
for (const auto& txt : texts) {
|
|
||||||
auto text = Resource::get()->getText("smb2");
|
|
||||||
|
|
||||||
const float WIDTH = text->lenght(txt.caption, 1) + 2 + 2;
|
|
||||||
const float HEIGHT = text->getCharacterSize() + 2 + 2;
|
|
||||||
auto text_color = static_cast<Uint8>(PaletteColor::WHITE);
|
|
||||||
auto shadow_color = static_cast<Uint8>(PaletteColor::BLACK);
|
|
||||||
|
|
||||||
EndingSurface st;
|
|
||||||
|
|
||||||
// Crea la textura
|
|
||||||
st.image_surface = std::make_shared<Surface>(WIDTH, HEIGHT);
|
|
||||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
||||||
Screen::get()->setRendererSurface(st.image_surface);
|
|
||||||
text->writeDX(TEXT_STROKE, 2, 2, txt.caption, 1, text_color, 2, shadow_color);
|
|
||||||
|
|
||||||
// Crea el sprite
|
|
||||||
st.image_sprite = std::make_shared<SSprite>(st.image_surface, 0, 0, st.image_surface->getWidth(), st.image_surface->getHeight());
|
|
||||||
st.image_sprite->setPosition((options.game.width - st.image_surface->getWidth()) / 2, txt.pos);
|
|
||||||
|
|
||||||
// Crea la cover_surface
|
|
||||||
st.cover_surface = std::make_shared<Surface>(WIDTH, HEIGHT + 8);
|
|
||||||
Screen::get()->setRendererSurface(st.cover_surface);
|
|
||||||
|
|
||||||
// Rellena la cover_surface con color transparente
|
|
||||||
st.cover_surface->clear(static_cast<Uint8>(PaletteColor::TRANSPARENT));
|
|
||||||
|
|
||||||
// Crea una malla de 8 pixels de alto
|
|
||||||
auto surface = Screen::get()->getRendererSurface();
|
|
||||||
auto color = static_cast<Uint8>(PaletteColor::BLACK);
|
|
||||||
for (int i = 0; i < WIDTH; i += 2) {
|
|
||||||
surface->putPixel(i, 0, color);
|
|
||||||
surface->putPixel(i, 2, color);
|
|
||||||
surface->putPixel(i, 4, color);
|
|
||||||
surface->putPixel(i, 6, color);
|
|
||||||
|
|
||||||
surface->putPixel(i + 1, 5, color);
|
|
||||||
surface->putPixel(i + 1, 7, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// El resto se rellena de color sólido
|
|
||||||
SDL_FRect rect = {0, 8, WIDTH, HEIGHT};
|
|
||||||
surface->fillRect(&rect, color);
|
|
||||||
|
|
||||||
// Crea el sprite
|
|
||||||
st.cover_sprite = std::make_shared<SSprite>(st.cover_surface, 0, 0, st.cover_surface->getWidth(), st.cover_surface->getHeight() - 8);
|
|
||||||
st.cover_sprite->setPosition((options.game.width - st.cover_surface->getWidth()) / 2, txt.pos);
|
|
||||||
st.cover_sprite->setClip(0, 8, st.cover_surface->getWidth(), st.cover_surface->getHeight());
|
|
||||||
|
|
||||||
// Inicializa variables
|
|
||||||
st.cover_clip_desp = 8;
|
|
||||||
st.cover_clip_height = HEIGHT;
|
|
||||||
|
|
||||||
sprite_texts_.push_back(st);
|
|
||||||
Screen::get()->setRendererSurface(previuos_renderer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa las imagenes
|
|
||||||
void Ending::iniPics() {
|
|
||||||
// Vector con las rutas y la posición
|
|
||||||
std::vector<TextAndPosition> pics;
|
|
||||||
|
|
||||||
pics.push_back({"ending1.gif", 48});
|
|
||||||
pics.push_back({"ending2.gif", 26});
|
|
||||||
pics.push_back({"ending3.gif", 29});
|
|
||||||
pics.push_back({"ending4.gif", 63});
|
|
||||||
pics.push_back({"ending5.gif", 53});
|
|
||||||
|
|
||||||
// Crea los sprites
|
|
||||||
sprite_pics_.clear();
|
|
||||||
|
|
||||||
for (const auto& pic : pics) {
|
|
||||||
EndingSurface sp;
|
|
||||||
|
|
||||||
// Crea la texture
|
|
||||||
sp.image_surface = Resource::get()->getSurface(pic.caption);
|
|
||||||
sp.image_surface->setTransparentColor();
|
|
||||||
const float WIDTH = sp.image_surface->getWidth();
|
|
||||||
const float HEIGHT = sp.image_surface->getHeight();
|
|
||||||
|
|
||||||
// Crea el sprite
|
|
||||||
sp.image_sprite = std::make_shared<SSprite>(sp.image_surface, 0, 0, WIDTH, HEIGHT);
|
|
||||||
sp.image_sprite->setPosition((options.game.width - WIDTH) / 2, pic.pos);
|
|
||||||
|
|
||||||
// Crea la cover_surface
|
|
||||||
sp.cover_surface = std::make_shared<Surface>(WIDTH, HEIGHT + 8);
|
|
||||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
||||||
Screen::get()->setRendererSurface(sp.cover_surface);
|
|
||||||
|
|
||||||
// Rellena la cover_surface con color transparente
|
|
||||||
sp.cover_surface->clear(static_cast<Uint8>(PaletteColor::TRANSPARENT));
|
|
||||||
|
|
||||||
// Crea una malla en los primeros 8 pixels
|
|
||||||
auto surface = Screen::get()->getRendererSurface();
|
|
||||||
auto color = static_cast<Uint8>(PaletteColor::BLACK);
|
|
||||||
for (int i = 0; i < WIDTH; i += 2) {
|
|
||||||
surface->putPixel(i, 0, color);
|
|
||||||
surface->putPixel(i, 2, color);
|
|
||||||
surface->putPixel(i, 4, color);
|
|
||||||
surface->putPixel(i, 6, color);
|
|
||||||
|
|
||||||
surface->putPixel(i + 1, 5, color);
|
|
||||||
surface->putPixel(i + 1, 7, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// El resto se rellena de color sólido
|
|
||||||
SDL_FRect rect = {0.0F, 8.0F, WIDTH, HEIGHT};
|
|
||||||
surface->fillRect(&rect, color);
|
|
||||||
|
|
||||||
// Crea el sprite
|
|
||||||
sp.cover_sprite = std::make_shared<SSprite>(sp.cover_surface, 0, 0, sp.cover_surface->getWidth(), sp.cover_surface->getHeight() - 8);
|
|
||||||
sp.cover_sprite->setPosition((options.game.width - sp.cover_surface->getWidth()) / 2, pic.pos);
|
|
||||||
sp.cover_sprite->setClip(0, 8, sp.cover_surface->getWidth(), sp.cover_surface->getHeight());
|
|
||||||
|
|
||||||
// Inicializa variables
|
|
||||||
sp.cover_clip_desp = 8;
|
|
||||||
sp.cover_clip_height = HEIGHT;
|
|
||||||
|
|
||||||
sprite_pics_.push_back(sp);
|
|
||||||
Screen::get()->setRendererSurface(previuos_renderer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa las escenas
|
|
||||||
void Ending::iniScenes() {
|
|
||||||
// Variable para los tiempos
|
|
||||||
int trigger;
|
|
||||||
constexpr int LAPSE = 80;
|
|
||||||
|
|
||||||
// Crea el contenedor
|
|
||||||
SceneData sc;
|
|
||||||
|
|
||||||
// Inicializa el vector
|
|
||||||
scenes_.clear();
|
|
||||||
|
|
||||||
// Crea la escena #0
|
|
||||||
sc.counter_end = 1000;
|
|
||||||
sc.picture_index = 0;
|
|
||||||
sc.text_index.clear();
|
|
||||||
trigger = 85 * 2;
|
|
||||||
trigger += LAPSE;
|
|
||||||
sc.text_index.push_back({0, trigger});
|
|
||||||
trigger += LAPSE;
|
|
||||||
sc.text_index.push_back({1, trigger});
|
|
||||||
trigger += LAPSE * 3;
|
|
||||||
sc.text_index.push_back({2, trigger});
|
|
||||||
trigger += LAPSE;
|
|
||||||
sc.text_index.push_back({3, trigger});
|
|
||||||
scenes_.push_back(sc);
|
|
||||||
|
|
||||||
// Crea la escena #1
|
|
||||||
sc.counter_end = 1400;
|
|
||||||
sc.picture_index = 1;
|
|
||||||
sc.text_index.clear();
|
|
||||||
trigger = 140 * 2;
|
|
||||||
trigger += LAPSE;
|
|
||||||
sc.text_index.push_back({4, trigger});
|
|
||||||
trigger += LAPSE;
|
|
||||||
sc.text_index.push_back({5, trigger});
|
|
||||||
trigger += LAPSE;
|
|
||||||
sc.text_index.push_back({6, trigger});
|
|
||||||
trigger += LAPSE * 3;
|
|
||||||
sc.text_index.push_back({7, trigger});
|
|
||||||
trigger += LAPSE;
|
|
||||||
sc.text_index.push_back({8, trigger});
|
|
||||||
trigger += LAPSE * 3;
|
|
||||||
sc.text_index.push_back({9, trigger});
|
|
||||||
scenes_.push_back(sc);
|
|
||||||
|
|
||||||
// Crea la escena #2
|
|
||||||
sc.counter_end = 1000;
|
|
||||||
sc.picture_index = 2;
|
|
||||||
sc.text_index.clear();
|
|
||||||
trigger = 148 / 2;
|
|
||||||
trigger += LAPSE;
|
|
||||||
sc.text_index.push_back({10, trigger});
|
|
||||||
trigger += LAPSE;
|
|
||||||
sc.text_index.push_back({11, trigger});
|
|
||||||
scenes_.push_back(sc);
|
|
||||||
|
|
||||||
// Crea la escena #3
|
|
||||||
sc.counter_end = 800;
|
|
||||||
sc.picture_index = 3;
|
|
||||||
sc.text_index.clear();
|
|
||||||
trigger = 87 / 2;
|
|
||||||
trigger += LAPSE;
|
|
||||||
sc.text_index.push_back({12, trigger});
|
|
||||||
trigger += LAPSE / 2;
|
|
||||||
sc.text_index.push_back({13, trigger});
|
|
||||||
scenes_.push_back(sc);
|
|
||||||
|
|
||||||
// Crea la escena #4
|
|
||||||
sc.counter_end = 1000;
|
|
||||||
sc.picture_index = 4;
|
|
||||||
sc.text_index.clear();
|
|
||||||
trigger = 91 * 2;
|
|
||||||
trigger += LAPSE;
|
|
||||||
sc.text_index.push_back({14, trigger});
|
|
||||||
trigger += LAPSE * 2;
|
|
||||||
sc.text_index.push_back({15, trigger});
|
|
||||||
trigger += LAPSE * 3;
|
|
||||||
sc.text_index.push_back({16, trigger});
|
|
||||||
scenes_.push_back(sc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bucle principal
|
|
||||||
void Ending::run() {
|
|
||||||
JA_PlayMusic(Resource::get()->getMusic("ending1.ogg"));
|
|
||||||
|
|
||||||
while (options.section.section == Section::ENDING) {
|
|
||||||
update();
|
|
||||||
checkEvents();
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
|
|
||||||
JA_StopMusic();
|
|
||||||
JA_SetVolume(128);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza los contadores
|
|
||||||
void Ending::updateCounters() {
|
|
||||||
// Incrementa el contador
|
|
||||||
if (pre_counter_ < 200) {
|
|
||||||
pre_counter_++;
|
|
||||||
} else {
|
|
||||||
counter_++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (counter_ > scenes_[current_scene_].counter_end - 100) {
|
|
||||||
cover_counter_++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza las cortinillas de los elementos
|
|
||||||
void Ending::updateSpriteCovers() {
|
|
||||||
// Actualiza la cortinilla de los textos
|
|
||||||
if (counter_ % 4 == 0) {
|
|
||||||
for (auto ti : scenes_.at(current_scene_).text_index) {
|
|
||||||
if (counter_ > ti.trigger) {
|
|
||||||
if (sprite_texts_.at(ti.index).cover_clip_desp > 0) {
|
|
||||||
sprite_texts_.at(ti.index).cover_clip_desp -= 2;
|
|
||||||
} else if (sprite_texts_.at(ti.index).cover_clip_height > 0) {
|
|
||||||
sprite_texts_.at(ti.index).cover_clip_height -= 2;
|
|
||||||
sprite_texts_.at(ti.index).cover_sprite->setY(sprite_texts_.at(ti.index).cover_sprite->getY() + 2);
|
|
||||||
}
|
|
||||||
sprite_texts_.at(ti.index).cover_sprite->setClip(0, sprite_texts_.at(ti.index).cover_clip_desp, sprite_texts_.at(ti.index).cover_sprite->getWidth(), sprite_texts_.at(ti.index).cover_clip_height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza la cortinilla de las imágenes
|
|
||||||
if (counter_ % 2 == 0) {
|
|
||||||
if (sprite_pics_.at(current_scene_).cover_clip_desp > 0) {
|
|
||||||
sprite_pics_.at(current_scene_).cover_clip_desp -= 2;
|
|
||||||
} else if (sprite_pics_.at(current_scene_).cover_clip_height > 0) {
|
|
||||||
sprite_pics_.at(current_scene_).cover_clip_height -= 2;
|
|
||||||
if (sprite_pics_.at(current_scene_).cover_clip_height < 0) {
|
|
||||||
sprite_pics_.at(current_scene_).cover_clip_height = 0;
|
|
||||||
}
|
|
||||||
sprite_pics_.at(current_scene_).cover_sprite->setY(sprite_pics_.at(current_scene_).cover_sprite->getY() + 2);
|
|
||||||
}
|
|
||||||
sprite_pics_.at(current_scene_).cover_sprite->setClip(0, sprite_pics_.at(current_scene_).cover_clip_desp, sprite_pics_.at(current_scene_).cover_sprite->getWidth(), sprite_pics_.at(current_scene_).cover_clip_height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si se ha de cambiar de escena
|
|
||||||
void Ending::checkChangeScene() {
|
|
||||||
if (counter_ > scenes_[current_scene_].counter_end) {
|
|
||||||
current_scene_++;
|
|
||||||
counter_ = 0;
|
|
||||||
cover_counter_ = 0;
|
|
||||||
if (current_scene_ == 5) {
|
|
||||||
// Termina el bucle
|
|
||||||
options.section.section = Section::ENDING2;
|
|
||||||
|
|
||||||
// Mantiene los valores anteriores
|
|
||||||
current_scene_ = 4;
|
|
||||||
cover_counter_ = 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rellena la textura para la cortinilla
|
|
||||||
void Ending::fillCoverTexture() {
|
|
||||||
// Rellena la textura que cubre el texto con color transparente
|
|
||||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
||||||
Screen::get()->setRendererSurface(cover_surface_);
|
|
||||||
cover_surface_->clear(static_cast<Uint8>(PaletteColor::TRANSPARENT));
|
|
||||||
|
|
||||||
// Los primeros 8 pixels crea una malla
|
|
||||||
const Uint8 color = static_cast<Uint8>(PaletteColor::BLACK);
|
|
||||||
auto surface = Screen::get()->getRendererSurface();
|
|
||||||
for (int i = 0; i < 256; i += 2) {
|
|
||||||
surface->putPixel(i + 0, options.game.height + 0, color);
|
|
||||||
surface->putPixel(i + 1, options.game.height + 1, color);
|
|
||||||
surface->putPixel(i + 0, options.game.height + 2, color);
|
|
||||||
surface->putPixel(i + 1, options.game.height + 3, color);
|
|
||||||
|
|
||||||
surface->putPixel(i, options.game.height + 4, color);
|
|
||||||
surface->putPixel(i, options.game.height + 6, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// El resto se rellena de color sólido
|
|
||||||
SDL_FRect rect = {0, 0, 256, options.game.height};
|
|
||||||
surface->fillRect(&rect, color);
|
|
||||||
|
|
||||||
Screen::get()->setRendererSurface(previuos_renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja la cortinilla de cambio de escena
|
|
||||||
void Ending::renderCoverTexture() {
|
|
||||||
if (cover_counter_ > 0) {
|
|
||||||
// Dibuja la textura que cubre el texto
|
|
||||||
const int OFFSET = std::min(cover_counter_, 100);
|
|
||||||
SDL_FRect srcRect = {0.0F, 200.0F - (cover_counter_ * 2.0F), 256.0F, OFFSET * 2.0F};
|
|
||||||
SDL_FRect dstRect = {0.0F, 0.0F, 256.0F, OFFSET * 2.0F};
|
|
||||||
cover_surface_->render(&srcRect, &dstRect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el volumen de la musica
|
|
||||||
void Ending::updateMusicVolume() {
|
|
||||||
if (current_scene_ == 4 && cover_counter_ > 0) {
|
|
||||||
const float step = (100.0f - cover_counter_) / 100.0f;
|
|
||||||
const int volume = 128 * step;
|
|
||||||
JA_SetVolume(volume);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,492 +0,0 @@
|
|||||||
#include "ending2.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include <algorithm> // Para max, replace
|
|
||||||
|
|
||||||
#include "defines.h" // Para GAMECANVAS_CENTER_X, GAMECANVAS_CENTER_Y
|
|
||||||
#include "external/jail_audio.h" // Para JA_SetVolume, JA_PlayMusic, JA_StopMusic
|
|
||||||
#include "global_events.h" // Para check
|
|
||||||
#include "global_inputs.h" // Para check
|
|
||||||
#include "options.h" // Para Options, options, OptionsGame, Sectio...
|
|
||||||
#include "resource.h" // Para Resource
|
|
||||||
#include "screen.h" // Para Screen
|
|
||||||
#include "sprite/surface_animated_sprite.h" // Para SAnimatedSprite
|
|
||||||
#include "sprite/surface_moving_sprite.h" // Para SMovingSprite
|
|
||||||
#include "surface.h" // Para Surface
|
|
||||||
#include "text.h" // Para Text
|
|
||||||
#include "utils.h" // Para PaletteColor, stringToColor
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Ending2::Ending2()
|
|
||||||
: state_(EndingState::PRE_CREDITS, SDL_GetTicks(), STATE_PRE_CREDITS_DURATION_) {
|
|
||||||
options.section.section = Section::ENDING2;
|
|
||||||
options.section.subsection = Subsection::NONE;
|
|
||||||
|
|
||||||
// Inicializa el vector de colores
|
|
||||||
const std::vector<std::string> COLORS = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"};
|
|
||||||
for (const auto& color : COLORS) {
|
|
||||||
colors_.push_back(stringToColor(color));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cambia el color del borde
|
|
||||||
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK));
|
|
||||||
|
|
||||||
// Inicializa la lista de sprites
|
|
||||||
iniSpriteList();
|
|
||||||
|
|
||||||
// Carga todos los sprites desde una lista
|
|
||||||
loadSprites();
|
|
||||||
|
|
||||||
// Coloca los sprites en su sito
|
|
||||||
placeSprites();
|
|
||||||
|
|
||||||
// Crea los sprites con las texturas con los textos
|
|
||||||
createSpriteTexts();
|
|
||||||
|
|
||||||
// Crea los sprites con las texturas con los textos del final
|
|
||||||
createTexts();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el objeto
|
|
||||||
void Ending2::update() {
|
|
||||||
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
|
||||||
if (SDL_GetTicks() - ticks_ > GAME_SPEED) {
|
|
||||||
// Actualiza el contador de ticks
|
|
||||||
ticks_ = SDL_GetTicks();
|
|
||||||
|
|
||||||
// Comprueba las entradas
|
|
||||||
checkInput();
|
|
||||||
|
|
||||||
// Actualiza el estado
|
|
||||||
updateState();
|
|
||||||
|
|
||||||
switch (state_.state) {
|
|
||||||
case EndingState::CREDITS:
|
|
||||||
// Actualiza los sprites, los textos y los textos del final
|
|
||||||
for (int i = 0; i < 25; ++i) {
|
|
||||||
updateSprites();
|
|
||||||
updateTextSprites();
|
|
||||||
updateTexts();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EndingState::FADING:
|
|
||||||
// Actualiza el fade final y el volumen de la música
|
|
||||||
updateFinalFade();
|
|
||||||
updateMusicVolume();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// No hacer nada si el estado no corresponde a un caso manejado
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el objeto
|
|
||||||
Screen::get()->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja el final en pantalla
|
|
||||||
void Ending2::render() {
|
|
||||||
// Prepara para empezar a dibujar en la surface de juego
|
|
||||||
Screen::get()->start();
|
|
||||||
|
|
||||||
// Limpia la pantalla
|
|
||||||
Screen::get()->clearSurface(static_cast<Uint8>(PaletteColor::BLACK));
|
|
||||||
|
|
||||||
// Dibuja los sprites
|
|
||||||
renderSprites();
|
|
||||||
|
|
||||||
// Dibuja los sprites con el texto
|
|
||||||
renderSpriteTexts();
|
|
||||||
|
|
||||||
// Dibuja los sprites con el texto del final
|
|
||||||
renderTexts();
|
|
||||||
|
|
||||||
// Dibuja una trama arriba y abajo
|
|
||||||
Uint8 color = static_cast<Uint8>(PaletteColor::BLACK);
|
|
||||||
auto surface = Screen::get()->getRendererSurface();
|
|
||||||
for (int i = 0; i < 256; i += 2) {
|
|
||||||
surface->putPixel(i + 0, 0, color);
|
|
||||||
surface->putPixel(i + 1, 1, color);
|
|
||||||
surface->putPixel(i + 0, 2, color);
|
|
||||||
surface->putPixel(i + 1, 3, color);
|
|
||||||
|
|
||||||
surface->putPixel(i, 4, color);
|
|
||||||
surface->putPixel(i, 6, color);
|
|
||||||
|
|
||||||
surface->putPixel(i + 0, 191, color);
|
|
||||||
surface->putPixel(i + 1, 190, color);
|
|
||||||
surface->putPixel(i + 0, 189, color);
|
|
||||||
surface->putPixel(i + 1, 188, color);
|
|
||||||
|
|
||||||
surface->putPixel(i, 187, color);
|
|
||||||
surface->putPixel(i, 185, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vuelca el contenido del renderizador en pantalla
|
|
||||||
Screen::get()->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba el manejador de eventos
|
|
||||||
void Ending2::checkEvents() {
|
|
||||||
SDL_Event event;
|
|
||||||
while (SDL_PollEvent(&event)) {
|
|
||||||
globalEvents::check(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba las entradas
|
|
||||||
void Ending2::checkInput() {
|
|
||||||
globalInputs::check();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bucle principal
|
|
||||||
void Ending2::run() {
|
|
||||||
JA_PlayMusic(Resource::get()->getMusic("ending2.ogg"));
|
|
||||||
|
|
||||||
while (options.section.section == Section::ENDING2) {
|
|
||||||
update();
|
|
||||||
checkEvents();
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
|
|
||||||
JA_StopMusic();
|
|
||||||
JA_SetVolume(128);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el estado
|
|
||||||
void Ending2::updateState() {
|
|
||||||
switch (state_.state) {
|
|
||||||
case EndingState::PRE_CREDITS:
|
|
||||||
if (state_.hasEnded(EndingState::PRE_CREDITS)) {
|
|
||||||
state_.set(EndingState::CREDITS, 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EndingState::CREDITS:
|
|
||||||
if (texts_.back()->getPosY() <= GAMECANVAS_CENTER_Y) {
|
|
||||||
state_.set(EndingState::POST_CREDITS, STATE_POST_CREDITS_DURATION_);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EndingState::POST_CREDITS:
|
|
||||||
if (state_.hasEnded(EndingState::POST_CREDITS)) {
|
|
||||||
state_.set(EndingState::FADING, STATE_FADE_DURATION_);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EndingState::FADING:
|
|
||||||
if (state_.hasEnded(EndingState::FADING)) {
|
|
||||||
options.section.section = Section::LOGO;
|
|
||||||
options.section.subsection = Subsection::LOGO_TO_INTRO;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa la lista de sprites
|
|
||||||
void Ending2::iniSpriteList() {
|
|
||||||
// Reinicia el vector
|
|
||||||
sprite_list_.clear();
|
|
||||||
|
|
||||||
// Añade los valores
|
|
||||||
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");
|
|
||||||
|
|
||||||
sprite_list_.push_back("bell");
|
|
||||||
sprite_list_.push_back("dong");
|
|
||||||
|
|
||||||
sprite_list_.push_back("amstrad_cs");
|
|
||||||
sprite_list_.push_back("breakout");
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
sprite_list_.push_back("abad");
|
|
||||||
sprite_list_.push_back("abad_bell");
|
|
||||||
sprite_list_.push_back("lord_abad");
|
|
||||||
|
|
||||||
sprite_list_.push_back("bat");
|
|
||||||
sprite_list_.push_back("batman_bell");
|
|
||||||
sprite_list_.push_back("batman_fire");
|
|
||||||
sprite_list_.push_back("batman");
|
|
||||||
|
|
||||||
sprite_list_.push_back("demon");
|
|
||||||
sprite_list_.push_back("heavy");
|
|
||||||
sprite_list_.push_back("dimallas");
|
|
||||||
sprite_list_.push_back("guitar");
|
|
||||||
|
|
||||||
sprite_list_.push_back("jailbattle_alien");
|
|
||||||
sprite_list_.push_back("jailbattle_human");
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
sprite_list_.push_back("matatunos");
|
|
||||||
sprite_list_.push_back("tuno");
|
|
||||||
|
|
||||||
sprite_list_.push_back("mummy");
|
|
||||||
sprite_list_.push_back("sam");
|
|
||||||
|
|
||||||
sprite_list_.push_back("qvoid");
|
|
||||||
sprite_list_.push_back("sigmasua");
|
|
||||||
|
|
||||||
sprite_list_.push_back("tv_panel");
|
|
||||||
sprite_list_.push_back("tv");
|
|
||||||
|
|
||||||
sprite_list_.push_back("spider");
|
|
||||||
sprite_list_.push_back("shock");
|
|
||||||
sprite_list_.push_back("wave");
|
|
||||||
|
|
||||||
sprite_list_.push_back("player");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carga todos los sprites desde una lista
|
|
||||||
void Ending2::loadSprites() {
|
|
||||||
// Inicializa variables
|
|
||||||
sprite_max_width_ = 0;
|
|
||||||
sprite_max_height_ = 0;
|
|
||||||
|
|
||||||
// Carga los sprites
|
|
||||||
for (const auto& file : sprite_list_) {
|
|
||||||
sprites_.emplace_back(std::make_shared<SAnimatedSprite>(Resource::get()->getSurface(file + ".gif"), Resource::get()->getAnimations(file + ".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_) {
|
|
||||||
sprite->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza los sprites de texto
|
|
||||||
void Ending2::updateTextSprites() {
|
|
||||||
for (auto sprite : sprite_texts_) {
|
|
||||||
sprite->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza los sprites de texto del final
|
|
||||||
void Ending2::updateTexts() {
|
|
||||||
for (auto sprite : texts_) {
|
|
||||||
sprite->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja los sprites
|
|
||||||
void Ending2::renderSprites() {
|
|
||||||
const Uint8 colorA = static_cast<Uint8>(PaletteColor::RED);
|
|
||||||
for (auto sprite : sprites_) {
|
|
||||||
const bool A = sprite->getRect().y + sprite->getRect().h > 0;
|
|
||||||
const bool B = sprite->getRect().y < options.game.height;
|
|
||||||
if (A && B) {
|
|
||||||
sprite->render(1, colorA);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pinta el ultimo elemento de otro color
|
|
||||||
const Uint8 colorB = static_cast<Uint8>(PaletteColor::WHITE);
|
|
||||||
sprites_.back()->render(1, colorB);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja los sprites con el texto
|
|
||||||
void Ending2::renderSpriteTexts() {
|
|
||||||
const Uint8 color = static_cast<Uint8>(PaletteColor::WHITE);
|
|
||||||
for (auto sprite : sprite_texts_) {
|
|
||||||
const bool A = sprite->getRect().y + sprite->getRect().h > 0;
|
|
||||||
const bool B = sprite->getRect().y < options.game.height;
|
|
||||||
if (A && B) {
|
|
||||||
sprite->render(1, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja los sprites con el texto del final
|
|
||||||
void Ending2::renderTexts() {
|
|
||||||
for (auto sprite : texts_) {
|
|
||||||
const bool A = sprite->getRect().y + sprite->getRect().h > 0;
|
|
||||||
const bool B = sprite->getRect().y < options.game.height;
|
|
||||||
if (A && B) {
|
|
||||||
sprite->render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Coloca los sprites en su sito
|
|
||||||
void Ending2::placeSprites() {
|
|
||||||
for (int i = 0; i < static_cast<int>(sprites_.size()); ++i) {
|
|
||||||
const float X = i % 2 == 0 ? FIRST_COL_ : SECOND_COL_;
|
|
||||||
const float Y = (i / 1) * (sprite_max_height_ + DIST_SPRITE_TEXT_ + Resource::get()->getText("smb2")->getCharacterSize() + DIST_SPRITE_SPRITE_) + options.game.height + 40;
|
|
||||||
const float W = sprites_.at(i)->getWidth();
|
|
||||||
const float H = sprites_.at(i)->getHeight();
|
|
||||||
const float DX = -(W / 2);
|
|
||||||
const float DY = sprite_max_height_ - H;
|
|
||||||
|
|
||||||
sprites_.at(i)->setPos({X + DX, Y + DY, W, H});
|
|
||||||
sprites_.at(i)->setVelY(SPRITE_DESP_SPEED_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recoloca el sprite del jugador, que es el último de la lista
|
|
||||||
const float X = (options.game.width - sprites_.back()->getWidth()) / 2;
|
|
||||||
const float Y = sprites_.back()->getPosY() + sprite_max_height_ * 2;
|
|
||||||
sprites_.back()->setPos(X, 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 (size_t i = 0; i < sprite_list_.size(); ++i) {
|
|
||||||
auto text = Resource::get()->getText("smb2");
|
|
||||||
|
|
||||||
// Procesa y ajusta el texto del sprite actual
|
|
||||||
std::string txt = sprite_list_[i];
|
|
||||||
std::replace(txt.begin(), txt.end(), '_', ' '); // Reemplaza '_' por ' '
|
|
||||||
if (txt == "player") {
|
|
||||||
txt = "JAILDOCTOR"; // Reemplaza "player" por "JAILDOCTOR"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calcula las dimensiones del texto
|
|
||||||
const float W = text->lenght(txt, 1);
|
|
||||||
const float H = text->getCharacterSize();
|
|
||||||
|
|
||||||
// Determina la columna y la posición X del texto
|
|
||||||
const float X = (i == sprite_list_.size() - 1)
|
|
||||||
? (GAMECANVAS_CENTER_X - (W / 2))
|
|
||||||
: ((i % 2 == 0 ? FIRST_COL_ : SECOND_COL_) - (W / 2));
|
|
||||||
|
|
||||||
// Calcula la posición Y del texto en base a la posición y altura del sprite
|
|
||||||
const float Y = sprites_.at(i)->getPosY() + sprites_.at(i)->getHeight() + DIST_SPRITE_TEXT_;
|
|
||||||
|
|
||||||
// Crea la surface
|
|
||||||
auto surface = std::make_shared<Surface>(W, H);
|
|
||||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
||||||
Screen::get()->setRendererSurface(surface);
|
|
||||||
text->write(0, 0, txt);
|
|
||||||
|
|
||||||
// Crea el sprite
|
|
||||||
SDL_FRect pos = {X, Y, W, H};
|
|
||||||
sprite_texts_.emplace_back(std::make_shared<SMovingSprite>(surface, pos));
|
|
||||||
sprite_texts_.back()->setVelY(SPRITE_DESP_SPEED_);
|
|
||||||
Screen::get()->setRendererSurface(previuos_renderer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crea los sprites con las texturas con los textos del final
|
|
||||||
void Ending2::createTexts() {
|
|
||||||
// Crea los primeros textos
|
|
||||||
std::vector<std::string> list;
|
|
||||||
list.push_back("STARRING");
|
|
||||||
|
|
||||||
auto text = Resource::get()->getText("smb2");
|
|
||||||
|
|
||||||
// Crea los sprites de texto a partir de la lista
|
|
||||||
for (size_t i = 0; i < list.size(); ++i) {
|
|
||||||
// Calcula constantes
|
|
||||||
const float W = text->lenght(list[i], 1);
|
|
||||||
const float H = text->getCharacterSize();
|
|
||||||
const float X = GAMECANVAS_CENTER_X;
|
|
||||||
const float DX = -(W / 2);
|
|
||||||
const float Y = options.game.height + (text->getCharacterSize() * (i * 2));
|
|
||||||
|
|
||||||
// Crea la surface
|
|
||||||
auto surface = std::make_shared<Surface>(W, H);
|
|
||||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
||||||
Screen::get()->setRendererSurface(surface);
|
|
||||||
text->write(0, 0, list[i]);
|
|
||||||
|
|
||||||
// Crea el sprite
|
|
||||||
SDL_FRect pos = {X + DX, Y, W, H};
|
|
||||||
texts_.emplace_back(std::make_shared<SMovingSprite>(surface, pos));
|
|
||||||
texts_.back()->setVelY(SPRITE_DESP_SPEED_);
|
|
||||||
Screen::get()->setRendererSurface(previuos_renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crea los últimos textos
|
|
||||||
// El primer texto va a continuación del ultimo spriteText
|
|
||||||
const int START = sprite_texts_.back()->getPosY() + text->getCharacterSize() * 15;
|
|
||||||
list.clear();
|
|
||||||
list.push_back("THANK YOU");
|
|
||||||
list.push_back("FOR PLAYING!");
|
|
||||||
|
|
||||||
// Crea los sprites de texto a partir de la lista
|
|
||||||
for (size_t i = 0; i < list.size(); ++i) {
|
|
||||||
// Calcula constantes
|
|
||||||
const float W = text->lenght(list[i], 1);
|
|
||||||
const float H = text->getCharacterSize();
|
|
||||||
const float X = GAMECANVAS_CENTER_X;
|
|
||||||
const float DX = -(W / 2);
|
|
||||||
const float Y = START + (text->getCharacterSize() * (i * 2));
|
|
||||||
|
|
||||||
// Crea la surface
|
|
||||||
auto surface = std::make_shared<Surface>(W, H);
|
|
||||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
||||||
Screen::get()->setRendererSurface(surface);
|
|
||||||
text->write(0, 0, list[i]);
|
|
||||||
|
|
||||||
// Crea el sprite
|
|
||||||
SDL_FRect pos = {X + DX, Y, W, H};
|
|
||||||
texts_.emplace_back(std::make_shared<SMovingSprite>(surface, pos));
|
|
||||||
texts_.back()->setVelY(SPRITE_DESP_SPEED_);
|
|
||||||
Screen::get()->setRendererSurface(previuos_renderer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el fade final
|
|
||||||
void Ending2::updateFinalFade() {
|
|
||||||
for (auto sprite : texts_) {
|
|
||||||
sprite->getSurface()->fadeSubPalette(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el volumen de la musica
|
|
||||||
void Ending2::updateMusicVolume() {
|
|
||||||
// Constante para la duración en milisegundos
|
|
||||||
constexpr Uint32 VOLUME_FADE_DURATION = 3000;
|
|
||||||
|
|
||||||
// Tiempo actual
|
|
||||||
const Uint32 CURRENT_TICKS = SDL_GetTicks();
|
|
||||||
|
|
||||||
// Calcular el tiempo transcurrido desde init_ticks
|
|
||||||
Uint32 elapsed_ticks = CURRENT_TICKS - state_.init_ticks;
|
|
||||||
|
|
||||||
// Limitar el tiempo máximo a la duración definida
|
|
||||||
elapsed_ticks = std::min(elapsed_ticks, VOLUME_FADE_DURATION);
|
|
||||||
|
|
||||||
// Calcular el step basado en la duración
|
|
||||||
const float STEP = (static_cast<float>(VOLUME_FADE_DURATION) - elapsed_ticks) / VOLUME_FADE_DURATION;
|
|
||||||
|
|
||||||
// Calcular el volumen en función del step
|
|
||||||
const int VOLUME = static_cast<int>(128 * STEP);
|
|
||||||
|
|
||||||
// Actualizar el volumen
|
|
||||||
JA_SetVolume(VOLUME);
|
|
||||||
}
|
|
||||||
@@ -1,620 +0,0 @@
|
|||||||
#include "game.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "asset.h" // Para Asset
|
|
||||||
#include "cheevos.h" // Para Cheevos
|
|
||||||
#include "debug.h" // Para Debug
|
|
||||||
#include "defines.h" // Para BLOCK, PLAY_AREA_HEIGHT, RoomBorder::BOTTOM
|
|
||||||
#include "external/jail_audio.h" // Para JA_PauseMusic, JA_GetMusicState, JA_P...
|
|
||||||
#include "global_events.h" // Para check
|
|
||||||
#include "global_inputs.h" // Para check
|
|
||||||
#include "input.h" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT
|
|
||||||
#include "item_tracker.h" // Para ItemTracker
|
|
||||||
#include "options.h" // Para Options, options, Cheat, SectionState
|
|
||||||
#include "resource.h" // Para ResourceRoom, Resource
|
|
||||||
#include "room.h" // Para Room, RoomData
|
|
||||||
#include "room_tracker.h" // Para RoomTracker
|
|
||||||
#include "scoreboard.h" // Para ScoreboardData, Scoreboard
|
|
||||||
#include "screen.h" // Para Screen
|
|
||||||
#include "stats.h" // Para Stats
|
|
||||||
#include "surface.h" // Para Surface
|
|
||||||
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR
|
|
||||||
#include "ui/notifier.h" // Para Notifier, NotificationText, CHEEVO_NO...
|
|
||||||
#include "utils.h" // Para PaletteColor, stringToColor
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Game::Game(GameMode mode)
|
|
||||||
: board_(std::make_shared<ScoreboardData>(0, 9, 0, true, 0, SDL_GetTicks(), options.cheats.jail_is_open == Cheat::CheatState::ENABLED)),
|
|
||||||
scoreboard_(std::make_shared<Scoreboard>(board_)),
|
|
||||||
room_tracker_(std::make_shared<RoomTracker>()),
|
|
||||||
stats_(std::make_shared<Stats>(Asset::get()->get("stats.csv"), Asset::get()->get("stats_buffer.csv"))),
|
|
||||||
mode_(mode),
|
|
||||||
#ifdef DEBUG
|
|
||||||
current_room_("03.room"),
|
|
||||||
spawn_point_(PlayerSpawn(25 * BLOCK, 13 * BLOCK, 0, 0, 0, PlayerState::STANDING, SDL_FLIP_HORIZONTAL))
|
|
||||||
#else
|
|
||||||
current_room_("03.room"),
|
|
||||||
spawn_point_(PlayerSpawn(25 * BLOCK, 13 * BLOCK, 0, 0, 0, PlayerState::STANDING, SDL_FLIP_HORIZONTAL))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
Debug::get()->setEnabled(false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Crea objetos e inicializa variables
|
|
||||||
ItemTracker::init();
|
|
||||||
DEMO_init();
|
|
||||||
room_ = std::make_shared<Room>(current_room_, board_);
|
|
||||||
initPlayer(spawn_point_, room_);
|
|
||||||
initStats();
|
|
||||||
total_items_ = getTotalItems();
|
|
||||||
|
|
||||||
createRoomNameTexture();
|
|
||||||
changeRoom(current_room_);
|
|
||||||
|
|
||||||
Cheevos::get()->enable(!options.cheats.enabled()); // Deshabilita los logros si hay trucos activados
|
|
||||||
Cheevos::get()->clearUnobtainableState();
|
|
||||||
|
|
||||||
options.section.section = (mode_ == GameMode::GAME) ? Section::GAME : Section::DEMO;
|
|
||||||
options.section.subsection = Subsection::NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Game::~Game() {
|
|
||||||
ItemTracker::destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba los eventos de la cola
|
|
||||||
void Game::checkEvents() {
|
|
||||||
SDL_Event event;
|
|
||||||
while (SDL_PollEvent(&event)) {
|
|
||||||
globalEvents::check(event);
|
|
||||||
#ifdef DEBUG
|
|
||||||
checkDebugEvents(event);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba el teclado
|
|
||||||
void Game::checkInput() {
|
|
||||||
if (Input::get()->checkInput(InputAction::TOGGLE_MUSIC, INPUT_DO_NOT_ALLOW_REPEAT)) {
|
|
||||||
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::get()->checkInput(InputAction::PAUSE, INPUT_DO_NOT_ALLOW_REPEAT)) {
|
|
||||||
togglePause();
|
|
||||||
Notifier::get()->show({std::string(paused_ ? "GAME PAUSED" : "GAME RUNNING")}, NotificationText::CENTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
globalInputs::check();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bucle para el juego
|
|
||||||
void Game::run() {
|
|
||||||
keepMusicPlaying();
|
|
||||||
if (!board_->music && mode_ == GameMode::GAME) {
|
|
||||||
JA_PauseMusic();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (options.section.section == Section::GAME || options.section.section == Section::DEMO) {
|
|
||||||
update();
|
|
||||||
checkEvents();
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode_ == GameMode::GAME) {
|
|
||||||
JA_StopMusic();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el juego, las variables, comprueba la entrada, etc.
|
|
||||||
void Game::update() {
|
|
||||||
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
|
||||||
if (SDL_GetTicks() - ticks_ > GAME_SPEED) {
|
|
||||||
// Actualiza el contador de ticks
|
|
||||||
ticks_ = SDL_GetTicks();
|
|
||||||
|
|
||||||
// Comprueba el teclado
|
|
||||||
checkInput();
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
Debug::get()->clear();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Actualiza los objetos
|
|
||||||
room_->update();
|
|
||||||
if (mode_ == GameMode::GAME) {
|
|
||||||
player_->update();
|
|
||||||
checkPlayerIsOnBorder();
|
|
||||||
checkPlayerAndItems();
|
|
||||||
checkPlayerAndEnemies();
|
|
||||||
checkIfPlayerIsAlive();
|
|
||||||
checkGameOver();
|
|
||||||
checkEndGame();
|
|
||||||
checkRestoringJail();
|
|
||||||
checkSomeCheevos();
|
|
||||||
}
|
|
||||||
DEMO_checkRoomChange();
|
|
||||||
scoreboard_->update();
|
|
||||||
keepMusicPlaying();
|
|
||||||
updateBlackScreen();
|
|
||||||
|
|
||||||
Screen::get()->update();
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
updateDebugInfo();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pinta los objetos en pantalla
|
|
||||||
void Game::render() {
|
|
||||||
// Prepara para dibujar el frame
|
|
||||||
Screen::get()->start();
|
|
||||||
|
|
||||||
// Dibuja los elementos del juego en orden
|
|
||||||
room_->renderMap();
|
|
||||||
room_->renderEnemies();
|
|
||||||
room_->renderItems();
|
|
||||||
if (mode_ == GameMode::GAME) {
|
|
||||||
player_->render();
|
|
||||||
}
|
|
||||||
renderRoomName();
|
|
||||||
scoreboard_->render();
|
|
||||||
renderBlackScreen();
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
// Debug info
|
|
||||||
renderDebugInfo();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Actualiza la pantalla
|
|
||||||
Screen::get()->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
// Pasa la información de debug
|
|
||||||
void Game::updateDebugInfo() {
|
|
||||||
Debug::get()->add("X = " + std::to_string(static_cast<int>(player_->x_)) + ", Y = " + std::to_string(static_cast<int>(player_->y_)));
|
|
||||||
Debug::get()->add("VX = " + std::to_string(player_->vx_).substr(0, 4) + ", VY = " + std::to_string(player_->vy_).substr(0, 4));
|
|
||||||
Debug::get()->add("STATE = " + std::to_string(static_cast<int>(player_->state_)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pone la información de debug en pantalla
|
|
||||||
void Game::renderDebugInfo() {
|
|
||||||
if (!Debug::get()->getEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto surface = Screen::get()->getRendererSurface();
|
|
||||||
|
|
||||||
// Borra el marcador
|
|
||||||
SDL_FRect rect = {0, 18 * BLOCK, PLAY_AREA_WIDTH, GAMECANVAS_HEIGHT - PLAY_AREA_HEIGHT};
|
|
||||||
surface->fillRect(&rect, static_cast<Uint8>(PaletteColor::BLACK));
|
|
||||||
|
|
||||||
// Pinta la rejilla
|
|
||||||
/*for (int i = 0; i < PLAY_AREA_BOTTOM; i += 8)
|
|
||||||
{
|
|
||||||
// Lineas horizontales
|
|
||||||
surface->drawLine(0, i, PLAY_AREA_RIGHT, i, static_cast<Uint8>(PaletteColor::BRIGHT_BLACK));
|
|
||||||
}
|
|
||||||
for (int i = 0; i < PLAY_AREA_RIGHT; i += 8)
|
|
||||||
{
|
|
||||||
// Lineas verticales
|
|
||||||
surface->drawLine(i, 0, i, PLAY_AREA_BOTTOM - 1, static_cast<Uint8>(PaletteColor::BRIGHT_BLACK));
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// Pinta el texto
|
|
||||||
Debug::get()->setPos({1, 18 * 8});
|
|
||||||
Debug::get()->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba los eventos
|
|
||||||
void Game::checkDebugEvents(const SDL_Event& event) {
|
|
||||||
if (event.type == SDL_EVENT_KEY_DOWN && event.key.repeat == 0) {
|
|
||||||
switch (event.key.key) {
|
|
||||||
case SDL_SCANCODE_G:
|
|
||||||
Debug::get()->toggleEnabled();
|
|
||||||
options.cheats.invincible = static_cast<Cheat::CheatState>(Debug::get()->getEnabled());
|
|
||||||
board_->music = !Debug::get()->getEnabled();
|
|
||||||
board_->music ? JA_ResumeMusic() : JA_PauseMusic();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_SCANCODE_R:
|
|
||||||
Resource::get()->reload();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_SCANCODE_W:
|
|
||||||
changeRoom(room_->getRoom(RoomBorder::TOP));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_SCANCODE_A:
|
|
||||||
changeRoom(room_->getRoom(RoomBorder::LEFT));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_SCANCODE_S:
|
|
||||||
changeRoom(room_->getRoom(RoomBorder::BOTTOM));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_SCANCODE_D:
|
|
||||||
changeRoom(room_->getRoom(RoomBorder::RIGHT));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_SCANCODE_7:
|
|
||||||
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, NotificationText::CENTER, CHEEVO_NOTIFICATION_DURATION, -1, false, "F7");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Escribe el nombre de la pantalla
|
|
||||||
void Game::renderRoomName() {
|
|
||||||
// Dibuja la textura con el nombre de la habitación
|
|
||||||
room_name_surface_->render(nullptr, &room_name_rect_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cambia de habitación
|
|
||||||
bool Game::changeRoom(const std::string& room_path) {
|
|
||||||
// En las habitaciones los limites tienen la cadena del fichero o un 0 en caso de no limitar con nada
|
|
||||||
if (room_path == "0") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verifica que exista el fichero que se va a cargar
|
|
||||||
if (Asset::get()->get(room_path) != "") {
|
|
||||||
// Crea un objeto habitación nuevo a partir del fichero
|
|
||||||
room_ = std::make_shared<Room>(room_path, board_);
|
|
||||||
|
|
||||||
// Pone el nombre de la habitación en la textura
|
|
||||||
fillRoomNameTexture();
|
|
||||||
|
|
||||||
// Pone el color del marcador en función del color del borde de la habitación
|
|
||||||
setScoreBoardColor();
|
|
||||||
|
|
||||||
if (room_tracker_->addRoom(room_path)) {
|
|
||||||
// Incrementa el contador de habitaciones visitadas
|
|
||||||
board_->rooms++;
|
|
||||||
options.stats.rooms = board_->rooms;
|
|
||||||
|
|
||||||
// Actualiza las estadisticas
|
|
||||||
stats_->addVisit(room_->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pasa la nueva habitación al jugador
|
|
||||||
player_->setRoom(room_);
|
|
||||||
|
|
||||||
// Cambia la habitación actual
|
|
||||||
current_room_ = room_path;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si el jugador esta en el borde de la pantalla
|
|
||||||
void Game::checkPlayerIsOnBorder() {
|
|
||||||
if (player_->getOnBorder()) {
|
|
||||||
const std::string roomName = room_->getRoom(player_->getBorder());
|
|
||||||
if (changeRoom(roomName)) {
|
|
||||||
player_->switchBorders();
|
|
||||||
spawn_point_ = player_->getSpawnParams();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba las colisiones del jugador con los enemigos
|
|
||||||
bool Game::checkPlayerAndEnemies() {
|
|
||||||
const bool death = room_->enemyCollision(player_->getCollider());
|
|
||||||
if (death) {
|
|
||||||
killPlayer();
|
|
||||||
}
|
|
||||||
return death;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba las colisiones del jugador con los objetos
|
|
||||||
void Game::checkPlayerAndItems() {
|
|
||||||
room_->itemCollision(player_->getCollider());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si el jugador esta vivo
|
|
||||||
void Game::checkIfPlayerIsAlive() {
|
|
||||||
if (!player_->isAlive()) {
|
|
||||||
killPlayer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si ha terminado la partida
|
|
||||||
void Game::checkGameOver() {
|
|
||||||
if (board_->lives < 0 && black_screen_counter_ > 17) {
|
|
||||||
options.section.section = Section::GAME_OVER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mata al jugador
|
|
||||||
void Game::killPlayer() {
|
|
||||||
if (options.cheats.invincible == Cheat::CheatState::ENABLED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resta una vida al jugador
|
|
||||||
if (options.cheats.infinite_lives == Cheat::CheatState::DISABLED) {
|
|
||||||
--board_->lives;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza las estadisticas
|
|
||||||
stats_->addDeath(room_->getName());
|
|
||||||
|
|
||||||
// Invalida el logro de pasarse el juego sin morir
|
|
||||||
Cheevos::get()->setUnobtainable(11);
|
|
||||||
|
|
||||||
// Sonido
|
|
||||||
JA_PlaySound(Resource::get()->getSound("death.wav"));
|
|
||||||
|
|
||||||
// Pone la pantalla en negro un tiempo
|
|
||||||
setBlackScreen();
|
|
||||||
|
|
||||||
// Crea la nueva habitación y el nuevo jugador
|
|
||||||
room_ = std::make_shared<Room>(current_room_, board_);
|
|
||||||
initPlayer(spawn_point_, room_);
|
|
||||||
|
|
||||||
// Pone los objetos en pausa mientras esta la habitación en negro
|
|
||||||
room_->setPaused(true);
|
|
||||||
player_->setPaused(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Establece la pantalla en negro
|
|
||||||
void Game::setBlackScreen() {
|
|
||||||
black_screen_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza las variables relativas a la pantalla en negro
|
|
||||||
void Game::updateBlackScreen() {
|
|
||||||
if (black_screen_) {
|
|
||||||
black_screen_counter_++;
|
|
||||||
if (black_screen_counter_ > 20) {
|
|
||||||
black_screen_ = false;
|
|
||||||
black_screen_counter_ = 0;
|
|
||||||
|
|
||||||
player_->setPaused(false);
|
|
||||||
room_->setPaused(false);
|
|
||||||
Screen::get()->setBorderColor(room_->getBorderColor());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja la pantalla negra
|
|
||||||
void Game::renderBlackScreen() {
|
|
||||||
if (black_screen_) {
|
|
||||||
auto const color = static_cast<Uint8>(PaletteColor::BLACK);
|
|
||||||
Screen::get()->setRendererSurface();
|
|
||||||
Screen::get()->clearSurface(color);
|
|
||||||
Screen::get()->setBorderColor(color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pone el color del marcador en función del color del borde de la habitación
|
|
||||||
void Game::setScoreBoardColor() {
|
|
||||||
// Obtiene el color del borde
|
|
||||||
const Uint8 BORDER_COLOR = room_->getBorderColor();
|
|
||||||
|
|
||||||
const bool IS_BLACK = BORDER_COLOR == static_cast<Uint8>(PaletteColor::BLACK);
|
|
||||||
const bool IS_BRIGHT_BLACK = BORDER_COLOR == static_cast<Uint8>(PaletteColor::BRIGHT_BLACK);
|
|
||||||
|
|
||||||
// Si el color del borde es negro o negro brillante cambia el texto del marcador a blanco
|
|
||||||
board_->color = IS_BLACK || IS_BRIGHT_BLACK ? static_cast<Uint8>(PaletteColor::WHITE) : BORDER_COLOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
|
|
||||||
if (haveTheItems) {
|
|
||||||
board_->jail_is_open = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (haveTheItems && isOnTheRoom && isOnTheDoor) {
|
|
||||||
// Comprueba los logros de completar el juego
|
|
||||||
checkEndGameCheevos();
|
|
||||||
|
|
||||||
options.section.section = Section::ENDING;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtiene la cantidad total de items que hay en el mapeado del juego
|
|
||||||
int Game::getTotalItems() {
|
|
||||||
int items = 0;
|
|
||||||
auto rooms = Resource::get()->getRooms();
|
|
||||||
|
|
||||||
for (const auto& room : rooms) {
|
|
||||||
items += room.room->items.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pone el juego en pausa
|
|
||||||
void Game::togglePause() {
|
|
||||||
paused_ = !paused_;
|
|
||||||
|
|
||||||
player_->setPaused(paused_);
|
|
||||||
room_->setPaused(paused_);
|
|
||||||
scoreboard_->setPaused(paused_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Da vidas al jugador cuando está en la Jail
|
|
||||||
void Game::checkRestoringJail() {
|
|
||||||
if (room_->getName() != "THE JAIL" || board_->lives == 9) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int counter = 0;
|
|
||||||
|
|
||||||
if (!paused_) {
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Incrementa el numero de vidas
|
|
||||||
if (counter == 100) {
|
|
||||||
counter = 0;
|
|
||||||
board_->lives++;
|
|
||||||
JA_PlaySound(Resource::get()->getSound("death.wav"));
|
|
||||||
|
|
||||||
// Invalida el logro de completar el juego sin entrar a la jail
|
|
||||||
const bool haveTheItems = board_->items >= int(total_items_ * 0.9f);
|
|
||||||
if (!haveTheItems) {
|
|
||||||
Cheevos::get()->setUnobtainable(9);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa el diccionario de las estadísticas
|
|
||||||
void Game::initStats() {
|
|
||||||
auto rooms = Resource::get()->getRooms();
|
|
||||||
|
|
||||||
for (const auto& room : rooms) {
|
|
||||||
stats_->addDictionary(room.room->number, room.room->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
stats_->init();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crea la textura con el nombre de la habitación
|
|
||||||
void Game::fillRoomNameTexture() {
|
|
||||||
// Pone la textura como destino de renderizado
|
|
||||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
||||||
Screen::get()->setRendererSurface(room_name_surface_);
|
|
||||||
|
|
||||||
// Rellena la textura de color
|
|
||||||
room_name_surface_->clear(stringToColor("white"));
|
|
||||||
|
|
||||||
// Escribe el texto en la textura
|
|
||||||
auto text = Resource::get()->getText("smb2");
|
|
||||||
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, text->getCharacterSize() / 2, room_->getName(), 1, room_->getBGColor());
|
|
||||||
|
|
||||||
// Deja el renderizador por defecto
|
|
||||||
Screen::get()->setRendererSurface(previuos_renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba algunos logros
|
|
||||||
void Game::checkSomeCheevos() {
|
|
||||||
auto cheevos = Cheevos::get();
|
|
||||||
|
|
||||||
// Logros sobre la cantidad de 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) {
|
|
||||||
cheevos->unlock(3);
|
|
||||||
cheevos->unlock(2);
|
|
||||||
cheevos->unlock(1);
|
|
||||||
} else if (board_->items >= total_items_ * 0.5f) {
|
|
||||||
cheevos->unlock(2);
|
|
||||||
cheevos->unlock(1);
|
|
||||||
} else if (board_->items >= total_items_ * 0.25f) {
|
|
||||||
cheevos->unlock(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logros sobre las habitaciones visitadas
|
|
||||||
if (board_->rooms >= 60) {
|
|
||||||
cheevos->unlock(7);
|
|
||||||
cheevos->unlock(6);
|
|
||||||
cheevos->unlock(5);
|
|
||||||
} else if (board_->rooms >= 40) {
|
|
||||||
cheevos->unlock(6);
|
|
||||||
cheevos->unlock(5);
|
|
||||||
} else if (board_->rooms >= 20) {
|
|
||||||
cheevos->unlock(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba los logros de completar el juego
|
|
||||||
void Game::checkEndGameCheevos() {
|
|
||||||
auto cheevos = Cheevos::get();
|
|
||||||
|
|
||||||
// "Complete the game"
|
|
||||||
cheevos->unlock(8);
|
|
||||||
|
|
||||||
// "Complete the game without entering the jail"
|
|
||||||
cheevos->unlock(9);
|
|
||||||
|
|
||||||
// "Complete the game with all items"
|
|
||||||
if (board_->items == total_items_) {
|
|
||||||
cheevos->unlock(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
// "Complete the game without dying"
|
|
||||||
cheevos->unlock(11);
|
|
||||||
|
|
||||||
// "Complete the game in under 30 minutes"
|
|
||||||
if (scoreboard_->getMinutes() < 30) {
|
|
||||||
cheevos->unlock(12);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa al jugador
|
|
||||||
void Game::initPlayer(const PlayerSpawn& spawn_point, std::shared_ptr<Room> room) {
|
|
||||||
std::string player_texture = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.gif" : "player.gif";
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crea la textura para poner el nombre de la habitación
|
|
||||||
void Game::createRoomNameTexture() {
|
|
||||||
auto text = Resource::get()->getText("smb2");
|
|
||||||
room_name_surface_ = std::make_shared<Surface>(options.game.width, text->getCharacterSize() * 2);
|
|
||||||
|
|
||||||
// Establece el destino de la textura
|
|
||||||
room_name_rect_ = {0.0F, PLAY_AREA_HEIGHT, options.game.width, text->getCharacterSize() * 2.0F};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hace sonar la música
|
|
||||||
void Game::keepMusicPlaying() {
|
|
||||||
const std::string music_path = mode_ == GameMode::GAME ? "game.ogg" : "title.ogg";
|
|
||||||
|
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEMO MODE: Inicializa las variables para el modo demo
|
|
||||||
void Game::DEMO_init() {
|
|
||||||
if (mode_ == GameMode::DEMO) {
|
|
||||||
demo_ = DemoData(0, 400, 0, {"04.room", "54.room", "20.room", "09.room", "05.room", "11.room", "31.room", "44.room"});
|
|
||||||
current_room_ = demo_.rooms.front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEMO MODE: Comprueba si se ha de cambiar de habitación
|
|
||||||
void Game::DEMO_checkRoomChange() {
|
|
||||||
if (mode_ == GameMode::DEMO) {
|
|
||||||
demo_.counter++;
|
|
||||||
if (demo_.counter == demo_.room_time) {
|
|
||||||
demo_.counter = 0;
|
|
||||||
demo_.room_index++;
|
|
||||||
if (demo_.room_index == (int)demo_.rooms.size()) {
|
|
||||||
options.section.section = Section::LOGO;
|
|
||||||
options.section.subsection = Subsection::LOGO_TO_TITLE;
|
|
||||||
} else {
|
|
||||||
changeRoom(demo_.rooms[demo_.room_index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include <initializer_list> // Para initializer_list
|
|
||||||
#include <memory> // Para shared_ptr
|
|
||||||
#include <string> // Para string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "player.h" // Para PlayerSpawn
|
|
||||||
class Room; // lines 12-12
|
|
||||||
class RoomTracker; // lines 13-13
|
|
||||||
class Scoreboard; // lines 14-14
|
|
||||||
class Stats; // lines 15-15
|
|
||||||
class Surface;
|
|
||||||
struct ScoreboardData; // lines 16-16
|
|
||||||
|
|
||||||
enum class GameMode {
|
|
||||||
DEMO,
|
|
||||||
GAME
|
|
||||||
};
|
|
||||||
|
|
||||||
class Game {
|
|
||||||
private:
|
|
||||||
// Estructuras
|
|
||||||
struct DemoData {
|
|
||||||
int counter; // Contador para el modo demo
|
|
||||||
int room_time; // Tiempo que se muestra cada habitación
|
|
||||||
int room_index; // Índice para el vector de habitaciones
|
|
||||||
std::vector<std::string> rooms; // Listado con los mapas de la demo
|
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
DemoData()
|
|
||||||
: counter(0),
|
|
||||||
room_time(0),
|
|
||||||
room_index(0),
|
|
||||||
rooms({}) {}
|
|
||||||
|
|
||||||
// Constructor parametrizado
|
|
||||||
DemoData(int counter, int room_time, int room_index, const std::vector<std::string>& rooms)
|
|
||||||
: counter(counter),
|
|
||||||
room_time(room_time),
|
|
||||||
room_index(room_index),
|
|
||||||
rooms(rooms) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Objetos y punteros
|
|
||||||
std::shared_ptr<ScoreboardData> board_; // Estructura con los datos del marcador
|
|
||||||
std::shared_ptr<Scoreboard> scoreboard_; // Objeto encargado de gestionar el marcador
|
|
||||||
std::shared_ptr<RoomTracker> room_tracker_; // Lleva el control de las habitaciones visitadas
|
|
||||||
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<Stats> stats_; // Objeto encargado de gestionar las estadísticas
|
|
||||||
std::shared_ptr<Surface> room_name_surface_; // Textura para escribir el nombre de la habitación
|
|
||||||
|
|
||||||
// Variables
|
|
||||||
GameMode mode_; // Modo del juego
|
|
||||||
DemoData demo_; // Variables para el modo demo
|
|
||||||
Uint32 ticks_ = 0; // 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
|
|
||||||
bool paused_ = false; // Indica si el juego se encuentra en pausa
|
|
||||||
bool black_screen_ = false; // Indica si la pantalla está en negro. Se utiliza para la muerte del jugador
|
|
||||||
int black_screen_counter_ = 0; // Contador para temporizar la pantalla en negro
|
|
||||||
int total_items_; // Cantidad total de items que hay en el mapeado del juego
|
|
||||||
SDL_FRect 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();
|
|
||||||
|
|
||||||
// Pinta los objetos en pantalla
|
|
||||||
void render();
|
|
||||||
|
|
||||||
// Comprueba los eventos de la cola
|
|
||||||
void checkEvents();
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
// Pone la información de debug en pantalla
|
|
||||||
void updateDebugInfo();
|
|
||||||
|
|
||||||
// Pone la información de debug en pantalla
|
|
||||||
void renderDebugInfo();
|
|
||||||
|
|
||||||
// Comprueba los eventos
|
|
||||||
void checkDebugEvents(const SDL_Event& event);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Escribe el nombre de la pantalla
|
|
||||||
void renderRoomName();
|
|
||||||
|
|
||||||
// Cambia de habitación
|
|
||||||
bool changeRoom(const std::string& file);
|
|
||||||
|
|
||||||
// Comprueba el teclado
|
|
||||||
void checkInput();
|
|
||||||
|
|
||||||
// Comprueba si el jugador esta en el borde de la pantalla y actua
|
|
||||||
void checkPlayerIsOnBorder();
|
|
||||||
|
|
||||||
// Comprueba las colisiones del jugador con los enemigos
|
|
||||||
bool checkPlayerAndEnemies();
|
|
||||||
|
|
||||||
// Comprueba las colisiones del jugador con los objetos
|
|
||||||
void checkPlayerAndItems();
|
|
||||||
|
|
||||||
// Comprueba si el jugador esta vivo
|
|
||||||
void checkIfPlayerIsAlive();
|
|
||||||
|
|
||||||
// Comprueba si ha terminado la partida
|
|
||||||
void checkGameOver();
|
|
||||||
|
|
||||||
// Mata al jugador
|
|
||||||
void killPlayer();
|
|
||||||
|
|
||||||
// Establece la pantalla en negro
|
|
||||||
void setBlackScreen();
|
|
||||||
|
|
||||||
// Actualiza las variables relativas a la pantalla en negro
|
|
||||||
void updateBlackScreen();
|
|
||||||
|
|
||||||
// Dibuja la pantalla negra
|
|
||||||
void renderBlackScreen();
|
|
||||||
|
|
||||||
// Pone el color del marcador en función del color del borde de la habitación
|
|
||||||
void setScoreBoardColor();
|
|
||||||
|
|
||||||
// Comprueba si ha finalizado el juego
|
|
||||||
bool checkEndGame();
|
|
||||||
|
|
||||||
// Obtiene la cantidad total de items que hay en el mapeado del juego
|
|
||||||
int getTotalItems();
|
|
||||||
|
|
||||||
// Pone el juego en pausa
|
|
||||||
void togglePause();
|
|
||||||
|
|
||||||
// Da vidas al jugador cuando está en la Jail
|
|
||||||
void checkRestoringJail();
|
|
||||||
|
|
||||||
// Inicializa el diccionario de las estadísticas
|
|
||||||
void initStats();
|
|
||||||
|
|
||||||
// Pone el nombre de la habitación en la textura
|
|
||||||
void fillRoomNameTexture();
|
|
||||||
|
|
||||||
// Comprueba algunos logros
|
|
||||||
void checkSomeCheevos();
|
|
||||||
|
|
||||||
// Comprueba los logros de completar el juego
|
|
||||||
void checkEndGameCheevos();
|
|
||||||
|
|
||||||
// Inicializa al jugador
|
|
||||||
void initPlayer(const PlayerSpawn& spawn_point, std::shared_ptr<Room> room);
|
|
||||||
|
|
||||||
// Crea la textura para poner el nombre de la habitación
|
|
||||||
void createRoomNameTexture();
|
|
||||||
|
|
||||||
// Hace sonar la música
|
|
||||||
void keepMusicPlaying();
|
|
||||||
|
|
||||||
// DEMO MODE: Inicializa las variables para el modo demo
|
|
||||||
void DEMO_init();
|
|
||||||
|
|
||||||
// DEMO MODE: Comprueba si se ha de cambiar de habitación
|
|
||||||
void DEMO_checkRoomChange();
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
explicit Game(GameMode mode);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~Game();
|
|
||||||
|
|
||||||
// Bucle para el juego
|
|
||||||
void run();
|
|
||||||
};
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
#include "game_over.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include <algorithm> // Para min, max
|
|
||||||
#include <string> // Para basic_string, operator+, to_string
|
|
||||||
|
|
||||||
#include "defines.h" // Para GAMECANVAS_CENTER_X, GAME_SPEED
|
|
||||||
#include "external/jail_audio.h" // Para JA_PlayMusic
|
|
||||||
#include "global_events.h" // Para check
|
|
||||||
#include "global_inputs.h" // Para check
|
|
||||||
#include "options.h" // Para Options, options, OptionsStats, Secti...
|
|
||||||
#include "resource.h" // Para Resource
|
|
||||||
#include "screen.h" // Para Screen
|
|
||||||
#include "sprite/surface_animated_sprite.h" // Para SAnimatedSprite
|
|
||||||
#include "text.h" // Para TEXT_CENTER, TEXT_COLOR, Text
|
|
||||||
#include "utils.h" // Para PaletteColor, stringToColor
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
GameOver::GameOver()
|
|
||||||
: player_sprite_(std::make_shared<SAnimatedSprite>(Resource::get()->getSurface("player_game_over.gif"), Resource::get()->getAnimations("player_game_over.ani"))),
|
|
||||||
tv_sprite_(std::make_shared<SAnimatedSprite>(Resource::get()->getSurface("tv.gif"), Resource::get()->getAnimations("tv.ani"))),
|
|
||||||
pre_counter_(0),
|
|
||||||
counter_(0),
|
|
||||||
ticks_(0) {
|
|
||||||
options.section.section = Section::GAME_OVER;
|
|
||||||
options.section.subsection = Subsection::NONE;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK));
|
|
||||||
|
|
||||||
// Inicializa el vector de colores
|
|
||||||
const std::vector<std::string> COLORS = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"};
|
|
||||||
for (const auto& color : COLORS) {
|
|
||||||
colors_.push_back(stringToColor(color));
|
|
||||||
}
|
|
||||||
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_ > GAME_SPEED) {
|
|
||||||
// Actualiza el contador de ticks
|
|
||||||
ticks_ = SDL_GetTicks();
|
|
||||||
|
|
||||||
// Comprueba las entradas
|
|
||||||
checkInput();
|
|
||||||
|
|
||||||
// Actualiza el color usado para renderizar los textos e imagenes
|
|
||||||
updateColor();
|
|
||||||
|
|
||||||
// Actualiza los contadores
|
|
||||||
updateCounters();
|
|
||||||
|
|
||||||
// Actualiza los dos sprites
|
|
||||||
player_sprite_->update();
|
|
||||||
tv_sprite_->update();
|
|
||||||
|
|
||||||
// Actualiza el objeto Screen
|
|
||||||
Screen::get()->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja el final en pantalla
|
|
||||||
void GameOver::render() {
|
|
||||||
constexpr int Y = 32;
|
|
||||||
|
|
||||||
Screen::get()->start();
|
|
||||||
Screen::get()->clearSurface(static_cast<Uint8>(PaletteColor::BLACK));
|
|
||||||
|
|
||||||
auto text = Resource::get()->getText("smb2");
|
|
||||||
|
|
||||||
// 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_);
|
|
||||||
|
|
||||||
// Dibuja los sprites
|
|
||||||
player_sprite_->setPosY(Y + 30);
|
|
||||||
tv_sprite_->setPosY(Y + 30);
|
|
||||||
renderSprites();
|
|
||||||
|
|
||||||
// Escribe el texto con las habitaciones y los items
|
|
||||||
const std::string ITEMS_TEXT = 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 ROOMS_TEXT = 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: " + ITEMS_TEXT, 1, color_);
|
|
||||||
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 90, "ROOMS: " + ROOMS_TEXT, 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_);
|
|
||||||
|
|
||||||
// Vuelca el contenido del renderizador en pantalla
|
|
||||||
Screen::get()->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba el manejador de eventos
|
|
||||||
void GameOver::checkEvents() {
|
|
||||||
SDL_Event event;
|
|
||||||
while (SDL_PollEvent(&event)) {
|
|
||||||
globalEvents::check(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba las entradas
|
|
||||||
void GameOver::checkInput() {
|
|
||||||
globalInputs::check();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bucle principal
|
|
||||||
void GameOver::run() {
|
|
||||||
while (options.section.section == Section::GAME_OVER) {
|
|
||||||
update();
|
|
||||||
checkEvents();
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el color usado para renderizar los textos e imagenes
|
|
||||||
void GameOver::updateColor() {
|
|
||||||
const int half = COUNTER_SECTION_END_ / 2;
|
|
||||||
|
|
||||||
if (counter_ < half) {
|
|
||||||
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_, 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() {
|
|
||||||
player_sprite_->render(1, color_);
|
|
||||||
tv_sprite_->render(1, color_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza los contadores
|
|
||||||
void GameOver::updateCounters() {
|
|
||||||
// Actualiza el contador
|
|
||||||
if (pre_counter_ < 50) {
|
|
||||||
pre_counter_++;
|
|
||||||
} else {
|
|
||||||
counter_++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hace sonar la música
|
|
||||||
if (counter_ == 1) {
|
|
||||||
JA_PlayMusic(Resource::get()->getMusic("game_over.ogg"), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si ha terminado la sección
|
|
||||||
else if (counter_ == COUNTER_SECTION_END_) {
|
|
||||||
options.section.section = Section::LOGO;
|
|
||||||
options.section.subsection = Subsection::LOGO_TO_TITLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
#include "loading_screen.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
#include <stdlib.h> // Para rand
|
|
||||||
|
|
||||||
#include "defines.h" // Para GAME_SPEED
|
|
||||||
#include "external/jail_audio.h" // Para JA_PlayMusic, JA_SetVolume, JA_StopMusic
|
|
||||||
#include "global_events.h" // Para check
|
|
||||||
#include "global_inputs.h" // Para check
|
|
||||||
#include "options.h" // Para Options, options, SectionState, Options...
|
|
||||||
#include "resource.h" // Para Resource
|
|
||||||
#include "screen.h" // Para Screen
|
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
|
||||||
#include "surface.h" // Para Surface
|
|
||||||
#include "utils.h" // Para stringToColor, PaletteColor
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
LoadingScreen::LoadingScreen()
|
|
||||||
: mono_loading_screen_surface_(Resource::get()->getSurface("loading_screen_bn.gif")),
|
|
||||||
color_loading_screen_surface_(Resource::get()->getSurface("loading_screen_color.gif")),
|
|
||||||
mono_loading_screen_sprite_(std::make_shared<SSprite>(mono_loading_screen_surface_, 0, 0, mono_loading_screen_surface_->getWidth(), mono_loading_screen_surface_->getHeight())),
|
|
||||||
color_loading_screen_sprite_(std::make_shared<SSprite>(color_loading_screen_surface_, 0, 0, color_loading_screen_surface_->getWidth(), color_loading_screen_surface_->getHeight())),
|
|
||||||
screen_surface_(std::make_shared<Surface>(options.game.width, options.game.height)) {
|
|
||||||
// Configura la superficie donde se van a pintar los sprites
|
|
||||||
screen_surface_->clear(static_cast<Uint8>(PaletteColor::WHITE));
|
|
||||||
|
|
||||||
// Inicializa variables
|
|
||||||
options.section.section = Section::LOADING_SCREEN;
|
|
||||||
options.section.subsection = Subsection::NONE;
|
|
||||||
|
|
||||||
// Establece el orden de las lineas para imitar el direccionamiento de memoria del spectrum
|
|
||||||
for (int i = 0; i < 192; ++i) {
|
|
||||||
if (i < 64) { // Primer bloque de 2K
|
|
||||||
line_index_[i] = ((i % 8) * 8) + (i / 8);
|
|
||||||
} else if (i < 128) { // Segundo bloque de 2K
|
|
||||||
line_index_[i] = 64 + ((i % 8) * 8) + ((i - 64) / 8);
|
|
||||||
} else { // Tercer bloque de 2K
|
|
||||||
line_index_[i] = 128 + ((i % 8) * 8) + ((i - 128) / 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cambia el color del borde
|
|
||||||
Screen::get()->setBorderColor(stringToColor("black"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
LoadingScreen::~LoadingScreen() {
|
|
||||||
JA_StopMusic();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba el manejador de eventos
|
|
||||||
void LoadingScreen::checkEvents() {
|
|
||||||
SDL_Event event;
|
|
||||||
while (SDL_PollEvent(&event)) {
|
|
||||||
globalEvents::check(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba las entradas
|
|
||||||
void LoadingScreen::checkInput() {
|
|
||||||
globalInputs::check();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gestiona el contador de carga
|
|
||||||
void LoadingScreen::updateLoad() {
|
|
||||||
// Primera parte de la carga, la parte en blanco y negro
|
|
||||||
if (loading_first_part_) {
|
|
||||||
// Cada 5 pasos el load_counter_ se incrementa en uno
|
|
||||||
constexpr int NUM_STEPS = 5;
|
|
||||||
constexpr int STEPS = 51;
|
|
||||||
load_counter_ = counter_ / NUM_STEPS;
|
|
||||||
|
|
||||||
if (load_counter_ < 192) {
|
|
||||||
load_rect_.x = STEPS * (counter_ % NUM_STEPS);
|
|
||||||
load_rect_.y = line_index_[load_counter_];
|
|
||||||
mono_loading_screen_sprite_->setClip(load_rect_);
|
|
||||||
mono_loading_screen_sprite_->setPosition(load_rect_);
|
|
||||||
}
|
|
||||||
// Una vez actualizadas las 192 lineas, pasa a la segunda fase de la carga
|
|
||||||
else if (load_counter_ == 192) {
|
|
||||||
loading_first_part_ = false;
|
|
||||||
load_counter_ = 0;
|
|
||||||
load_rect_ = {0, 0, 16, 8};
|
|
||||||
color_loading_screen_sprite_->setClip(load_rect_);
|
|
||||||
color_loading_screen_sprite_->setPosition(load_rect_);
|
|
||||||
JA_PlayMusic(Resource::get()->getMusic("loading_sound3.ogg"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Segunda parte de la carga, la parte de los bloques en color
|
|
||||||
else {
|
|
||||||
load_counter_ += 2;
|
|
||||||
load_rect_.x = (load_counter_ * 8) % 256;
|
|
||||||
load_rect_.y = (load_counter_ / 32) * 8;
|
|
||||||
color_loading_screen_sprite_->setClip(load_rect_);
|
|
||||||
color_loading_screen_sprite_->setPosition(load_rect_);
|
|
||||||
|
|
||||||
// Comprueba si ha terminado la intro
|
|
||||||
if (load_counter_ >= 768) {
|
|
||||||
options.section.section = Section::TITLE;
|
|
||||||
options.section.subsection = Subsection::TITLE_WITH_LOADING_SCREEN;
|
|
||||||
JA_StopMusic();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gestiona el contador interno
|
|
||||||
void LoadingScreen::updateCounter() {
|
|
||||||
(pre_counter_ >= 50) ? counter_++ : pre_counter_++;
|
|
||||||
|
|
||||||
if (counter_ == 1) {
|
|
||||||
JA_PlayMusic(Resource::get()->getMusic("loading_sound2.ogg"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja la pantalla de carga
|
|
||||||
void LoadingScreen::renderLoad() {
|
|
||||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
||||||
Screen::get()->setRendererSurface(screen_surface_);
|
|
||||||
loading_first_part_ ? mono_loading_screen_sprite_->render(1, stringToColor("black")) : color_loading_screen_sprite_->render();
|
|
||||||
Screen::get()->setRendererSurface(previuos_renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja el efecto de carga en el borde
|
|
||||||
void LoadingScreen::renderBorder() {
|
|
||||||
// Obtiene la Surface del borde
|
|
||||||
auto border = Screen::get()->getBorderSurface();
|
|
||||||
|
|
||||||
// Pinta el borde de color azul
|
|
||||||
border->clear(static_cast<Uint8>(PaletteColor::BLUE));
|
|
||||||
|
|
||||||
// Añade lineas amarillas
|
|
||||||
const Uint8 COLOR = static_cast<Uint8>(PaletteColor::YELLOW);
|
|
||||||
const int WIDTH = options.game.width + (options.video.border.width * 2);
|
|
||||||
const int HEIGHT = options.game.height + (options.video.border.height * 2);
|
|
||||||
bool draw_enabled = rand() % 2 == 0 ? true : false;
|
|
||||||
|
|
||||||
int row = 0;
|
|
||||||
while (row < HEIGHT) {
|
|
||||||
const int ROW_HEIGHT = (rand() % 4) + 3;
|
|
||||||
if (draw_enabled) {
|
|
||||||
for (int i = row; i < row + ROW_HEIGHT; ++i) {
|
|
||||||
border->drawLine(0, i, WIDTH, i, COLOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
row += ROW_HEIGHT;
|
|
||||||
draw_enabled = !draw_enabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza las variables
|
|
||||||
void LoadingScreen::update() {
|
|
||||||
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
|
||||||
if (SDL_GetTicks() - ticks_ > GAME_SPEED) {
|
|
||||||
ticks_ = SDL_GetTicks();
|
|
||||||
checkInput();
|
|
||||||
updateCounter();
|
|
||||||
updateLoad();
|
|
||||||
renderLoad();
|
|
||||||
Screen::get()->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja en pantalla
|
|
||||||
void LoadingScreen::render() {
|
|
||||||
if (options.video.border.enabled) {
|
|
||||||
// Dibuja el efecto de carga en el borde
|
|
||||||
renderBorder();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepara para empezar a dibujar en la textura de juego
|
|
||||||
Screen::get()->start();
|
|
||||||
Screen::get()->clearSurface(stringToColor("white"));
|
|
||||||
|
|
||||||
// Copia la surface a la surface de Screen
|
|
||||||
screen_surface_->render(0, 0);
|
|
||||||
|
|
||||||
// Vuelca el contenido del renderizador en pantalla
|
|
||||||
Screen::get()->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bucle para el logo del juego
|
|
||||||
void LoadingScreen::run() {
|
|
||||||
// Inicia el sonido de carga
|
|
||||||
JA_SetVolume(64);
|
|
||||||
JA_PlayMusic(Resource::get()->getMusic("loading_sound1.ogg"));
|
|
||||||
|
|
||||||
// Limpia la pantalla
|
|
||||||
Screen::get()->start();
|
|
||||||
Screen::get()->clearRenderer();
|
|
||||||
Screen::get()->render();
|
|
||||||
|
|
||||||
while (options.section.section == Section::LOADING_SCREEN) {
|
|
||||||
update();
|
|
||||||
checkEvents();
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
|
|
||||||
JA_SetVolume(128);
|
|
||||||
}
|
|
||||||
@@ -1,332 +0,0 @@
|
|||||||
#include "title.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include <algorithm> // Para clamp
|
|
||||||
|
|
||||||
#include "cheevos.h" // Para Cheevos, Achievement
|
|
||||||
#include "defines.h" // Para PLAY_AREA_CENTER_X, GAMECANVAS_WIDTH
|
|
||||||
#include "global_events.h" // Para check
|
|
||||||
#include "global_inputs.h" // Para check
|
|
||||||
#include "input.h" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT, REP...
|
|
||||||
#include "options.h" // Para Options, options, SectionState, Section
|
|
||||||
#include "resource.h" // Para Resource
|
|
||||||
#include "screen.h" // Para Screen
|
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
|
||||||
#include "surface.h" // Para Surface
|
|
||||||
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR
|
|
||||||
#include "utils.h" // Para stringToColor, PaletteColor, playMusic
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Title::Title()
|
|
||||||
: title_logo_surface_(Resource::get()->getSurface("title_logo.gif")),
|
|
||||||
title_logo_sprite_(std::make_shared<SSprite>(title_logo_surface_, 29, 9, title_logo_surface_->getWidth(), title_logo_surface_->getHeight())),
|
|
||||||
loading_screen_surface_(Resource::get()->getSurface("loading_screen_color.gif")),
|
|
||||||
loading_screen_sprite_(std::make_shared<SSprite>(loading_screen_surface_, 0, 0, loading_screen_surface_->getWidth(), loading_screen_surface_->getHeight())),
|
|
||||||
bg_surface_(std::make_shared<Surface>(options.game.width, options.game.height)) {
|
|
||||||
// Inicializa variables
|
|
||||||
state_ = options.section.subsection == Subsection::TITLE_WITH_LOADING_SCREEN ? TitleState::SHOW_LOADING_SCREEN : TitleState::SHOW_MENU;
|
|
||||||
options.section.section = Section::TITLE;
|
|
||||||
options.section.subsection = Subsection::NONE;
|
|
||||||
initMarquee();
|
|
||||||
|
|
||||||
// Crea y rellena la textura para mostrar los logros
|
|
||||||
createCheevosTexture();
|
|
||||||
|
|
||||||
// Cambia el color del borde
|
|
||||||
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK));
|
|
||||||
|
|
||||||
// Rellena la textura de fondo con todos los gráficos
|
|
||||||
fillSurface();
|
|
||||||
|
|
||||||
// Inicia la musica
|
|
||||||
playMusic("title.ogg");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa la marquesina
|
|
||||||
void Title::initMarquee() {
|
|
||||||
letters_.clear();
|
|
||||||
long_text_ = "HEY JAILERS!! IT'S 2022 AND WE'RE STILL ROCKING LIKE IT'S 1998!!! HAVE YOU HEARD IT? JAILGAMES ARE BACK!! YEEESSS BACK!! MORE THAN 10 TITLES ON JAILDOC'S KITCHEN!! THATS A LOOOOOOT OF JAILGAMES, BUT WHICH ONE WILL STRIKE FIRST? THERE IS ALSO A NEW DEVICE TO COME THAT WILL BLOW YOUR MIND WITH JAILGAMES ON THE GO: P.A.C.O. BUT WAIT! WHAT'S THAT BEAUTY I'M SEEING RIGHT OVER THERE?? OOOH THAT TINY MINIASCII IS PURE LOVE!! I WANT TO LICK EVERY BYTE OF IT!! OH SHIT! AND DON'T FORGET TO BRING BACK THOSE OLD AND FAT MS-DOS JAILGAMES TO GITHUB TO KEEP THEM ALIVE!! WHAT WILL BE THE NEXT JAILDOC RELEASE? WHAT WILL BE THE NEXT PROJECT TO COME ALIVE?? OH BABY WE DON'T KNOW BUT HERE YOU CAN FIND THE ANSWER, YOU JUST HAVE TO COMPLETE JAILDOCTOR'S DILEMMA ... COULD YOU?";
|
|
||||||
for (int i = 0; i < (int)long_text_.length(); ++i) {
|
|
||||||
TitleLetter l;
|
|
||||||
l.letter = long_text_.substr(i, 1);
|
|
||||||
l.x = 256;
|
|
||||||
l.enabled = false;
|
|
||||||
letters_.push_back(l);
|
|
||||||
}
|
|
||||||
letters_[0].enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba el manejador de eventos
|
|
||||||
void Title::checkEvents() {
|
|
||||||
SDL_Event event;
|
|
||||||
while (SDL_PollEvent(&event)) {
|
|
||||||
globalEvents::check(event);
|
|
||||||
|
|
||||||
// Solo se comprueban estas teclas si no está activo el menu de logros
|
|
||||||
if (event.type == SDL_EVENT_KEY_DOWN) {
|
|
||||||
if (!show_cheevos_) {
|
|
||||||
switch (event.key.key) {
|
|
||||||
case SDLK_1:
|
|
||||||
options.section.section = Section::GAME;
|
|
||||||
options.section.subsection = Subsection::NONE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDLK_2:
|
|
||||||
show_cheevos_ = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba las entradas
|
|
||||||
void Title::checkInput() {
|
|
||||||
if (show_cheevos_) {
|
|
||||||
if (Input::get()->checkInput(InputAction::DOWN, INPUT_ALLOW_REPEAT)) {
|
|
||||||
moveCheevosList(1);
|
|
||||||
} else if (Input::get()->checkInput(InputAction::UP, INPUT_ALLOW_REPEAT)) {
|
|
||||||
moveCheevosList(0);
|
|
||||||
} else if (Input::get()->checkInput(InputAction::ACCEPT, INPUT_DO_NOT_ALLOW_REPEAT)) {
|
|
||||||
hideCheevosList();
|
|
||||||
counter_ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Input::get()->checkInput(InputAction::ACCEPT, INPUT_DO_NOT_ALLOW_REPEAT)) {
|
|
||||||
if (state_ == TitleState::SHOW_LOADING_SCREEN) {
|
|
||||||
state_ = TitleState::FADE_LOADING_SCREEN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
globalInputs::check();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza la marquesina
|
|
||||||
void Title::updateMarquee() {
|
|
||||||
const auto TEXT = Resource::get()->getText("gauntlet");
|
|
||||||
|
|
||||||
for (int i = 0; i < (int)letters_.size(); ++i) {
|
|
||||||
if (letters_[i].enabled) {
|
|
||||||
letters_[i].x -= marquee_speed_;
|
|
||||||
if (letters_[i].x < -10) {
|
|
||||||
letters_[i].enabled = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (i > 0 && letters_[i - 1].x < 256 && letters_[i - 1].enabled) {
|
|
||||||
letters_[i].enabled = true;
|
|
||||||
letters_[i].x = letters_[i - 1].x + TEXT->lenght(letters_[i - 1].letter) + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si ha terminado la marquesina y la reinicia
|
|
||||||
if (letters_[letters_.size() - 1].x < -10) {
|
|
||||||
// Inicializa la marquesina
|
|
||||||
initMarquee();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja la marquesina
|
|
||||||
void Title::renderMarquee() {
|
|
||||||
const auto TEXT = Resource::get()->getText("gauntlet");
|
|
||||||
for (const auto& l : letters_) {
|
|
||||||
if (l.enabled) {
|
|
||||||
TEXT->writeColored(l.x, 184, l.letter, static_cast<Uint8>(PaletteColor::BRIGHT_RED));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza las variables
|
|
||||||
void Title::update() {
|
|
||||||
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
|
||||||
if (SDL_GetTicks() - ticks_ > GAME_SPEED) {
|
|
||||||
// Actualiza el contador de ticks
|
|
||||||
ticks_ = SDL_GetTicks();
|
|
||||||
|
|
||||||
// Comprueba las entradas
|
|
||||||
checkInput();
|
|
||||||
|
|
||||||
Screen::get()->update();
|
|
||||||
|
|
||||||
// Incrementa el contador
|
|
||||||
counter_++;
|
|
||||||
|
|
||||||
switch (state_) {
|
|
||||||
case TitleState::SHOW_LOADING_SCREEN:
|
|
||||||
if (counter_ == 500) {
|
|
||||||
counter_ = 0;
|
|
||||||
state_ = TitleState::FADE_LOADING_SCREEN;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TitleState::FADE_LOADING_SCREEN:
|
|
||||||
if (counter_ % 4 == 0) {
|
|
||||||
if (loading_screen_surface_->fadeSubPalette()) {
|
|
||||||
counter_ = 0;
|
|
||||||
state_ = TitleState::SHOW_MENU;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TitleState::SHOW_MENU:
|
|
||||||
// Actualiza la marquesina
|
|
||||||
updateMarquee();
|
|
||||||
|
|
||||||
// Si el contador alcanza cierto valor, termina la seccion
|
|
||||||
if (counter_ == 2200) {
|
|
||||||
if (!show_cheevos_) {
|
|
||||||
options.section.section = Section::CREDITS;
|
|
||||||
options.section.subsection = Subsection::NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja en pantalla
|
|
||||||
void Title::render() {
|
|
||||||
// Prepara para empezar a dibujar en la textura de juego
|
|
||||||
Screen::get()->start();
|
|
||||||
Screen::get()->clearSurface(static_cast<Uint8>(PaletteColor::BLACK));
|
|
||||||
|
|
||||||
switch (state_) {
|
|
||||||
case TitleState::SHOW_MENU:
|
|
||||||
// Dibuja la textura de fondo
|
|
||||||
bg_surface_->render(0, 0);
|
|
||||||
|
|
||||||
// Dibuja la marquesina
|
|
||||||
renderMarquee();
|
|
||||||
|
|
||||||
// Dibuja la información de logros
|
|
||||||
if (show_cheevos_) {
|
|
||||||
cheevos_sprite_->render();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TitleState::SHOW_LOADING_SCREEN:
|
|
||||||
case TitleState::FADE_LOADING_SCREEN:
|
|
||||||
loading_screen_sprite_->render();
|
|
||||||
title_logo_sprite_->render();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vuelca el contenido del renderizador en pantalla
|
|
||||||
Screen::get()->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bucle para el logo del juego
|
|
||||||
void Title::run() {
|
|
||||||
while (options.section.section == Section::TITLE) {
|
|
||||||
update();
|
|
||||||
checkEvents();
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Desplaza la lista de logros
|
|
||||||
void Title::moveCheevosList(int direction) {
|
|
||||||
// Modifica la posición de la ventana de vista
|
|
||||||
constexpr int SPEED = 2;
|
|
||||||
cheevos_surface_view_.y = direction == 0 ? cheevos_surface_view_.y - SPEED : cheevos_surface_view_.y + SPEED;
|
|
||||||
|
|
||||||
// Ajusta los limites
|
|
||||||
const float BOTTOM = cheevos_surface_->getHeight() - cheevos_surface_view_.h;
|
|
||||||
cheevos_surface_view_.y = std::clamp(cheevos_surface_view_.y, 0.0F, BOTTOM);
|
|
||||||
|
|
||||||
cheevos_sprite_->setClip(cheevos_surface_view_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rellena la textura de fondo con todos los gráficos
|
|
||||||
void Title::fillSurface() {
|
|
||||||
// Coloca el puntero del renderizador sobre la textura
|
|
||||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
||||||
Screen::get()->setRendererSurface(bg_surface_);
|
|
||||||
|
|
||||||
// Rellena la textura de color
|
|
||||||
bg_surface_->clear(static_cast<Uint8>(PaletteColor::BLACK));
|
|
||||||
|
|
||||||
// Pinta el gráfico del titulo a partir del sprite
|
|
||||||
title_logo_sprite_->render();
|
|
||||||
|
|
||||||
// Escribe el texto en la textura
|
|
||||||
auto text = Resource::get()->getText("smb2");
|
|
||||||
const Uint8 COLOR = stringToColor("green");
|
|
||||||
const int TEXT_SIZE = text->getCharacterSize();
|
|
||||||
text->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 11 * TEXT_SIZE, "1.PLAY", 1, COLOR);
|
|
||||||
text->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 13 * TEXT_SIZE, "2.ACHIEVEMENTS", 1, COLOR);
|
|
||||||
text->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 15 * TEXT_SIZE, "3.REDEFINE KEYS", 1, COLOR);
|
|
||||||
|
|
||||||
// Devuelve el puntero del renderizador a su sitio
|
|
||||||
Screen::get()->setRendererSurface(previuos_renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crea y rellena la textura para mostrar los logros
|
|
||||||
void Title::createCheevosTexture() {
|
|
||||||
// Crea la textura con el listado de logros
|
|
||||||
const auto CHEEVOS_LIST = Cheevos::get()->list();
|
|
||||||
const auto TEXT = Resource::get()->getText("subatomic");
|
|
||||||
constexpr int CHEEVOS_TEXTURE_WIDTH = 200;
|
|
||||||
constexpr int CHEEVOS_TEXTURE_VIEW_HEIGHT = 110 - 8;
|
|
||||||
constexpr int CHEEVOS_TEXTURE_POS_Y = 73;
|
|
||||||
constexpr int CHEEVOS_PADDING = 10;
|
|
||||||
const int CHEEVO_HEIGHT = CHEEVOS_PADDING + (TEXT->getCharacterSize() * 2) + 1;
|
|
||||||
const int CHEEVOS_TEXTURE_HEIGHT = (CHEEVO_HEIGHT * CHEEVOS_LIST.size()) + 2 + TEXT->getCharacterSize() + 8;
|
|
||||||
cheevos_surface_ = std::make_shared<Surface>(CHEEVOS_TEXTURE_WIDTH, CHEEVOS_TEXTURE_HEIGHT);
|
|
||||||
|
|
||||||
// Prepara para dibujar sobre la textura
|
|
||||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
||||||
Screen::get()->setRendererSurface(cheevos_surface_);
|
|
||||||
|
|
||||||
// Rellena la textura con color sólido
|
|
||||||
const Uint8 CHEEVOS_BG_COLOR = static_cast<Uint8>(PaletteColor::BLACK);
|
|
||||||
cheevos_surface_->clear(CHEEVOS_BG_COLOR);
|
|
||||||
|
|
||||||
// Escribe la lista de logros en la textura
|
|
||||||
const std::string CHEEVOS_OWNER = "ACHIEVEMENTS";
|
|
||||||
const std::string CHEEVOS_LIST_CAPTION = CHEEVOS_OWNER + " (" + std::to_string(Cheevos::get()->getTotalUnlockedAchievements()) + " / " + std::to_string(Cheevos::get()->size()) + ")";
|
|
||||||
int pos = 2;
|
|
||||||
TEXT->writeDX(TEXT_CENTER | TEXT_COLOR, cheevos_surface_->getWidth() / 2, pos, CHEEVOS_LIST_CAPTION, 1, stringToColor("bright_green"));
|
|
||||||
pos += TEXT->getCharacterSize();
|
|
||||||
const Uint8 CHEEVO_LOCKED_COLOR = stringToColor("white");
|
|
||||||
const Uint8 CHEEVO_UNLOCKED_COLOR = stringToColor("bright_green");
|
|
||||||
constexpr int LINE_X1 = (CHEEVOS_TEXTURE_WIDTH / 7) * 3;
|
|
||||||
constexpr int LINE_X2 = LINE_X1 + ((CHEEVOS_TEXTURE_WIDTH / 7) * 1);
|
|
||||||
|
|
||||||
for (const auto& cheevo : CHEEVOS_LIST) {
|
|
||||||
const Uint8 CHEEVO_COLOR = cheevo.completed ? CHEEVO_UNLOCKED_COLOR : CHEEVO_LOCKED_COLOR;
|
|
||||||
pos += CHEEVOS_PADDING;
|
|
||||||
constexpr int HALF = CHEEVOS_PADDING / 2;
|
|
||||||
cheevos_surface_->drawLine(LINE_X1, pos - HALF - 1, LINE_X2, pos - HALF - 1, CHEEVO_COLOR);
|
|
||||||
TEXT->writeDX(TEXT_CENTER | TEXT_COLOR, CHEEVOS_TEXTURE_WIDTH / 2, pos, cheevo.caption, 1, CHEEVO_COLOR);
|
|
||||||
pos += TEXT->getCharacterSize() + 1;
|
|
||||||
TEXT->writeDX(TEXT_CENTER | TEXT_COLOR, CHEEVOS_TEXTURE_WIDTH / 2, pos, cheevo.description, 1, CHEEVO_COLOR);
|
|
||||||
pos += TEXT->getCharacterSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restablece el RenderSurface
|
|
||||||
Screen::get()->setRendererSurface(previuos_renderer);
|
|
||||||
|
|
||||||
// Crea el sprite para el listado de logros
|
|
||||||
cheevos_sprite_ = std::make_shared<SSprite>(cheevos_surface_, (GAMECANVAS_WIDTH - cheevos_surface_->getWidth()) / 2, CHEEVOS_TEXTURE_POS_Y, cheevos_surface_->getWidth(), cheevos_surface_->getHeight());
|
|
||||||
cheevos_surface_view_ = {0, 0, cheevos_surface_->getWidth(), CHEEVOS_TEXTURE_VIEW_HEIGHT};
|
|
||||||
cheevos_sprite_->setClip(cheevos_surface_view_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Oculta la lista de logros
|
|
||||||
void Title::hideCheevosList() {
|
|
||||||
show_cheevos_ = false;
|
|
||||||
cheevos_surface_view_.y = 0;
|
|
||||||
cheevos_sprite_->setClip(cheevos_surface_view_);
|
|
||||||
}
|
|
||||||
@@ -1,564 +0,0 @@
|
|||||||
// IWYU pragma: no_include <bits/std_abs.h>
|
|
||||||
#include "surface.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include <algorithm> // Para min, max, copy_n, fill
|
|
||||||
#include <cmath> // Para abs
|
|
||||||
#include <cstdint> // Para uint32_t
|
|
||||||
#include <cstring> // Para memcpy, size_t
|
|
||||||
#include <fstream> // Para basic_ifstream, basic_ostream, basic_ist...
|
|
||||||
#include <iostream> // Para cerr
|
|
||||||
#include <memory> // Para shared_ptr, __shared_ptr_access, default...
|
|
||||||
#include <sstream> // Para basic_istringstream
|
|
||||||
#include <stdexcept> // Para runtime_error
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "gif.h" // Para Gif
|
|
||||||
#include "screen.h" // Para Screen
|
|
||||||
|
|
||||||
// Carga una paleta desde un archivo .gif
|
|
||||||
Palette 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtener el tamaño del archivo y leerlo 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
|
|
||||||
GIF::Gif gif;
|
|
||||||
std::vector<uint32_t> pal = gif.loadPalette(buffer.data());
|
|
||||||
if (pal.empty()) {
|
|
||||||
throw std::runtime_error("No palette found in GIF file: " + file_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crear la paleta y copiar los datos desde 'pal'
|
|
||||||
Palette palette = {}; // Inicializa la paleta con ceros
|
|
||||||
std::copy_n(pal.begin(), std::min(pal.size(), palette.size()), palette.begin());
|
|
||||||
|
|
||||||
// Mensaje de depuración
|
|
||||||
printWithDots("Palette : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]");
|
|
||||||
|
|
||||||
return palette;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carga una paleta desde un archivo .pal
|
|
||||||
Palette readPalFile(const std::string& file_path) {
|
|
||||||
Palette palette{};
|
|
||||||
palette.fill(0); // Inicializar todo con 0 (transparente por defecto)
|
|
||||||
|
|
||||||
std::ifstream file(file_path);
|
|
||||||
if (!file.is_open()) {
|
|
||||||
throw std::runtime_error("No se pudo abrir el archivo .pal");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string line;
|
|
||||||
int line_number = 0;
|
|
||||||
int color_index = 0;
|
|
||||||
|
|
||||||
while (std::getline(file, line)) {
|
|
||||||
++line_number;
|
|
||||||
|
|
||||||
// Ignorar las tres primeras líneas del archivo
|
|
||||||
if (line_number <= 3) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Procesar las líneas restantes con valores RGB
|
|
||||||
std::istringstream ss(line);
|
|
||||||
int r, g, b;
|
|
||||||
if (ss >> r >> g >> b) {
|
|
||||||
// Construir el color ARGB (A = 255 por defecto)
|
|
||||||
Uint32 color = (255 << 24) | (r << 16) | (g << 8) | b;
|
|
||||||
palette[color_index++] = color;
|
|
||||||
|
|
||||||
// Limitar a un máximo de 256 colores (opcional)
|
|
||||||
if (color_index >= 256) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
return palette;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Surface::Surface(int w, int h)
|
|
||||||
: surface_data_(std::make_shared<SurfaceData>(w, h)),
|
|
||||||
transparent_color_(static_cast<Uint8>(PaletteColor::TRANSPARENT)) { initializeSubPalette(sub_palette_); }
|
|
||||||
|
|
||||||
Surface::Surface(const std::string& file_path)
|
|
||||||
: transparent_color_(static_cast<Uint8>(PaletteColor::TRANSPARENT)) {
|
|
||||||
SurfaceData loadedData = loadSurface(file_path);
|
|
||||||
surface_data_ = std::make_shared<SurfaceData>(std::move(loadedData));
|
|
||||||
|
|
||||||
initializeSubPalette(sub_palette_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carga una superficie desde un archivo
|
|
||||||
SurfaceData Surface::loadSurface(const std::string& file_path) {
|
|
||||||
// Abrir el archivo usando std::ifstream para manejo automático del recurso
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtener el tamaño del archivo
|
|
||||||
std::streamsize size = file.tellg();
|
|
||||||
file.seekg(0, std::ios::beg);
|
|
||||||
|
|
||||||
// Leer el contenido del archivo en un buffer
|
|
||||||
std::vector<Uint8> buffer(size);
|
|
||||||
if (!file.read(reinterpret_cast<char*>(buffer.data()), size)) {
|
|
||||||
std::cerr << "Error reading file: " << file_path << std::endl;
|
|
||||||
throw std::runtime_error("Error reading file");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crear un objeto Gif y llamar a la función loadGif
|
|
||||||
GIF::Gif gif;
|
|
||||||
Uint16 w = 0, h = 0;
|
|
||||||
std::vector<Uint8> rawPixels = gif.loadGif(buffer.data(), w, h);
|
|
||||||
if (rawPixels.empty()) {
|
|
||||||
std::cerr << "Error loading GIF from file: " << file_path << std::endl;
|
|
||||||
throw std::runtime_error("Error loading GIF");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si el constructor de Surface espera un std::shared_ptr<Uint8[]>,
|
|
||||||
// reservamos un bloque dinámico y copiamos los datos del vector.
|
|
||||||
size_t pixelCount = rawPixels.size();
|
|
||||||
auto pixels = std::shared_ptr<Uint8[]>(new Uint8[pixelCount], std::default_delete<Uint8[]>());
|
|
||||||
std::memcpy(pixels.get(), rawPixels.data(), pixelCount);
|
|
||||||
|
|
||||||
// Crear y devolver directamente el objeto SurfaceData
|
|
||||||
printWithDots("Surface : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]");
|
|
||||||
return SurfaceData(w, h, pixels);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carga una paleta desde un archivo
|
|
||||||
void Surface::loadPalette(const std::string& file_path) {
|
|
||||||
palette_ = ::loadPalette(file_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carga una paleta desde otra paleta
|
|
||||||
void Surface::loadPalette(Palette palette) {
|
|
||||||
palette_ = palette;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Establece un color en la paleta
|
|
||||||
void Surface::setColor(int index, Uint32 color) {
|
|
||||||
palette_.at(index) = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rellena la superficie con un color
|
|
||||||
void Surface::clear(Uint8 color) {
|
|
||||||
const size_t total_pixels = surface_data_->width * surface_data_->height;
|
|
||||||
Uint8* data_ptr = surface_data_->data.get();
|
|
||||||
std::fill(data_ptr, data_ptr + total_pixels, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pone un pixel en la SurfaceData
|
|
||||||
void Surface::putPixel(int x, int y, Uint8 color) {
|
|
||||||
if (x < 0 || y < 0 || x >= surface_data_->width || y >= surface_data_->height) {
|
|
||||||
return; // Coordenadas fuera de rango
|
|
||||||
}
|
|
||||||
|
|
||||||
const int index = x + y * surface_data_->width;
|
|
||||||
surface_data_->data.get()[index] = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtiene el color de un pixel de la surface_data
|
|
||||||
Uint8 Surface::getPixel(int x, int y) { return surface_data_->data.get()[x + y * static_cast<int>(surface_data_->width)]; }
|
|
||||||
|
|
||||||
// Dibuja un rectangulo relleno
|
|
||||||
void Surface::fillRect(const SDL_FRect* rect, Uint8 color) {
|
|
||||||
// Limitar los valores del rectángulo al tamaño de la superficie
|
|
||||||
float x_start = std::max(0.0F, rect->x);
|
|
||||||
float y_start = std::max(0.0F, rect->y);
|
|
||||||
float x_end = std::min(rect->x + rect->w, surface_data_->width);
|
|
||||||
float y_end = std::min(rect->y + rect->h, surface_data_->height);
|
|
||||||
|
|
||||||
// Recorrer cada píxel dentro del rectángulo directamente
|
|
||||||
for (int y = y_start; y < y_end; ++y) {
|
|
||||||
for (int x = x_start; x < x_end; ++x) {
|
|
||||||
const int INDEX = x + y * surface_data_->width;
|
|
||||||
surface_data_->data.get()[INDEX] = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja el borde de un rectangulo
|
|
||||||
void Surface::drawRectBorder(const SDL_FRect* rect, Uint8 color) {
|
|
||||||
// Limitar los valores del rectángulo al tamaño de la superficie
|
|
||||||
float x_start = std::max(0.0F, rect->x);
|
|
||||||
float y_start = std::max(0.0F, rect->y);
|
|
||||||
float x_end = std::min(rect->x + rect->w, surface_data_->width);
|
|
||||||
float y_end = std::min(rect->y + rect->h, surface_data_->height);
|
|
||||||
|
|
||||||
// Dibujar bordes horizontales
|
|
||||||
for (int x = x_start; x < x_end; ++x) {
|
|
||||||
// Borde superior
|
|
||||||
const int top_index = x + y_start * surface_data_->width;
|
|
||||||
surface_data_->data.get()[top_index] = color;
|
|
||||||
|
|
||||||
// Borde inferior
|
|
||||||
const int bottom_index = x + (y_end - 1) * surface_data_->width;
|
|
||||||
surface_data_->data.get()[bottom_index] = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibujar bordes verticales
|
|
||||||
for (int y = y_start; y < y_end; ++y) {
|
|
||||||
// Borde izquierdo
|
|
||||||
const int LEFT_INDEX = x_start + y * surface_data_->width;
|
|
||||||
surface_data_->data.get()[LEFT_INDEX] = color;
|
|
||||||
|
|
||||||
// Borde derecho
|
|
||||||
const int RIGHT_INDEX = (x_end - 1) + y * surface_data_->width;
|
|
||||||
surface_data_->data.get()[RIGHT_INDEX] = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja una linea
|
|
||||||
void Surface::drawLine(float x1, float y1, float x2, float y2, Uint8 color) {
|
|
||||||
// Calcula las diferencias
|
|
||||||
float dx = std::abs(x2 - x1);
|
|
||||||
float dy = std::abs(y2 - y1);
|
|
||||||
|
|
||||||
// Determina la dirección del incremento
|
|
||||||
float sx = (x1 < x2) ? 1 : -1;
|
|
||||||
float sy = (y1 < y2) ? 1 : -1;
|
|
||||||
|
|
||||||
float err = dx - dy;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
// Asegúrate de no dibujar fuera de los límites de la superficie
|
|
||||||
if (x1 >= 0 && x1 < surface_data_->width && y1 >= 0 && y1 < surface_data_->height) {
|
|
||||||
surface_data_->data.get()[static_cast<size_t>(x1 + y1 * surface_data_->width)] = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si alcanzamos el punto final, salimos
|
|
||||||
if (x1 == x2 && y1 == y2)
|
|
||||||
break;
|
|
||||||
|
|
||||||
int e2 = 2 * err;
|
|
||||||
if (e2 > -dy) {
|
|
||||||
err -= dy;
|
|
||||||
x1 += sx;
|
|
||||||
}
|
|
||||||
if (e2 < dx) {
|
|
||||||
err += dx;
|
|
||||||
y1 += sy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Surface::render(float dx, float dy, float sx, float sy, float w, float h) {
|
|
||||||
auto surface_data = Screen::get()->getRendererSurface()->getSurfaceData();
|
|
||||||
|
|
||||||
// Limitar la región para evitar accesos fuera de rango en origen
|
|
||||||
w = std::min(w, surface_data_->width - sx);
|
|
||||||
h = std::min(h, surface_data_->height - sy);
|
|
||||||
|
|
||||||
// Limitar la región para evitar accesos fuera de rango en destino
|
|
||||||
w = std::min(w, surface_data->width - dx);
|
|
||||||
h = std::min(h, surface_data->height - dy);
|
|
||||||
|
|
||||||
for (int iy = 0; iy < h; ++iy) {
|
|
||||||
for (int ix = 0; ix < w; ++ix) {
|
|
||||||
// Verificar que las coordenadas de destino están dentro de los límites
|
|
||||||
if (int dest_x = dx + ix; dest_x >= 0 && dest_x < surface_data->width) {
|
|
||||||
if (int dest_y = dy + iy; dest_y >= 0 && dest_y < surface_data->height) {
|
|
||||||
int src_x = sx + ix;
|
|
||||||
int src_y = sy + iy;
|
|
||||||
|
|
||||||
Uint8 color = surface_data_->data.get()[static_cast<size_t>(src_x + src_y * surface_data_->width)];
|
|
||||||
if (color != transparent_color_) {
|
|
||||||
surface_data->data.get()[static_cast<size_t>(dest_x + dest_y * surface_data->width)] = sub_palette_[color];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Surface::render(int x, int y, SDL_FRect* srcRect, SDL_FlipMode flip) {
|
|
||||||
auto surface_data_dest = Screen::get()->getRendererSurface()->getSurfaceData();
|
|
||||||
|
|
||||||
// Determina la región de origen (clip) a renderizar
|
|
||||||
float sx = (srcRect) ? srcRect->x : 0;
|
|
||||||
float sy = (srcRect) ? srcRect->y : 0;
|
|
||||||
float w = (srcRect) ? srcRect->w : surface_data_->width;
|
|
||||||
float h = (srcRect) ? srcRect->h : surface_data_->height;
|
|
||||||
|
|
||||||
// Limitar la región para evitar accesos fuera de rango en origen
|
|
||||||
w = std::min(w, surface_data_->width - sx);
|
|
||||||
h = std::min(h, surface_data_->height - sy);
|
|
||||||
w = std::min(w, surface_data_dest->width - x);
|
|
||||||
h = std::min(h, surface_data_dest->height - y);
|
|
||||||
|
|
||||||
// Limitar la región para evitar accesos fuera de rango en destino
|
|
||||||
w = std::min(w, surface_data_dest->width - x);
|
|
||||||
h = std::min(h, surface_data_dest->height - y);
|
|
||||||
|
|
||||||
// Renderiza píxel por píxel aplicando el flip si es necesario
|
|
||||||
for (int iy = 0; iy < h; ++iy) {
|
|
||||||
for (int ix = 0; ix < w; ++ix) {
|
|
||||||
// Coordenadas de origen
|
|
||||||
int src_x = (flip == SDL_FLIP_HORIZONTAL) ? (sx + w - 1 - ix) : (sx + ix);
|
|
||||||
int src_y = (flip == SDL_FLIP_VERTICAL) ? (sy + h - 1 - iy) : (sy + iy);
|
|
||||||
|
|
||||||
// Coordenadas de destino
|
|
||||||
int dest_x = x + ix;
|
|
||||||
int dest_y = y + iy;
|
|
||||||
|
|
||||||
// Verificar que las coordenadas de destino están dentro de los límites
|
|
||||||
if (dest_x >= 0 && dest_x < surface_data_dest->width && dest_y >= 0 && dest_y < surface_data_dest->height) {
|
|
||||||
// Copia el píxel si no es transparente
|
|
||||||
Uint8 color = surface_data_->data.get()[static_cast<size_t>(src_x + src_y * surface_data_->width)];
|
|
||||||
if (color != transparent_color_) {
|
|
||||||
surface_data_dest->data[dest_x + dest_y * surface_data_dest->width] = sub_palette_[color];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copia una región de la superficie de origen a la de destino
|
|
||||||
void Surface::render(SDL_FRect* srcRect, SDL_FRect* dstRect, SDL_FlipMode flip) {
|
|
||||||
auto surface_data = Screen::get()->getRendererSurface()->getSurfaceData();
|
|
||||||
|
|
||||||
// Si srcRect es nullptr, tomar toda la superficie fuente
|
|
||||||
float sx = (srcRect) ? srcRect->x : 0;
|
|
||||||
float sy = (srcRect) ? srcRect->y : 0;
|
|
||||||
float sw = (srcRect) ? srcRect->w : surface_data_->width;
|
|
||||||
float sh = (srcRect) ? srcRect->h : surface_data_->height;
|
|
||||||
|
|
||||||
// Si dstRect es nullptr, asignar las mismas dimensiones que srcRect
|
|
||||||
float dx = (dstRect) ? dstRect->x : 0;
|
|
||||||
float dy = (dstRect) ? dstRect->y : 0;
|
|
||||||
float dw = (dstRect) ? dstRect->w : sw;
|
|
||||||
float dh = (dstRect) ? dstRect->h : sh;
|
|
||||||
|
|
||||||
// Asegurarse de que srcRect y dstRect tienen las mismas dimensiones
|
|
||||||
if (sw != dw || sh != dh) {
|
|
||||||
dw = sw; // Respetar las dimensiones de srcRect
|
|
||||||
dh = sh;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limitar la región para evitar accesos fuera de rango en src y dst
|
|
||||||
sw = std::min(sw, surface_data_->width - sx);
|
|
||||||
sh = std::min(sh, surface_data_->height - sy);
|
|
||||||
dw = std::min(dw, surface_data->width - dx);
|
|
||||||
dh = std::min(dh, surface_data->height - dy);
|
|
||||||
|
|
||||||
int final_width = std::min(sw, dw);
|
|
||||||
int final_height = std::min(sh, dh);
|
|
||||||
|
|
||||||
// Renderiza píxel por píxel aplicando el flip si es necesario
|
|
||||||
for (int iy = 0; iy < final_height; ++iy) {
|
|
||||||
for (int ix = 0; ix < final_width; ++ix) {
|
|
||||||
// Coordenadas de origen
|
|
||||||
int src_x = (flip == SDL_FLIP_HORIZONTAL) ? (sx + final_width - 1 - ix) : (sx + ix);
|
|
||||||
int src_y = (flip == SDL_FLIP_VERTICAL) ? (sy + final_height - 1 - iy) : (sy + iy);
|
|
||||||
|
|
||||||
// Coordenadas de destino
|
|
||||||
if (int dest_x = dx + ix; dest_x >= 0 && dest_x < surface_data->width) {
|
|
||||||
if (int dest_y = dy + iy; dest_y >= 0 && dest_y < surface_data->height) {
|
|
||||||
// Copiar el píxel si no es transparente
|
|
||||||
Uint8 color = surface_data_->data.get()[static_cast<size_t>(src_x + src_y * surface_data_->width)];
|
|
||||||
if (color != transparent_color_) {
|
|
||||||
surface_data->data[dest_x + dest_y * surface_data->width] = sub_palette_[color];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copia una región de la SurfaceData de origen a la SurfaceData de destino reemplazando un color por otro
|
|
||||||
void Surface::renderWithColorReplace(int x, int y, Uint8 source_color, Uint8 target_color, SDL_FRect* srcRect, SDL_FlipMode flip) {
|
|
||||||
auto surface_data = Screen::get()->getRendererSurface()->getSurfaceData();
|
|
||||||
|
|
||||||
// Determina la región de origen (clip) a renderizar
|
|
||||||
float sx = (srcRect) ? srcRect->x : 0;
|
|
||||||
float sy = (srcRect) ? srcRect->y : 0;
|
|
||||||
float w = (srcRect) ? srcRect->w : surface_data_->width;
|
|
||||||
float h = (srcRect) ? srcRect->h : surface_data_->height;
|
|
||||||
|
|
||||||
// Limitar la región para evitar accesos fuera de rango
|
|
||||||
w = std::min(w, surface_data_->width - sx);
|
|
||||||
h = std::min(h, surface_data_->height - sy);
|
|
||||||
|
|
||||||
// Renderiza píxel por píxel aplicando el flip si es necesario
|
|
||||||
for (int iy = 0; iy < h; ++iy) {
|
|
||||||
for (int ix = 0; ix < w; ++ix) {
|
|
||||||
// Coordenadas de origen
|
|
||||||
int src_x = (flip == SDL_FLIP_HORIZONTAL) ? (sx + w - 1 - ix) : (sx + ix);
|
|
||||||
int src_y = (flip == SDL_FLIP_VERTICAL) ? (sy + h - 1 - iy) : (sy + iy);
|
|
||||||
|
|
||||||
// Coordenadas de destino
|
|
||||||
int dest_x = x + ix;
|
|
||||||
int dest_y = y + iy;
|
|
||||||
|
|
||||||
// Verifica que las coordenadas de destino estén dentro de los límites
|
|
||||||
if (dest_x < 0 || dest_y < 0 || dest_x >= surface_data->width || dest_y >= surface_data->height) {
|
|
||||||
continue; // Saltar píxeles fuera del rango del destino
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copia el píxel si no es transparente
|
|
||||||
Uint8 color = surface_data_->data.get()[static_cast<size_t>(src_x + src_y * surface_data_->width)];
|
|
||||||
if (color != transparent_color_) {
|
|
||||||
surface_data->data[dest_x + dest_y * surface_data->width] =
|
|
||||||
(color == source_color) ? target_color : color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vuelca la superficie a una textura
|
|
||||||
void Surface::copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture) {
|
|
||||||
if (!renderer || !texture || !surface_data_) {
|
|
||||||
throw std::runtime_error("Renderer or texture is null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (surface_data_->width <= 0 || surface_data_->height <= 0 || !surface_data_->data.get()) {
|
|
||||||
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, reinterpret_cast<void**>(&pixels), &pitch)) {
|
|
||||||
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_data_->height; ++y) {
|
|
||||||
for (int x = 0; x < surface_data_->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_data_->width + x;
|
|
||||||
|
|
||||||
pixels[texture_index] = palette_[surface_data_->data.get()[surface_index]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_UnlockTexture(texture); // Desbloquea la textura
|
|
||||||
|
|
||||||
// Renderiza la textura en la pantalla completa
|
|
||||||
if (!SDL_RenderTexture(renderer, texture, nullptr, nullptr)) {
|
|
||||||
throw std::runtime_error("Failed to copy texture to renderer: " + std::string(SDL_GetError()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vuelca la superficie a una textura
|
|
||||||
void Surface::copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_FRect* srcRect, SDL_FRect* destRect) {
|
|
||||||
if (!renderer || !texture || !surface_data_) {
|
|
||||||
throw std::runtime_error("Renderer or texture is null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (surface_data_->width <= 0 || surface_data_->height <= 0 || !surface_data_->data.get()) {
|
|
||||||
throw std::runtime_error("Invalid surface dimensions or data.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Uint32* pixels = nullptr;
|
|
||||||
int pitch = 0;
|
|
||||||
|
|
||||||
SDL_Rect lockRect;
|
|
||||||
if (destRect) {
|
|
||||||
lockRect.x = static_cast<int>(destRect->x);
|
|
||||||
lockRect.y = static_cast<int>(destRect->y);
|
|
||||||
lockRect.w = static_cast<int>(destRect->w);
|
|
||||||
lockRect.h = static_cast<int>(destRect->h);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usa lockRect solo si destRect no es nulo
|
|
||||||
if (!SDL_LockTexture(texture, destRect ? &lockRect : nullptr, reinterpret_cast<void**>(&pixels), &pitch)) {
|
|
||||||
throw std::runtime_error("Failed to lock texture: " + std::string(SDL_GetError()));
|
|
||||||
}
|
|
||||||
|
|
||||||
int row_stride = pitch / sizeof(Uint32);
|
|
||||||
|
|
||||||
for (int y = 0; y < surface_data_->height; ++y) {
|
|
||||||
for (int x = 0; x < surface_data_->width; ++x) {
|
|
||||||
int texture_index = y * row_stride + x;
|
|
||||||
int surface_index = y * surface_data_->width + x;
|
|
||||||
|
|
||||||
pixels[texture_index] = palette_[surface_data_->data.get()[surface_index]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_UnlockTexture(texture);
|
|
||||||
|
|
||||||
// Renderiza la textura con los rectángulos especificados
|
|
||||||
if (!SDL_RenderTexture(renderer, texture, srcRect, destRect)) {
|
|
||||||
throw std::runtime_error("Failed to copy texture to renderer: " + std::string(SDL_GetError()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Realiza un efecto de fundido en la paleta principal
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Realiza un efecto de fundido en la paleta secundaria
|
|
||||||
bool Surface::fadeSubPalette(Uint32 delay) {
|
|
||||||
// Variable estática para almacenar el último tick
|
|
||||||
static Uint32 last_tick = 0;
|
|
||||||
|
|
||||||
// Obtener el tiempo actual
|
|
||||||
Uint32 current_tick = SDL_GetTicks();
|
|
||||||
|
|
||||||
// Verificar si ha pasado el tiempo de retardo
|
|
||||||
if (current_tick - last_tick < delay) {
|
|
||||||
return false; // No se realiza el fade
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualizar el último tick
|
|
||||||
last_tick = current_tick;
|
|
||||||
|
|
||||||
// Verificar que el tamaño mínimo de sub_palette_ sea adecuado
|
|
||||||
static constexpr int sub_palette_size = 19;
|
|
||||||
if (sizeof(sub_palette_) / sizeof(sub_palette_[0]) < sub_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) {
|
|
||||||
sub_palette_[i] = sub_palette_[i - 2];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajustar el primer color
|
|
||||||
sub_palette_[1] = sub_palette_[0];
|
|
||||||
|
|
||||||
// Devolver si el índice 15 coincide con el índice 0
|
|
||||||
return sub_palette_[15] == sub_palette_[0];
|
|
||||||
}
|
|
||||||
133
source/surface.h
133
source/surface.h
@@ -1,133 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include <array> // Para array
|
|
||||||
#include <memory> // Para default_delete, shared_ptr, __shared_pt...
|
|
||||||
#include <numeric> // Para iota
|
|
||||||
#include <string> // Para string
|
|
||||||
#include <utility> // Para move
|
|
||||||
|
|
||||||
#include "utils.h" // Para PaletteColor
|
|
||||||
|
|
||||||
// Alias
|
|
||||||
using Palette = std::array<Uint32, 256>;
|
|
||||||
using SubPalette = std::array<Uint8, 256>;
|
|
||||||
|
|
||||||
// Carga una paleta desde un archivo .gif
|
|
||||||
Palette loadPalette(const std::string& file_path);
|
|
||||||
|
|
||||||
// Carga una paleta desde un archivo .pal
|
|
||||||
Palette readPalFile(const std::string& file_path);
|
|
||||||
|
|
||||||
struct SurfaceData {
|
|
||||||
std::shared_ptr<Uint8[]> data; // Usa std::shared_ptr para gestión automática
|
|
||||||
float width; // Ancho de la imagen
|
|
||||||
float height; // Alto de la imagen
|
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
SurfaceData()
|
|
||||||
: data(nullptr),
|
|
||||||
width(0),
|
|
||||||
height(0) {}
|
|
||||||
|
|
||||||
// Constructor que inicializa dimensiones y asigna memoria
|
|
||||||
SurfaceData(float w, float h)
|
|
||||||
: data(std::shared_ptr<Uint8[]>(new Uint8[static_cast<size_t>(w * h)](), std::default_delete<Uint8[]>())),
|
|
||||||
width(w),
|
|
||||||
height(h) {}
|
|
||||||
|
|
||||||
// Constructor para inicializar directamente con datos
|
|
||||||
SurfaceData(float w, float h, std::shared_ptr<Uint8[]> pixels)
|
|
||||||
: data(std::move(pixels)),
|
|
||||||
width(w),
|
|
||||||
height(h) {}
|
|
||||||
|
|
||||||
// Constructor de movimiento
|
|
||||||
SurfaceData(SurfaceData&& other) noexcept = default;
|
|
||||||
|
|
||||||
// Operador de movimiento
|
|
||||||
SurfaceData& operator=(SurfaceData&& other) noexcept = default;
|
|
||||||
|
|
||||||
// Evita copias accidentales
|
|
||||||
SurfaceData(const SurfaceData&) = delete;
|
|
||||||
SurfaceData& operator=(const SurfaceData&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Surface {
|
|
||||||
private:
|
|
||||||
std::shared_ptr<SurfaceData> surface_data_; // Datos a dibujar
|
|
||||||
Palette palette_; // Paleta para volcar la SurfaceData a una Textura
|
|
||||||
SubPalette sub_palette_; // Paleta para reindexar colores
|
|
||||||
int transparent_color_; // Indice de la paleta que se omite en la copia de datos
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
Surface(int w, int h);
|
|
||||||
explicit Surface(const std::string& file_path);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~Surface() = default;
|
|
||||||
|
|
||||||
// Carga una SurfaceData desde un archivo
|
|
||||||
SurfaceData loadSurface(const std::string& file_path);
|
|
||||||
|
|
||||||
// Carga una paleta desde un archivo
|
|
||||||
void loadPalette(const std::string& file_path);
|
|
||||||
void loadPalette(Palette palette);
|
|
||||||
|
|
||||||
// Copia una región de la SurfaceData de origen a la SurfaceData de destino
|
|
||||||
void render(float dx, float dy, float sx, float sy, float w, float h);
|
|
||||||
void render(int x, int y, SDL_FRect* clip = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE);
|
|
||||||
void render(SDL_FRect* srcRect = nullptr, SDL_FRect* dstRect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE);
|
|
||||||
|
|
||||||
// Copia una región de la SurfaceData de origen a la SurfaceData de destino reemplazando un color por otro
|
|
||||||
void renderWithColorReplace(int x, int y, Uint8 source_color = 0, Uint8 target_color = 0, SDL_FRect* srcRect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE);
|
|
||||||
|
|
||||||
// Establece un color en la paleta
|
|
||||||
void setColor(int index, Uint32 color);
|
|
||||||
|
|
||||||
// Rellena la SurfaceData con un color
|
|
||||||
void clear(Uint8 color);
|
|
||||||
|
|
||||||
// Vuelca la SurfaceData a una textura
|
|
||||||
void copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture);
|
|
||||||
void copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_FRect* srcRect, SDL_FRect* destRect);
|
|
||||||
|
|
||||||
// Realiza un efecto de fundido en las paletas
|
|
||||||
bool fadePalette();
|
|
||||||
bool fadeSubPalette(Uint32 delay = 0);
|
|
||||||
|
|
||||||
// Pone un pixel en la SurfaceData
|
|
||||||
void putPixel(int x, int y, Uint8 color);
|
|
||||||
|
|
||||||
// Obtiene el color de un pixel de la surface_data
|
|
||||||
Uint8 getPixel(int x, int y);
|
|
||||||
|
|
||||||
// Dibuja un rectangulo relleno
|
|
||||||
void fillRect(const SDL_FRect* rect, Uint8 color);
|
|
||||||
|
|
||||||
// Dibuja el borde de un rectangulo
|
|
||||||
void drawRectBorder(const SDL_FRect* rect, Uint8 color);
|
|
||||||
|
|
||||||
// Dibuja una linea
|
|
||||||
void drawLine(float x1, float y1, float x2, float y2, Uint8 color);
|
|
||||||
|
|
||||||
// Metodos para gestionar surface_data_
|
|
||||||
std::shared_ptr<SurfaceData> getSurfaceData() const { return surface_data_; }
|
|
||||||
void setSurfaceData(std::shared_ptr<SurfaceData> new_data) { surface_data_ = new_data; }
|
|
||||||
|
|
||||||
// Obtien ancho y alto
|
|
||||||
float getWidth() const { return surface_data_->width; }
|
|
||||||
float getHeight() const { return surface_data_->height; }
|
|
||||||
|
|
||||||
// Color transparente
|
|
||||||
Uint8 getTransparentColor() const { return transparent_color_; }
|
|
||||||
void setTransparentColor(Uint8 color = 255) { transparent_color_ = color; }
|
|
||||||
|
|
||||||
// Paleta
|
|
||||||
void setPalette(const std::array<Uint32, 256>& palette) { palette_ = palette; }
|
|
||||||
|
|
||||||
// Inicializa la sub paleta
|
|
||||||
void initializeSubPalette(SubPalette& palette) { std::iota(palette.begin(), palette.end(), 0); }
|
|
||||||
};
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include <memory> // Para shared_ptr, unique_ptr
|
|
||||||
#include <string> // Para string
|
|
||||||
|
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
|
||||||
class Surface; // lines 8-8
|
|
||||||
|
|
||||||
constexpr int TEXT_COLOR = 1;
|
|
||||||
constexpr int TEXT_SHADOW = 2;
|
|
||||||
constexpr int TEXT_CENTER = 4;
|
|
||||||
constexpr int TEXT_STROKE = 8;
|
|
||||||
|
|
||||||
struct TextOffset {
|
|
||||||
int x, y, w;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TextFile {
|
|
||||||
int box_width; // Anchura de la caja de cada caracter en el png
|
|
||||||
int box_height; // Altura de la caja de cada caracter en el png
|
|
||||||
TextOffset offset[128]; // Vector con las posiciones y ancho de cada letra
|
|
||||||
};
|
|
||||||
|
|
||||||
// Llena una estructuta TextFile desde un fichero
|
|
||||||
std::shared_ptr<TextFile> loadTextFile(const std::string& file_path);
|
|
||||||
|
|
||||||
// Clase texto. Pinta texto en pantalla a partir de un bitmap
|
|
||||||
class Text {
|
|
||||||
private:
|
|
||||||
// Objetos y punteros
|
|
||||||
std::unique_ptr<SSprite> sprite_ = nullptr; // Objeto con los graficos para el texto
|
|
||||||
|
|
||||||
// Variables
|
|
||||||
int box_width_ = 0; // Anchura de la caja de cada caracter en el png
|
|
||||||
int box_height_ = 0; // Altura de la caja de cada caracter en el png
|
|
||||||
bool fixed_width_ = false; // Indica si el texto se ha de escribir con longitud fija en todas las letras
|
|
||||||
TextOffset offset_[128] = {}; // Vector con las posiciones y ancho de cada letra
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
Text(std::shared_ptr<Surface> surface, const std::string& text_file);
|
|
||||||
Text(std::shared_ptr<Surface> surface, std::shared_ptr<TextFile> text_file);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~Text() = default;
|
|
||||||
|
|
||||||
// Escribe el texto en pantalla
|
|
||||||
void write(int x, int y, const std::string& text, int kerning = 1, int lenght = -1);
|
|
||||||
|
|
||||||
// Escribe el texto en una textura
|
|
||||||
std::shared_ptr<Surface> writeToSurface(const std::string& text, int zoom = 1, int kerning = 1);
|
|
||||||
|
|
||||||
// Escribe el texto con extras en una textura
|
|
||||||
std::shared_ptr<Surface> writeDXToSurface(Uint8 flags, const std::string& text, int kerning = 1, Uint8 textColor = Uint8(), Uint8 shadow_distance = 1, Uint8 shadow_color = Uint8(), int lenght = -1);
|
|
||||||
|
|
||||||
// Escribe el texto con colores
|
|
||||||
void writeColored(int x, int y, const std::string& text, Uint8 color, int kerning = 1, int lenght = -1);
|
|
||||||
|
|
||||||
// Escribe el texto con sombra
|
|
||||||
void writeShadowed(int x, int y, const std::string& text, Uint8 color, Uint8 shadow_distance = 1, int kerning = 1, int lenght = -1);
|
|
||||||
|
|
||||||
// Escribe el texto centrado en un punto x
|
|
||||||
void writeCentered(int x, int y, const std::string& text, int kerning = 1, int lenght = -1);
|
|
||||||
|
|
||||||
// Escribe texto con extras
|
|
||||||
void writeDX(Uint8 flags, int x, int y, const std::string& text, int kerning = 1, Uint8 textColor = Uint8(), Uint8 shadow_distance = 1, Uint8 shadow_color = Uint8(), int lenght = -1);
|
|
||||||
|
|
||||||
// Obtiene la longitud en pixels de una cadena
|
|
||||||
int lenght(const std::string& text, int kerning = 1) const;
|
|
||||||
|
|
||||||
// Devuelve el valor de la variable
|
|
||||||
int getCharacterSize() const;
|
|
||||||
|
|
||||||
// Establece si se usa un tamaño fijo de letra
|
|
||||||
void setFixedWidth(bool value);
|
|
||||||
};
|
|
||||||
@@ -1,278 +0,0 @@
|
|||||||
#include "ui/notifier.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include <algorithm> // Para remove_if
|
|
||||||
#include <iterator> // Para prev
|
|
||||||
#include <string> // Para string, basic_string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "external/jail_audio.h" // Para JA_PlaySound
|
|
||||||
#include "options.h" // Para Options, options, NotificationPosition
|
|
||||||
#include "resource.h" // Para Resource
|
|
||||||
#include "screen.h" // Para Screen
|
|
||||||
#include "sprite/surface_sprite.h" // Para SSprite
|
|
||||||
#include "surface.h" // Para Surface
|
|
||||||
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR
|
|
||||||
#include "utils.h" // Para PaletteColor
|
|
||||||
|
|
||||||
// [SINGLETON]
|
|
||||||
Notifier* Notifier::notifier_ = nullptr;
|
|
||||||
|
|
||||||
// [SINGLETON] Crearemos el objeto con esta función estática
|
|
||||||
void Notifier::init(const std::string& icon_file, const std::string& text) {
|
|
||||||
Notifier::notifier_ = new Notifier(icon_file, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// [SINGLETON] Destruiremos el objeto con esta función estática
|
|
||||||
void Notifier::destroy() {
|
|
||||||
delete Notifier::notifier_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
|
|
||||||
Notifier* Notifier::get() {
|
|
||||||
return Notifier::notifier_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Notifier::Notifier(const std::string& icon_file, const std::string& text)
|
|
||||||
: icon_surface_(!icon_file.empty() ? Resource::get()->getSurface(icon_file) : nullptr),
|
|
||||||
text_(Resource::get()->getText(text)),
|
|
||||||
bg_color_(options.notifications.color),
|
|
||||||
stack_(false),
|
|
||||||
has_icons_(!icon_file.empty()) {}
|
|
||||||
|
|
||||||
// Dibuja las notificaciones por pantalla
|
|
||||||
void Notifier::render() {
|
|
||||||
for (auto it = notifications_.rbegin(); it != notifications_.rend(); ++it) {
|
|
||||||
it->sprite->render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el estado de las notificaiones
|
|
||||||
void Notifier::update() {
|
|
||||||
for (auto& notification : notifications_) {
|
|
||||||
// Si la notificación anterior está "saliendo", no hagas nada
|
|
||||||
if (!notifications_.empty() && ¬ification != ¬ifications_.front()) {
|
|
||||||
const auto& PREVIOUS_NOTIFICATION = *(std::prev(¬ification));
|
|
||||||
if (PREVIOUS_NOTIFICATION.state == NotificationStatus::RISING) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (notification.state) {
|
|
||||||
case NotificationStatus::RISING: {
|
|
||||||
const int DIRECTION = (options.notifications.getVerticalPosition() == NotificationPosition::TOP) ? 1 : -1;
|
|
||||||
notification.rect.y += DIRECTION;
|
|
||||||
|
|
||||||
if (notification.rect.y == notification.y) {
|
|
||||||
notification.state = NotificationStatus::STAY;
|
|
||||||
notification.start_time = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NotificationStatus::STAY: {
|
|
||||||
notification.elapsed_time = SDL_GetTicks() - notification.start_time;
|
|
||||||
if (notification.elapsed_time >= notification.display_duration) {
|
|
||||||
notification.state = NotificationStatus::VANISHING;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case NotificationStatus::VANISHING: {
|
|
||||||
const int DIRECTION = (options.notifications.getVerticalPosition() == NotificationPosition::TOP) ? -1 : 1;
|
|
||||||
notification.rect.y += DIRECTION;
|
|
||||||
|
|
||||||
if (notification.rect.y == notification.y - notification.travel_dist) {
|
|
||||||
notification.state = NotificationStatus::FINISHED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case NotificationStatus::FINISHED:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
notification.sprite->setPosition(notification.rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
clearFinishedNotifications();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Elimina las notificaciones finalizadas
|
|
||||||
void Notifier::clearFinishedNotifications() {
|
|
||||||
notifications_.erase(
|
|
||||||
std::remove_if(notifications_.begin(), notifications_.end(), [](const Notification& notification) {
|
|
||||||
return notification.state == NotificationStatus::FINISHED;
|
|
||||||
}),
|
|
||||||
notifications_.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Notifier::show(std::vector<std::string> texts, NotificationText text_is, Uint32 display_duration, int icon, bool can_be_removed, const std::string& code) {
|
|
||||||
// Si no hay texto, acaba
|
|
||||||
if (texts.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si las notificaciones no se apilan, elimina las anteriores
|
|
||||||
if (!stack_) {
|
|
||||||
clearNotifications();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Elimina las cadenas vacías
|
|
||||||
texts.erase(std::remove_if(texts.begin(), texts.end(), [](const std::string& s) { return s.empty(); }),
|
|
||||||
texts.end());
|
|
||||||
|
|
||||||
// Encuentra la cadena más larga
|
|
||||||
std::string longest;
|
|
||||||
for (const auto& text : texts) {
|
|
||||||
if (text.length() > longest.length()) {
|
|
||||||
longest = text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa variables
|
|
||||||
const int text_size = 6;
|
|
||||||
const auto PADDING_IN_H = text_size;
|
|
||||||
const auto PADDING_IN_V = text_size / 2;
|
|
||||||
const int ICON_SPACE = icon >= 0 ? ICON_SIZE_ + PADDING_IN_H : 0;
|
|
||||||
text_is = ICON_SPACE > 0 ? NotificationText::LEFT : text_is;
|
|
||||||
const float WIDTH = options.game.width - (PADDING_OUT_ * 2);
|
|
||||||
const float HEIGHT = (text_size * texts.size()) + (PADDING_IN_V * 2);
|
|
||||||
const auto SHAPE = NotificationShape::SQUARED;
|
|
||||||
|
|
||||||
// Posición horizontal
|
|
||||||
float desp_h = 0;
|
|
||||||
switch (options.notifications.getHorizontalPosition()) {
|
|
||||||
case NotificationPosition::LEFT:
|
|
||||||
desp_h = PADDING_OUT_;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NotificationPosition::CENTER:
|
|
||||||
desp_h = ((options.game.width / 2) - (WIDTH / 2));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NotificationPosition::RIGHT:
|
|
||||||
desp_h = options.game.width - WIDTH - PADDING_OUT_;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
desp_h = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Posición vertical
|
|
||||||
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 int TRAVEL_MOD = (options.notifications.getVerticalPosition() == NotificationPosition::TOP) ? 1 : -1;
|
|
||||||
const int OFFSET = !notifications_.empty() ? notifications_.back().y + TRAVEL_MOD * notifications_.back().travel_dist : DESP_V;
|
|
||||||
|
|
||||||
// Crea la notificacion
|
|
||||||
Notification n;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
n.display_duration = display_duration;
|
|
||||||
const float Y_POS = OFFSET + ((options.notifications.getVerticalPosition() == NotificationPosition::TOP) ? -TRAVEL_DIST : TRAVEL_DIST);
|
|
||||||
n.rect = {desp_h, Y_POS, WIDTH, HEIGHT};
|
|
||||||
|
|
||||||
// Crea la textura
|
|
||||||
n.surface = std::make_shared<Surface>(WIDTH, HEIGHT);
|
|
||||||
|
|
||||||
// Prepara para dibujar en la textura
|
|
||||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
||||||
Screen::get()->setRendererSurface(n.surface);
|
|
||||||
|
|
||||||
// Dibuja el fondo de la notificación
|
|
||||||
SDL_FRect rect;
|
|
||||||
if (SHAPE == NotificationShape::ROUNDED) {
|
|
||||||
rect = {4, 0, WIDTH - (4 * 2), HEIGHT};
|
|
||||||
n.surface->fillRect(&rect, bg_color_);
|
|
||||||
|
|
||||||
rect = {4 / 2, 1, WIDTH - 4, HEIGHT - 2};
|
|
||||||
n.surface->fillRect(&rect, bg_color_);
|
|
||||||
|
|
||||||
rect = {1, 4 / 2, WIDTH - 2, HEIGHT - 4};
|
|
||||||
n.surface->fillRect(&rect, bg_color_);
|
|
||||||
|
|
||||||
rect = {0, 4, WIDTH, HEIGHT - (4 * 2)};
|
|
||||||
n.surface->fillRect(&rect, bg_color_);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (SHAPE == NotificationShape::SQUARED) {
|
|
||||||
n.surface->clear(bg_color_);
|
|
||||||
SDL_FRect squared_rect = {0, 0, n.surface->getWidth(), n.surface->getHeight()};
|
|
||||||
n.surface->drawRectBorder(&squared_rect, static_cast<Uint8>(PaletteColor::CYAN));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja el icono de la notificación
|
|
||||||
if (has_icons_ && icon >= 0 && texts.size() >= 2) {
|
|
||||||
auto sp = std::make_unique<SSprite>(icon_surface_, (SDL_FRect){0, 0, ICON_SIZE_, ICON_SIZE_});
|
|
||||||
sp->setPosition({PADDING_IN_H, PADDING_IN_V, ICON_SIZE_, ICON_SIZE_});
|
|
||||||
sp->setClip((SDL_FRect){ICON_SIZE_ * (icon % 10), ICON_SIZE_ * (icon / 10), ICON_SIZE_, ICON_SIZE_});
|
|
||||||
sp->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escribe el texto de la notificación
|
|
||||||
const Uint8 COLOR = static_cast<Uint8>(PaletteColor::WHITE);
|
|
||||||
int iterator = 0;
|
|
||||||
for (const auto& text : texts) {
|
|
||||||
switch (text_is) {
|
|
||||||
case NotificationText::LEFT:
|
|
||||||
text_->writeColored(PADDING_IN_H + ICON_SPACE, PADDING_IN_V + iterator * (text_size + 1), text, COLOR);
|
|
||||||
break;
|
|
||||||
case NotificationText::CENTER:
|
|
||||||
text_->writeDX(TEXT_CENTER | TEXT_COLOR, WIDTH / 2, PADDING_IN_V + iterator * (text_size + 1), text, 1, COLOR);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
++iterator;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deja de dibujar en la textura
|
|
||||||
Screen::get()->setRendererSurface(previuos_renderer);
|
|
||||||
|
|
||||||
// Crea el sprite de la notificación
|
|
||||||
n.sprite = std::make_shared<SSprite>(n.surface, n.rect);
|
|
||||||
|
|
||||||
// Añade la notificación a la lista
|
|
||||||
notifications_.emplace_back(n);
|
|
||||||
|
|
||||||
// Reproduce el sonido de la notificación
|
|
||||||
JA_PlaySound(Resource::get()->getSound("notify.wav"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Indica si hay notificaciones activas
|
|
||||||
bool Notifier::isActive() { return !notifications_.empty(); }
|
|
||||||
|
|
||||||
// Finaliza y elimnina todas las notificaciones activas
|
|
||||||
void Notifier::clearNotifications() {
|
|
||||||
for (auto& notification : notifications_) {
|
|
||||||
if (notification.can_be_removed) {
|
|
||||||
notification.state = NotificationStatus::FINISHED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clearFinishedNotifications();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtiene los códigos de las notificaciones
|
|
||||||
std::vector<std::string> Notifier::getCodes() {
|
|
||||||
std::vector<std::string> codes;
|
|
||||||
for (const auto& notification : notifications_) {
|
|
||||||
codes.emplace_back(notification.code);
|
|
||||||
}
|
|
||||||
return codes;
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils/utils.hpp"
|
||||||
|
|
||||||
// Textos
|
// Textos
|
||||||
constexpr const char* WINDOW_CAPTION = "JailDoctor's Dilemma";
|
constexpr const char* WINDOW_CAPTION = "JailDoctor's Dilemma";
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "global_events.h"
|
#include "utils/global_events.hpp"
|
||||||
#include "options.h" // Para Options, options, OptionsGame, OptionsAudio
|
#include "game/gameplay/options.hpp" // Para Options, options, OptionsGame, OptionsAudio
|
||||||
#include "mouse.h"
|
#include "core/input/mouse.hpp"
|
||||||
|
|
||||||
namespace globalEvents
|
namespace globalEvents
|
||||||
{
|
{
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user