Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e525642a0 | |||
| c7db6aeaa3 | |||
| 5ff04daf20 | |||
| 5bb2b5e7c4 | |||
| 7a685c0cc8 | |||
| 07e83fc811 | |||
| 3167251eae | |||
| 4efbb61fbc | |||
| 3992fc08bf | |||
| 366fe404ca | |||
| 217781c621 | |||
| 212b2b481c | |||
| 59e766f5c3 | |||
| 2e11fec2cb | |||
| 0d7ab830c9 | |||
| 0cec9f8556 | |||
| c6474cb2da | |||
| e6fd4225a2 | |||
| 85ab5ea03f | |||
| 2457517f2b | |||
| 64880a427e | |||
| a8e5517a77 | |||
| a07a08adb7 | |||
| 32c31a8cb6 | |||
| c9da5135b2 | |||
| 817140825a | |||
| e6f101ece6 | |||
| 48971cd5d1 | |||
| 5bb5be9c33 | |||
| 2ee0c70319 | |||
| 3ba4293e8a | |||
| 8ae686a70b | |||
| 2ac425483b | |||
| fc01676df2 | |||
| e361d295c1 | |||
| f6098a479b | |||
| 7a0bc5c9ae | |||
| 5f68c6256f | |||
| debcc3409e | |||
| c86a6496b3 | |||
| 6bb877b510 | |||
| ec73c5fa30 | |||
| 4dd6c94730 | |||
| e1d6aff724 | |||
| bcb2e96069 | |||
| e23f6b5ed9 | |||
| 9cb57e2ff2 | |||
| cc0f050c50 | |||
| d75a733985 | |||
| 33d91dab55 | |||
| bd6807d655 | |||
| c6d15bb96f | |||
| e20cc3b4bb | |||
| 0baf7e5e2c | |||
| d9d4818d8a |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -13,4 +13,6 @@ thumbs.db
|
|||||||
*_debug*
|
*_debug*
|
||||||
sync_jail_engine.sh
|
sync_jail_engine.sh
|
||||||
jaildoctors_dilemma*
|
jaildoctors_dilemma*
|
||||||
todo
|
todo
|
||||||
|
build/
|
||||||
|
linux_utils/
|
||||||
85
CMakeLists.txt
Normal file
85
CMakeLists.txt
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# CMakeLists.txt
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
project(jaildoctors_dilemma VERSION 1.00)
|
||||||
|
|
||||||
|
# Configuración de compilador para MinGW en Windows, si es necesario
|
||||||
|
if(WIN32 AND NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||||
|
set(CMAKE_CXX_COMPILER "g++")
|
||||||
|
set(CMAKE_C_COMPILER "gcc")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Establecer estándar de C++
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
|
# Configuración global de flags de compilación
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Os -ffunction-sections -fdata-sections")
|
||||||
|
|
||||||
|
# Define el directorio de los archivos fuente
|
||||||
|
set(DIR_SOURCES "${CMAKE_SOURCE_DIR}/source")
|
||||||
|
|
||||||
|
# Cargar todos los archivos fuente en DIR_SOURCES
|
||||||
|
file(GLOB SOURCES "${DIR_SOURCES}/*.cpp")
|
||||||
|
|
||||||
|
# Verificar si se encontraron archivos fuente
|
||||||
|
if(NOT SOURCES)
|
||||||
|
message(FATAL_ERROR "No se encontraron archivos fuente en ${DIR_SOURCES}. Verifica que el directorio existe y contiene archivos .cpp.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Configuración de SDL2
|
||||||
|
find_package(SDL2 REQUIRED)
|
||||||
|
if(SDL2_FOUND)
|
||||||
|
message(STATUS "SDL2 encontrado: ${SDL2_INCLUDE_DIRS}")
|
||||||
|
include_directories(${SDL2_INCLUDE_DIRS})
|
||||||
|
link_directories(${SDL2_LIBDIR})
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "SDL2 no encontrado")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Incluye rutas de SDL2 obtenidas con pkg-config
|
||||||
|
include_directories(/usr/local/include /usr/local/include/SDL2)
|
||||||
|
link_directories(/usr/local/lib)
|
||||||
|
|
||||||
|
# Definir las bibliotecas comunes
|
||||||
|
set(LIBS SDL2)
|
||||||
|
|
||||||
|
# Configuración común de salida de ejecutables en el directorio raíz
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||||
|
|
||||||
|
# Añadir ejecutable principal
|
||||||
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
|
|
||||||
|
# Añadir definiciones de compilación dependiendo del tipo de build
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:DEBUG>:DEBUG VERBOSE>)
|
||||||
|
|
||||||
|
# Enlazar bibliotecas
|
||||||
|
target_link_libraries(${PROJECT_NAME} ${LIBS})
|
||||||
|
|
||||||
|
# Configuración específica para cada plataforma
|
||||||
|
if(WIN32)
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE WINDOWS_BUILD)
|
||||||
|
target_link_libraries(${PROJECT_NAME} mingw32 opengl32 gdi32 winmm imm32 ole32 version)
|
||||||
|
elseif(APPLE)
|
||||||
|
set(LIBS ${LIBS} "-framework OpenGL")
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE MACOS_BUILD)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated")
|
||||||
|
# Configurar compilación para Apple Silicon
|
||||||
|
set(CMAKE_OSX_ARCHITECTURES "arm64")
|
||||||
|
elseif(UNIX AND NOT APPLE)
|
||||||
|
set(LIBS ${LIBS} GL)
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE LINUX_BUILD)
|
||||||
|
target_link_libraries(${PROJECT_NAME} ${LIBS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Añadir OpenGL a las bibliotecas enlazadas
|
||||||
|
if(NOT WIN32)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
if(OPENGL_FOUND)
|
||||||
|
message(STATUS "OpenGL encontrado: ${OPENGL_LIBRARIES}")
|
||||||
|
target_link_libraries(${PROJECT_NAME} ${OPENGL_LIBRARIES})
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "OpenGL no encontrado")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
27
Makefile
27
Makefile
@@ -1,8 +1,8 @@
|
|||||||
executable = jaildoctors_dilemma
|
executable = jaildoctors_dilemma
|
||||||
source = source/*.cpp source/jail_engine/*.cpp
|
source = source/*.cpp
|
||||||
appName = JailDoctor's Dilemma
|
appName = JailDoctor's Dilemma
|
||||||
releaseFolder = jdd_release
|
releaseFolder = jdd_release
|
||||||
version = v1.08
|
version = v1.09
|
||||||
|
|
||||||
# Release names
|
# Release names
|
||||||
windowsRelease = $(executable)-$(version)-win32-x64.zip
|
windowsRelease = $(executable)-$(version)-win32-x64.zip
|
||||||
@@ -10,14 +10,17 @@ macosIntelRelease = $(executable)-$(version)-macos-intel.dmg
|
|||||||
macosAppleSiliconRelease = $(executable)-$(version)-macos-apple-silicon.dmg
|
macosAppleSiliconRelease = $(executable)-$(version)-macos-apple-silicon.dmg
|
||||||
linuxRelease = $(executable)-$(version)-linux.tar.gz
|
linuxRelease = $(executable)-$(version)-linux.tar.gz
|
||||||
|
|
||||||
|
# Specify the C++ standard
|
||||||
|
cpp_standard = c++20
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
@echo off
|
@echo off
|
||||||
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"
|
g++ $(source) -std=$(cpp_standard) -Wall -Os -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32 -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
|
strip -s -R .comment -R .gnu.version "$(executable).exe" --strip-unneeded
|
||||||
|
|
||||||
windows_debug:
|
windows_debug:
|
||||||
@echo off
|
@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"
|
g++ $(source) -D DEBUG -std=$(cpp_standard) -Wall -Os -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32 -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
|
strip -s -R .comment -R .gnu.version "$(executable)_debug.exe" --strip-unneeded
|
||||||
|
|
||||||
windows_release:
|
windows_release:
|
||||||
@@ -38,7 +41,7 @@ windows_release:
|
|||||||
powershell Copy-Item "release\*.dll" -Destination "$(releaseFolder)"
|
powershell Copy-Item "release\*.dll" -Destination "$(releaseFolder)"
|
||||||
|
|
||||||
# Build
|
# 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"
|
g++ $(source) -std=$(cpp_standard) -Wall -Os -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32 -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows -o "$(releaseFolder)/$(executable).exe"
|
||||||
strip -s -R .comment -R .gnu.version "$(releaseFolder)/$(executable).exe" --strip-unneeded
|
strip -s -R .comment -R .gnu.version "$(releaseFolder)/$(executable).exe" --strip-unneeded
|
||||||
|
|
||||||
# Create ZIP
|
# Create ZIP
|
||||||
@@ -49,10 +52,10 @@ windows_release:
|
|||||||
powershell if (Test-Path "$(releaseFolder)") {Remove-Item "$(releaseFolder)" -Recurse -Force}
|
powershell if (Test-Path "$(releaseFolder)") {Remove-Item "$(releaseFolder)" -Recurse -Force}
|
||||||
|
|
||||||
macos:
|
macos:
|
||||||
clang++ $(source) -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -o "$(executable)"
|
clang++ $(source) -std=$(cpp_standard) -Wall -Os -lSDL2 -framework OpenGL -Wno-deprecated -ffunction-sections -fdata-sections -o "$(executable)"
|
||||||
|
|
||||||
macos_debug:
|
macos_debug:
|
||||||
clang++ $(source) -D DEBUG -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -o "$(executable)_debug"
|
clang++ $(source) -D DEBUG -std=$(cpp_standard) -Wall -Os -lSDL2 -framework OpenGL -Wno-deprecated -ffunction-sections -fdata-sections -o "$(executable)_debug"
|
||||||
|
|
||||||
macos_release:
|
macos_release:
|
||||||
# Remove data and possible data from previous builds
|
# Remove data and possible data from previous builds
|
||||||
@@ -87,7 +90,7 @@ macos_release:
|
|||||||
ln -s /Applications "$(releaseFolder)"/Applications
|
ln -s /Applications "$(releaseFolder)"/Applications
|
||||||
|
|
||||||
# Build INTEL
|
# 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
|
clang++ $(source) -D MACOS_BUNDLE -std=$(cpp_standard) -Wall -Os -framework SDL2 -F ./Frameworks -framework OpenGL -Wno-deprecated -ffunction-sections -fdata-sections -o "$(releaseFolder)/$(appName).app/Contents/MacOS/$(executable)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.12
|
||||||
|
|
||||||
# Build INTEL DMG
|
# Build INTEL DMG
|
||||||
hdiutil create tmp.dmg -ov -volname "$(appName)" -fs HFS+ -srcfolder "$(releaseFolder)"
|
hdiutil create tmp.dmg -ov -volname "$(appName)" -fs HFS+ -srcfolder "$(releaseFolder)"
|
||||||
@@ -95,7 +98,7 @@ macos_release:
|
|||||||
rm -f tmp.dmg
|
rm -f tmp.dmg
|
||||||
|
|
||||||
# Build APPLE SILICON
|
# 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
|
clang++ $(source) -D MACOS_BUNDLE -std=$(cpp_standard) -Wall -Os -framework SDL2 -F ./Frameworks -framework OpenGL -Wno-deprecated -ffunction-sections -fdata-sections -o "$(releaseFolder)/$(appName).app/Contents/MacOS/$(executable)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11
|
||||||
|
|
||||||
# Build APPLE SILICON DMG
|
# Build APPLE SILICON DMG
|
||||||
hdiutil create tmp.dmg -ov -volname "$(appName)" -fs HFS+ -srcfolder "$(releaseFolder)"
|
hdiutil create tmp.dmg -ov -volname "$(appName)" -fs HFS+ -srcfolder "$(releaseFolder)"
|
||||||
@@ -107,11 +110,11 @@ macos_release:
|
|||||||
rm -rdf "$(releaseFolder)"
|
rm -rdf "$(releaseFolder)"
|
||||||
|
|
||||||
linux:
|
linux:
|
||||||
g++ $(source) -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -o "$(executable)"
|
g++ $(source) -std=$(cpp_standard) -Wall -Os -lSDL2 -lGL -ffunction-sections -fdata-sections -Wl,--gc-sections -o "$(executable)"
|
||||||
strip -s -R .comment -R .gnu.version "$(executable)" --strip-unneeded
|
strip -s -R .comment -R .gnu.version "$(executable)" --strip-unneeded
|
||||||
|
|
||||||
linux_debug:
|
linux_debug:
|
||||||
g++ $(source) -D DEBUG -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -o "$(executable)_debug"
|
g++ $(source) -D DEBUG -std=$(cpp_standard) -Wall -Os -lSDL2 -lGL -ffunction-sections -fdata-sections -Wl,--gc-sections -o "$(executable)_debug"
|
||||||
strip -s -R .comment -R .gnu.version "$(executable)_debug" --strip-unneeded
|
strip -s -R .comment -R .gnu.version "$(executable)_debug" --strip-unneeded
|
||||||
|
|
||||||
linux_release:
|
linux_release:
|
||||||
@@ -131,7 +134,7 @@ linux_release:
|
|||||||
rm -f "$(releaseFolder)/data/room/standard.tsx"
|
rm -f "$(releaseFolder)/data/room/standard.tsx"
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
g++ $(source) -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -o "$(releaseFolder)/$(executable)"
|
g++ $(source) -std=$(cpp_standard) -Wall -Os -lSDL2 -lGL -ffunction-sections -fdata-sections -Wl,--gc-sections -o "$(releaseFolder)/$(executable)"
|
||||||
strip -s -R .comment -R .gnu.version "$(releaseFolder)/$(executable)" --strip-unneeded
|
strip -s -R .comment -R .gnu.version "$(releaseFolder)/$(executable)" --strip-unneeded
|
||||||
|
|
||||||
# Pack files
|
# Pack files
|
||||||
|
|||||||
100
README.md
100
README.md
@@ -1,89 +1,65 @@
|
|||||||
# JailDoctor's Dilemma
|
# JailDoctor's Dilemma
|
||||||
|
|
||||||
JailDoc es un Jailer. A los Jailers les gusta empezar proyectos. A nadie le gusta terminarlos. Los Jailers viven en la Jail. A la Jail va uno a empezar proyectos. A la Jail va uno a enseñar sus proyectos. A la Jail va uno a aprender como empezar nuevos proyectos. A la Jail va uno a ayudar a sus compañeros a que empiecen nuevos proyectos.
|
JailDoc és un Jailer. Als Jailers els agrada començar projectes. A ningú li agrada acabar-los. Els Jailers viuen a la Jail. A la Jail s'hi va a començar projectes. A la Jail s'hi va a ensenyar els projectes. A la Jail s'hi va a aprendre com començar nous projectes. A la Jail s'hi va a ajudar els companys a començar nous projectes.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||

|
JailDoc és un Jailer destacat entre els Jailers. Té més projectes començats que ningú i és qui més ajuda als altres a iniciar els seus.
|
||||||
|
|
||||||
|
Però un dia, va passar una cosa inesperada. Algú va acabar un projecte. Algú va alliberar el *Puzzle Jail Facker*. Un autèntic desaprensiu.
|
||||||
|
|
||||||
JailDoc es un Jailer destacado entre los Jailers. Tiene más proyectos empezados que nadie y es el que más ayuda a que los demas empiecen los suyos.
|
Això va fer que JailDoc prenguera una decisió: acabaria i lliuraria un dels seus projectes. Però, quin? *JailBattle*? *Sigmasuá*? *Calculín Doom*? Quin dilema! Finalment, es va arromangar i va decidir acabar i lliurar **tots** els seus projectes inacabats. Ho aconseguirà?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
Un día, ocurrió algo. Alguien terminó un proyecto. Alguien liberó el *Puzzle Jail Facker*. Algún desaprensivo.
|
## Jugabilitat
|
||||||
|
|
||||||
|
Ajuda a JailDoc a recuperar les peces dels seus projectes, que estan escampades per qualsevol racó de l'Univers Jailer. Hi ha més de **150 peces** repartides en **60 pantalles**. Algunes són senzilles, però en altres hauràs de calcular molt bé els teus moviments si no vols acabar com un *arounder* més.
|
||||||
|
|
||||||
Esto hizo que JailDoc decidiera terminar y entregar uno de sus proyectos, pero, ¿cual? ¿JailBattle? ¿Sigmasuá? ¿Calculín Doom? Menudo dilema. JailDoc se arremangó y decidió finalizar y entregar todos sus proyectos inacabados. ¿Lo logrará?
|

|
||||||
|
|
||||||
|
Quan hages recuperat la major part de les peces, dirigeix-te a la Jail per mostrar als Jailers com es finalitza un projecte. Però compte! Bry no et deixarà entrar així com així. Només aquells que han creat un *Fire Effect* o un *Facedor de Tornejos* són dignes d'aquesta fita.
|
||||||
|
|
||||||
## Jugabilidad
|
---
|
||||||
|
|
||||||
Ayuda a JailDoc a recuperar las partes de su proyecto que estan desperdigadas por cualquier lugar del Universo Jailer. Hay mas de **150 piezas** desperdigadas por **60 pantallas**. Algunas son un paseo, pero en otras tendras que calcular muy bien tus movimientos si no quieres acabar como un arounder del montón.
|
## Controls
|
||||||
|
|
||||||
|
El joc permet tant l'ús del teclat com d'un comandament. Les tecles per a jugar són les següents:
|
||||||
|
|
||||||

|
- **Cursors**: Per moure's a l'esquerra o dreta i per saltar. Es poden modificar les tecles en el fitxer de configuració, triant entre aquestes opcions:
|
||||||
|
- O, P per moure's i Q per saltar.
|
||||||
|
- A, D per moure's i W per saltar.
|
||||||
|
|
||||||
|
- **Tecla M**: Activa o desactiva la música.
|
||||||
|
- **Tecla P**: Pausa el joc.
|
||||||
|
- **Tecla ESC**: Ix del joc si estàs jugant. Tanca el programa en qualsevol altra circumstància.
|
||||||
|
- **Tecla F1**: Disminueix la mida de la finestra.
|
||||||
|
- **Tecla F2**: Augmenta la mida de la finestra.
|
||||||
|
- **Tecla F3**: Alterna entre el mode de pantalla completa i el mode finestra.
|
||||||
|
- **Tecla F4**: Activa o desactiva els shaders
|
||||||
|
- **Tecla F5**: Canvia la paleta de colors del joc.
|
||||||
|
- **Tecla B**: Activa o desactiva el marge de colors en mode finestra.
|
||||||
|
|
||||||
Cuando consigas recuperar gran parte de las piezas desperdigadas, dirigete a la Jail a mostrar a los Jailers como se termina un proyecto. Ten en cuenta que Bry no te dejará entrar. Solo aquellos que han realizado un *Fire Effect* o un *Facedor de Tornejos* son dignos de tal privilegio.
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Controles
|
## Dades del programa
|
||||||
|
|
||||||
El juego permite tanto el uso del teclado como de un mando de control. Las teclas para manejar el juego son las siguientes:
|
El programa guarda automàticament la configuració del mode de vídeo i les estadístiques del joc a la teua carpeta personal del sistema. La ubicació d'aquesta carpeta depén del sistema operatiu que utilitzes:
|
||||||
|
|
||||||
|
- **Windows**: `C:\Users\<nom_d'usuari>\AppData\Roaming\jailgames\jaildoctors_dilemma`
|
||||||
|
- **MacOS**: `~/Library/Application Support/jailgames/jaildoctors_dilemma`
|
||||||
|
- **Linux**: `~/.jailgames/jaildoctors_dilemma`
|
||||||
|
|
||||||
- **Cursores**: Para mover a izquierda o derecha a JailDoc y para saltar. En el fichero de configuración se pueden cambiar las teclas por otras opciones prefijadas: O, P para moverse y Q para saltar o A, D para moverse y W para saltar.
|
Dins de la carpeta es troba el fitxer de configuració `config.txt`, on es pot modificar la configuració per connectar-se al servei en línia, i els fitxers `stats.csv` i `stats_buffer.csv`, que contenen informació sobre les estadístiques del joc.
|
||||||
|
|
||||||
- **Tecla M**: Activa o desactiva la música
|
---
|
||||||
|
|
||||||
- **Tecla P**: Pone en pausa el juego
|
## Agraïments
|
||||||
|
|
||||||
- **Tecla ESC**: Sale del juego si estas jugando. Sale del programa en cualquier otra circunstancia
|
Gràcies, com sempre, a tots els Jailers per motivar-me a crear aquest joc i per ajudar-me en els moments de dubte en escriure el codi. I, com sempre, un agraïment especial a JailDoc per la seua unitat de *Jail_Audio* i per qualsevol altre codi, ajuda o ensenyament que haja necessitat per a completar el programa.
|
||||||
|
|
||||||
- **Tecla F1**: Disminuye el tamaño de la ventana
|
Si no he perdut el compte, aquest és el quart joc que aconseguisc crear.
|
||||||
|
|
||||||
- **Tecla F2**: Aumenta el tamaño de la ventana
|
*13 de novembre de 2022, JailDesigner*
|
||||||
|
|
||||||
- **Tecla F3**: Cambia entre el modo de pantalla completa y el de ventana
|
|
||||||
|
|
||||||
- **Tecla F5**: Cambia la paleta de colores del juego
|
|
||||||
|
|
||||||
- **Tecla B**: Activa o desactiva el borde de colores de la pantalla cuando el programa se ejecuta en modo de ventana
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Datos del programa
|
|
||||||
El programa guarda automáticamente la configuración del modo de video y las estadísticas de juego en tu carpeta personal del sistema. Esta carpeta tiene una ubicación distinta en función del sistema operativo que utilices.
|
|
||||||
|
|
||||||
En **Windows** se encuentra en:
|
|
||||||
`C:\Users\<nombre_de_usuario>\AppData\Roaming\jailgames\jaildoctors_dilemma`
|
|
||||||
|
|
||||||
En **MacOS** se encuentra en:
|
|
||||||
`~/Library/Application Support/jailgames/jaildoctors_dilemma`
|
|
||||||
|
|
||||||
En **Linux** se encuentra en:
|
|
||||||
`~/./jailgames/jaildoctors_dilemma`
|
|
||||||
|
|
||||||
En la carpeta está el fichero de configuración `config.txt` donde se puede modificar la configuración para conectarse al servicio online y los ficheros `stats.csv` y `stats_buffer.csv` con información de las estadisticas de juego.
|
|
||||||
|
|
||||||
## Agradecimientos
|
|
||||||
|
|
||||||
Agradecimientos como siempre a todos los Jailers por motivarme a hacer el juego y ayudarme en los momentos de duda a la hora de escribir el código. Y, como siempre, en especial a JailDoc por su unidad de Jail_Audio y cualquier otro código/ayuda/enseñanzas que haya necesitado para terminar el programa.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Si no me he descontado, este es el cuarto juego que consigo crear.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*13 de noviembre de 2022, JailDesigner*
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=8
|
frame_height=8
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=8
|
frame_height=8
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=9
|
frame_width=9
|
||||||
frameHeight=7
|
frame_height=7
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=8
|
frame_height=8
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=24
|
frame_width=24
|
||||||
frameHeight=32
|
frame_height=32
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=10
|
frame_width=10
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=22
|
frame_width=22
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=7
|
frame_width=7
|
||||||
frameHeight=7
|
frame_height=7
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=13
|
frame_width=13
|
||||||
frameHeight=15
|
frame_height=15
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=11
|
frame_width=11
|
||||||
frameHeight=13
|
frame_height=13
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=32
|
frame_height=32
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=8
|
frame_height=8
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=43
|
frame_width=43
|
||||||
frameHeight=44
|
frame_height=44
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=79
|
frame_width=79
|
||||||
frameHeight=90
|
frame_height=90
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=62
|
frame_width=62
|
||||||
frameHeight=47
|
frame_height=47
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=64
|
frame_width=64
|
||||||
frameHeight=64
|
frame_height=64
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=8
|
frame_height=8
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=7
|
frame_width=7
|
||||||
frameHeight=8
|
frame_height=8
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=18
|
frame_height=18
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=24
|
frame_width=24
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=5
|
frame_width=5
|
||||||
frameHeight=8
|
frame_height=8
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=8
|
frame_height=8
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=16
|
frame_width=16
|
||||||
frameHeight=32
|
frame_height=32
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
BIN
data/font/8bithud.png
Normal file
BIN
data/font/8bithud.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
194
data/font/8bithud.txt
Normal file
194
data/font/8bithud.txt
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
# box width
|
||||||
|
8
|
||||||
|
# box height
|
||||||
|
8
|
||||||
|
# 32 espacio ( )
|
||||||
|
2
|
||||||
|
# 33 !
|
||||||
|
2
|
||||||
|
# 34 "
|
||||||
|
5
|
||||||
|
# 35 #
|
||||||
|
6
|
||||||
|
# 36 $
|
||||||
|
6
|
||||||
|
# 37 %
|
||||||
|
6
|
||||||
|
# 38 &
|
||||||
|
6
|
||||||
|
# 39 '
|
||||||
|
2
|
||||||
|
# 40 (
|
||||||
|
3
|
||||||
|
# 41 )
|
||||||
|
3
|
||||||
|
# 42 *
|
||||||
|
4
|
||||||
|
# 43 +
|
||||||
|
3
|
||||||
|
# 44 ,
|
||||||
|
2
|
||||||
|
# 45 -
|
||||||
|
3
|
||||||
|
# 46 .
|
||||||
|
2
|
||||||
|
# 47 /
|
||||||
|
4
|
||||||
|
# 48 0
|
||||||
|
6
|
||||||
|
# 49 1
|
||||||
|
6
|
||||||
|
# 50 2
|
||||||
|
6
|
||||||
|
# 51 3
|
||||||
|
6
|
||||||
|
# 52 4
|
||||||
|
6
|
||||||
|
# 53 5
|
||||||
|
6
|
||||||
|
# 54 6
|
||||||
|
6
|
||||||
|
# 55 7
|
||||||
|
6
|
||||||
|
# 56 8
|
||||||
|
6
|
||||||
|
# 57 9
|
||||||
|
6
|
||||||
|
# 58 :
|
||||||
|
2
|
||||||
|
# 59 ;
|
||||||
|
2
|
||||||
|
# 60 <
|
||||||
|
4
|
||||||
|
# 61 =
|
||||||
|
3
|
||||||
|
# 62 >
|
||||||
|
4
|
||||||
|
# 63 ?
|
||||||
|
6
|
||||||
|
# 64 @
|
||||||
|
8
|
||||||
|
# 65 A
|
||||||
|
6
|
||||||
|
# 66 B
|
||||||
|
6
|
||||||
|
# 67 C
|
||||||
|
6
|
||||||
|
# 68 D
|
||||||
|
6
|
||||||
|
# 69 E
|
||||||
|
6
|
||||||
|
# 70 F
|
||||||
|
6
|
||||||
|
# 71 G
|
||||||
|
6
|
||||||
|
# 72 H
|
||||||
|
6
|
||||||
|
# 73 I
|
||||||
|
6
|
||||||
|
# 74 J
|
||||||
|
6
|
||||||
|
# 75 K
|
||||||
|
6
|
||||||
|
# 76 L
|
||||||
|
6
|
||||||
|
# 77 M
|
||||||
|
6
|
||||||
|
# 78 N
|
||||||
|
6
|
||||||
|
# 79 O
|
||||||
|
6
|
||||||
|
# 80 P
|
||||||
|
6
|
||||||
|
# 81 Q
|
||||||
|
6
|
||||||
|
# 82 R
|
||||||
|
6
|
||||||
|
# 83 S
|
||||||
|
6
|
||||||
|
# 84 T
|
||||||
|
6
|
||||||
|
# 85 U
|
||||||
|
6
|
||||||
|
# 86 V
|
||||||
|
5
|
||||||
|
# 87 W
|
||||||
|
6
|
||||||
|
# 88 X
|
||||||
|
6
|
||||||
|
# 89 Y
|
||||||
|
6
|
||||||
|
# 90 Z
|
||||||
|
6
|
||||||
|
# 91 [
|
||||||
|
3
|
||||||
|
# 92 \
|
||||||
|
5
|
||||||
|
# 93 ]
|
||||||
|
3
|
||||||
|
# 94 ^
|
||||||
|
4
|
||||||
|
# 95 _
|
||||||
|
6
|
||||||
|
# 96 `
|
||||||
|
2
|
||||||
|
# 97 a
|
||||||
|
5
|
||||||
|
# 98 b
|
||||||
|
5
|
||||||
|
# 99 c
|
||||||
|
5
|
||||||
|
# 100 d
|
||||||
|
5
|
||||||
|
# 101 e
|
||||||
|
5
|
||||||
|
# 102 f
|
||||||
|
5
|
||||||
|
# 103 g
|
||||||
|
5
|
||||||
|
# 104 h
|
||||||
|
5
|
||||||
|
# 105 i
|
||||||
|
4
|
||||||
|
# 106 j
|
||||||
|
5
|
||||||
|
# 107 k
|
||||||
|
5
|
||||||
|
# 108 l
|
||||||
|
5
|
||||||
|
# 109 m
|
||||||
|
6
|
||||||
|
# 110 n
|
||||||
|
5
|
||||||
|
# 111 o
|
||||||
|
5
|
||||||
|
# 112 p
|
||||||
|
5
|
||||||
|
# 113 q
|
||||||
|
5
|
||||||
|
# 114 r
|
||||||
|
5
|
||||||
|
# 115 s
|
||||||
|
5
|
||||||
|
# 116 t
|
||||||
|
4
|
||||||
|
# 117 u
|
||||||
|
5
|
||||||
|
# 118 v
|
||||||
|
5
|
||||||
|
# 119 w
|
||||||
|
6
|
||||||
|
# 120 x
|
||||||
|
4
|
||||||
|
# 121 y
|
||||||
|
4
|
||||||
|
# 122 z
|
||||||
|
5
|
||||||
|
# 123 {
|
||||||
|
3
|
||||||
|
# 124 |
|
||||||
|
2
|
||||||
|
# 125 }
|
||||||
|
3
|
||||||
|
# 126 ~
|
||||||
|
3
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=stand
|
name=stand
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=8
|
frame_width=8
|
||||||
frameHeight=16
|
frame_height=16
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=stand
|
name=stand
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frameWidth=19
|
frame_width=19
|
||||||
frameHeight=18
|
frame_height=18
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=default
|
name=default
|
||||||
|
|||||||
234
data/shaders/crtpi_192.glsl
Normal file
234
data/shaders/crtpi_192.glsl
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
crt-pi - A Raspberry Pi friendly CRT shader.
|
||||||
|
|
||||||
|
Copyright (C) 2015-2016 davej
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
This shader is designed to work well on Raspberry Pi GPUs (i.e. 1080P @ 60Hz on a game with a 4:3 aspect ratio). It pushes the Pi's GPU hard and enabling some features will slow it down so that it is no longer able to match 1080P @ 60Hz. You will need to overclock your Pi to the fastest setting in raspi-config to get the best results from this shader: 'Pi2' for Pi2 and 'Turbo' for original Pi and Pi Zero. Note: Pi2s are slower at running the shader than other Pis, this seems to be down to Pi2s lower maximum memory speed. Pi2s don't quite manage 1080P @ 60Hz - they drop about 1 in 1000 frames. You probably won't notice this, but if you do, try enabling FAKE_GAMMA.
|
||||||
|
|
||||||
|
SCANLINES enables scanlines. You'll almost certainly want to use it with MULTISAMPLE to reduce moire effects. SCANLINE_WEIGHT defines how wide scanlines are (it is an inverse value so a higher number = thinner lines). SCANLINE_GAP_BRIGHTNESS defines how dark the gaps between the scan lines are. Darker gaps between scan lines make moire effects more likely.
|
||||||
|
|
||||||
|
GAMMA enables gamma correction using the values in INPUT_GAMMA and OUTPUT_GAMMA. FAKE_GAMMA causes it to ignore the values in INPUT_GAMMA and OUTPUT_GAMMA and approximate gamma correction in a way which is faster than true gamma whilst still looking better than having none. You must have GAMMA defined to enable FAKE_GAMMA.
|
||||||
|
|
||||||
|
CURVATURE distorts the screen by CURVATURE_X and CURVATURE_Y. Curvature slows things down a lot.
|
||||||
|
|
||||||
|
By default the shader uses linear blending horizontally. If you find this too blury, enable SHARPER.
|
||||||
|
|
||||||
|
BLOOM_FACTOR controls the increase in width for bright scanlines.
|
||||||
|
|
||||||
|
MASK_TYPE defines what, if any, shadow mask to use. MASK_BRIGHTNESS defines how much the mask type darkens the screen.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma parameter CURVATURE_X "Screen curvature - horizontal" 0.10 0.0 1.0 0.01
|
||||||
|
#pragma parameter CURVATURE_Y "Screen curvature - vertical" 0.15 0.0 1.0 0.01
|
||||||
|
#pragma parameter MASK_BRIGHTNESS "Mask brightness" 0.70 0.0 1.0 0.01
|
||||||
|
#pragma parameter SCANLINE_WEIGHT "Scanline weight" 6.0 0.0 15.0 0.1
|
||||||
|
#pragma parameter SCANLINE_GAP_BRIGHTNESS "Scanline gap brightness" 0.12 0.0 1.0 0.01
|
||||||
|
#pragma parameter BLOOM_FACTOR "Bloom factor" 1.5 0.0 5.0 0.01
|
||||||
|
#pragma parameter INPUT_GAMMA "Input gamma" 2.4 0.0 5.0 0.01
|
||||||
|
#pragma parameter OUTPUT_GAMMA "Output gamma" 2.2 0.0 5.0 0.01
|
||||||
|
|
||||||
|
// Haven't put these as parameters as it would slow the code down.
|
||||||
|
#define SCANLINES
|
||||||
|
#define MULTISAMPLE
|
||||||
|
#define GAMMA
|
||||||
|
//#define FAKE_GAMMA
|
||||||
|
//#define CURVATURE
|
||||||
|
//#define SHARPER
|
||||||
|
// MASK_TYPE: 0 = none, 1 = green/magenta, 2 = trinitron(ish)
|
||||||
|
#define MASK_TYPE 2
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GL_ES
|
||||||
|
#define COMPAT_PRECISION mediump
|
||||||
|
precision mediump float;
|
||||||
|
#else
|
||||||
|
#define COMPAT_PRECISION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PARAMETER_UNIFORM
|
||||||
|
uniform COMPAT_PRECISION float CURVATURE_X;
|
||||||
|
uniform COMPAT_PRECISION float CURVATURE_Y;
|
||||||
|
uniform COMPAT_PRECISION float MASK_BRIGHTNESS;
|
||||||
|
uniform COMPAT_PRECISION float SCANLINE_WEIGHT;
|
||||||
|
uniform COMPAT_PRECISION float SCANLINE_GAP_BRIGHTNESS;
|
||||||
|
uniform COMPAT_PRECISION float BLOOM_FACTOR;
|
||||||
|
uniform COMPAT_PRECISION float INPUT_GAMMA;
|
||||||
|
uniform COMPAT_PRECISION float OUTPUT_GAMMA;
|
||||||
|
#else
|
||||||
|
#define CURVATURE_X 0.05
|
||||||
|
#define CURVATURE_Y 0.1
|
||||||
|
#define MASK_BRIGHTNESS 0.80
|
||||||
|
#define SCANLINE_WEIGHT 6.0
|
||||||
|
#define SCANLINE_GAP_BRIGHTNESS 0.12
|
||||||
|
#define BLOOM_FACTOR 3.5
|
||||||
|
#define INPUT_GAMMA 2.4
|
||||||
|
#define OUTPUT_GAMMA 2.2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* COMPATIBILITY
|
||||||
|
- GLSL compilers
|
||||||
|
*/
|
||||||
|
|
||||||
|
//uniform vec2 TextureSize;
|
||||||
|
#if defined(CURVATURE)
|
||||||
|
varying vec2 screenScale;
|
||||||
|
#endif
|
||||||
|
varying vec2 TEX0;
|
||||||
|
varying float filterWidth;
|
||||||
|
|
||||||
|
#if defined(VERTEX)
|
||||||
|
//uniform mat4 MVPMatrix;
|
||||||
|
//attribute vec4 VertexCoord;
|
||||||
|
//attribute vec2 TexCoord;
|
||||||
|
//uniform vec2 InputSize;
|
||||||
|
//uniform vec2 OutputSize;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
#if defined(CURVATURE)
|
||||||
|
screenScale = vec2(1.0, 1.0); //TextureSize / InputSize;
|
||||||
|
#endif
|
||||||
|
filterWidth = (768.0 / 192.0) / 3.0;
|
||||||
|
TEX0 = vec2(gl_MultiTexCoord0.x, 1.0-gl_MultiTexCoord0.y)*1.0001;
|
||||||
|
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||||
|
}
|
||||||
|
#elif defined(FRAGMENT)
|
||||||
|
|
||||||
|
uniform sampler2D Texture;
|
||||||
|
|
||||||
|
#if defined(CURVATURE)
|
||||||
|
vec2 Distort(vec2 coord)
|
||||||
|
{
|
||||||
|
vec2 CURVATURE_DISTORTION = vec2(CURVATURE_X, CURVATURE_Y);
|
||||||
|
// Barrel distortion shrinks the display area a bit, this will allow us to counteract that.
|
||||||
|
vec2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION);
|
||||||
|
coord *= screenScale;
|
||||||
|
coord -= vec2(0.5);
|
||||||
|
float rsq = coord.x * coord.x + coord.y * coord.y;
|
||||||
|
coord += coord * (CURVATURE_DISTORTION * rsq);
|
||||||
|
coord *= barrelScale;
|
||||||
|
if (abs(coord.x) >= 0.5 || abs(coord.y) >= 0.5)
|
||||||
|
coord = vec2(-1.0); // If out of bounds, return an invalid value.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
coord += vec2(0.5);
|
||||||
|
coord /= screenScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
return coord;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float CalcScanLineWeight(float dist)
|
||||||
|
{
|
||||||
|
return max(1.0-dist*dist*SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
float CalcScanLine(float dy)
|
||||||
|
{
|
||||||
|
float scanLineWeight = CalcScanLineWeight(dy);
|
||||||
|
#if defined(MULTISAMPLE)
|
||||||
|
scanLineWeight += CalcScanLineWeight(dy-filterWidth);
|
||||||
|
scanLineWeight += CalcScanLineWeight(dy+filterWidth);
|
||||||
|
scanLineWeight *= 0.3333333;
|
||||||
|
#endif
|
||||||
|
return scanLineWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 TextureSize = vec2(256.0, 192.0);
|
||||||
|
#if defined(CURVATURE)
|
||||||
|
vec2 texcoord = Distort(TEX0);
|
||||||
|
if (texcoord.x < 0.0)
|
||||||
|
gl_FragColor = vec4(0.0);
|
||||||
|
else
|
||||||
|
#else
|
||||||
|
vec2 texcoord = TEX0;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
vec2 texcoordInPixels = texcoord * TextureSize;
|
||||||
|
#if defined(SHARPER)
|
||||||
|
vec2 tempCoord = floor(texcoordInPixels) + 0.5;
|
||||||
|
vec2 coord = tempCoord / TextureSize;
|
||||||
|
vec2 deltas = texcoordInPixels - tempCoord;
|
||||||
|
float scanLineWeight = CalcScanLine(deltas.y);
|
||||||
|
vec2 signs = sign(deltas);
|
||||||
|
deltas.x *= 2.0;
|
||||||
|
deltas = deltas * deltas;
|
||||||
|
deltas.y = deltas.y * deltas.y;
|
||||||
|
deltas.x *= 0.5;
|
||||||
|
deltas.y *= 8.0;
|
||||||
|
deltas /= TextureSize;
|
||||||
|
deltas *= signs;
|
||||||
|
vec2 tc = coord + deltas;
|
||||||
|
#else
|
||||||
|
float tempY = floor(texcoordInPixels.y) + 0.5;
|
||||||
|
float yCoord = tempY / TextureSize.y;
|
||||||
|
float dy = texcoordInPixels.y - tempY;
|
||||||
|
float scanLineWeight = CalcScanLine(dy);
|
||||||
|
float signY = sign(dy);
|
||||||
|
dy = dy * dy;
|
||||||
|
dy = dy * dy;
|
||||||
|
dy *= 8.0;
|
||||||
|
dy /= TextureSize.y;
|
||||||
|
dy *= signY;
|
||||||
|
vec2 tc = vec2(texcoord.x, yCoord + dy);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec3 colour = texture2D(Texture, tc).rgb;
|
||||||
|
|
||||||
|
#if defined(SCANLINES)
|
||||||
|
#if defined(GAMMA)
|
||||||
|
#if defined(FAKE_GAMMA)
|
||||||
|
colour = colour * colour;
|
||||||
|
#else
|
||||||
|
colour = pow(colour, vec3(INPUT_GAMMA));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
scanLineWeight *= BLOOM_FACTOR;
|
||||||
|
colour *= scanLineWeight;
|
||||||
|
|
||||||
|
#if defined(GAMMA)
|
||||||
|
#if defined(FAKE_GAMMA)
|
||||||
|
colour = sqrt(colour);
|
||||||
|
#else
|
||||||
|
colour = pow(colour, vec3(1.0/OUTPUT_GAMMA));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if MASK_TYPE == 0
|
||||||
|
gl_FragColor = vec4(colour, 1.0);
|
||||||
|
#else
|
||||||
|
#if MASK_TYPE == 1
|
||||||
|
float whichMask = fract((gl_FragCoord.x*1.0001) * 0.5);
|
||||||
|
vec3 mask;
|
||||||
|
if (whichMask < 0.5)
|
||||||
|
mask = vec3(MASK_BRIGHTNESS, 1.0, MASK_BRIGHTNESS);
|
||||||
|
else
|
||||||
|
mask = vec3(1.0, MASK_BRIGHTNESS, 1.0);
|
||||||
|
#elif MASK_TYPE == 2
|
||||||
|
float whichMask = fract((gl_FragCoord.x*1.0001) * 0.3333333);
|
||||||
|
vec3 mask = vec3(MASK_BRIGHTNESS, MASK_BRIGHTNESS, MASK_BRIGHTNESS);
|
||||||
|
if (whichMask < 0.3333333)
|
||||||
|
mask.x = 1.0;
|
||||||
|
else if (whichMask < 0.6666666)
|
||||||
|
mask.y = 1.0;
|
||||||
|
else
|
||||||
|
mask.z = 1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gl_FragColor = vec4(colour * mask, 1.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
234
data/shaders/crtpi_240.glsl
Normal file
234
data/shaders/crtpi_240.glsl
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
crt-pi - A Raspberry Pi friendly CRT shader.
|
||||||
|
|
||||||
|
Copyright (C) 2015-2016 davej
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
This shader is designed to work well on Raspberry Pi GPUs (i.e. 1080P @ 60Hz on a game with a 4:3 aspect ratio). It pushes the Pi's GPU hard and enabling some features will slow it down so that it is no longer able to match 1080P @ 60Hz. You will need to overclock your Pi to the fastest setting in raspi-config to get the best results from this shader: 'Pi2' for Pi2 and 'Turbo' for original Pi and Pi Zero. Note: Pi2s are slower at running the shader than other Pis, this seems to be down to Pi2s lower maximum memory speed. Pi2s don't quite manage 1080P @ 60Hz - they drop about 1 in 1000 frames. You probably won't notice this, but if you do, try enabling FAKE_GAMMA.
|
||||||
|
|
||||||
|
SCANLINES enables scanlines. You'll almost certainly want to use it with MULTISAMPLE to reduce moire effects. SCANLINE_WEIGHT defines how wide scanlines are (it is an inverse value so a higher number = thinner lines). SCANLINE_GAP_BRIGHTNESS defines how dark the gaps between the scan lines are. Darker gaps between scan lines make moire effects more likely.
|
||||||
|
|
||||||
|
GAMMA enables gamma correction using the values in INPUT_GAMMA and OUTPUT_GAMMA. FAKE_GAMMA causes it to ignore the values in INPUT_GAMMA and OUTPUT_GAMMA and approximate gamma correction in a way which is faster than true gamma whilst still looking better than having none. You must have GAMMA defined to enable FAKE_GAMMA.
|
||||||
|
|
||||||
|
CURVATURE distorts the screen by CURVATURE_X and CURVATURE_Y. Curvature slows things down a lot.
|
||||||
|
|
||||||
|
By default the shader uses linear blending horizontally. If you find this too blury, enable SHARPER.
|
||||||
|
|
||||||
|
BLOOM_FACTOR controls the increase in width for bright scanlines.
|
||||||
|
|
||||||
|
MASK_TYPE defines what, if any, shadow mask to use. MASK_BRIGHTNESS defines how much the mask type darkens the screen.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma parameter CURVATURE_X "Screen curvature - horizontal" 0.10 0.0 1.0 0.01
|
||||||
|
#pragma parameter CURVATURE_Y "Screen curvature - vertical" 0.15 0.0 1.0 0.01
|
||||||
|
#pragma parameter MASK_BRIGHTNESS "Mask brightness" 0.70 0.0 1.0 0.01
|
||||||
|
#pragma parameter SCANLINE_WEIGHT "Scanline weight" 6.0 0.0 15.0 0.1
|
||||||
|
#pragma parameter SCANLINE_GAP_BRIGHTNESS "Scanline gap brightness" 0.12 0.0 1.0 0.01
|
||||||
|
#pragma parameter BLOOM_FACTOR "Bloom factor" 1.5 0.0 5.0 0.01
|
||||||
|
#pragma parameter INPUT_GAMMA "Input gamma" 2.4 0.0 5.0 0.01
|
||||||
|
#pragma parameter OUTPUT_GAMMA "Output gamma" 2.2 0.0 5.0 0.01
|
||||||
|
|
||||||
|
// Haven't put these as parameters as it would slow the code down.
|
||||||
|
#define SCANLINES
|
||||||
|
#define MULTISAMPLE
|
||||||
|
#define GAMMA
|
||||||
|
//#define FAKE_GAMMA
|
||||||
|
//#define CURVATURE
|
||||||
|
//#define SHARPER
|
||||||
|
// MASK_TYPE: 0 = none, 1 = green/magenta, 2 = trinitron(ish)
|
||||||
|
#define MASK_TYPE 2
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GL_ES
|
||||||
|
#define COMPAT_PRECISION mediump
|
||||||
|
precision mediump float;
|
||||||
|
#else
|
||||||
|
#define COMPAT_PRECISION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PARAMETER_UNIFORM
|
||||||
|
uniform COMPAT_PRECISION float CURVATURE_X;
|
||||||
|
uniform COMPAT_PRECISION float CURVATURE_Y;
|
||||||
|
uniform COMPAT_PRECISION float MASK_BRIGHTNESS;
|
||||||
|
uniform COMPAT_PRECISION float SCANLINE_WEIGHT;
|
||||||
|
uniform COMPAT_PRECISION float SCANLINE_GAP_BRIGHTNESS;
|
||||||
|
uniform COMPAT_PRECISION float BLOOM_FACTOR;
|
||||||
|
uniform COMPAT_PRECISION float INPUT_GAMMA;
|
||||||
|
uniform COMPAT_PRECISION float OUTPUT_GAMMA;
|
||||||
|
#else
|
||||||
|
#define CURVATURE_X 0.05
|
||||||
|
#define CURVATURE_Y 0.1
|
||||||
|
#define MASK_BRIGHTNESS 0.80
|
||||||
|
#define SCANLINE_WEIGHT 6.0
|
||||||
|
#define SCANLINE_GAP_BRIGHTNESS 0.12
|
||||||
|
#define BLOOM_FACTOR 3.5
|
||||||
|
#define INPUT_GAMMA 2.4
|
||||||
|
#define OUTPUT_GAMMA 2.2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* COMPATIBILITY
|
||||||
|
- GLSL compilers
|
||||||
|
*/
|
||||||
|
|
||||||
|
//uniform vec2 TextureSize;
|
||||||
|
#if defined(CURVATURE)
|
||||||
|
varying vec2 screenScale;
|
||||||
|
#endif
|
||||||
|
varying vec2 TEX0;
|
||||||
|
varying float filterWidth;
|
||||||
|
|
||||||
|
#if defined(VERTEX)
|
||||||
|
//uniform mat4 MVPMatrix;
|
||||||
|
//attribute vec4 VertexCoord;
|
||||||
|
//attribute vec2 TexCoord;
|
||||||
|
//uniform vec2 InputSize;
|
||||||
|
//uniform vec2 OutputSize;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
#if defined(CURVATURE)
|
||||||
|
screenScale = vec2(1.0, 1.0); //TextureSize / InputSize;
|
||||||
|
#endif
|
||||||
|
filterWidth = (768.0 / 240.0) / 3.0;
|
||||||
|
TEX0 = vec2(gl_MultiTexCoord0.x, 1.0-gl_MultiTexCoord0.y)*1.0001;
|
||||||
|
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||||
|
}
|
||||||
|
#elif defined(FRAGMENT)
|
||||||
|
|
||||||
|
uniform sampler2D Texture;
|
||||||
|
|
||||||
|
#if defined(CURVATURE)
|
||||||
|
vec2 Distort(vec2 coord)
|
||||||
|
{
|
||||||
|
vec2 CURVATURE_DISTORTION = vec2(CURVATURE_X, CURVATURE_Y);
|
||||||
|
// Barrel distortion shrinks the display area a bit, this will allow us to counteract that.
|
||||||
|
vec2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION);
|
||||||
|
coord *= screenScale;
|
||||||
|
coord -= vec2(0.5);
|
||||||
|
float rsq = coord.x * coord.x + coord.y * coord.y;
|
||||||
|
coord += coord * (CURVATURE_DISTORTION * rsq);
|
||||||
|
coord *= barrelScale;
|
||||||
|
if (abs(coord.x) >= 0.5 || abs(coord.y) >= 0.5)
|
||||||
|
coord = vec2(-1.0); // If out of bounds, return an invalid value.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
coord += vec2(0.5);
|
||||||
|
coord /= screenScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
return coord;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float CalcScanLineWeight(float dist)
|
||||||
|
{
|
||||||
|
return max(1.0-dist*dist*SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
float CalcScanLine(float dy)
|
||||||
|
{
|
||||||
|
float scanLineWeight = CalcScanLineWeight(dy);
|
||||||
|
#if defined(MULTISAMPLE)
|
||||||
|
scanLineWeight += CalcScanLineWeight(dy-filterWidth);
|
||||||
|
scanLineWeight += CalcScanLineWeight(dy+filterWidth);
|
||||||
|
scanLineWeight *= 0.3333333;
|
||||||
|
#endif
|
||||||
|
return scanLineWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 TextureSize = vec2(320.0, 240.0);
|
||||||
|
#if defined(CURVATURE)
|
||||||
|
vec2 texcoord = Distort(TEX0);
|
||||||
|
if (texcoord.x < 0.0)
|
||||||
|
gl_FragColor = vec4(0.0);
|
||||||
|
else
|
||||||
|
#else
|
||||||
|
vec2 texcoord = TEX0;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
vec2 texcoordInPixels = texcoord * TextureSize;
|
||||||
|
#if defined(SHARPER)
|
||||||
|
vec2 tempCoord = floor(texcoordInPixels) + 0.5;
|
||||||
|
vec2 coord = tempCoord / TextureSize;
|
||||||
|
vec2 deltas = texcoordInPixels - tempCoord;
|
||||||
|
float scanLineWeight = CalcScanLine(deltas.y);
|
||||||
|
vec2 signs = sign(deltas);
|
||||||
|
deltas.x *= 2.0;
|
||||||
|
deltas = deltas * deltas;
|
||||||
|
deltas.y = deltas.y * deltas.y;
|
||||||
|
deltas.x *= 0.5;
|
||||||
|
deltas.y *= 8.0;
|
||||||
|
deltas /= TextureSize;
|
||||||
|
deltas *= signs;
|
||||||
|
vec2 tc = coord + deltas;
|
||||||
|
#else
|
||||||
|
float tempY = floor(texcoordInPixels.y) + 0.5;
|
||||||
|
float yCoord = tempY / TextureSize.y;
|
||||||
|
float dy = texcoordInPixels.y - tempY;
|
||||||
|
float scanLineWeight = CalcScanLine(dy);
|
||||||
|
float signY = sign(dy);
|
||||||
|
dy = dy * dy;
|
||||||
|
dy = dy * dy;
|
||||||
|
dy *= 8.0;
|
||||||
|
dy /= TextureSize.y;
|
||||||
|
dy *= signY;
|
||||||
|
vec2 tc = vec2(texcoord.x, yCoord + dy);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec3 colour = texture2D(Texture, tc).rgb;
|
||||||
|
|
||||||
|
#if defined(SCANLINES)
|
||||||
|
#if defined(GAMMA)
|
||||||
|
#if defined(FAKE_GAMMA)
|
||||||
|
colour = colour * colour;
|
||||||
|
#else
|
||||||
|
colour = pow(colour, vec3(INPUT_GAMMA));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
scanLineWeight *= BLOOM_FACTOR;
|
||||||
|
colour *= scanLineWeight;
|
||||||
|
|
||||||
|
#if defined(GAMMA)
|
||||||
|
#if defined(FAKE_GAMMA)
|
||||||
|
colour = sqrt(colour);
|
||||||
|
#else
|
||||||
|
colour = pow(colour, vec3(1.0/OUTPUT_GAMMA));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if MASK_TYPE == 0
|
||||||
|
gl_FragColor = vec4(colour, 1.0);
|
||||||
|
#else
|
||||||
|
#if MASK_TYPE == 1
|
||||||
|
float whichMask = fract((gl_FragCoord.x*1.0001) * 0.5);
|
||||||
|
vec3 mask;
|
||||||
|
if (whichMask < 0.5)
|
||||||
|
mask = vec3(MASK_BRIGHTNESS, 1.0, MASK_BRIGHTNESS);
|
||||||
|
else
|
||||||
|
mask = vec3(1.0, MASK_BRIGHTNESS, 1.0);
|
||||||
|
#elif MASK_TYPE == 2
|
||||||
|
float whichMask = fract((gl_FragCoord.x*1.0001) * 0.3333333);
|
||||||
|
vec3 mask = vec3(MASK_BRIGHTNESS, MASK_BRIGHTNESS, MASK_BRIGHTNESS);
|
||||||
|
if (whichMask < 0.3333333)
|
||||||
|
mask.x = 1.0;
|
||||||
|
else if (whichMask < 0.6666666)
|
||||||
|
mask.y = 1.0;
|
||||||
|
else
|
||||||
|
mask.z = 1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gl_FragColor = vec4(colour * mask, 1.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
BIN
data/test.gif
Normal file
BIN
data/test.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 630 B |
@@ -23,11 +23,11 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.08</string>
|
<string>1.09</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.08</string>
|
<string>1.09</string>
|
||||||
<key>CSResourcesFileMapped</key>
|
<key>CSResourcesFileMapped</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
|||||||
269
source/animated_sprite.cpp
Normal file
269
source/animated_sprite.cpp
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
#include "animated_sprite.h"
|
||||||
|
#include <stddef.h> // Para size_t
|
||||||
|
#include <fstream> // Para basic_ostream, basic_istream, operator<<, basic...
|
||||||
|
#include <iostream> // Para cout, cerr
|
||||||
|
#include <sstream> // Para basic_stringstream
|
||||||
|
#include <stdexcept> // Para runtime_error
|
||||||
|
#include "texture.h" // Para Texture
|
||||||
|
#include "utils.h" // Para printWithDots
|
||||||
|
|
||||||
|
// Carga las animaciones en un vector(Animations) desde un fichero
|
||||||
|
Animations loadAnimationsFromFile(const std::string &file_path)
|
||||||
|
{
|
||||||
|
std::ifstream file(file_path);
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
std::cerr << "Error: Fichero no encontrado " << file_path << std::endl;
|
||||||
|
throw std::runtime_error("Fichero no encontrado: " + file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
printWithDots("Animation : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]");
|
||||||
|
|
||||||
|
std::vector<std::string> buffer;
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(file, line))
|
||||||
|
{
|
||||||
|
if (!line.empty())
|
||||||
|
buffer.push_back(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path)
|
||||||
|
: MovingSprite(texture)
|
||||||
|
{
|
||||||
|
// Carga las animaciones
|
||||||
|
if (!file_path.empty())
|
||||||
|
{
|
||||||
|
Animations v = loadAnimationsFromFile(file_path);
|
||||||
|
setAnimations(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const Animations &animations)
|
||||||
|
: MovingSprite(texture)
|
||||||
|
{
|
||||||
|
if (!animations.empty())
|
||||||
|
{
|
||||||
|
setAnimations(animations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtiene el indice de la animación a partir del nombre
|
||||||
|
int AnimatedSprite::getIndex(const std::string &name)
|
||||||
|
{
|
||||||
|
auto index = -1;
|
||||||
|
|
||||||
|
for (const auto &a : animations_)
|
||||||
|
{
|
||||||
|
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 (animations_[current_animation_].speed == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcula el frame actual a partir del contador
|
||||||
|
animations_[current_animation_].current_frame = animations_[current_animation_].counter / animations_[current_animation_].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 (animations_[current_animation_].current_frame >= static_cast<int>(animations_[current_animation_].frames.size()))
|
||||||
|
{
|
||||||
|
if (animations_[current_animation_].loop == -1)
|
||||||
|
{ // Si no hay loop, deja el último frame
|
||||||
|
animations_[current_animation_].current_frame = animations_[current_animation_].frames.size();
|
||||||
|
animations_[current_animation_].completed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Si hay loop, vuelve al frame indicado
|
||||||
|
animations_[current_animation_].counter = 0;
|
||||||
|
animations_[current_animation_].current_frame = animations_[current_animation_].loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// En caso contrario
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Escoge el frame correspondiente de la animación
|
||||||
|
setClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
|
||||||
|
|
||||||
|
// Incrementa el contador de la animacion
|
||||||
|
animations_[current_animation_].counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba si ha terminado la animación
|
||||||
|
bool AnimatedSprite::animationIsCompleted()
|
||||||
|
{
|
||||||
|
return animations_[current_animation_].completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establece la animacion actual
|
||||||
|
void AnimatedSprite::setCurrentAnimation(const std::string &name)
|
||||||
|
{
|
||||||
|
const auto new_animation = getIndex(name);
|
||||||
|
if (current_animation_ != new_animation)
|
||||||
|
{
|
||||||
|
current_animation_ = new_animation;
|
||||||
|
animations_[current_animation_].current_frame = 0;
|
||||||
|
animations_[current_animation_].counter = 0;
|
||||||
|
animations_[current_animation_].completed = false;
|
||||||
|
setClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establece la animacion actual
|
||||||
|
void AnimatedSprite::setCurrentAnimation(int index)
|
||||||
|
{
|
||||||
|
const auto new_animation = index;
|
||||||
|
if (current_animation_ != new_animation)
|
||||||
|
{
|
||||||
|
current_animation_ = new_animation;
|
||||||
|
animations_[current_animation_].current_frame = 0;
|
||||||
|
animations_[current_animation_].counter = 0;
|
||||||
|
animations_[current_animation_].completed = false;
|
||||||
|
setClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza las variables del objeto
|
||||||
|
void AnimatedSprite::update()
|
||||||
|
{
|
||||||
|
animate();
|
||||||
|
MovingSprite::update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reinicia la animación
|
||||||
|
void AnimatedSprite::resetAnimation()
|
||||||
|
{
|
||||||
|
animations_[current_animation_].current_frame = 0;
|
||||||
|
animations_[current_animation_].counter = 0;
|
||||||
|
animations_[current_animation_].completed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Carga la animación desde un vector de cadenas
|
||||||
|
void AnimatedSprite::setAnimations(const Animations &animations)
|
||||||
|
{
|
||||||
|
int frame_width = 1;
|
||||||
|
int frame_height = 1;
|
||||||
|
int frames_per_row = 1;
|
||||||
|
int max_tiles = 1;
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
while (index < animations.size())
|
||||||
|
{
|
||||||
|
std::string line = animations.at(index);
|
||||||
|
|
||||||
|
// Parsea el fichero para buscar variables y valores
|
||||||
|
if (line != "[animation]")
|
||||||
|
{
|
||||||
|
// Encuentra la posición del caracter '='
|
||||||
|
size_t pos = line.find("=");
|
||||||
|
|
||||||
|
// Procesa las dos subcadenas
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string key = line.substr(0, pos);
|
||||||
|
int value = std::stoi(line.substr(pos + 1));
|
||||||
|
if (key == "frame_width")
|
||||||
|
frame_width = value;
|
||||||
|
else if (key == "frame_height")
|
||||||
|
frame_height = value;
|
||||||
|
else
|
||||||
|
std::cout << "Warning: unknown parameter " << key << std::endl;
|
||||||
|
|
||||||
|
frames_per_row = texture_->getWidth() / frame_width;
|
||||||
|
const int w = texture_->getWidth() / frame_width;
|
||||||
|
const int h = texture_->getHeight() / frame_height;
|
||||||
|
max_tiles = w * h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
|
||||||
|
if (line == "[animation]")
|
||||||
|
{
|
||||||
|
AnimationData animation;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
line = animations.at(index);
|
||||||
|
size_t pos = line.find("=");
|
||||||
|
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string key = line.substr(0, pos);
|
||||||
|
std::string value = line.substr(pos + 1);
|
||||||
|
|
||||||
|
if (key == "name")
|
||||||
|
animation.name = value;
|
||||||
|
else if (key == "speed")
|
||||||
|
animation.speed = std::stoi(value);
|
||||||
|
else if (key == "loop")
|
||||||
|
animation.loop = std::stoi(value);
|
||||||
|
else if (key == "frames")
|
||||||
|
{
|
||||||
|
// Se introducen los valores separados por comas en un vector
|
||||||
|
std::stringstream ss(value);
|
||||||
|
std::string tmp;
|
||||||
|
SDL_Rect rect = {0, 0, frame_width, frame_height};
|
||||||
|
while (getline(ss, tmp, ','))
|
||||||
|
{
|
||||||
|
// Comprueba que el tile no sea mayor que el maximo indice permitido
|
||||||
|
const int num_tile = std::stoi(tmp);
|
||||||
|
if (num_tile <= max_tiles)
|
||||||
|
{
|
||||||
|
rect.x = (num_tile % frames_per_row) * frame_width;
|
||||||
|
rect.y = (num_tile / frames_per_row) * frame_height;
|
||||||
|
animation.frames.emplace_back(rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
std::cout << "Warning: unknown parameter " << key << std::endl;
|
||||||
|
}
|
||||||
|
} while (line != "[/animation]");
|
||||||
|
|
||||||
|
// Añade la animación al vector de animaciones
|
||||||
|
animations_.emplace_back(animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Una vez procesada la linea, aumenta el indice para pasar a la siguiente
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pone un valor por defecto
|
||||||
|
setWidth(frame_width);
|
||||||
|
setHeight(frame_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establece el frame actual de la animación
|
||||||
|
void AnimatedSprite::setCurrentAnimationFrame(int num)
|
||||||
|
{
|
||||||
|
// Descarta valores fuera de rango
|
||||||
|
if (num < 0 || num >= static_cast<int>(animations_[current_animation_].frames.size()))
|
||||||
|
{
|
||||||
|
num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cambia el valor de la variable
|
||||||
|
animations_[current_animation_].current_frame = num;
|
||||||
|
animations_[current_animation_].counter = 0;
|
||||||
|
|
||||||
|
// Escoge el frame correspondiente de la animación
|
||||||
|
setClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
|
||||||
|
}
|
||||||
72
source/animated_sprite.h
Normal file
72
source/animated_sprite.h
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL_rect.h> // Para SDL_Rect
|
||||||
|
#include <memory> // Para shared_ptr
|
||||||
|
#include <string> // Para string
|
||||||
|
#include <vector> // Para vector
|
||||||
|
#include "moving_sprite.h" // Para MovingSprite
|
||||||
|
class Texture; // lines 9-9
|
||||||
|
|
||||||
|
struct AnimationData
|
||||||
|
{
|
||||||
|
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 current_frame; // Frame actual
|
||||||
|
int counter; // Contador para las animaciones
|
||||||
|
|
||||||
|
AnimationData() : name(std::string()), speed(5), loop(0), completed(false), current_frame(0), counter(0) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
using Animations = std::vector<std::string>;
|
||||||
|
|
||||||
|
// Carga las animaciones en un vector(Animations) desde un fichero
|
||||||
|
Animations loadAnimationsFromFile(const std::string &file_path);
|
||||||
|
|
||||||
|
class AnimatedSprite : public MovingSprite
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
// Variables
|
||||||
|
std::vector<AnimationData> animations_; // Vector con las diferentes animaciones
|
||||||
|
int current_animation_ = 0; // Animacion activa
|
||||||
|
|
||||||
|
// Calcula el frame correspondiente a la animación actual
|
||||||
|
void animate();
|
||||||
|
|
||||||
|
// Carga la animación desde un vector de cadenas
|
||||||
|
void setAnimations(const Animations &animations);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path);
|
||||||
|
AnimatedSprite(std::shared_ptr<Texture> texture, const Animations &animations);
|
||||||
|
explicit AnimatedSprite(std::shared_ptr<Texture> texture)
|
||||||
|
: MovingSprite(texture) {}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
virtual ~AnimatedSprite() = default;
|
||||||
|
|
||||||
|
// Actualiza las variables del objeto
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
// Comprueba si ha terminado la animación
|
||||||
|
bool animationIsCompleted();
|
||||||
|
|
||||||
|
// Obtiene el indice de la animación a partir del nombre
|
||||||
|
int getIndex(const std::string &name);
|
||||||
|
|
||||||
|
// Establece la animacion actual
|
||||||
|
void setCurrentAnimation(const std::string &name = "default");
|
||||||
|
void setCurrentAnimation(int index = 0);
|
||||||
|
|
||||||
|
// Reinicia la animación
|
||||||
|
void resetAnimation();
|
||||||
|
|
||||||
|
// Establece el frame actual de la animación
|
||||||
|
void setCurrentAnimationFrame(int num);
|
||||||
|
|
||||||
|
// Obtiene el numero de frames de la animación actual
|
||||||
|
int getCurrentAnimationSize() { return static_cast<int>(animations_[current_animation_].frames.size()); }
|
||||||
|
};
|
||||||
173
source/asset.cpp
Normal file
173
source/asset.cpp
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
#include "asset.h"
|
||||||
|
#include <algorithm> // Para find_if, max
|
||||||
|
#include <fstream> // Para basic_ostream, operator<<, basic_ifstream, endl
|
||||||
|
#include <iostream> // Para cout
|
||||||
|
#include <string> // Para allocator, char_traits, string, operator+, oper...
|
||||||
|
#include "utils.h" // Para getFileName, printWithDots
|
||||||
|
|
||||||
|
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
|
||||||
|
Asset *Asset::asset_ = nullptr;
|
||||||
|
|
||||||
|
// [SINGLETON] Crearemos el objeto asset con esta función estática
|
||||||
|
void Asset::init(const std::string &executable_path)
|
||||||
|
{
|
||||||
|
Asset::asset_ = new Asset(executable_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [SINGLETON] Destruiremos el objeto asset con esta función estática
|
||||||
|
void Asset::destroy()
|
||||||
|
{
|
||||||
|
delete Asset::asset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [SINGLETON] Con este método obtenemos el objeto asset y podemos trabajar con él
|
||||||
|
Asset *Asset::get()
|
||||||
|
{
|
||||||
|
return Asset::asset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Añade un elemento a la lista
|
||||||
|
void Asset::add(const std::string &file, AssetType type, bool required, bool absolute)
|
||||||
|
{
|
||||||
|
file_list_.emplace_back(absolute ? file : executable_path_ + file, type, required);
|
||||||
|
longest_name_ = std::max(longest_name_, static_cast<int>(file_list_.back().file.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Devuelve la ruta completa a un fichero a partir de una cadena
|
||||||
|
std::string Asset::get(const std::string &text) const
|
||||||
|
{
|
||||||
|
auto it = std::find_if(file_list_.begin(), file_list_.end(),
|
||||||
|
[&text](const auto &f)
|
||||||
|
{
|
||||||
|
return getFileName(f.file) == text;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != file_list_.end())
|
||||||
|
{
|
||||||
|
return it->file;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Warning: file " << text << " not found" << std::endl;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba que existen todos los elementos
|
||||||
|
bool Asset::check() const
|
||||||
|
{
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
std::cout << "\n** CHECKING FILES" << std::endl;
|
||||||
|
|
||||||
|
// std::cout << "Executable path is: " << executable_path_ << std::endl;
|
||||||
|
// std::cout << "Sample filepath: " << file_list_.back().file << std::endl;
|
||||||
|
|
||||||
|
// Comprueba la lista de ficheros clasificandolos por tipo
|
||||||
|
for (int type = 0; type < static_cast<int>(AssetType::MAX_ASSET_TYPE); ++type)
|
||||||
|
{
|
||||||
|
// Comprueba si hay ficheros de ese tipo
|
||||||
|
bool any = false;
|
||||||
|
|
||||||
|
for (const auto &f : file_list_)
|
||||||
|
{
|
||||||
|
if (f.required && f.type == static_cast<AssetType>(type))
|
||||||
|
{
|
||||||
|
any = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si hay ficheros de ese tipo, comprueba si existen
|
||||||
|
if (any)
|
||||||
|
{
|
||||||
|
std::cout << "\n>> " << getTypeName(static_cast<AssetType>(type)).c_str() << " FILES" << std::endl;
|
||||||
|
|
||||||
|
for (const auto &f : file_list_)
|
||||||
|
{
|
||||||
|
if (f.required && f.type == static_cast<AssetType>(type))
|
||||||
|
{
|
||||||
|
success &= checkFile(f.file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (success)
|
||||||
|
std::cout << " All files are OK." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resultado
|
||||||
|
std::cout << (success ? "\n** CHECKING FILES COMPLETED.\n" : "\n** CHECKING FILES FAILED.\n") << std::endl;
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba que existe un fichero
|
||||||
|
bool Asset::checkFile(const std::string &path) const
|
||||||
|
{
|
||||||
|
std::ifstream file(path);
|
||||||
|
bool success = file.good();
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
printWithDots("Checking file : ", getFileName(path), "[ ERROR ]");
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Devuelve el nombre del tipo de recurso
|
||||||
|
std::string Asset::getTypeName(AssetType type) const
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case AssetType::DATA:
|
||||||
|
return "DATA";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssetType::BITMAP:
|
||||||
|
return "BITMAP";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssetType::ANIMATION:
|
||||||
|
return "ANIMATION";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssetType::MUSIC:
|
||||||
|
return "MUSIC";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssetType::SOUND:
|
||||||
|
return "SOUND";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssetType::FONT:
|
||||||
|
return "FONT";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssetType::ROOM:
|
||||||
|
return "ROOM";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssetType::TILEMAP:
|
||||||
|
return "TILEMAP";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "ERROR";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Devuelve la lista de recursos de un tipo
|
||||||
|
std::vector<std::string> Asset::getListByType(AssetType type) const
|
||||||
|
{
|
||||||
|
std::vector<std::string> list;
|
||||||
|
|
||||||
|
for (auto f : file_list_)
|
||||||
|
{
|
||||||
|
if (f.type == type)
|
||||||
|
{
|
||||||
|
list.push_back(f.file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
78
source/asset.h
Normal file
78
source/asset.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string> // para string, basic_string
|
||||||
|
#include <vector> // para vector
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
enum class AssetType : int
|
||||||
|
{
|
||||||
|
DATA,
|
||||||
|
BITMAP,
|
||||||
|
ANIMATION,
|
||||||
|
MUSIC,
|
||||||
|
SOUND,
|
||||||
|
FONT,
|
||||||
|
ROOM,
|
||||||
|
TILEMAP,
|
||||||
|
MAX_ASSET_TYPE
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clase Asset
|
||||||
|
class Asset
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// [SINGLETON] Objeto asset privado para Don Melitón
|
||||||
|
static Asset *asset_;
|
||||||
|
|
||||||
|
// Estructura para definir un item
|
||||||
|
struct AssetItem
|
||||||
|
{
|
||||||
|
std::string file; // Ruta del fichero desde la raíz del directorio
|
||||||
|
AssetType type; // Indica el tipo de recurso
|
||||||
|
bool required; // Indica si es un fichero que debe de existir
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
AssetItem(const std::string &filePath, AssetType assetType, bool isRequired)
|
||||||
|
: file(filePath), type(assetType), required(isRequired) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
int longest_name_ = 0; // Contiene la longitud del nombre de fichero mas largo
|
||||||
|
std::vector<AssetItem> file_list_; // Listado con todas las rutas a los ficheros
|
||||||
|
std::string executable_path_; // Ruta al ejecutable
|
||||||
|
|
||||||
|
// Comprueba que existe un fichero
|
||||||
|
bool checkFile(const std::string &path) const;
|
||||||
|
|
||||||
|
// Devuelve el nombre del tipo de recurso
|
||||||
|
std::string getTypeName(AssetType type) const;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
explicit Asset(const std::string &executable_path)
|
||||||
|
: executable_path_(getPath(executable_path)) {}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~Asset() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// [SINGLETON] Crearemos el objeto con esta función estática
|
||||||
|
static void init(const std::string &executable_path);
|
||||||
|
|
||||||
|
// [SINGLETON] Destruiremos el objeto con esta función estática
|
||||||
|
static void destroy();
|
||||||
|
|
||||||
|
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
|
||||||
|
static Asset *get();
|
||||||
|
|
||||||
|
// Añade un elemento a la lista
|
||||||
|
void add(const std::string &file, AssetType type, bool required = true, bool absolute = false);
|
||||||
|
|
||||||
|
// Devuelve la ruta completa a un fichero a partir de una cadena
|
||||||
|
std::string get(const std::string &text) const;
|
||||||
|
|
||||||
|
// Comprueba que existen todos los elementos
|
||||||
|
bool check() const;
|
||||||
|
|
||||||
|
// Devuelve la lista de recursos de un tipo
|
||||||
|
std::vector<std::string> getListByType(AssetType type) const;
|
||||||
|
};
|
||||||
@@ -1,111 +1,71 @@
|
|||||||
#include "cheevos.h"
|
#include "cheevos.h"
|
||||||
#include <iostream>
|
#include <SDL2/SDL_error.h> // for SDL_GetError
|
||||||
|
#include <SDL2/SDL_rwops.h> // for SDL_RWFromFile, SDL_RWclose, SDL_RWwrite
|
||||||
|
#include <stddef.h> // for NULL
|
||||||
|
#include <fstream> // for basic_ostream, operator<<, basic_ofstream
|
||||||
|
#include <iostream> // for cout, cerr
|
||||||
|
#include "notifier.h" // for Notifier
|
||||||
|
#include "options.h" // for Options, options
|
||||||
|
|
||||||
|
// [SINGLETON]
|
||||||
|
Cheevos *Cheevos::cheevos_ = nullptr;
|
||||||
|
|
||||||
|
// [SINGLETON] Crearemos el objeto con esta función estática
|
||||||
|
void Cheevos::init(const std::string &file)
|
||||||
|
{
|
||||||
|
Cheevos::cheevos_ = new Cheevos(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [SINGLETON] Destruiremos el objeto con esta función estática
|
||||||
|
void Cheevos::destroy()
|
||||||
|
{
|
||||||
|
delete Cheevos::cheevos_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
|
||||||
|
Cheevos *Cheevos::get()
|
||||||
|
{
|
||||||
|
return Cheevos::cheevos_;
|
||||||
|
}
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Cheevos::Cheevos(Screen *screen, options_t *options, std::string file, Online *online)
|
Cheevos::Cheevos(const std::string &file)
|
||||||
|
: file_(file)
|
||||||
{
|
{
|
||||||
// Copia la dirección de los objetos
|
|
||||||
this->options = options;
|
|
||||||
this->screen = screen;
|
|
||||||
this->file = file;
|
|
||||||
this->online = online;
|
|
||||||
|
|
||||||
// Inicializa los logros
|
|
||||||
init();
|
init();
|
||||||
|
loadFromFile();
|
||||||
// Inicializa variables
|
|
||||||
enabled = true;
|
|
||||||
|
|
||||||
// Carga el estado de los logros
|
|
||||||
load();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
Cheevos::~Cheevos()
|
Cheevos::~Cheevos()
|
||||||
{
|
{
|
||||||
// Guarda el estado de los logros
|
saveToFile();
|
||||||
save();
|
|
||||||
|
|
||||||
cheevos.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa los logros
|
// Inicializa los logros
|
||||||
void Cheevos::init()
|
void Cheevos::init()
|
||||||
{
|
{
|
||||||
cheevos.clear();
|
cheevos_list_.clear();
|
||||||
|
cheevos_list_.emplace_back(1, "SHINY THINGS", "Get 25% of the items", 2);
|
||||||
cheevos_t c;
|
cheevos_list_.emplace_back(2, "HALF THE WORK", "Get 50% of the items", 2);
|
||||||
c.completed = false;
|
cheevos_list_.emplace_back(3, "GETTING THERE", "Get 75% of the items", 2);
|
||||||
c.valid = true;
|
cheevos_list_.emplace_back(4, "THE COLLECTOR", "Get 100% of the items", 2);
|
||||||
c.icon = 2;
|
cheevos_list_.emplace_back(5, "WANDERING AROUND", "Visit 20 rooms", 2);
|
||||||
|
cheevos_list_.emplace_back(6, "I GOT LOST", "Visit 40 rooms", 2);
|
||||||
c.id = 1;
|
cheevos_list_.emplace_back(7, "I LIKE TO EXPLORE", "Visit all rooms", 2);
|
||||||
c.caption = "SHINY THINGS";
|
cheevos_list_.emplace_back(8, "FINISH THE GAME", "Complete the game", 2);
|
||||||
c.description = "Get 25\% of the items";
|
cheevos_list_.emplace_back(9, "I WAS SUCKED BY A HOLE", "Complete the game without entering the jail", 2);
|
||||||
cheevos.push_back(c);
|
cheevos_list_.emplace_back(10, "MY LITTLE PROJECTS", "Complete the game with all items", 2);
|
||||||
|
cheevos_list_.emplace_back(11, "I LIKE MY MULTICOLOURED FRIENDS", "Complete the game without dying", 2);
|
||||||
c.id = 2;
|
cheevos_list_.emplace_back(12, "SHIT PROJECTS DONE FAST", "Complete the game in under 30 minutes", 2);
|
||||||
c.caption = "HALF THE WORK";
|
|
||||||
c.description = "Get 50\% of the items";
|
|
||||||
cheevos.push_back(c);
|
|
||||||
|
|
||||||
c.id = 3;
|
|
||||||
c.caption = "GETTING THERE";
|
|
||||||
c.description = "Get 75\% of the items";
|
|
||||||
cheevos.push_back(c);
|
|
||||||
|
|
||||||
c.id = 4;
|
|
||||||
c.caption = "THE COLLECTOR";
|
|
||||||
c.description = "Get 100\% of the items";
|
|
||||||
cheevos.push_back(c);
|
|
||||||
|
|
||||||
c.id = 5;
|
|
||||||
c.caption = "WANDERING AROUND";
|
|
||||||
c.description = "Visit 20 rooms";
|
|
||||||
cheevos.push_back(c);
|
|
||||||
|
|
||||||
c.id = 6;
|
|
||||||
c.caption = "I GOT LOST";
|
|
||||||
c.description = "Visit 40 rooms";
|
|
||||||
cheevos.push_back(c);
|
|
||||||
|
|
||||||
c.id = 7;
|
|
||||||
c.caption = "I LIKE TO EXPLORE";
|
|
||||||
c.description = "Visit all rooms";
|
|
||||||
cheevos.push_back(c);
|
|
||||||
|
|
||||||
c.id = 8;
|
|
||||||
c.caption = "FINISH THE GAME";
|
|
||||||
c.description = "Complete the game";
|
|
||||||
cheevos.push_back(c);
|
|
||||||
|
|
||||||
c.id = 9;
|
|
||||||
c.caption = "I WAS SUCKED BY A HOLE";
|
|
||||||
c.description = "Complete the game without entering the jail";
|
|
||||||
cheevos.push_back(c);
|
|
||||||
|
|
||||||
c.id = 10;
|
|
||||||
c.caption = "MY LITTLE PROJECTS";
|
|
||||||
c.description = "Complete the game with all items";
|
|
||||||
cheevos.push_back(c);
|
|
||||||
|
|
||||||
c.id = 11;
|
|
||||||
c.caption = "I LIKE MY MULTICOLOURED FRIENDS";
|
|
||||||
c.description = "Complete the game without dying";
|
|
||||||
cheevos.push_back(c);
|
|
||||||
|
|
||||||
c.id = 12;
|
|
||||||
c.caption = "SHIT PROJECTS DONE FAST";
|
|
||||||
c.description = "Complete the game in under 30 minutes";
|
|
||||||
cheevos.push_back(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Busca un logro por id y devuelve el indice
|
// Busca un logro por id y devuelve el indice
|
||||||
int Cheevos::find(int id)
|
int Cheevos::find(int id)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < (int)cheevos.size(); ++i)
|
for (int i = 0; i < (int)cheevos_list_.size(); ++i)
|
||||||
{
|
{
|
||||||
if (cheevos[i].id == id)
|
if (cheevos_list_[i].id == id)
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@@ -119,130 +79,82 @@ void Cheevos::unlock(int id)
|
|||||||
{
|
{
|
||||||
const int index = find(id);
|
const int index = find(id);
|
||||||
|
|
||||||
if (index == -1)
|
// Si el índice es inválido, el logro no es válido, ya está completado o el sistema de logros no está habilitado, no hacemos nada
|
||||||
|
if (index == -1 || !cheevos_list_.at(index).valid || cheevos_list_.at(index).completed || !enabled_)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cheevos[index].valid)
|
// Marcar el logro como completado
|
||||||
{
|
cheevos_list_.at(index).completed = true;
|
||||||
return;
|
// Mostrar notificación en la pantalla
|
||||||
}
|
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", cheevos_list_.at(index).caption}, NotificationText::LEFT, cheevos_list_.at(index).icon);
|
||||||
|
// Guardar el estado de los logros
|
||||||
if (cheevos[index].completed)
|
saveToFile();
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cheevos[index].completed = true;
|
|
||||||
screen->showNotification("ACHIEVEMENT UNLOCKED!", cheevos[index].caption, cheevos[index].icon);
|
|
||||||
save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalida un logro
|
// Invalida un logro
|
||||||
void Cheevos::invalidate(int id)
|
void Cheevos::invalidate(int id)
|
||||||
{
|
{
|
||||||
const int index = find(id);
|
const int index = find(id);
|
||||||
if (index == -1)
|
|
||||||
|
// Si el índice es válido, se invalida el logro
|
||||||
|
if (index != -1)
|
||||||
{
|
{
|
||||||
return;
|
cheevos_list_.at(index).valid = false;
|
||||||
}
|
|
||||||
cheevos[index].valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Habilita o deshabilita los logros
|
|
||||||
void Cheevos::enable(bool value)
|
|
||||||
{
|
|
||||||
enabled = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carga el estado de los logros
|
|
||||||
void Cheevos::load()
|
|
||||||
{
|
|
||||||
if (options->online.enabled)
|
|
||||||
{ // Carga el estado de los logros desde el servidor online
|
|
||||||
loadFromServer();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // Carga el estado de los logros desde un fichero
|
|
||||||
loadFromFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Guarda el estado de los logros
|
|
||||||
void Cheevos::save()
|
|
||||||
{
|
|
||||||
if (options->online.enabled)
|
|
||||||
{ // Guarda el estado de los logros en el servidor online
|
|
||||||
saveToServer();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // Guarda el estado de los logros en un fichero
|
|
||||||
saveToFile();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carga el estado de los logros desde un fichero
|
// Carga el estado de los logros desde un fichero
|
||||||
void Cheevos::loadFromFile()
|
void Cheevos::loadFromFile()
|
||||||
{
|
{
|
||||||
// Abre el fichero en modo lectura (binario)
|
std::ifstream file(file_, std::ios::binary);
|
||||||
SDL_RWops *file = SDL_RWFromFile(this->file.c_str(), "r+b");
|
|
||||||
|
|
||||||
// El fichero no existe
|
// El fichero no existe
|
||||||
if (file == NULL)
|
if (!file)
|
||||||
{
|
{
|
||||||
if (options->console)
|
if (options.console)
|
||||||
{
|
{
|
||||||
std::cout << "Warning: Unable to open file! SDL Error: " << SDL_GetError() << std::endl;
|
std::cout << "Warning: Unable to open " << file_ << "! Creating new file..." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea el fichero en modo escritura (binario)
|
// Crea el fichero en modo escritura (binario)
|
||||||
file = SDL_RWFromFile(this->file.c_str(), "w+b");
|
std::ofstream newFile(file_, std::ios::binary);
|
||||||
|
|
||||||
if (file != NULL)
|
if (newFile)
|
||||||
{
|
{
|
||||||
if (options->console)
|
if (options.console)
|
||||||
{
|
{
|
||||||
std::cout << "New file created!" << std::endl;
|
std::cout << "New " << file_ << " created!" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Guarda la información
|
// Guarda la información
|
||||||
for (int i = 0; i < (int)cheevos.size(); ++i)
|
for (const auto &cheevo : cheevos_list_)
|
||||||
{
|
{
|
||||||
SDL_RWwrite(file, &cheevos[i].completed, sizeof(bool), 1);
|
newFile.write(reinterpret_cast<const char *>(&cheevo.completed), sizeof(bool));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cierra el fichero
|
|
||||||
SDL_RWclose(file);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (options->console)
|
if (options.console)
|
||||||
{
|
{
|
||||||
std::cout << "Error: Unable to create file! SDL Error: " << SDL_GetError() << std::endl;
|
std::cerr << "Error: Unable to create " << file_ << "!" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// El fichero existe
|
// El fichero existe
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Carga los datos
|
if (options.console)
|
||||||
if (options->console)
|
|
||||||
{
|
{
|
||||||
std::cout << "Reading file...!" << std::endl;
|
std::cout << "Reading " << file_ << std::endl;
|
||||||
}
|
|
||||||
for (int i = 0; i < (int)cheevos.size(); ++i)
|
|
||||||
{
|
|
||||||
SDL_RWread(file, &cheevos[i].completed, sizeof(bool), 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cierra el fichero
|
// Carga los datos
|
||||||
SDL_RWclose(file);
|
for (auto &cheevo : cheevos_list_)
|
||||||
|
{
|
||||||
|
file.read(reinterpret_cast<char *>(&cheevo.completed), sizeof(bool));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,13 +162,13 @@ void Cheevos::loadFromFile()
|
|||||||
void Cheevos::saveToFile()
|
void Cheevos::saveToFile()
|
||||||
{
|
{
|
||||||
// Abre el fichero en modo escritura (binario)
|
// Abre el fichero en modo escritura (binario)
|
||||||
SDL_RWops *file = SDL_RWFromFile(this->file.c_str(), "w+b");
|
SDL_RWops *file = SDL_RWFromFile(this->file_.c_str(), "w+b");
|
||||||
if (file != NULL)
|
if (file != NULL)
|
||||||
{
|
{
|
||||||
// Guarda la información
|
// Guarda la información
|
||||||
for (int i = 0; i < (int)cheevos.size(); ++i)
|
for (int i = 0; i < (int)cheevos_list_.size(); ++i)
|
||||||
{
|
{
|
||||||
SDL_RWwrite(file, &cheevos[i].completed, sizeof(bool), 1);
|
SDL_RWwrite(file, &cheevos_list_[i].completed, sizeof(bool), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cierra el fichero
|
// Cierra el fichero
|
||||||
@@ -264,76 +176,23 @@ void Cheevos::saveToFile()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (options->console)
|
if (options.console)
|
||||||
{
|
{
|
||||||
std::cout << "Error: Unable to save file! " << SDL_GetError() << std::endl;
|
std::cout << "Error: Unable to save file! " << SDL_GetError() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lista los logros
|
|
||||||
std::vector<cheevos_t> Cheevos::list()
|
|
||||||
{
|
|
||||||
return cheevos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Devuelve el número total de logros desbloqueados
|
// Devuelve el número total de logros desbloqueados
|
||||||
int Cheevos::unlocked()
|
int Cheevos::unlocked()
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (auto cheevo : cheevos)
|
for (auto cheevo : cheevos_list_)
|
||||||
{
|
{
|
||||||
if (cheevo.completed)
|
if (cheevo.completed)
|
||||||
|
{
|
||||||
count++;
|
count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
|
||||||
|
|
||||||
// Devuelve el número total de logros
|
|
||||||
int Cheevos::count()
|
|
||||||
{
|
|
||||||
return cheevos.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carga el estado de los logros desde el servidor online
|
|
||||||
void Cheevos::loadFromServer()
|
|
||||||
{
|
|
||||||
std::string cheevosData = online->getCheevos();
|
|
||||||
|
|
||||||
// Gestiona los posibles errores
|
|
||||||
const bool noData = cheevosData == "" ? true : false;
|
|
||||||
const bool incompleteData = cheevosData.length() != cheevos.size() ? true : false;
|
|
||||||
if (noData || incompleteData)
|
|
||||||
{
|
|
||||||
// Pone todos los logros en incompleto
|
|
||||||
init();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Asigna los valores leídos desde el servidor
|
|
||||||
for (int i = 0; i < (int)cheevosData.length(); ++i)
|
|
||||||
{
|
|
||||||
bool value = cheevosData.at(i) == '1' ? true : false;
|
|
||||||
cheevos.at(i).completed = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Guarda el estado de los logros en el servidor online
|
|
||||||
void Cheevos::saveToServer()
|
|
||||||
{
|
|
||||||
std::string cheevosData = "";
|
|
||||||
// cheevos[2].completed = true;
|
|
||||||
for (auto cheevo : cheevos)
|
|
||||||
{
|
|
||||||
std::string data = cheevo.completed ? "1" : "0";
|
|
||||||
cheevosData.append(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
online->setCheevos(cheevosData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vuelve a cargar los logros desde el origen
|
|
||||||
void Cheevos::reload()
|
|
||||||
{
|
|
||||||
load();
|
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <SDL2/SDL.h>
|
|
||||||
#include "jail_engine/screen.h"
|
|
||||||
#include "jail_engine/utils.h"
|
|
||||||
#include "online.h"
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#ifndef CHEEVOS_H
|
#include <string> // for string
|
||||||
#define CHEEVOS_H
|
#include <vector> // for vector
|
||||||
|
|
||||||
struct cheevos_t
|
// Struct para los logros
|
||||||
|
struct Achievement
|
||||||
{
|
{
|
||||||
int id; // Identificador del logro
|
int id; // Identificador del logro
|
||||||
std::string caption; // Texto con el nombre del logro
|
std::string caption; // Texto con el nombre del logro
|
||||||
@@ -17,52 +12,54 @@ struct cheevos_t
|
|||||||
int icon; // Indice del icono a utilizar en la notificación
|
int icon; // Indice del icono a utilizar en la notificación
|
||||||
bool completed; // Indica si se ha obtenido el logro
|
bool completed; // Indica si se ha obtenido el logro
|
||||||
bool valid; // Indica si se puede obtener el logro
|
bool valid; // Indica si se puede obtener el logro
|
||||||
|
|
||||||
|
// Constructor vacío
|
||||||
|
Achievement() : id(0), icon(0), completed(false), valid(true) {}
|
||||||
|
|
||||||
|
// Constructor parametrizado
|
||||||
|
Achievement(int id, const std::string &caption, const std::string &description, int icon, bool completed = false, bool valid = true)
|
||||||
|
: id(id), caption(caption), description(description), icon(icon), completed(completed), valid(valid) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Cheevos
|
class Cheevos
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Punteros y objetos
|
// [SINGLETON] Objeto privado
|
||||||
Screen *screen; // Objeto encargado de dibujar en pantalla
|
static Cheevos *cheevos_;
|
||||||
options_t *options; // Puntero a las opciones del juego
|
|
||||||
Online *online; // Objeto para gestionar la lectura y escritura de datos en el servidor remoto
|
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
std::vector<cheevos_t> cheevos; // Listado de logros
|
std::vector<Achievement> cheevos_list_; // Listado de logros
|
||||||
bool enabled; // Indica si los logros se pueden obtener
|
bool enabled_ = true; // Indica si los logros se pueden obtener
|
||||||
std::string file; // Fichero done leer/almacenar el estado de los logros
|
std::string file_; // Fichero donde leer/almacenar el estado de los logros
|
||||||
|
|
||||||
// Inicializa los logros
|
// Inicializa los logros
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
// Busca un logro por id y devuelve el indice
|
// Busca un logro por id y devuelve el índice
|
||||||
int find(int id);
|
int find(int id);
|
||||||
|
|
||||||
// Carga el estado de los logros
|
|
||||||
void load();
|
|
||||||
|
|
||||||
// Guarda el estado de los logros
|
|
||||||
void save();
|
|
||||||
|
|
||||||
// Carga el estado de los logros desde un fichero
|
// Carga el estado de los logros desde un fichero
|
||||||
void loadFromFile();
|
void loadFromFile();
|
||||||
|
|
||||||
// Guarda el estado de los logros en un fichero
|
// Guarda el estado de los logros en un fichero
|
||||||
void saveToFile();
|
void saveToFile();
|
||||||
|
|
||||||
// Carga el estado de los logros desde el servidor online
|
|
||||||
void loadFromServer();
|
|
||||||
|
|
||||||
// Guarda el estado de los logros en el servidor online
|
|
||||||
void saveToServer();
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Cheevos(Screen *screen, options_t *options, std::string file, Online *online);
|
Cheevos(const std::string &file);
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~Cheevos();
|
~Cheevos();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// [SINGLETON] Crearemos el objeto con esta función estática
|
||||||
|
static void init(const std::string &file);
|
||||||
|
|
||||||
|
// [SINGLETON] Destruiremos el objeto con esta función estática
|
||||||
|
static void destroy();
|
||||||
|
|
||||||
|
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
|
||||||
|
static Cheevos *get();
|
||||||
|
|
||||||
// Desbloquea un logro
|
// Desbloquea un logro
|
||||||
void unlock(int id);
|
void unlock(int id);
|
||||||
|
|
||||||
@@ -70,19 +67,14 @@ public:
|
|||||||
void invalidate(int id);
|
void invalidate(int id);
|
||||||
|
|
||||||
// Habilita o deshabilita los logros
|
// Habilita o deshabilita los logros
|
||||||
void enable(bool value);
|
void enable(bool value) { enabled_ = value; }
|
||||||
|
|
||||||
// Lista los logros
|
// Lista los logros
|
||||||
std::vector<cheevos_t> list();
|
std::vector<Achievement> list() { return cheevos_list_; }
|
||||||
|
|
||||||
// Devuelve el número total de logros desbloqueados
|
// Devuelve el número total de logros desbloqueados
|
||||||
int unlocked();
|
int unlocked();
|
||||||
|
|
||||||
// Devuelve el número total de logros
|
// Devuelve el número total de logros
|
||||||
int count();
|
int count() { return cheevos_list_.size(); }
|
||||||
|
|
||||||
// Vuelve a cargar los logros desde el origen
|
|
||||||
void reload();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
|
||||||
#include <string>
|
|
||||||
#include "jail_engine/utils.h"
|
|
||||||
|
|
||||||
#ifndef CONST_H
|
|
||||||
#define CONST_H
|
|
||||||
|
|
||||||
// Textos
|
|
||||||
#define WINDOW_CAPTION "JailDoctor's Dilemma"
|
|
||||||
#define TEXT_COPYRIGHT "@2022 JailDesigner"
|
|
||||||
#define VERSION "0.7"
|
|
||||||
|
|
||||||
// Tamaño de bloque
|
|
||||||
#define BLOCK 8
|
|
||||||
#define HALF_BLOCK 4
|
|
||||||
|
|
||||||
// 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 = (16 * BLOCK);
|
|
||||||
const int PLAY_AREA_LEFT = (0 * BLOCK);
|
|
||||||
const int PLAY_AREA_RIGHT = (32 * 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);
|
|
||||||
const int PLAY_AREA_CENTER_FIRST_QUARTER_X = (PLAY_AREA_WIDTH / 4);
|
|
||||||
const int PLAY_AREA_CENTER_THIRD_QUARTER_X = (PLAY_AREA_WIDTH / 4) * 3;
|
|
||||||
const int PLAY_AREA_CENTER_Y = PLAY_AREA_TOP + (PLAY_AREA_HEIGHT / 2);
|
|
||||||
const int PLAY_AREA_FIRST_QUARTER_Y = PLAY_AREA_HEIGHT / 4;
|
|
||||||
const int PLAY_AREA_THIRD_QUARTER_Y = (PLAY_AREA_HEIGHT / 4) * 3;
|
|
||||||
|
|
||||||
#define BORDER_TOP 0
|
|
||||||
#define BORDER_RIGHT 1
|
|
||||||
#define BORDER_BOTTOM 2
|
|
||||||
#define BORDER_LEFT 3
|
|
||||||
|
|
||||||
// Anclajes de pantalla
|
|
||||||
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 SECTION_LOGO 0
|
|
||||||
#define SECTION_LOADING_SCREEN 1
|
|
||||||
#define SECTION_TITLE 2
|
|
||||||
#define SECTION_CREDITS 3
|
|
||||||
#define SECTION_GAME 4
|
|
||||||
#define SECTION_DEMO 5
|
|
||||||
#define SECTION_GAME_OVER 6
|
|
||||||
#define SECTION_ENDING 7
|
|
||||||
#define SECTION_ENDING2 8
|
|
||||||
#define SECTION_QUIT 9
|
|
||||||
|
|
||||||
// Subsecciones
|
|
||||||
#define SUBSECTION_LOGO_TO_INTRO 0
|
|
||||||
#define SUBSECTION_LOGO_TO_TITLE 1
|
|
||||||
#define SUBSECTION_TITLE_WITH_LOADING_SCREEN 2
|
|
||||||
#define SUBSECTION_TITLE_WITHOUT_LOADING_SCREEN 3
|
|
||||||
|
|
||||||
// Colores
|
|
||||||
const color_t borderColor = {0x27, 0x27, 0x36};
|
|
||||||
const color_t black = {0xFF, 0xFF, 0xFF};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
323
source/credits.cpp
Normal file
323
source/credits.cpp
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
#include "credits.h"
|
||||||
|
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
|
||||||
|
#include <SDL2/SDL_error.h> // for SDL_GetError
|
||||||
|
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
|
||||||
|
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
|
||||||
|
#include <SDL2/SDL_rect.h> // for SDL_Rect
|
||||||
|
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
|
||||||
|
#include <algorithm> // for min
|
||||||
|
#include <iostream> // for basic_ostream, operator<<, cout, endl
|
||||||
|
#include "animated_sprite.h" // for AnimatedSprite
|
||||||
|
#include "asset.h" // for Asset
|
||||||
|
#include "defines.h" // for GAMECANVAS_HEIGHT, GAMECANVAS_WIDTH
|
||||||
|
#include "global_events.h" // for check
|
||||||
|
#include "global_inputs.h" // for check
|
||||||
|
#include "input.h" // for Input
|
||||||
|
#include "options.h" // for Options, options, OptionsVideo, Sect...
|
||||||
|
#include "resource.h" // for Resource
|
||||||
|
#include "screen.h" // for Screen
|
||||||
|
#include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
Credits::Credits()
|
||||||
|
: screen_(Screen::get()),
|
||||||
|
renderer_(Screen::get()->getRenderer()),
|
||||||
|
resource_(Resource::get()),
|
||||||
|
asset_(Asset::get()),
|
||||||
|
input_(Input::get())
|
||||||
|
{
|
||||||
|
// Reserva memoria para los punteros
|
||||||
|
text_ = resource_->getText("smb2");
|
||||||
|
sprite_ = std::make_shared<AnimatedSprite>(resource_->getTexture("shine.png"), resource_->getAnimations("shine.ani"));
|
||||||
|
|
||||||
|
// Inicializa variables
|
||||||
|
options.section.section = Section::CREDITS;
|
||||||
|
options.section.subsection = Subsection::NONE;
|
||||||
|
sprite_->setPosition({194, 174, 8, 8});
|
||||||
|
|
||||||
|
// Cambia el color del borde
|
||||||
|
screen_->setBorderColor(stringToColor(options.video.palette, "black"));
|
||||||
|
|
||||||
|
// Crea la textura para el texto que se escribe en pantalla
|
||||||
|
text_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT);
|
||||||
|
if (text_texture_ == nullptr)
|
||||||
|
{
|
||||||
|
if (options.console)
|
||||||
|
{
|
||||||
|
std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_SetTextureBlendMode(text_texture_, SDL_BLENDMODE_BLEND);
|
||||||
|
|
||||||
|
// Crea la textura para cubrir el rexto
|
||||||
|
cover_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT);
|
||||||
|
if (cover_texture_ == nullptr)
|
||||||
|
{
|
||||||
|
if (options.console)
|
||||||
|
{
|
||||||
|
std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_SetTextureBlendMode(cover_texture_, SDL_BLENDMODE_BLEND);
|
||||||
|
|
||||||
|
// Escribe el texto en la textura
|
||||||
|
fillTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
Credits::~Credits()
|
||||||
|
{
|
||||||
|
SDL_DestroyTexture(text_texture_);
|
||||||
|
SDL_DestroyTexture(cover_texture_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba el manejador de eventos
|
||||||
|
void Credits::checkEvents()
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
globalEvents::check(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
void Credits::checkInput()
|
||||||
|
{
|
||||||
|
globalInputs::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicializa los textos
|
||||||
|
void Credits::iniTexts()
|
||||||
|
{
|
||||||
|
std::string keys = "";
|
||||||
|
if (options.keys == ControlScheme::CURSOR)
|
||||||
|
{
|
||||||
|
keys = "CURSORS";
|
||||||
|
}
|
||||||
|
else if (options.keys == ControlScheme::OPQA)
|
||||||
|
{
|
||||||
|
keys = "O,P AND Q";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
keys = "A,D AND W";
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef GAME_CONSOLE
|
||||||
|
texts_.clear();
|
||||||
|
texts_.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"INSTRUCTIONS:", stringToColor(options.video.palette, "yellow")});
|
||||||
|
texts_.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"HELP JAILDOC TO GET BACK ALL", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"HIS PROJECTS AND GO TO THE", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"JAIL TO FINISH THEM", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
|
||||||
|
texts_.push_back({"KEYS:", stringToColor(options.video.palette, "yellow")});
|
||||||
|
texts_.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({keys + " TO MOVE AND JUMP", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"M TO SWITCH THE MUSIC", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"H TO PAUSE THE GAME", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"F1-F2 TO CHANGE WINDOWS SIZE", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"F3 TO SWITCH TO FULLSCREEN", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"B TO TOOGLE THE BORDER SCREEN", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
|
||||||
|
texts_.push_back({"A GAME BY JAILDESIGNER", stringToColor(options.video.palette, "yellow")});
|
||||||
|
texts_.push_back({"MADE ON SUMMER/FALL 2022", stringToColor(options.video.palette, "yellow")});
|
||||||
|
texts_.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
|
||||||
|
texts_.push_back({"I LOVE JAILGAMES! ", stringToColor(options.video.palette, "white")});
|
||||||
|
texts_.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
#else
|
||||||
|
texts.clear();
|
||||||
|
texts.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"INSTRUCTIONS:", stringToColor(options.video.palette, "yellow")});
|
||||||
|
texts.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"HELP JAILDOC TO GET BACK ALL", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"HIS PROJECTS AND GO TO THE", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"JAIL TO FINISH THEM", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
|
||||||
|
texts.push_back({"KEYS:", stringToColor(options.video.palette, "yellow")});
|
||||||
|
texts.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"B TO JUMP", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"R TO SWITCH THE MUSIC", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"L TO SWAP THE COLOR PALETTE", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"START TO PAUSE", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"SELECT TO EXIT", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
|
||||||
|
texts.push_back({"A GAME BY JAILDESIGNER", stringToColor(options.video.palette, "yellow")});
|
||||||
|
texts.push_back({"MADE ON SUMMER/FALL 2022", stringToColor(options.video.palette, "yellow")});
|
||||||
|
texts.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
|
||||||
|
texts.push_back({"I LOVE JAILGAMES! ", stringToColor(options.video.palette, "white")});
|
||||||
|
texts.push_back({"", stringToColor(options.video.palette, "white")});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escribe el texto en la textura
|
||||||
|
void Credits::fillTexture()
|
||||||
|
{
|
||||||
|
// Inicializa los textos
|
||||||
|
iniTexts();
|
||||||
|
|
||||||
|
// Rellena la textura de texto
|
||||||
|
SDL_SetRenderTarget(renderer_, text_texture_);
|
||||||
|
Color c = stringToColor(options.video.palette, "black");
|
||||||
|
SDL_SetRenderDrawColor(renderer_, c.r, c.g, c.b, 0xFF);
|
||||||
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
|
// Escribe el texto en la textura
|
||||||
|
const int size = text_->getCharacterSize();
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (auto t : texts_)
|
||||||
|
{
|
||||||
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, i * size, t.label, 1, t.color);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escribe el corazón
|
||||||
|
const int textLenght = text_->lenght(texts_[22].label, 1) - text_->lenght(" ", 1); // Se resta el ultimo caracter que es un espacio
|
||||||
|
const int posX = ((PLAY_AREA_WIDTH - textLenght) / 2) + textLenght;
|
||||||
|
text_->writeColored(posX, 176, "}", stringToColor(options.video.palette, "bright_red"));
|
||||||
|
|
||||||
|
// Recoloca el sprite del brillo
|
||||||
|
sprite_->setPosX(posX + 2);
|
||||||
|
|
||||||
|
SDL_SetRenderTarget(renderer_, nullptr);
|
||||||
|
|
||||||
|
// Rellena la textura que cubre el texto con color transparente
|
||||||
|
SDL_SetRenderTarget(renderer_, cover_texture_);
|
||||||
|
SDL_SetRenderDrawColor(renderer_, c.r, c.g, c.b, 0x00);
|
||||||
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
|
// Los primeros 8 pixels crea una malla
|
||||||
|
SDL_SetRenderDrawColor(renderer_, c.r, c.g, c.b, 0xFF);
|
||||||
|
for (int i = 0; i < 256; i += 2)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 0);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 2);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 4);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 6);
|
||||||
|
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 1, 5);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 1, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// El resto se rellena de color sólido
|
||||||
|
SDL_Rect rect = {0, 8, 256, 192};
|
||||||
|
SDL_RenderFillRect(renderer_, &rect);
|
||||||
|
|
||||||
|
SDL_SetRenderTarget(renderer_, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza el contador
|
||||||
|
void Credits::updateCounter()
|
||||||
|
{
|
||||||
|
// Incrementa el contador
|
||||||
|
if (counter_enabled_)
|
||||||
|
{
|
||||||
|
counter_++;
|
||||||
|
if (counter_ == 224 || counter_ == 544 || counter_ == 672)
|
||||||
|
{
|
||||||
|
counter_enabled_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sub_counter_++;
|
||||||
|
if (sub_counter_ == 100)
|
||||||
|
{
|
||||||
|
counter_enabled_ = true;
|
||||||
|
sub_counter_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba si ha terminado la sección
|
||||||
|
if (counter_ > 1200)
|
||||||
|
{
|
||||||
|
options.section.section = Section::DEMO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza las variables
|
||||||
|
void Credits::update()
|
||||||
|
{
|
||||||
|
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
||||||
|
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
|
||||||
|
{
|
||||||
|
// Actualiza el contador de ticks
|
||||||
|
ticks_ = SDL_GetTicks();
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
checkInput();
|
||||||
|
|
||||||
|
// Actualiza el contador
|
||||||
|
updateCounter();
|
||||||
|
|
||||||
|
screen_->update();
|
||||||
|
|
||||||
|
// Actualiza el sprite con el brillo
|
||||||
|
if (counter_ > 770)
|
||||||
|
{
|
||||||
|
sprite_->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja en pantalla
|
||||||
|
void Credits::render()
|
||||||
|
{
|
||||||
|
// Prepara para empezar a dibujar en la textura de juego
|
||||||
|
screen_->start();
|
||||||
|
|
||||||
|
// Limpia la pantalla
|
||||||
|
screen_->clean();
|
||||||
|
|
||||||
|
if (counter_ < 1150)
|
||||||
|
{
|
||||||
|
// Dibuja la textura con el texto en pantalla
|
||||||
|
SDL_RenderCopy(renderer_, text_texture_, nullptr, nullptr);
|
||||||
|
|
||||||
|
// Dibuja la textura que cubre el texto
|
||||||
|
const int offset = std::min(counter_ / 8, 192 / 2);
|
||||||
|
SDL_Rect srcRect = {0, 0, 256, 192 - (offset * 2)};
|
||||||
|
SDL_Rect dstRect = {0, offset * 2, 256, 192 - (offset * 2)};
|
||||||
|
SDL_RenderCopy(renderer_, cover_texture_, &srcRect, &dstRect);
|
||||||
|
|
||||||
|
// Dibuja el sprite con el brillo
|
||||||
|
sprite_->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vuelca el contenido del renderizador en pantalla
|
||||||
|
screen_->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bucle para el logo del juego
|
||||||
|
void Credits::run()
|
||||||
|
{
|
||||||
|
while (options.section.section == Section::CREDITS)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
checkEvents();
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cambia la paleta
|
||||||
|
void Credits::switchPalette()
|
||||||
|
{
|
||||||
|
options.video.palette = options.video.palette == Palette::ZXSPECTRUM ? Palette::ZXARNE : Palette::ZXSPECTRUM;
|
||||||
|
fillTexture();
|
||||||
|
}
|
||||||
76
source/credits.h
Normal file
76
source/credits.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL_render.h> // for SDL_Texture, SDL_Renderer
|
||||||
|
#include <SDL2/SDL_stdinc.h> // for Uint32
|
||||||
|
#include <memory> // for shared_ptr
|
||||||
|
#include <string> // for string
|
||||||
|
#include <vector> // for vector
|
||||||
|
#include "utils.h" // for Color
|
||||||
|
class AnimatedSprite; // lines 10-10
|
||||||
|
class Asset; // lines 11-11
|
||||||
|
class Input; // lines 12-12
|
||||||
|
class Resource; // lines 13-13
|
||||||
|
class Screen; // lines 14-14
|
||||||
|
class Text; // lines 15-15
|
||||||
|
|
||||||
|
class Credits
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct captions_t
|
||||||
|
{
|
||||||
|
std::string label; // Texto a escribir
|
||||||
|
Color color; // Color del texto
|
||||||
|
};
|
||||||
|
|
||||||
|
// Objetos y punteros
|
||||||
|
Screen *screen_; // Objeto encargado de dibujar en pantalla
|
||||||
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
|
Resource *resource_; // Objeto con los recursos
|
||||||
|
Asset *asset_; // Objeto con los ficheros de recursos
|
||||||
|
Input *input_; // Objeto pata gestionar la entrada
|
||||||
|
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
|
||||||
|
SDL_Texture *text_texture_; // Textura para dibujar el texto
|
||||||
|
SDL_Texture *cover_texture_; // Textura para cubrir el texto
|
||||||
|
std::shared_ptr<AnimatedSprite> sprite_; // Sprite para el brillo del corazón
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
int counter_ = 0; // Contador
|
||||||
|
bool counter_enabled_ = true; // Indica si esta activo el contador
|
||||||
|
int sub_counter_ = 0; // Contador secundario
|
||||||
|
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
||||||
|
std::vector<captions_t> texts_; // Vector con los textos
|
||||||
|
|
||||||
|
// Actualiza las variables
|
||||||
|
void update();
|
||||||
|
|
||||||
|
// Dibuja en pantalla
|
||||||
|
void render();
|
||||||
|
|
||||||
|
// Comprueba el manejador de eventos
|
||||||
|
void checkEvents();
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
void checkInput();
|
||||||
|
|
||||||
|
// Actualiza el contador
|
||||||
|
void updateCounter();
|
||||||
|
|
||||||
|
// Inicializa los textos
|
||||||
|
void iniTexts();
|
||||||
|
|
||||||
|
// Escribe el texto en la textura
|
||||||
|
void fillTexture();
|
||||||
|
|
||||||
|
// Cambia la paleta
|
||||||
|
void switchPalette();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
Credits();
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~Credits();
|
||||||
|
|
||||||
|
// Bucle principal
|
||||||
|
void run();
|
||||||
|
};
|
||||||
76
source/debug.cpp
Normal file
76
source/debug.cpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#include "debug.h"
|
||||||
|
#include <algorithm> // for max
|
||||||
|
#include "resource.h" // for Resource
|
||||||
|
#include "screen.h" // for Screen
|
||||||
|
#include "text.h" // for Text
|
||||||
|
#include "utils.h" // for Color
|
||||||
|
|
||||||
|
// [SINGLETON]
|
||||||
|
Debug *Debug::debug_ = nullptr;
|
||||||
|
|
||||||
|
// [SINGLETON] Crearemos el objeto con esta función estática
|
||||||
|
void Debug::init()
|
||||||
|
{
|
||||||
|
Debug::debug_ = new Debug();
|
||||||
|
}
|
||||||
|
|
||||||
|
// [SINGLETON] Destruiremos el objeto con esta función estática
|
||||||
|
void Debug::destroy()
|
||||||
|
{
|
||||||
|
delete Debug::debug_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
|
||||||
|
Debug *Debug::get()
|
||||||
|
{
|
||||||
|
return Debug::debug_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
Debug::Debug()
|
||||||
|
// Copia la dirección de los objetos
|
||||||
|
: screen_(Screen::get()),
|
||||||
|
renderer_(Screen::get()->getRenderer())
|
||||||
|
{
|
||||||
|
// Reserva memoria para los punteros
|
||||||
|
texture_ = Resource::get()->getTexture("debug.png");
|
||||||
|
text_ = Resource::get()->getText("debug");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza las variables
|
||||||
|
void Debug::update()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja en pantalla
|
||||||
|
void Debug::render()
|
||||||
|
{
|
||||||
|
int y = y_;
|
||||||
|
int w = 0;
|
||||||
|
|
||||||
|
for (auto s : slot_)
|
||||||
|
{
|
||||||
|
text_->write(x_, y, s);
|
||||||
|
w = (std::max(w, (int)s.length()));
|
||||||
|
y += text_->getCharacterSize() + 1;
|
||||||
|
if (y > 192 - text_->getCharacterSize())
|
||||||
|
{
|
||||||
|
y = y_;
|
||||||
|
x_ += w * text_->getCharacterSize() + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
y = 0;
|
||||||
|
for (auto l : log_)
|
||||||
|
{
|
||||||
|
text_->writeColored(x_ + 10, y, l, Color(255, 255, 255));
|
||||||
|
y += text_->getCharacterSize() + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establece la posición donde se colocará la información de debug
|
||||||
|
void Debug::setPos(SDL_Point p)
|
||||||
|
{
|
||||||
|
x_ = p.x;
|
||||||
|
y_ = p.y;
|
||||||
|
}
|
||||||
67
source/debug.h
Normal file
67
source/debug.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL_rect.h> // for SDL_Point
|
||||||
|
#include <SDL2/SDL_render.h> // for SDL_Renderer
|
||||||
|
#include <memory> // for shared_ptr
|
||||||
|
#include <string> // for string
|
||||||
|
#include <vector> // for vector
|
||||||
|
class Screen; // lines 9-9
|
||||||
|
class Text; // lines 10-10
|
||||||
|
class Texture; // lines 11-11
|
||||||
|
|
||||||
|
// Clase Debug
|
||||||
|
class Debug
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// [SINGLETON] Objeto privado
|
||||||
|
static Debug *debug_;
|
||||||
|
|
||||||
|
// Objetos y punteros
|
||||||
|
Screen *screen_; // Objeto encargado de dibujar en pantalla
|
||||||
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
|
std::shared_ptr<Text> text_; // Objeto encargado de escribir texto en pantalla
|
||||||
|
std::shared_ptr<Texture> texture_; // Textura para el texto
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
std::vector<std::string> slot_; // Vector con los textos a escribir
|
||||||
|
std::vector<std::string> log_; // Vector con los textos a escribir
|
||||||
|
int x_ = 0; // Posicion donde escribir el texto de debug
|
||||||
|
int y_ = 0; // Posición donde escribir el texto de debug
|
||||||
|
bool enabled_ = false; // Indica si esta activo el modo debug
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
Debug();
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~Debug() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// [SINGLETON] Crearemos el objeto con esta función estática
|
||||||
|
static void init();
|
||||||
|
|
||||||
|
// [SINGLETON] Destruiremos el objeto con esta función estática
|
||||||
|
static void destroy();
|
||||||
|
|
||||||
|
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
|
||||||
|
static Debug *get();
|
||||||
|
|
||||||
|
// Actualiza las variables
|
||||||
|
void update();
|
||||||
|
|
||||||
|
// Dibuja en pantalla
|
||||||
|
void render();
|
||||||
|
|
||||||
|
// Establece la posición donde se colocará la información de debug
|
||||||
|
void setPos(SDL_Point p);
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
bool getEnabled() { return enabled_; }
|
||||||
|
|
||||||
|
// Setters
|
||||||
|
void add(std::string text) { slot_.push_back(text); }
|
||||||
|
void clear() { slot_.clear(); }
|
||||||
|
void addToLog(std::string text) { log_.push_back(text); }
|
||||||
|
void clearLog() { log_.clear(); }
|
||||||
|
void setEnabled(bool value) { enabled_ = value; }
|
||||||
|
void switchEnabled() { enabled_ = !enabled_; }
|
||||||
|
};
|
||||||
52
source/defines.h
Normal file
52
source/defines.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <string>
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
// Textos
|
||||||
|
constexpr const char *WINDOW_CAPTION = "JailDoctor's Dilemma";
|
||||||
|
constexpr const char *TEXT_COPYRIGHT = "@2022 JailDesigner";
|
||||||
|
constexpr const char *VERSION = "1.09";
|
||||||
|
|
||||||
|
// Velocidad del juego
|
||||||
|
constexpr Uint32 GAME_SPEED = 1000 / 60;
|
||||||
|
|
||||||
|
// Tamaño de bloque
|
||||||
|
constexpr int BLOCK = 8;
|
||||||
|
constexpr int HALF_BLOCK = 4;
|
||||||
|
|
||||||
|
// Tamaño de la pantalla virtual
|
||||||
|
constexpr int GAMECANVAS_WIDTH = 256;
|
||||||
|
constexpr int GAMECANVAS_HEIGHT = 192;
|
||||||
|
|
||||||
|
// Zona de juego
|
||||||
|
constexpr int PLAY_AREA_TOP = (0 * BLOCK);
|
||||||
|
constexpr int PLAY_AREA_BOTTOM = (16 * BLOCK);
|
||||||
|
constexpr int PLAY_AREA_LEFT = (0 * BLOCK);
|
||||||
|
constexpr int PLAY_AREA_RIGHT = (32 * BLOCK);
|
||||||
|
constexpr int PLAY_AREA_WIDTH = PLAY_AREA_RIGHT - PLAY_AREA_LEFT;
|
||||||
|
constexpr int PLAY_AREA_HEIGHT = PLAY_AREA_BOTTOM - PLAY_AREA_TOP;
|
||||||
|
constexpr int PLAY_AREA_CENTER_X = PLAY_AREA_LEFT + (PLAY_AREA_WIDTH / 2);
|
||||||
|
constexpr int PLAY_AREA_CENTER_FIRST_QUARTER_X = (PLAY_AREA_WIDTH / 4);
|
||||||
|
constexpr int PLAY_AREA_CENTER_THIRD_QUARTER_X = (PLAY_AREA_WIDTH / 4) * 3;
|
||||||
|
constexpr int PLAY_AREA_CENTER_Y = PLAY_AREA_TOP + (PLAY_AREA_HEIGHT / 2);
|
||||||
|
constexpr int PLAY_AREA_FIRST_QUARTER_Y = PLAY_AREA_HEIGHT / 4;
|
||||||
|
constexpr int PLAY_AREA_THIRD_QUARTER_Y = (PLAY_AREA_HEIGHT / 4) * 3;
|
||||||
|
|
||||||
|
constexpr int BORDER_TOP = 0;
|
||||||
|
constexpr int BORDER_RIGHT = 1;
|
||||||
|
constexpr int BORDER_BOTTOM = 2;
|
||||||
|
constexpr int BORDER_LEFT = 3;
|
||||||
|
|
||||||
|
// Anclajes de pantalla
|
||||||
|
constexpr int GAMECANVAS_CENTER_X = GAMECANVAS_WIDTH / 2;
|
||||||
|
constexpr int GAMECANVAS_FIRST_QUARTER_X = GAMECANVAS_WIDTH / 4;
|
||||||
|
constexpr int GAMECANVAS_THIRD_QUARTER_X = (GAMECANVAS_WIDTH / 4) * 3;
|
||||||
|
constexpr int GAMECANVAS_CENTER_Y = GAMECANVAS_HEIGHT / 2;
|
||||||
|
constexpr int GAMECANVAS_FIRST_QUARTER_Y = GAMECANVAS_HEIGHT / 4;
|
||||||
|
constexpr int GAMECANVAS_THIRD_QUARTER_Y = (GAMECANVAS_HEIGHT / 4) * 3;
|
||||||
|
|
||||||
|
// Colores
|
||||||
|
const Color borderColor = {0x27, 0x27, 0x36};
|
||||||
|
const Color black = {0xFF, 0xFF, 0xFF};
|
||||||
235
source/demo.cpp
Normal file
235
source/demo.cpp
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
#include "demo.h"
|
||||||
|
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
|
||||||
|
#include <SDL2/SDL_rect.h> // for SDL_Rect
|
||||||
|
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
|
||||||
|
#include <iostream> // for basic_ostream, operator<<, cout, endl
|
||||||
|
#include "asset.h" // for Asset
|
||||||
|
#include "debug.h" // for Debug
|
||||||
|
#include "defines.h" // for BLOCK, PLAY_AREA_WIDTH, GAMECANVAS_CENT...
|
||||||
|
#include "global_events.h" // for check
|
||||||
|
#include "global_inputs.h" // for check
|
||||||
|
#include "input.h" // for Input
|
||||||
|
#include "item_tracker.h" // for ItemTracker
|
||||||
|
#include "options.h" // for Options, options, OptionsVideo, Section...
|
||||||
|
#include "resource.h" // for Resource
|
||||||
|
#include "room.h" // for Room
|
||||||
|
#include "screen.h" // for Screen
|
||||||
|
#include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR
|
||||||
|
#include "utils.h" // for Color, stringToColor, colorAreEqual
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
Demo::Demo()
|
||||||
|
: screen_(Screen::get()),
|
||||||
|
renderer_(Screen::get()->getRenderer()),
|
||||||
|
resource_(Resource::get()),
|
||||||
|
asset_(Asset::get()),
|
||||||
|
input_(Input::get()),
|
||||||
|
debug_(Debug::get())
|
||||||
|
{
|
||||||
|
// Inicia algunas variables
|
||||||
|
board_ = std::make_shared<ScoreboardData>();
|
||||||
|
board_->ini_clock = SDL_GetTicks();
|
||||||
|
rooms_.push_back("04.room");
|
||||||
|
rooms_.push_back("54.room");
|
||||||
|
rooms_.push_back("20.room");
|
||||||
|
rooms_.push_back("09.room");
|
||||||
|
rooms_.push_back("05.room");
|
||||||
|
rooms_.push_back("11.room");
|
||||||
|
rooms_.push_back("31.room");
|
||||||
|
rooms_.push_back("44.room");
|
||||||
|
|
||||||
|
room_index_ = 0;
|
||||||
|
current_room_ = rooms_[room_index_];
|
||||||
|
|
||||||
|
// Crea los objetos
|
||||||
|
ItemTracker::init();
|
||||||
|
scoreboard_ = std::make_shared<Scoreboard>(board_);
|
||||||
|
room_ = std::make_shared<Room>(resource_->getRoom(current_room_), board_);
|
||||||
|
text_ = resource_->getText("smb2");
|
||||||
|
|
||||||
|
// Inicializa el resto de variables
|
||||||
|
counter_ = 0;
|
||||||
|
room_time_ = 400;
|
||||||
|
ticks_ = 0;
|
||||||
|
board_->lives = 9;
|
||||||
|
board_->items = 0;
|
||||||
|
board_->rooms = 1;
|
||||||
|
board_->jail_is_open = false;
|
||||||
|
board_->music = true;
|
||||||
|
setScoreBoardColor();
|
||||||
|
|
||||||
|
options.section.section = Section::DEMO;
|
||||||
|
options.section.subsection = Subsection::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
Demo::~Demo()
|
||||||
|
{
|
||||||
|
ItemTracker::destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba los eventos de la cola
|
||||||
|
void Demo::checkEvents()
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
globalEvents::check(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
void Demo::checkInput()
|
||||||
|
{
|
||||||
|
globalInputs::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bucle para el juego
|
||||||
|
void Demo::run()
|
||||||
|
{
|
||||||
|
while (options.section.section == Section::DEMO)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
checkEvents();
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza el juego, las variables, comprueba la entrada, etc.
|
||||||
|
void Demo::update()
|
||||||
|
{
|
||||||
|
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
||||||
|
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
|
||||||
|
{
|
||||||
|
// Actualiza el contador de ticks
|
||||||
|
ticks_ = SDL_GetTicks();
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
checkInput();
|
||||||
|
|
||||||
|
// Actualiza los objetos
|
||||||
|
room_->update();
|
||||||
|
scoreboard_->update();
|
||||||
|
checkRoomChange();
|
||||||
|
|
||||||
|
screen_->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pinta los objetos en pantalla
|
||||||
|
void Demo::render()
|
||||||
|
{
|
||||||
|
// Prepara para dibujar el frame
|
||||||
|
screen_->start();
|
||||||
|
|
||||||
|
// Dibuja los elementos del juego en orden
|
||||||
|
room_->renderMap();
|
||||||
|
room_->renderEnemies();
|
||||||
|
room_->renderItems();
|
||||||
|
renderRoomName();
|
||||||
|
scoreboard_->render();
|
||||||
|
|
||||||
|
// Actualiza la pantalla
|
||||||
|
screen_->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escribe el nombre de la pantalla
|
||||||
|
void Demo::renderRoomName()
|
||||||
|
{
|
||||||
|
// Texto en el centro de la pantalla
|
||||||
|
SDL_Rect rect = {0, 16 * BLOCK, PLAY_AREA_WIDTH, BLOCK * 2};
|
||||||
|
Color color = stringToColor(options.video.palette, "white");
|
||||||
|
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 0xFF);
|
||||||
|
SDL_RenderFillRect(renderer_, &rect);
|
||||||
|
|
||||||
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, 16 * 8 + 4, room_->getName(), 1, room_->getBGColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recarga todas las texturas
|
||||||
|
void Demo::reLoadTextures()
|
||||||
|
{
|
||||||
|
if (options.console)
|
||||||
|
{
|
||||||
|
std::cout << "** RELOAD REQUESTED" << std::endl;
|
||||||
|
}
|
||||||
|
room_->reLoadTexture();
|
||||||
|
scoreboard_->reLoadTexture();
|
||||||
|
text_->reLoadTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cambia la paleta
|
||||||
|
void Demo::switchPalette()
|
||||||
|
{
|
||||||
|
// Modifica la variable
|
||||||
|
if (options.video.palette == Palette::ZXSPECTRUM)
|
||||||
|
{
|
||||||
|
options.video.palette = Palette::ZXARNE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
options.video.palette = Palette::ZXSPECTRUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
room_->reLoadPalette();
|
||||||
|
scoreboard_->reLoadPalette();
|
||||||
|
|
||||||
|
// Pone el color del marcador en función del color del borde de la habitación
|
||||||
|
setScoreBoardColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cambia de habitación
|
||||||
|
bool Demo::changeRoom(std::string file)
|
||||||
|
{
|
||||||
|
// En las habitaciones los limites tienen la cadena del fichero o un 0 en caso de no limitar con nada
|
||||||
|
if (file != "0")
|
||||||
|
{
|
||||||
|
// Verifica que exista el fichero que se va a cargar
|
||||||
|
if (asset_->get(file) != "")
|
||||||
|
{
|
||||||
|
// Crea un objeto habitación a partir del fichero
|
||||||
|
room_ = std::make_shared<Room>(resource_->getRoom(file), board_);
|
||||||
|
|
||||||
|
// Pone el color del marcador en función del color del borde de la habitación
|
||||||
|
setScoreBoardColor();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba si se ha de cambiar de habitación
|
||||||
|
void Demo::checkRoomChange()
|
||||||
|
{
|
||||||
|
counter_++;
|
||||||
|
if (counter_ == room_time_)
|
||||||
|
{
|
||||||
|
counter_ = 0;
|
||||||
|
room_index_++;
|
||||||
|
if (room_index_ == (int)rooms_.size())
|
||||||
|
{
|
||||||
|
options.section.section = Section::LOGO;
|
||||||
|
options.section.subsection = Subsection::LOGO_TO_TITLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
changeRoom(rooms_[room_index_]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pone el color del marcador en función del color del borde de la habitación
|
||||||
|
void Demo::setScoreBoardColor()
|
||||||
|
{
|
||||||
|
// Obtiene el color del borde
|
||||||
|
const Color color = room_->getBorderColor();
|
||||||
|
|
||||||
|
// Si el color es negro lo cambia a blanco
|
||||||
|
const Color black_color = stringToColor(options.video.palette, "black");
|
||||||
|
board_->color = colorAreEqual(color, black_color) ? stringToColor(options.video.palette, "white") : color;
|
||||||
|
|
||||||
|
// Si el color es negro brillante lo cambia a blanco
|
||||||
|
const Color bright_blac_color = stringToColor(options.video.palette, "bright_black");
|
||||||
|
board_->color = colorAreEqual(color, bright_blac_color) ? stringToColor(options.video.palette, "white") : color;
|
||||||
|
}
|
||||||
80
source/demo.h
Normal file
80
source/demo.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL_render.h> // for SDL_Renderer
|
||||||
|
#include <SDL2/SDL_stdinc.h> // for Uint32
|
||||||
|
#include <memory> // for shared_ptr
|
||||||
|
#include <string> // for string
|
||||||
|
#include <vector> // for vector
|
||||||
|
#include "scoreboard.h" // for board_t
|
||||||
|
class Asset; // lines 11-11
|
||||||
|
class Debug; // lines 12-12
|
||||||
|
class Input; // lines 13-13
|
||||||
|
class ItemTracker; // lines 14-14
|
||||||
|
class Resource; // lines 15-15
|
||||||
|
class Room; // lines 16-16
|
||||||
|
class Screen; // lines 17-17
|
||||||
|
class Text; // lines 18-18
|
||||||
|
|
||||||
|
class Demo
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// Objetos y punteros
|
||||||
|
Screen *screen_; // Objeto encargado de manejar el renderizador
|
||||||
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
|
Resource *resource_; // Objeto con los recursos
|
||||||
|
Asset *asset_; // Objeto con la ruta a todos los ficheros de recursos
|
||||||
|
Input *input_; // Objeto pata gestionar la entrada
|
||||||
|
Debug *debug_; // Objeto para gestionar la información de debug
|
||||||
|
std::shared_ptr<Room> room_; // Objeto encargado de gestionar cada habitación del juego
|
||||||
|
std::shared_ptr<Text> text_; // Objeto para los textos del juego
|
||||||
|
std::shared_ptr<Scoreboard> scoreboard_; // Objeto encargado de gestionar el marcador
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
|
||||||
|
std::string current_room_; // Fichero de la habitación actual
|
||||||
|
std::shared_ptr<ScoreboardData> board_; // Estructura con los datos del marcador
|
||||||
|
int counter_; // Contador para el modo demo
|
||||||
|
int room_time_; // Tiempo que se muestra cada habitacion
|
||||||
|
int room_index_; // Indice para el vector de habitaciones
|
||||||
|
std::vector<std::string> rooms_; // Listado con los mapas de la demo
|
||||||
|
|
||||||
|
// Actualiza el juego, las variables, comprueba la entrada, etc.
|
||||||
|
void update();
|
||||||
|
|
||||||
|
// Pinta los objetos en pantalla
|
||||||
|
void render();
|
||||||
|
|
||||||
|
// Comprueba los eventos de la cola
|
||||||
|
void checkEvents();
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
void checkInput();
|
||||||
|
|
||||||
|
// Escribe el nombre de la pantalla
|
||||||
|
void renderRoomName();
|
||||||
|
|
||||||
|
// Recarga todas las texturas
|
||||||
|
void reLoadTextures();
|
||||||
|
|
||||||
|
// Cambia la paleta
|
||||||
|
void switchPalette();
|
||||||
|
|
||||||
|
// Cambia de habitación
|
||||||
|
bool changeRoom(std::string file);
|
||||||
|
|
||||||
|
// Comprueba si se ha de cambiar de habitación
|
||||||
|
void checkRoomChange();
|
||||||
|
|
||||||
|
// Pone el color del marcador en función del color del borde de la habitación
|
||||||
|
void setScoreBoardColor();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
Demo();
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~Demo();
|
||||||
|
|
||||||
|
// Bucle para el juego
|
||||||
|
void run();
|
||||||
|
};
|
||||||
2089
source/director.cpp
2089
source/director.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,82 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <SDL2/SDL.h>
|
|
||||||
#include "jail_engine/asset.h"
|
|
||||||
#include "jail_engine/debug.h"
|
|
||||||
#include "jail_engine/input.h"
|
|
||||||
#include "jail_engine/jail_audio.h"
|
|
||||||
#include "jail_engine/movingsprite.h"
|
|
||||||
#include "jail_engine/resource.h"
|
|
||||||
#include "jail_engine/sprite.h"
|
|
||||||
#include "jail_engine/text.h"
|
|
||||||
#include "jail_engine/utils.h"
|
|
||||||
#include "const.h"
|
|
||||||
#include "gamestate_credits.h"
|
|
||||||
#include "gamestate_demo.h"
|
|
||||||
#include "gamestate_ending.h"
|
|
||||||
#include "gamestate_ending2.h"
|
|
||||||
#include "enter_id.h"
|
|
||||||
#include "gamestate_game_over.h"
|
|
||||||
#include "gamestate_game.h"
|
|
||||||
#include "gamestate_loading_screen.h"
|
|
||||||
#include "gamestate_logo.h"
|
|
||||||
#include "online.h"
|
|
||||||
#include "gamestate_title.h"
|
|
||||||
|
|
||||||
#ifndef DIRECTOR_H
|
#include <SDL2/SDL_render.h> // for SDL_Renderer
|
||||||
#define DIRECTOR_H
|
#include <SDL2/SDL_video.h> // for SDL_Window
|
||||||
|
#include <string> // for string
|
||||||
|
struct JA_Music_t; // lines 11-11
|
||||||
|
|
||||||
class Director
|
class Director
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Objetos y punteros
|
// Objetos y punteros
|
||||||
SDL_Window *window; // La ventana donde dibujamos
|
SDL_Window *window_; // La ventana donde dibujamos
|
||||||
SDL_Renderer *renderer; // El renderizador de la ventana
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
Screen *screen; // Objeto encargado de dibujar en pantalla
|
|
||||||
Resource *resource; // Objeto con los recursos
|
|
||||||
Asset *asset; // Objeto que gestiona todos los ficheros de recursos
|
|
||||||
Input *input; // Objeto Input para gestionar las entradas
|
|
||||||
Game *game; // Objeto para gestionar la sección del juego
|
|
||||||
Logo *logo; // Objeto para gestionar la sección del logo del programa
|
|
||||||
Title *title; // Objeto para gestionar la pantalla de título
|
|
||||||
LoadingScreen *loadingScreen; // Objeto para gestionar la introducción del juego
|
|
||||||
Credits *credits; // Objeto para gestionar los creditos del juego
|
|
||||||
Demo *demo; // Objeto para gestionar el modo demo, en el que se ven pantallas del juego
|
|
||||||
Ending *ending; // Objeto para gestionar el final del juego
|
|
||||||
Ending2 *ending2; // Objeto para gestionar el final del juego
|
|
||||||
GameOver *gameOver; // Objeto para gestionar el final de la partida
|
|
||||||
Debug *debug; // Objeto para getsionar la información de debug
|
|
||||||
Online *online; // Objeto para gestionar la lectura y escritura de datos en el servidor remoto
|
|
||||||
struct options_t *options; // Variable con todas las opciones del programa
|
|
||||||
section_t *section; // Sección y subsección actual del programa;
|
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
JA_Music_t *music; // Musica del titulo
|
std::string executable_path_; // Path del ejecutable
|
||||||
std::string executablePath; // Path del ejecutable
|
std::string system_folder_; // Carpeta del sistema donde guardar datos
|
||||||
std::string systemFolder; // Carpeta del sistema donde guardar datos
|
|
||||||
|
|
||||||
// Crea e inicializa las opciones del programa
|
|
||||||
void initOptions();
|
|
||||||
|
|
||||||
// Inicializa los servicios online
|
|
||||||
void initOnline();
|
|
||||||
|
|
||||||
// Comprueba los parametros del programa
|
// Comprueba los parametros del programa
|
||||||
void checkProgramArguments(int argc, char *argv[]);
|
std::string checkProgramArguments(int argc, const char *argv[]);
|
||||||
|
|
||||||
// Carga el fichero de configuración
|
|
||||||
bool loadConfig();
|
|
||||||
|
|
||||||
// Guarda el fichero de configuración
|
|
||||||
bool saveConfig();
|
|
||||||
|
|
||||||
// Crea la carpeta del sistema donde guardar datos
|
// Crea la carpeta del sistema donde guardar datos
|
||||||
void createSystemFolder(std::string folder);
|
void createSystemFolder(const std::string &folder);
|
||||||
|
|
||||||
// Carga los recursos
|
|
||||||
void loadResources(section_t *section);
|
|
||||||
|
|
||||||
// Asigna variables a partir de dos cadenas
|
|
||||||
bool setOptions(options_t *options, std::string var, std::string value);
|
|
||||||
|
|
||||||
// Inicializa jail_audio
|
// Inicializa jail_audio
|
||||||
void initJailAudio();
|
void initJailAudio();
|
||||||
@@ -119,13 +63,11 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
Director(int argc, char *argv[]);
|
Director(int argc, const char *argv[]);
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~Director();
|
~Director();
|
||||||
|
|
||||||
// Bucle principal
|
// Bucle principal
|
||||||
void run();
|
int run();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
565
source/ending.cpp
Normal file
565
source/ending.cpp
Normal file
@@ -0,0 +1,565 @@
|
|||||||
|
#include "ending.h"
|
||||||
|
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
|
||||||
|
#include <SDL2/SDL_error.h> // for SDL_GetError
|
||||||
|
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
|
||||||
|
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
|
||||||
|
#include <SDL2/SDL_rect.h> // for SDL_Rect
|
||||||
|
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
|
||||||
|
#include <algorithm> // for min
|
||||||
|
#include <iostream> // for basic_ostream, operator<<, cout, endl
|
||||||
|
#include "asset.h" // for Asset
|
||||||
|
#include "defines.h" // for GAMECANVAS_HEIGHT, GAMECANVAS_WIDTH
|
||||||
|
#include "global_events.h" // for check
|
||||||
|
#include "global_inputs.h" // for check
|
||||||
|
#include "input.h" // for Input
|
||||||
|
#include "jail_audio.h" // for JA_SetVolume, JA_PlayMusic, JA_StopM...
|
||||||
|
#include "options.h" // for Options, options, OptionsVideo, Sect...
|
||||||
|
#include "resource.h" // for Resource
|
||||||
|
#include "screen.h" // for Screen
|
||||||
|
#include "sprite.h" // for Sprite
|
||||||
|
#include "text.h" // for Text, TEXT_STROKE
|
||||||
|
#include "texture.h" // for Texture
|
||||||
|
#include "utils.h" // for Color, stringToColor, Palette
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
Ending::Ending()
|
||||||
|
: screen_(Screen::get()),
|
||||||
|
renderer_(Screen::get()->getRenderer()),
|
||||||
|
resource_(Resource::get()),
|
||||||
|
asset_(Asset::get()),
|
||||||
|
input_(Input::get())
|
||||||
|
{
|
||||||
|
// Reserva memoria para los punteros a objetos
|
||||||
|
text_ = resource_->getText("smb2");
|
||||||
|
music = resource_->getMusic("ending1.ogg");
|
||||||
|
|
||||||
|
// Inicializa variables
|
||||||
|
counter_ = -1;
|
||||||
|
pre_counter_ = 0;
|
||||||
|
cover_counter_ = 0;
|
||||||
|
options.section.section = Section::ENDING;
|
||||||
|
options.section.subsection = Subsection::NONE;
|
||||||
|
ticks_ = 0;
|
||||||
|
current_scene_ = 0;
|
||||||
|
|
||||||
|
// Inicializa los textos
|
||||||
|
iniTexts();
|
||||||
|
|
||||||
|
// Inicializa las imagenes
|
||||||
|
iniPics();
|
||||||
|
|
||||||
|
// Inicializa las escenas
|
||||||
|
iniScenes();
|
||||||
|
|
||||||
|
// Cambia el color del borde
|
||||||
|
screen_->setBorderColor(stringToColor(options.video.palette, "black"));
|
||||||
|
|
||||||
|
// Crea la textura para cubrir el rexto
|
||||||
|
cover_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT + 8);
|
||||||
|
if (cover_texture_ == nullptr)
|
||||||
|
{
|
||||||
|
if (options.console)
|
||||||
|
{
|
||||||
|
std::cout << "Error: canvasTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_SetTextureBlendMode(cover_texture_, SDL_BLENDMODE_BLEND);
|
||||||
|
|
||||||
|
// Rellena la textura para la cortinilla
|
||||||
|
fillCoverTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
Ending::~Ending()
|
||||||
|
{
|
||||||
|
// Libera la memoria de los objetos
|
||||||
|
SDL_DestroyTexture(cover_texture_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza el objeto
|
||||||
|
void Ending::update()
|
||||||
|
{
|
||||||
|
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
||||||
|
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
|
||||||
|
{
|
||||||
|
// Actualiza el contador de ticks
|
||||||
|
ticks_ = SDL_GetTicks();
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
checkInput();
|
||||||
|
|
||||||
|
// Actualiza el contador
|
||||||
|
updateCounters();
|
||||||
|
|
||||||
|
// Actualiza las cortinillas de los elementos
|
||||||
|
updateSpriteCovers();
|
||||||
|
|
||||||
|
// Comprueba si se ha de cambiar de escena
|
||||||
|
checkChangeScene();
|
||||||
|
|
||||||
|
// Actualiza el volumen de la musica
|
||||||
|
updateMusicVolume();
|
||||||
|
|
||||||
|
screen_->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja el final en pantalla
|
||||||
|
void Ending::render()
|
||||||
|
{
|
||||||
|
// Prepara para empezar a dibujar en la textura de juego
|
||||||
|
screen_->start();
|
||||||
|
|
||||||
|
// Limpia la pantalla
|
||||||
|
screen_->clean(stringToColor(options.video.palette, "black"));
|
||||||
|
|
||||||
|
// Dibuja las imagenes de la escena
|
||||||
|
sprite_pics_[current_scene_].sprite->render();
|
||||||
|
sprite_pics_[current_scene_].cover_sprite->render();
|
||||||
|
|
||||||
|
// Dibuja los textos de la escena
|
||||||
|
for (auto ti : scenes_[current_scene_].text_index)
|
||||||
|
{
|
||||||
|
if (counter_ > ti.trigger)
|
||||||
|
{
|
||||||
|
sprite_texts_[ti.index].sprite->render();
|
||||||
|
sprite_texts_[ti.index].cover_sprite->render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja la cortinilla de cambio de escena
|
||||||
|
renderCoverTexture();
|
||||||
|
|
||||||
|
// Vuelca el contenido del renderizador en pantalla
|
||||||
|
screen_->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba el manejador de eventos
|
||||||
|
void Ending::checkEvents()
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
globalEvents::check(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
void Ending::checkInput()
|
||||||
|
{
|
||||||
|
globalInputs::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicializa los textos
|
||||||
|
void Ending::iniTexts()
|
||||||
|
{
|
||||||
|
// Vector con los textos
|
||||||
|
std::vector<TextAndPosition> texts;
|
||||||
|
|
||||||
|
// Escena #0
|
||||||
|
texts.push_back({"HE FINALLY MANAGED", 32});
|
||||||
|
texts.push_back({"TO GET TO THE JAIL", 42});
|
||||||
|
texts.push_back({"WITH ALL HIS PROJECTS", 142});
|
||||||
|
texts.push_back({"READY TO BE FREED", 152});
|
||||||
|
|
||||||
|
// Escena #1
|
||||||
|
texts.push_back({"ALL THE JAILERS WERE THERE", 1});
|
||||||
|
texts.push_back({"WAITING FOR THE JAILGAMES", 11});
|
||||||
|
texts.push_back({"TO BE RELEASED", 21});
|
||||||
|
|
||||||
|
texts.push_back({"THERE WERE EVEN BARRULLS AND", 161});
|
||||||
|
texts.push_back({"BEGINNERS AMONG THE CROWD", 171});
|
||||||
|
|
||||||
|
texts.push_back({"BRY WAS CRYING...", 181});
|
||||||
|
|
||||||
|
// Escena #2
|
||||||
|
texts.push_back({"BUT SUDDENLY SOMETHING", 19});
|
||||||
|
texts.push_back({"CAUGHT HIS ATTENTION", 29});
|
||||||
|
|
||||||
|
// Escena #3
|
||||||
|
texts.push_back({"A PILE OF JUNK!", 36});
|
||||||
|
texts.push_back({"FULL OF NON WORKING TRASH!!", 46});
|
||||||
|
|
||||||
|
// Escena #4
|
||||||
|
texts.push_back({"AND THEN,", 36});
|
||||||
|
texts.push_back({"FOURTY NEW PROJECTS", 46});
|
||||||
|
texts.push_back({"WERE BORN...", 158});
|
||||||
|
|
||||||
|
// Crea los sprites
|
||||||
|
sprite_texts_.clear();
|
||||||
|
|
||||||
|
for (auto t : texts)
|
||||||
|
{
|
||||||
|
EndingTexture st;
|
||||||
|
const int width = text_->lenght(t.caption, 1) + 2 + 2;
|
||||||
|
const int height = text_->getCharacterSize() + 2 + 2;
|
||||||
|
Color c = stringToColor(options.video.palette, "black");
|
||||||
|
|
||||||
|
// Crea la texture
|
||||||
|
st.texture = std::make_shared<Texture>(renderer_);
|
||||||
|
st.texture->createBlank(width, height);
|
||||||
|
st.texture->setAsRenderTarget(renderer_);
|
||||||
|
st.texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
||||||
|
text_->writeDX(TEXT_STROKE, 2, 2, t.caption, 1, c, 2, c);
|
||||||
|
|
||||||
|
// Crea el sprite
|
||||||
|
st.sprite = std::make_shared<Sprite>(st.texture, 0, 0, st.texture->getWidth(), st.texture->getHeight());
|
||||||
|
st.sprite->setPosition((GAMECANVAS_WIDTH - st.texture->getWidth()) / 2, t.pos);
|
||||||
|
|
||||||
|
// Crea la coverTexture
|
||||||
|
st.cover_texture = std::make_shared<Texture>(renderer_);
|
||||||
|
st.cover_texture->createBlank(width, height + 8);
|
||||||
|
st.cover_texture->setAsRenderTarget(renderer_);
|
||||||
|
st.cover_texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
||||||
|
|
||||||
|
// Rellena la coverTexture con color transparente
|
||||||
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
||||||
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
|
// Los primeros 8 pixels crea una malla
|
||||||
|
c = stringToColor(options.video.palette, "black");
|
||||||
|
SDL_SetRenderDrawColor(renderer_, c.r, c.g, c.b, 0xFF);
|
||||||
|
for (int i = 0; i < width; i += 2)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 0);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 2);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 4);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 6);
|
||||||
|
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 1, 5);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 1, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// El resto se rellena de color sólido
|
||||||
|
SDL_Rect rect = {0, 8, width, height};
|
||||||
|
c = stringToColor(options.video.palette, "black");
|
||||||
|
SDL_SetRenderDrawColor(renderer_, c.r, c.g, c.b, 0xFF);
|
||||||
|
SDL_RenderFillRect(renderer_, &rect);
|
||||||
|
|
||||||
|
// Crea el sprite
|
||||||
|
st.cover_sprite = std::make_shared<Sprite>(st.cover_texture, 0, 0, st.cover_texture->getWidth(), st.cover_texture->getHeight() - 8);
|
||||||
|
st.cover_sprite->setPosition((GAMECANVAS_WIDTH - st.cover_texture->getWidth()) / 2, t.pos);
|
||||||
|
st.cover_sprite->setClip(0, 8, -1, -1);
|
||||||
|
|
||||||
|
// Inicializa variables
|
||||||
|
st.clip_desp = 8;
|
||||||
|
st.clip_height = height;
|
||||||
|
|
||||||
|
sprite_texts_.push_back(st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicializa las imagenes
|
||||||
|
void Ending::iniPics()
|
||||||
|
{
|
||||||
|
// Vector con las rutas y la posición
|
||||||
|
std::vector<TextAndPosition> pics;
|
||||||
|
|
||||||
|
if (options.video.palette == Palette::ZXSPECTRUM)
|
||||||
|
{
|
||||||
|
pics.push_back({"ending1.png", 48});
|
||||||
|
pics.push_back({"ending2.png", 26});
|
||||||
|
pics.push_back({"ending3.png", 29});
|
||||||
|
pics.push_back({"ending4.png", 63});
|
||||||
|
pics.push_back({"ending5.png", 53});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pics.push_back({"ending1_zxarne.png", 48});
|
||||||
|
pics.push_back({"ending2_zxarne.png", 26});
|
||||||
|
pics.push_back({"ending3_zxarne.png", 29});
|
||||||
|
pics.push_back({"ending4_zxarne.png", 63});
|
||||||
|
pics.push_back({"ending5_zxarne.png", 53});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crea los sprites
|
||||||
|
sprite_pics_.clear();
|
||||||
|
|
||||||
|
for (auto p : pics)
|
||||||
|
{
|
||||||
|
EndingTexture sp;
|
||||||
|
|
||||||
|
// Crea la texture
|
||||||
|
sp.texture = resource_->getTexture(p.caption);
|
||||||
|
const int width = sp.texture->getWidth();
|
||||||
|
const int height = sp.texture->getHeight();
|
||||||
|
|
||||||
|
// Crea el sprite
|
||||||
|
sp.sprite = std::make_shared<Sprite>(sp.texture, 0, 0, width, height);
|
||||||
|
sp.sprite->setPosition((GAMECANVAS_WIDTH - width) / 2, p.pos);
|
||||||
|
|
||||||
|
// Crea la coverTexture
|
||||||
|
sp.cover_texture = std::make_shared<Texture>(renderer_);
|
||||||
|
sp.cover_texture->createBlank(width, height + 8);
|
||||||
|
sp.cover_texture->setAsRenderTarget(renderer_);
|
||||||
|
sp.cover_texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
||||||
|
|
||||||
|
// Rellena la coverTexture con color transparente
|
||||||
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
||||||
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
|
// Los primeros 8 pixels crea una malla
|
||||||
|
Color c = stringToColor(options.video.palette, "black");
|
||||||
|
SDL_SetRenderDrawColor(renderer_, c.r, c.g, c.b, 0xFF);
|
||||||
|
for (int i = 0; i < width; i += 2)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 0);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 2);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 4);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 6);
|
||||||
|
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 1, 5);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 1, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// El resto se rellena de color sólido
|
||||||
|
SDL_Rect rect = {0, 8, width, height};
|
||||||
|
c = stringToColor(options.video.palette, "black");
|
||||||
|
SDL_SetRenderDrawColor(renderer_, c.r, c.g, c.b, 0xFF);
|
||||||
|
SDL_RenderFillRect(renderer_, &rect);
|
||||||
|
|
||||||
|
// Crea el sprite
|
||||||
|
sp.cover_sprite = std::make_shared<Sprite>(sp.cover_texture, 0, 0, sp.cover_texture->getWidth(), sp.cover_texture->getHeight() - 8);
|
||||||
|
sp.cover_sprite->setPosition((GAMECANVAS_WIDTH - sp.cover_texture->getWidth()) / 2, p.pos);
|
||||||
|
sp.cover_sprite->setClip(0, 8, -1, -1);
|
||||||
|
|
||||||
|
// Inicializa variables
|
||||||
|
sp.clip_desp = 8;
|
||||||
|
sp.clip_height = height;
|
||||||
|
|
||||||
|
sprite_pics_.push_back(sp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicializa las escenas
|
||||||
|
void Ending::iniScenes()
|
||||||
|
{
|
||||||
|
// Variable para los tiempos
|
||||||
|
int trigger;
|
||||||
|
const int lapse = 80;
|
||||||
|
|
||||||
|
// Crea el contenedor
|
||||||
|
SceneData sc;
|
||||||
|
|
||||||
|
// Inicializa el vector
|
||||||
|
scenes_.clear();
|
||||||
|
|
||||||
|
// Crea la escena #0
|
||||||
|
sc.counter_end = 1000;
|
||||||
|
sc.picture_index = 0;
|
||||||
|
sc.text_index.clear();
|
||||||
|
trigger = 85 * 2;
|
||||||
|
trigger += lapse;
|
||||||
|
sc.text_index.push_back({0, trigger});
|
||||||
|
trigger += lapse;
|
||||||
|
sc.text_index.push_back({1, trigger});
|
||||||
|
trigger += lapse * 3;
|
||||||
|
sc.text_index.push_back({2, trigger});
|
||||||
|
trigger += lapse;
|
||||||
|
sc.text_index.push_back({3, trigger});
|
||||||
|
scenes_.push_back(sc);
|
||||||
|
|
||||||
|
// Crea la escena #1
|
||||||
|
sc.counter_end = 1400;
|
||||||
|
sc.picture_index = 1;
|
||||||
|
sc.text_index.clear();
|
||||||
|
trigger = 140 * 2;
|
||||||
|
trigger += lapse;
|
||||||
|
sc.text_index.push_back({4, trigger});
|
||||||
|
trigger += lapse;
|
||||||
|
sc.text_index.push_back({5, trigger});
|
||||||
|
trigger += lapse;
|
||||||
|
sc.text_index.push_back({6, trigger});
|
||||||
|
trigger += lapse * 3;
|
||||||
|
sc.text_index.push_back({7, trigger});
|
||||||
|
trigger += lapse;
|
||||||
|
sc.text_index.push_back({8, trigger});
|
||||||
|
trigger += lapse * 3;
|
||||||
|
sc.text_index.push_back({9, trigger});
|
||||||
|
scenes_.push_back(sc);
|
||||||
|
|
||||||
|
// Crea la escena #2
|
||||||
|
sc.counter_end = 1000;
|
||||||
|
sc.picture_index = 2;
|
||||||
|
sc.text_index.clear();
|
||||||
|
trigger = 148 / 2;
|
||||||
|
trigger += lapse;
|
||||||
|
sc.text_index.push_back({10, trigger});
|
||||||
|
trigger += lapse;
|
||||||
|
sc.text_index.push_back({11, trigger});
|
||||||
|
scenes_.push_back(sc);
|
||||||
|
|
||||||
|
// Crea la escena #3
|
||||||
|
sc.counter_end = 800;
|
||||||
|
sc.picture_index = 3;
|
||||||
|
sc.text_index.clear();
|
||||||
|
trigger = 87 / 2;
|
||||||
|
trigger += lapse;
|
||||||
|
sc.text_index.push_back({12, trigger});
|
||||||
|
trigger += lapse / 2;
|
||||||
|
sc.text_index.push_back({13, trigger});
|
||||||
|
scenes_.push_back(sc);
|
||||||
|
|
||||||
|
// Crea la escena #4
|
||||||
|
sc.counter_end = 1000;
|
||||||
|
sc.picture_index = 4;
|
||||||
|
sc.text_index.clear();
|
||||||
|
trigger = 91 * 2;
|
||||||
|
trigger += lapse;
|
||||||
|
sc.text_index.push_back({14, trigger});
|
||||||
|
trigger += lapse * 2;
|
||||||
|
sc.text_index.push_back({15, trigger});
|
||||||
|
trigger += lapse * 3;
|
||||||
|
sc.text_index.push_back({16, trigger});
|
||||||
|
scenes_.push_back(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bucle principal
|
||||||
|
void Ending::run()
|
||||||
|
{
|
||||||
|
JA_PlayMusic(music);
|
||||||
|
|
||||||
|
while (options.section.section == Section::ENDING)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
checkEvents();
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
|
||||||
|
JA_StopMusic();
|
||||||
|
JA_SetVolume(128);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza los contadores
|
||||||
|
void Ending::updateCounters()
|
||||||
|
{
|
||||||
|
// Incrementa el contador
|
||||||
|
if (pre_counter_ < 200)
|
||||||
|
{
|
||||||
|
pre_counter_++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
counter_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (counter_ > scenes_[current_scene_].counter_end - 100)
|
||||||
|
{
|
||||||
|
cover_counter_++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza las cortinillas de los elementos
|
||||||
|
void Ending::updateSpriteCovers()
|
||||||
|
{ // Actualiza la cortinilla de los textos
|
||||||
|
if (counter_ % 4 == 0)
|
||||||
|
{
|
||||||
|
for (auto ti : scenes_[current_scene_].text_index)
|
||||||
|
{
|
||||||
|
if (counter_ > ti.trigger)
|
||||||
|
{
|
||||||
|
if (sprite_texts_[ti.index].clip_desp > 0)
|
||||||
|
{
|
||||||
|
sprite_texts_[ti.index].clip_desp -= 2;
|
||||||
|
}
|
||||||
|
else if (sprite_texts_[ti.index].clip_height > 0)
|
||||||
|
{
|
||||||
|
sprite_texts_[ti.index].clip_height -= 2;
|
||||||
|
sprite_texts_[ti.index].cover_sprite->setY(sprite_texts_[ti.index].cover_sprite->getY() + 2);
|
||||||
|
}
|
||||||
|
sprite_texts_[ti.index].cover_sprite->setClip(0, sprite_texts_[ti.index].clip_desp, sprite_texts_[ti.index].cover_sprite->getWidth(), sprite_texts_[ti.index].clip_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza la cortinilla de las imagenes
|
||||||
|
if (counter_ % 2 == 0)
|
||||||
|
{
|
||||||
|
if (sprite_pics_[current_scene_].clip_desp > 0)
|
||||||
|
{
|
||||||
|
sprite_pics_[current_scene_].clip_desp -= 2;
|
||||||
|
}
|
||||||
|
else if (sprite_pics_[current_scene_].clip_height > 0)
|
||||||
|
{
|
||||||
|
sprite_pics_[current_scene_].clip_height -= 2;
|
||||||
|
if (sprite_pics_[current_scene_].clip_height < 0)
|
||||||
|
{
|
||||||
|
sprite_pics_[current_scene_].clip_height = 0;
|
||||||
|
}
|
||||||
|
sprite_pics_[current_scene_].cover_sprite->setY(sprite_pics_[current_scene_].cover_sprite->getY() + 2);
|
||||||
|
}
|
||||||
|
sprite_pics_[current_scene_].cover_sprite->setClip(0, sprite_pics_[current_scene_].clip_desp, sprite_pics_[current_scene_].cover_sprite->getWidth(), sprite_pics_[current_scene_].clip_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba si se ha de cambiar de escena
|
||||||
|
void Ending::checkChangeScene()
|
||||||
|
{
|
||||||
|
if (counter_ > scenes_[current_scene_].counter_end)
|
||||||
|
{
|
||||||
|
current_scene_++;
|
||||||
|
counter_ = 0;
|
||||||
|
cover_counter_ = 0;
|
||||||
|
if (current_scene_ == 5)
|
||||||
|
{
|
||||||
|
// Termina el bucle
|
||||||
|
options.section.section = Section::ENDING2;
|
||||||
|
|
||||||
|
// Mantiene los valores anteriores
|
||||||
|
current_scene_ = 4;
|
||||||
|
cover_counter_ = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rellena la textura para la cortinilla
|
||||||
|
void Ending::fillCoverTexture()
|
||||||
|
{
|
||||||
|
// Rellena la textura que cubre el texto con color transparente
|
||||||
|
SDL_SetRenderTarget(renderer_, cover_texture_);
|
||||||
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
||||||
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
|
// Los primeros 8 pixels crea una malla
|
||||||
|
const Color color = stringToColor(options.video.palette, "black");
|
||||||
|
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 0xFF);
|
||||||
|
for (int i = 0; i < 256; i += 2)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 0, GAMECANVAS_HEIGHT + 0);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 1, GAMECANVAS_HEIGHT + 1);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 0, GAMECANVAS_HEIGHT + 2);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 1, GAMECANVAS_HEIGHT + 3);
|
||||||
|
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, GAMECANVAS_HEIGHT + 4);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, GAMECANVAS_HEIGHT + 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
// El resto se rellena de color sólido
|
||||||
|
SDL_Rect rect = {0, 0, 256, GAMECANVAS_HEIGHT};
|
||||||
|
SDL_RenderFillRect(renderer_, &rect);
|
||||||
|
|
||||||
|
SDL_SetRenderTarget(renderer_, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja la cortinilla de cambio de escena
|
||||||
|
void Ending::renderCoverTexture()
|
||||||
|
{
|
||||||
|
if (cover_counter_ > 0)
|
||||||
|
{ // Dibuja la textura que cubre el texto
|
||||||
|
const int offset = std::min(cover_counter_, 100);
|
||||||
|
SDL_Rect srcRect = {0, 200 - (cover_counter_ * 2), 256, offset * 2};
|
||||||
|
SDL_Rect dstRect = {0, 0, 256, offset * 2};
|
||||||
|
SDL_RenderCopy(renderer_, cover_texture_, &srcRect, &dstRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza el volumen de la musica
|
||||||
|
void Ending::updateMusicVolume()
|
||||||
|
{
|
||||||
|
if (current_scene_ == 4 && cover_counter_ > 0)
|
||||||
|
{
|
||||||
|
const float step = (100.0f - cover_counter_) / 100.0f;
|
||||||
|
const int volume = 128 * step;
|
||||||
|
JA_SetVolume(volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
118
source/ending.h
Normal file
118
source/ending.h
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
|
||||||
|
#include <SDL2/SDL_stdinc.h> // for Uint32
|
||||||
|
#include <memory> // for shared_ptr
|
||||||
|
#include <string> // for string
|
||||||
|
#include <vector> // for vector
|
||||||
|
class Asset; // lines 9-9
|
||||||
|
class Input; // lines 10-10
|
||||||
|
class Resource; // lines 11-11
|
||||||
|
class Screen; // lines 12-12
|
||||||
|
class Sprite; // lines 13-13
|
||||||
|
class Text; // lines 14-14
|
||||||
|
class Texture; // lines 15-15
|
||||||
|
struct JA_Music_t; // lines 16-16
|
||||||
|
|
||||||
|
class Ending
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// Estructuras
|
||||||
|
struct EndingTexture // Estructura con dos texturas y sprites, uno para mostrar y el otro hace de cortinilla
|
||||||
|
{
|
||||||
|
std::shared_ptr<Texture> texture; // Textura a mostrar
|
||||||
|
std::shared_ptr<Sprite> sprite; // Sprite para mostrar la textura
|
||||||
|
std::shared_ptr<Texture> cover_texture; // Textura que cubre a la otra textura
|
||||||
|
std::shared_ptr<Sprite> cover_sprite; // Sprite para mostrar la textura que cubre a la otra textura
|
||||||
|
int clip_desp; // Desplazamiento del spriteClip de la textura de cobertura
|
||||||
|
int clip_height; // Altura del spriteClip de la textura de cobertura
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TextAndPosition // Estructura con un texto y su posición en el eje Y
|
||||||
|
{
|
||||||
|
std::string caption; // Texto
|
||||||
|
int pos; // Posición
|
||||||
|
};
|
||||||
|
|
||||||
|
struct asdhk
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
int trigger;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SceneData // Estructura para crear cada una de las escenas del final
|
||||||
|
{
|
||||||
|
std::vector<asdhk> text_index; // Indices del vector de textos a mostrar y su disparador
|
||||||
|
int picture_index; // Indice del vector de imagenes a mostrar
|
||||||
|
int counter_end; // Valor del contador en el que finaliza la escena
|
||||||
|
};
|
||||||
|
|
||||||
|
// Objetos y punteros
|
||||||
|
Screen *screen_; // Objeto encargado de dibujar en pantalla
|
||||||
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
|
Resource *resource_; // Objeto con los recursos
|
||||||
|
Asset *asset_; // Objeto con los ficheros de recursos
|
||||||
|
Input *input_; // Objeto pata gestionar la entrada
|
||||||
|
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
|
||||||
|
SDL_Texture *cover_texture_; // Textura para cubrir el texto
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
int counter_; // Contador
|
||||||
|
int pre_counter_; // Contador previo
|
||||||
|
int cover_counter_; // Contador para la cortinilla
|
||||||
|
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
|
||||||
|
std::vector<EndingTexture> sprite_texts_; // Vector con los sprites de texto con su cortinilla
|
||||||
|
std::vector<EndingTexture> sprite_pics_; // Vector con los sprites de texto con su cortinilla
|
||||||
|
int current_scene_; // Escena actual
|
||||||
|
std::vector<SceneData> scenes_; // Vector con los textos e imagenes de cada escena
|
||||||
|
JA_Music_t *music; // Musica que suena durante el final
|
||||||
|
|
||||||
|
// Actualiza el objeto
|
||||||
|
void update();
|
||||||
|
|
||||||
|
// Dibuja el final en pantalla
|
||||||
|
void render();
|
||||||
|
|
||||||
|
// Comprueba el manejador de eventos
|
||||||
|
void checkEvents();
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
void checkInput();
|
||||||
|
|
||||||
|
// Inicializa los textos
|
||||||
|
void iniTexts();
|
||||||
|
|
||||||
|
// Inicializa las imagenes
|
||||||
|
void iniPics();
|
||||||
|
|
||||||
|
// Inicializa las escenas
|
||||||
|
void iniScenes();
|
||||||
|
|
||||||
|
// Actualiza los contadores
|
||||||
|
void updateCounters();
|
||||||
|
|
||||||
|
// Actualiza las cortinillas de los elementos
|
||||||
|
void updateSpriteCovers();
|
||||||
|
|
||||||
|
// Comprueba si se ha de cambiar de escena
|
||||||
|
void checkChangeScene();
|
||||||
|
|
||||||
|
// Rellena la textura para la cortinilla
|
||||||
|
void fillCoverTexture();
|
||||||
|
|
||||||
|
// Dibuja la cortinilla de cambio de escena
|
||||||
|
void renderCoverTexture();
|
||||||
|
|
||||||
|
// Actualiza el volumen de la musica
|
||||||
|
void updateMusicVolume();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
Ending();
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~Ending();
|
||||||
|
|
||||||
|
// Bucle principal
|
||||||
|
void run();
|
||||||
|
};
|
||||||
553
source/ending2.cpp
Normal file
553
source/ending2.cpp
Normal file
@@ -0,0 +1,553 @@
|
|||||||
|
#include "ending2.h"
|
||||||
|
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
|
||||||
|
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
|
||||||
|
#include <SDL2/SDL_rect.h> // for SDL_Rect
|
||||||
|
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
|
||||||
|
#include <algorithm> // for max, min, replace
|
||||||
|
#include "animated_sprite.h" // for AnimatedSprite
|
||||||
|
#include "asset.h" // for Asset
|
||||||
|
#include "defines.h" // for GAMECANVAS_HEIGHT, GAMECANVAS_CENTER_X
|
||||||
|
#include "global_events.h" // for check
|
||||||
|
#include "global_inputs.h" // for check
|
||||||
|
#include "input.h" // for Input
|
||||||
|
#include "jail_audio.h" // for JA_SetVolume, JA_PlayMusic, JA_StopM...
|
||||||
|
#include "moving_sprite.h" // for MovingSprite
|
||||||
|
#include "options.h" // for Options, options, OptionsVideo, Sect...
|
||||||
|
#include "resource.h" // for Resource
|
||||||
|
#include "screen.h" // for Screen
|
||||||
|
#include "text.h" // for Text
|
||||||
|
#include "texture.h" // for Texture
|
||||||
|
#include "utils.h" // for Color, stringToColor
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
Ending2::Ending2()
|
||||||
|
: screen_(Screen::get()),
|
||||||
|
renderer_(Screen::get()->getRenderer()),
|
||||||
|
resource_(Resource::get()),
|
||||||
|
asset_(Asset::get()),
|
||||||
|
input_(Input::get())
|
||||||
|
{
|
||||||
|
// Reserva memoria para los punteros a objetos
|
||||||
|
text_ = resource_->getText("smb2");
|
||||||
|
music_ = resource_->getMusic("ending2.ogg");
|
||||||
|
|
||||||
|
// Inicializa variables
|
||||||
|
counter_enabled_ = false;
|
||||||
|
pre_counter_ = 0;
|
||||||
|
post_counter_ = 0;
|
||||||
|
post_counter_enabled_ = false;
|
||||||
|
options.section.section = Section::ENDING2;
|
||||||
|
options.section.subsection = Subsection::NONE;
|
||||||
|
ticks_ = 0;
|
||||||
|
dist_sprite_text_ = 8;
|
||||||
|
dist_sprite_sprite_ = 0;
|
||||||
|
sprite_desp_speed_ = -0.2f;
|
||||||
|
|
||||||
|
// Inicializa el vector de colores
|
||||||
|
const std::vector<std::string> color_list = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"};
|
||||||
|
for (auto color : color_list)
|
||||||
|
{
|
||||||
|
colors_.push_back(stringToColor(options.video.palette, color));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cambia el color del borde
|
||||||
|
screen_->setBorderColor(stringToColor(options.video.palette, "black"));
|
||||||
|
|
||||||
|
// Inicializa la lista de sprites
|
||||||
|
iniSpriteList();
|
||||||
|
|
||||||
|
// Carga todos los sprites desde una lista
|
||||||
|
loadSprites();
|
||||||
|
|
||||||
|
// Coloca los sprites en su sito
|
||||||
|
placeSprites();
|
||||||
|
|
||||||
|
// Crea los sprites con las texturas con los textos
|
||||||
|
createSpriteTexts();
|
||||||
|
|
||||||
|
// Crea los sprites con las texturas con los textos del final
|
||||||
|
createTexts();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza el objeto
|
||||||
|
void Ending2::update()
|
||||||
|
{
|
||||||
|
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
||||||
|
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
|
||||||
|
{
|
||||||
|
// Actualiza el contador de ticks
|
||||||
|
ticks_ = SDL_GetTicks();
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
checkInput();
|
||||||
|
|
||||||
|
// Actualiza los contadores
|
||||||
|
updateCounters();
|
||||||
|
|
||||||
|
if (counter_enabled_)
|
||||||
|
{
|
||||||
|
// Actualiza los sprites
|
||||||
|
updateSprites();
|
||||||
|
|
||||||
|
// Actualiza los sprites de texto
|
||||||
|
updateTextSprites();
|
||||||
|
|
||||||
|
// Actualiza los sprites de texto del final
|
||||||
|
updateTexts();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza el fade final
|
||||||
|
updateFinalFade();
|
||||||
|
|
||||||
|
// Actualiza el volumen de la musica
|
||||||
|
updateMusicVolume();
|
||||||
|
|
||||||
|
screen_->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja el final en pantalla
|
||||||
|
void Ending2::render()
|
||||||
|
{
|
||||||
|
// Prepara para empezar a dibujar en la textura de juego
|
||||||
|
screen_->start();
|
||||||
|
|
||||||
|
// Limpia la pantalla
|
||||||
|
screen_->clean(stringToColor(options.video.palette, "black"));
|
||||||
|
|
||||||
|
// Dibuja los sprites
|
||||||
|
renderSprites();
|
||||||
|
|
||||||
|
// Dibuja los sprites con el texto
|
||||||
|
renderSpriteTexts();
|
||||||
|
|
||||||
|
// Dibuja los sprites con el texto del final
|
||||||
|
renderTexts();
|
||||||
|
|
||||||
|
const std::string txt = std::to_string(post_counter_);
|
||||||
|
// text->write(0, 192 - 8, txt);
|
||||||
|
|
||||||
|
// Dibuja la cuadricula
|
||||||
|
/*{
|
||||||
|
SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255);
|
||||||
|
const int sw = maxSpriteWidth + 6;
|
||||||
|
const int sh = maxSpriteHeight + 6;
|
||||||
|
for (int i = 0; i < 256; i += sw)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer, i, 0, i, 192);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 192; i += sh)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer, 0, i, 255, i);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
{
|
||||||
|
// Dibuja una trama arriba y abajo
|
||||||
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0xFF);
|
||||||
|
for (int i = 0; i < 256; i += 2)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 0, 0);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 1, 1);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 0, 2);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 1, 3);
|
||||||
|
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 4);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 6);
|
||||||
|
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 0, 191);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 1, 190);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 0, 189);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i + 1, 188);
|
||||||
|
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 187);
|
||||||
|
SDL_RenderDrawPoint(renderer_, i, 185);
|
||||||
|
}
|
||||||
|
// SDL_RenderDrawLine(renderer, 0, 1, 255, 1);
|
||||||
|
// SDL_RenderDrawLine(renderer, 0, 3, 255, 3);
|
||||||
|
// SDL_RenderDrawLine(renderer, 0, 188, 255, 188);
|
||||||
|
// SDL_RenderDrawLine(renderer, 0, 190, 255, 190);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vuelca el contenido del renderizador en pantalla
|
||||||
|
screen_->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba el manejador de eventos
|
||||||
|
void Ending2::checkEvents()
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
globalEvents::check(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
void Ending2::checkInput()
|
||||||
|
{
|
||||||
|
globalInputs::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bucle principal
|
||||||
|
void Ending2::run()
|
||||||
|
{
|
||||||
|
JA_PlayMusic(music_);
|
||||||
|
|
||||||
|
while (options.section.section == Section::ENDING2)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
checkEvents();
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
|
||||||
|
JA_StopMusic();
|
||||||
|
JA_SetVolume(128);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza los contadores
|
||||||
|
void Ending2::updateCounters()
|
||||||
|
{
|
||||||
|
// Incrementa el contador
|
||||||
|
if (pre_counter_ < 200)
|
||||||
|
{
|
||||||
|
pre_counter_++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
counter_enabled_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (post_counter_enabled_)
|
||||||
|
{
|
||||||
|
post_counter_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (post_counter_ > 600)
|
||||||
|
{
|
||||||
|
options.section.section = Section::LOGO;
|
||||||
|
options.section.subsection = Subsection::LOGO_TO_INTRO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicializa la lista de sprites
|
||||||
|
void Ending2::iniSpriteList()
|
||||||
|
{
|
||||||
|
// Reinicia el vector
|
||||||
|
sprite_list_.clear();
|
||||||
|
|
||||||
|
// Añade los valores
|
||||||
|
sprite_list_.push_back("bin");
|
||||||
|
sprite_list_.push_back("floppy");
|
||||||
|
sprite_list_.push_back("bird");
|
||||||
|
sprite_list_.push_back("chip");
|
||||||
|
sprite_list_.push_back("jeannine");
|
||||||
|
sprite_list_.push_back("spark");
|
||||||
|
sprite_list_.push_back("code");
|
||||||
|
sprite_list_.push_back("paco");
|
||||||
|
sprite_list_.push_back("elsa");
|
||||||
|
sprite_list_.push_back("z80");
|
||||||
|
|
||||||
|
sprite_list_.push_back("bell");
|
||||||
|
sprite_list_.push_back("dong");
|
||||||
|
|
||||||
|
sprite_list_.push_back("amstrad_cs");
|
||||||
|
sprite_list_.push_back("breakout");
|
||||||
|
|
||||||
|
sprite_list_.push_back("flying_arounder");
|
||||||
|
sprite_list_.push_back("stopped_arounder");
|
||||||
|
sprite_list_.push_back("walking_arounder");
|
||||||
|
sprite_list_.push_back("arounders_door");
|
||||||
|
sprite_list_.push_back("arounders_machine");
|
||||||
|
|
||||||
|
sprite_list_.push_back("abad");
|
||||||
|
sprite_list_.push_back("abad_bell");
|
||||||
|
sprite_list_.push_back("lord_abad");
|
||||||
|
|
||||||
|
sprite_list_.push_back("bat");
|
||||||
|
sprite_list_.push_back("batman_bell");
|
||||||
|
sprite_list_.push_back("batman_fire");
|
||||||
|
sprite_list_.push_back("batman");
|
||||||
|
|
||||||
|
sprite_list_.push_back("demon");
|
||||||
|
sprite_list_.push_back("heavy");
|
||||||
|
sprite_list_.push_back("dimallas");
|
||||||
|
sprite_list_.push_back("guitar");
|
||||||
|
|
||||||
|
sprite_list_.push_back("jailbattle_alien");
|
||||||
|
sprite_list_.push_back("jailbattle_human");
|
||||||
|
|
||||||
|
sprite_list_.push_back("jailer_#1");
|
||||||
|
sprite_list_.push_back("jailer_#2");
|
||||||
|
sprite_list_.push_back("jailer_#3");
|
||||||
|
sprite_list_.push_back("bry");
|
||||||
|
sprite_list_.push_back("upv_student");
|
||||||
|
|
||||||
|
sprite_list_.push_back("lamp");
|
||||||
|
sprite_list_.push_back("robot");
|
||||||
|
sprite_list_.push_back("congo");
|
||||||
|
sprite_list_.push_back("crosshair");
|
||||||
|
sprite_list_.push_back("tree_thing");
|
||||||
|
|
||||||
|
sprite_list_.push_back("matatunos");
|
||||||
|
sprite_list_.push_back("tuno");
|
||||||
|
|
||||||
|
sprite_list_.push_back("mummy");
|
||||||
|
sprite_list_.push_back("sam");
|
||||||
|
|
||||||
|
sprite_list_.push_back("qvoid");
|
||||||
|
sprite_list_.push_back("sigmasua");
|
||||||
|
|
||||||
|
sprite_list_.push_back("tv_panel");
|
||||||
|
sprite_list_.push_back("tv");
|
||||||
|
|
||||||
|
sprite_list_.push_back("spider");
|
||||||
|
sprite_list_.push_back("shock");
|
||||||
|
sprite_list_.push_back("wave");
|
||||||
|
|
||||||
|
sprite_list_.push_back("player");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Carga todos los sprites desde una lista
|
||||||
|
void Ending2::loadSprites()
|
||||||
|
{
|
||||||
|
// Inicializa variables
|
||||||
|
sprite_max_width_ = 0;
|
||||||
|
sprite_max_height_ = 0;
|
||||||
|
|
||||||
|
// Carga los sprites
|
||||||
|
for (auto sl : sprite_list_)
|
||||||
|
{
|
||||||
|
sprites_.emplace_back(std::make_shared<AnimatedSprite>(resource_->getTexture(sl + ".png"), resource_->getAnimations(sl + ".ani")));
|
||||||
|
sprite_max_width_ = std::max(sprites_.back()->getWidth(), sprite_max_width_);
|
||||||
|
sprite_max_height_ = std::max(sprites_.back()->getHeight(), sprite_max_height_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza los sprites
|
||||||
|
void Ending2::updateSprites()
|
||||||
|
{
|
||||||
|
for (auto sprite : sprites_)
|
||||||
|
{
|
||||||
|
sprite->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza los sprites de texto
|
||||||
|
void Ending2::updateTextSprites()
|
||||||
|
{
|
||||||
|
for (auto sprite : sprite_texts_)
|
||||||
|
{
|
||||||
|
sprite->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza los sprites de texto del final
|
||||||
|
void Ending2::updateTexts()
|
||||||
|
{
|
||||||
|
if (texts_.back()->getPosY() > GAMECANVAS_CENTER_Y)
|
||||||
|
{
|
||||||
|
for (auto sprite : texts_)
|
||||||
|
{
|
||||||
|
sprite->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
post_counter_enabled_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja los sprites
|
||||||
|
void Ending2::renderSprites()
|
||||||
|
{
|
||||||
|
const Color color = stringToColor(options.video.palette, "red");
|
||||||
|
for (auto sprite : sprites_)
|
||||||
|
{
|
||||||
|
const bool a = sprite->getRect().y + sprite->getRect().h > 0;
|
||||||
|
const bool b = sprite->getRect().y < GAMECANVAS_HEIGHT;
|
||||||
|
if (a && b)
|
||||||
|
{
|
||||||
|
sprite->getTexture()->setColor(color.r, color.g, color.b);
|
||||||
|
sprite->render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pinta el ultimo elemento de otro color
|
||||||
|
const Color c = stringToColor(options.video.palette, "white");
|
||||||
|
sprites_.back()->getTexture()->setColor(c.r, c.g, c.b);
|
||||||
|
sprites_.back()->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja los sprites con el texto
|
||||||
|
void Ending2::renderSpriteTexts()
|
||||||
|
{
|
||||||
|
const Color color = stringToColor(options.video.palette, "white");
|
||||||
|
for (auto sprite : sprite_texts_)
|
||||||
|
{
|
||||||
|
const bool a = sprite->getRect().y + sprite->getRect().h > 0;
|
||||||
|
const bool b = sprite->getRect().y < GAMECANVAS_HEIGHT;
|
||||||
|
if (a && b)
|
||||||
|
{
|
||||||
|
sprite->getTexture()->setColor(color.r, color.g, color.b);
|
||||||
|
sprite->render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja los sprites con el texto del final
|
||||||
|
void Ending2::renderTexts()
|
||||||
|
{
|
||||||
|
for (auto sprite : texts_)
|
||||||
|
{
|
||||||
|
const bool a = sprite->getRect().y + sprite->getRect().h > 0;
|
||||||
|
const bool b = sprite->getRect().y < GAMECANVAS_HEIGHT;
|
||||||
|
if (a && b)
|
||||||
|
{
|
||||||
|
sprite->render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Coloca los sprites en su sito
|
||||||
|
void Ending2::placeSprites()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < (int)sprites_.size(); ++i)
|
||||||
|
{
|
||||||
|
const int x = i % 2 == 0 ? FIRST_COL_ : SECOND_COL_;
|
||||||
|
const int y = (i / 1) * (sprite_max_height_ + dist_sprite_text_ + text_->getCharacterSize() + dist_sprite_sprite_) + GAMECANVAS_HEIGHT + 40;
|
||||||
|
const int w = sprites_[i]->getWidth();
|
||||||
|
const int h = sprites_[i]->getHeight();
|
||||||
|
const int dx = -(w / 2);
|
||||||
|
const int dy = i % 1 == 0 ? sprite_max_height_ - h : (int)(sprite_max_height_ * 1.5f) - h;
|
||||||
|
|
||||||
|
sprites_[i]->setPosition({x + dx, y + dy, w, h});
|
||||||
|
sprites_[i]->setVelY(sprite_desp_speed_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recoloca el último sprite, que es el del jugador
|
||||||
|
const int w = sprites_.back()->getWidth();
|
||||||
|
const int x = GAMECANVAS_CENTER_X - (w / 2);
|
||||||
|
const int y = sprites_.back()->getPosY() + sprite_max_height_ * 2;
|
||||||
|
sprites_.back()->setPosX(x);
|
||||||
|
sprites_.back()->setPosY(y);
|
||||||
|
sprites_.back()->setCurrentAnimation("walk");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crea los sprites con las texturas con los textos
|
||||||
|
void Ending2::createSpriteTexts()
|
||||||
|
{
|
||||||
|
// Crea los sprites de texto a partir de la lista
|
||||||
|
for (int i = 0; i < (int)sprite_list_.size(); ++i)
|
||||||
|
{
|
||||||
|
// Calcula constantes
|
||||||
|
std::string txt = sprite_list_[i];
|
||||||
|
std::replace(txt.begin(), txt.end(), '_', ' ');
|
||||||
|
txt = txt == "player" ? "JAILDOCTOR" : txt; // Reemplaza el texto
|
||||||
|
const int w = text_->lenght(txt, 1);
|
||||||
|
const int h = text_->getCharacterSize();
|
||||||
|
const int x = i % 2 == 0 ? FIRST_COL_ : SECOND_COL_;
|
||||||
|
const int dx = -(w / 2);
|
||||||
|
const int y = sprites_[i]->getPosY() + sprites_[i]->getHeight() + dist_sprite_text_;
|
||||||
|
|
||||||
|
// Cambia la posición del último sprite
|
||||||
|
const int X = (i == (int)sprite_list_.size() - 1) ? GAMECANVAS_CENTER_X - (w / 2) : x + dx;
|
||||||
|
|
||||||
|
// Crea la textura
|
||||||
|
auto texture = std::make_shared<Texture>(renderer_);
|
||||||
|
texture->createBlank(w, h);
|
||||||
|
texture->setAsRenderTarget(renderer_);
|
||||||
|
texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
||||||
|
text_->write(0, 0, txt);
|
||||||
|
|
||||||
|
// Crea el sprite
|
||||||
|
SDL_Rect pos = {X, y, w, h};
|
||||||
|
sprite_texts_.emplace_back(std::make_shared<MovingSprite>(texture, pos));
|
||||||
|
sprite_texts_.back()->setVelY(sprite_desp_speed_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crea los sprites con las texturas con los textos del final
|
||||||
|
void Ending2::createTexts()
|
||||||
|
{
|
||||||
|
// Crea los primeros textos
|
||||||
|
std::vector<std::string> list;
|
||||||
|
list.push_back("STARRING");
|
||||||
|
|
||||||
|
// Crea los sprites de texto a partir de la lista
|
||||||
|
for (int i = 0; i < (int)list.size(); ++i)
|
||||||
|
{
|
||||||
|
// Calcula constantes
|
||||||
|
const int w = text_->lenght(list[i], 1);
|
||||||
|
const int h = text_->getCharacterSize();
|
||||||
|
const int x = GAMECANVAS_CENTER_X;
|
||||||
|
const int dx = -(w / 2);
|
||||||
|
const int y = GAMECANVAS_HEIGHT + (text_->getCharacterSize() * (i * 2));
|
||||||
|
|
||||||
|
// Crea la textura
|
||||||
|
auto texture = std::make_shared<Texture>(renderer_);
|
||||||
|
texture->createBlank(w, h);
|
||||||
|
texture->setAsRenderTarget(renderer_);
|
||||||
|
texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
||||||
|
text_->write(0, 0, list[i]);
|
||||||
|
|
||||||
|
// Crea el sprite
|
||||||
|
SDL_Rect pos = {x + dx, y, w, h};
|
||||||
|
texts_.emplace_back(std::make_shared<MovingSprite>(texture, pos));
|
||||||
|
texts_.back()->setVelY(sprite_desp_speed_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crea los últimos textos
|
||||||
|
// El primer texto va a continuación del ultimo spriteText
|
||||||
|
const int start = sprite_texts_.back()->getPosY() + text_->getCharacterSize() * 15;
|
||||||
|
list.clear();
|
||||||
|
list.push_back("THANK YOU");
|
||||||
|
list.push_back("FOR PLAYING!");
|
||||||
|
|
||||||
|
// Crea los sprites de texto a partir de la lista
|
||||||
|
for (int i = 0; i < (int)list.size(); ++i)
|
||||||
|
{
|
||||||
|
// Calcula constantes
|
||||||
|
const int w = text_->lenght(list[i], 1);
|
||||||
|
const int h = text_->getCharacterSize();
|
||||||
|
const int x = GAMECANVAS_CENTER_X;
|
||||||
|
const int dx = -(w / 2);
|
||||||
|
const int y = start + (text_->getCharacterSize() * (i * 2));
|
||||||
|
|
||||||
|
// Crea la textura
|
||||||
|
auto texture = std::make_shared<Texture>(renderer_);
|
||||||
|
texture->createBlank(w, h);
|
||||||
|
texture->setAsRenderTarget(renderer_);
|
||||||
|
texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
||||||
|
text_->write(0, 0, list[i]);
|
||||||
|
|
||||||
|
// Crea el sprite
|
||||||
|
SDL_Rect pos = {x + dx, y, w, h};
|
||||||
|
texts_.emplace_back(std::make_shared<MovingSprite>(texture, pos));
|
||||||
|
texts_.back()->setVelY(sprite_desp_speed_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza el fade final
|
||||||
|
void Ending2::updateFinalFade()
|
||||||
|
{
|
||||||
|
// La variable step va de 0 a 40 en el tramo de postCounter que va de 500 a 540. Al dividirlo por 40, va de 0.0f a 1.0f
|
||||||
|
const float step = std::min(std::max(post_counter_, 500) - 500, 40) / 40.0f;
|
||||||
|
const int index = (colors_.size() - 1) * step;
|
||||||
|
|
||||||
|
for (auto t : texts_)
|
||||||
|
{
|
||||||
|
t->getTexture()->setColor(colors_[index].r, colors_[index].g, colors_[index].b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza el volumen de la musica
|
||||||
|
void Ending2::updateMusicVolume()
|
||||||
|
{
|
||||||
|
if (post_counter_ > 0)
|
||||||
|
{
|
||||||
|
const float step = (600.0f - post_counter_) / 600.0f;
|
||||||
|
const int volume = 128 * step;
|
||||||
|
JA_SetVolume(volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
115
source/ending2.h
Normal file
115
source/ending2.h
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL_render.h> // for SDL_Renderer
|
||||||
|
#include <SDL2/SDL_stdinc.h> // for Uint32
|
||||||
|
#include <memory> // for shared_ptr
|
||||||
|
#include <string> // for string
|
||||||
|
#include <vector> // for vector
|
||||||
|
#include "utils.h" // for Color
|
||||||
|
#include "defines.h" // for GAMECANVAS_FIRST_QUARTER_X, GAMECANVAS_THIRD_QUARTER_X, GAMECANVAS_WIDTH
|
||||||
|
class AnimatedSprite; // lines 9-9
|
||||||
|
class Asset; // lines 10-10
|
||||||
|
class Input; // lines 11-11
|
||||||
|
class MovingSprite; // lines 12-12
|
||||||
|
class Resource; // lines 13-13
|
||||||
|
class Screen; // lines 14-14
|
||||||
|
class Text; // lines 15-15
|
||||||
|
struct JA_Music_t; // lines 16-16
|
||||||
|
|
||||||
|
class Ending2
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// Constantes
|
||||||
|
static constexpr int FIRST_COL_ = GAMECANVAS_FIRST_QUARTER_X + (GAMECANVAS_WIDTH / 16); // Primera columna por donde desfilan los sprites
|
||||||
|
static constexpr int SECOND_COL_ = GAMECANVAS_THIRD_QUARTER_X - (GAMECANVAS_WIDTH / 16); // Segunda columna por donde desfilan los sprites
|
||||||
|
|
||||||
|
// Objetos y punteros
|
||||||
|
Screen *screen_; // Objeto encargado de dibujar en pantalla
|
||||||
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
|
Resource *resource_; // Objeto con los recursos
|
||||||
|
Asset *asset_; // Objeto con los ficheros de recursos
|
||||||
|
Input *input_; // Objeto pata gestionar la entrada
|
||||||
|
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
|
||||||
|
std::vector<std::shared_ptr<AnimatedSprite>> sprites_; // Vector con todos los sprites a dibujar
|
||||||
|
std::vector<std::shared_ptr<MovingSprite>> sprite_texts_; // Vector con los sprites de texto de los sprites
|
||||||
|
std::vector<std::shared_ptr<MovingSprite>> texts_; // Vector con los sprites de texto
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
bool counter_enabled_; // Indica si está el contador habilitado
|
||||||
|
int pre_counter_; // Contador previo
|
||||||
|
int post_counter_; // Contador posterior
|
||||||
|
bool post_counter_enabled_; // Indica si está habilitado el contador
|
||||||
|
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
|
||||||
|
JA_Music_t *music_; // Musica que suena durante el final
|
||||||
|
std::vector<std::string> sprite_list_; // Lista con todos los sprites a dibujar
|
||||||
|
std::vector<Color> colors_; // Vector con los colores para el fade
|
||||||
|
int sprite_max_width_; // El valor de ancho del sprite mas ancho
|
||||||
|
int sprite_max_height_; // El valor de alto del sprite mas alto
|
||||||
|
int dist_sprite_text_; // Distancia entre el sprite y el texto que lo acompaña
|
||||||
|
int dist_sprite_sprite_; // Distancia entre dos sprites de la misma columna
|
||||||
|
float sprite_desp_speed_; // Velocidad de desplazamiento de los sprites
|
||||||
|
|
||||||
|
// Actualiza el objeto
|
||||||
|
void update();
|
||||||
|
|
||||||
|
// Dibuja el final en pantalla
|
||||||
|
void render();
|
||||||
|
|
||||||
|
// Comprueba el manejador de eventos
|
||||||
|
void checkEvents();
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
void checkInput();
|
||||||
|
|
||||||
|
// Actualiza los contadores
|
||||||
|
void updateCounters();
|
||||||
|
|
||||||
|
// Inicializa la lista de sprites
|
||||||
|
void iniSpriteList();
|
||||||
|
|
||||||
|
// Carga todos los sprites desde una lista
|
||||||
|
void loadSprites();
|
||||||
|
|
||||||
|
// Actualiza los sprites
|
||||||
|
void updateSprites();
|
||||||
|
|
||||||
|
// Actualiza los sprites de texto
|
||||||
|
void updateTextSprites();
|
||||||
|
|
||||||
|
// Actualiza los sprites de texto del final
|
||||||
|
void updateTexts();
|
||||||
|
|
||||||
|
// Dibuja los sprites
|
||||||
|
void renderSprites();
|
||||||
|
|
||||||
|
// Dibuja los sprites con el texto
|
||||||
|
void renderSpriteTexts();
|
||||||
|
|
||||||
|
// Dibuja los sprites con el texto del final
|
||||||
|
void renderTexts();
|
||||||
|
|
||||||
|
// Coloca los sprites en su sito
|
||||||
|
void placeSprites();
|
||||||
|
|
||||||
|
// Crea los sprites con las texturas con los textos
|
||||||
|
void createSpriteTexts();
|
||||||
|
|
||||||
|
// Crea los sprites con las texturas con los textos del final
|
||||||
|
void createTexts();
|
||||||
|
|
||||||
|
// Actualiza el fade final
|
||||||
|
void updateFinalFade();
|
||||||
|
|
||||||
|
// Actualiza el volumen de la musica
|
||||||
|
void updateMusicVolume();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
Ending2();
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~Ending2() = default;
|
||||||
|
|
||||||
|
// Bucle principal
|
||||||
|
void run();
|
||||||
|
};
|
||||||
112
source/enemy.cpp
112
source/enemy.cpp
@@ -1,115 +1,110 @@
|
|||||||
#include "enemy.h"
|
#include "enemy.h"
|
||||||
|
#include <SDL2/SDL_render.h> // for SDL_RendererFlip, SDL_FLIP_NONE, SDL_FL...
|
||||||
|
#include <stdlib.h> // for rand
|
||||||
|
#include "animated_sprite.h" // for AnimatedSprite
|
||||||
|
#include "options.h" // for Options, OptionsVideo, options
|
||||||
|
#include "resource.h" // for Resource
|
||||||
|
#include "texture.h" // for Texture
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Enemy::Enemy(enemy_t enemy)
|
Enemy::Enemy(EnemyData enemy)
|
||||||
{
|
{
|
||||||
// Crea objetos
|
// Crea objetos
|
||||||
sprite = new AnimatedSprite(enemy.renderer, enemy.animation);
|
sprite_ = std::make_shared<AnimatedSprite>(Resource::get()->getTexture(enemy.texture_path), Resource::get()->getAnimations(enemy.animation_path));
|
||||||
|
|
||||||
// Obten el resto de valores
|
// Obten el resto de valores
|
||||||
x1 = enemy.x1;
|
x1_ = enemy.x1;
|
||||||
x2 = enemy.x2;
|
x2_ = enemy.x2;
|
||||||
y1 = enemy.y1;
|
y1_ = enemy.y1;
|
||||||
y2 = enemy.y2;
|
y2_ = enemy.y2;
|
||||||
palette = enemy.palette;
|
color_string_ = enemy.color;
|
||||||
colorString = enemy.color;
|
setPalette(options.video.palette);
|
||||||
color = stringToColor(palette, colorString);
|
sprite_->setPosX(enemy.x);
|
||||||
sprite->setPosX(enemy.x);
|
sprite_->setPosY(enemy.y);
|
||||||
sprite->setPosY(enemy.y);
|
sprite_->setVelX(enemy.vx);
|
||||||
sprite->setVelX(enemy.vx);
|
sprite_->setVelY(enemy.vy);
|
||||||
sprite->setVelY(enemy.vy);
|
sprite_->setWidth(enemy.w);
|
||||||
sprite->setWidth(enemy.w);
|
sprite_->setHeight(enemy.h);
|
||||||
sprite->setHeight(enemy.h);
|
should_flip_ = enemy.flip;
|
||||||
doFlip = enemy.flip;
|
should_mirror_ = enemy.mirror;
|
||||||
mirror = enemy.mirror;
|
|
||||||
if (doFlip)
|
|
||||||
{
|
|
||||||
if (enemy.vx < 0.0f)
|
|
||||||
{
|
|
||||||
sprite->setFlipH(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sprite->setFlipV(mirror);
|
|
||||||
|
|
||||||
collider = getRect();
|
const SDL_RendererFlip flip = (should_flip_ && enemy.vx < 0.0f) ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
|
||||||
|
const SDL_RendererFlip mirror = should_mirror_ ? SDL_FLIP_VERTICAL : SDL_FLIP_NONE;
|
||||||
|
sprite_->setFlip(static_cast<SDL_RendererFlip>(flip | mirror));
|
||||||
|
|
||||||
|
collider_ = getRect();
|
||||||
|
|
||||||
// Coloca un frame al azar o el designado
|
// Coloca un frame al azar o el designado
|
||||||
if (enemy.frame == -1)
|
if (enemy.frame == -1)
|
||||||
{
|
{
|
||||||
sprite->setCurrentFrame(rand() % sprite->getNumFrames());
|
sprite_->setCurrentAnimationFrame(rand() % sprite_->getCurrentAnimationSize());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprite->setCurrentFrame(std::min(enemy.frame, sprite->getNumFrames() - 1));
|
sprite_->setCurrentAnimationFrame(enemy.frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
|
||||||
Enemy::~Enemy()
|
|
||||||
{
|
|
||||||
delete sprite;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pinta el enemigo en pantalla
|
// Pinta el enemigo en pantalla
|
||||||
void Enemy::render()
|
void Enemy::render()
|
||||||
{
|
{
|
||||||
sprite->getTexture()->setColor(color.r, color.g, color.b);
|
sprite_->getTexture()->setColor(color_.r, color_.g, color_.b);
|
||||||
sprite->render();
|
sprite_->render();
|
||||||
sprite->getTexture()->setColor(255, 255, 255);
|
sprite_->getTexture()->setColor(255, 255, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las variables del objeto
|
// Actualiza las variables del objeto
|
||||||
void Enemy::update()
|
void Enemy::update()
|
||||||
{
|
{
|
||||||
sprite->update();
|
sprite_->update();
|
||||||
checkPath();
|
checkPath();
|
||||||
collider = getRect();
|
collider_ = getRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba si ha llegado al limite del recorrido para darse media vuelta
|
// Comprueba si ha llegado al limite del recorrido para darse media vuelta
|
||||||
void Enemy::checkPath()
|
void Enemy::checkPath()
|
||||||
{
|
{
|
||||||
if (sprite->getPosX() > x2 || sprite->getPosX() < x1)
|
if (sprite_->getPosX() > x2_ || sprite_->getPosX() < x1_)
|
||||||
{
|
{
|
||||||
// Recoloca
|
// Recoloca
|
||||||
if (sprite->getPosX() > x2)
|
if (sprite_->getPosX() > x2_)
|
||||||
{
|
{
|
||||||
sprite->setPosX(x2);
|
sprite_->setPosX(x2_);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprite->setPosX(x1);
|
sprite_->setPosX(x1_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cambia el sentido
|
// Cambia el sentido
|
||||||
sprite->setVelX(sprite->getVelX() * (-1));
|
sprite_->setVelX(sprite_->getVelX() * (-1));
|
||||||
|
|
||||||
// Invierte el sprite
|
// Invierte el sprite
|
||||||
if (doFlip)
|
if (should_flip_)
|
||||||
{
|
{
|
||||||
sprite->flipH();
|
sprite_->flip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sprite->getPosY() > y2 || sprite->getPosY() < y1)
|
if (sprite_->getPosY() > y2_ || sprite_->getPosY() < y1_)
|
||||||
{
|
{
|
||||||
// Recoloca
|
// Recoloca
|
||||||
if (sprite->getPosY() > y2)
|
if (sprite_->getPosY() > y2_)
|
||||||
{
|
{
|
||||||
sprite->setPosY(y2);
|
sprite_->setPosY(y2_);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprite->setPosY(y1);
|
sprite_->setPosY(y1_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cambia el sentido
|
// Cambia el sentido
|
||||||
sprite->setVelY(sprite->getVelY() * (-1));
|
sprite_->setVelY(sprite_->getVelY() * (-1));
|
||||||
|
|
||||||
// Invierte el sprite
|
// Invierte el sprite
|
||||||
if (doFlip)
|
if (should_flip_)
|
||||||
{
|
{
|
||||||
sprite->flipH();
|
sprite_->flip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,24 +112,23 @@ void Enemy::checkPath()
|
|||||||
// Devuelve el rectangulo que contiene al enemigo
|
// Devuelve el rectangulo que contiene al enemigo
|
||||||
SDL_Rect Enemy::getRect()
|
SDL_Rect Enemy::getRect()
|
||||||
{
|
{
|
||||||
return sprite->getRect();
|
return sprite_->getRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el rectangulo de colision del enemigo
|
// Obtiene el rectangulo de colision del enemigo
|
||||||
SDL_Rect &Enemy::getCollider()
|
SDL_Rect &Enemy::getCollider()
|
||||||
{
|
{
|
||||||
return collider;
|
return collider_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recarga la textura
|
// Recarga la textura
|
||||||
void Enemy::reLoadTexture()
|
void Enemy::reLoadTexture()
|
||||||
{
|
{
|
||||||
sprite->getTexture()->reLoad();
|
sprite_->getTexture()->reLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Asigna la paleta
|
// Asigna la paleta
|
||||||
void Enemy::setPalette(palette_e pal)
|
void Enemy::setPalette(Palette pal)
|
||||||
{
|
{
|
||||||
palette = pal;
|
color_ = stringToColor(pal, color_string_);
|
||||||
color = stringToColor(palette, colorString);
|
|
||||||
}
|
}
|
||||||
@@ -1,64 +1,58 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL_rect.h> // for SDL_Rect
|
||||||
#include "jail_engine/animatedsprite.h"
|
#include <memory> // for shared_ptr
|
||||||
#include "jail_engine/asset.h"
|
#include <string> // for string
|
||||||
#include "jail_engine/utils.h"
|
#include "utils.h" // for Color
|
||||||
#include <string>
|
class AnimatedSprite;
|
||||||
|
|
||||||
#ifndef ENEMY_H
|
|
||||||
#define ENEMY_H
|
|
||||||
|
|
||||||
// Estructura para pasar los datos de un enemigo
|
// Estructura para pasar los datos de un enemigo
|
||||||
struct enemy_t
|
struct EnemyData
|
||||||
{
|
{
|
||||||
SDL_Renderer *renderer; // El renderizador de la ventana
|
std::string texture_path; // Ruta al fichero con la textura
|
||||||
animatedSprite_t *animation; // Puntero a las animaciones del enemigo
|
std::string animation_path; // Ruta al fichero con la animación
|
||||||
std::string animationString; // Ruta al fichero con la animación
|
int w; // Anchura del enemigo
|
||||||
int w; // Anchura del enemigo
|
int h; // Altura del enemigo
|
||||||
int h; // Altura del enemigo
|
float x; // Posición inicial en el eje X
|
||||||
float x; // Posición inicial en el eje X
|
float y; // Posición inicial en el eje Y
|
||||||
float y; // Posición inicial en el eje Y
|
float vx; // Velocidad en el eje X
|
||||||
float vx; // Velocidad en el eje X
|
float vy; // Velocidad en el eje Y
|
||||||
float vy; // Velocidad en el eje Y
|
int x1; // Limite izquierdo de la ruta en el eje X
|
||||||
int x1; // Limite izquierdo de la ruta en el eje X
|
int x2; // Limite derecho de la ruta en el eje X
|
||||||
int x2; // Limite derecho de la ruta en el eje X
|
int y1; // Limite superior de la ruta en el eje Y
|
||||||
int y1; // Limite superior de la ruta en el eje Y
|
int y2; // Limite inferior de la ruta en el eje Y
|
||||||
int y2; // Limite inferior de la ruta en el eje Y
|
bool flip; // Indica si el enemigo hace flip al terminar su ruta
|
||||||
bool flip; // Indica si el enemigo hace flip al terminar su ruta
|
bool mirror; // Indica si el enemigo está volteado verticalmente
|
||||||
bool mirror; // Indica si el enemigo está volteado verticalmente
|
int frame; // Frame inicial para la animación del enemigo
|
||||||
int frame; // Frame inicial para la animación del enemigo
|
std::string color; // Color del enemigo
|
||||||
std::string color; // Color del enemigo
|
|
||||||
palette_e palette; // Paleta de colores
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Enemy
|
class Enemy
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Objetos y punteros
|
// Objetos y punteros
|
||||||
AnimatedSprite *sprite; // Sprite del enemigo
|
std::shared_ptr<AnimatedSprite> sprite_; // Sprite del enemigo
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
color_t color; // Color del enemigo
|
Color color_; // Color del enemigo
|
||||||
std::string colorString; // Color del enemigo en formato texto
|
std::string color_string_; // Color del enemigo en formato texto
|
||||||
palette_e palette; // Paleta de colores
|
int x1_; // Limite izquierdo de la ruta en el eje X
|
||||||
int x1; // Limite izquierdo de la ruta en el eje X
|
int x2_; // Limite derecho de la ruta en el eje X
|
||||||
int x2; // Limite derecho de la ruta en el eje X
|
int y1_; // Limite superior de la ruta en el eje Y
|
||||||
int y1; // Limite superior de la ruta en el eje Y
|
int y2_; // Limite inferior de la ruta en el eje Y
|
||||||
int y2; // Limite inferior de la ruta en el eje Y
|
SDL_Rect collider_; // Caja de colisión
|
||||||
SDL_Rect collider; // Caja de colisión
|
bool should_flip_; // Indica si el enemigo hace flip al terminar su ruta
|
||||||
bool doFlip; // Indica si el enemigo hace flip al terminar su ruta
|
bool should_mirror_; // Indica si el enemigo se dibuja volteado verticalmente
|
||||||
bool mirror; // Indica si el enemigo se dibuja volteado verticalmente
|
|
||||||
|
|
||||||
// Comprueba si ha llegado al limite del recorrido para darse media vuelta
|
// Comprueba si ha llegado al limite del recorrido para darse media vuelta
|
||||||
void checkPath();
|
void checkPath();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
Enemy(enemy_t enemy);
|
Enemy(EnemyData enemy);
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~Enemy();
|
~Enemy() = default;
|
||||||
|
|
||||||
// Pinta el enemigo en pantalla
|
// Pinta el enemigo en pantalla
|
||||||
void render();
|
void render();
|
||||||
@@ -76,7 +70,5 @@ public:
|
|||||||
void reLoadTexture();
|
void reLoadTexture();
|
||||||
|
|
||||||
// Asigna la paleta
|
// Asigna la paleta
|
||||||
void setPalette(palette_e pal);
|
void setPalette(Palette pal);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -1,326 +0,0 @@
|
|||||||
#include "jail_engine/jail_audio.h"
|
|
||||||
#include "jail_engine/jscore.h"
|
|
||||||
#include "const.h"
|
|
||||||
#include "enter_id.h"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
EnterID::EnterID(SDL_Renderer *renderer, Screen *screen, Asset *asset, options_t *options, section_t *section)
|
|
||||||
{
|
|
||||||
// Copia la dirección de los objetos
|
|
||||||
this->renderer = renderer;
|
|
||||||
this->screen = screen;
|
|
||||||
this->asset = asset;
|
|
||||||
this->options = options;
|
|
||||||
this->section = section;
|
|
||||||
|
|
||||||
// Reserva memoria para los punteros
|
|
||||||
eventHandler = new SDL_Event();
|
|
||||||
texture = new Texture(renderer, asset->get("smb2.png"));
|
|
||||||
text = new Text(asset->get("smb2.txt"), texture, renderer);
|
|
||||||
|
|
||||||
// Crea la textura para el texto que se escribe en pantalla
|
|
||||||
textTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT);
|
|
||||||
if (textTexture == nullptr)
|
|
||||||
{
|
|
||||||
if (options->console)
|
|
||||||
{
|
|
||||||
std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SDL_SetTextureBlendMode(textTexture, SDL_BLENDMODE_BLEND);
|
|
||||||
|
|
||||||
// Inicializa variables
|
|
||||||
oldJailerID = options->online.jailerID;
|
|
||||||
loopRunning = true;
|
|
||||||
counter = 0;
|
|
||||||
ticks = 0;
|
|
||||||
ticksSpeed = 15;
|
|
||||||
jailerIDPos = 0;
|
|
||||||
initName();
|
|
||||||
|
|
||||||
// Escribe el texto en la textura
|
|
||||||
fillTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
EnterID::~EnterID()
|
|
||||||
{
|
|
||||||
delete eventHandler;
|
|
||||||
delete text;
|
|
||||||
delete texture;
|
|
||||||
SDL_DestroyTexture(textTexture);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bucle para el logo del juego
|
|
||||||
void EnterID::run()
|
|
||||||
{
|
|
||||||
while (loopRunning)
|
|
||||||
{
|
|
||||||
update();
|
|
||||||
checkEvents();
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba el manejador de eventos
|
|
||||||
void EnterID::checkEvents()
|
|
||||||
{
|
|
||||||
// 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 = SECTION_QUIT;
|
|
||||||
loopRunning = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba las teclas que se han pulsado
|
|
||||||
if ((eventHandler->type == SDL_KEYDOWN && eventHandler->key.repeat == 0) || (eventHandler->type == SDL_JOYBUTTONDOWN))
|
|
||||||
{
|
|
||||||
if (eventHandler->key.keysym.scancode == SDL_SCANCODE_RETURN)
|
|
||||||
{
|
|
||||||
options->online.jailerID = toLower((std::string)name);
|
|
||||||
endSection();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventHandler->key.keysym.scancode >= SDL_SCANCODE_A && eventHandler->key.keysym.scancode <= SDL_SCANCODE_Z)
|
|
||||||
{ // Si pulsa una letra
|
|
||||||
if (pos < maxLenght)
|
|
||||||
{
|
|
||||||
name[pos++] = eventHandler->key.keysym.scancode + 61;
|
|
||||||
name[pos] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (eventHandler->key.keysym.scancode >= SDL_SCANCODE_1 && eventHandler->key.keysym.scancode <= SDL_SCANCODE_9)
|
|
||||||
{ // Si pulsa un número
|
|
||||||
if (pos < maxLenght)
|
|
||||||
{ // En ascii el '0' va antes del '1', pero en scancode el '0' va despues de '9'
|
|
||||||
name[pos++] = eventHandler->key.keysym.scancode + 19;
|
|
||||||
name[pos] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (eventHandler->key.keysym.scancode == SDL_SCANCODE_0)
|
|
||||||
{
|
|
||||||
if (pos < maxLenght)
|
|
||||||
{
|
|
||||||
name[pos++] = 48;
|
|
||||||
name[pos] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (eventHandler->key.keysym.scancode == SDL_SCANCODE_BACKSPACE)
|
|
||||||
{
|
|
||||||
if (pos > 0)
|
|
||||||
{
|
|
||||||
name[--pos] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (eventHandler->key.keysym.scancode == SDL_SCANCODE_ESCAPE)
|
|
||||||
{
|
|
||||||
section->name = SECTION_QUIT;
|
|
||||||
loopRunning = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (eventHandler->key.keysym.scancode == SDL_SCANCODE_F1)
|
|
||||||
{
|
|
||||||
screen->setWindowSize(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (eventHandler->key.keysym.scancode == SDL_SCANCODE_F2)
|
|
||||||
{
|
|
||||||
screen->setWindowSize(2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (eventHandler->key.keysym.scancode == SDL_SCANCODE_F3)
|
|
||||||
{
|
|
||||||
screen->setWindowSize(3);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (eventHandler->key.keysym.scancode == SDL_SCANCODE_F4)
|
|
||||||
{
|
|
||||||
screen->setWindowSize(4);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (eventHandler->key.keysym.scancode == SDL_SCANCODE_F5)
|
|
||||||
{
|
|
||||||
switchPalette();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza las variables
|
|
||||||
void EnterID::update()
|
|
||||||
{
|
|
||||||
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
|
||||||
if (SDL_GetTicks() - ticks > ticksSpeed)
|
|
||||||
{
|
|
||||||
// Actualiza el contador de ticks
|
|
||||||
ticks = SDL_GetTicks();
|
|
||||||
|
|
||||||
// Actualiza el contador
|
|
||||||
counter++;
|
|
||||||
|
|
||||||
// Actualiza el cursor
|
|
||||||
cursor = (counter % 20 >= 10) ? " " : "_";
|
|
||||||
|
|
||||||
// Actualiza las notificaciones
|
|
||||||
screen->updateNotifier();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja en pantalla
|
|
||||||
void EnterID::render()
|
|
||||||
{
|
|
||||||
// Prepara para empezar a dibujar en la textura de juego
|
|
||||||
screen->start();
|
|
||||||
|
|
||||||
// Dibuja la textura con el texto en pantalla
|
|
||||||
SDL_RenderCopy(renderer, textTexture, nullptr, nullptr);
|
|
||||||
|
|
||||||
// Escribe el jailerID
|
|
||||||
const std::string jailerID = (std::string)name + cursor;
|
|
||||||
const color_t color = stringToColor(options->palette, "white");
|
|
||||||
text->writeDX(TXT_CENTER | TXT_COLOR, GAMECANVAS_CENTER_X, jailerIDPos, jailerID, 1, color);
|
|
||||||
|
|
||||||
// Vuelca el contenido del renderizador en pantalla
|
|
||||||
screen->blit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa los textos
|
|
||||||
void EnterID::iniTexts()
|
|
||||||
{
|
|
||||||
texts.clear();
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"ONLINE CONFIGURATION:", stringToColor(options->palette, "green")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"PLEASE ENTER AN ID OR", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"LEAVE BLANK FOR OFFLINE MODE", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"JAILER_ID:", stringToColor(options->palette, "green")});
|
|
||||||
|
|
||||||
jailerIDPos = ((int)texts.size() + 1) * text->getCharacterSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escribe el texto en la textura
|
|
||||||
void EnterID::fillTexture()
|
|
||||||
{
|
|
||||||
// Inicializa los textos
|
|
||||||
iniTexts();
|
|
||||||
|
|
||||||
// Rellena la textura de texto
|
|
||||||
SDL_SetRenderTarget(renderer, textTexture);
|
|
||||||
color_t c = stringToColor(options->palette, "black");
|
|
||||||
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, 0xFF);
|
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
|
|
||||||
// Escribe el texto en la textura
|
|
||||||
const int size = text->getCharacterSize();
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (auto t : texts)
|
|
||||||
{
|
|
||||||
text->writeDX(TXT_CENTER | TXT_COLOR, PLAY_AREA_CENTER_X, i * size, t.label, 1, t.color);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetRenderTarget(renderer, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa los servicios online
|
|
||||||
void EnterID::initOnline()
|
|
||||||
{
|
|
||||||
// Si ya ha iniciado la sesión y no ha cambiado el jailerID, que no continue
|
|
||||||
if (options->online.sessionEnabled)
|
|
||||||
{
|
|
||||||
if (oldJailerID == options->online.jailerID)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options->online.jailerID == "")
|
|
||||||
{ // Jailer ID no definido
|
|
||||||
options->online.enabled = false;
|
|
||||||
options->online.sessionEnabled = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // Jailer ID iniciado
|
|
||||||
options->online.enabled = options->online.sessionEnabled = true;
|
|
||||||
// Establece el servidor y el puerto
|
|
||||||
jscore::init(options->online.server, options->online.port);
|
|
||||||
#ifdef DEBUG
|
|
||||||
const std::string caption = "IS LOGGED IN (DEBUG)";
|
|
||||||
#else
|
|
||||||
const std::string caption = "IS LOGGED IN";
|
|
||||||
#endif
|
|
||||||
screen->showNotification(options->online.jailerID, caption, 12);
|
|
||||||
if (options->console)
|
|
||||||
{
|
|
||||||
std::cout << caption << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Termina la sección
|
|
||||||
void EnterID::endSection()
|
|
||||||
{
|
|
||||||
loopRunning = false;
|
|
||||||
initOnline();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa el vector utilizado para almacenar el texto que se escribe en pantalla
|
|
||||||
void EnterID::initName()
|
|
||||||
{
|
|
||||||
// Calcula el tamaño del vector
|
|
||||||
name[0] = 0;
|
|
||||||
maxLenght = sizeof(name) / sizeof(name[pos]);
|
|
||||||
|
|
||||||
// Inicializa el vector con ceros
|
|
||||||
for (int i = 0; i < maxLenght; ++i)
|
|
||||||
{
|
|
||||||
name[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si no hay definido ningun JailerID, coloca el cursor en primera posición
|
|
||||||
if (options->online.jailerID == "")
|
|
||||||
{
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // En caso contrario, copia el texto al vector y coloca el cursor en posición
|
|
||||||
const int len = std::min((int)options->online.jailerID.size(), maxLenght);
|
|
||||||
for (int i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
name[i] = (char)options->online.jailerID[i];
|
|
||||||
}
|
|
||||||
pos = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cambia la paleta
|
|
||||||
void EnterID::switchPalette()
|
|
||||||
{
|
|
||||||
options->palette = options->palette == p_zxspectrum ? p_zxarne : p_zxspectrum;
|
|
||||||
fillTexture();
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <SDL2/SDL.h>
|
|
||||||
#include "jail_engine/asset.h"
|
|
||||||
#include "jail_engine/screen.h"
|
|
||||||
#include "jail_engine/utils.h"
|
|
||||||
#include "jail_engine/text.h"
|
|
||||||
#include "jail_engine/texture.h"
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#ifndef ENTER_ID_H
|
|
||||||
#define ENTER_ID_H
|
|
||||||
|
|
||||||
class EnterID
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
struct captions_t
|
|
||||||
{
|
|
||||||
std::string label; // Texto a escribir
|
|
||||||
color_t color; // Color del texto
|
|
||||||
};
|
|
||||||
|
|
||||||
// Punteros y objetos
|
|
||||||
Asset *asset; // Objeto con los ficheros de recursos
|
|
||||||
options_t *options; // Puntero a las opciones del juego
|
|
||||||
Screen *screen; // Objeto encargado de dibujar en pantalla
|
|
||||||
SDL_Event *eventHandler; // Manejador de eventos
|
|
||||||
SDL_Renderer *renderer; // El renderizador de la ventana
|
|
||||||
SDL_Texture *textTexture; // Textura para dibujar el texto
|
|
||||||
Text *text; // Objeto para escribir texto en pantalla
|
|
||||||
Texture *texture; // Textura para la fuente para el texto
|
|
||||||
section_t *section; // Estado del bucle principal para saber si continua o se sale
|
|
||||||
|
|
||||||
// Variables
|
|
||||||
bool loopRunning; // Indica si ha de terminar el bucle principal
|
|
||||||
int counter; // Contador
|
|
||||||
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa
|
|
||||||
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa
|
|
||||||
std::vector<captions_t> texts; // Vector con los textos
|
|
||||||
std::string cursor; // Contiene el caracter que se muestra como cursor
|
|
||||||
|
|
||||||
char name[15]; // Aqui se guardan los caracteres de las teclas que se van pulsando
|
|
||||||
int pos; // Posición actual en el vector name
|
|
||||||
int maxLenght; // Tamaño máximo del jailerID
|
|
||||||
std::string oldJailerID; // Almacena el valor de jailerID al inicio para ver si se ha modificado
|
|
||||||
int jailerIDPos; // Posición en el eje Y donde ser va a escribir el texto
|
|
||||||
|
|
||||||
// Actualiza las variables
|
|
||||||
void update();
|
|
||||||
|
|
||||||
// Dibuja en pantalla
|
|
||||||
void render();
|
|
||||||
|
|
||||||
// Comprueba el manejador de eventos
|
|
||||||
void checkEvents();
|
|
||||||
|
|
||||||
// Inicializa los textos
|
|
||||||
void iniTexts();
|
|
||||||
|
|
||||||
// Escribe el texto en la textura
|
|
||||||
void fillTexture();
|
|
||||||
|
|
||||||
// Inicializa los servicios online
|
|
||||||
void initOnline();
|
|
||||||
|
|
||||||
// Termina la sección
|
|
||||||
void endSection();
|
|
||||||
|
|
||||||
// Inicializa el vector utilizado para almacenar el texto que se escribe en pantalla
|
|
||||||
void initName();
|
|
||||||
|
|
||||||
// Cambia la paleta
|
|
||||||
void switchPalette();
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
EnterID(SDL_Renderer *renderer, Screen *screen, Asset *asset, options_t *options, section_t *section);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~EnterID();
|
|
||||||
|
|
||||||
// Bucle principal
|
|
||||||
void run();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
716
source/game.cpp
Normal file
716
source/game.cpp
Normal file
@@ -0,0 +1,716 @@
|
|||||||
|
#include "game.h"
|
||||||
|
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
|
||||||
|
#include <SDL2/SDL_error.h> // for SDL_GetError
|
||||||
|
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
|
||||||
|
#include <SDL2/SDL_scancode.h> // for SDL_SCANCODE_A, SDL_SCANCODE_D, SDL_...
|
||||||
|
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
|
||||||
|
#include <iostream> // for basic_ostream, operator<<, cout, endl
|
||||||
|
#include <vector> // for vector
|
||||||
|
#include "asset.h" // for Asset
|
||||||
|
#include "cheevos.h" // for Cheevos
|
||||||
|
#include "defines.h" // for PLAY_AREA_HEIGHT, GAMECANVAS_WIDTH
|
||||||
|
#include "debug.h" // for Debug
|
||||||
|
#include "input.h" // for Input, REPEAT_FALSE, inputs_e
|
||||||
|
#include "item_tracker.h" // for ItemTracker
|
||||||
|
#include "jail_audio.h" // for JA_PauseMusic, JA_PlaySound, JA_Resu...
|
||||||
|
#include "resource.h" // for Resource, res_room_t
|
||||||
|
#include "room.h" // for Room, room_t
|
||||||
|
#include "room_tracker.h" // for RoomTracker
|
||||||
|
#include "screen.h" // for Screen
|
||||||
|
#include "stats.h" // for Stats
|
||||||
|
#include "text.h" // for Text, TXT_CENTER, TXT_COLOR
|
||||||
|
#include "utils.h" // for options_t, cheat_t, stringToColor
|
||||||
|
#include "options.h"
|
||||||
|
#include "notifier.h"
|
||||||
|
#include "global_inputs.h"
|
||||||
|
#include "global_events.h"
|
||||||
|
//#include "surface.h"
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
Game::Game()
|
||||||
|
: screen_(Screen::get()),
|
||||||
|
renderer_(Screen::get()->getRenderer()),
|
||||||
|
asset_(Asset::get()),
|
||||||
|
input_(Input::get()),
|
||||||
|
resource_(Resource::get()),
|
||||||
|
debug_(Debug::get()),
|
||||||
|
cheevos_(Cheevos::get())
|
||||||
|
{
|
||||||
|
// Inicia algunas variables
|
||||||
|
//test_surface_ = std::make_shared<Surface>(Screen::get()->getSurface(), "test.gif");
|
||||||
|
board_ = std::make_shared<ScoreboardData>();
|
||||||
|
board_->ini_clock = SDL_GetTicks();
|
||||||
|
#ifdef DEBUG
|
||||||
|
current_room_ = "03.room";
|
||||||
|
constexpr int X = 25;
|
||||||
|
constexpr int Y = 13;
|
||||||
|
spawn_point_ = PlayerSpawn(X * 8, Y * 8, 0, 0, 0, PlayerState::STANDING, SDL_FLIP_HORIZONTAL);
|
||||||
|
debug_->setEnabled(false);
|
||||||
|
#else
|
||||||
|
current_room_ = "03.room";
|
||||||
|
constexpr int X = 25;
|
||||||
|
constexpr int Y = 13;
|
||||||
|
spawn_point_ = PlayerSpawn(X * 8, Y * 8, 0, 0, 0, PlayerState::STANDING, SDL_FLIP_HORIZONTAL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Crea los objetos
|
||||||
|
ItemTracker::init();
|
||||||
|
scoreboard_ = std::make_shared<Scoreboard>(board_);
|
||||||
|
room_tracker_ = std::make_shared<RoomTracker>();
|
||||||
|
room_ = std::make_shared<Room>(resource_->getRoom(current_room_), board_);
|
||||||
|
std::string player_texture = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.png" : "player.png";
|
||||||
|
std::string player_animations = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.ani" : "player.ani";
|
||||||
|
const PlayerData player(spawn_point_, player_texture, player_animations, room_);
|
||||||
|
player_ = std::make_shared<Player>(player);
|
||||||
|
text_ = resource_->getText("smb2");
|
||||||
|
music_ = resource_->getMusic("game.ogg");
|
||||||
|
death_sound_ = resource_->getSound("death.wav");
|
||||||
|
stats_ = std::make_shared<Stats>(asset_->get("stats.csv"), asset_->get("stats_buffer.csv"));
|
||||||
|
|
||||||
|
// Crea la textura para poner el nombre de la habitación
|
||||||
|
room_name_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, text_->getCharacterSize() * 2);
|
||||||
|
if (room_name_texture_ == nullptr)
|
||||||
|
{
|
||||||
|
if (options.console)
|
||||||
|
{
|
||||||
|
std::cout << "Error: roomNameTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establece el blend mode de la textura
|
||||||
|
SDL_SetTextureBlendMode(room_name_texture_, SDL_BLENDMODE_BLEND);
|
||||||
|
|
||||||
|
// Establece el destino de la textura
|
||||||
|
room_name_rect_ = {0, PLAY_AREA_HEIGHT, GAMECANVAS_WIDTH, text_->getCharacterSize() * 2};
|
||||||
|
|
||||||
|
// Pone el nombre de la habitación en la textura
|
||||||
|
fillRoomNameTexture();
|
||||||
|
|
||||||
|
// Inicializa el resto de variables
|
||||||
|
ticks_ = 0;
|
||||||
|
board_->lives = 9;
|
||||||
|
#ifdef DEBUG
|
||||||
|
board_->lives = 9;
|
||||||
|
#endif
|
||||||
|
board_->items = 0;
|
||||||
|
board_->rooms = 1;
|
||||||
|
board_->music = true;
|
||||||
|
board_->jail_is_open = options.cheats.jail_is_open == Cheat::CheatState::ENABLED;
|
||||||
|
setScoreBoardColor();
|
||||||
|
room_tracker_->addRoom(current_room_);
|
||||||
|
paused_ = false;
|
||||||
|
black_screen_ = false;
|
||||||
|
black_screen_counter_ = 0;
|
||||||
|
total_items_ = getTotalItems();
|
||||||
|
initStats();
|
||||||
|
stats_->addVisit(room_->getName());
|
||||||
|
cheevos_->enable(!options.cheats.enabled()); // Deshabilita los logros si hay trucos activados
|
||||||
|
|
||||||
|
options.section.section = Section::GAME;
|
||||||
|
options.section.subsection = Subsection::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::~Game()
|
||||||
|
{
|
||||||
|
ItemTracker::destroy();
|
||||||
|
SDL_DestroyTexture(room_name_texture_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba los eventos de la cola
|
||||||
|
void Game::checkEvents()
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
globalEvents::check(event);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (event.type == SDL_KEYDOWN && event.key.repeat == 0)
|
||||||
|
{
|
||||||
|
switch (event.key.keysym.scancode)
|
||||||
|
{
|
||||||
|
case SDL_SCANCODE_G:
|
||||||
|
debug_->switchEnabled();
|
||||||
|
options.cheats.invincible = static_cast<Cheat::CheatState>(debug_->getEnabled());
|
||||||
|
board_->music = !debug_->getEnabled();
|
||||||
|
board_->music ? JA_ResumeMusic() : JA_PauseMusic();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_R:
|
||||||
|
resource_->reload();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_W:
|
||||||
|
goToRoom(BORDER_TOP);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_A:
|
||||||
|
goToRoom(BORDER_LEFT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_S:
|
||||||
|
goToRoom(BORDER_BOTTOM);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_D:
|
||||||
|
goToRoom(BORDER_RIGHT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_F6:
|
||||||
|
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, NotificationText::LEFT, 2, false, "F6");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_F7:
|
||||||
|
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, NotificationText::LEFT, 3, false, "F7");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_F8:
|
||||||
|
Notifier::get()->show({"JAILDESIGNER", "IS LOGGED IN"}, NotificationText::LEFT, 4, false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_F9:
|
||||||
|
Notifier::get()->show({"JAILDESIGNER", "IS LOGGED IN"}, NotificationText::LEFT, 5, false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba el teclado
|
||||||
|
void Game::checkInput()
|
||||||
|
{
|
||||||
|
if (input_->checkInput(input_toggle_music, REPEAT_FALSE))
|
||||||
|
{
|
||||||
|
board_->music = !board_->music;
|
||||||
|
board_->music ? JA_ResumeMusic() : JA_PauseMusic();
|
||||||
|
Notifier::get()->show({"MUSIC " + std::string(board_->music ? "ENABLED" : "DISABLED")}, NotificationText::CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (input_->checkInput(input_pause, REPEAT_FALSE))
|
||||||
|
{
|
||||||
|
switchPause();
|
||||||
|
Notifier::get()->show({std::string(paused_ ? "GAME PAUSED" : "GAME RUNNING")}, NotificationText::CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
globalInputs::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bucle para el juego
|
||||||
|
void Game::run()
|
||||||
|
{
|
||||||
|
JA_PlayMusic(music_);
|
||||||
|
if (!board_->music)
|
||||||
|
{
|
||||||
|
JA_PauseMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (options.section.section == Section::GAME)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
checkEvents();
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
|
||||||
|
JA_StopMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza el juego, las variables, comprueba la entrada, etc.
|
||||||
|
void Game::update()
|
||||||
|
{
|
||||||
|
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
||||||
|
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
|
||||||
|
{
|
||||||
|
// Actualiza el contador de ticks
|
||||||
|
ticks_ = SDL_GetTicks();
|
||||||
|
|
||||||
|
// Comprueba el teclado
|
||||||
|
checkInput();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug_->clear();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Actualiza los objetos
|
||||||
|
room_->update();
|
||||||
|
player_->update();
|
||||||
|
checkPlayerOnBorder();
|
||||||
|
checkPlayerAndItems();
|
||||||
|
checkPlayerAndEnemies();
|
||||||
|
checkIfPlayerIsAlive();
|
||||||
|
checkGameOver();
|
||||||
|
checkEndGame();
|
||||||
|
checkRestoringJail();
|
||||||
|
checkSomeCheevos();
|
||||||
|
scoreboard_->update();
|
||||||
|
input_->update();
|
||||||
|
|
||||||
|
updateBlackScreen();
|
||||||
|
|
||||||
|
screen_->update();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
updateDebugInfo();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pinta los objetos en pantalla
|
||||||
|
void Game::render()
|
||||||
|
{
|
||||||
|
// Prepara para dibujar el frame
|
||||||
|
screen_->start();
|
||||||
|
//test_surface_->render(0, 0, 10, 10, 64, 64);
|
||||||
|
|
||||||
|
// Dibuja los elementos del juego en orden
|
||||||
|
room_->renderMap();
|
||||||
|
room_->renderEnemies();
|
||||||
|
room_->renderItems();
|
||||||
|
player_->render();
|
||||||
|
renderRoomName();
|
||||||
|
scoreboard_->render();
|
||||||
|
renderBlackScreen();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// Debug info
|
||||||
|
renderDebugInfo();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Actualiza la pantalla
|
||||||
|
screen_->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// Pasa la información de debug
|
||||||
|
void Game::updateDebugInfo()
|
||||||
|
{
|
||||||
|
debug_->add("X = " + std::to_string(static_cast<int>(player_->x_)) + ", Y = " + std::to_string(static_cast<int>(player_->y_)));
|
||||||
|
debug_->add("VX = " + std::to_string(player_->vx_).substr(0, 4) + ", VY = " + std::to_string(player_->vy_).substr(0, 4));
|
||||||
|
debug_->add("STATE = " + std::to_string(static_cast<int>(player_->state_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pone la información de debug en pantalla
|
||||||
|
void Game::renderDebugInfo()
|
||||||
|
{
|
||||||
|
if (!debug_->getEnabled())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Borra el marcador
|
||||||
|
SDL_Rect rect = {0, 18 * BLOCK, PLAY_AREA_WIDTH, GAMECANVAS_HEIGHT - PLAY_AREA_HEIGHT};
|
||||||
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255);
|
||||||
|
SDL_RenderFillRect(renderer_, &rect);
|
||||||
|
|
||||||
|
// Pinta la rejilla
|
||||||
|
SDL_SetRenderDrawColor(renderer_, 255, 255, 255, 32);
|
||||||
|
for (int i = 0; i < PLAY_AREA_BOTTOM; i += 8)
|
||||||
|
{ // Lineas horizontales
|
||||||
|
SDL_RenderDrawLine(renderer_, 0, i, PLAY_AREA_RIGHT, i);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < PLAY_AREA_RIGHT; i += 8)
|
||||||
|
{ // Lineas verticales
|
||||||
|
SDL_RenderDrawLine(renderer_, i, 0, i, PLAY_AREA_BOTTOM - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pinta el texto
|
||||||
|
debug_->setPos({1, 18 * 8});
|
||||||
|
debug_->render();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Escribe el nombre de la pantalla
|
||||||
|
void Game::renderRoomName()
|
||||||
|
{
|
||||||
|
// Dibuja la textura con el nombre de la habitación
|
||||||
|
SDL_RenderCopy(renderer_, room_name_texture_, nullptr, &room_name_rect_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cambia de habitación
|
||||||
|
bool Game::changeRoom(std::string file)
|
||||||
|
{
|
||||||
|
// En las habitaciones los limites tienen la cadena del fichero o un 0 en caso de no limitar con nada
|
||||||
|
if (file == "0")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica que exista el fichero que se va a cargar
|
||||||
|
if (asset_->get(file) != "")
|
||||||
|
{
|
||||||
|
// Crea un objeto habitación nuevo a partir del fichero
|
||||||
|
room_ = std::make_shared<Room>(resource_->getRoom(file), board_);
|
||||||
|
|
||||||
|
// Pone el nombre de la habitación en la textura
|
||||||
|
fillRoomNameTexture();
|
||||||
|
|
||||||
|
// Pone el color del marcador en función del color del borde de la habitación
|
||||||
|
setScoreBoardColor();
|
||||||
|
|
||||||
|
if (room_tracker_->addRoom(file))
|
||||||
|
{
|
||||||
|
// Incrementa el contador de habitaciones visitadas
|
||||||
|
board_->rooms++;
|
||||||
|
options.stats.rooms = board_->rooms;
|
||||||
|
|
||||||
|
// Actualiza las estadisticas
|
||||||
|
stats_->addVisit(room_->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pasa la nueva habitación al jugador
|
||||||
|
player_->setRoom(room_);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba si el jugador esta en el borde de la pantalla
|
||||||
|
void Game::checkPlayerOnBorder()
|
||||||
|
{
|
||||||
|
if (player_->getOnBorder())
|
||||||
|
{
|
||||||
|
const std::string roomName = room_->getRoom(player_->getBorder());
|
||||||
|
if (changeRoom(roomName))
|
||||||
|
{
|
||||||
|
player_->switchBorders();
|
||||||
|
current_room_ = roomName;
|
||||||
|
spawn_point_ = player_->getSpawnParams();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba las colisiones del jugador con los enemigos
|
||||||
|
bool Game::checkPlayerAndEnemies()
|
||||||
|
{
|
||||||
|
const bool death = room_->enemyCollision(player_->getCollider());
|
||||||
|
if (death)
|
||||||
|
{
|
||||||
|
killPlayer();
|
||||||
|
}
|
||||||
|
return death;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba las colisiones del jugador con los objetos
|
||||||
|
void Game::checkPlayerAndItems()
|
||||||
|
{
|
||||||
|
room_->itemCollision(player_->getCollider());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba si el jugador esta vivo
|
||||||
|
void Game::checkIfPlayerIsAlive()
|
||||||
|
{
|
||||||
|
if (!player_->isAlive())
|
||||||
|
{
|
||||||
|
killPlayer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba si ha terminado la partida
|
||||||
|
void Game::checkGameOver()
|
||||||
|
{
|
||||||
|
if (board_->lives < 0 && black_screen_counter_ > 17)
|
||||||
|
{
|
||||||
|
options.section.section = Section::GAME_OVER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mata al jugador
|
||||||
|
void Game::killPlayer()
|
||||||
|
{
|
||||||
|
if (options.cheats.invincible == Cheat::CheatState::ENABLED)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resta una vida al jugador
|
||||||
|
if (options.cheats.infinite_lives == Cheat::CheatState::DISABLED)
|
||||||
|
{
|
||||||
|
--board_->lives;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza las estadisticas
|
||||||
|
stats_->addDeath(room_->getName());
|
||||||
|
|
||||||
|
// Invalida el logro de pasarse el juego sin morir
|
||||||
|
cheevos_->invalidate(11);
|
||||||
|
|
||||||
|
// Sonido
|
||||||
|
JA_PlaySound(death_sound_);
|
||||||
|
|
||||||
|
// Pone la pantalla en negro un tiempo
|
||||||
|
setBlackScreen();
|
||||||
|
|
||||||
|
// Crea la nueva habitación y el nuevo jugador
|
||||||
|
room_ = std::make_shared<Room>(resource_->getRoom(current_room_), board_);
|
||||||
|
std::string player_texture = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.png" : "player.png";
|
||||||
|
std::string player_animations = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.ani" : "player.ani";
|
||||||
|
const PlayerData player(spawn_point_, player_texture, player_animations, room_);
|
||||||
|
player_ = std::make_shared<Player>(player);
|
||||||
|
|
||||||
|
// Pone los objetos en pausa mientras esta la habitación en negro
|
||||||
|
room_->pause();
|
||||||
|
player_->pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recarga todas las texturas
|
||||||
|
void Game::reLoadTextures()
|
||||||
|
{
|
||||||
|
if (options.console)
|
||||||
|
{
|
||||||
|
std::cout << "** RELOAD REQUESTED" << std::endl;
|
||||||
|
}
|
||||||
|
player_->reLoadTexture();
|
||||||
|
room_->reLoadTexture();
|
||||||
|
scoreboard_->reLoadTexture();
|
||||||
|
text_->reLoadTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establece la pantalla en negro
|
||||||
|
void Game::setBlackScreen()
|
||||||
|
{
|
||||||
|
black_screen_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza las variables relativas a la pantalla en negro
|
||||||
|
void Game::updateBlackScreen()
|
||||||
|
{
|
||||||
|
if (black_screen_)
|
||||||
|
{
|
||||||
|
black_screen_counter_++;
|
||||||
|
if (black_screen_counter_ > 20)
|
||||||
|
{
|
||||||
|
black_screen_ = false;
|
||||||
|
black_screen_counter_ = 0;
|
||||||
|
|
||||||
|
player_->resume();
|
||||||
|
room_->resume();
|
||||||
|
screen_->setBorderColor(room_->getBorderColor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja la pantalla negra
|
||||||
|
void Game::renderBlackScreen()
|
||||||
|
{
|
||||||
|
if (black_screen_)
|
||||||
|
{
|
||||||
|
screen_->clean();
|
||||||
|
screen_->setBorderColor(stringToColor(options.video.palette, "black"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pone el color del marcador en función del color del borde de la habitación
|
||||||
|
void Game::setScoreBoardColor()
|
||||||
|
{
|
||||||
|
// Obtiene el color del borde
|
||||||
|
const Color colorBorder = room_->getBorderColor();
|
||||||
|
|
||||||
|
const bool isBlack = colorAreEqual(colorBorder, stringToColor(options.video.palette, "black"));
|
||||||
|
const bool isBrightBlack = colorAreEqual(colorBorder, stringToColor(options.video.palette, "bright_black"));
|
||||||
|
|
||||||
|
// Si el color del borde es negro o negro brillante cambia el texto del marcador a blanco
|
||||||
|
board_->color = isBlack || isBrightBlack ? stringToColor(options.video.palette, "white") : colorBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba si ha finalizado el juego
|
||||||
|
bool Game::checkEndGame()
|
||||||
|
{
|
||||||
|
const bool isOnTheRoom = room_->getName() == "THE JAIL"; // Estar en la habitación que toca
|
||||||
|
const bool haveTheItems = board_->items >= int(total_items_ * 0.9f) || options.cheats.jail_is_open == Cheat::CheatState::ENABLED; // Con mas del 90% de los items recogidos
|
||||||
|
const bool isOnTheDoor = player_->getRect().x <= 128; // Y en la ubicación que toca (En la puerta)
|
||||||
|
|
||||||
|
if (haveTheItems)
|
||||||
|
{
|
||||||
|
board_->jail_is_open = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (haveTheItems && isOnTheRoom && isOnTheDoor)
|
||||||
|
{
|
||||||
|
// Comprueba los logros de completar el juego
|
||||||
|
checkEndGameCheevos();
|
||||||
|
|
||||||
|
options.section.section = Section::ENDING;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtiene la cantidad total de items que hay en el mapeado del juego
|
||||||
|
int Game::getTotalItems()
|
||||||
|
{
|
||||||
|
int items = 0;
|
||||||
|
auto rooms = resource_->getRooms();
|
||||||
|
|
||||||
|
for (auto room : rooms)
|
||||||
|
{
|
||||||
|
items += room.room->items.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Va a la habitación designada
|
||||||
|
void Game::goToRoom(int border)
|
||||||
|
{
|
||||||
|
const std::string roomName = room_->getRoom(border);
|
||||||
|
if (changeRoom(roomName))
|
||||||
|
{
|
||||||
|
current_room_ = roomName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pone el juego en pausa
|
||||||
|
void Game::switchPause()
|
||||||
|
{
|
||||||
|
if (paused_)
|
||||||
|
{
|
||||||
|
player_->resume();
|
||||||
|
room_->resume();
|
||||||
|
scoreboard_->resume();
|
||||||
|
paused_ = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player_->pause();
|
||||||
|
room_->pause();
|
||||||
|
scoreboard_->pause();
|
||||||
|
paused_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Da vidas al jugador cuando está en la Jail
|
||||||
|
void Game::checkRestoringJail()
|
||||||
|
{
|
||||||
|
if (room_->getName() != "THE JAIL" || board_->lives == 9)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int counter = 0;
|
||||||
|
|
||||||
|
if (!paused_)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Incrementa el numero de vidas
|
||||||
|
if (counter == 100)
|
||||||
|
{
|
||||||
|
counter = 0;
|
||||||
|
board_->lives++;
|
||||||
|
JA_PlaySound(death_sound_);
|
||||||
|
|
||||||
|
// Invalida el logro de completar el juego sin entrar a la jail
|
||||||
|
const bool haveTheItems = board_->items >= int(total_items_ * 0.9f);
|
||||||
|
if (!haveTheItems)
|
||||||
|
{
|
||||||
|
cheevos_->invalidate(9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicializa el diccionario de las estadísticas
|
||||||
|
void Game::initStats()
|
||||||
|
{
|
||||||
|
auto rooms = resource_->getRooms();
|
||||||
|
|
||||||
|
for (auto room : rooms)
|
||||||
|
{
|
||||||
|
stats_->addDictionary(room.room->number, room.room->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
stats_->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crea la textura con el nombre de la habitación
|
||||||
|
void Game::fillRoomNameTexture()
|
||||||
|
{
|
||||||
|
// Pone la textura como destino de renderizado
|
||||||
|
SDL_SetRenderTarget(renderer_, room_name_texture_);
|
||||||
|
|
||||||
|
// Rellena la textura de color
|
||||||
|
const Color color = stringToColor(options.video.palette, "white");
|
||||||
|
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 0xFF);
|
||||||
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
|
// Escribe el texto en la textura
|
||||||
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, text_->getCharacterSize() / 2, room_->getName(), 1, room_->getBGColor());
|
||||||
|
|
||||||
|
// Deja el renderizador por defecto
|
||||||
|
SDL_SetRenderTarget(renderer_, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba algunos logros
|
||||||
|
void Game::checkSomeCheevos()
|
||||||
|
{
|
||||||
|
// Logros sobre la cantidad de items
|
||||||
|
if (board_->items == total_items_)
|
||||||
|
{
|
||||||
|
cheevos_->unlock(4);
|
||||||
|
cheevos_->unlock(3);
|
||||||
|
cheevos_->unlock(2);
|
||||||
|
cheevos_->unlock(1);
|
||||||
|
}
|
||||||
|
else if (board_->items >= total_items_ * 0.75f)
|
||||||
|
{
|
||||||
|
cheevos_->unlock(3);
|
||||||
|
cheevos_->unlock(2);
|
||||||
|
cheevos_->unlock(1);
|
||||||
|
}
|
||||||
|
else if (board_->items >= total_items_ * 0.5f)
|
||||||
|
{
|
||||||
|
cheevos_->unlock(2);
|
||||||
|
cheevos_->unlock(1);
|
||||||
|
}
|
||||||
|
else if (board_->items >= total_items_ * 0.25f)
|
||||||
|
{
|
||||||
|
cheevos_->unlock(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logros sobre las habitaciones visitadas
|
||||||
|
if (board_->rooms >= 60)
|
||||||
|
{
|
||||||
|
cheevos_->unlock(7);
|
||||||
|
cheevos_->unlock(6);
|
||||||
|
cheevos_->unlock(5);
|
||||||
|
}
|
||||||
|
else if (board_->rooms >= 40)
|
||||||
|
{
|
||||||
|
cheevos_->unlock(6);
|
||||||
|
cheevos_->unlock(5);
|
||||||
|
}
|
||||||
|
else if (board_->rooms >= 20)
|
||||||
|
{
|
||||||
|
cheevos_->unlock(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba los logros de completar el juego
|
||||||
|
void Game::checkEndGameCheevos()
|
||||||
|
{
|
||||||
|
// "Complete the game"
|
||||||
|
cheevos_->unlock(8);
|
||||||
|
|
||||||
|
// "Complete the game without entering the jail"
|
||||||
|
cheevos_->unlock(9);
|
||||||
|
|
||||||
|
// "Complete the game with all items"
|
||||||
|
if (board_->items == total_items_)
|
||||||
|
{
|
||||||
|
cheevos_->unlock(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Complete the game without dying"
|
||||||
|
cheevos_->unlock(11);
|
||||||
|
|
||||||
|
// "Complete the game in under 30 minutes"
|
||||||
|
if (scoreboard_->getMinutes() < 30)
|
||||||
|
{
|
||||||
|
cheevos_->unlock(12);
|
||||||
|
}
|
||||||
|
}
|
||||||
156
source/game.h
Normal file
156
source/game.h
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL_events.h> // Para SDL_Event
|
||||||
|
#include <SDL2/SDL_rect.h> // Para SDL_Rect
|
||||||
|
#include <SDL2/SDL_render.h> // Para SDL_Renderer, SDL_Texture
|
||||||
|
#include <SDL2/SDL_stdinc.h> // Para Uint32
|
||||||
|
#include <string> // Para string, basic_string
|
||||||
|
#include "player.h" // Para playerSpawn_t
|
||||||
|
#include "scoreboard.h" // Para board_t
|
||||||
|
#include "room.h"
|
||||||
|
//#include "surface.h"
|
||||||
|
class Asset;
|
||||||
|
class Cheevos;
|
||||||
|
class Debug;
|
||||||
|
class Input;
|
||||||
|
class ItemTracker;
|
||||||
|
class Resource;
|
||||||
|
class Room;
|
||||||
|
class RoomTracker;
|
||||||
|
class Screen;
|
||||||
|
class Stats;
|
||||||
|
class Text;
|
||||||
|
struct JA_Music_t;
|
||||||
|
struct JA_Sound_t;
|
||||||
|
struct Options;
|
||||||
|
struct SectionState;
|
||||||
|
|
||||||
|
class Game
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// Objetos y punteros
|
||||||
|
Screen *screen_; // Objeto encargado de manejar el renderizador
|
||||||
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
|
Asset *asset_; // Objeto con la ruta a todos los ficheros de recursos
|
||||||
|
Input *input_; // Objeto pata gestionar la entrada
|
||||||
|
Resource *resource_; // Objeto con los recursos
|
||||||
|
Debug *debug_; // Objeto para gestionar la información de debug
|
||||||
|
Cheevos *cheevos_; // Objeto encargado de gestionar los logros del juego
|
||||||
|
std::shared_ptr<Room> room_; // Objeto encargado de gestionar cada habitación del juego
|
||||||
|
std::shared_ptr<Player> player_; // Objeto con el jugador
|
||||||
|
std::shared_ptr<RoomTracker> room_tracker_; // Lleva el control de las habitaciones visitadas
|
||||||
|
std::shared_ptr<Text> text_; // Objeto para los textos del juego
|
||||||
|
std::shared_ptr<Scoreboard> scoreboard_; // Objeto encargado de gestionar el marcador
|
||||||
|
std::shared_ptr<Stats> stats_; // Objeto encargado de gestionar las estadísticas
|
||||||
|
SDL_Texture *room_name_texture_; // Textura para escribir el nombre de la habitación
|
||||||
|
//std::shared_ptr<Surface> test_surface_;
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
JA_Music_t *music_; // Musica que suena durante el juego
|
||||||
|
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
|
||||||
|
std::string current_room_; // Fichero de la habitación actual
|
||||||
|
PlayerSpawn spawn_point_; // Lugar de la habitación donde aparece el jugador
|
||||||
|
JA_Sound_t *death_sound_; // Sonido a reproducir cuando muere el jugador
|
||||||
|
std::shared_ptr<ScoreboardData> board_; // Estructura con los datos del marcador
|
||||||
|
bool paused_; // Indica si el juego se encuentra en pausa
|
||||||
|
bool black_screen_; // Indica si la pantalla está en negro. Se utiliza para la muerte del jugador
|
||||||
|
int black_screen_counter_; // Contador para temporizar la pantalla en negro
|
||||||
|
int total_items_; // Cantidad total de items que hay en el mapeado del juego
|
||||||
|
SDL_Rect room_name_rect_; // Rectangulo donde pintar la textura con el nombre de la habitación
|
||||||
|
|
||||||
|
// Actualiza el juego, las variables, comprueba la entrada, etc.
|
||||||
|
void update();
|
||||||
|
|
||||||
|
// Pinta los objetos en pantalla
|
||||||
|
void render();
|
||||||
|
|
||||||
|
// Comprueba los eventos de la cola
|
||||||
|
void checkEvents();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// Pone la información de debug en pantalla
|
||||||
|
void updateDebugInfo();
|
||||||
|
|
||||||
|
// Pone la información de debug en pantalla
|
||||||
|
void renderDebugInfo();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Escribe el nombre de la pantalla
|
||||||
|
void renderRoomName();
|
||||||
|
|
||||||
|
// Cambia de habitación
|
||||||
|
bool changeRoom(std::string file);
|
||||||
|
|
||||||
|
// Comprueba el teclado
|
||||||
|
void checkInput();
|
||||||
|
|
||||||
|
// Comprueba si el jugador esta en el borde de la pantalla y actua
|
||||||
|
void checkPlayerOnBorder();
|
||||||
|
|
||||||
|
// Comprueba las colisiones del jugador con los enemigos
|
||||||
|
bool checkPlayerAndEnemies();
|
||||||
|
|
||||||
|
// Comprueba las colisiones del jugador con los objetos
|
||||||
|
void checkPlayerAndItems();
|
||||||
|
|
||||||
|
// Comprueba si el jugador esta vivo
|
||||||
|
void checkIfPlayerIsAlive();
|
||||||
|
|
||||||
|
// Comprueba si ha terminado la partida
|
||||||
|
void checkGameOver();
|
||||||
|
|
||||||
|
// Mata al jugador
|
||||||
|
void killPlayer();
|
||||||
|
|
||||||
|
// Recarga todas las texturas
|
||||||
|
void reLoadTextures();
|
||||||
|
|
||||||
|
// Establece la pantalla en negro
|
||||||
|
void setBlackScreen();
|
||||||
|
|
||||||
|
// Actualiza las variables relativas a la pantalla en negro
|
||||||
|
void updateBlackScreen();
|
||||||
|
|
||||||
|
// Dibuja la pantalla negra
|
||||||
|
void renderBlackScreen();
|
||||||
|
|
||||||
|
// Pone el color del marcador en función del color del borde de la habitación
|
||||||
|
void setScoreBoardColor();
|
||||||
|
|
||||||
|
// Comprueba si ha finalizado el juego
|
||||||
|
bool checkEndGame();
|
||||||
|
|
||||||
|
// Obtiene la cantidad total de items que hay en el mapeado del juego
|
||||||
|
int getTotalItems();
|
||||||
|
|
||||||
|
// Va a la habitación designada
|
||||||
|
void goToRoom(int border);
|
||||||
|
|
||||||
|
// Pone el juego en pausa
|
||||||
|
void switchPause();
|
||||||
|
|
||||||
|
// Da vidas al jugador cuando está en la Jail
|
||||||
|
void checkRestoringJail();
|
||||||
|
|
||||||
|
// Inicializa el diccionario de las estadísticas
|
||||||
|
void initStats();
|
||||||
|
|
||||||
|
// Pone el nombre de la habitación en la textura
|
||||||
|
void fillRoomNameTexture();
|
||||||
|
|
||||||
|
// Comprueba algunos logros
|
||||||
|
void checkSomeCheevos();
|
||||||
|
|
||||||
|
// Comprueba los logros de completar el juego
|
||||||
|
void checkEndGameCheevos();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
Game();
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~Game();
|
||||||
|
|
||||||
|
// Bucle para el juego
|
||||||
|
void run();
|
||||||
|
};
|
||||||
190
source/game_over.cpp
Normal file
190
source/game_over.cpp
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
#include "game_over.h"
|
||||||
|
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
|
||||||
|
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
|
||||||
|
#include <algorithm> // for min, max
|
||||||
|
#include <string> // for basic_string, operator+, to_string, cha...
|
||||||
|
#include "animated_sprite.h" // for AnimatedSprite
|
||||||
|
#include "asset.h" // for Asset
|
||||||
|
#include "defines.h" // for GAMECANVAS_CENTER_X
|
||||||
|
#include "global_events.h" // for check
|
||||||
|
#include "global_inputs.h" // for check
|
||||||
|
#include "input.h" // for Input
|
||||||
|
#include "jail_audio.h" // for JA_PlayMusic
|
||||||
|
#include "options.h" // for Options, options, OptionsStats, Section...
|
||||||
|
#include "resource.h" // for Resource
|
||||||
|
#include "screen.h" // for Screen
|
||||||
|
#include "text.h" // for TEXT_CENTER, TEXT_COLOR, Text
|
||||||
|
#include "texture.h" // for Texture
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
GameOver::GameOver()
|
||||||
|
: screen_(Screen::get()),
|
||||||
|
renderer_(Screen::get()->getRenderer()),
|
||||||
|
resource_(Resource::get()),
|
||||||
|
asset_(Asset::get()),
|
||||||
|
input_(Input::get())
|
||||||
|
{
|
||||||
|
// Reserva memoria para los punteros a objetos
|
||||||
|
text_ = resource_->getText("smb2");
|
||||||
|
player_sprite_ = std::make_shared<AnimatedSprite>(resource_->getTexture("player_game_over.png"), resource_->getAnimations("player_game_over.ani"));
|
||||||
|
tv_sprite_ = std::make_shared<AnimatedSprite>(resource_->getTexture("tv.png"), resource_->getAnimations("tv.ani"));
|
||||||
|
music_ = resource_->getMusic("game_over.ogg");
|
||||||
|
|
||||||
|
// Inicializa variables
|
||||||
|
pre_counter_ = 0;
|
||||||
|
counter_ = 0;
|
||||||
|
options.section.section = Section::GAME_OVER;
|
||||||
|
options.section.subsection = Subsection::NONE;
|
||||||
|
ticks_ = 0;
|
||||||
|
player_sprite_->setPosX(GAMECANVAS_CENTER_X + 10);
|
||||||
|
player_sprite_->setPosY(30);
|
||||||
|
tv_sprite_->setPosX(GAMECANVAS_CENTER_X - tv_sprite_->getWidth() - 10);
|
||||||
|
tv_sprite_->setPosY(30);
|
||||||
|
|
||||||
|
// Inicializa el vector de colores
|
||||||
|
const std::vector<std::string> colorList = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"};
|
||||||
|
for (auto cl : colorList)
|
||||||
|
{
|
||||||
|
colors_.push_back(stringToColor(options.video.palette, cl));
|
||||||
|
}
|
||||||
|
color_ = colors_.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza el objeto
|
||||||
|
void GameOver::update()
|
||||||
|
{
|
||||||
|
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
||||||
|
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
|
||||||
|
{
|
||||||
|
// Actualiza el contador de ticks
|
||||||
|
ticks_ = SDL_GetTicks();
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
checkInput();
|
||||||
|
|
||||||
|
// Actualiza el color usado para renderizar los textos e imagenes
|
||||||
|
updateColor();
|
||||||
|
|
||||||
|
// Actualiza los contadores
|
||||||
|
updateCounters();
|
||||||
|
|
||||||
|
// Actualiza los dos sprites
|
||||||
|
player_sprite_->update();
|
||||||
|
tv_sprite_->update();
|
||||||
|
|
||||||
|
screen_->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja el final en pantalla
|
||||||
|
void GameOver::render()
|
||||||
|
{
|
||||||
|
constexpr int Y = 32;
|
||||||
|
|
||||||
|
screen_->start();
|
||||||
|
screen_->clean();
|
||||||
|
|
||||||
|
// Escribe el texto de GAME OVER
|
||||||
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y, "G A M E O V E R", 1, color_);
|
||||||
|
|
||||||
|
// Dibuja los sprites
|
||||||
|
player_sprite_->setPosY(Y + 30);
|
||||||
|
tv_sprite_->setPosY(Y + 30);
|
||||||
|
renderSprites();
|
||||||
|
|
||||||
|
// Escribe el texto con las habitaciones y los items
|
||||||
|
const std::string itemsTxt = std::to_string(options.stats.items / 100) + std::to_string((options.stats.items % 100) / 10) + std::to_string(options.stats.items % 10);
|
||||||
|
const std::string roomsTxt = std::to_string(options.stats.rooms / 100) + std::to_string((options.stats.rooms % 100) / 10) + std::to_string(options.stats.rooms % 10);
|
||||||
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 80, "ITEMS: " + itemsTxt, 1, color_);
|
||||||
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 90, "ROOMS: " + roomsTxt, 1, color_);
|
||||||
|
|
||||||
|
// Escribe el texto con "Tu peor pesadilla"
|
||||||
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 110, "YOUR WORST NIGHTMARE IS", 1, color_);
|
||||||
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 120, options.stats.worst_nightmare, 1, color_);
|
||||||
|
|
||||||
|
// Vuelca el contenido del renderizador en pantalla
|
||||||
|
screen_->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba el manejador de eventos
|
||||||
|
void GameOver::checkEvents()
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
globalEvents::check(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
void GameOver::checkInput()
|
||||||
|
{
|
||||||
|
globalInputs::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bucle principal
|
||||||
|
void GameOver::run()
|
||||||
|
{
|
||||||
|
while (options.section.section == Section::GAME_OVER)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
checkEvents();
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza el color usado para renderizar los textos e imagenes
|
||||||
|
void GameOver::updateColor()
|
||||||
|
{
|
||||||
|
const int half = COUNTER_SECTION_END_ / 2;
|
||||||
|
|
||||||
|
if (counter_ < half)
|
||||||
|
{
|
||||||
|
const float step = std::min(counter_, COUNTER_FADE_LENGHT_) / (float)COUNTER_FADE_LENGHT_;
|
||||||
|
const int index = (colors_.size() - 1) - int((colors_.size() - 1) * step);
|
||||||
|
color_ = colors_[index];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const float step = std::min(std::max(counter_, COUNTER_INIT_FADE_) - COUNTER_INIT_FADE_, COUNTER_FADE_LENGHT_) / (float)COUNTER_FADE_LENGHT_;
|
||||||
|
const int index = (colors_.size() - 1) * step;
|
||||||
|
color_ = colors_[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja los sprites
|
||||||
|
void GameOver::renderSprites()
|
||||||
|
{
|
||||||
|
player_sprite_->getTexture()->setColor(color_.r, color_.g, color_.b);
|
||||||
|
player_sprite_->render();
|
||||||
|
|
||||||
|
tv_sprite_->getTexture()->setColor(color_.r, color_.g, color_.b);
|
||||||
|
tv_sprite_->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza los contadores
|
||||||
|
void GameOver::updateCounters()
|
||||||
|
{
|
||||||
|
// Actualiza el contador
|
||||||
|
if (pre_counter_ < 50)
|
||||||
|
{
|
||||||
|
pre_counter_++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
counter_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hace sonar la música
|
||||||
|
if (counter_ == 1)
|
||||||
|
{
|
||||||
|
JA_PlayMusic(music_, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba si ha terminado la sección
|
||||||
|
else if (counter_ == COUNTER_SECTION_END_)
|
||||||
|
{
|
||||||
|
options.section.section = Section::LOGO;
|
||||||
|
options.section.subsection = Subsection::LOGO_TO_TITLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
72
source/game_over.h
Normal file
72
source/game_over.h
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL_render.h> // for SDL_Renderer
|
||||||
|
#include <SDL2/SDL_stdinc.h> // for Uint32
|
||||||
|
#include <memory> // for shared_ptr
|
||||||
|
#include <vector> // for vector
|
||||||
|
#include "utils.h" // for Color
|
||||||
|
class AnimatedSprite; // lines 9-9
|
||||||
|
class Asset; // lines 10-10
|
||||||
|
class Input; // lines 11-11
|
||||||
|
class Resource; // lines 12-12
|
||||||
|
class Screen; // lines 13-13
|
||||||
|
class Text; // lines 14-14
|
||||||
|
struct JA_Music_t; // lines 15-15
|
||||||
|
|
||||||
|
class GameOver
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// Constantes
|
||||||
|
static constexpr int COUNTER_SECTION_END_ = 400; // Contador: cuando acaba la sección
|
||||||
|
static constexpr int COUNTER_INIT_FADE_ = 310; // Contador: cuando emiepza el fade
|
||||||
|
static constexpr int COUNTER_FADE_LENGHT_ = 20; // Contador: duración del fade
|
||||||
|
|
||||||
|
// Objetos y punteros
|
||||||
|
Screen *screen_; // Objeto encargado de dibujar en pantalla
|
||||||
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
|
Resource *resource_; // Objeto con los recursos
|
||||||
|
Asset *asset_; // Objeto con los ficheros de recursos
|
||||||
|
Input *input_; // Objeto pata gestionar la entrada
|
||||||
|
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
|
||||||
|
std::shared_ptr<AnimatedSprite> player_sprite_; // Sprite con el jugador
|
||||||
|
std::shared_ptr<AnimatedSprite> tv_sprite_; // Sprite con el televisor
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
int pre_counter_ = 0; // Contador previo
|
||||||
|
int counter_ = 0; // Contador
|
||||||
|
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
||||||
|
std::vector<Color> colors_; // Vector con los colores para el fade
|
||||||
|
Color color_; // Color usado para el texto y los sprites
|
||||||
|
JA_Music_t *music_; // Musica que suena durante el juego
|
||||||
|
|
||||||
|
// Actualiza el objeto
|
||||||
|
void update();
|
||||||
|
|
||||||
|
// Dibuja el final en pantalla
|
||||||
|
void render();
|
||||||
|
|
||||||
|
// Comprueba el manejador de eventos
|
||||||
|
void checkEvents();
|
||||||
|
|
||||||
|
// Comprueba las entradas
|
||||||
|
void checkInput();
|
||||||
|
|
||||||
|
// Actualiza el color usado para renderizar los textos e imagenes
|
||||||
|
void updateColor();
|
||||||
|
|
||||||
|
// Dibuja los sprites
|
||||||
|
void renderSprites();
|
||||||
|
|
||||||
|
// Actualiza los contadores
|
||||||
|
void updateCounters();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
GameOver();
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~GameOver() = default;
|
||||||
|
|
||||||
|
// Bucle principal
|
||||||
|
void run();
|
||||||
|
};
|
||||||
@@ -1,360 +0,0 @@
|
|||||||
#include "gamestate_credits.h"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Credits::Credits(SDL_Renderer *renderer, Screen *screen, Resource *resource, Asset *asset, Input *input, options_t *options, section_t *section)
|
|
||||||
{
|
|
||||||
// Copia la dirección de los objetos
|
|
||||||
this->renderer = renderer;
|
|
||||||
this->screen = screen;
|
|
||||||
this->resource = resource;
|
|
||||||
this->asset = asset;
|
|
||||||
this->input = input;
|
|
||||||
this->options = options;
|
|
||||||
this->section = section;
|
|
||||||
|
|
||||||
// Reserva memoria para los punteros
|
|
||||||
eventHandler = new SDL_Event();
|
|
||||||
text = new Text(resource->getOffset("smb2.txt"), resource->getTexture("smb2.png"), renderer);
|
|
||||||
sprite = new AnimatedSprite(renderer, resource->getAnimation("shine.ani"));
|
|
||||||
|
|
||||||
// Inicializa variables
|
|
||||||
counter = 0;
|
|
||||||
counterEnabled = true;
|
|
||||||
subCounter = 0;
|
|
||||||
section->name = SECTION_CREDITS;
|
|
||||||
section->subsection = 0;
|
|
||||||
ticks = 0;
|
|
||||||
ticksSpeed = 15;
|
|
||||||
sprite->setRect({194, 174, 8, 8});
|
|
||||||
|
|
||||||
// Cambia el color del borde
|
|
||||||
screen->setBorderColor(stringToColor(options->palette, "black"));
|
|
||||||
|
|
||||||
// Crea la textura para el texto que se escribe en pantalla
|
|
||||||
textTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT);
|
|
||||||
if (textTexture == nullptr)
|
|
||||||
{
|
|
||||||
if (options->console)
|
|
||||||
{
|
|
||||||
std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SDL_SetTextureBlendMode(textTexture, SDL_BLENDMODE_BLEND);
|
|
||||||
|
|
||||||
// Crea la textura para cubrir el rexto
|
|
||||||
coverTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT);
|
|
||||||
if (coverTexture == nullptr)
|
|
||||||
{
|
|
||||||
if (options->console)
|
|
||||||
{
|
|
||||||
std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SDL_SetTextureBlendMode(coverTexture, SDL_BLENDMODE_BLEND);
|
|
||||||
|
|
||||||
// Escribe el texto en la textura
|
|
||||||
fillTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
Credits::~Credits()
|
|
||||||
{
|
|
||||||
delete eventHandler;
|
|
||||||
delete text;
|
|
||||||
delete sprite;
|
|
||||||
SDL_DestroyTexture(textTexture);
|
|
||||||
SDL_DestroyTexture(coverTexture);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba el manejador de eventos
|
|
||||||
void Credits::checkEvents()
|
|
||||||
{
|
|
||||||
// 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 = SECTION_QUIT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba las entradas
|
|
||||||
void Credits::checkInput()
|
|
||||||
{
|
|
||||||
|
|
||||||
if (input->checkInput(input_exit, REPEAT_FALSE))
|
|
||||||
{
|
|
||||||
section->name = SECTION_QUIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (input->checkInput(input_toggle_border, REPEAT_FALSE))
|
|
||||||
{
|
|
||||||
screen->switchBorder();
|
|
||||||
}
|
|
||||||
|
|
||||||
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_swap_palette, REPEAT_FALSE))
|
|
||||||
{
|
|
||||||
switchPalette();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (input->checkInput(input_pause, REPEAT_FALSE) || input->checkInput(input_accept, REPEAT_FALSE) || input->checkInput(input_jump, REPEAT_FALSE))
|
|
||||||
{
|
|
||||||
section->name = SECTION_TITLE;
|
|
||||||
section->subsection = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa los textos
|
|
||||||
void Credits::iniTexts()
|
|
||||||
{
|
|
||||||
std::string keys = "";
|
|
||||||
if (options->keys == ctrl_cursor)
|
|
||||||
{
|
|
||||||
keys = "CURSORS";
|
|
||||||
}
|
|
||||||
else if (options->keys == ctrl_opqa)
|
|
||||||
{
|
|
||||||
keys = "O,P AND Q";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
keys = "A,D AND W";
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef GAME_CONSOLE
|
|
||||||
texts.clear();
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"INSTRUCTIONS:", stringToColor(options->palette, "yellow")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"HELP JAILDOC TO GET BACK ALL", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"HIS PROJECTS AND GO TO THE", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"JAIL TO FINISH THEM", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
|
|
||||||
texts.push_back({"KEYS:", stringToColor(options->palette, "yellow")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({keys + " TO MOVE AND JUMP", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"M TO SWITCH THE MUSIC", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"H TO PAUSE THE GAME", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"F1-F2 TO CHANGE WINDOWS SIZE", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"F3 TO SWITCH TO FULLSCREEN", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"B TO TOOGLE THE BORDER SCREEN", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
|
|
||||||
texts.push_back({"A GAME BY JAILDESIGNER", stringToColor(options->palette, "yellow")});
|
|
||||||
texts.push_back({"MADE ON SUMMER/FALL 2022", stringToColor(options->palette, "yellow")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
|
|
||||||
texts.push_back({"I LOVE JAILGAMES! ", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
#else
|
|
||||||
texts.clear();
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"INSTRUCTIONS:", stringToColor(options->palette, "yellow")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"HELP JAILDOC TO GET BACK ALL", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"HIS PROJECTS AND GO TO THE", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"JAIL TO FINISH THEM", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
|
|
||||||
texts.push_back({"KEYS:", stringToColor(options->palette, "yellow")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"B TO JUMP", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"R TO SWITCH THE MUSIC", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"L TO SWAP THE COLOR PALETTE", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"START TO PAUSE", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"SELECT TO EXIT", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
|
|
||||||
texts.push_back({"A GAME BY JAILDESIGNER", stringToColor(options->palette, "yellow")});
|
|
||||||
texts.push_back({"MADE ON SUMMER/FALL 2022", stringToColor(options->palette, "yellow")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
|
|
||||||
texts.push_back({"I LOVE JAILGAMES! ", stringToColor(options->palette, "white")});
|
|
||||||
texts.push_back({"", stringToColor(options->palette, "white")});
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escribe el texto en la textura
|
|
||||||
void Credits::fillTexture()
|
|
||||||
{
|
|
||||||
// Inicializa los textos
|
|
||||||
iniTexts();
|
|
||||||
|
|
||||||
// Rellena la textura de texto
|
|
||||||
SDL_SetRenderTarget(renderer, textTexture);
|
|
||||||
color_t c = stringToColor(options->palette, "black");
|
|
||||||
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, 0xFF);
|
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
|
|
||||||
// Escribe el texto en la textura
|
|
||||||
const int size = text->getCharacterSize();
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (auto t : texts)
|
|
||||||
{
|
|
||||||
text->writeDX(TXT_CENTER | TXT_COLOR, PLAY_AREA_CENTER_X, i * size, t.label, 1, t.color);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escribe el corazón
|
|
||||||
const int textLenght = text->lenght(texts[22].label, 1) - text->lenght(" ", 1); // Se resta el ultimo caracter que es un espacio
|
|
||||||
const int posX = ((PLAY_AREA_WIDTH - textLenght) / 2) + textLenght;
|
|
||||||
text->writeColored(posX, 176, "}", stringToColor(options->palette, "bright_red"));
|
|
||||||
|
|
||||||
// Recoloca el sprite del brillo
|
|
||||||
sprite->setPosX(posX + 2);
|
|
||||||
|
|
||||||
SDL_SetRenderTarget(renderer, nullptr);
|
|
||||||
|
|
||||||
// Rellena la textura que cubre el texto con color transparente
|
|
||||||
SDL_SetRenderTarget(renderer, coverTexture);
|
|
||||||
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, 0x00);
|
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
|
|
||||||
// Los primeros 8 pixels crea una malla
|
|
||||||
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, 0xFF);
|
|
||||||
for (int i = 0; i < 256; i += 2)
|
|
||||||
{
|
|
||||||
SDL_RenderDrawPoint(renderer, i, 0);
|
|
||||||
SDL_RenderDrawPoint(renderer, i, 2);
|
|
||||||
SDL_RenderDrawPoint(renderer, i, 4);
|
|
||||||
SDL_RenderDrawPoint(renderer, i, 6);
|
|
||||||
|
|
||||||
SDL_RenderDrawPoint(renderer, i + 1, 5);
|
|
||||||
SDL_RenderDrawPoint(renderer, i + 1, 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
// El resto se rellena de color sólido
|
|
||||||
SDL_Rect rect = {0, 8, 256, 192};
|
|
||||||
SDL_RenderFillRect(renderer, &rect);
|
|
||||||
|
|
||||||
SDL_SetRenderTarget(renderer, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el contador
|
|
||||||
void Credits::updateCounter()
|
|
||||||
{
|
|
||||||
// Incrementa el contador
|
|
||||||
if (counterEnabled)
|
|
||||||
{
|
|
||||||
counter++;
|
|
||||||
if (counter == 224 || counter == 544 || counter == 672)
|
|
||||||
{
|
|
||||||
counterEnabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
subCounter++;
|
|
||||||
if (subCounter == 100)
|
|
||||||
{
|
|
||||||
counterEnabled = true;
|
|
||||||
subCounter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si ha terminado la sección
|
|
||||||
if (counter > 1200)
|
|
||||||
{
|
|
||||||
section->name = SECTION_DEMO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza las variables
|
|
||||||
void Credits::update()
|
|
||||||
{
|
|
||||||
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
|
||||||
if (SDL_GetTicks() - ticks > ticksSpeed)
|
|
||||||
{
|
|
||||||
// Actualiza el contador de ticks
|
|
||||||
ticks = SDL_GetTicks();
|
|
||||||
|
|
||||||
// Comprueba las entradas
|
|
||||||
checkInput();
|
|
||||||
|
|
||||||
// Actualiza el contador
|
|
||||||
updateCounter();
|
|
||||||
|
|
||||||
// Actualiza las notificaciones
|
|
||||||
screen->updateNotifier();
|
|
||||||
|
|
||||||
// Actualiza el sprite con el brillo
|
|
||||||
if (counter > 770)
|
|
||||||
{
|
|
||||||
sprite->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja en pantalla
|
|
||||||
void Credits::render()
|
|
||||||
{
|
|
||||||
// Prepara para empezar a dibujar en la textura de juego
|
|
||||||
screen->start();
|
|
||||||
|
|
||||||
// Limpia la pantalla
|
|
||||||
screen->clean();
|
|
||||||
|
|
||||||
if (counter < 1150)
|
|
||||||
{
|
|
||||||
// Dibuja la textura con el texto en pantalla
|
|
||||||
SDL_RenderCopy(renderer, textTexture, nullptr, nullptr);
|
|
||||||
|
|
||||||
// Dibuja la textura que cubre el texto
|
|
||||||
const int offset = std::min(counter / 8, 192 / 2);
|
|
||||||
SDL_Rect srcRect = {0, 0, 256, 192 - (offset * 2)};
|
|
||||||
SDL_Rect dstRect = {0, offset * 2, 256, 192 - (offset * 2)};
|
|
||||||
SDL_RenderCopy(renderer, coverTexture, &srcRect, &dstRect);
|
|
||||||
|
|
||||||
// Dibuja el sprite con el brillo
|
|
||||||
sprite->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vuelca el contenido del renderizador en pantalla
|
|
||||||
screen->blit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bucle para el logo del juego
|
|
||||||
void Credits::run()
|
|
||||||
{
|
|
||||||
while (section->name == SECTION_CREDITS)
|
|
||||||
{
|
|
||||||
update();
|
|
||||||
checkEvents();
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cambia la paleta
|
|
||||||
void Credits::switchPalette()
|
|
||||||
{
|
|
||||||
options->palette = options->palette == p_zxspectrum ? p_zxarne : p_zxspectrum;
|
|
||||||
fillTexture();
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user