29 Commits

Author SHA1 Message Date
64138c1017 Ya funcionan los nuevos inputs de teclado y mando en el titulo 2023-02-12 19:03:54 +01:00
50a2038ef9 Ya funcionan los nuevos inputs de teclado y mando en el logo
Ya funcionan los nuevos inputs de teclado y mando en la intro
2023-02-12 18:58:29 +01:00
cbb5d54250 Reasignados los controles para ordenador, mando y consola 2023-02-12 18:50:40 +01:00
ca99857b5b Cuando se cambia el tamaño de la ventana, aparece centrada en el escritorio 2023-02-12 18:19:13 +01:00
dfed098ffb Añadida opción de incrementar o decrementar el tamaño de la ventana en la clase screen 2023-02-12 18:16:37 +01:00
d9b08cf13a Configurando el initOnline 2022-12-07 11:55:32 +01:00
bbe82d329b Los datos se guardan en la carpeta de sistema 2022-12-07 11:23:19 +01:00
c87e1e68a9 Cambiados los accesos a vector de .at a [] 2022-12-07 09:29:06 +01:00
7adb049b37 Cambiados los printf por std::cout 2022-12-07 09:12:30 +01:00
6aebb28f37 Actualizado menu.cpp 2022-12-07 08:37:16 +01:00
cbdee55148 Actualizado animatedsprite.cpp 2022-12-07 08:11:49 +01:00
3cca4373d3 Actualizado asset.cpp 2022-12-07 08:08:04 +01:00
90785d2506 Actualizado input.cpp 2022-12-07 07:58:04 +01:00
fbeea9f424 Actualizados los ficheros de release 2022-12-05 10:21:18 +01:00
5f263fa71d Cambiando printf por std::cout 2022-12-05 10:07:27 +01:00
a32582f1ec Actualizadas las librerias comunes 2022-12-05 09:55:15 +01:00
09a205a288 Actualizando las clases comunes a sus ultimas versiones 2022-12-05 09:13:04 +01:00
cdb5040b9d Actualizado Makefile y numero de version 2022-12-05 08:31:30 +01:00
ded9b40922 Actualizado a la última versión de jail_audio 2022-12-05 08:05:15 +01:00
1144fc3626 Las notificaciones se dibujan a la mitad de resolución del juego 2022-11-19 09:39:14 +01:00
ea994bcc2f Optimizado el renderizado de notificaciones 2022-11-18 19:26:31 +01:00
74d5bbddaa Quitados dos warnings de variables sin usar 2022-11-17 22:01:43 +01:00
8ec0914bb5 Si no puede conectar al servidor online, desactiva el modo online 2022-11-17 20:15:34 +01:00
6d1bc066bd La tabla de records no sale si no está el modo online activo 2022-11-17 20:13:53 +01:00
975078307f Terminada la tabla de records 2022-11-17 20:08:31 +01:00
74d3066871 Actualizado el numero de versión 2022-11-17 18:58:20 +01:00
53c6da4a37 Añadida la primera versión de la tabla de records 2022-11-17 18:57:54 +01:00
3e666689c5 Actualizado Makefile 2022-11-17 10:16:58 +01:00
ef124cf309 Actualizado Makefile 2022-11-17 10:09:25 +01:00
54 changed files with 2397 additions and 1258 deletions

View File

@@ -2,7 +2,7 @@ executable = coffee_crisis
source = source/*.cpp source/common/*.cpp
appName = Coffee Crisis
releaseFolder = cc_release
version = v2.1b
version = v2.2a
# Release names
windowsRelease = $(executable)-$(version)-win32-x64.zip
@@ -12,27 +12,30 @@ linuxRelease = $(executable)-$(version)-linux.tar.gz
windows:
@echo off
g++ $(source) -D DEBUG -std=c++11 -Wall -Os -lmingw32 -lws2_32 -lSDL2main -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows -o $(executable).exe
strip -s -R .comment -R .gnu.version $(executable).exe --strip-unneeded
g++ $(source) -std=c++11 -Wall -Os -lmingw32 -lws2_32 -lSDL2main -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows -o "$(executable).exe"
strip -s -R .comment -R .gnu.version "$(executable).exe" --strip-unneeded
windows_debug:
@echo off
g++ $(source) -D DEBUG -std=c++11 -Wall -Os -lmingw32 -lws2_32 -lSDL2main -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows -o "$(executable)_debug.exe"
strip -s -R .comment -R .gnu.version "$(executable)_debug.exe" --strip-unneeded
windows_release:
@echo off
# Remove data
powershell if (Test-Path $(releaseFolder)) {Remove-Item $(releaseFolder) -Recurse -Force}
# Create release folder
powershell if (Test-Path "$(releaseFolder)") {Remove-Item "$(releaseFolder)" -Recurse -Force}
powershell if (-not (Test-Path "$(releaseFolder)")) {New-Item "$(releaseFolder)" -ItemType Directory}
# Create folders
powershell if (-not (Test-Path $(releaseFolder))) {New-Item $(releaseFolder) -ItemType Directory}
# Copy data
# Prepare data folder
powershell Copy-Item -Path "data" -Destination "$(releaseFolder)" -recurse -Force
powershell Copy-Item -Path "release/config.txt" -Destination "$(releaseFolder)/data/config" -recurse -Force
powershell Copy-Item "LICENSE" -Destination "$(releaseFolder)"
powershell Copy-Item "README.md" -Destination "$(releaseFolder)"
powershell Copy-Item "release/SDL2.dll" -Destination "$(releaseFolder)"
powershell Copy-Item "release\config.txt" -Destination "$(releaseFolder)\data\config\"
powershell if (Test-Path "$(releaseFolder)\data\config\score.bin") {Remove-Item "$(releaseFolder)\data\config\score.bin" -Recurse -Force}
# Remove data
powershell if (Test-Path data\config\score.bin) {Remove-Item data\config\score.bin -Recurse -Force}
# Copy root files
powershell Copy-Item "LICENSE.txt" -Destination "$(releaseFolder)"
powershell Copy-Item "README.md" -Destination "$(releaseFolder)"
powershell Copy-Item "release\*.dll" -Destination "$(releaseFolder)"
# Build
g++ $(source) -std=c++11 -Wall -Os -lmingw32 -lws2_32 -lSDL2main -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows -o "$(releaseFolder)/$(executable).exe"
@@ -43,13 +46,16 @@ windows_release:
powershell Compress-Archive -Path "$(releaseFolder)"/* -DestinationPath $(windowsRelease)
# Remove folder
powershell if (Test-Path $(releaseFolder)) {Remove-Item $(releaseFolder) -Recurse -Force}
powershell if (Test-Path "$(releaseFolder)") {Remove-Item "$(releaseFolder)" -Recurse -Force}
macos:
clang++ $(source) -D DEBUG -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -o $(executable)_macos
clang++ $(source) -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -o "$(executable)"
macos_debug:
clang++ $(source) -D DEBUG -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -o "$(executable)_debug"
macos_release:
# Remove data and possible data
# Remove data and possible data from previous builds
rm -rdf "$(releaseFolder)"
rm -rdf Frameworks
rm -f tmp.dmg
@@ -62,8 +68,9 @@ macos_release:
mkdir -p "$(releaseFolder)/$(appName).app/Contents/Resources"
mkdir -p Frameworks
# Copy folders
# Copy folders and files
cp -R data "$(releaseFolder)/$(appName).app/Contents/Resources"
cp release/config.txt "$(releaseFolder)/$(appName).app/Contents/Resources/data/config"
cp -R release/SDL2.framework "$(releaseFolder)/$(appName).app/Contents/Frameworks"
cp -R release/SDL2.framework Frameworks
@@ -73,57 +80,63 @@ macos_release:
# Copy files
cp release/*.icns "$(releaseFolder)/$(appName).app/Contents/Resources"
cp release/Info.plist "$(releaseFolder)/$(appName).app/Contents"
cp release/config.txt "$(releaseFolder)/$(appName).app/Contents/Resources/data/config"
cp LICENSE.txt "$(releaseFolder)"
cp README.md "$(releaseFolder)"
# Create links
ln -s /Applications "$(releaseFolder)"/Applications
# Build INTEL
clang++ $(source) -D MACOS_BUNDLE -std=c++11 -Wall -Os -framework SDL2 -F ./Frameworks -ffunction-sections -fdata-sections -o "$(releaseFolder)/$(appName).app/Contents/MacOS/$(executable)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.12
# Build INTEL DMG
rm -f "$(executable)_macos_intel_$(version).dmg"
hdiutil create tmp.dmg -ov -volname "$(appName)" -fs HFS+ -srcfolder "$(releaseFolder)"
hdiutil convert tmp.dmg -format UDZO -o "$(macosIntelRelease)"
rm tmp.dmg
rm -f tmp.dmg
# Build APPLE SILICON
clang++ $(source) -D MACOS_BUNDLE -std=c++11 -Wall -Os -framework SDL2 -F ./Frameworks -ffunction-sections -fdata-sections -o "$(releaseFolder)/$(appName).app/Contents/MacOS/$(executable)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11
# Build APPLE SILICON DMG
rm -f "$(executable)_macos_apple_silicon_$(version).dmg"
hdiutil create tmp.dmg -ov -volname "$(appName)" -fs HFS+ -srcfolder "$(releaseFolder)"
hdiutil convert tmp.dmg -format UDZO -o "$(macosAppleSiliconRelease)"
rm tmp.dmg
rm -f tmp.dmg
# Remove data
rm -rdf Frameworks
rm -rdf "$(releaseFolder)"
linux:
g++ $(source) -D DEBUG -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -o $(executable)_linux
strip -s -R .comment -R .gnu.version $(executable)_linux --strip-unneeded
g++ $(source) -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -o "$(executable)"
strip -s -R .comment -R .gnu.version "$(executable)" --strip-unneeded
linux_debug:
g++ $(source) -D DEBUG -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -o "$(executable)_debug"
strip -s -R .comment -R .gnu.version "$(executable)_debug" --strip-unneeded
linux_release:
# Remove data
rm -rdf $(releaseFolder)
rm -rdf "$(releaseFolder)"
# Create folders
mkdir -p $(releaseFolder)
mkdir -p "$(releaseFolder)"
# Copy data
cp -R data $(releaseFolder)
cp -R release/config.txt $(releaseFolder)/data/config
cp LICENSE $(releaseFolder)
cp README.md $(releaseFolder)
cp -R data "$(releaseFolder)"
cp release/config.txt "$(releaseFolder)/data/config/"
cp LICENSE.txt "$(releaseFolder)"
cp README.md "$(releaseFolder)"
# Delete data
rm -f $(releaseFolder)/data/config/score.bin
rm -f "$(releaseFolder)/data/config/score.bin"
# Build
g++ $(source) -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -o $(releaseFolder)/$(executable)
strip -s -R .comment -R .gnu.version $(releaseFolder)/$(executable) --strip-unneeded
g++ $(source) -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -o "$(releaseFolder)/$(executable)"
strip -s -R .comment -R .gnu.version "$(releaseFolder)/$(executable)" --strip-unneeded
# Pack files
rm -f $(linuxRelease)
cd $(releaseFolder) && tar -czvf ../$(linuxRelease) *
rm -f "$(linuxRelease)"
cd "$(releaseFolder)" && tar -czvf "../$(linuxRelease)" *
# Remove data
rm -rdf $(releaseFolder)
rm -rdf "$(releaseFolder)"

View File

@@ -124,8 +124,8 @@ Enrere
## 41 - MENU DE PAUSA
Menu de pausa
## 42 -
-
## 42 - TABLA DE RECORDS
Millors puntuacions
## 43 - PANTALLA DE GAME OVER
FI DEL JOC

View File

@@ -124,8 +124,8 @@ Back
## 41 - MENU DE PAUSA
Pause Menu
## 42 -
-
## 42 - TABLA DE RECORDS
Best scores
## 43 - PANTALLA DE GAME OVER
GAME OVER

View File

@@ -124,8 +124,8 @@ Volver
## 41 - MENU DE PAUSA
Menu de pausa
## 42 -
-
## 42 - TABLA DE RECORDS
Mejores puntuaciones
## 43 - PANTALLA DE GAME OVER
FIN DE JUEGO

BIN
data/sound/notify.wav Normal file

Binary file not shown.

View File

@@ -13,7 +13,7 @@
<key>CFBundleIconName</key>
<string>coffee_crisis</string>
<key>CFBundleIdentifier</key>
<string>org.jailgames.coffee_crisis</string>
<string>net.jailgames.coffee_crisis</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -21,11 +21,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<string>2.2a</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<string>2.2a</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSMinimumSystemVersion</key>

View File

@@ -0,0 +1 @@
Versions/Current/Headers

View File

@@ -0,0 +1 @@
Versions/Current/Resources

1
release/SDL2.framework/SDL2 Symbolic link
View File

@@ -0,0 +1 @@
Versions/Current/SDL2

0
release/SDL2.framework/Versions/A/SDL2 Normal file → Executable file
View File

View File

@@ -0,0 +1 @@
A

View File

@@ -1,14 +1,13 @@
## VISUAL OPTIONS
fullScreenMode=0
videoMode=0
windowSize=3
filter=FILTER_NEAREST
vSync=true
integerScale=true
keepAspect=true
borderEnabled=false
borderSize=0.000000
screenWidth=256
screenHeight=192
borderWidth=0
borderHeight=0
## OTHER OPTIONS
language=1

BIN
release/libgcc_s_seh-1.dll Normal file

Binary file not shown.

BIN
release/libstdc++-6.dll Normal file

Binary file not shown.

BIN
release/libwinpthread-1.dll Normal file

Binary file not shown.

View File

@@ -849,8 +849,8 @@ void Balloon::updateBounce()
{
if (bouncing.enabled)
{
bouncing.zoomW = bouncing.w.at(bouncing.counter / bouncing.speed);
bouncing.zoomH = bouncing.h.at(bouncing.counter / bouncing.speed);
bouncing.zoomW = bouncing.w[bouncing.counter / bouncing.speed];
bouncing.zoomH = bouncing.h[bouncing.counter / bouncing.speed];
sprite->setZoomW(bouncing.zoomW);
sprite->setZoomH(bouncing.zoomH);
bouncing.despX = (sprite->getSpriteClip().w - (sprite->getSpriteClip().w * bouncing.zoomW));

View File

@@ -1,186 +1,16 @@
#include "animatedsprite.h"
// Constructor
AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, std::string file, std::vector<std::string> *buffer)
{
// Copia los punteros
setTexture(texture);
setRenderer(renderer);
// Carga las animaciones
if (file != "")
{
loadFromFile(file);
}
else if (buffer)
{
loadFromVector(buffer);
}
// Inicializa variables
currentAnimation = 0;
}
// Destructor
AnimatedSprite::~AnimatedSprite()
{
for (auto &a : animation)
{
a.frames.clear();
}
animation.clear();
}
// Obtiene el indice de la animación a partir del nombre
int AnimatedSprite::getIndex(std::string name)
{
int index = -1;
for (auto a : animation)
{
index++;
if (a.name == name)
{
return index;
}
}
printf("** Warning: could not find \"%s\" animation\n", name.c_str());
return -1;
}
// Calcula el frame correspondiente a la animación
void AnimatedSprite::animate()
{
if (!enabled || animation.at(currentAnimation).speed == 0)
{
return;
}
// Calcula el frame actual a partir del contador
animation.at(currentAnimation).currentFrame = animation.at(currentAnimation).counter / animation.at(currentAnimation).speed;
// Si alcanza el final de la animación, reinicia el contador de la animación
// en función de la variable loop y coloca el nuevo frame
if (animation.at(currentAnimation).currentFrame >= (int)animation.at(currentAnimation).frames.size())
{
if (animation.at(currentAnimation).loop == -1)
{ // Si no hay loop, deja el último frame
animation.at(currentAnimation).currentFrame = animation.at(currentAnimation).frames.size();
animation.at(currentAnimation).completed = true;
}
else
{ // Si hay loop, vuelve al frame indicado
animation.at(currentAnimation).counter = 0;
animation.at(currentAnimation).currentFrame = animation.at(currentAnimation).loop;
}
}
// En caso contrario
else
{
// Escoge el frame correspondiente de la animación
setSpriteClip(animation.at(currentAnimation).frames.at(animation.at(currentAnimation).currentFrame));
// Incrementa el contador de la animacion
animation.at(currentAnimation).counter++;
}
}
// Obtiene el numero de frames de la animación actual
int AnimatedSprite::getNumFrames()
{
return (int)animation.at(currentAnimation).frames.size();
}
// Establece el frame actual de la animación
void AnimatedSprite::setCurrentFrame(int num)
{
// Descarta valores fuera de rango
if (num >= (int)animation.at(currentAnimation).frames.size())
{
num = 0;
}
// Cambia el valor de la variable
animation.at(currentAnimation).counter = animation.at(currentAnimation).speed * num;
// Escoge el frame correspondiente de la animación
setSpriteClip(animation.at(currentAnimation).frames.at(animation.at(currentAnimation).currentFrame));
}
// Establece el valor del contador
void AnimatedSprite::setAnimationCounter(std::string name, int num)
{
animation.at(getIndex(name)).counter = num;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(std::string name, int speed)
{
animation.at(getIndex(name)).counter = speed;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(int index, int speed)
{
animation.at(index).counter = speed;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(std::string name, int loop)
{
animation.at(getIndex(name)).loop = loop;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(int index, int loop)
{
animation.at(index).loop = loop;
}
// Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(std::string name, bool value)
{
animation.at(getIndex(name)).completed = value;
}
// OLD - Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(int index, bool value)
{
animation.at(index).completed = value;
}
// Comprueba si ha terminado la animación
bool AnimatedSprite::animationIsCompleted()
{
return animation.at(currentAnimation).completed;
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(std::string name, Uint8 index)
{
return animation.at(getIndex(name)).frames.at(index);
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF)
{
return animation.at(indexA).frames.at(indexF);
}
// Carga la animación desde un fichero
bool AnimatedSprite::loadFromFile(std::string filePath)
animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, bool verbose)
{
// Inicializa variables
animatedSprite_t as;
as.texture = texture;
int framesPerRow = 0;
int frameWidth = 0;
int frameHeight = 0;
int maxTiles = 0;
// Indicador de éxito en la carga
bool success = true;
const std::string filename = filePath.substr(filePath.find_last_of("\\/") + 1);
std::ifstream file(filePath);
std::string line;
@@ -189,13 +19,16 @@ bool AnimatedSprite::loadFromFile(std::string filePath)
if (file.good())
{
// Procesa el fichero linea a linea
std::cout << "Loading animation from file: " << filePath.c_str() << std::endl;
if (verbose)
{
std::cout << "Animation loaded: " << filename << std::endl;
}
while (std::getline(file, line))
{
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
t_animation buffer;
animation_t buffer;
buffer.counter = 0;
buffer.currentFrame = 0;
buffer.completed = false;
@@ -243,14 +76,13 @@ bool AnimatedSprite::loadFromFile(std::string filePath)
else
{
printf("Warning: file %s, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str());
success = false;
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
}
}
} while (line != "[/animation]");
// Añade la animación al vector de animaciones
animation.push_back(buffer);
as.animations.push_back(buffer);
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
@@ -279,8 +111,7 @@ bool AnimatedSprite::loadFromFile(std::string filePath)
else
{
printf("Warning: file %s, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str());
success = false;
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
}
// Normaliza valores
@@ -305,14 +136,207 @@ bool AnimatedSprite::loadFromFile(std::string filePath)
// El fichero no se puede abrir
else
{
printf("Warning: Unable to open %s file\n", filename.c_str());
success = false;
if (verbose)
{
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
}
}
// Pone un valor por defecto
setRect({0, 0, frameWidth, frameHeight});
return as;
}
return success;
// Constructor
AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, std::string file, std::vector<std::string> *buffer)
{
// Copia los punteros
setTexture(texture);
setRenderer(renderer);
// Carga las animaciones
if (file != "")
{
animatedSprite_t as = loadAnimationFromFile(texture, file);
// Copia los datos de las animaciones
for (auto animation : as.animations)
{
this->animation.push_back(animation);
}
}
else if (buffer)
{
loadFromVector(buffer);
}
// Inicializa variables
currentAnimation = 0;
}
// Constructor
AnimatedSprite::AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation)
{
// Copia los punteros
setTexture(animation->texture);
setRenderer(renderer);
// Inicializa variables
currentAnimation = 0;
// Copia los datos de las animaciones
for (auto a : animation->animations)
{
this->animation.push_back(a);
}
}
// Destructor
AnimatedSprite::~AnimatedSprite()
{
for (auto &a : animation)
{
a.frames.clear();
}
animation.clear();
}
// Obtiene el indice de la animación a partir del nombre
int AnimatedSprite::getIndex(std::string name)
{
int index = -1;
for (auto a : animation)
{
index++;
if (a.name == name)
{
return index;
}
}
std::cout << "** Warning: could not find \"" << name.c_str() << "\" animation" << std::endl;
return -1;
}
// Calcula el frame correspondiente a la animación
void AnimatedSprite::animate()
{
if (!enabled || animation[currentAnimation].speed == 0)
{
return;
}
// Calcula el frame actual a partir del contador
animation[currentAnimation].currentFrame = animation[currentAnimation].counter / animation[currentAnimation].speed;
// Si alcanza el final de la animación, reinicia el contador de la animación
// en función de la variable loop y coloca el nuevo frame
if (animation[currentAnimation].currentFrame >= (int)animation[currentAnimation].frames.size())
{
if (animation[currentAnimation].loop == -1)
{ // Si no hay loop, deja el último frame
animation[currentAnimation].currentFrame = animation[currentAnimation].frames.size();
animation[currentAnimation].completed = true;
}
else
{ // Si hay loop, vuelve al frame indicado
animation[currentAnimation].counter = 0;
animation[currentAnimation].currentFrame = animation[currentAnimation].loop;
}
}
// En caso contrario
else
{
// Escoge el frame correspondiente de la animación
setSpriteClip(animation[currentAnimation].frames[animation[currentAnimation].currentFrame]);
// Incrementa el contador de la animacion
animation[currentAnimation].counter++;
}
}
// Obtiene el numero de frames de la animación actual
int AnimatedSprite::getNumFrames()
{
return (int)animation[currentAnimation].frames.size();
}
// Establece el frame actual de la animación
void AnimatedSprite::setCurrentFrame(int num)
{
// Descarta valores fuera de rango
if (num >= (int)animation[currentAnimation].frames.size())
{
num = 0;
}
// Cambia el valor de la variable
animation[currentAnimation].currentFrame = num;
animation[currentAnimation].counter = 0;
// Escoge el frame correspondiente de la animación
setSpriteClip(animation[currentAnimation].frames[animation[currentAnimation].currentFrame]);
}
// Establece el valor del contador
void AnimatedSprite::setAnimationCounter(std::string name, int num)
{
animation[getIndex(name)].counter = num;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(std::string name, int speed)
{
animation[getIndex(name)].counter = speed;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(int index, int speed)
{
animation[index].counter = speed;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(std::string name, int loop)
{
animation[getIndex(name)].loop = loop;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(int index, int loop)
{
animation[index].loop = loop;
}
// Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(std::string name, bool value)
{
animation[getIndex(name)].completed = value;
}
// OLD - Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(int index, bool value)
{
animation[index].completed = value;
}
// Comprueba si ha terminado la animación
bool AnimatedSprite::animationIsCompleted()
{
return animation[currentAnimation].completed;
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(std::string name, Uint8 index)
{
return animation[getIndex(name)].frames[index];
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF)
{
return animation[indexA].frames[indexF];
}
// Carga la animación desde un vector
@@ -338,7 +362,7 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
t_animation buffer;
animation_t buffer;
buffer.counter = 0;
buffer.currentFrame = 0;
buffer.completed = false;
@@ -460,9 +484,9 @@ void AnimatedSprite::setCurrentAnimation(std::string name)
if (currentAnimation != newAnimation)
{
currentAnimation = newAnimation;
animation.at(currentAnimation).currentFrame = 0;
animation.at(currentAnimation).counter = 0;
animation.at(currentAnimation).completed = false;
animation[currentAnimation].currentFrame = 0;
animation[currentAnimation].counter = 0;
animation[currentAnimation].completed = false;
}
}
@@ -473,9 +497,9 @@ void AnimatedSprite::setCurrentAnimation(int index)
if (currentAnimation != newAnimation)
{
currentAnimation = newAnimation;
animation.at(currentAnimation).currentFrame = 0;
animation.at(currentAnimation).counter = 0;
animation.at(currentAnimation).completed = false;
animation[currentAnimation].currentFrame = 0;
animation[currentAnimation].counter = 0;
animation[currentAnimation].completed = false;
}
}
@@ -489,7 +513,7 @@ void AnimatedSprite::update()
// Establece el rectangulo para un frame de una animación
void AnimatedSprite::setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h)
{
animation.at(index_animation).frames.push_back({x, y, w, h});
animation[index_animation].frames.push_back({x, y, w, h});
}
// OLD - Establece el contador para todas las animaciones
@@ -504,7 +528,7 @@ void AnimatedSprite::setAnimationCounter(int value)
// Reinicia la animación
void AnimatedSprite::resetAnimation()
{
animation.at(currentAnimation).currentFrame = 0;
animation.at(currentAnimation).counter = 0;
animation.at(currentAnimation).completed = false;
animation[currentAnimation].currentFrame = 0;
animation[currentAnimation].counter = 0;
animation[currentAnimation].completed = false;
}

View File

@@ -11,28 +11,37 @@
#ifndef ANIMATEDSPRITE_H
#define ANIMATEDSPRITE_H
// Clase AnimatedSprite
struct animation_t
{
std::string name; // Nombre de la animacion
std::vector<SDL_Rect> frames; // Cada uno de los frames que componen la animación
int speed; // Velocidad de la animación
int loop; // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva
bool completed; // Indica si ha finalizado la animación
int currentFrame; // Frame actual
int counter; // Contador para las animaciones
};
struct animatedSprite_t
{
std::vector<animation_t> animations; // Vector con las diferentes animaciones
Texture *texture; // Textura con los graficos para el sprite
};
// Carga la animación desde un fichero
animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, bool verbose = false);
class AnimatedSprite : public MovingSprite
{
private:
struct t_animation
{
std::string name; // Nombre de la animacion
std::vector<SDL_Rect> frames; // Cada uno de los frames que componen la animación
int speed; // Velocidad de la animación
int loop; // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva
bool completed; // Indica si ha finalizado la animación
int currentFrame; // Frame actual
int counter; // Contador para las animaciones
};
// Variables
std::vector<t_animation> animation; // Vector con las diferentes animaciones
std::vector<animation_t> animation; // Vector con las diferentes animaciones
int currentAnimation; // Animacion activa
public:
// Constructor
AnimatedSprite(Texture *texture = nullptr, SDL_Renderer *renderer = nullptr, std::string file = "", std::vector<std::string> *buffer = nullptr);
AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation);
// Destructor
~AnimatedSprite();
@@ -65,15 +74,12 @@ public:
bool animationIsCompleted();
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect getAnimationClip(std::string name, Uint8 index);
SDL_Rect getAnimationClip(int indexA, Uint8 indexF);
SDL_Rect getAnimationClip(std::string name = "default", Uint8 index = 0);
SDL_Rect getAnimationClip(int indexA = 0, Uint8 indexF = 0);
// Obtiene el indice de la animación a partir del nombre
int getIndex(std::string name);
// Carga la animación desde un fichero
bool loadFromFile(std::string filePath);
// Carga la animación desde un vector
bool loadFromVector(std::vector<std::string> *source);

View File

@@ -1,22 +1,19 @@
#include "asset.h"
#include <iostream>
// Constructor
Asset::Asset(std::string executablePath)
{
this->executablePath = executablePath.substr(0, executablePath.find_last_of("\\/"));
longestName = 0;
}
// Destructor
Asset::~Asset()
{
verbose = true;
}
// Añade un elemento a la lista
void Asset::add(std::string file, enum assetType type, bool required)
void Asset::add(std::string file, enum assetType type, bool required, bool absolute)
{
item_t temp;
temp.file = executablePath + file;
temp.file = absolute ? file : executablePath + file;
temp.type = type;
temp.required = required;
fileList.push_back(temp);
@@ -30,13 +27,19 @@ std::string Asset::get(std::string text)
{
for (auto f : fileList)
{
if (f.file.find(text) != std::string::npos)
const size_t lastIndex = f.file.find_last_of("/") + 1;
const std::string file = f.file.substr(lastIndex, std::string::npos);
if (file == text)
{
return f.file;
}
}
printf("Warning: file %s not found\n", text.c_str());
if (verbose)
{
std::cout << "Warning: file " << text.c_str() << " not found" << std::endl;
}
return "";
}
@@ -45,7 +48,13 @@ bool Asset::check()
{
bool success = true;
printf("\n** Checking files.\n");
if (verbose)
{
std::cout << "\n** Checking files" << std::endl;
std::cout << "Executable path is: " << executablePath << std::endl;
std::cout << "Sample filepath: " << fileList.back().file << std::endl;
}
// Comprueba la lista de ficheros clasificandolos por tipo
for (int type = 0; type < t_maxAssetType; ++type)
@@ -64,7 +73,10 @@ bool Asset::check()
// Si hay ficheros de ese tipo, comprueba si existen
if (any)
{
printf("\n>> %s FILES\n", getTypeName(type).c_str());
if (verbose)
{
std::cout << "\n>> " << getTypeName(type).c_str() << " FILES" << std::endl;
}
for (auto f : fileList)
{
@@ -77,13 +89,18 @@ bool Asset::check()
}
// Resultado
if (success)
if (verbose)
{
printf("\n** All files OK.\n\n");
}
else
{
printf("\n** A file is missing. Exiting.\n\n");
if (success)
{
std::cout << "\n** All files OK.\n"
<< std::endl;
}
else
{
std::cout << "\n** A file is missing. Exiting.\n"
<< std::endl;
}
}
return success;
@@ -97,7 +114,7 @@ bool Asset::checkFile(std::string path)
// Comprueba si existe el fichero
const std::string filename = path.substr(path.find_last_of("\\/") + 1);
SDL_RWops *file = SDL_RWFromFile(path.c_str(), "r+b");
SDL_RWops *file = SDL_RWFromFile(path.c_str(), "rb");
if (file != nullptr)
{
@@ -106,8 +123,15 @@ bool Asset::checkFile(std::string path)
SDL_RWclose(file);
}
const std::string s = "Checking file %-" + std::to_string(longestName) + "s [" + result + "]\n";
printf(s.c_str(), filename.c_str());
if (verbose)
{
std::cout.setf(std::ios::left, std::ios::adjustfield);
std::cout << "Checking file: ";
std::cout.width(longestName + 2);
std::cout.fill('.');
std::cout << filename + " ";
std::cout << " [" + result + "]" << std::endl;
}
return success;
}
@@ -157,4 +181,10 @@ std::string Asset::getTypeName(int type)
return "ERROR";
break;
}
}
// Establece si ha de mostrar texto por pantalla
void Asset::setVerbose(bool value)
{
verbose = value;
}

View File

@@ -31,34 +31,36 @@ private:
std::string file; // Ruta del fichero desde la raiz del directorio
enum assetType type; // Indica el tipo de recurso
bool required; // Indica si es un fichero que debe de existir
//bool absolute; // Indica si la ruta que se ha proporcionado es una ruta absoluta
};
int longestName; // Contiene la longitud del nombre de fichero mas largo
std::vector<item_t> fileList;
std::string executablePath;
// Variables
int longestName; // Contiene la longitud del nombre de fichero mas largo
std::vector<item_t> fileList; // Listado con todas las rutas a los ficheros
std::string executablePath; // Ruta al ejecutable
bool verbose; // Indica si ha de mostrar información por pantalla
// Comprueba que existe un fichero
bool checkFile(std::string path);
bool checkFile(std::string executablePath);
// Devuelve el nombre del tipo de recurso
std::string getTypeName(int type);
public:
// Constructor
Asset(std::string executablePath);
// Destructor
~Asset();
Asset(std::string path);
// Añade un elemento a la lista
void add(std::string file, enum assetType type, bool required = true);
void add(std::string file, enum assetType type, bool required = true, bool absolute = false);
// Devuelve un elemento de la lista a partir de una cadena
std::string get(std::string text);
// Comprueba que existen todos los elementos
bool check();
// Establece si ha de mostrar texto por pantalla
void setVerbose(bool value);
};
#endif

View File

@@ -11,42 +11,53 @@ Input::Input(std::string file)
keyBindings_t kb;
kb.scancode = 0;
kb.active = false;
keyBindings.resize(17, kb);
keyBindings.resize(input_number_of_inputs, kb);
GameControllerBindings_t gcb;
gcb.button = SDL_CONTROLLER_BUTTON_INVALID;
gcb.active = false;
gameControllerBindings.resize(17, gcb);
gameControllerBindings.resize(input_number_of_inputs, gcb);
// Comprueba si hay un mando conectado
discoverGameController();
verbose = true;
enabled = true;
}
// Destructor
Input::~Input()
// Actualiza el estado del objeto
void Input::update()
{
if (disabledUntil == d_keyPressed && !checkAnyInput())
{
enable();
}
}
// Asigna uno de los posibles inputs a una tecla del teclado
// Asigna inputs a teclas
void Input::bindKey(Uint8 input, SDL_Scancode code)
{
keyBindings.at(input).scancode = code;
keyBindings[input].scancode = code;
}
// Asigna uno de los posibles inputs a un botón del mando
// Asigna inputs a botones del mando
void Input::bindGameControllerButton(Uint8 input, SDL_GameControllerButton button)
{
gameControllerBindings.at(input).button = button;
gameControllerBindings[input].button = button;
}
// Comprueba si un input esta activo
bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
{
if (!enabled)
{
return false;
}
bool successKeyboard = false;
bool successGameController = false;
if (device == INPUT_USE_ANY)
{
index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
{
@@ -54,7 +65,7 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
if (repeat)
{
if (keyStates[keyBindings.at(input).scancode] != 0)
if (keyStates[keyBindings[input].scancode] != 0)
{
successKeyboard = true;
}
@@ -65,11 +76,11 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
}
else
{
if (!keyBindings.at(input).active)
if (!keyBindings[input].active)
{
if (keyStates[keyBindings.at(input).scancode] != 0)
if (keyStates[keyBindings[input].scancode] != 0)
{
keyBindings.at(input).active = true;
keyBindings[input].active = true;
successKeyboard = true;
}
else
@@ -79,9 +90,9 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
}
else
{
if (keyStates[keyBindings.at(input).scancode] == 0)
if (keyStates[keyBindings[input].scancode] == 0)
{
keyBindings.at(input).active = false;
keyBindings[input].active = false;
successKeyboard = false;
}
else
@@ -97,7 +108,7 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
{
if (repeat)
{
if (SDL_GameControllerGetButton(connectedControllers.at(index), gameControllerBindings.at(input).button) != 0)
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[input].button) != 0)
{
successGameController = true;
}
@@ -108,11 +119,11 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
}
else
{
if (!gameControllerBindings.at(input).active)
if (!gameControllerBindings[input].active)
{
if (SDL_GameControllerGetButton(connectedControllers.at(index), gameControllerBindings.at(input).button) != 0)
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[input].button) != 0)
{
gameControllerBindings.at(input).active = true;
gameControllerBindings[input].active = true;
successGameController = true;
}
else
@@ -122,9 +133,9 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
}
else
{
if (SDL_GameControllerGetButton(connectedControllers.at(index), gameControllerBindings.at(input).button) == 0)
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[input].button) == 0)
{
gameControllerBindings.at(input).active = false;
gameControllerBindings[input].active = false;
successGameController = false;
}
else
@@ -152,7 +163,7 @@ bool Input::checkAnyInput(int device, int index)
for (int i = 0; i < (int)keyBindings.size(); ++i)
{
if (mKeystates[keyBindings.at(i).scancode] != 0)
if (mKeystates[keyBindings[i].scancode] != 0)
{
return true;
}
@@ -165,7 +176,7 @@ bool Input::checkAnyInput(int device, int index)
{
for (int i = 0; i < (int)gameControllerBindings.size(); ++i)
{
if (SDL_GameControllerGetButton(connectedControllers.at(index), gameControllerBindings.at(i).button) != 0)
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[i].button) != 0)
{
return true;
}
@@ -176,7 +187,7 @@ bool Input::checkAnyInput(int device, int index)
return false;
}
// Comprueba si hay un mando conectado
// Busca si hay un mando conectado
bool Input::discoverGameController()
{
bool found = false;
@@ -188,7 +199,10 @@ bool Input::discoverGameController()
if (SDL_GameControllerAddMappingsFromFile(dbPath.c_str()) < 0)
{
printf("Error, could not load %s file: %s\n", dbPath.c_str(), SDL_GetError());
if (verbose)
{
std::cout << "Error, could not load " << dbPath.c_str() << " file: " << SDL_GetError() << std::endl;
}
}
const int nJoysticks = SDL_NumJoysticks();
@@ -203,8 +217,11 @@ bool Input::discoverGameController()
}
}
printf("\nChecking for game controllers...\n");
printf("%i joysticks found, %i are gamepads\n", nJoysticks, numGamepads);
if (verbose)
{
std::cout << "\nChecking for game controllers...\n";
std::cout << nJoysticks << " joysticks found, " << numGamepads << " are gamepads\n";
}
if (numGamepads > 0)
{
@@ -221,12 +238,18 @@ bool Input::discoverGameController()
std::string name = SDL_GameControllerNameForIndex(i);
name.resize(25);
name = name + separator + std::to_string(i);
std::cout << name << std::endl;
if (verbose)
{
std::cout << name << std::endl;
}
controllerNames.push_back(name);
}
else
{
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
if (verbose)
{
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
}
}
}
@@ -254,7 +277,7 @@ std::string Input::getControllerName(int index)
{
if (numGamepads > 0)
{
return controllerNames.at(index);
return controllerNames[index];
}
else
{
@@ -266,4 +289,24 @@ std::string Input::getControllerName(int index)
int Input::getNumControllers()
{
return numGamepads;
}
// Establece si ha de mostrar mensajes
void Input::setVerbose(bool value)
{
verbose = value;
}
// Deshabilita las entradas durante un periodo de tiempo
void Input::disableUntil(i_disable_e value)
{
disabledUntil = value;
enabled = false;
}
// Hablita las entradas
void Input::enable()
{
enabled = true;
disabledUntil = d_notDisabled;
}

View File

@@ -7,23 +7,30 @@
#ifndef INPUT_H
#define INPUT_H
#define INPUT_NULL 0
#define INPUT_UP 1
#define INPUT_DOWN 2
#define INPUT_LEFT 3
#define INPUT_RIGHT 4
#define INPUT_ACCEPT 5
#define INPUT_CANCEL 6
#define INPUT_BUTTON_1 7
#define INPUT_BUTTON_2 8
#define INPUT_BUTTON_3 9
#define INPUT_BUTTON_4 10
#define INPUT_BUTTON_5 11
#define INPUT_BUTTON_6 12
#define INPUT_BUTTON_7 13
#define INPUT_BUTTON_8 14
#define INPUT_BUTTON_PAUSE 15
#define INPUT_BUTTON_ESCAPE 16
enum inputs_e
{
// Inputs obligatorios
input_null,
input_up,
input_down,
input_left,
input_right,
input_pause,
input_exit,
input_accept,
input_cancel,
// Inputs personalizados
input_fire_left,
input_fire_center,
input_fire_right,
input_window_fullscreen,
input_window_inc_size,
input_window_dec_size,
// Input obligatorio
input_number_of_inputs
};
#define REPEAT_TRUE true
#define REPEAT_FALSE false
@@ -32,7 +39,13 @@
#define INPUT_USE_GAMECONTROLLER 1
#define INPUT_USE_ANY 2
// Clase Input
enum i_disable_e
{
d_notDisabled,
d_forever,
d_keyPressed
};
class Input
{
private:
@@ -48,34 +61,40 @@ private:
bool active; // Indica si está activo
};
// Objetos y punteros
std::vector<SDL_GameController *> connectedControllers; // Vector con todos los mandos conectados
// Variables
std::vector<keyBindings_t> keyBindings; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<GameControllerBindings_t> gameControllerBindings; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<SDL_GameController *> connectedControllers; // Vector con todos los mandos conectados
std::vector<std::string> controllerNames; // Vector con los nombres de los mandos
int numGamepads; // Numero de mandos conectados
std::string dbPath; // Ruta al archivo gamecontrollerdb.txt
// Comprueba si hay un mando conectado
bool discoverGameController();
bool verbose; // Indica si ha de mostrar mensajes
i_disable_e disabledUntil; // Tiempo que esta deshabilitado
bool enabled; // Indica si está habilitado
public:
// Constructor
Input(std::string file);
// Destructor
~Input();
// Actualiza el estado del objeto
void update();
// Asigna uno de los posibles inputs a una tecla del teclado
// Asigna inputs a teclas
void bindKey(Uint8 input, SDL_Scancode code);
// Asigna uno de los posibles inputs a un botón del mando
// Asigna inputs a botones del mando
void bindGameControllerButton(Uint8 input, SDL_GameControllerButton button);
// Comprueba si un input esta activo
bool checkInput(Uint8 input, bool repeat, int device = INPUT_USE_ANY, int index = 0);
bool checkInput(Uint8 input, bool repeat = true, int device = INPUT_USE_ANY, int index = 0);
// Comprueba si hay almenos un input activo
bool checkAnyInput(int device, int index);
bool checkAnyInput(int device = INPUT_USE_ANY, int index = 0);
// Busca si hay un mando conectado
bool discoverGameController();
// Comprueba si hay algun mando conectado
bool gameControllerFound();
@@ -85,6 +104,15 @@ public:
// Obten el nombre de un mando de juego
std::string getControllerName(int index);
// Establece si ha de mostrar mensajes
void setVerbose(bool value);
// Deshabilita las entradas durante un periodo de tiempo
void disableUntil(i_disable_e value);
// Hablita las entradas
void enable();
};
#endif

View File

@@ -1,3 +1,4 @@
#ifndef JA_USESDLMIXER
#include "jail_audio.h"
#include "stb_vorbis.c"
#include <SDL2/SDL.h>
@@ -11,7 +12,7 @@ struct JA_Sound_t {
};
struct JA_Channel_t {
JA_Sound sound;
JA_Sound_t *sound;
int pos {0};
int times {0};
JA_Channel_state state { JA_CHANNEL_FREE };
@@ -25,7 +26,7 @@ struct JA_Music_t {
JA_Music_state state {JA_MUSIC_INVALID};
};
JA_Music current_music{NULL};
JA_Music_t *current_music{NULL};
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
int JA_freq {48000};
@@ -86,7 +87,7 @@ void JA_Quit() {
sdlAudioDevice = 0;
}
JA_Music JA_LoadMusic(const char* filename) {
JA_Music_t *JA_LoadMusic(const char* filename) {
int chan, samplerate;
// [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid.
@@ -98,7 +99,7 @@ JA_Music JA_LoadMusic(const char* filename) {
if (fread(buffer, fsize, 1, f)!=1) return NULL;
fclose(f);
JA_Music music = new JA_Music_t();
JA_Music_t *music = new JA_Music_t();
music->samples = stb_vorbis_decode_memory(buffer, fsize, &chan, &samplerate, &music->output);
free(buffer);
@@ -121,7 +122,7 @@ JA_Music JA_LoadMusic(const char* filename) {
return music;
}
void JA_PlayMusic(JA_Music music, const int loop) {
void JA_PlayMusic(JA_Music_t *music, const int loop) {
if (current_music != NULL) {
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
@@ -153,21 +154,21 @@ JA_Music_state JA_GetMusicState() {
return current_music->state;
}
void JA_DeleteMusic(JA_Music music) {
void JA_DeleteMusic(JA_Music_t *music) {
if (current_music == music) current_music = NULL;
free(music->output);
delete music;
}
JA_Sound JA_NewSound(Uint8* buffer, Uint32 length) {
JA_Sound sound = new JA_Sound_t();
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length) {
JA_Sound_t *sound = new JA_Sound_t();
sound->buffer = buffer;
sound->length = length;
return sound;
}
JA_Sound JA_LoadSound(const char* filename) {
JA_Sound sound = new JA_Sound_t();
JA_Sound_t *JA_LoadSound(const char* filename) {
JA_Sound_t *sound = new JA_Sound_t();
SDL_AudioSpec wavSpec;
SDL_LoadWAV(filename, &wavSpec, &sound->buffer, &sound->length);
@@ -184,7 +185,7 @@ JA_Sound JA_LoadSound(const char* filename) {
return sound;
}
int JA_PlaySound(JA_Sound sound, const int loop) {
int JA_PlaySound(JA_Sound_t *sound, const int loop) {
int channel = 0;
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; }
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0;
@@ -196,7 +197,7 @@ int JA_PlaySound(JA_Sound sound, const int loop) {
return channel;
}
void JA_DeleteSound(JA_Sound sound) {
void JA_DeleteSound(JA_Sound_t *sound) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].sound == sound) JA_StopChannel(i);
}
@@ -246,4 +247,5 @@ JA_Channel_state JA_GetChannelState(const int channel) {
int JA_SetVolume(int volume) {
JA_volume = volume > 128 ? 128 : volume < 0 ? 0 : volume;
return JA_volume;
}
}
#endif

View File

@@ -4,27 +4,27 @@
enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED };
enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED };
typedef struct JA_Sound_t *JA_Sound;
typedef struct JA_Music_t *JA_Music;
struct JA_Sound_t;
struct JA_Music_t;
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels);
void JA_Quit();
JA_Music JA_LoadMusic(const char* filename);
void JA_PlayMusic(JA_Music music, const int loop = -1);
JA_Music_t *JA_LoadMusic(const char* filename);
void JA_PlayMusic(JA_Music_t *music, const int loop = -1);
void JA_PauseMusic();
void JA_ResumeMusic();
void JA_StopMusic();
JA_Music_state JA_GetMusicState();
void JA_DeleteMusic(JA_Music music);
void JA_DeleteMusic(JA_Music_t *music);
JA_Sound JA_NewSound(Uint8* buffer, Uint32 length);
JA_Sound JA_LoadSound(const char* filename);
int JA_PlaySound(JA_Sound sound, const int loop = 0);
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length);
JA_Sound_t *JA_LoadSound(const char* filename);
int JA_PlaySound(JA_Sound_t *sound, const int loop = 0);
void JA_PauseChannel(const int channel);
void JA_ResumeChannel(const int channel);
void JA_StopChannel(const int channel);
JA_Channel_state JA_GetChannelState(const int channel);
void JA_DeleteSound(JA_Sound sound);
void JA_DeleteSound(JA_Sound_t *sound);
int JA_SetVolume(int volume);

View File

@@ -0,0 +1,101 @@
#ifdef JA_USESDLMIXER
#include "jail_audio.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
#include <stdio.h>
struct JA_Sound_t {}; // Dummy structs
struct JA_Music_t {};
int JA_freq {48000};
SDL_AudioFormat JA_format {AUDIO_S16};
Uint8 JA_channels {2};
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) {
JA_freq = freq;
JA_format = format;
JA_channels = channels;
Mix_OpenAudio(JA_freq, JA_format, JA_channels, 1024);
}
void JA_Quit() {
Mix_CloseAudio();
}
JA_Music_t *JA_LoadMusic(const char* filename) {
return (JA_Music_t*)Mix_LoadMUS(filename);
}
void JA_PlayMusic(JA_Music_t *music, const int loop) {
Mix_PlayMusic((Mix_Music*)music, loop);
}
void JA_PauseMusic() {
Mix_PauseMusic();
}
void JA_ResumeMusic() {
Mix_ResumeMusic();
}
void JA_StopMusic() {
Mix_HaltMusic();
}
JA_Music_state JA_GetMusicState() {
if (Mix_PausedMusic()) {
return JA_MUSIC_PAUSED;
} else if (Mix_PlayingMusic()) {
return JA_MUSIC_PLAYING;
} else {
return JA_MUSIC_STOPPED;
}
}
void JA_DeleteMusic(JA_Music_t *music) {
Mix_FreeMusic((Mix_Music*)music);
}
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length) {
return NULL;
}
JA_Sound_t *JA_LoadSound(const char* filename) {
JA_Sound_t *sound = (JA_Sound_t*)Mix_LoadWAV(filename);
return sound;
}
int JA_PlaySound(JA_Sound_t *sound, const int loop) {
return Mix_PlayChannel(-1, (Mix_Chunk*)sound, loop);
}
void JA_DeleteSound(JA_Sound_t *sound) {
Mix_FreeChunk((Mix_Chunk*)sound);
}
void JA_PauseChannel(const int channel) {
Mix_Pause(channel);
}
void JA_ResumeChannel(const int channel) {
Mix_Resume(channel);
}
void JA_StopChannel(const int channel) {
Mix_HaltChannel(channel);
}
JA_Channel_state JA_GetChannelState(const int channel) {
if (Mix_Paused(channel)) {
return JA_CHANNEL_PAUSED;
} else if (Mix_Playing(channel)) {
return JA_CHANNEL_PLAYING;
} else {
return JA_CHANNEL_FREE;
}
}
int JA_SetVolume(int volume) {
return Mix_Volume(-1, volume);
}
#endif

View File

@@ -1,4 +1,6 @@
#include "../const.h"
#include "menu.h"
#include <iostream>
// Constructor
Menu::Menu(SDL_Renderer *renderer, Asset *asset, Input *input, std::string file)
@@ -106,7 +108,7 @@ bool Menu::load(std::string file_path)
if (file.good())
{
// Procesa el fichero linea a linea
printf("Reading file %s\n", filename.c_str());
std::cout << "Reading file " << filename.c_str() << std::endl;
while (std::getline(file, line))
{
if (line == "[item]")
@@ -129,7 +131,7 @@ bool Menu::load(std::string file_path)
// Procesa las dos subcadenas
if (!setItem(&item, line.substr(0, pos), line.substr(pos + 1, line.length())))
{
printf("Warning: file %s\n, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str());
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
success = false;
}
@@ -146,7 +148,7 @@ bool Menu::load(std::string file_path)
// Procesa las dos subcadenas
if (!setVars(line.substr(0, pos), line.substr(pos + 1, line.length())))
{
printf("Warning: file %s, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str());
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
success = false;
}
@@ -160,13 +162,13 @@ bool Menu::load(std::string file_path)
}
// Cierra el fichero
printf("Closing file %s\n", filename.c_str());
std::cout << "Closing file " << filename.c_str() << std::endl;
file.close();
}
// El fichero no se puede abrir
else
{
printf("Warning: Unable to open %s file\n", filename.c_str());
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
success = false;
}
@@ -207,7 +209,7 @@ bool Menu::setItem(item_t *item, std::string var, std::string value)
else if ((var == "") || (var == "[/item]"))
{
}
else
{
success = false;
@@ -404,7 +406,7 @@ void Menu::updateSelector()
selector.moving = false;
}
}
else if (selector.despY < 0) // Va hacia arriba
{
if (selector.y < selector.targetY) // Ha llegado al destino
@@ -433,7 +435,7 @@ void Menu::updateSelector()
selector.resizing = false;
}
}
else if (selector.incH < 0) // Decrece
{
if (selector.h < selector.targetH) // Ha llegado al destino
@@ -457,7 +459,7 @@ void Menu::setSelectorPos(int index)
if (index < (int)item.size())
{
selector.index = index;
selector.rect.y = selector.y = selector.originY = selector.targetY = item.at(selector.index).rect.y;
selector.rect.y = selector.y = selector.originY = selector.targetY = item[selector.index].rect.y;
selector.rect.w = rectBG.rect.w;
selector.rect.x = rectBG.rect.x;
selector.originH = selector.targetH = selector.rect.h = getSelectorHeight(selector.index);
@@ -485,13 +487,13 @@ void Menu::reset()
{
itemSelected = MENU_NO_OPTION;
selector.index = 0;
selector.originY = selector.targetY = selector.y = item.at(0).rect.y;
selector.originH = selector.targetH = item.at(0).rect.h;
selector.originY = selector.targetY = selector.y = item[0].rect.y;
selector.originH = selector.targetH = item[0].rect.h;
selector.moving = false;
selector.resizing = false;
// Si el primer elemento no es seleccionable, incrementa el selector
if (!item.at(selector.index).selectable)
if (!item[selector.index].selectable)
{
increaseSelectorIndex();
setSelectorPos(selector.index);
@@ -523,18 +525,18 @@ void Menu::reorganize()
bool Menu::increaseSelectorIndex()
{
// Obten las coordenadas del elemento actual
selector.y = selector.originY = item.at(selector.index).rect.y;
selector.y = selector.originY = item[selector.index].rect.y;
selector.h = selector.originH = getSelectorHeight(selector.index);
// Calcula cual es el siguiente elemento
++selector.index %= item.size();
while (!item.at(selector.index).selectable)
while (!item[selector.index].selectable)
{
++selector.index %= item.size();
}
// Establece las coordenadas y altura de destino
selector.targetY = item.at(selector.index).rect.y;
selector.targetY = item[selector.index].rect.y;
selector.despY = (selector.targetY - selector.originY) / selector.numJumps;
selector.targetH = getSelectorHeight(selector.index);
@@ -553,7 +555,7 @@ bool Menu::increaseSelectorIndex()
bool Menu::decreaseSelectorIndex()
{
// Obten las coordenadas del elemento actual
selector.y = selector.originY = item.at(selector.index).rect.y;
selector.y = selector.originY = item[selector.index].rect.y;
selector.h = selector.originH = getSelectorHeight(selector.index);
// Calcula cual es el siguiente elemento
@@ -566,7 +568,7 @@ bool Menu::decreaseSelectorIndex()
selector.index--;
}
while (!item.at(selector.index).selectable)
while (!item[selector.index].selectable)
{
if (selector.index == 0)
{
@@ -579,7 +581,7 @@ bool Menu::decreaseSelectorIndex()
}
// Establece las coordenadas y altura de destino
selector.targetY = item.at(selector.index).rect.y;
selector.targetY = item[selector.index].rect.y;
selector.despY = (selector.targetY - selector.originY) / selector.numJumps;
selector.targetH = getSelectorHeight(selector.index);
@@ -629,29 +631,29 @@ void Menu::render()
if (i == selector.index)
{
const color_t color = {selector.itemColor.r, selector.itemColor.g, selector.itemColor.b};
text->writeColored(item.at(i).rect.x, item.at(i).rect.y, item.at(i).label, color);
text->writeColored(item[i].rect.x, item[i].rect.y, item[i].label, color);
}
else if (item.at(i).selectable)
else if (item[i].selectable)
{
text->write(item.at(i).rect.x, item.at(i).rect.y, item.at(i).label);
text->write(item[i].rect.x, item[i].rect.y, item[i].label);
}
else if (item.at(i).greyed)
else if (item[i].greyed)
{
text->writeColored(item.at(i).rect.x, item.at(i).rect.y, item.at(i).label, colorGreyed);
text->writeColored(item[i].rect.x, item[i].rect.y, item[i].label, colorGreyed);
}
else
{ // No seleccionable
if ((item.at(i).linkedUp) && (i == selector.index + 1))
if ((item[i].linkedUp) && (i == selector.index + 1))
{
const color_t color = {selector.itemColor.r, selector.itemColor.g, selector.itemColor.b};
text->writeColored(item.at(i).rect.x, item.at(i).rect.y, item.at(i).label, color);
text->writeColored(item[i].rect.x, item[i].rect.y, item[i].label, color);
}
else // No enlazado con el de arriba
{
text->write(item.at(i).rect.x, item.at(i).rect.y, item.at(i).label);
text->write(item[i].rect.x, item[i].rect.y, item[i].label);
}
}
}
@@ -821,7 +823,7 @@ void Menu::addItem(std::string text, int hPaddingDown, bool selectable, bool gre
if (item.size() > 1)
{
if (item.at(item.size() - 2).linkedDown)
if (item[item.size() - 2].linkedDown)
{
item.back().linkedUp = true;
}
@@ -834,9 +836,9 @@ void Menu::addItem(std::string text, int hPaddingDown, bool selectable, bool gre
// Cambia el texto de un item
void Menu::setItemCaption(int index, std::string text)
{
item.at(index).label = text;
item.at(index).rect.w = this->text->lenght(item.at(index).label);
item.at(index).rect.h = this->text->getCharacterSize();
item[index].label = text;
item[index].rect.w = this->text->lenght(item[index].label);
item[index].rect.h = this->text->getCharacterSize();
reorganize();
}
@@ -849,7 +851,7 @@ void Menu::setDefaultActionWhenCancel(int item)
// Gestiona la entrada de teclado y mando durante el menu
void Menu::checkInput()
{
if (input->checkInput(INPUT_UP, REPEAT_FALSE))
if (input->checkInput(input_up, REPEAT_FALSE))
{
if (decreaseSelectorIndex())
{
@@ -860,7 +862,7 @@ void Menu::checkInput()
}
}
if (input->checkInput(INPUT_DOWN, REPEAT_FALSE))
if (input->checkInput(input_down, REPEAT_FALSE))
{
if (increaseSelectorIndex())
{
@@ -871,7 +873,7 @@ void Menu::checkInput()
}
}
if (input->checkInput(INPUT_ACCEPT, REPEAT_FALSE))
if (input->checkInput(input_accept, REPEAT_FALSE))
{
itemSelected = selector.index;
if (soundAccept)
@@ -880,7 +882,7 @@ void Menu::checkInput()
}
}
if (input->checkInput(INPUT_CANCEL, REPEAT_FALSE))
if (input->checkInput(input_cancel, REPEAT_FALSE))
{
itemSelected = defaultActionWhenCancel;
if (soundCancel)
@@ -913,42 +915,42 @@ int Menu::findHeight()
// Recoloca los elementos del menu en el eje Y
void Menu::replaceElementsOnY()
{
item.at(0).rect.y = y;
item[0].rect.y = y;
for (int i = 1; i < (int)item.size(); i++)
{
item.at(i).rect.y = item.at(i - 1).rect.y + item.at(i - 1).rect.h + item.at(i - 1).hPaddingDown;
item[i].rect.y = item[i - 1].rect.y + item[i - 1].rect.h + item[i - 1].hPaddingDown;
}
}
// Establece el estado seleccionable de un item
void Menu::setSelectable(int index, bool value)
{
item.at(index).selectable = value;
item[index].selectable = value;
}
// Establece el estado agrisado de un item
void Menu::setGreyed(int index, bool value)
{
item.at(index).greyed = value;
item[index].greyed = value;
}
// Establece el estado de enlace de un item
void Menu::setLinkedDown(int index, bool value)
{
item.at(index).linkedDown = value;
item[index].linkedDown = value;
}
// Calcula la altura del selector
int Menu::getSelectorHeight(int value)
{
if (item.at(value).linkedDown)
if (item[value].linkedDown)
{
return item.at(value).rect.h + item.at(value).hPaddingDown + item.at(value + 1).rect.h;
return item[value].rect.h + item[value].hPaddingDown + item[value + 1].rect.h;
}
else
{
return item.at(value).rect.h;
return item[value].rect.h;
}
}
@@ -976,6 +978,6 @@ void Menu::setText(std::string font_png, std::string font_txt)
{
if (!text)
{
text = new Text(font_png, font_txt, renderer);
text = new Text(asset->get(font_png), asset->get(font_txt), renderer);
}
}

View File

@@ -70,9 +70,9 @@ private:
// Objetos y punteros
SDL_Renderer *renderer; // Puntero al renderizador de la ventana
Asset *asset; // Objeto para gestionar los ficheros de recursos
Text *text; // Texto para poder escribir los items del menu
Input *input; // Gestor de eventos de entrada de teclado o gamepad
Asset *asset; // Objeto para gestionar los ficheros de recursos
// Variables
std::string name; // Nombre del menu
@@ -89,9 +89,9 @@ private:
bool isCenteredOnY; // Variable para saber si el menu debe estar centrado respecto a un punto en el eje Y
bool areElementsCenteredOnX; // Variable para saber si los elementos van centrados en el eje X
int widestItem; // Anchura del elemento más ancho
JA_Sound soundAccept; // Sonido al aceptar o elegir una opción del menu
JA_Sound soundCancel; // Sonido al cancelar el menu
JA_Sound soundMove; // Sonido al mover el selector
JA_Sound_t* soundAccept; // Sonido al aceptar o elegir una opción del menu
JA_Sound_t* soundCancel; // Sonido al cancelar el menu
JA_Sound_t* soundMove; // Sonido al mover el selector
color_t colorGreyed; // Color para los elementos agrisados
rectangle_t rectBG; // Rectangulo de fondo del menu
std::vector<item_t> item; // Estructura para cada elemento del menu

View File

@@ -1,24 +1,30 @@
#include "notify.h"
#include <string>
#include <stdio.h>
#include <iostream>
// Constructor
Notify::Notify(SDL_Renderer *renderer, std::string bitmapFile, std::string textFile)
Notify::Notify(SDL_Renderer *renderer, std::string bitmapFile, std::string textFile, std::string soundFile, options_t *options)
{
// Inicializa variables
this->renderer = renderer;
bgColor = {64, 64, 64};
this->options = options;
bgColor = options->notifications.color;
waitTime = 300;
// Crea objetos
text = new Text(bitmapFile, textFile, renderer);
texture = new Texture(renderer, bitmapFile);
text = new Text(textFile, texture, renderer);
sound = JA_LoadSound(soundFile.c_str());
}
// Destructor
Notify::~Notify()
{
// Libera la memoria de los objetos
delete texture;
delete text;
JA_DeleteSound(sound);
for (auto notification : notifications)
{
@@ -32,7 +38,7 @@ void Notify::render()
{
for (int i = (int)notifications.size() - 1; i >= 0; --i)
{
notifications.at(i).sprite->render();
notifications[i].sprite->render();
}
}
@@ -41,49 +47,63 @@ void Notify::update()
{
for (int i = 0; i < (int)notifications.size(); ++i)
{
notifications.at(i).counter++;
notifications[i].counter++;
// Comprueba los estados
if (notifications.at(i).state == ns_rising)
if (notifications[i].state == ns_rising)
{
const float step = ((float)notifications.at(i).counter / notifications.at(i).travelDist);
const float step = ((float)notifications[i].counter / notifications[i].travelDist);
const int alpha = 255 * step;
notifications.at(i).rect.y++;
notifications.at(i).texture->setAlpha(alpha);
if (notifications.at(i).rect.y == notifications.at(i).y)
if (options->notifications.posV == pos_top)
{
notifications.at(i).state = ns_stay;
notifications.at(i).texture->setAlpha(255);
notifications.at(i).counter = 0;
notifications[i].rect.y++;
}
else
{
notifications[i].rect.y--;
}
notifications[i].texture->setAlpha(alpha);
if (notifications[i].rect.y == notifications[i].y)
{
notifications[i].state = ns_stay;
notifications[i].texture->setAlpha(255);
notifications[i].counter = 0;
}
}
else if (notifications.at(i).state == ns_stay)
else if (notifications[i].state == ns_stay)
{
if (notifications.at(i).counter == waitTime)
if (notifications[i].counter == waitTime)
{
notifications.at(i).state = ns_vanishing;
notifications.at(i).counter = 0;
notifications[i].state = ns_vanishing;
notifications[i].counter = 0;
}
}
else if (notifications.at(i).state == ns_vanishing)
else if (notifications[i].state == ns_vanishing)
{
const float step = (notifications.at(i).counter / (float)notifications.at(i).travelDist);
const float step = (notifications[i].counter / (float)notifications[i].travelDist);
const int alpha = 255 * (1 - step);
notifications.at(i).rect.y--;
notifications.at(i).texture->setAlpha(alpha);
if (notifications.at(i).rect.y == notifications.at(i).y - notifications.at(i).travelDist)
if (options->notifications.posV == pos_top)
{
notifications.at(i).state = ns_finished;
notifications[i].rect.y--;
}
else
{
notifications[i].rect.y++;
}
notifications[i].texture->setAlpha(alpha);
if (notifications[i].rect.y == notifications[i].y - notifications[i].travelDist)
{
notifications[i].state = ns_finished;
}
}
notifications.at(i).sprite->setRect(notifications.at(i).rect);
notifications[i].sprite->setRect(notifications[i].rect);
}
clearFinishedNotifications();
@@ -94,10 +114,10 @@ void Notify::clearFinishedNotifications()
{
for (int i = (int)notifications.size() - 1; i >= 0; --i)
{
if (notifications.at(i).state == ns_finished)
if (notifications[i].state == ns_finished)
{
delete notifications.at(i).sprite;
delete notifications.at(i).texture;
delete notifications[i].sprite;
delete notifications[i].texture;
notifications.erase(notifications.begin() + i);
}
}
@@ -106,25 +126,67 @@ void Notify::clearFinishedNotifications()
// Muestra una notificación de texto por pantalla;
void Notify::showText(std::string text)
{
// Crea constantes
// Inicializa variables
const int width = this->text->lenght(text) + (this->text->getCharacterSize() * 2);
const int height = this->text->getCharacterSize() * 2;
const int despH = this->text->getCharacterSize() / 2;
const int despV = despH;
const int travelDist = height + despV;
// const int offset = (int)notifications.size() * (travelDist) + despV;
const int offset = (int)notifications.size() > 0 ? notifications.back().y + travelDist : despV;
const int padding = (this->text->getCharacterSize() / 2);
// Posición horizontal
int despH = 0;
if (options->notifications.posH == pos_left)
{
despH = padding;
}
else if (options->notifications.posH == pos_middle)
{
despH = ((options->screen.windowWidth * options->windowSize) / 2 - (width / 2));
}
else
{
despH = (options->screen.windowWidth * options->windowSize) - width - padding;
}
// Posición vertical
int despV = 0;
if (options->notifications.posV == pos_top)
{
despV = padding;
}
else
{
despV = (options->screen.windowHeight * options->windowSize) - height - padding;
}
const int travelDist = height + padding;
// Offset
int offset = 0;
if (options->notifications.posV == pos_top)
{
offset = (int)notifications.size() > 0 ? notifications.back().y + travelDist : despV;
}
else
{
offset = (int)notifications.size() > 0 ? notifications.back().y - travelDist : despV;
}
// Crea la notificacion
notification_t n;
// inicializa variables
// Inicializa variables
n.y = offset;
n.travelDist = travelDist;
n.counter = 0;
n.state = ns_rising;
n.text = text;
n.rect = {despH, offset - travelDist, width, height};
if (options->notifications.posV == pos_top)
{
n.rect = {despH, offset - travelDist, width, height};
}
else
{
n.rect = {despH, offset + travelDist, width, height};
}
// Crea la textura
n.texture = new Texture(renderer);
@@ -133,11 +195,29 @@ void Notify::showText(std::string text)
SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(renderer);
n.texture->setBlendMode(SDL_BLENDMODE_BLEND);
this->text->writeDX(TXT_CENTER | TXT_STROKE, width / 2, despV, text, 1, {255, 255, 255}, 1, {0, 0, 0});
this->text->writeDX(TXT_CENTER | TXT_STROKE, width / 2, padding, text, 1, {255, 255, 255}, 1, {0, 0, 0});
SDL_SetRenderTarget(renderer, nullptr);
// Crea el sprite
n.sprite = new Sprite(n.rect, n.texture, renderer);
// Añade la notificación a la lista
notifications.push_back(n);
// Reproduce el sonido de la notificación
if (options->notifications.sound)
{
JA_PlaySound(sound);
}
}
// Indica si hay notificaciones activas
bool Notify::active()
{
if ((int)notifications.size() > 0)
{
return true;
}
return false;
}

View File

@@ -1,9 +1,10 @@
#pragma once
#include <SDL2/SDL.h>
#include "jail_audio.h"
#include "sprite.h"
#include "text.h"
#include "texture.h"
#include "sprite.h"
#include "utils.h"
#include <vector>
@@ -48,12 +49,15 @@ private:
// Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana
Texture *texture; // Textura para la fuente de las notificaciones
Text *text; // Objeto para dibujar texto
options_t *options; // Variable con todas las opciones del programa
// Variables
color_t bgColor; // Color de fondo de las notificaciones
int waitTime; // Tiempo que se ve la notificación
std::vector<notification_t> notifications; // La lista de notificaciones activas
JA_Sound_t* sound; // Sonido a reproducir cuando suena la notificación
// Elimina las notificaciones finalizadas
void clearFinishedNotifications();
@@ -66,13 +70,16 @@ public:
void update();
// Constructor
Notify(SDL_Renderer *renderer, std::string bitmapFile, std::string textFile);
Notify(SDL_Renderer *renderer, std::string bitmapFile, std::string textFile, std::string soundFile, options_t *options);
// Destructor
~Notify();
// Muestra una notificación de texto por pantalla;
void showText(std::string text);
// Indica si hay notificaciones activas
bool active();
};
#endif

View File

@@ -1,9 +1,9 @@
#include "screen.h"
#include <string>
#include <stdio.h>
#include <iostream>
// Constructor
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options, int gameInternalResX, int gameInternalResY)
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options)
{
// Inicializa variables
this->window = window;
@@ -12,11 +12,14 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options
this->asset = asset;
// Crea los objetos
//notify = new Notify(renderer, asset->get("smb2_big.png"), asset->get("smb2_big.txt"));
notify = new Notify(renderer, asset->get("smb2.png"), asset->get("smb2.txt"));
notify = new Notify(renderer, asset->get("smb2.png"), asset->get("smb2.txt"), asset->get("notify.wav"), options);
gameCanvasWidth = gameInternalResX;
gameCanvasHeight = gameInternalResY;
gameCanvasWidth = options->gameWidth;
gameCanvasHeight = options->gameHeight;
borderWidth = options->borderWidth * 2;
borderHeight = options->borderHeight * 2;
notificationLogicalWidth = gameCanvasWidth;
notificationLogicalHeight = gameCanvasHeight;
iniFade();
iniSpectrumFade();
@@ -28,19 +31,17 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options
gameCanvas = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, gameCanvasWidth, gameCanvasHeight);
if (gameCanvas == nullptr)
{
printf("TitleSurface could not be created!\nSDL Error: %s\n", SDL_GetError());
if (options->console)
{
std::cout << "TitleSurface could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
// Establece el modo de video
setVideoMode(options->fullScreenMode);
setVideoMode(options->videoMode);
// Calcula los anclajes
anchor.left = 0;
anchor.right = gameCanvasWidth;
anchor.center = gameCanvasWidth / 2;
anchor.top = 0;
anchor.bottom = gameCanvasHeight;
anchor.middle = gameCanvasHeight / 2;
// Inicializa variables
notifyActive = false;
}
// Destructor
@@ -83,104 +84,103 @@ void Screen::blit()
}
// Establece el modo de video
void Screen::setVideoMode(int fullScreenMode)
void Screen::setVideoMode(int videoMode)
{
// Aplica el modo de video
SDL_SetWindowFullscreen(window, fullScreenMode);
SDL_SetWindowFullscreen(window, videoMode);
// Si está activo el modo ventana quita el borde
if (fullScreenMode == 0)
if (videoMode == 0)
{
// Muestra el puntero
SDL_ShowCursor(SDL_ENABLE);
if (options->borderEnabled)
{
const int incWidth = gameCanvasWidth * options->borderSize;
const int incHeight = gameCanvasHeight * options->borderSize;
screenWidth = gameCanvasWidth + incWidth;
screenHeight = gameCanvasHeight + incHeight;
dest = {0 + (incWidth / 2), 0 + (incHeight / 2), gameCanvasWidth, gameCanvasHeight};
windowWidth = gameCanvasWidth + borderWidth;
windowHeight = gameCanvasHeight + borderHeight;
dest = {0 + (borderWidth / 2), 0 + (borderHeight / 2), gameCanvasWidth, gameCanvasHeight};
}
else
{
screenWidth = gameCanvasWidth * options->windowSize;
screenHeight = gameCanvasHeight * options->windowSize;
windowWidth = gameCanvasWidth;
windowHeight = gameCanvasHeight;
dest = {0, 0, gameCanvasWidth, gameCanvasHeight};
}
// Modifica el tamaño del renderizador y de la ventana
// SDL_RenderSetLogicalSize(renderer, screenWidth, screenHeight);
// SDL_SetWindowSize(window, screenWidth * options->windowSize, screenHeight * options->windowSize);
SDL_RenderSetLogicalSize(renderer, gameCanvasWidth, gameCanvasHeight);
SDL_SetWindowSize(window, screenWidth, screenHeight);
// Modifica el tamaño de la ventana
SDL_SetWindowSize(window, windowWidth * options->windowSize, windowHeight * options->windowSize);
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
}
// Si está activo el modo de pantalla completa añade el borde
else if (fullScreenMode == SDL_WINDOW_FULLSCREEN_DESKTOP)
else if (videoMode == SDL_WINDOW_FULLSCREEN_DESKTOP)
{
// Oculta el puntero
SDL_ShowCursor(SDL_DISABLE);
// Obten el alto y el ancho de la ventana
SDL_GetWindowSize(window, &screenWidth, &screenHeight);
SDL_GetWindowSize(window, &windowWidth, &windowHeight);
// Aplica el escalado al rectangulo donde se pinta la textura del juego
if (options->integerScale)
{
// Calcula el tamaño de la escala máxima
int scale = 0;
while (((gameCanvasWidth * (scale + 1)) <= screenWidth) && ((gameCanvasHeight * (scale + 1)) <= screenHeight))
while (((gameCanvasWidth * (scale + 1)) <= windowWidth) && ((gameCanvasHeight * (scale + 1)) <= windowHeight))
{
scale++;
}
dest.w = gameCanvasWidth * scale;
dest.h = gameCanvasHeight * scale;
dest.x = (screenWidth - dest.w) / 2;
dest.y = (screenHeight - dest.h) / 2;
dest.x = (windowWidth - dest.w) / 2;
dest.y = (windowHeight - dest.h) / 2;
}
else if (options->keepAspect)
{
float ratio = (float)gameCanvasWidth / (float)gameCanvasHeight;
if ((screenWidth - gameCanvasWidth) >= (screenHeight - gameCanvasHeight))
if ((windowWidth - gameCanvasWidth) >= (windowHeight - gameCanvasHeight))
{
dest.h = screenHeight;
dest.w = (int)((screenHeight * ratio) + 0.5f);
dest.x = (screenWidth - dest.w) / 2;
dest.y = (screenHeight - dest.h) / 2;
dest.h = windowHeight;
dest.w = (int)((windowHeight * ratio) + 0.5f);
dest.x = (windowWidth - dest.w) / 2;
dest.y = (windowHeight - dest.h) / 2;
}
else
{
dest.w = screenWidth;
dest.h = (int)((screenWidth / ratio) + 0.5f);
dest.x = (screenWidth - dest.w) / 2;
dest.y = (screenHeight - dest.h) / 2;
dest.w = windowWidth;
dest.h = (int)((windowWidth / ratio) + 0.5f);
dest.x = (windowWidth - dest.w) / 2;
dest.y = (windowHeight - dest.h) / 2;
}
}
else
{
dest.w = screenWidth;
dest.h = screenHeight;
dest.w = windowWidth;
dest.h = windowHeight;
dest.x = dest.y = 0;
}
// Modifica el tamaño del renderizador
SDL_RenderSetLogicalSize(renderer, screenWidth, screenHeight);
}
// Actualiza el valor de la variable
options->fullScreenMode = fullScreenMode;
// Modifica el tamaño del renderizador
SDL_RenderSetLogicalSize(renderer, windowWidth, windowHeight);
// Actualiza las opciones
options->videoMode = videoMode;
options->screen.windowWidth = windowWidth;
options->screen.windowHeight = windowHeight;
// Establece el tamaño de las notificaciones
setNotificationSize();
}
// Camibia entre pantalla completa y ventana
void Screen::switchVideoMode()
{
if (options->fullScreenMode == 0)
{
options->fullScreenMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
}
else
{
options->fullScreenMode = 0;
}
setVideoMode(options->fullScreenMode);
options->videoMode = (options->videoMode == 0) ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0;
setVideoMode(options->videoMode);
}
// Cambia el tamaño de la ventana
@@ -190,6 +190,22 @@ void Screen::setWindowSize(int size)
setVideoMode(0);
}
// Reduce el tamaño de la ventana
void Screen::decWindowSize()
{
--options->windowSize;
options->windowSize = std::max(options->windowSize, 1);
setVideoMode(0);
}
// Aumenta el tamaño de la ventana
void Screen::incWindowSize()
{
++options->windowSize;
options->windowSize = std::min(options->windowSize, 4);
setVideoMode(0);
}
// Cambia el color del borde
void Screen::setBorderColor(color_t color)
{
@@ -203,9 +219,15 @@ void Screen::setBlendMode(SDL_BlendMode blendMode)
}
// Establece el tamaño del borde
void Screen::setBorderSize(float s)
void Screen::setBorderWidth(int s)
{
options->borderSize = s;
options->borderWidth = s;
}
// Establece el tamaño del borde
void Screen::setBorderHeight(int s)
{
options->borderHeight = s;
}
// Establece si se ha de ver el borde en el modo ventana
@@ -303,30 +325,12 @@ void Screen::iniSpectrumFade()
spectrumColor.clear();
color_t c;
c = stringToColor("black");
spectrumColor.push_back(c);
c = stringToColor("blue");
spectrumColor.push_back(c);
c = stringToColor("red");
spectrumColor.push_back(c);
c = stringToColor("magenta");
spectrumColor.push_back(c);
c = stringToColor("green");
spectrumColor.push_back(c);
c = stringToColor("cyan");
spectrumColor.push_back(c);
c = stringToColor("yellow");
spectrumColor.push_back(c);
c = stringToColor("bright_white");
spectrumColor.push_back(c);
// Inicializa el vector de colores
const std::vector<std::string> vColors = {"black", "blue", "red", "magenta", "green", "cyan", "yellow", "bright_white"};
for (auto v : vColors)
{
spectrumColor.push_back(stringToColor(options->palette, v));
}
}
// Actualiza el spectrum fade
@@ -356,7 +360,7 @@ void Screen::renderSpectrumFade()
const float step = (float)spectrumFadeCounter / (float)spectrumFadeLenght;
const int max = spectrumColor.size() - 1;
const int index = max + (0 - max) * step;
const color_t c = spectrumColor.at(index);
const color_t c = spectrumColor[index];
SDL_SetTextureColorMod(gameCanvas, c.r, c.g, c.b);
}
@@ -378,10 +382,11 @@ void Screen::renderFX()
void Screen::updateNotifier()
{
notify->update();
notifyActive = notify->active();
}
// Muestra una notificación de texto por pantalla;
void Screen::showText(std::string text)
void Screen::showNotification(std::string text)
{
notify->showText(text);
}
@@ -389,7 +394,36 @@ void Screen::showText(std::string text)
// Dibuja las notificaciones
void Screen::renderNotifications()
{
SDL_RenderSetLogicalSize(renderer, screenWidth, screenHeight);
if (!notifyActive)
{
return;
}
SDL_RenderSetLogicalSize(renderer, notificationLogicalWidth, notificationLogicalHeight);
notify->render();
SDL_RenderSetLogicalSize(renderer, gameCanvasWidth, gameCanvasHeight);
SDL_RenderSetLogicalSize(renderer, windowWidth, windowHeight);
}
// Establece el tamaño de las notificaciones
void Screen::setNotificationSize()
{
if (options->videoMode == 0)
{
if (options->windowSize == 3)
{
notificationLogicalWidth = (windowWidth * 3) / 2;
notificationLogicalHeight = (windowHeight * 3) / 2;
}
else
{
notificationLogicalWidth = windowWidth * 2;
notificationLogicalHeight = windowHeight * 2;
}
}
if (options->videoMode == SDL_WINDOW_FULLSCREEN_DESKTOP)
{
notificationLogicalWidth = windowWidth / 3;
notificationLogicalHeight = windowHeight / 3;
}
}

View File

@@ -12,21 +12,10 @@
#define FILTER_NEAREST 0
#define FILTER_LINEAL 1
struct anchor_t
{
int left; // Parte izquierda de la pantalla de juego
int right; // Parte drecha de la pantalla de juego
int center; // Parte central horizontal de la pantalla de juego
int top; // Parte superior de la pantalla de juego
int bottom; // Parte infoerior de la pantalla de juego
int middle; // Parte central vertical de la pantalla de juego
};
// Clase Screen
class Screen
{
private:
// Objetos y variables
// Objetos y punteros
SDL_Window *window; // Ventana de la aplicación
SDL_Renderer *renderer; // El renderizador de la ventana
Asset *asset; // Objeto con el listado de recursos
@@ -34,15 +23,20 @@ private:
options_t *options; // Variable con todas las opciones del programa
Notify *notify; // Dibuja notificaciones por pantalla
int screenWidth; // Ancho de la pantalla o ventana
int screenHeight; // Alto de la pantalla o ventana
int gameCanvasWidth; // Resolución interna del juego. Es el ancho de la textura donde se dibuja el juego
int gameCanvasHeight; // Resolución interna del juego. Es el alto de la textura donde se dibuja el juego
anchor_t anchor; // Variable con los anclajes de la pantalla
SDL_Rect dest; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
color_t borderColor; // Color del borde añadido a la textura de juego para rellenar la pantalla
// Variables
int windowWidth; // Ancho de la pantalla o ventana
int windowHeight; // Alto de la pantalla o ventana
int gameCanvasWidth; // Resolución interna del juego. Es el ancho de la textura donde se dibuja el juego
int gameCanvasHeight; // Resolución interna del juego. Es el alto de la textura donde se dibuja el juego
int borderWidth; // Anchura del borde
int borderHeight; // Anltura del borde
SDL_Rect dest; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
color_t borderColor; // Color del borde añadido a la textura de juego para rellenar la pantalla
bool notifyActive; // Indica si hay notificaciones activas
int notificationLogicalWidth; // Ancho lógico de las notificaciones en relación al tamaño de pantalla
int notificationLogicalHeight; // Alto lógico de las notificaciones en relación al tamaño de pantalla
// EFECTOS
// Variables - Efectos
bool fade; // Indica si esta activo el efecto de fade
int fadeCounter; // Temporizador para el efecto de fade
int fadeLenght; // Duración del fade
@@ -72,9 +66,12 @@ private:
// Dibuja las notificaciones
void renderNotifications();
// Establece el tamaño de las notificaciones
void setNotificationSize();
public:
// Constructor
Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options, int gameInternalResX, int gameInternalResY);
Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options);
// Destructor
~Screen();
@@ -89,7 +86,7 @@ public:
void blit();
// Establece el modo de video
void setVideoMode(int fullScreenMode);
void setVideoMode(int videoMode);
// Camibia entre pantalla completa y ventana
void switchVideoMode();
@@ -97,6 +94,12 @@ public:
// Cambia el tamaño de la ventana
void setWindowSize(int size);
// Reduce el tamaño de la ventana
void decWindowSize();
// Aumenta el tamaño de la ventana
void incWindowSize();
// Cambia el color del borde
void setBorderColor(color_t color);
@@ -104,7 +107,8 @@ public:
void setBlendMode(SDL_BlendMode blendMode);
// Establece el tamaño del borde
void setBorderSize(float s);
void setBorderWidth(int s);
void setBorderHeight(int s);
// Establece si se ha de ver el borde en el modo ventana
void setBorderEnabled(bool value);
@@ -134,7 +138,7 @@ public:
void updateNotifier();
// Muestra una notificación de texto por pantalla;
void showText(std::string text);
void showNotification(std::string text);
};
#endif

View File

@@ -3,22 +3,156 @@
#include <iostream>
#include <fstream>
// Llena una estructuta textFile_t desde un fichero
textFile_t LoadTextFile(std::string file, bool verbose)
{
textFile_t tf;
// Inicializa a cero el vector con las coordenadas
for (int i = 0; i < 128; ++i)
{
tf.offset[i].x = 0;
tf.offset[i].y = 0;
tf.offset[i].w = 0;
}
// Abre el fichero para leer los valores
const std::string filename = file.substr(file.find_last_of("\\/") + 1).c_str();
std::ifstream rfile(file);
if (rfile.is_open() && rfile.good())
{
std::string buffer;
// Lee los dos primeros valores del fichero
std::getline(rfile, buffer);
std::getline(rfile, buffer);
tf.boxWidth = std::stoi(buffer);
std::getline(rfile, buffer);
std::getline(rfile, buffer);
tf.boxHeight = std::stoi(buffer);
// lee el resto de datos del fichero
int index = 32;
int line_read = 0;
while (std::getline(rfile, buffer))
{
// Almacena solo las lineas impares
if (line_read % 2 == 1)
{
tf.offset[index++].w = std::stoi(buffer);
}
// Limpia el buffer
buffer.clear();
line_read++;
};
// Cierra el fichero
if (verbose)
{
std::cout << "Text loaded: " << filename.c_str() << std::endl;
}
rfile.close();
}
// El fichero no se puede abrir
else
{
if (verbose)
{
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
}
}
// Establece las coordenadas para cada caracter ascii de la cadena y su ancho
for (int i = 32; i < 128; ++i)
{
tf.offset[i].x = ((i - 32) % 15) * tf.boxWidth;
tf.offset[i].y = ((i - 32) / 15) * tf.boxHeight;
}
return tf;
}
// Constructor
Text::Text(std::string bitmapFile, std::string textFile, SDL_Renderer *renderer)
{
// Carga los offsets desde el fichero
initOffsetFromFile(textFile);
textFile_t tf = LoadTextFile(textFile);
// Inicializa variables desde la estructura
boxHeight = tf.boxHeight;
boxWidth = tf.boxWidth;
for (int i = 0; i < 128; ++i)
{
offset[i].x = tf.offset[i].x;
offset[i].y = tf.offset[i].y;
offset[i].w = tf.offset[i].w;
}
// Crea los objetos
texture = new Texture(renderer, bitmapFile);
sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture, renderer);
// Inicializa variables
fixedWidth = false;
}
// Constructor
Text::Text(std::string textFile, Texture *texture, SDL_Renderer *renderer)
{
// Carga los offsets desde el fichero
textFile_t tf = LoadTextFile(textFile);
// Inicializa variables desde la estructura
boxHeight = tf.boxHeight;
boxWidth = tf.boxWidth;
for (int i = 0; i < 128; ++i)
{
offset[i].x = tf.offset[i].x;
offset[i].y = tf.offset[i].y;
offset[i].w = tf.offset[i].w;
}
// Crea los objetos
this->texture = nullptr;
sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture, renderer);
// Inicializa variables
fixedWidth = false;
}
// Constructor
Text::Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer)
{
// Inicializa variables desde la estructura
boxHeight = textFile->boxHeight;
boxWidth = textFile->boxWidth;
for (int i = 0; i < 128; ++i)
{
offset[i].x = textFile->offset[i].x;
offset[i].y = textFile->offset[i].y;
offset[i].w = textFile->offset[i].w;
}
// Crea los objetos
this->texture = nullptr;
sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture, renderer);
// Inicializa variables
fixedWidth = false;
}
// Destructor
Text::~Text()
{
delete texture;
delete sprite;
if (texture != nullptr)
{
delete texture;
}
}
// Escribe texto en pantalla
@@ -27,15 +161,20 @@ void Text::write(int x, int y, std::string text, int kerning, int lenght)
int shift = 0;
if (lenght == -1)
{
lenght = text.length();
}
sprite->setPosY(y);
const int width = sprite->getWidth();
const int height = sprite->getHeight();
for (int i = 0; i < lenght; ++i)
{
sprite->setSpriteClip(offset[int(text[i])].x, offset[int(text[i])].y, sprite->getWidth(), sprite->getHeight());
const int index = text[i];
sprite->setSpriteClip(offset[index].x, offset[index].y, width, height);
sprite->setPosX(x + shift);
sprite->setPosY(y);
sprite->render();
shift += (offset[int(text[i])].w + kerning);
shift += fixedWidth ? boxWidth : (offset[int(text[i])].w + kerning);
}
}
@@ -72,28 +211,37 @@ void Text::writeDX(Uint8 flags, int x, int y, std::string text, int kerning, col
const bool stroked = ((flags & TXT_STROKE) == TXT_STROKE);
if (centered)
{
x -= (Text::lenght(text, kerning) / 2);
}
if (shadowed)
{
writeColored(x + shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
}
if (stroked)
{
writeColored(x + shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x - shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x + shadowDistance, y - shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x - shadowDistance, y - shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x, y + shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x, y - shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x + shadowDistance, y, text, shadowColor, kerning, lenght);
writeColored(x - shadowDistance, y, text, shadowColor, kerning, lenght);
for (int dist = 1; dist <= shadowDistance; ++dist)
{
for (int dy = -dist; dy <= dist; ++dy)
{
for (int dx = -dist; dx <= dist; ++dx)
{
writeColored(x + dx, y + dy, text, shadowColor, kerning, lenght);
}
}
}
}
if (colored)
{
writeColored(x, y, text, textColor, kerning, lenght);
}
else
{
write(x, y, text, kerning, lenght);
}
}
// Obtiene la longitud en pixels de una cadena
@@ -108,69 +256,6 @@ int Text::lenght(std::string text, int kerning)
return shift - kerning;
}
// Inicializa el vector de offsets desde un fichero
void Text::initOffsetFromFile(std::string file)
{
// Inicializa a cero el vector con las coordenadas
for (int i = 0; i < 128; ++i)
{
offset[i].x = 0;
offset[i].y = 0;
offset[i].w = 0;
}
// Abre el fichero para leer los valores
const std::string filename = file.substr(file.find_last_of("\\/") + 1).c_str();
std::ifstream rfile(file);
if (rfile.is_open() && rfile.good())
{
std::string buffer;
// Lee los dos primeros valores del fichero
std::getline(rfile, buffer);
std::getline(rfile, buffer);
boxWidth = std::stoi(buffer);
std::getline(rfile, buffer);
std::getline(rfile, buffer);
boxHeight = std::stoi(buffer);
// lee el resto de datos del fichero
int index = 32;
int line_read = 0;
while (std::getline(rfile, buffer))
{
// Almacena solo las lineas impares
if (line_read % 2 == 1)
{
offset[index++].w = std::stoi(buffer);
}
// Limpia el buffer
buffer.clear();
line_read++;
};
// Cierra el fichero
printf("Text loaded: %s\n", filename.c_str());
rfile.close();
}
// El fichero no se puede abrir
else
{
printf("Warning: Unable to open %s file\n", filename.c_str());
}
// Establece las coordenadas para cada caracter ascii de la cadena y su ancho
for (int i = 32; i < 128; ++i)
{
offset[i].x = ((i - 32) % 15) * boxWidth;
offset[i].y = ((i - 32) / 15) * boxHeight;
}
}
// Devuelve el valor de la variable
int Text::getCharacterSize()
{
@@ -180,5 +265,11 @@ int Text::getCharacterSize()
// Recarga la textura
void Text::reLoadTexture()
{
texture->reLoad();
sprite->getTexture()->reLoad();
}
// Establece si se usa un tamaño fijo de letra
void Text::setFixedWidth(bool value)
{
fixedWidth = value;
}

View File

@@ -11,32 +11,42 @@
#define TXT_CENTER 4
#define TXT_STROKE 8
struct offset_t
{
int x;
int y;
int w;
};
struct textFile_t
{
int boxWidth; // Anchura de la caja de cada caracter en el png
int boxHeight; // Altura de la caja de cada caracter en el png
offset_t offset[128]; // Vector con las posiciones y ancho de cada letra
};
// Llena una estructuta textFile_t desde un fichero
textFile_t LoadTextFile(std::string file, bool verbose = false);
// Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text
{
private:
struct offset_t
{
int x;
int y;
int w;
};
// Objetos y punteros
Sprite *sprite; // Objeto con los graficos para el texto
Sprite *sprite; // Objeto con los graficos para el texto
Texture *texture; // Textura con los bitmaps del texto
// Variables
int boxWidth; // Anchura de la caja de cada caracter en el png
int boxHeight; // Altura de la caja de cada caracter en el png
int boxWidth; // Anchura de la caja de cada caracter en el png
int boxHeight; // Altura de la caja de cada caracter en el png
bool fixedWidth; // Indica si el texto se ha de escribir con longitud fija en todas las letras
offset_t offset[128]; // Vector con las posiciones y ancho de cada letra
// Inicializa el vector de offsets desde un fichero
void initOffsetFromFile(std::string file);
public:
// Constructor
Text(std::string bitmapFile, std::string textFile, SDL_Renderer *renderer);
Text(std::string textFile, Texture *texture, SDL_Renderer *renderer);
Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer);
// Destructor
~Text();
@@ -64,6 +74,9 @@ public:
// Recarga la textura
void reLoadTexture();
// Establece si se usa un tamaño fijo de letra
void setFixedWidth(bool value);
};
#endif

View File

@@ -2,9 +2,10 @@
#include "texture.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <iostream>
// Constructor
Texture::Texture(SDL_Renderer *renderer, std::string path)
Texture::Texture(SDL_Renderer *renderer, std::string path, bool verbose)
{
// Copia punteros
this->renderer = renderer;
@@ -18,7 +19,7 @@ Texture::Texture(SDL_Renderer *renderer, std::string path)
// Carga el fichero en la textura
if (path != "")
{
loadFromFile(path, renderer);
loadFromFile(path, renderer, verbose);
}
}
@@ -30,9 +31,9 @@ Texture::~Texture()
}
// Carga una imagen desde un fichero
bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer)
bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbose)
{
const std::string filename = path.substr(path.find_last_of("\\/") + 1);
const std::string filename = path.substr(path.find_last_of("\\/") + 1);
int req_format = STBI_rgb_alpha;
int width, height, orig_format;
unsigned char *data = stbi_load(path.c_str(), &width, &height, &orig_format, req_format);
@@ -43,7 +44,10 @@ bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer)
}
else
{
printf("Image loaded: %s\n", filename.c_str());
if (verbose)
{
std::cout << "Image loaded: " << filename.c_str() << std::endl;
}
}
int depth, pitch;
@@ -71,7 +75,10 @@ bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer)
SDL_Surface *loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom((void *)data, width, height, depth, pitch, pixel_format);
if (loadedSurface == nullptr)
{
printf("Unable to load image %s!\n", path.c_str());
if (verbose)
{
std::cout << "Unable to load image " << path.c_str() << std::endl;
}
}
else
{
@@ -79,7 +86,10 @@ bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer)
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
if (newTexture == nullptr)
{
printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
if (verbose)
{
std::cout << "Unable to create texture from " << path.c_str() << "! SDL Error: " << SDL_GetError() << std::endl;
}
}
else
{
@@ -93,6 +103,7 @@ bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer)
}
// Return success
stbi_image_free(data);
texture = newTexture;
return texture != nullptr;
}
@@ -104,7 +115,7 @@ bool Texture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_Tex
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, access, width, height);
if (texture == nullptr)
{
printf("Unable to create blank texture! SDL Error: %s\n", SDL_GetError());
std::cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << std::endl;
}
else
{
@@ -188,4 +199,10 @@ int Texture::getHeight()
bool Texture::reLoad()
{
return loadFromFile(path, renderer);
}
// Obtiene la textura
SDL_Texture *Texture::getSDLTexture()
{
return texture;
}

View File

@@ -21,13 +21,13 @@ private:
public:
// Constructor
Texture(SDL_Renderer *renderer, std::string path = "");
Texture(SDL_Renderer *renderer, std::string path = "", bool verbose = false);
// Destructor
~Texture();
// Carga una imagen desde un fichero
bool loadFromFile(std::string path, SDL_Renderer *renderer);
bool loadFromFile(std::string path, SDL_Renderer *renderer, bool verbose = false);
// Crea una textura en blanco
bool createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING);
@@ -58,6 +58,9 @@ public:
// Recarga la textura
bool reLoad();
// Obtiene la textura
SDL_Texture *getSDLTexture();
};
#endif

View File

@@ -380,11 +380,9 @@ bool checkCollision(SDL_Point &p, d_line_t &l)
}
// Devuelve un color_t a partir de un string
color_t stringToColor(std::string str)
color_t stringToColor(palette_e pal, std::string str)
{
const std::string palette = "spectrum";
if (palette == "spectrum")
if (pal == p_zxspectrum)
{
if (str == "black")
{
@@ -467,7 +465,7 @@ color_t stringToColor(std::string str)
}
}
else
else if (pal == p_zxarne)
{ // zxarne
if (str == "black")
{

View File

@@ -57,6 +57,23 @@ struct color_t
Uint8 b;
};
// Tipos de paleta
enum palette_e
{
p_zxspectrum,
p_zxarne
};
// Posiciones de las notificaciones
enum not_pos_e
{
pos_top,
pos_bottom,
pos_left,
pos_middle,
pos_right
};
// Estructura para saber la seccion y subseccion del programa
struct section_t
{
@@ -87,6 +104,7 @@ struct input_t
struct online_t
{
bool enabled; // Indica si se quiere usar el modo online o no
bool sessionEnabled; // Indica ya se ha hecho login
std::string server; // Servidor para los servicios online
int port; // Puerto del servidor
std::string gameID; // Identificador del juego para los servicios online
@@ -94,6 +112,22 @@ struct online_t
int score; // Puntuación almacenada online
};
// Estructura con opciones de la pantalla
struct op_screen_t
{
int windowWidth; // Ancho de la ventana
int windowHeight; // Alto de la ventana
};
// Estructura para las opciones de las notificaciones
struct op_notification_t
{
not_pos_e posH; // Ubicación de las notificaciones en pantalla
not_pos_e posV; // Ubicación de las notificaciones en pantalla
bool sound; // Indica si las notificaciones suenan
color_t color; // Color de las notificaciones
};
// Estructura con todas las opciones de configuración del programa
struct options_t
{
@@ -101,17 +135,24 @@ struct options_t
Uint8 playerSelected; // Jugador seleccionado para el modo 1P
std::vector<input_t> input; // Modo de control (teclado o mando)
Uint8 language; // Idioma usado en el juego
Uint32 fullScreenMode; // Contiene el valor del modo de pantalla completa
Uint8 windowSize; // Contiene el valor por el que se multiplica el tamaño de la ventana
Uint32 filter; // Filtro usado para el escalado de la imagen
bool vSync; // Indica si se quiere usar vsync o no
int screenWidth; // Ancho de la pantalla/ventana
int screenHeight; // Alto de la pantalla/ventana
bool integerScale; // Indica si el escalado de la imagen ha de ser entero en el modo a pantalla completa
bool keepAspect; // Indica si se ha de mantener la relación de aspecto al poner el modo a pantalla completa
bool borderEnabled; // Indica si ha de mostrar el borde en el modo de ventana
float borderSize; // Porcentaje de borde que se añade a lo ventana
online_t online; // Datos del servicio online
Uint32 videoMode; // Contiene el valor del modo de pantalla completa
int windowSize; // Contiene el valor por el que se multiplica el tamaño de la ventana
Uint32 filter; // Filtro usado para el escalado de la imagen
bool vSync; // Indica si se quiere usar vsync o no
int gameWidth; // Ancho de la resolucion nativa del juego
int gameHeight; // Alto de la resolucion nativa del juego
bool integerScale; // Indica si el escalado de la imagen ha de ser entero en el modo a pantalla completa
bool keepAspect; // Indica si se ha de mantener la relación de aspecto al poner el modo a pantalla completa
bool borderEnabled; // Indica si ha de mostrar el borde en el modo de ventana
int borderWidth; // Cantidad de pixels que se añade en el borde de la ventana
int borderHeight; // Cantidad de pixels que se añade en el borde de la ventana
palette_e palette; // Paleta de colores a usar en el juego
bool console; // Indica si ha de mostrar información por la consola de texto
online_t online; // Datos del servicio online
op_screen_t screen; // Opciones relativas a la clase screen
op_notification_t notifications; // Opciones relativas a las notificaciones;
};
// Calcula el cuadrado de la distancia entre dos puntos
@@ -151,7 +192,7 @@ bool checkCollision(SDL_Point &p, d_line_t &l);
void normalizeLine(d_line_t &l);
// Devuelve un color_t a partir de un string
color_t stringToColor(std::string str);
color_t stringToColor(palette_e pal, std::string str);
// Convierte una cadena en un valor booleano
bool stringToBool(std::string str);

View File

@@ -11,15 +11,15 @@
#define BLOCK 8
#define HALF_BLOCK BLOCK / 2
// Tamaño de la pantalla de juego
#define GAME_WIDTH 256
#define GAME_HEIGHT 192
// Tamaño de la pantalla virtual
#define GAMECANVAS_WIDTH 256
#define GAMECANVAS_HEIGHT 192
// Zona de juego
const int PLAY_AREA_TOP = (0 * BLOCK);
const int PLAY_AREA_BOTTOM = GAME_HEIGHT - (4 * BLOCK);
const int PLAY_AREA_BOTTOM = GAMECANVAS_HEIGHT - (4 * BLOCK);
const int PLAY_AREA_LEFT = (0 * BLOCK);
const int PLAY_AREA_RIGHT = GAME_WIDTH - (0 * BLOCK);
const int PLAY_AREA_RIGHT = GAMECANVAS_WIDTH - (0 * BLOCK);
const int PLAY_AREA_WIDTH = PLAY_AREA_RIGHT - PLAY_AREA_LEFT;
const int PLAY_AREA_HEIGHT = PLAY_AREA_BOTTOM - PLAY_AREA_TOP;
const int PLAY_AREA_CENTER_X = PLAY_AREA_LEFT + (PLAY_AREA_WIDTH / 2);
@@ -30,12 +30,12 @@ const int PLAY_AREA_FIRST_QUARTER_Y = PLAY_AREA_HEIGHT / 4;
const int PLAY_AREA_THIRD_QUARTER_Y = (PLAY_AREA_HEIGHT / 4) * 3;
// Anclajes de pantalla
const int SCREEN_CENTER_X = GAME_WIDTH / 2;
const int SCREEN_FIRST_QUARTER_X = GAME_WIDTH / 4;
const int SCREEN_THIRD_QUARTER_X = (GAME_WIDTH / 4) * 3;
const int SCREEN_CENTER_Y = GAME_HEIGHT / 2;
const int SCREEN_FIRST_QUARTER_Y = GAME_HEIGHT / 4;
const int SCREEN_THIRD_QUARTER_Y = (GAME_HEIGHT / 4) * 3;
const int GAMECANVAS_CENTER_X = GAMECANVAS_WIDTH / 2;
const int GAMECANVAS_FIRST_QUARTER_X = GAMECANVAS_WIDTH / 4;
const int GAMECANVAS_THIRD_QUARTER_X = (GAMECANVAS_WIDTH / 4) * 3;
const int GAMECANVAS_CENTER_Y = GAMECANVAS_HEIGHT / 2;
const int GAMECANVAS_FIRST_QUARTER_Y = GAMECANVAS_HEIGHT / 4;
const int GAMECANVAS_THIRD_QUARTER_Y = (GAMECANVAS_HEIGHT / 4) * 3;
// Secciones del programa
#define PROG_SECTION_LOGO 0

View File

@@ -5,25 +5,38 @@
#include <iostream>
#include <fstream>
#include <string>
#include <sys/stat.h>
#include <unistd.h>
#ifndef _WIN32
#include <pwd.h>
#endif
// Constructor
Director::Director(std::string path)
Director::Director(int argc, char *argv[])
{
// Inicializa variables
section.name = PROG_SECTION_LOGO;
// Crea el objeto que controla los ficheros de recursos
asset = new Asset(path);
// Establece la lista de ficheros
if (!setFileList())
{ // Si falta algún fichero no inicia el programa
section.name = PROG_SECTION_QUIT;
}
// Inicializa las opciones del programa
initOptions();
// Comprueba los parametros del programa
checkProgramArguments(argc, argv);
// Crea la carpeta del sistema donde guardar datos
createSystemFolder();
// Crea el objeto que controla los ficheros de recursos
asset = new Asset(executablePath);
asset->setVerbose(options->console);
// Si falta algún fichero no inicia el programa
if (!setFileList())
{
exit(EXIT_FAILURE);
}
// Carga el fichero de configuración
loadConfigFile();
@@ -37,10 +50,10 @@ Director::Director(std::string path)
lang = new Lang(asset);
lang->setLang(options->language);
input = new Input(asset->get("controllerdb.txt"));
input = new Input(asset->get("gamecontrollerdb.txt"));
initInput();
screen = new Screen(window, renderer, asset, options, GAME_WIDTH, GAME_HEIGHT);
screen = new Screen(window, renderer, asset, options);
// Inicializa los servicios online
initOnline();
@@ -65,31 +78,49 @@ Director::~Director()
// Inicializa el objeto input
void Director::initInput()
{
// Teclado
input->bindKey(INPUT_UP, SDL_SCANCODE_UP);
input->bindKey(INPUT_DOWN, SDL_SCANCODE_DOWN);
input->bindKey(INPUT_LEFT, SDL_SCANCODE_LEFT);
input->bindKey(INPUT_RIGHT, SDL_SCANCODE_RIGHT);
input->bindKey(INPUT_ACCEPT, SDL_SCANCODE_RETURN);
input->bindKey(INPUT_CANCEL, SDL_SCANCODE_ESCAPE);
input->bindKey(INPUT_BUTTON_1, SDL_SCANCODE_Q);
input->bindKey(INPUT_BUTTON_2, SDL_SCANCODE_W);
input->bindKey(INPUT_BUTTON_3, SDL_SCANCODE_E);
input->bindKey(INPUT_BUTTON_PAUSE, SDL_SCANCODE_ESCAPE); // PAUSE
input->bindKey(INPUT_BUTTON_ESCAPE, SDL_SCANCODE_ESCAPE); // ESCAPE
// Establece si ha de mostrar mensajes
input->setVerbose(options->console);
// Mando
input->bindGameControllerButton(INPUT_UP, SDL_CONTROLLER_BUTTON_DPAD_UP);
input->bindGameControllerButton(INPUT_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
input->bindGameControllerButton(INPUT_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
input->bindGameControllerButton(INPUT_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
input->bindGameControllerButton(INPUT_ACCEPT, SDL_CONTROLLER_BUTTON_B);
input->bindGameControllerButton(INPUT_CANCEL, SDL_CONTROLLER_BUTTON_A);
input->bindGameControllerButton(INPUT_BUTTON_1, SDL_CONTROLLER_BUTTON_X);
input->bindGameControllerButton(INPUT_BUTTON_2, SDL_CONTROLLER_BUTTON_Y);
input->bindGameControllerButton(INPUT_BUTTON_3, SDL_CONTROLLER_BUTTON_B);
input->bindGameControllerButton(INPUT_BUTTON_PAUSE, SDL_CONTROLLER_BUTTON_GUIDE); // PAUSE
input->bindGameControllerButton(INPUT_BUTTON_ESCAPE, SDL_CONTROLLER_BUTTON_GUIDE); // ESCAPE
// Busca si hay un mando conectado
input->discoverGameController();
// Teclado - Movimiento del jugador
input->bindKey(input_up, SDL_SCANCODE_UP);
input->bindKey(input_down, SDL_SCANCODE_DOWN);
input->bindKey(input_left, SDL_SCANCODE_LEFT);
input->bindKey(input_right, SDL_SCANCODE_RIGHT);
input->bindKey(input_fire_left, SDL_SCANCODE_Q);
input->bindKey(input_fire_center, SDL_SCANCODE_W);
input->bindKey(input_fire_right, SDL_SCANCODE_E);
// Teclado - Otros
input->bindKey(input_accept, SDL_SCANCODE_RETURN);
input->bindKey(input_cancel, SDL_SCANCODE_ESCAPE);
input->bindKey(input_pause, SDL_SCANCODE_ESCAPE);
input->bindKey(input_exit, SDL_SCANCODE_ESCAPE);
input->bindKey(input_window_dec_size, SDL_SCANCODE_F1);
input->bindKey(input_window_inc_size, SDL_SCANCODE_F2);
input->bindKey(input_window_fullscreen, SDL_SCANCODE_F3);
// Mando - Movimiento del jugador
input->bindGameControllerButton(input_up, SDL_CONTROLLER_BUTTON_DPAD_UP);
input->bindGameControllerButton(input_down, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
input->bindGameControllerButton(input_left, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
input->bindGameControllerButton(input_right, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
input->bindGameControllerButton(input_fire_left, SDL_CONTROLLER_BUTTON_X);
input->bindGameControllerButton(input_fire_center, SDL_CONTROLLER_BUTTON_Y);
input->bindGameControllerButton(input_fire_right, SDL_CONTROLLER_BUTTON_B);
// Mando - Otros
input->bindGameControllerButton(input_accept, SDL_CONTROLLER_BUTTON_B);
input->bindGameControllerButton(input_cancel, SDL_CONTROLLER_BUTTON_A);
#ifdef GAME_CONSOLE
input->bindGameControllerButton(input_pause, SDL_CONTROLLER_BUTTON_BACK);
input->bindGameControllerButton(input_exit, SDL_CONTROLLER_BUTTON_START);
#else
input->bindGameControllerButton(input_pause, SDL_CONTROLLER_BUTTON_START);
input->bindGameControllerButton(input_exit, SDL_CONTROLLER_BUTTON_BACK);
#endif
}
// Inicializa JailAudio
@@ -108,7 +139,10 @@ bool Director::initSDL()
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
// if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO) < 0)
{
printf("SDL could not initialize!\nSDL Error: %s\n", SDL_GetError());
if (options->console)
{
std::cout << "SDL could not initialize!\nSDL Error: " << SDL_GetError() << std::endl;
}
success = false;
}
else
@@ -119,14 +153,27 @@ bool Director::initSDL()
// Establece el filtro de la textura
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(options->filter).c_str()))
{
printf("Warning: Nearest texture filtering not enabled!\n");
if (options->console)
{
std::cout << "Warning: Nearest texture filtering not enabled!\n";
}
}
// Crea la ventana
window = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, options->screenWidth * options->windowSize, options->screenHeight * options->windowSize, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
int incW = 0;
int incH = 0;
if (options->borderEnabled)
{
incW = options->borderWidth * 2;
incH = options->borderHeight * 2;
}
window = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (options->gameWidth + incW) * options->windowSize, (options->gameHeight + incH) * options->windowSize, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
if (window == nullptr)
{
printf("Window could not be created!\nSDL Error: %s\n", SDL_GetError());
if (options->console)
{
std::cout << "Window could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
success = false;
}
else
@@ -143,7 +190,10 @@ bool Director::initSDL()
if (renderer == nullptr)
{
printf("Renderer could not be created!\nSDL Error: %s\n", SDL_GetError());
if (options->console)
{
std::cout << "Renderer could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
success = false;
}
else
@@ -152,7 +202,7 @@ bool Director::initSDL()
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
// Establece el tamaño del buffer de renderizado
SDL_RenderSetLogicalSize(renderer, options->screenWidth, options->screenHeight);
SDL_RenderSetLogicalSize(renderer, options->gameWidth, options->gameHeight);
// Establece el modo de mezcla
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
@@ -160,7 +210,10 @@ bool Director::initSDL()
}
}
printf("\n");
if (options->console)
{
std::cout << std::endl;
}
return success;
}
@@ -174,11 +227,9 @@ bool Director::setFileList()
#endif
// Ficheros de configuración
asset->add(prefix + "/data/config/score.bin", t_data, false);
asset->add(systemFolder + "/config.txt", t_data, false, true);
asset->add(systemFolder + "/score.bin", t_data, false, true);
asset->add(prefix + "/data/config/demo.bin", t_data);
asset->add(prefix + "/data/config/config.bin", t_data, false);
asset->add(prefix + "/data/config/config.txt", t_data, false);
asset->add(prefix + "/data/config/jailer_id.txt", t_data, false);
asset->add(prefix + "/data/config/gamecontrollerdb.txt", t_data);
// Musicas
@@ -204,6 +255,7 @@ bool Director::setFileList()
asset->add(prefix + "/data/sound/title.wav", t_sound);
asset->add(prefix + "/data/sound/clock.wav", t_sound);
asset->add(prefix + "/data/sound/powerball.wav", t_sound);
asset->add(prefix + "/data/sound/notify.wav", t_sound);
// Texturas
asset->add(prefix + "/data/gfx/balloon1.png", t_bitmap);
@@ -314,29 +366,105 @@ void Director::initOptions()
inp.deviceType = INPUT_USE_GAMECONTROLLER;
options->input.push_back(inp);
options->fullScreenMode = 0;
// Video
options->gameWidth = GAMECANVAS_WIDTH;
options->gameHeight = GAMECANVAS_HEIGHT;
options->videoMode = 0;
options->windowSize = 3;
options->language = ba_BA;
options->difficulty = DIFFICULTY_NORMAL;
options->playerSelected = 0;
options->filter = FILTER_NEAREST;
options->vSync = true;
options->screenWidth = GAME_WIDTH;
options->screenHeight = GAME_HEIGHT;
options->integerScale = true;
options->keepAspect = true;
options->borderSize = 0.0f;
options->borderWidth = 0;
options->borderHeight = 0;
options->borderEnabled = false;
// Varios
options->playerSelected = 0;
options->difficulty = DIFFICULTY_NORMAL;
options->language = ba_BA;
options->console = false;
// Online
options->online.enabled = false;
options->online.server = "";
options->online.port = 0;
options->online.server = "jaildoctor.duckdns.org";
options->online.port = 9911;
options->online.gameID = "coffee_crisis";
options->online.jailerID = "";
options->online.score = 0;
}
// Comprueba los parametros del programa
void Director::checkProgramArguments(int argc, char *argv[])
{
// Establece la ruta del programa
executablePath = argv[0];
// Comprueba el resto de parametros
for (int i = 1; i < argc; ++i)
{
if (strcmp(argv[i], "--console") == 0)
{
options->console = true;
}
}
}
// Crea la carpeta del sistema donde guardar datos
void Director::createSystemFolder()
{
#ifdef DEBUG
const std::string folderName = "coffee_crisis_debug";
#else
const std::string folderName = "coffee_crisis";
#endif
#ifdef _WIN32
systemFolder = std::string(getenv("APPDATA")) + "/" + folderName;
#elif __APPLE__
struct passwd *pw = getpwuid(getuid());
const char *homedir = pw->pw_dir;
systemFolder = std::string(homedir) + "/Library/Application Support/" + folderName;
#elif __linux__
struct passwd *pw = getpwuid(getuid());
const char *homedir = pw->pw_dir;
systemFolder = std::string(homedir) + "/." + folderName;
#endif
struct stat st = {0};
if (stat(systemFolder.c_str(), &st) == -1)
{
errno = 0;
#ifdef _WIN32
int ret = mkdir(systemFolder.c_str());
#else
int ret = mkdir(systemFolder.c_str(), S_IRWXU);
#endif
if (ret == -1)
{
switch (errno)
{
case EACCES:
printf("the parent directory does not allow write");
exit(EXIT_FAILURE);
case EEXIST:
printf("pathname already exists");
exit(EXIT_FAILURE);
case ENAMETOOLONG:
printf("pathname is too long");
exit(EXIT_FAILURE);
default:
perror("mkdir");
exit(EXIT_FAILURE);
}
}
}
}
// Carga el fichero de configuración
bool Director::loadConfigFile()
{
@@ -344,14 +472,18 @@ bool Director::loadConfigFile()
bool success = true;
// Variables para manejar el fichero
const std::string filePath = "config.txt";
std::string line;
std::ifstream file(asset->get("config.txt"));
std::ifstream file(asset->get(filePath));
// Si el fichero se puede abrir
if (file.good())
{
// Procesa el fichero linea a linea
std::cout << "Reading file config.txt\n";
if (options->console)
{
std::cout << "Reading file " << filePath << std::endl;
}
while (std::getline(file, line))
{
// Comprueba que la linea no sea un comentario
@@ -362,15 +494,21 @@ bool Director::loadConfigFile()
// Procesa las dos subcadenas
if (!setOptions(options, line.substr(0, pos), line.substr(pos + 1, line.length())))
{
std::cout << "Warning: file config.txt\n";
std::cout << "unknown parameter " << line.substr(0, pos).c_str() << std::endl;
if (options->console)
{
std::cout << "Warning: file " << filePath << std::endl;
std::cout << "Unknown parameter " << line.substr(0, pos).c_str() << std::endl;
}
success = false;
}
}
}
// Cierra el fichero
std::cout << "Closing file config.txt\n\n";
if (options->console)
{
std::cout << "Closing file " << filePath << std::endl;
}
file.close();
}
@@ -381,12 +519,12 @@ bool Director::loadConfigFile()
}
// Normaliza los valores
const bool a = options->fullScreenMode == 0;
const bool b = options->fullScreenMode == SDL_WINDOW_FULLSCREEN;
const bool c = options->fullScreenMode == SDL_WINDOW_FULLSCREEN_DESKTOP;
const bool a = options->videoMode == 0;
const bool b = options->videoMode == SDL_WINDOW_FULLSCREEN;
const bool c = options->videoMode == SDL_WINDOW_FULLSCREEN_DESKTOP;
if (!(a || b || c))
{
options->fullScreenMode = 0;
options->videoMode = 0;
}
if (options->windowSize < 1 || options->windowSize > 4)
@@ -412,17 +550,17 @@ bool Director::saveConfigFile()
// Escribe en el fichero
file << "## VISUAL OPTIONS\n";
if (options->fullScreenMode == 0)
if (options->videoMode == 0)
{
file << "fullScreenMode=0\n";
file << "videoMode=0\n";
}
else if (options->fullScreenMode == SDL_WINDOW_FULLSCREEN)
else if (options->videoMode == SDL_WINDOW_FULLSCREEN)
{
file << "fullScreenMode=SDL_WINDOW_FULLSCREEN\n";
}
else if (options->fullScreenMode == SDL_WINDOW_FULLSCREEN_DESKTOP)
else if (options->videoMode == SDL_WINDOW_FULLSCREEN_DESKTOP)
{
file << "fullScreenMode=SDL_WINDOW_FULLSCREEN_DESKTOP\n";
}
@@ -442,15 +580,14 @@ bool Director::saveConfigFile()
file << "integerScale=" + boolToString(options->integerScale) + "\n";
file << "keepAspect=" + boolToString(options->keepAspect) + "\n";
file << "borderEnabled=" + boolToString(options->borderEnabled) + "\n";
file << "borderSize=" + std::to_string(options->borderSize) + "\n";
file << "screenWidth=" + std::to_string(options->screenWidth) + "\n";
file << "screenHeight=" + std::to_string(options->screenHeight) + "\n";
file << "borderWidth=" + std::to_string(options->borderWidth) + "\n";
file << "borderHeight=" + std::to_string(options->borderHeight) + "\n";
file << "\n## OTHER OPTIONS\n";
file << "language=" + std::to_string(options->language) + "\n";
file << "difficulty=" + std::to_string(options->difficulty) + "\n";
file << "input0=" + std::to_string(options->input.at(0).deviceType) + "\n";
file << "input1=" + std::to_string(options->input.at(1).deviceType) + "\n";
file << "input0=" + std::to_string(options->input[0].deviceType) + "\n";
file << "input1=" + std::to_string(options->input[1].deviceType) + "\n";
file << "\n## ONLINE OPTIONS\n";
file << "enabled=" + boolToString(options->online.enabled) + "\n";
@@ -472,14 +609,14 @@ void Director::setSection(section_t section)
void Director::runLogo()
{
logo = new Logo(renderer, screen, asset);
logo = new Logo(renderer, screen, asset, input);
setSection(logo->run());
delete logo;
}
void Director::runIntro()
{
intro = new Intro(renderer, screen, asset, lang);
intro = new Intro(renderer, screen, asset, input, lang);
setSection(intro->run());
delete intro;
}
@@ -528,18 +665,49 @@ void Director::run()
// Inicializa los servicios online
void Director::initOnline()
{
if (options->online.sessionEnabled)
{ // Si ya ha iniciado la sesión, que no continue
return;
}
if (options->online.jailerID == "")
{ // Jailer ID no definido
options->online.enabled = false;
}
else
{ // Jailer ID iniciado
options->online.enabled = options->online.sessionEnabled = true;
jscore::init(options->online.server, options->online.port);
#ifdef DEBUG
const std::string caption = options->online.jailerID + " IS LOGGED IN (DEBUG)";
#else
const std::string caption = options->online.jailerID + " IS LOGGED IN";
#endif
screen->showNotification(caption);
if (options->console)
{
std::cout << caption << std::endl;
}
}
// OLD
if (!options->online.enabled)
{
//screen->showText("Modo Offline");
//std::cout << "Modo Offline" << std::endl;
return;
}
// Obten el Jailer ID
if (options->online.jailerID == "")
{ // Jailer ID no definido
screen->showText("No ha especificado ningun Jailer ID");
std::cout << "No ha especificado ningun Jailer ID" << std::endl;
screen->showNotification("No ha especificado ningun Jailer ID");
if (options->console)
{
std::cout << "No ha especificado ningun Jailer ID" << std::endl;
}
}
else
{ // Jailer ID iniciado
@@ -550,21 +718,34 @@ void Director::initOnline()
// Obtiene la información online
if (jscore::initOnlineScore(options->online.gameID))
{
screen->showText(options->online.jailerID + " ha iniciado sesion");
std::cout << options->online.jailerID << " ha iniciado sesion" << std::endl;
screen->showNotification(options->online.jailerID + " ha iniciado sesion");
if (options->console)
{
std::cout << options->online.jailerID << " ha iniciado sesion" << std::endl;
}
}
else
{
screen->showText("Fallo al conectar a " + options->online.server);
std::cout << "Fallo al conectar a " << options->online.server << std::endl;
screen->showNotification("Fallo al conectar a " + options->online.server);
if (options->console)
{
std::cout << "Fallo al conectar a " << options->online.server << std::endl;
}
options->online.enabled = false;
return;
}
// Obten la puntuación online
const int points = jscore::getUserPoints(options->online.gameID, options->online.jailerID);
if (points == 0)
{ // Fallo de conexión o no hay registros
screen->showText("No se ha podido obtener la puntuacion online");
std::cout << "No se ha podido obtener la puntuacion online" << std::endl;
screen->showNotification("No se ha podido obtener la puntuacion online");
if (options->console)
{
std::cout << "No se ha podido obtener la puntuacion online" << std::endl;
}
}
else
{
@@ -579,19 +760,19 @@ bool Director::setOptions(options_t *options, std::string var, std::string value
// Indicador de éxito en la asignación
bool success = true;
if (var == "fullScreenMode")
if (var == "videoMode")
{
if (value == "SDL_WINDOW_FULLSCREEN_DESKTOP")
{
options->fullScreenMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
options->videoMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
}
else if (value == "SDL_WINDOW_FULLSCREEN")
{
options->fullScreenMode = SDL_WINDOW_FULLSCREEN;
options->videoMode = SDL_WINDOW_FULLSCREEN;
}
else
{
options->fullScreenMode = 0;
options->videoMode = 0;
}
}
@@ -636,23 +817,14 @@ bool Director::setOptions(options_t *options, std::string var, std::string value
options->borderEnabled = stringToBool(value);
}
else if (var == "borderSize")
else if (var == "borderWidth")
{
options->borderSize = std::stof(value);
if (options->borderSize < 0.0f || options->borderSize > 0.5f)
{
options->borderSize = 0.1f;
}
options->borderWidth = std::stoi(value);
}
else if (var == "screenWidth")
else if (var == "borderHeight")
{
options->screenWidth = std::stoi(value);
}
else if (var == "screenHeight")
{
options->screenHeight = std::stoi(value);
options->borderHeight = std::stoi(value);
}
else if (var == "language")
@@ -667,12 +839,12 @@ bool Director::setOptions(options_t *options, std::string var, std::string value
else if (var == "input0")
{
options->input.at(0).deviceType = std::stoi(value);
options->input[0].deviceType = std::stoi(value);
}
else if (var == "input1")
{
options->input.at(1).deviceType = std::stoi(value);
options->input[1].deviceType = std::stoi(value);
}
else if (var == "enabled")

View File

@@ -45,8 +45,10 @@ private:
Asset *asset; // Objeto que gestiona todos los ficheros de recursos
// Variables
struct options_t *options; // Variable con todas las opciones del programa
section_t section; // Sección y subsección actual del programa;
struct options_t *options; // Variable con todas las opciones del programa
section_t section; // Sección y subsección actual del programa;
std::string executablePath; // Path del ejecutable
std::string systemFolder; // Carpeta del sistema donde guardar datos
// Inicializa jail_audio
void initJailAudio();
@@ -75,6 +77,12 @@ private:
// Guarda el fichero de configuración
bool saveConfigFile();
// Comprueba los parametros del programa
void checkProgramArguments(int argc, char *argv[]);
// Crea la carpeta del sistema donde guardar datos
void createSystemFolder();
// Establece el valor de la variable
void setSection(section_t section);
@@ -92,7 +100,7 @@ private:
public:
// Constructor
Director(std::string path);
Director(int argc, char *argv[]);
// Destructor
~Director();

View File

@@ -1,14 +1,17 @@
#include "fade.h"
#include "const.h"
#include <iostream>
// Constructor
Fade::Fade(SDL_Renderer *renderer)
{
mRenderer = renderer;
mBackbuffer = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAME_WIDTH, GAME_HEIGHT);
mBackbuffer = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT);
if (mBackbuffer == nullptr)
printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError());
{
std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
// Destructor
@@ -38,7 +41,7 @@ void Fade::render()
switch (mFadeType)
{
case FADE_FULLSCREEN:
mRect1 = {0, 0, GAME_WIDTH, GAME_HEIGHT};
mRect1 = {0, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT};
for (int i = 0; i < 256; i += 4)
{
@@ -66,21 +69,21 @@ void Fade::render()
break;
case FADE_CENTER:
mRect1 = {0, 0, GAME_WIDTH, 0};
mRect2 = {0, 0, GAME_WIDTH, 0};
mRect1 = {0, 0, GAMECANVAS_WIDTH, 0};
mRect2 = {0, 0, GAMECANVAS_WIDTH, 0};
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 64);
for (int i = 0; i < mCounter; i++)
{
mRect1.h = mRect2.h = i * 4;
mRect2.y = GAME_HEIGHT - (i * 4);
mRect2.y = GAMECANVAS_HEIGHT - (i * 4);
SDL_RenderFillRect(mRenderer, &mRect1);
SDL_RenderFillRect(mRenderer, &mRect2);
}
if ((mCounter * 4) > GAME_HEIGHT)
if ((mCounter * 4) > GAMECANVAS_HEIGHT)
mFinished = true;
break;
@@ -98,8 +101,8 @@ void Fade::render()
// Dibujamos sobre el backbuffer
SDL_SetRenderTarget(mRenderer, mBackbuffer);
mRect1.x = rand() % (GAME_WIDTH - mRect1.w);
mRect1.y = rand() % (GAME_HEIGHT - mRect1.h);
mRect1.x = rand() % (GAMECANVAS_WIDTH - mRect1.w);
mRect1.y = rand() % (GAMECANVAS_HEIGHT - mRect1.h);
SDL_RenderFillRect(mRenderer, &mRect1);
// Volvemos a usar el renderizador de forma normal

View File

@@ -42,7 +42,7 @@ Game::Game(int numPlayers, int currentStage, SDL_Renderer *renderer, Screen *scr
buildingsSprite = new Sprite(0, 0, 256, 160, gameBuildingsTexture, renderer);
skyColorsSprite = new Sprite(0, 0, GAME_WIDTH, GAME_HEIGHT, gameSkyColorsTexture, renderer);
skyColorsSprite = new Sprite(0, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT, gameSkyColorsTexture, renderer);
grassSprite = new Sprite(0, 0, 256, 6, gameGrassTexture, renderer);
powerMeterSprite = new Sprite(PLAY_AREA_CENTER_X - 20, 170, 40, 7, gamePowerMeterTexture, renderer);
gameOverSprite = new Sprite(16, 80, 128, 96, gameOverTexture, renderer);
@@ -201,14 +201,14 @@ void Game::init()
// Crea los jugadores
if (numPlayers == 1)
{
Player *player = new Player(PLAY_AREA_CENTER_X - 11, PLAY_AREA_BOTTOM - 24, renderer, playerTextures.at(options->playerSelected), playerAnimations);
Player *player = new Player(PLAY_AREA_CENTER_X - 11, PLAY_AREA_BOTTOM - 24, renderer, playerTextures[options->playerSelected], playerAnimations);
players.push_back(player);
}
else if (numPlayers == 2)
{
Player *player1 = new Player((PLAY_AREA_CENTER_FIRST_QUARTER_X * ((0 * 2) + 1)) - 11, PLAY_AREA_BOTTOM - 24, renderer, playerTextures.at(0), playerAnimations);
Player *player2 = new Player((PLAY_AREA_CENTER_FIRST_QUARTER_X * ((1 * 2) + 1)) - 11, PLAY_AREA_BOTTOM - 24, renderer, playerTextures.at(1), playerAnimations);
Player *player1 = new Player((PLAY_AREA_CENTER_FIRST_QUARTER_X * ((0 * 2) + 1)) - 11, PLAY_AREA_BOTTOM - 24, renderer, playerTextures[0], playerAnimations);
Player *player2 = new Player((PLAY_AREA_CENTER_FIRST_QUARTER_X * ((1 * 2) + 1)) - 11, PLAY_AREA_BOTTOM - 24, renderer, playerTextures[1], playerAnimations);
players.push_back(player1);
players.push_back(player2);
}
@@ -376,17 +376,20 @@ void Game::init()
n5000Sprite->setDestY(0);
// Los fondos
skyColorsRect[0] = {0, 0, GAME_WIDTH, GAME_HEIGHT};
skyColorsRect[1] = {256, 0, GAME_WIDTH, GAME_HEIGHT};
skyColorsRect[2] = {0, 192, GAME_WIDTH, GAME_HEIGHT};
skyColorsRect[3] = {256, 192, GAME_WIDTH, GAME_HEIGHT};
skyColorsRect[0] = {0, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT};
skyColorsRect[1] = {256, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT};
skyColorsRect[2] = {0, 192, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT};
skyColorsRect[3] = {256, 192, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT};
}
// Carga los recursos necesarios para la sección 'Game'
void Game::loadMedia()
{
std::cout << std::endl
<< "** LOADING RESOURCES FOR GAME SECTION" << std::endl;
if (options->console)
{
std::cout << std::endl
<< "** LOADING RESOURCES FOR GAME SECTION" << std::endl;
}
// Carga ficheros
loadScoreFile();
@@ -573,8 +576,11 @@ void Game::loadMedia()
// Musicas
gameMusic = JA_LoadMusic(asset->get("playing.ogg").c_str());
std::cout << "** RESOURCES FOR GAME SECTION LOADED" << std::endl
<< std::endl;
if (options->console)
{
std::cout << "** RESOURCES FOR GAME SECTION LOADED" << std::endl
<< std::endl;
}
}
// Carga el fichero de puntos
@@ -589,13 +595,19 @@ bool Game::loadScoreFile()
// El fichero no existe
if (file == nullptr)
{
printf("Warning: Unable to open %s file\n", filename.c_str());
if (options->console)
{
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
}
// Creamos el fichero para escritura
file = SDL_RWFromFile(p.c_str(), "w+b");
if (file != nullptr)
{
printf("New file (%s) created!\n", filename.c_str());
if (options->console)
{
std::cout << "New file (" << filename.c_str() << ") created!" << std::endl;
}
// Inicializamos los datos
for (int i = 0; i < TOTAL_SCORE_DATA; ++i)
@@ -609,7 +621,10 @@ bool Game::loadScoreFile()
}
else
{
printf("Error: Unable to create file %s\n", filename.c_str());
if (options->console)
{
std::cout << "Error: Unable to create file " << filename.c_str() << std::endl;
}
success = false;
}
}
@@ -617,7 +632,10 @@ bool Game::loadScoreFile()
else
{
// Cargamos los datos
printf("Reading file %s\n", filename.c_str());
if (options->console)
{
std::cout << "Reading file " << filename.c_str() << std::endl;
}
for (int i = 0; i < TOTAL_SCORE_DATA; ++i)
SDL_RWread(file, &scoreDataFile[i], sizeof(Uint32), 1);
@@ -655,13 +673,19 @@ bool Game::loadDemoFile()
// El fichero no existe
if (file == nullptr)
{
printf("Warning: Unable to open %s file\n", filename.c_str());
if (options->console)
{
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
}
// Creamos el fichero para escritura
file = SDL_RWFromFile(p.c_str(), "w+b");
if (file != nullptr)
{
printf("New file (%s) created!\n", filename.c_str());
if (options->console)
{
std::cout << "New file (" << filename.c_str() << ") created!" << std::endl;
}
// Inicializamos los datos
for (int i = 0; i < TOTAL_DEMO_DATA; ++i)
@@ -681,7 +705,10 @@ bool Game::loadDemoFile()
}
else
{
printf("Error: Unable to create file %s\n", filename.c_str());
if (options->console)
{
std::cout << "Error: Unable to create file " << filename.c_str() << std::endl;
}
success = false;
}
}
@@ -689,7 +716,10 @@ bool Game::loadDemoFile()
else
{
// Cargamos los datos
printf("Reading file %s\n", filename.c_str());
if (options->console)
{
std::cout << "Reading file " << filename.c_str() << std::endl;
}
for (int i = 0; i < TOTAL_DEMO_DATA; ++i)
SDL_RWread(file, &demo.dataFile[i], sizeof(demoKeys_t), 1);
@@ -715,14 +745,20 @@ bool Game::saveScoreFile()
SDL_RWwrite(file, &scoreDataFile[i], sizeof(Uint32), 1);
}
printf("Writing file %s\n", filename.c_str());
if (options->console)
{
std::cout << "Writing file " << filename.c_str() << std::endl;
}
// Cerramos el fichero
SDL_RWclose(file);
}
else
{
printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError());
if (options->console)
{
std::cout << "Error: Unable to save " << filename.c_str() << " file! " << SDL_GetError() << std::endl;
}
}
return success;
}
@@ -735,7 +771,7 @@ bool Game::sendOnlineScore()
return true;
}
const int score = players.at(0)->getScore();
const int score = players[0]->getScore();
if (score <= options->online.score)
{
return true;
@@ -744,12 +780,12 @@ bool Game::sendOnlineScore()
if (jscore::updateUserPoints("coffee_crisis", options->online.jailerID, score))
{
options->online.score = score;
screen->showText("PUNTUACION ENVIADA: " + std::to_string(score) + " PUNTOS");
screen->showNotification("PUNTUACION ENVIADA: " + std::to_string(score) + " PUNTOS");
return true;
}
else
{
screen->showText("NO SE HA PODIDO ENVIAR LA PUNTUACION");
screen->showNotification("NO SE HA PODIDO ENVIAR LA PUNTUACION");
return false;
}
}
@@ -771,14 +807,20 @@ bool Game::saveDemoFile()
SDL_RWwrite(file, &demo.dataFile[i], sizeof(demoKeys_t), 1);
}
printf("Writing file %s\n", filename.c_str());
if (options->console)
{
std::cout << "Writing file " << filename.c_str() << std::endl;
}
// Cerramos el fichero
SDL_RWclose(file);
}
else
{
printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError());
if (options->console)
{
std::cout << "Error: Unable to save " << filename.c_str() << " file! " << SDL_GetError() << std::endl;
}
}
}
return success;
@@ -1648,21 +1690,21 @@ void Game::renderScoreBoard()
// PLAYER1 - SCORE
textScoreBoard->writeCentered(offsetLeft, offset1, lang->getText(53));
textScoreBoard->writeCentered(offsetLeft, offset2, updateScoreText(players.at(0)->getScore()));
textScoreBoard->writeCentered(offsetLeft, offset2, updateScoreText(players[0]->getScore()));
// PLAYER1 - MULT
textScoreBoard->writeCentered(offsetLeft, offset3, lang->getText(55));
textScoreBoard->writeCentered(offsetLeft, offset4, std::to_string(players.at(0)->getScoreMultiplier()).substr(0, 3));
textScoreBoard->writeCentered(offsetLeft, offset4, std::to_string(players[0]->getScoreMultiplier()).substr(0, 3));
if (numPlayers == 2)
{
// PLAYER2 - SCORE
textScoreBoard->writeCentered(offsetRight, offset1, lang->getText(54));
textScoreBoard->writeCentered(offsetRight, offset2, updateScoreText(players.at(1)->getScore()));
textScoreBoard->writeCentered(offsetRight, offset2, updateScoreText(players[1]->getScore()));
// PLAYER2 - MULT
textScoreBoard->writeCentered(offsetRight, offset3, lang->getText(55));
textScoreBoard->writeCentered(offsetRight, offset4, std::to_string(players.at(1)->getScoreMultiplier()).substr(0, 3));
textScoreBoard->writeCentered(offsetRight, offset4, std::to_string(players[1]->getScoreMultiplier()).substr(0, 3));
}
else
{
@@ -1806,7 +1848,7 @@ void Game::updateDeath()
{
// Hace sonar aleatoriamente uno de los 4 sonidos de burbujas
const Uint8 index = rand() % 4;
const JA_Sound sound[4] = {bubble1Sound, bubble2Sound, bubble3Sound, bubble4Sound};
JA_Sound_t *sound[4] = {bubble1Sound, bubble2Sound, bubble3Sound, bubble4Sound};
JA_PlaySound(sound[index], 0);
}
}
@@ -1831,7 +1873,7 @@ void Game::renderDeathFade(int counter)
{
rect[i].x = 0;
rect[i].y = i * 16;
rect[i].w = GAME_WIDTH;
rect[i].w = GAMECANVAS_WIDTH;
if (i == 0)
{
rect[i].h = h;
@@ -1845,7 +1887,7 @@ void Game::renderDeathFade(int counter)
}
else
{
SDL_Rect rect = {0, 0, GAME_WIDTH, GAME_HEIGHT};
SDL_Rect rect = {0, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT};
SDL_RenderFillRect(renderer, &rect);
}
}
@@ -1872,7 +1914,7 @@ void Game::renderBalloons()
Uint8 Game::createBalloon(float x, int y, Uint8 kind, float velx, float speed, Uint16 creationtimer)
{
const int index = (kind - 1) % 4;
Balloon *b = new Balloon(x, y, kind, velx, speed, creationtimer, balloonTextures.at(index), balloonAnimations.at(index), renderer);
Balloon *b = new Balloon(x, y, kind, velx, speed, creationtimer, balloonTextures[index], balloonAnimations[index], renderer);
balloons.push_back(b);
return (Uint8)(balloons.size() - 1);
}
@@ -1890,7 +1932,7 @@ void Game::createPowerBall()
const int x[3] = {left, center, right};
const float vx[3] = {BALLOON_VELX_POSITIVE, BALLOON_VELX_POSITIVE, BALLOON_VELX_NEGATIVE};
Balloon *b = new Balloon(x[luck], posY, POWER_BALL, vx[luck], enemySpeed, 100, balloonTextures.at(3), balloonAnimations.at(3), renderer);
Balloon *b = new Balloon(x[luck], posY, POWER_BALL, vx[luck], enemySpeed, 100, balloonTextures[3], balloonAnimations[3], renderer);
balloons.push_back(b);
powerBallEnabled = true;
@@ -2035,25 +2077,25 @@ void Game::popBalloon(Balloon *balloon)
// En cualquier otro caso, crea dos globos de un tipo inferior
default:
const int index = createBalloon(0, balloon->getPosY(), balloon->getKind() - 1, BALLOON_VELX_NEGATIVE, enemySpeed, 0);
balloons.at(index)->allignTo(balloon->getPosX() + (balloon->getWidth() / 2));
if (balloons.at(index)->getClass() == BALLOON_CLASS)
balloons[index]->allignTo(balloon->getPosX() + (balloon->getWidth() / 2));
if (balloons[index]->getClass() == BALLOON_CLASS)
{
balloons.at(index)->setVelY(-2.50f);
balloons[index]->setVelY(-2.50f);
}
else
{
balloons.at(index)->setVelY(BALLOON_VELX_NEGATIVE);
balloons[index]->setVelY(BALLOON_VELX_NEGATIVE);
}
const int index2 = createBalloon(0, balloon->getPosY(), balloon->getKind() - 1, BALLOON_VELX_POSITIVE, enemySpeed, 0);
balloons.at(index2)->allignTo(balloon->getPosX() + (balloon->getWidth() / 2));
if (balloons.at(index2)->getClass() == BALLOON_CLASS)
balloons[index2]->allignTo(balloon->getPosX() + (balloon->getWidth() / 2));
if (balloons[index2]->getClass() == BALLOON_CLASS)
{
balloons.at(index2)->setVelY(-2.50f);
balloons[index2]->setVelY(-2.50f);
}
else
{
balloons.at(index2)->setVelY(BALLOON_VELX_NEGATIVE);
balloons[index2]->setVelY(BALLOON_VELX_NEGATIVE);
}
// Elimina el globo
@@ -2201,9 +2243,9 @@ void Game::freeBalloons()
{
for (int i = balloons.size() - 1; i >= 0; --i)
{
if (balloons.at(i)->isEnabled() == false)
if (balloons[i]->isEnabled() == false)
{
delete balloons.at(i);
delete balloons[i];
balloons.erase(balloons.begin() + i);
}
}
@@ -2309,8 +2351,8 @@ void Game::checkBulletBalloonCollision()
{
// Otorga los puntos correspondientes al globo al jugador que disparó la bala
int index = bullet->getOwner();
players.at(index)->incScoreMultiplier();
players.at(index)->addScore(Uint32(balloon->getScore() * players.at(index)->getScoreMultiplier() * difficultyScoreMultiplier));
players[index]->incScoreMultiplier();
players[index]->addScore(Uint32(balloon->getScore() * players[index]->getScoreMultiplier() * difficultyScoreMultiplier));
updateHiScore();
// Explota el globo
@@ -2336,7 +2378,7 @@ void Game::checkBulletBalloonCollision()
}
else
{
createItem(droppeditem, players.at(index)->getPosX(), 0);
createItem(droppeditem, players[index]->getPosX(), 0);
coffeeMachineEnabled = true;
}
}
@@ -2357,7 +2399,7 @@ void Game::moveBullets()
{
if (bullet->move() == BULLET_MOVE_OUT)
{
players.at(bullet->getOwner())->decScoreMultiplier();
players[bullet->getOwner()]->decScoreMultiplier();
}
}
}
@@ -2389,9 +2431,9 @@ void Game::freeBullets()
{
for (int i = bullets.size() - 1; i >= 0; --i)
{
if (bullets.at(i)->isEnabled() == false)
if (bullets[i]->isEnabled() == false)
{
delete bullets.at(i);
delete bullets[i];
bullets.erase(bullets.begin() + i);
}
}
@@ -2503,7 +2545,7 @@ Uint8 Game::dropItem()
// Crea un objeto item
void Game::createItem(Uint8 kind, float x, float y)
{
Item *item = new Item(kind, x, y, itemTextures.at(kind), itemAnimations.at(kind), renderer);
Item *item = new Item(kind, x, y, itemTextures[kind], itemAnimations[kind], renderer);
items.push_back(item);
}
@@ -2514,9 +2556,9 @@ void Game::freeItems()
{
for (int i = items.size() - 1; i >= 0; --i)
{
if (items.at(i)->isEnabled() == false)
if (items[i]->isEnabled() == false)
{
delete items.at(i);
delete items[i];
items.erase(items.begin() + i);
}
}
@@ -2546,9 +2588,9 @@ void Game::freeSmartSprites()
{
for (int i = smartSprites.size() - 1; i >= 0; --i)
{
if (smartSprites.at(i)->hasFinished())
if (smartSprites[i]->hasFinished())
{
delete smartSprites.at(i);
delete smartSprites[i];
smartSprites.erase(smartSprites.begin() + i);
}
}
@@ -2588,7 +2630,7 @@ void Game::updateShakeEffect()
// Crea un SmartSprite para arrojar el item café al recibir un impacto
void Game::throwCoffee(int x, int y)
{
SmartSprite *ss = new SmartSprite(itemTextures.at(4), renderer);
SmartSprite *ss = new SmartSprite(itemTextures[4], renderer);
smartSprites.push_back(ss);
ss->setPosX(x - 8);
@@ -2600,7 +2642,7 @@ void Game::throwCoffee(int x, int y)
ss->setAccelX(0.0f);
ss->setAccelY(0.2f);
ss->setDestX(x + (ss->getVelX() * 50));
ss->setDestY(GAME_HEIGHT + 1);
ss->setDestY(GAMECANVAS_HEIGHT + 1);
ss->setEnabled(true);
ss->setEnabledCounter(1);
ss->setSpriteClip(0, 0, 16, 16);
@@ -2919,7 +2961,7 @@ void Game::render()
renderScoreBoard();
renderPlayers();
if ((deathCounter <= 150) && !players.at(0)->isAlive())
if ((deathCounter <= 150) && !players[0]->isAlive())
{
renderDeathFade(150 - deathCounter);
}
@@ -2976,50 +3018,51 @@ void Game::checkGameInput()
const int index = 0;
if (demo.dataFile[demo.counter].left == 1)
{
players.at(index)->setInput(INPUT_LEFT);
players[index]->setInput(input_left);
}
if (demo.dataFile[demo.counter].right == 1)
{
players.at(index)->setInput(INPUT_RIGHT);
players[index]->setInput(input_right);
}
if (demo.dataFile[demo.counter].noInput == 1)
{
players.at(index)->setInput(INPUT_NULL);
players[index]->setInput(input_null);
}
if (demo.dataFile[demo.counter].fire == 1)
{
if (players.at(index)->canFire())
if (players[index]->canFire())
{
players.at(index)->setInput(INPUT_BUTTON_2);
createBullet(players.at(index)->getPosX() + (players.at(index)->getWidth() / 2) - 4, players.at(index)->getPosY() + (players.at(index)->getHeight() / 2), BULLET_UP, players.at(index)->isPowerUp(), index);
players.at(index)->setFireCooldown(10);
players[index]->setInput(input_fire_center);
createBullet(players[index]->getPosX() + (players[index]->getWidth() / 2) - 4, players[index]->getPosY() + (players[index]->getHeight() / 2), BULLET_UP, players[index]->isPowerUp(), index);
players[index]->setFireCooldown(10);
}
}
if (demo.dataFile[demo.counter].fireLeft == 1)
{
if (players.at(index)->canFire())
if (players[index]->canFire())
{
players.at(index)->setInput(INPUT_BUTTON_1);
createBullet(players.at(index)->getPosX() + (players.at(index)->getWidth() / 2) - 4, players.at(index)->getPosY() + (players.at(index)->getHeight() / 2), BULLET_UP, players.at(index)->isPowerUp(), index);
players.at(index)->setFireCooldown(10);
players[index]->setInput(input_fire_left);
createBullet(players[index]->getPosX() + (players[index]->getWidth() / 2) - 4, players[index]->getPosY() + (players[index]->getHeight() / 2), BULLET_UP, players[index]->isPowerUp(), index);
players[index]->setFireCooldown(10);
}
}
if (demo.dataFile[demo.counter].fireRight == 1)
{
if (players.at(index)->canFire())
if (players[index]->canFire())
{
players.at(index)->setInput(INPUT_BUTTON_3);
createBullet(players.at(index)->getPosX() + (players.at(index)->getWidth() / 2) - 4, players.at(index)->getPosY() + (players.at(index)->getHeight() / 2), BULLET_UP, players.at(index)->isPowerUp(), index);
players.at(index)->setFireCooldown(10);
players[index]->setInput(input_fire_right);
createBullet(players[index]->getPosX() + (players[index]->getWidth() / 2) - 4, players[index]->getPosY() + (players[index]->getHeight() / 2), BULLET_UP, players[index]->isPowerUp(), index);
players[index]->setFireCooldown(10);
}
}
// Comprueba el input de pausa
if (input->checkInput(INPUT_BUTTON_PAUSE, REPEAT_FALSE))
if (input->checkInput(input_pause, REPEAT_FALSE))
{
section.name = PROG_SECTION_TITLE;
}
@@ -3043,32 +3086,32 @@ void Game::checkGameInput()
if (player->isAlive())
{
// Input a la izquierda
if (input->checkInput(INPUT_LEFT, REPEAT_TRUE, options->input[i].deviceType, options->input[i].id))
if (input->checkInput(input_left, REPEAT_TRUE, options->input[i].deviceType, options->input[i].id))
{
player->setInput(INPUT_LEFT);
player->setInput(input_left);
demo.keys.left = 1;
}
else
{
// Input a la derecha
if (input->checkInput(INPUT_RIGHT, REPEAT_TRUE, options->input[i].deviceType, options->input[i].id))
if (input->checkInput(input_right, REPEAT_TRUE, options->input[i].deviceType, options->input[i].id))
{
player->setInput(INPUT_RIGHT);
player->setInput(input_right);
demo.keys.right = 1;
}
else
{
// Ninguno de los dos inputs anteriores
player->setInput(INPUT_NULL);
player->setInput(input_null);
demo.keys.noInput = 1;
}
}
// Comprueba el input de disparar al centro
if (input->checkInput(INPUT_BUTTON_2, REPEAT_TRUE, options->input[i].deviceType, options->input[i].id))
if (input->checkInput(input_fire_center, REPEAT_TRUE, options->input[i].deviceType, options->input[i].id))
{
if (player->canFire())
{
player->setInput(INPUT_BUTTON_2);
player->setInput(input_fire_center);
createBullet(player->getPosX() + (player->getWidth() / 2) - 4, player->getPosY() + (player->getHeight() / 2), BULLET_UP, player->isPowerUp(), i);
player->setFireCooldown(10);
@@ -3080,11 +3123,11 @@ void Game::checkGameInput()
}
// Comprueba el input de disparar a la izquierda
if (input->checkInput(INPUT_BUTTON_1, REPEAT_TRUE, options->input[i].deviceType, options->input[i].id))
if (input->checkInput(input_fire_left, REPEAT_TRUE, options->input[i].deviceType, options->input[i].id))
{
if (player->canFire())
{
player->setInput(INPUT_BUTTON_1);
player->setInput(input_fire_left);
createBullet(player->getPosX() + (player->getWidth() / 2) - 4, player->getPosY() + (player->getHeight() / 2), BULLET_LEFT, player->isPowerUp(), i);
player->setFireCooldown(10);
@@ -3096,11 +3139,11 @@ void Game::checkGameInput()
}
// Comprueba el input de disparar a la derecha
if (input->checkInput(INPUT_BUTTON_3, REPEAT_TRUE, options->input[i].deviceType, options->input[i].id))
if (input->checkInput(input_fire_right, REPEAT_TRUE, options->input[i].deviceType, options->input[i].id))
{
if (player->canFire())
{
player->setInput(INPUT_BUTTON_3);
player->setInput(input_fire_right);
createBullet(player->getPosX() + (player->getWidth() / 2) - 4, player->getPosY() + (player->getHeight() / 2), BULLET_RIGHT, player->isPowerUp(), i);
player->setFireCooldown(10);
@@ -3112,7 +3155,7 @@ void Game::checkGameInput()
}
// Comprueba el input de pausa
if (input->checkInput(INPUT_CANCEL, REPEAT_FALSE, options->input[i].deviceType, options->input[i].id))
if (input->checkInput(input_cancel, REPEAT_FALSE, options->input[i].deviceType, options->input[i].id))
{
section.subsection = GAME_SECTION_PAUSE;
}
@@ -3296,7 +3339,7 @@ section_t Game::run()
// Reproduce la música
if (!gameCompleted)
{
if (players.at(0)->isAlive())
if (players[0]->isAlive())
{
JA_PlayMusic(gameMusic);
}
@@ -3408,7 +3451,7 @@ void Game::renderPausedGame()
renderScoreBoard();
renderPlayers();
if ((deathCounter <= 150) && !players.at(0)->isAlive())
if ((deathCounter <= 150) && !players[0]->isAlive())
{
renderDeathFade(150 - deathCounter);
}
@@ -3423,7 +3466,7 @@ void Game::renderPausedGame()
if (leavingPauseMenu)
{
textNokiaBig2->writeCentered(SCREEN_CENTER_X, PLAY_AREA_FIRST_QUARTER_Y, std::to_string((pauseCounter / 30) + 1));
textNokiaBig2->writeCentered(GAMECANVAS_CENTER_X, PLAY_AREA_FIRST_QUARTER_Y, std::to_string((pauseCounter / 30) + 1));
}
else
{
@@ -3578,7 +3621,7 @@ void Game::renderGameOverScreen()
textBig->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 6), lang->getText(43));
// Your Score
text->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 3), lang->getText(44) + std::to_string(players.at(0)->getScore()));
text->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 3), lang->getText(44) + std::to_string(players[0]->getScore()));
}
else
{
@@ -3592,10 +3635,10 @@ void Game::renderGameOverScreen()
textBig->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 7), lang->getText(43));
// Player1 Score
text->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 4), lang->getText(77) + std::to_string(players.at(0)->getScore()));
text->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 4), lang->getText(77) + std::to_string(players[0]->getScore()));
// Player2 Score
text->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 2), lang->getText(78) + std::to_string(players.at(1)->getScore()));
text->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 2), lang->getText(78) + std::to_string(players[1]->getScore()));
}
// Continue?
@@ -3851,7 +3894,10 @@ void Game::loadAnimations(std::string filePath, std::vector<std::string> *buffer
if (file)
{
std::cout << "Animation loaded: " << filePath.substr(filePath.find_last_of("\\/") + 1).c_str() << std::endl;
if (options->console)
{
std::cout << "Animation loaded: " << filePath.substr(filePath.find_last_of("\\/") + 1).c_str() << std::endl;
}
while (std::getline(file, line))
{
buffer->push_back(line);

View File

@@ -174,23 +174,23 @@ private:
Sprite *gameOverSprite; // Sprite para dibujar los graficos del game over
Sprite *gameOverEndSprite; // Sprite para dibujar los graficos del game over de acabar el juego
JA_Sound balloonSound; // Sonido para la explosión del globo
JA_Sound bulletSound; // Sonido para los disparos
JA_Sound playerCollisionSound; // Sonido para la colisión del jugador con un enemigo
JA_Sound hiScoreSound; // Sonido para cuando se alcanza la máxima puntuación
JA_Sound itemDropSound; // Sonido para cuando se genera un item
JA_Sound itemPickUpSound; // Sonido para cuando se recoge un item
JA_Sound coffeeOutSound; // Sonido para cuando el jugador pierde el café al recibir un impacto
JA_Sound stageChangeSound; // Sonido para cuando se cambia de fase
JA_Sound bubble1Sound; // Sonido para cuando el jugador muere
JA_Sound bubble2Sound; // Sonido para cuando el jugador muere
JA_Sound bubble3Sound; // Sonido para cuando el jugador muere
JA_Sound bubble4Sound; // Sonido para cuando el jugador muere
JA_Sound clockSound; // Sonido para cuando se detiene el tiempo con el item reloj
JA_Sound powerBallSound; // Sonido para cuando se explota una Power Ball
JA_Sound coffeeMachineSound; // Sonido para cuando la máquina de café toca el suelo
JA_Sound_t* balloonSound; // Sonido para la explosión del globo
JA_Sound_t* bulletSound; // Sonido para los disparos
JA_Sound_t* playerCollisionSound; // Sonido para la colisión del jugador con un enemigo
JA_Sound_t* hiScoreSound; // Sonido para cuando se alcanza la máxima puntuación
JA_Sound_t* itemDropSound; // Sonido para cuando se genera un item
JA_Sound_t* itemPickUpSound; // Sonido para cuando se recoge un item
JA_Sound_t* coffeeOutSound; // Sonido para cuando el jugador pierde el café al recibir un impacto
JA_Sound_t* stageChangeSound; // Sonido para cuando se cambia de fase
JA_Sound_t* bubble1Sound; // Sonido para cuando el jugador muere
JA_Sound_t* bubble2Sound; // Sonido para cuando el jugador muere
JA_Sound_t* bubble3Sound; // Sonido para cuando el jugador muere
JA_Sound_t* bubble4Sound; // Sonido para cuando el jugador muere
JA_Sound_t* clockSound; // Sonido para cuando se detiene el tiempo con el item reloj
JA_Sound_t* powerBallSound; // Sonido para cuando se explota una Power Ball
JA_Sound_t* coffeeMachineSound; // Sonido para cuando la máquina de café toca el suelo
JA_Music gameMusic; // Musica de fondo
JA_Music_t* gameMusic; // Musica de fondo
// Variables
int numPlayers; // Numero de jugadores

254
source/hiscore_table.cpp Normal file
View File

@@ -0,0 +1,254 @@
#include "hiscore_table.h"
#include "common/jscore.h"
#include <iostream>
const Uint8 SELF = 0;
// Constructor
HiScoreTable::HiScoreTable(SDL_Renderer *renderer, Screen *screen, Asset *asset, Lang *lang, options_t *options)
{
// Copia los punteros
this->renderer = renderer;
this->screen = screen;
this->asset = asset;
this->lang = lang;
// Reserva memoria para los punteros
eventHandler = new SDL_Event();
text = new Text(asset->get("smb2.png"), asset->get("smb2.txt"), renderer);
// Crea un backbuffer para el renderizador
backbuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT);
if (backbuffer == nullptr)
{
if (options->console)
{
std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
// Inicializa variables
section.name = SELF;
ticks = 0;
ticksSpeed = 15;
manualQuit = false;
counter = 0;
counterEnd = 600;
}
// Destructor
HiScoreTable::~HiScoreTable()
{
delete eventHandler;
delete text;
SDL_DestroyTexture(backbuffer);
}
// Actualiza las variables
void HiScoreTable::update()
{
// Comprueba los eventos
checkEventHandler();
// Actualiza las variables
if (SDL_GetTicks() - ticks > ticksSpeed)
{
// Actualiza el contador de ticks
ticks = SDL_GetTicks();
if (mode == mhst_auto)
{ // Modo automático
counter++;
if (counter == counterEnd)
{
section.name = PROG_SECTION_TITLE;
section.subsection = TITLE_SECTION_1;
}
}
else
{ // Modo manual
++counter %= 60000;
if (manualQuit)
{
section.name = PROG_SECTION_TITLE;
section.subsection = TITLE_SECTION_3;
}
}
}
}
// Pinta en pantalla
void HiScoreTable::render()
{
// Pinta en pantalla
SDL_Rect window = {0, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT};
const color_t orangeColor = {0xFF, 0x7A, 0x00};
// hay 27 letras - 7 de puntos quedan 20 caracteres 20 - nameLenght 0 numDots
const int spaceBetweenHeader = 32;
const int spaceBetweenLines = text->getCharacterSize() * 1.8f;
// Pinta en el backbuffer el texto y los sprites
SDL_SetRenderTarget(renderer, backbuffer);
SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(renderer);
// Escribe el texto: Mejores puntuaciones
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, GAMECANVAS_CENTER_X, 8, lang->getText(42), 1, orangeColor, 1, shdwTxtColor);
// Escribe la lista de jugadores
int numUsers = jscore::getNumUsers();
for (int i = 0; i < numUsers; ++i)
{
const int nameLenght = jscore::getUserName(i).length();
const int numDots = 20 - nameLenght;
std::string dots = "";
for (int j = 0; j < numDots; ++j)
{
dots = dots + ".";
}
const std::string line = jscore::getUserName(i) + dots + scoreToString(jscore::getPoints(i));
text->writeDX(TXT_CENTER | TXT_SHADOW, GAMECANVAS_CENTER_X, (i * spaceBetweenLines) + spaceBetweenHeader, line, 1, orangeColor, 1, shdwTxtColor);
}
// Rellena la lista con otros nombres
if (numUsers < 10)
{
std::vector<std::string> names;
names.insert(names.end(), {"BRY", "USUFONDO", "G.LUCAS", "P.DELGAT", "P.ARRABALERA", "PELECHANO", "SAHUQUILLO"});
for (int i = numUsers; i < 10; ++i)
{
const int nameLenght = names[i - numUsers].length();
const int numDots = 20 - nameLenght;
std::string dots = "";
for (int j = 0; j < numDots; ++j)
{
dots = dots + ".";
}
const std::string line = names[i - numUsers] + dots + "0000000";
text->writeDX(TXT_CENTER | TXT_SHADOW, GAMECANVAS_CENTER_X, (i * spaceBetweenLines) + spaceBetweenHeader, line, 1, orangeColor, 1, shdwTxtColor);
}
}
if ((mode == mhst_manual) && (counter % 50 > 14))
{
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, GAMECANVAS_CENTER_X, GAMECANVAS_HEIGHT - 12, lang->getText(22), 1, orangeColor, 1, shdwTxtColor);
}
// Cambia el destino de renderizado
SDL_SetRenderTarget(renderer, nullptr);
// Prepara para empezar a dibujar en la textura de juego
screen->start();
// Limpia la pantalla
screen->clean(bgColor);
// Establece la ventana del backbuffer
if (mode == mhst_auto)
{
window.y = std::max(8, GAMECANVAS_HEIGHT - counter + 100);
}
else
{
window.y = 0;
}
// Copia el backbuffer al renderizador
SDL_RenderCopy(renderer, backbuffer, nullptr, &window);
// Vuelca el contenido del renderizador en pantalla
screen->blit();
}
// Comprueba los eventos
void HiScoreTable::checkEventHandler()
{
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(eventHandler) != 0)
{
// Evento de salida de la aplicación
if (eventHandler->type == SDL_QUIT)
{
section.name = PROG_SECTION_QUIT;
break;
}
if ((eventHandler->type == SDL_KEYUP) || (eventHandler->type == SDL_JOYBUTTONUP))
{
if (mode == mhst_auto)
{
JA_StopMusic();
section.name = PROG_SECTION_TITLE;
section.subsection = TITLE_SECTION_1;
}
else
{
if (counter > 30)
{
manualQuit = true;
}
}
}
}
}
// Bucle para la pantalla de instrucciones
section_t HiScoreTable::run(mode_hiScoreTable_e mode)
{
this->mode = mode;
while (section.name == SELF)
{
update();
render();
}
return section;
}
// Transforma un valor numérico en una cadena de 6 cifras
std::string HiScoreTable::scoreToString(Uint32 num)
{
if ((num >= 0) && (num <= 9))
{
return ("000000" + std::to_string(num));
}
if ((num >= 10) && (num <= 99))
{
return ("00000" + std::to_string(num));
}
if ((num >= 100) && (num <= 999))
{
return ("0000" + std::to_string(num));
}
if ((num >= 1000) && (num <= 9999))
{
return ("000" + std::to_string(num));
}
if ((num >= 010000) && (num <= 99999))
{
return ("00" + std::to_string(num));
}
if ((num >= 100000) && (num <= 999999))
{
return ("0" + std::to_string(num));
}
if ((num >= 1000000) && (num <= 9999999))
{
return (std::to_string(num));
}
return (std::to_string(num));
}

66
source/hiscore_table.h Normal file
View File

@@ -0,0 +1,66 @@
#pragma once
#include <SDL2/SDL.h>
#include "common/asset.h"
#include "common/jail_audio.h"
#include "common/screen.h"
#include "common/sprite.h"
#include "common/text.h"
#include "common/utils.h"
#include "const.h"
#ifndef HISCORE_TABLE_H
#define HISCORE_TABLE_H
enum mode_hiScoreTable_e
{
mhst_manual,
mhst_auto
};
class HiScoreTable
{
private:
// Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana
Screen *screen; // Objeto encargado de dibujar en pantalla
SDL_Event *eventHandler; // Manejador de eventos
SDL_Texture *backbuffer; // Textura para usar como backbuffer
Asset *asset; // Objeto que gestiona todos los ficheros de recursos
Lang *lang; // Objeto para gestionar los textos en diferentes idiomas
Text *text; // Objeto para escribir texto
options_t *options; // Opciones y parametyros del programa
// Variables
Uint16 counter; // Contador
Uint16 counterEnd; // Valor final para el contador
section_t section; // Estado del bucle principal para saber si continua o se sale
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa
bool manualQuit; // Indica si se quiere salir del modo manual
mode_hiScoreTable_e mode; // Modo en el que se van a ejecutar las instrucciones
// Actualiza las variables
void update();
// Pinta en pantalla
void render();
// Comprueba los eventos
void checkEventHandler();
// Transforma un valor numérico en una cadena de 6 cifras
std::string scoreToString(Uint32 num);
public:
// Constructor
HiScoreTable(SDL_Renderer *renderer, Screen *screen, Asset *mAsset, Lang *lang, options_t *options);
// Destructor
~HiScoreTable();
// Bucle principal
section_t run(mode_hiScoreTable_e mode);
};
#endif

View File

@@ -1,4 +1,5 @@
#include "instructions.h"
#include <iostream>
const Uint8 SELF = 0;
@@ -32,14 +33,14 @@ Instructions::Instructions(SDL_Renderer *renderer, Screen *screen, Asset *asset,
eventHandler = new SDL_Event();
sprite = new Sprite(0, 0, 16, 16, itemTextures.at(0), renderer);
sprite = new Sprite(0, 0, 16, 16, itemTextures[0], renderer);
text = new Text(asset->get("smb2.png"), asset->get("smb2.txt"), renderer);
// Crea un backbuffer para el renderizador
backbuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAME_WIDTH, GAME_HEIGHT);
backbuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT);
if (backbuffer == nullptr)
{
printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError());
std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
// Inicializa variables
@@ -107,7 +108,7 @@ void Instructions::update()
void Instructions::render()
{
// Pinta en pantalla
SDL_Rect window = {0, 0, GAME_WIDTH, GAME_HEIGHT};
SDL_Rect window = {0, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT};
SDL_Rect srcRect = {0, 0, 16, 16};
const color_t orangeColor = {0xFF, 0x7A, 0x00};
@@ -124,12 +125,12 @@ void Instructions::render()
SDL_RenderClear(renderer);
// Escribe el texto
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 8, lang->getText(11), 1, orangeColor, 1, shdwTxtColor);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 24, lang->getText(12), 1, noColor, 1, shdwTxtColor);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 34, lang->getText(13), 1, noColor, 1, shdwTxtColor);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 48, lang->getText(14), 1, noColor, 1, shdwTxtColor);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 58, lang->getText(15), 1, noColor, 1, shdwTxtColor);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 75, lang->getText(16), 1, orangeColor, 1, shdwTxtColor);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, GAMECANVAS_CENTER_X, 8, lang->getText(11), 1, orangeColor, 1, shdwTxtColor);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, GAMECANVAS_CENTER_X, 24, lang->getText(12), 1, noColor, 1, shdwTxtColor);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, GAMECANVAS_CENTER_X, 34, lang->getText(13), 1, noColor, 1, shdwTxtColor);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, GAMECANVAS_CENTER_X, 48, lang->getText(14), 1, noColor, 1, shdwTxtColor);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, GAMECANVAS_CENTER_X, 58, lang->getText(15), 1, noColor, 1, shdwTxtColor);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, GAMECANVAS_CENTER_X, 75, lang->getText(16), 1, orangeColor, 1, shdwTxtColor);
text->writeShadowed(84, 92, lang->getText(17), shdwTxtColor);
text->writeShadowed(84, 108, lang->getText(18), shdwTxtColor);
@@ -139,39 +140,39 @@ void Instructions::render()
if ((mode == m_manual) && (counter % 50 > 14))
{
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, GAME_HEIGHT - 12, lang->getText(22), 1, orangeColor, 1, shdwTxtColor);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, GAMECANVAS_CENTER_X, GAMECANVAS_HEIGHT - 12, lang->getText(22), 1, orangeColor, 1, shdwTxtColor);
}
// Disquito
sprite->setTexture(itemTextures.at(0));
sprite->setTexture(itemTextures[0]);
sprite->setPos(destRect1);
srcRect.y = 16 * (((counter + 12) / 36) % 2);
sprite->setSpriteClip(srcRect);
sprite->render();
// Gavineixon
sprite->setTexture(itemTextures.at(1));
sprite->setTexture(itemTextures[1]);
sprite->setPos(destRect2);
srcRect.y = 16 * (((counter + 9) / 36) % 2);
sprite->setSpriteClip(srcRect);
sprite->render();
// Pacmar
sprite->setTexture(itemTextures.at(2));
sprite->setTexture(itemTextures[2]);
sprite->setPos(destRect3);
srcRect.y = 16 * (((counter + 6) / 36) % 2);
sprite->setSpriteClip(srcRect);
sprite->render();
// Time Stopper
sprite->setTexture(itemTextures.at(3));
sprite->setTexture(itemTextures[3]);
sprite->setPos(destRect4);
srcRect.y = 16 * (((counter + 3) / 36) % 2);
sprite->setSpriteClip(srcRect);
sprite->render();
// Coffee
sprite->setTexture(itemTextures.at(4));
sprite->setTexture(itemTextures[4]);
sprite->setPos(destRect5);
srcRect.y = 16 * (((counter + 0) / 36) % 2);
sprite->setSpriteClip(srcRect);
@@ -189,7 +190,7 @@ void Instructions::render()
// Establece la ventana del backbuffer
if (mode == m_auto)
{
window.y = std::max(8, GAME_HEIGHT - counter + 100);
window.y = std::max(8, GAMECANVAS_HEIGHT - counter + 100);
}
else
{

View File

@@ -1,13 +1,14 @@
#include "intro.h"
// Constructor
Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Lang *lang)
Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, Lang *lang)
{
// Copia los punteros
this->renderer = renderer;
this->screen = screen;
this->lang = lang;
this->asset = asset;
this->input = input;
// Reserva memoria para los objetos
eventHandler = new SDL_Event();
@@ -32,59 +33,59 @@ Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Lang *lang)
ss->setWidth(128);
ss->setHeight(96);
ss->setEnabledCounter(20);
ss->setDestX(SCREEN_CENTER_X - 64);
ss->setDestY(SCREEN_FIRST_QUARTER_Y - 24);
ss->setDestX(GAMECANVAS_CENTER_X - 64);
ss->setDestY(GAMECANVAS_FIRST_QUARTER_Y - 24);
bitmaps.push_back(ss);
}
bitmaps.at(0)->setPosX(-128);
bitmaps.at(0)->setPosY(SCREEN_FIRST_QUARTER_Y - 24);
bitmaps.at(0)->setVelX(0.0f);
bitmaps.at(0)->setVelY(0.0f);
bitmaps.at(0)->setAccelX(0.6f);
bitmaps.at(0)->setAccelY(0.0f);
bitmaps.at(0)->setSpriteClip(0, 0, 128, 96);
bitmaps[0]->setPosX(-128);
bitmaps[0]->setPosY(GAMECANVAS_FIRST_QUARTER_Y - 24);
bitmaps[0]->setVelX(0.0f);
bitmaps[0]->setVelY(0.0f);
bitmaps[0]->setAccelX(0.6f);
bitmaps[0]->setAccelY(0.0f);
bitmaps[0]->setSpriteClip(0, 0, 128, 96);
bitmaps.at(1)->setPosX(GAME_WIDTH);
bitmaps.at(1)->setPosY(SCREEN_FIRST_QUARTER_Y - 24);
bitmaps.at(1)->setVelX(-1.0f);
bitmaps.at(1)->setVelY(0.0f);
bitmaps.at(1)->setAccelX(-0.3f);
bitmaps.at(1)->setAccelY(0.0f);
bitmaps.at(1)->setSpriteClip(128, 0, 128, 96);
bitmaps[1]->setPosX(GAMECANVAS_WIDTH);
bitmaps[1]->setPosY(GAMECANVAS_FIRST_QUARTER_Y - 24);
bitmaps[1]->setVelX(-1.0f);
bitmaps[1]->setVelY(0.0f);
bitmaps[1]->setAccelX(-0.3f);
bitmaps[1]->setAccelY(0.0f);
bitmaps[1]->setSpriteClip(128, 0, 128, 96);
bitmaps.at(2)->setPosX(SCREEN_CENTER_X - 64);
bitmaps.at(2)->setPosY(-96);
bitmaps.at(2)->setVelX(0.0f);
bitmaps.at(2)->setVelY(3.0f);
bitmaps.at(2)->setAccelX(0.1f);
bitmaps.at(2)->setAccelY(0.3f);
bitmaps.at(2)->setSpriteClip(0, 96, 128, 96);
bitmaps.at(2)->setEnabledCounter(250);
bitmaps[2]->setPosX(GAMECANVAS_CENTER_X - 64);
bitmaps[2]->setPosY(-96);
bitmaps[2]->setVelX(0.0f);
bitmaps[2]->setVelY(3.0f);
bitmaps[2]->setAccelX(0.1f);
bitmaps[2]->setAccelY(0.3f);
bitmaps[2]->setSpriteClip(0, 96, 128, 96);
bitmaps[2]->setEnabledCounter(250);
bitmaps.at(3)->setPosX(SCREEN_CENTER_X - 64);
bitmaps.at(3)->setPosY(GAME_HEIGHT);
bitmaps.at(3)->setVelX(0.0f);
bitmaps.at(3)->setVelY(-0.7f);
bitmaps.at(3)->setAccelX(0.0f);
bitmaps.at(3)->setAccelY(0.0f);
bitmaps.at(3)->setSpriteClip(128, 96, 128, 96);
bitmaps[3]->setPosX(GAMECANVAS_CENTER_X - 64);
bitmaps[3]->setPosY(GAMECANVAS_HEIGHT);
bitmaps[3]->setVelX(0.0f);
bitmaps[3]->setVelY(-0.7f);
bitmaps[3]->setAccelX(0.0f);
bitmaps[3]->setAccelY(0.0f);
bitmaps[3]->setSpriteClip(128, 96, 128, 96);
bitmaps.at(4)->setPosX(SCREEN_CENTER_X - 64);
bitmaps.at(4)->setPosY(-96);
bitmaps.at(4)->setVelX(0.0f);
bitmaps.at(4)->setVelY(3.0f);
bitmaps.at(4)->setAccelX(0.1f);
bitmaps.at(4)->setAccelY(0.3f);
bitmaps.at(4)->setSpriteClip(0, 192, 128, 96);
bitmaps[4]->setPosX(GAMECANVAS_CENTER_X - 64);
bitmaps[4]->setPosY(-96);
bitmaps[4]->setVelX(0.0f);
bitmaps[4]->setVelY(3.0f);
bitmaps[4]->setAccelX(0.1f);
bitmaps[4]->setAccelY(0.3f);
bitmaps[4]->setSpriteClip(0, 192, 128, 96);
bitmaps.at(5)->setPosX(GAME_WIDTH);
bitmaps.at(5)->setPosY(SCREEN_FIRST_QUARTER_Y - 24);
bitmaps.at(5)->setVelX(-0.7f);
bitmaps.at(5)->setVelY(0.0f);
bitmaps.at(5)->setAccelX(0.0f);
bitmaps.at(5)->setAccelY(0.0f);
bitmaps.at(5)->setSpriteClip(128, 192, 128, 96);
bitmaps[5]->setPosX(GAMECANVAS_WIDTH);
bitmaps[5]->setPosY(GAMECANVAS_FIRST_QUARTER_Y - 24);
bitmaps[5]->setVelX(-0.7f);
bitmaps[5]->setVelY(0.0f);
bitmaps[5]->setAccelX(0.0f);
bitmaps[5]->setAccelY(0.0f);
bitmaps[5]->setSpriteClip(128, 192, 128, 96);
// Inicializa los textos de la intro
const int totalTexts = 9;
@@ -92,7 +93,7 @@ Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Lang *lang)
{
Writer *w = new Writer(text);
w->setPosX(BLOCK * 0);
w->setPosY(GAME_HEIGHT - (BLOCK * 6));
w->setPosY(GAMECANVAS_HEIGHT - (BLOCK * 6));
w->setKerning(-1);
w->setEnabled(false);
w->setEnabledCounter(180);
@@ -100,44 +101,44 @@ Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Lang *lang)
}
// Un dia qualsevol de l'any 2000
texts.at(0)->setCaption(lang->getText(27));
texts.at(0)->setSpeed(8);
texts[0]->setCaption(lang->getText(27));
texts[0]->setSpeed(8);
// Tot esta tranquil a la UPV
texts.at(1)->setCaption(lang->getText(28));
texts.at(1)->setSpeed(8);
texts[1]->setCaption(lang->getText(28));
texts[1]->setSpeed(8);
// Fins que un desaprensiu...
texts.at(2)->setCaption(lang->getText(29));
texts.at(2)->setSpeed(12);
texts[2]->setCaption(lang->getText(29));
texts[2]->setSpeed(12);
// HEY! ME ANE A FERME UN CORTAET...
texts.at(3)->setCaption(lang->getText(30));
texts.at(3)->setSpeed(8);
texts[3]->setCaption(lang->getText(30));
texts[3]->setSpeed(8);
// UAAAAAAAAAAAAA!!!
texts.at(4)->setCaption(lang->getText(31));
texts.at(4)->setSpeed(1);
texts[4]->setCaption(lang->getText(31));
texts[4]->setSpeed(1);
// Espera un moment...
texts.at(5)->setCaption(lang->getText(32));
texts.at(5)->setSpeed(16);
texts[5]->setCaption(lang->getText(32));
texts[5]->setSpeed(16);
// Si resulta que no tinc solt!
texts.at(6)->setCaption(lang->getText(33));
texts.at(6)->setSpeed(2);
texts[6]->setCaption(lang->getText(33));
texts[6]->setSpeed(2);
// MERDA DE MAQUINA!
texts.at(7)->setCaption(lang->getText(34));
texts.at(7)->setSpeed(3);
texts[7]->setCaption(lang->getText(34));
texts[7]->setSpeed(3);
// Blop... blop... blop...
texts.at(8)->setCaption(lang->getText(35));
texts.at(8)->setSpeed(16);
texts[8]->setCaption(lang->getText(35));
texts[8]->setSpeed(16);
for (auto text : texts)
{
text->center(SCREEN_CENTER_X);
text->center(GAMECANVAS_CENTER_X);
}
}
@@ -183,48 +184,37 @@ void Intro::checkEventHandler()
section.name = PROG_SECTION_QUIT;
break;
}
}
}
// Cualquier tecla pulsada
if ((eventHandler->type == SDL_KEYDOWN) || (eventHandler->type == SDL_JOYBUTTONDOWN))
{
switch (eventHandler->key.keysym.scancode)
{
case SDL_SCANCODE_F:
screen->switchVideoMode();
texture->reLoad();
break;
// Comprueba las entradas
void Intro::checkInput()
{
if (input->checkInput(input_exit, REPEAT_FALSE))
{
section.name = PROG_SECTION_QUIT;
}
case SDL_SCANCODE_F1:
screen->setWindowSize(1);
texture->reLoad();
break;
else if (input->checkInput(input_window_fullscreen, REPEAT_FALSE))
{
screen->switchVideoMode();
}
case SDL_SCANCODE_F2:
screen->setWindowSize(2);
texture->reLoad();
break;
else if (input->checkInput(input_window_dec_size, REPEAT_FALSE))
{
screen->decWindowSize();
}
case SDL_SCANCODE_F3:
screen->setWindowSize(3);
texture->reLoad();
break;
else if (input->checkInput(input_window_inc_size, REPEAT_FALSE))
{
screen->incWindowSize();
}
case SDL_SCANCODE_F4:
screen->setWindowSize(4);
texture->reLoad();
break;
case SDL_SCANCODE_F5:
screen->showText("HOLA MAMA!");
break;
default:
JA_StopMusic();
section.name = PROG_SECTION_TITLE;
section.subsection = TITLE_SECTION_1;
break;
}
}
else if (input->checkInput(input_pause, REPEAT_FALSE) || input->checkInput(input_accept, REPEAT_FALSE) || input->checkInput(input_fire_left, REPEAT_FALSE) || input->checkInput(input_fire_center, REPEAT_FALSE) || input->checkInput(input_fire_right, REPEAT_FALSE))
{
JA_StopMusic();
section.name = PROG_SECTION_TITLE;
section.subsection = TITLE_SECTION_1;
}
}
@@ -235,36 +225,36 @@ void Intro::updateScenes()
{
case 1:
// Primera imagen - UPV
if (!bitmaps.at(0)->hasFinished())
if (!bitmaps[0]->hasFinished())
{
bitmaps.at(0)->setEnabled(true);
bitmaps[0]->setEnabled(true);
}
// Primer texto de la primera imagen
if (bitmaps.at(0)->hasFinished() && !texts.at(0)->hasFinished())
if (bitmaps[0]->hasFinished() && !texts[0]->hasFinished())
{
texts.at(0)->setEnabled(true);
texts[0]->setEnabled(true);
}
// Segundo texto de la primera imagen
if (texts.at(0)->hasFinished() && !texts.at(1)->hasFinished())
if (texts[0]->hasFinished() && !texts[1]->hasFinished())
{
texts.at(0)->setEnabled(false);
texts.at(1)->setEnabled(true);
texts[0]->setEnabled(false);
texts[1]->setEnabled(true);
}
// Tercer texto de la primera imagen
if (texts.at(1)->hasFinished() && !texts.at(2)->hasFinished())
if (texts[1]->hasFinished() && !texts[2]->hasFinished())
{
texts.at(1)->setEnabled(false);
texts.at(2)->setEnabled(true);
texts[1]->setEnabled(false);
texts[2]->setEnabled(true);
}
// Fin de la primera escena
if (texts.at(2)->hasFinished())
if (texts[2]->hasFinished())
{
bitmaps.at(0)->setEnabled(false);
texts.at(2)->setEnabled(false);
bitmaps[0]->setEnabled(false);
texts[2]->setEnabled(false);
scene++;
}
@@ -272,22 +262,22 @@ void Intro::updateScenes()
case 2:
// Segunda imagen - Máquina
if (!bitmaps.at(1)->hasFinished())
if (!bitmaps[1]->hasFinished())
{
bitmaps.at(1)->setEnabled(true);
bitmaps[1]->setEnabled(true);
}
// Primer texto de la segunda imagen
if (bitmaps.at(1)->hasFinished() && !texts.at(3)->hasFinished())
if (bitmaps[1]->hasFinished() && !texts[3]->hasFinished())
{
texts.at(3)->setEnabled(true);
texts[3]->setEnabled(true);
}
// Fin de la segunda escena
if (texts.at(3)->hasFinished())
if (texts[3]->hasFinished())
{
bitmaps.at(1)->setEnabled(false);
texts.at(3)->setEnabled(false);
bitmaps[1]->setEnabled(false);
texts[3]->setEnabled(false);
scene++;
}
@@ -295,17 +285,17 @@ void Intro::updateScenes()
case 3:
// Tercera imagen junto con primer texto - GRITO
if (!bitmaps.at(2)->hasFinished() && !texts.at(4)->hasFinished())
if (!bitmaps[2]->hasFinished() && !texts[4]->hasFinished())
{
bitmaps.at(2)->setEnabled(true);
texts.at(4)->setEnabled(true);
bitmaps[2]->setEnabled(true);
texts[4]->setEnabled(true);
}
// Fin de la tercera escena
if (bitmaps.at(2)->hasFinished() && texts.at(4)->hasFinished())
if (bitmaps[2]->hasFinished() && texts[4]->hasFinished())
{
bitmaps.at(2)->setEnabled(false);
texts.at(4)->setEnabled(false);
bitmaps[2]->setEnabled(false);
texts[4]->setEnabled(false);
scene++;
}
@@ -313,24 +303,24 @@ void Intro::updateScenes()
case 4:
// Cuarta imagen junto con primer texto - Reflexión
if (!bitmaps.at(3)->hasFinished() && !texts.at(5)->hasFinished())
if (!bitmaps[3]->hasFinished() && !texts[5]->hasFinished())
{
bitmaps.at(3)->setEnabled(true);
texts.at(5)->setEnabled(true);
bitmaps[3]->setEnabled(true);
texts[5]->setEnabled(true);
}
// Segundo texto de la cuarta imagen
if (texts.at(5)->hasFinished() && !texts.at(6)->hasFinished())
if (texts[5]->hasFinished() && !texts[6]->hasFinished())
{
texts.at(5)->setEnabled(false);
texts.at(6)->setEnabled(true);
texts[5]->setEnabled(false);
texts[6]->setEnabled(true);
}
// Fin de la cuarta escena
if (bitmaps.at(3)->hasFinished() && texts.at(6)->hasFinished())
if (bitmaps[3]->hasFinished() && texts[6]->hasFinished())
{
bitmaps.at(3)->setEnabled(false);
texts.at(6)->setEnabled(false);
bitmaps[3]->setEnabled(false);
texts[6]->setEnabled(false);
scene++;
}
@@ -338,22 +328,22 @@ void Intro::updateScenes()
case 5:
// Quinta imagen - Patada
if (!bitmaps.at(4)->hasFinished())
if (!bitmaps[4]->hasFinished())
{
bitmaps.at(4)->setEnabled(true);
bitmaps[4]->setEnabled(true);
}
// Primer texto de la quinta imagen
if (bitmaps.at(4)->hasFinished() && !texts.at(7)->hasFinished())
if (bitmaps[4]->hasFinished() && !texts[7]->hasFinished())
{
texts.at(7)->setEnabled(true);
texts[7]->setEnabled(true);
}
// Fin de la quinta escena
if (bitmaps.at(4)->hasFinished() && texts.at(7)->hasFinished())
if (bitmaps[4]->hasFinished() && texts[7]->hasFinished())
{
bitmaps.at(4)->setEnabled(false);
texts.at(7)->setEnabled(false);
bitmaps[4]->setEnabled(false);
texts[7]->setEnabled(false);
scene++;
}
@@ -361,17 +351,17 @@ void Intro::updateScenes()
case 6:
// Sexta imagen junto con texto - Globos de café
if (!bitmaps.at(5)->hasFinished() && !texts.at(8)->hasFinished())
if (!bitmaps[5]->hasFinished() && !texts[8]->hasFinished())
{
bitmaps.at(5)->setEnabled(true);
texts.at(8)->setEnabled(true);
bitmaps[5]->setEnabled(true);
texts[8]->setEnabled(true);
}
// Acaba el último texto
if (bitmaps.at(5)->hasFinished() && texts.at(8)->hasFinished())
if (bitmaps[5]->hasFinished() && texts[8]->hasFinished())
{
bitmaps.at(5)->setEnabled(false);
texts.at(8)->setEnabled(false);
bitmaps[5]->setEnabled(false);
texts[8]->setEnabled(false);
JA_StopMusic();
section.name = PROG_SECTION_TITLE;
section.subsection = TITLE_SECTION_1;
@@ -388,6 +378,7 @@ void Intro::updateScenes()
void Intro::update()
{
checkEventHandler();
checkInput();
if (SDL_GetTicks() - ticks > ticksSpeed)
{

View File

@@ -2,6 +2,7 @@
#include <SDL2/SDL.h>
#include "common/asset.h"
#include "common/input.h"
#include "common/jail_audio.h"
#include "common/screen.h"
#include "common/smartsprite.h"
@@ -24,6 +25,7 @@ private:
SDL_Event *eventHandler; // Manejador de eventos
Asset *asset; // Objeto que gestiona todos los ficheros de recursos
Lang *lang; // Objeto para gestionar los textos en diferentes idiomas
Input *input; // Objeto pata gestionar la entrada
std::vector<SmartSprite *> bitmaps; // Vector con los sprites inteligentes para los dibujos de la intro
std::vector<Writer *> texts; // Textos de la intro
Text *text; // Textos de la intro
@@ -32,7 +34,7 @@ private:
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa
Uint8 ticksSpeed; // Velocidad a la que se repiten los bucles del programa
section_t section; // Estado del bucle principal para saber si continua o se sale
JA_Music music; // Musica para la intro
JA_Music_t *music; // Musica para la intro
int scene; // Indica que escena está activa
// Actualiza las variables del objeto
@@ -47,12 +49,15 @@ private:
// Comprueba los eventos
void checkEventHandler();
// Comprueba las entradas
void checkInput();
// Actualiza las escenas de la intro
void updateScenes();
public:
// Constructor
Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Lang *lang);
Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, Lang *lang);
// Destructor
~Intro();

View File

@@ -4,12 +4,13 @@
#define END_LOGO 200
// Constructor
Logo::Logo(SDL_Renderer *renderer, Screen *screen, Asset *asset)
Logo::Logo(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input)
{
// Copia la dirección de los objetos
this->renderer = renderer;
this->screen = screen;
this->asset = asset;
this->input = input;
// Reserva memoria para los punteros
eventHandler = new SDL_Event();
@@ -56,47 +57,36 @@ void Logo::checkEventHandler()
section.name = PROG_SECTION_QUIT;
break;
}
}
}
// Cualquier tecla pulsada
if ((eventHandler->type == SDL_KEYDOWN) || (eventHandler->type == SDL_JOYBUTTONDOWN))
{
switch (eventHandler->key.keysym.scancode)
{
case SDL_SCANCODE_F:
screen->switchVideoMode();
texture->reLoad();
break;
// Comprueba las entradas
void Logo::checkInput()
{
if (input->checkInput(input_exit, REPEAT_FALSE))
{
section.name = PROG_SECTION_QUIT;
}
case SDL_SCANCODE_F1:
screen->setWindowSize(1);
texture->reLoad();
break;
else if (input->checkInput(input_window_fullscreen, REPEAT_FALSE))
{
screen->switchVideoMode();
}
case SDL_SCANCODE_F2:
screen->setWindowSize(2);
texture->reLoad();
break;
else if (input->checkInput(input_window_dec_size, REPEAT_FALSE))
{
screen->decWindowSize();
}
case SDL_SCANCODE_F3:
screen->setWindowSize(3);
texture->reLoad();
break;
else if (input->checkInput(input_window_inc_size, REPEAT_FALSE))
{
screen->incWindowSize();
}
case SDL_SCANCODE_F4:
screen->setWindowSize(4);
texture->reLoad();
break;
case SDL_SCANCODE_F5:
screen->showText("Conectado a Jailers.net");
break;
default:
section.name = PROG_SECTION_TITLE;
section.subsection = TITLE_SECTION_1;
break;
}
}
else if (input->checkInput(input_pause, REPEAT_FALSE) || input->checkInput(input_accept, REPEAT_FALSE) || input->checkInput(input_fire_left, REPEAT_FALSE) || input->checkInput(input_fire_center, REPEAT_FALSE) || input->checkInput(input_fire_right, REPEAT_FALSE))
{
section.name = PROG_SECTION_TITLE;
section.subsection = TITLE_SECTION_1;
}
}
@@ -117,6 +107,7 @@ void Logo::renderFade()
void Logo::update()
{
checkEventHandler();
checkInput();
if (SDL_GetTicks() - ticks > ticksSpeed)
{

View File

@@ -2,6 +2,7 @@
#include <SDL2/SDL.h>
#include "common/asset.h"
#include "common/input.h"
#include "common/jail_audio.h"
#include "common/screen.h"
#include "common/sprite.h"
@@ -19,15 +20,16 @@ private:
SDL_Renderer *renderer; // El renderizador de la ventana
Screen *screen; // Objeto encargado de dibujar en pantalla
Asset *asset; // Objeto que gestiona todos los ficheros de recursos
Input *input; // Objeto pata gestionar la entrada
Texture *texture; // Textura con los graficos
SDL_Event *eventHandler; // Manejador de eventos
Sprite *sprite; // Sprite con la textura del logo
// Variables
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa
section_t section; // Estado del bucle principal para saber si continua o se sale
int counter; // Contador
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa
section_t section; // Estado del bucle principal para saber si continua o se sale
int counter; // Contador
// Actualiza las variables del objeto
void update();
@@ -41,12 +43,15 @@ private:
// Comprueba los eventos
void checkEventHandler();
// Comprueba las entradas
void checkInput();
// Dibuja el fade
void renderFade();
public:
// Constructor
Logo(SDL_Renderer *renderer, Screen *screen, Asset *mAsset);
Logo(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input);
// Destructor
~Logo();

View File

@@ -42,12 +42,13 @@ Reescribiendo el código el 27/09/2022
#include "director.h"
#include <stdio.h>
int main(int argc, char *args[])
int main(int argc, char *argv[])
{
printf("Starting the game...\n\n");
std::cout << "Starting the game..." << std::endl
<< std::endl;
// Crea el objeto Director
Director *director = new Director(args[0]);
Director *director = new Director(argc, argv);
// Bucle principal
director->run();
@@ -55,7 +56,7 @@ int main(int argc, char *args[])
// Destruye el objeto Director
delete director;
printf("\nShutting down the game...\n");
std::cout << "\nShutting down the game..." << std::endl;
return 0;
}

View File

@@ -8,11 +8,11 @@ Player::Player(float x, int y, SDL_Renderer *renderer, std::vector<Texture *> te
this->renderer = renderer;
// Reserva memoria para los objetos
headSprite = new AnimatedSprite(texture.at(0), renderer, "", animations.at(0));
bodySprite = new AnimatedSprite(texture.at(1), renderer, "", animations.at(1));
legsSprite = new AnimatedSprite(texture.at(2), renderer, "", animations.at(2));
deathSprite = new AnimatedSprite(texture.at(3), renderer, "", animations.at(3));
fireSprite = new AnimatedSprite(texture.at(4), renderer, "", animations.at(4));
headSprite = new AnimatedSprite(texture[0], renderer, "", animations[0]);
bodySprite = new AnimatedSprite(texture[1], renderer, "", animations[1]);
legsSprite = new AnimatedSprite(texture[2], renderer, "", animations[2]);
deathSprite = new AnimatedSprite(texture[3], renderer, "", animations[3]);
fireSprite = new AnimatedSprite(texture[4], renderer, "", animations[4]);
fireSprite->getTexture()->setAlpha(224);
// Establece la posición inicial del jugador
@@ -95,25 +95,25 @@ void Player::setInput(Uint8 input)
{
switch (input)
{
case INPUT_LEFT:
case input_left:
velX = -baseSpeed;
setWalkingStatus(PLAYER_STATUS_WALKING_LEFT);
break;
case INPUT_RIGHT:
case input_right:
velX = baseSpeed;
setWalkingStatus(PLAYER_STATUS_WALKING_RIGHT);
break;
case INPUT_BUTTON_2:
case input_fire_center:
setFiringStatus(PLAYER_STATUS_FIRING_UP);
break;
case INPUT_BUTTON_1:
case input_fire_left:
setFiringStatus(PLAYER_STATUS_FIRING_LEFT);
break;
case INPUT_BUTTON_3:
case input_fire_right:
setFiringStatus(PLAYER_STATUS_FIRING_RIGHT);
break;
@@ -620,9 +620,9 @@ void Player::updatePowerUpHeadOffset()
// Pone las texturas del jugador
void Player::setPlayerTextures(std::vector<Texture *> texture)
{
headSprite->setTexture(texture.at(0));
bodySprite->setTexture(texture.at(1));
legsSprite->setTexture(texture.at(2));
deathSprite->setTexture(texture.at(3));
fireSprite->setTexture(texture.at(4));
headSprite->setTexture(texture[0]);
bodySprite->setTexture(texture[1]);
legsSprite->setTexture(texture[2]);
deathSprite->setTexture(texture[3]);
fireSprite->setTexture(texture[4]);
}

View File

@@ -125,9 +125,9 @@ void Title::init()
// Si ha encontrado un mando se lo asigna al segundo jugador
if (input->gameControllerFound())
{
options->input.at(1).id = availableInputDevices.at(deviceIndex.at(1)).id;
options->input.at(1).name = availableInputDevices.at(deviceIndex.at(1)).name;
options->input.at(1).deviceType = availableInputDevices.at(deviceIndex.at(1)).deviceType;
options->input[1].id = availableInputDevices[deviceIndex[1]].id;
options->input[1].name = availableInputDevices[deviceIndex[1]].name;
options->input[1].deviceType = availableInputDevices[deviceIndex[1]].deviceType;
}
// Inicializa el bitmap de Coffee
@@ -186,8 +186,8 @@ void Title::init()
// Coloca la ventana que recorre el mosaico de fondo de manera que coincida con el mosaico que hay pintado en el titulo al iniciar
backgroundWindow.x = 128;
backgroundWindow.y = 96;
backgroundWindow.w = GAME_WIDTH;
backgroundWindow.h = GAME_HEIGHT;
backgroundWindow.w = GAMECANVAS_WIDTH;
backgroundWindow.h = GAMECANVAS_HEIGHT;
// Inicializa los valores del vector con los valores del seno
for (int i = 0; i < 360; ++i)
@@ -205,6 +205,9 @@ void Title::update()
// Comprueba los eventos
checkEventHandler();
// Comprueba las entradas
checkInput();
// Calcula la lógica de los objetos
if (SDL_GetTicks() - ticks > ticksSpeed)
{
@@ -309,6 +312,10 @@ void Title::update()
{
runInstructions(m_auto);
}
if (section.name != PROG_SECTION_QUIT)
{
runHiScoreTable(mhst_auto);
}
}
else
section.name = PROG_SECTION_LOGO;
@@ -422,7 +429,7 @@ void Title::update()
case 6: // Display mode
switchFullScreenModeVar();
if (options->fullScreenMode != 0)
if (options->videoMode != 0)
{
menu.options->setSelectable(8, false);
menu.options->setGreyed(8, true);
@@ -494,6 +501,10 @@ void Title::update()
{
runInstructions(m_auto);
}
if (section.name != PROG_SECTION_QUIT)
{
runHiScoreTable(mhst_auto);
}
init();
demo = false;
counter = TITLE_COUNTER;
@@ -615,7 +626,7 @@ void Title::render()
crisisBitmap->render();
// Texto con el copyright y versión
text2->writeDX(TXT_CENTER | TXT_SHADOW, SCREEN_CENTER_X, GAME_HEIGHT - (BLOCK * 2), TEXT_COPYRIGHT, 1, noColor, 1, shdwTxtColor);
text2->writeDX(TXT_CENTER | TXT_SHADOW, GAMECANVAS_CENTER_X, GAMECANVAS_HEIGHT - (BLOCK * 2), TEXT_COPYRIGHT, 1, noColor, 1, shdwTxtColor);
}
if (menuVisible == true)
@@ -629,7 +640,7 @@ void Title::render()
// PRESS ANY KEY!
if ((counter % 50 > 14) && (menuVisible == false))
{
text1->writeDX(TXT_CENTER | TXT_SHADOW, SCREEN_CENTER_X, PLAY_AREA_THIRD_QUARTER_Y + BLOCK, lang->getText(23), 1, noColor, 1, shdwTxtColor);
text1->writeDX(TXT_CENTER | TXT_SHADOW, GAMECANVAS_CENTER_X, PLAY_AREA_THIRD_QUARTER_Y + BLOCK, lang->getText(23), 1, noColor, 1, shdwTxtColor);
}
// Fade
@@ -658,42 +669,9 @@ void Title::checkEventHandler()
break;
}
else if (eventHandler->type == SDL_KEYDOWN && eventHandler->key.repeat == 0)
else if (eventHandler->type == SDL_RENDER_DEVICE_RESET || eventHandler->type == SDL_RENDER_TARGETS_RESET)
{
switch (eventHandler->key.keysym.scancode)
{
case SDL_SCANCODE_ESCAPE:
section.name = PROG_SECTION_QUIT;
break;
case SDL_SCANCODE_F:
screen->switchVideoMode();
reloadTextures();
break;
case SDL_SCANCODE_F1:
screen->setWindowSize(1);
reloadTextures();
break;
case SDL_SCANCODE_F2:
screen->setWindowSize(2);
reloadTextures();
break;
case SDL_SCANCODE_F3:
screen->setWindowSize(3);
reloadTextures();
break;
case SDL_SCANCODE_F4:
screen->setWindowSize(4);
reloadTextures();
break;
default:
break;
}
reLoadTextures();
}
if (section.subsection == TITLE_SECTION_3)
@@ -710,6 +688,36 @@ void Title::checkEventHandler()
}
}
// Comprueba las entradas
void Title::checkInput()
{
if (input->checkInput(input_exit, REPEAT_FALSE))
{
section.name = PROG_SECTION_QUIT;
}
else if (input->checkInput(input_window_fullscreen, REPEAT_FALSE))
{
screen->switchVideoMode();
}
else if (input->checkInput(input_window_dec_size, REPEAT_FALSE))
{
screen->decWindowSize();
}
else if (input->checkInput(input_window_inc_size, REPEAT_FALSE))
{
screen->incWindowSize();
}
else if (input->checkInput(input_pause, REPEAT_FALSE) || input->checkInput(input_accept, REPEAT_FALSE) || input->checkInput(input_fire_left, REPEAT_FALSE) || input->checkInput(input_fire_center, REPEAT_FALSE) || input->checkInput(input_fire_right, REPEAT_FALSE))
{
section.name = PROG_SECTION_TITLE;
section.subsection = TITLE_SECTION_1;
}
}
// Actualiza el tileado de fondo
void Title::updateBG()
{
@@ -729,20 +737,20 @@ void Title::updateBG()
// Cambia el valor de la variable de modo de pantalla completa
void Title::switchFullScreenModeVar()
{
switch (options->fullScreenMode)
switch (options->videoMode)
{
case 0:
options->fullScreenMode = SDL_WINDOW_FULLSCREEN;
options->videoMode = SDL_WINDOW_FULLSCREEN;
break;
case SDL_WINDOW_FULLSCREEN:
options->fullScreenMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
options->videoMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
break;
case SDL_WINDOW_FULLSCREEN_DESKTOP:
options->fullScreenMode = 0;
options->videoMode = 0;
break;
default:
options->fullScreenMode = 0;
options->videoMode = 0;
break;
}
}
@@ -856,7 +864,7 @@ void Title::updateMenuLabels()
i++;
// DISPLAY MODE - OPTIONS
switch (options->fullScreenMode)
switch (options->videoMode)
{
case 0:
menu.options->setItemCaption(i, lang->getText(4)); // WINDOW
@@ -906,8 +914,8 @@ void Title::updateMenuLabels()
menu.options->setItemCaption(i, lang->getText(10)); // CANCEL
// Recoloca el menu de opciones
menu.options->centerMenuOnX(SCREEN_CENTER_X);
menu.options->centerMenuOnY(SCREEN_CENTER_Y);
menu.options->centerMenuOnX(GAMECANVAS_CENTER_X);
menu.options->centerMenuOnY(GAMECANVAS_CENTER_Y);
menu.options->centerMenuElementsOnX();
// Establece las etiquetas del menu de titulo
@@ -917,7 +925,7 @@ void Title::updateMenuLabels()
menu.title->setItemCaption(3, lang->getText(3)); // QUIT
// Recoloca el menu de titulo
menu.title->centerMenuOnX(SCREEN_CENTER_X);
menu.title->centerMenuOnX(GAMECANVAS_CENTER_X);
menu.title->centerMenuElementsOnX();
// Establece las etiquetas del menu de seleccion de jugador
@@ -925,14 +933,14 @@ void Title::updateMenuLabels()
menu.playerSelect->setItemCaption(3, lang->getText(40)); // BACK
// Recoloca el menu de selección de jugador
menu.playerSelect->centerMenuOnX(SCREEN_CENTER_X);
menu.playerSelect->centerMenuOnX(GAMECANVAS_CENTER_X);
menu.playerSelect->centerMenuElementsOnX();
}
// Aplica las opciones de menu seleccionadas
void Title::applyOptions()
{
screen->setVideoMode(options->fullScreenMode);
screen->setVideoMode(options->videoMode);
lang->setLang(options->language);
@@ -962,6 +970,24 @@ section_t Title::runInstructions(mode_e mode)
return section;
}
// Ejecuta la parte donde se muestra la tabla de puntuaciones
section_t Title::runHiScoreTable(mode_hiScoreTable_e mode)
{
if (!options->online.enabled)
{
section.name = PROG_SECTION_TITLE;
section.subsection = TITLE_SECTION_1;
return section;
}
hiScoreTable = new HiScoreTable(renderer, screen, asset, lang, options);
section = hiScoreTable->run(mode);
delete hiScoreTable;
return section;
}
// Ejecuta el juego en modo demo
section_t Title::runDemoGame()
{
@@ -979,49 +1005,55 @@ bool Title::updatePlayerInputs(int numPlayer)
if (!input->gameControllerFound())
{ // Si no hay mandos se deja todo de manera prefijada
deviceIndex.at(0) = 0;
deviceIndex.at(1) = 0;
deviceIndex[0] = 0;
deviceIndex[1] = 0;
options->input.at(0).id = -1;
options->input.at(0).name = "KEYBOARD";
options->input.at(0).deviceType = INPUT_USE_KEYBOARD;
options->input[0].id = -1;
options->input[0].name = "KEYBOARD";
options->input[0].deviceType = INPUT_USE_KEYBOARD;
options->input.at(1).id = 0;
options->input.at(1).name = "GAME CONTROLLER";
options->input.at(1).deviceType = INPUT_USE_GAMECONTROLLER;
options->input[1].id = 0;
options->input[1].name = "GAME CONTROLLER";
options->input[1].deviceType = INPUT_USE_GAMECONTROLLER;
return true;
}
else
{ // Si hay mas de un dispositivo, se recorre el vector
printf("numplayer:%i\n", numPlayer);
printf("deviceindex:%i\n", deviceIndex.at(numPlayer));
if (options->console)
{
std::cout << "numplayer:" << numPlayer << std::endl;
std::cout << "deviceindex:" << deviceIndex[numPlayer] << std::endl;
}
// Incrementa el indice
if (deviceIndex.at(numPlayer) < numDevices - 1)
if (deviceIndex[numPlayer] < numDevices - 1)
{
deviceIndex.at(numPlayer)++;
deviceIndex[numPlayer]++;
}
else
{
deviceIndex.at(numPlayer) = 0;
deviceIndex[numPlayer] = 0;
}
if (options->console)
{
std::cout << "deviceindex:" << deviceIndex[numPlayer] << std::endl;
}
printf("deviceindex:%i\n", deviceIndex.at(numPlayer));
// Si coincide con el del otro jugador, se lo intercambian
if (deviceIndex.at(0) == deviceIndex.at(1))
if (deviceIndex[0] == deviceIndex[1])
{
const int theOtherPlayer = (numPlayer + 1) % 2;
deviceIndex.at(theOtherPlayer)--;
if (deviceIndex.at(theOtherPlayer) < 0)
deviceIndex[theOtherPlayer]--;
if (deviceIndex[theOtherPlayer] < 0)
{
deviceIndex.at(theOtherPlayer) = numDevices - 1;
deviceIndex[theOtherPlayer] = numDevices - 1;
}
}
// Copia el dispositivo marcado por el indice a la variable de opciones de cada jugador
options->input[0] = availableInputDevices.at(deviceIndex.at(0));
options->input[1] = availableInputDevices.at(deviceIndex.at(1));
options->input[0] = availableInputDevices[deviceIndex[0]];
options->input[1] = availableInputDevices[deviceIndex[1]];
return true;
}
@@ -1031,10 +1063,13 @@ bool Title::updatePlayerInputs(int numPlayer)
void Title::createTiledBackground()
{
// Crea la textura para el mosaico de fondo
background = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAME_WIDTH * 2, GAME_HEIGHT * 2);
background = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH * 2, GAMECANVAS_HEIGHT * 2);
if (background == nullptr)
{
printf("TitleSurface could not be created!\nSDL Error: %s\n", SDL_GetError());
if (options->console)
{
std::cout << "TitleSurface could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
// Crea los objetos para pintar en la textura de fondo
@@ -1070,7 +1105,11 @@ void Title::createTiledBackground()
// Comprueba cuantos mandos hay conectados para gestionar el menu de opciones
void Title::checkInputDevices()
{
printf("Filling devices for options menu...\n");
if (options->console)
{
std::cout << "Filling devices for options menu..." << std::endl;
}
input->discoverGameController();
const int numControllers = input->getNumControllers();
availableInputDevices.clear();
input_t temp;
@@ -1083,7 +1122,10 @@ void Title::checkInputDevices()
temp.name = input->getControllerName(i);
temp.deviceType = INPUT_USE_GAMECONTROLLER;
availableInputDevices.push_back(temp);
printf("Device %i:\t%s\n", (int)availableInputDevices.size(), temp.name.c_str());
if (options->console)
{
std::cout << "Device " << (int)availableInputDevices.size() << " - " << temp.name.c_str() << std::endl;
}
}
// Añade el teclado al final
@@ -1091,11 +1133,15 @@ void Title::checkInputDevices()
temp.name = "KEYBOARD";
temp.deviceType = INPUT_USE_KEYBOARD;
availableInputDevices.push_back(temp);
printf("Device %i:\t%s\n\n", (int)availableInputDevices.size(), temp.name.c_str());
if (options->console)
{
std::cout << "Device " << (int)availableInputDevices.size() << " - " << temp.name.c_str() << std::endl;
std::cout << std::endl;
}
}
// Recarga las texturas
void Title::reloadTextures()
void Title::reLoadTextures()
{
dustTexture->reLoad();
coffeeTexture->reLoad();

View File

@@ -14,6 +14,7 @@
#include "const.h"
#include "fade.h"
#include "game.h"
#include "hiscore_table.h"
#include "instructions.h"
#include "item.h"
@@ -21,7 +22,7 @@
#define TITLE_H
// Textos
#define TEXT_COPYRIGHT "@2020,2022 JailDesigner (v2.1b)"
#define TEXT_COPYRIGHT "@2020,2022 JailDesigner (v2.2a)"
// Contadores
#define TITLE_COUNTER 800
@@ -48,12 +49,13 @@ private:
Input *input; // Objeto para leer las entradas de teclado o mando
Lang *lang; // Objeto para gestionar los textos en diferentes idiomas
Instructions *instructions; // Objeto para la sección de las instrucciones
HiScoreTable *hiScoreTable; // Objeto para mostrar las mejores puntuaciones online
Game *demoGame; // Objeto para lanzar la demo del juego
SDL_Event *eventHandler; // Manejador de eventos
Texture *dustTexture; // Textura con los graficos del polvo
Texture *coffeeTexture; // Textura con los graficos de la palabra coffee
Texture *crisisTexture; // Textura con los graficos de la plabra crisis
Texture *dustTexture; // Textura con los graficos del polvo
Texture *coffeeTexture; // Textura con los graficos de la palabra coffee
Texture *crisisTexture; // Textura con los graficos de la plabra crisis
Texture *gradientTexture; // Textura con los graficos para el degradado del fondo del titulo
SDL_Rect backgroundWindow; // Ventana visible para la textura de fondo del titulo
@@ -72,8 +74,8 @@ private:
Fade *fade; // Objeto para realizar fundidos en pantalla
// Variable
JA_Music titleMusic; // Musica para el titulo
JA_Sound crashSound; // Sonido con el impacto del título
JA_Music_t *titleMusic; // Musica para el titulo
JA_Sound_t *crashSound; // Sonido con el impacto del título
int backgroundCounter; // Temporizador para el fondo de tiles de la pantalla de titulo
int counter; // Temporizador para la pantalla de titulo
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa
@@ -103,6 +105,9 @@ private:
// Comprueba los eventos
void checkEventHandler();
// Comprueba las entradas
void checkInput();
// Actualiza el tileado de fondo
void updateBG();
@@ -118,6 +123,9 @@ private:
// Ejecuta la parte donde se muestran las instrucciones
section_t runInstructions(mode_e mode);
// Ejecuta la parte donde se muestra la tabla de puntuaciones
section_t runHiScoreTable(mode_hiScoreTable_e mode);
// Ejecuta el juego en modo demo
section_t runDemoGame();
@@ -131,7 +139,7 @@ private:
void checkInputDevices();
// Recarga las texturas
void reloadTextures();
void reLoadTextures();
public:
// Constructor