145 Commits

Author SHA1 Message Date
e3d0145417 Opció de fer el reset amb o sense reload 2024-12-05 08:25:44 +01:00
f0863b3691 Afegit zoom al subtitol ARCADE EDITION 2024-12-05 08:18:40 +01:00
80e366b208 Treballant en el zoom del titol s'ha arreglat el rebot dels globos i ara mola mes, o aixo pense 2024-12-03 13:59:40 +01:00
3c5bbf2ab0 Afegit zoom a la classe Sprite 2024-12-03 11:39:31 +01:00
1aa0dd3864 Acabats els credits a 320x240 (i per extensió, a qualsevol resolució) 2024-12-03 10:51:19 +01:00
ab45c984a2 Treballant en els credits a 240 2024-12-02 13:45:31 +01:00
020ee81479 Duplicat el fitxers de shaders per a resolucions verticals de 256 i 240 2024-12-02 13:39:19 +01:00
0cd96aced5 Afegit globalInputs::update() a totes les seccions del programa 2024-12-02 11:34:31 +01:00
ad32bb7d45 Treballant en globalInputs::update() 2024-12-02 11:11:03 +01:00
c3a5166ee1 Afegit un pragma per a IWYU 2024-12-02 09:27:51 +01:00
687d329d23 FIX: Faltva corregir el flash de destroyAllBalloons() 2024-11-27 18:58:17 +01:00
faba87c06d FIX: Si saltes el logo talla el so a meitat sonar
FIX: Corregida la lògica del efecte de flash
2024-11-27 18:39:23 +01:00
eed45bdbc6 Notifier no gastava Resource per als sons
Resource no alliberava correctament els elements de JailAudio
2024-11-27 18:20:33 +01:00
6ed37425bf Furtat el so del logo de JAILGAMES de The Pool 2024-11-27 18:02:25 +01:00
b987d06aca El joc ja reinicia correctament 2024-11-27 17:54:52 +01:00
9c9cfdabc2 Canvi de idioma (i reinicia) amb una tecla 2024-11-27 09:48:14 +01:00
9f2448753b Afegides les traduccions dels credits 2024-11-27 09:16:17 +01:00
736bf7e544 Credits acabats e integrats amb la resta del joc. Falta traduirlos pero de moment me la pela un rato 2024-11-26 19:42:26 +01:00
a2d4331430 Treballant en els credits 2024-11-25 22:56:59 +01:00
fd7beee5a1 Continuem treballant en els credits 2024-11-25 17:48:25 +01:00
a36120cf0c Continuemtreballant enels credits 2024-11-24 20:21:46 +01:00
ad221243cb Afegida musica als credits
Els globos ara tenen definida una play_area
Opció de canviar la paleta al text
2024-11-24 19:07:19 +01:00
b8d4c8f17c Començan a treballar en la secció Credits 2024-11-22 20:48:52 +01:00
8941072357 Els items reboten al tocar el piso 2024-11-20 21:55:55 +01:00
77bf1d73b3 Afegits els grafics de caure derrotat per al segon jugador 2024-11-19 19:30:30 +01:00
700d3846fb Afegits rebots en la animació de morir 2024-11-19 18:59:35 +01:00
185a1b47d1 Afegida llengua fora i ulls en X a la animació de derrotat 2024-11-19 18:59:22 +01:00
121774e460 Nova animació de jugador derrotat 2024-11-19 18:33:52 +01:00
47e468034f Nova animació per a la mort del personatge
Nova lògica al morir
2024-11-17 08:43:24 +01:00
da74b8dfce La powerball ja no mata
La powerball no pillava la rotació si es creava amb el rellotge actiu
2024-11-16 12:45:58 +01:00
065336c310 Els globos fills ja no ixen centrats al pare, si no al final havia varios apilats 2024-11-16 12:24:20 +01:00
79d25fb812 Nous grafics per a la powerball
Nou comportament per a la powerball
2024-11-16 12:13:00 +01:00
6262b5814d Arreglos varios relacionats amb el nom al obtenir la màxima puntuació:
No canviava al marcador, ni el nom del que tenia la maxima puntuació en calent ni al posar nom
retallat el nom de 8 a 6 caracters, i tots en majuscula pa que capia en el marcador
ja actualitza be la cadena amb el nom al posar nom per segona vegada en la mateixa partida
2024-11-08 20:49:07 +01:00
f9520185a2 Acabat BalloonManager 2024-11-08 18:29:08 +01:00
2fb7e88e4b Continue amb BalloonManager 2024-11-07 20:56:56 +01:00
0e527ff9d9 Au, a dormir que tinc son 2024-11-06 22:22:35 +01:00
d902bb9088 canvi de pc 2024-11-06 17:22:16 +01:00
caf04e3a7e Treballant en BalloonManager 2024-11-05 22:06:15 +01:00
12213a3dab Toooooornem a commitaaaar, aci vinga jugar al ping pong entre windows i macos i el puto copilot. Apanye aci i trenque allà 2024-11-05 17:54:23 +01:00
1f2a8ae38d Canvis en CMakeLists.txt 2024-11-05 17:38:26 +01:00
aa8d3502e2 Actualitzat make i cmake 2024-11-05 16:51:41 +01:00
e445a0b218 CMakeLists.txt crea el executable en la arrel del projecte 2024-11-05 13:13:43 +01:00
3f9c4b887f Apareixia brossa en la textura al crear un text i no netejarla primer (en el windows de la faena) 2024-11-05 13:06:32 +01:00
27ccae6132 Refet CMakeLists.txt 2024-11-05 13:05:52 +01:00
443f0f3254 Añadido CMakeLists.txt 2024-11-05 07:15:54 +01:00
2e62214a4b Canviat un #include <bits/chrono.h> per #include <chrono> 2024-11-04 22:26:31 +01:00
7b1c2a6005 Nova font de text per al text gran amb el doble de definició 2024-11-04 20:28:19 +01:00
2256ee46eb Modificada la paleta verda del primer jugador per a fer la mes pareguda a la del coffee crisis original 2024-11-04 19:39:27 +01:00
087fd3377c fix: els globos verds, al popparlos, uno tirava cap avall el molt cabró 2024-11-04 19:16:44 +01:00
30735f00e8 Els objectes de Text es precarreguen al inici 2024-11-04 19:08:18 +01:00
e0e82ee273 Retocs en Texture::loadPaletteFromFile 2024-11-03 20:43:52 +01:00
371c477d0d Varios arreglos 2024-11-03 20:28:01 +01:00
f29eb2f411 Les notificacions ara accepten un vector de cadenes en lloc de una o dos cadenes 2024-11-03 18:12:46 +01:00
69a92cba66 Apanyats alguns bugs que quedaven respecte a lo del teclat 2024-11-03 17:25:31 +01:00
86cd7b0f16 Ja es pot gastar el teclat com a control independent del primer mando
Ja pot jugar un jugador amb teclat i altre amb mando
Es pot asignar el teclat a qualsevol dels dos jugadors
Continua podentse gastar mando i teclat a l'hora per al mateix jugador
2024-11-03 11:07:58 +01:00
a1ccb6102a Abans de clavar-li ma a Input 2024-11-01 20:01:17 +01:00
2dd8bbbbf7 Moguts els checkInputs de Screen a GlobalInputs 2024-11-01 19:07:19 +01:00
c66cc965f1 define_buttons ja acaba be de definir els buttons 2024-11-01 18:39:10 +01:00
0757f63b73 Eliminat checkModInput 2024-11-01 18:20:18 +01:00
80a110e1d7 Abans de llevar checkInputMod 2024-11-01 16:48:03 +01:00
cd68c5ffea Al redefinir botons, ja no pots repetir botó. Util per als qui tenim la ma tremolosa i apretem dos voltes sense voler 2024-11-01 14:32:27 +01:00
f786cb7776 Implementat el final del joc 2024-11-01 13:05:11 +01:00
2e0d27a95c Modificats parámetres 2024-11-01 12:56:09 +01:00
861a9411d3 Nous textos 2024-11-01 12:55:37 +01:00
da27fde366 Millores en la gestió del "mute" en el joc 2024-11-01 07:55:37 +01:00
c6e2368e82 Noves animacions per a deixar de disparar 2024-10-31 23:32:11 +01:00
30dfa4c545 Treballant en el final del joc 2024-10-31 11:58:01 +01:00
7e2691e33e Finalitzat el Attract Mode 2024-10-30 21:29:23 +01:00
7e918e99f7 Arreglat un include 2024-10-30 13:15:30 +01:00
2aa3f827cb Arreglada la animació de morir, que s'updatava dos voltes per frame 2024-10-30 10:15:53 +01:00
06899d95a8 Arreglat el efecte de flash. Estava passant-li un valor massa xicotet 2024-10-30 09:45:57 +01:00
20c51d0796 Acabat el nou motor per a textos en pantalla 2024-10-30 09:25:28 +01:00
b43782786a Modificades les linux_utils 2024-10-30 09:25:12 +01:00
15554c449f Nuevos textos para el game_text 2024-10-30 08:19:32 +01:00
ba05eab79e Reduida la dependencia de PathSprite a Sprite
Treballant en els missatges de text que ixen durant la partida
2024-10-29 20:05:05 +01:00
d83c05bad4 El game_text dels items ja son textures generades i precarregades 2024-10-29 16:04:14 +01:00
e2abf835f9 Afegida nova tipografia 04b_25
Eliminades tipografies que no s'utilitzaven
La classe Text ara pot tornar una textura amb el text
2024-10-29 15:22:19 +01:00
59e2865a4a El game_text ara gasta PathSprites en lloc d'SmartSprites
fix: la paleta dels jugadors no s'iniciava correctament
2024-10-28 22:09:28 +01:00
787cb6366f Pasaeta de include-what-you-use
Acabada de perfilar la classe PathSprite
Menjeades declaracions de utils.h als fitxers que toca
2024-10-28 20:45:24 +01:00
0fe371653a commit de me ane cap a casa 2024-10-28 13:51:26 +01:00
2cffe8dfc9 Merge branch 'main' of https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition 2024-10-27 22:28:47 +01:00
1dd96cfaff Completada la classe PathSprite 2024-10-27 22:28:44 +01:00
d054e188b6 fix: alguns minibugs tontos 2024-10-27 19:04:05 +01:00
ca6ff71a46 Actualitzat README.MD 2024-10-27 18:46:42 +01:00
b90ac65cfc Eliminats warnings que nomes es veuen al compilar en macos/linux 2024-10-27 17:45:49 +01:00
759adbf6fd Actualitzat README.MD 2024-10-27 17:09:40 +01:00
71f76fda05 Redissenyat el time stopper 2024-10-27 13:36:00 +01:00
ddfb3672ea Afegida la funció createTwoBigBalloons() per a que la partida sempre comence igual 2024-10-26 18:16:23 +02:00
6235d0b684 Revisada la classe Balloon 2024-10-26 18:08:04 +02:00
f750997b34 Revisant la classe Balloon 2024-10-26 14:13:08 +02:00
de2a29b669 Ajustado el game_text para que se dibuje siempre en pantalla, sin clipping 2024-10-26 12:23:04 +02:00
f99f908c11 Revisant la classe Balloon 2024-10-26 11:38:08 +02:00
d44bfd51de Balloon: inicialitzades variables en la declaració 2024-10-26 09:09:19 +02:00
4f095ab018 Repasada la classe Bullet 2024-10-26 09:01:32 +02:00
bffd2bdace . 2024-10-26 08:11:30 +02:00
24d09a2e3c Millorada la aparició dels game_text 2024-10-24 22:16:57 +02:00
caf191672e Posat ordre en el constructor de Game 2024-10-24 22:08:53 +02:00
43e7b83403 Continue arreglant cosetes amb cppcheck 2024-10-24 20:36:30 +02:00
a5c72a0f65 Collons, que m'havien stagejat no se que.. ara si, arreglada la carrega d'animacions 2024-10-24 19:58:45 +02:00
ca464b2e81 Arreglada la cárrega d'animacions 2024-10-24 19:58:25 +02:00
f26ecbd969 Canviat el final de linea als scripts de linux 2024-10-24 18:14:33 +02:00
018bb68f9a Canviat el nom de la carpeta a linux_utils 2024-10-24 17:59:50 +02:00
f36ff3d7fe Actualitzats scripts de linux_utils 2024-10-24 17:53:24 +02:00
8f33308f8d . 2024-10-24 14:03:12 +02:00
8c98430b68 . 2024-10-23 22:18:46 +02:00
6e2f80d8ce . 2024-10-23 18:29:52 +02:00
95478134dd Merdetes en la faena, básicament arreglar uns quants iniciadors de variables en les clases 2024-10-23 14:00:19 +02:00
528533fd9b Au, a casa 2024-10-22 13:56:50 +02:00
5df85e1b1a Pasaeta de cppcheck, ale 2024-10-22 09:24:19 +02:00
1d0c2e01a5 Varios arreglos d'estil en el codi i llevar metodes que ja no servien 2024-10-21 22:47:00 +02:00
236d6f58b6 Nous gràfics per al game_text 2024-10-21 19:29:54 +02:00
898b551e06 Paletes noves per al primer café dels jugadors 2024-10-21 18:09:34 +02:00
84238032e0 Afegits uns overrides pa agafar parametres per linea de comandos 2024-10-21 17:46:05 +02:00
2cb22ed013 fix: els globos tenien un parell de setters mal asignats per culpa de buscar y reemplazar
fix: els globos verds s'inicialitzaven amb vy = 0 per gastar abs en lloc de fabs
fix: corregit un bug milenari que de sempre havia creat els balloons verds al popar al pare amb la meitat de velocitat en y. Lo que jo no se es com anava res. Supose que ara el joc serà un poc mes xungo. Quan rebotaven en el piso ja se'ls posava la velocitat bona (crec)
2024-10-20 22:58:15 +02:00
a3a583deb7 Precàrrega dels fitxers amb dades per al mode demostració 2024-10-20 21:23:04 +02:00
b263e0c4be Modificada la estructura on es guarden els datos de la demo 2024-10-20 20:43:03 +02:00
3bf61fc758 fix: no guardar el fitxer de puntuacions en el modo demo 2024-10-20 19:40:09 +02:00
2377815c02 Amb les textures en memoria i compartides ja no puc fer el trick de canvi de paleta per a la flama del segon jugador tal i com està plantejat el codi. Arreglat creant una segona textura 2024-10-20 19:38:28 +02:00
7434869894 Corregit un fallo amagat baix un ifdef ARCADE. Ja he posat que estiga definit per defecte pa que no torne a passar 2024-10-20 15:43:10 +02:00
848d61b5c0 He fet un "manolete" i he pasat a c++ i smartpointers la cárrega de surfaces desde gif. Sembla que no ha petat res
Precárrega i asignació de paletes a les textures
Ara si algú toca una paleta, que siga conscient que la textura es compartida durant tot el joc
2024-10-20 15:36:04 +02:00
cbc9b3f071 Eliminats els últimes defines i passats a enum class 2024-10-20 12:07:55 +02:00
8bca5095da Modificats, estructurats i ben formatats alguns missatges de consola
Canvis en els codis d'eixida del programa
2024-10-20 11:37:26 +02:00
a4b4e188cd Precàrrega de tots els recursos al inici del joc
8.000.000 de cherrypickings que he anat fent pel codi
2024-10-20 11:06:10 +02:00
f23dcae5b6 Creada la classe Resource
Afegida la musica i els sons a Resource
2024-10-19 10:07:14 +02:00
b879673bc2 Mes merdes que faltaven del merge 2024-10-18 17:10:06 +02:00
a8701dbebc Merge branch 'main' of https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition 2024-10-18 16:53:53 +02:00
afe835914e Revisada la carrega de recursos en game.cpp 2024-10-18 14:07:25 +02:00
808f1595e9 Treballant en la càrrega de animacions desde fitxers 2024-10-17 21:02:28 +02:00
8e8346b2ab Li he demanat a la IA que revente Game::checkInput() que aixo si que era un monstruo amb sombreret i pajarita 2024-10-17 20:05:26 +02:00
1da8f33a5e Llevats tots els ifdef VERBOSE i redirigit cout a null_stream 2024-10-17 19:31:44 +02:00
50a376e582 Comença a estar tot mes o menos be el desaguisao de les classes Sprite. Encara algunes animacions sembla que van massa ràpides 2024-10-17 19:26:39 +02:00
59de566c5b commit de acabar la jornada laboral 2024-10-17 13:57:41 +02:00
db884cb422 Commit de vesprà tirada a la brossa 2024-10-16 22:35:19 +02:00
5585f996cb A vore si el helper ja funciona com toca 2024-10-16 13:29:16 +02:00
24556eeaa8 Implementat contador per a posar el nom al acabar la partida 2024-10-16 09:18:22 +02:00
dbffda491f Retocat l'aspecte visual de les notificacions 2024-10-15 22:56:24 +02:00
53f5f3f8b0 Ja comprova la notificació d'eixir per diferenciarla de la resta
En ARCADE la notificació diferencia si vas a eixir o a apagar el sistema
2024-10-15 20:40:45 +02:00
e0faa0890e Afegides noves cadenes de text 2024-10-15 20:12:16 +02:00
de6508c37c Don Melitonitzada la classe Notifier e independitzada de la classe Screen
Ara es poden afegir codis a les notificacions per identificarles
2024-10-15 20:09:09 +02:00
e99c2c5265 fix: faltava el nom de la classe en shutdownSystem() 2024-10-15 18:58:10 +02:00
942924c65c Afegit codi per apagar el sistema al eixir del joc 2024-10-15 18:24:19 +02:00
089da99b5b Afegida la funció getNewPosition a la classe Screen per a respectar la posició de la finestra al canviarla de tamany 2024-10-15 18:12:16 +02:00
3fdd60c9e2 Treballant en els game_texts 2024-10-15 14:02:37 +02:00
3b9885ab03 Commit de Boromir 2024-10-14 22:33:45 +02:00
39a8c992e1 Ja duplica la ultima lletra al posar el nom 2024-10-14 17:12:07 +02:00
147 changed files with 13092 additions and 12171 deletions

85
CMakeLists.txt Normal file
View File

@@ -0,0 +1,85 @@
# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(coffee_crisis_arcade_edition VERSION 0.01)
# 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()

View File

@@ -50,84 +50,7 @@ else
endif
endif
OBJECTS := $(subst $(DIR_SOURCES), $(DIR_BUILD), $(SOURCES))
OBJECTS := $(OBJECTS:.cpp=.o)
DEPENDENCIES:= $(OBJECTS:.o=.d)
###############################################################################
# #
# RULES #
# #
###############################################################################
.PHONY: all a1
all: a1
a1: $(TARGET_FILE)
$(TARGET_FILE): $(OBJECTS)
$(MKD) $(@D)
$(CXX) $(OBJECTS) $(LDFLAGS) -o $(TARGET_FILE)
$(DIR_BUILD)%.o: $(DIR_SOURCES)%.cpp
$(MKD) $(@D)
$(CXX) -c $< $(CXXFLAGS) $(INCLUDES) -o $@
-include $(DEPENDENCIES)
###############################################################################
# #
# CLEAN #
# #
###############################################################################
.PHONY: clean
clean:
$(RM) $(call FixPath,$(DIR_BUILD))
###############################################################################
# #
# PRINT-VARIABLES #
# #
###############################################################################
.PHONY: print-variables
print-variables:
@echo MAKEFILE_LIST: $(MAKEFILE_LIST)
@echo "DIR_ROOT :" $(DIR_ROOT)
@echo "DIR_SOURCES:" $(DIR_SOURCES)
@echo "DIR_BIN :" $(DIR_BIN)
@echo "DIR_BUILD :" $(DIR_BUILD)
@echo "DIR_IMGUI :" $(DIR_IMGUI)
@echo "DIR_IMGUI_SFML:" $(DIR_IMGUI_SFML)
@echo "INCLUDES :" $(INCLUDES)
@echo CXX: $(CXX)
@echo CXXFLAGS: $(CXXFLAGS)
@echo LDFLAGS: $(LDFLAGS)
@echo SOURCES: $(SOURCES)
@echo OBJECTS: $(OBJECTS)
@echo DEPENDENCIES: $(DEPENDENCIES)
@echo TARGET_NAME: $(TARGET_NAME)
@echo TARGET_FILE: $(TARGET_FILE)
@echo RM: $(RM)
raspi:
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(TARGET_FILE)
strip -s -R .comment -R .gnu.version $(TARGET_FILE) --strip-unneeded
raspi_debug:
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE -D DEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
# Rules
windows:
@echo off
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE).exe"
@@ -249,6 +172,13 @@ linux_release:
# Elimina la carpeta temporal
$(RM) "$(RELEASE_FOLDER)"
raspi:
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(TARGET_FILE)
strip -s -R .comment -R .gnu.version $(TARGET_FILE) --strip-unneeded
raspi_debug:
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE -D DEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
anbernic:
# Elimina carpetas previas
$(RM) "$(RELEASE_FOLDER)"_anbernic
@@ -259,6 +189,5 @@ anbernic:
# Copia ficheros
cp -R data "$(RELEASE_FOLDER)"_anbernic
# Complia
# Compila
$(CXX) $(SOURCES) -D ANBERNIC -D NO_SHADERS -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(RELEASE_FOLDER)_anbernic/$(TARGET_NAME)
$(CXX) $(SOURCES) -D ANBERNIC -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(RELEASE_FOLDER)_anbernic/$(TARGET_NAME).shaders

View File

@@ -1,67 +1,43 @@
# Coffee Crisis
# Coffee Crisis Arcade Edition
Coffee Crisis es un juego arcade que pondrá a prueba tus reflejos. Empezado durante el verano de 2020 y terminado un año despues, en el verano de 2021. Intenta conseguir todos los puntos que puedas con una sola vida a traves de los 10 niveles de juego y ayuda a Bal1 a defender la UPV de la invasión de la cafeína esférica y saltarina.
Coffee Crisis Arcade Edition es la versió ampliada i millorada del aclamat Coffee Crisis. Preparat per a jugar sense parar amn dos jugadors, nous gràfics i moltes sorpreses mes.
![alt text](https://php.sustancia.synology.me/images/cc1.png)
<p align="center">
<img src="https://php.sustancia.synology.me/images/ccae_title.png" alt="Titol"
</p>
## Teclado
El juego se maneja con teclado, aunque tambien se puede conectar un mando de control.
Las teclas son las siguientes:
## Controls
El joc està optimitzat per a ser jugat amb un mando de jocs, encara que un dels jugadors pot utilitzar el teclat.
Les tecles son les següents:
* **Cursores**: Mover al personaje, moverse por los menus
* **Q, W, E**: Disparar a la izquierda, al centro y a la derecha respectivamente
* **ESCAPE**: Pone en pausa el juego durante la partida. Sale de los menus. Cierra el juego
* **ENTER**: Acepta las opciones en los menus
* **Fletxes**: Mou al personatge
* **Q, W, E**: Disparar a la esquerra, al centre i a la dreta respectivament
![alt text](https://php.sustancia.synology.me/images/cc2.png)
<p align="center">
<img src="https://php.sustancia.synology.me/images/ccae1.png" alt="Joc"
</p>
## Compilar
## Altres tecles
- **Tecla ESC**: Tancar el joc
Para compilar el código se necesitan tener las librerías SDL instaladas en el sistema y el compilador g++.
- **Tecla F1**: Fa la finestra mes xicoteta
En Linux:
```bash
sudo apt install libsdl2-dev g++
```
- **Tecla F2**: Fa la finestra mes gran
En macOS se pueden instalar fácilmente con [brew](https://brew.sh):
```bash
brew install sdl2 g++
```
- **Tecla F3**: Alterna entre el mode de pantalla completa i el de finestra
Una vez instaladas las librerías SDL, se puede compilar utilizando el fichero Makefile suministrado.
- **Tecla F4**: Activa o desactiva els shaders
En Linux:
```bash
make linux
```
- **Tecla F5**: Activa o desactiva l'audio
En macOS:
```bash
make macos
```
![alt text](https://php.sustancia.synology.me/images/cc3.png)
- **Tecla F6**: Canvia el idioma del joc i reinicia
## Como ejecutar
- **Tecla F10**: Reset
Para ejecutar el juego hay que escribir en la terminal la orden que se muestra a continuación.
<p align="center">
<img src="https://php.sustancia.synology.me/images/ccae2.png" alt="Joc"
</p>
En Linux:
```bash
./coffee_crisis_linux
```
En macOS:
```bash
./coffee_crisis_macos
```
En macOS tambien puedes hacer doble click sobre el archivo coffee_crisis_macos
## Agradecimientos
A los jailers y a la jail. Y entre ellos, a JailDoctor por estar siempre ahí apoyándonos/obligándonos a sacar un Jailgame más.
Y por supuesto a ti por estar aquí.
## Licencia
Usa el código para lo que quieras: aprender, reirte, curiosear... excepto para sacar beneficio económico. Si lo consigues, por favor avísame y vamos a medias.
## Agraiments
A chatGPT i sobretot a Copilot. Gracies per estar sempre quan vos he necesitat.

View File

@@ -1,11 +1,12 @@
## GAME
game.item_size 20
game.width 320
game.height 240
game.play_area.rect.x 0
game.play_area.rect.y 0
game.play_area.rect.w 320
game.play_area.rect.h 200
game.item_size 20 # Tamaño de los items del juego
game.width 320 # Ancho de la resolucion nativa del juego
game.height 240 # Alto de la resolucion nativa del juego
game.play_area.rect.x 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego
game.play_area.rect.h 200 # Rectangulo con la posición de la zona de juego
game.enter_name_seconds 60 # Duración en segundos para introducir el nombre al finalizar la partida
## FADE
fade.num_squares_width 160

View File

@@ -1,11 +1,12 @@
## GAME
game.item_size 20
game.width 320
game.height 256
game.play_area.rect.x 0
game.play_area.rect.y 0
game.play_area.rect.w 320
game.play_area.rect.h 216
game.item_size 20 # Tamaño de los items del juego
game.width 320 # Ancho de la resolucion nativa del juego
game.height 256 # Alto de la resolucion nativa del juego
game.play_area.rect.x 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego
game.play_area.rect.h 216 # Rectangulo con la posición de la zona de juego
game.enter_name_seconds 60 # Duración en segundos para introducir el nombre al finalizar la partida
## FADE
fade.num_squares_width 160

BIN
data/font/04b_25.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,194 +1,194 @@
# box width
10
14
# box height
10
14
# 32 espacio ( )
5
8
# 33 !
4
5
# 34 "
5
# 35 #
7
8
# 35
10
# 36 $
7
10
# 37 %
8
9
# 38 &
8
11
# 39 '
3
5
# 40 (
5
7
# 41 )
5
7
# 42 *
7
# 43 +
7
9
# 44 ,
4
5
# 45 -
6
9
# 46 .
4
5
# 47 /
5
12
# 48 0
7
# 49 1
5
# 50 2
7
# 51 3
7
# 52 4
7
# 53 5
7
# 54 6
7
# 55 7
7
# 56 8
7
# 57 9
7
# 58 :
4
# 59 ;
4
# 60 <
6
# 61 =
6
# 62 >
6
# 63 ?
7
# 64 @
8
# 65 A
7
# 66 B
7
# 67 C
7
# 68 D
7
# 69 E
7
# 70 F
7
# 71 G
7
# 72 H
7
# 73 I
4
# 74 J
# 49 1
6
# 50 2
8
# 51 3
8
# 52 4
8
# 53 5
8
# 54 6
8
# 55 7
8
# 56 8
8
# 57 9
8
# 58 :
5
# 59 ;
5
# 60 <
8
# 61 =
8
# 62 >
8
# 63 ?
8
# 64 @
11
# 65 A
8
# 66 B
8
# 67 C
8
# 68 D
8
# 69 E
8
# 70 F
8
# 71 G
8
# 72 H
8
# 73 I
5
# 74 J
8
# 75 K
8
# 76 L
6
8
# 77 M
9
11
# 78 N
8
# 79 O
8
# 80 P
7
8
# 81 Q
8
# 82 R
7
# 83 S
6
# 84 T
8
# 83 S
8
# 84 T
9
# 85 U
7
8
# 86 V
8
# 87 W
9
11
# 88 X
8
# 89 Y
8
# 90 Z
7
# 91 [
4
# 92 \
5
# 93 ]
4
# 94 ^
5
# 95 _
8
# 91 [
7
# 92 \
11
# 93 ]
7
# 94 ^
6
# 95 _
7
# 96 `
4
6
# 97 a
7
8
# 98 b
7
8
# 99 c
6
8
# 100 d
7
8
# 101 e
7
8
# 102 f
5
8
# 103 g
7
8
# 104 h
7
8
# 105 i
4
5
# 106 j
5
8
# 107 k
7
8
# 108 l
4
8
# 109 m
10
11
# 110 n
7
8
# 111 o
7
8
# 112 p
7
8
# 113 q
7
8
# 114 r
6
8
# 115 s
6
8
# 116 t
5
# 117 u
7
# 118 v
7
# 119 w
9
# 117 u
8
# 118 v
8
# 119 w
11
# 120 x
7
8
# 121 y
7
8
# 122 z
7
# 123 { -> ñ
7
# 124 | -> ç
7
8
# 123 {
1
# 124 |
1
# 125 }
0
1
# 126 ~
0
1

BIN
data/font/04b_25_2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@@ -1,43 +1,43 @@
# box width
16
28
# box height
16
28
# 32 espacio ( )
16
# 33 !
16
10
# 34 "
16
# 35 #
16
# 35
20
# 36 $
16
20
# 37 %
16
18
# 38 &
16
22
# 39 '
16
10
# 40 (
16
14
# 41 )
16
14
# 42 *
16
14
# 43 +
16
18
# 44 ,
16
10
# 45 -
16
18
# 46 .
16
10
# 47 /
16
24
# 48 0
16
# 49 1
16
12
# 50 2
16
# 51 3
@@ -55,9 +55,9 @@
# 57 9
16
# 58 :
16
10
# 59 ;
16
10
# 60 <
16
# 61 =
@@ -67,7 +67,7 @@
# 63 ?
16
# 64 @
16
22
# 65 A
16
# 66 B
@@ -85,7 +85,7 @@
# 72 H
16
# 73 I
16
10
# 74 J
16
# 75 K
@@ -93,7 +93,7 @@
# 76 L
16
# 77 M
16
22
# 78 N
16
# 79 O
@@ -107,13 +107,13 @@
# 83 S
16
# 84 T
16
18
# 85 U
16
# 86 V
16
# 87 W
16
22
# 88 X
16
# 89 Y
@@ -121,17 +121,17 @@
# 90 Z
16
# 91 [
16
14
# 92 \
16
22
# 93 ]
16
14
# 94 ^
16
12
# 95 _
16
14
# 96 `
16
12
# 97 a
16
# 98 b
@@ -149,7 +149,7 @@
# 104 h
16
# 105 i
16
10
# 106 j
16
# 107 k
@@ -157,7 +157,7 @@
# 108 l
16
# 109 m
16
22
# 110 n
16
# 111 o
@@ -171,13 +171,13 @@
# 115 s
16
# 116 t
16
18
# 117 u
16
# 118 v
16
# 119 w
16
22
# 120 x
16
# 121 y
@@ -185,10 +185,10 @@
# 122 z
16
# 123 {
16
2
# 124 |
16
2
# 125 }
16
2
# 126 ~
16
2

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -1,194 +0,0 @@
# box width
20
# box height
20
# 32 espacio ( )
8
# 33 !
8
# 34 "
10
# 35 #
14
# 36 $
14
# 37 %
16
# 38 &
16
# 39 '
6
# 40 (
10
# 41 )
10
# 42 *
14
# 43 +
14
# 44 ,
8
# 45 -
12
# 46 .
8
# 47 /
10
# 48 0
14
# 49 1
10
# 50 2
14
# 51 6
14
# 52 8
14
# 53 10
14
# 54 12
14
# 55 14
14
# 56 16
14
# 57 18
14
# 58 :
8
# 59 ;
8
# 60 <
12
# 61 =
12
# 62 >
12
# 63 ?
14
# 64 @
16
# 65 A
14
# 66 B
14
# 67 C
14
# 68 D
14
# 69 E
14
# 70 F
14
# 71 G
14
# 72 H
14
# 73 I
8
# 74 J
12
# 75 K
16
# 76 L
12
# 77 M
18
# 78 N
16
# 79 O
16
# 80 P
14
# 81 Q
16
# 82 R
14
# 83 S
12
# 84 T
16
# 85 U
14
# 86 V
16
# 87 W
18
# 88 X
16
# 89 Y
16
# 90 Z
14
# 91 [
8
# 92 \
10
# 93 ]
8
# 94 ^
10
# 95 _
16
# 96 `
8
# 97 a
14
# 98 b
14
# 99 c
12
# 100 d
14
# 101 e
14
# 102 f
10
# 103 g
14
# 104 h
14
# 105 i
8
# 106 j
10
# 107 k
14
# 108 l
8
# 109 m
20
# 110 n
14
# 111 o
14
# 112 p
14
# 113 q
14
# 114 r
12
# 115 s
12
# 116 t
10
# 117 u
14
# 118 v
14
# 119 w
18
# 120 x
14
# 121 y
14
# 122 z
14
# 123 { -> ñ
14
# 124 | -> ç
14
# 125 }
0
# 126 ~
0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 84 B

After

Width:  |  Height:  |  Size: 84 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 935 B

View File

@@ -23,29 +23,71 @@ frames=8,9,10,11
[/animation]
[animation]
name=stand-sideshoot
name=walk-sideshoot-cooldown
speed=5
loop=0
frames=12,13,14,15
[/animation]
[animation]
name=walk-centershoot
name=stand-sideshoot
speed=5
loop=0
frames=16,17,18,19
[/animation]
[animation]
name=stand-centershoot
name=stand-sideshoot-cooldown
speed=5
loop=0
frames=15
[/animation]
[animation]
name=walk-centershoot
speed=5
loop=0
frames=20,21,22,23
[/animation]
[animation]
name=death
speed=15
name=walk-centershoot-cooldown
speed=5
loop=0
frames=24,25,26,27
[/animation]
[animation]
name=stand-centershoot
speed=5
loop=0
frames=28,29,30,31
[/animation]
[animation]
name=stand-centershoot-cooldown
speed=5
loop=0
frames=27
[/animation]
[animation]
name=dying
speed=10
loop=0
frames=32,33,34,35
[/animation]
[animation]
name=dead
speed=3
loop=0
frames=44,45,46,47,48,49,50
[/animation]
[animation]
name=celebration
speed=10
loop=-1
frames=36,36,36,36,36,36,37,38,39,40,40,40,40,40,40,39,39,39,40,40,40,39,39,39,38,37,36,36,36
[/animation]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 B

View File

@@ -158,19 +158,19 @@ Felicitats!!
2 JUGADORS
## 53 MARCADOR
jugador 1
Jugador 1
## 54 MARCADOR
jugador 2
Jugador 2
## 55 MARCADOR
mult
Multiplicador
## 56 MARCADOR
max. puntuacio
Max. puntuacio
## 57 MARCADOR
fase
Fase
## 58 - MENU DE OPCIONES
MODE DE VISUALITZACIO
@@ -206,7 +206,7 @@ NORMAL
DIFICIL
## 69 - MENU DE OPCIONES
TECLAT
Teclat
## 70 - MENU DE OPCIONES
MANDO
@@ -281,7 +281,7 @@ MODE FORA DE LINEA
TAULER DE PUNTS
## 94 - NOTIFICACIONES
Torna a polsar per eixir ...
Torna a polsar per eixir
## 95 - DEFINE BUTTONS
Disparar cap a l'esquerra
@@ -345,3 +345,30 @@ Per favor
## 115 - MARCADOR
espere
## 116 - NOTIFICACIONES
Torna a polsar per apagar el sistema
## 117 - GAME TEXT
SuperPoder!
## 118 - GAME TEXT
+1 Colp
## 119 - GAME TEXT
Temps!
## 120 - SCOREBOARD
Puntuacio
## 121 - CREDITS
PROGRAMAT I DISSENYAT PER
## 122 - CREDITS
GRAFICS DIBUIXATS PER
## 123 - CREDITS
MUSICA COMPOSADA PER
## 124 - CREDITS
EFECTES DE SO

View File

@@ -158,19 +158,19 @@ Congratulations!!
2 PLAYERS
## 53 - MARCADOR
player 1
Player 1
## 54 - MARCADOR
player 2
Player 2
## 55 - MARCADOR
mult
Multiplier
## 56 - MARCADOR
high score
High Score
## 57 - MARCADOR
stage
Stage
## 58 - MENU DE OPCIONES
DISPLAY MODE
@@ -206,7 +206,7 @@ NORMAL
HARD
## 69 - MENU DE OPCIONES
KEYBOARD
Keyboard
## 70 - MENU DE OPCIONES
GAME CONTROLLER
@@ -345,3 +345,30 @@ Please
## 115 - MARCADOR
wait
## 116 - NOTIFICACIONES
Press again to shutdown system
## 117 - GAME TEXT
PowerUp
## 118 - GAME TEXT
+1 Hit
## 119 - GAME TEXT
Stop!
## 120 - SCOREBOARD
Score
## 121 - CREDITS
PROGRAMMED AND DESIGNED BY
## 122 - CREDITS
PIXELART DRAWN BY
## 123 - CREDITS
MUSIC COMPOSED BY
## 124 - CREDITS
SOUND EFFECTS

View File

@@ -158,19 +158,19 @@ Felicidades!!
2 JUGADORES
## 53 - MARCADOR
jugador 1
Jugador 1
## 54 - MARCADOR
jugador 2
Jugador 2
## 55 - MARCADOR
mult
Multiplicador
## 56 - MARCADOR
max. puntuacion
Max. puntuacion
## 57 - MARCADOR
FASE
Fase
## 58 - MENU DE OPCIONES
MODO DE VISUALIZACION
@@ -206,7 +206,7 @@ NORMAL
DIFICIL
## 69 - MENU DE OPCIONES
TECLADO
Teclado
## 70 - MENU DE OPCIONES
MANDO
@@ -345,3 +345,30 @@ Por favor
## 115 - MARCADOR
espere
## 94 - NOTIFICACIONES
Pulsa otra vez para apagar el sistema
## 117 - GAME TEXT
Potenciador
## 118 - GAME TEXT
+1 Golpe
## 119 - GAME TEXT
Tiempo!
## 120 - SCOREBOARD
Puntuacion
## 121 - CREDITS
PROGRAMADO Y DISE{ADO POR
## 122 - CREDITS
GRAFICOS DIBUJADOS POR
## 123 - CREDITS
MUSICA COMPUESTA POR
## 124 - CREDITS
EFECTOS DE SONIDO

BIN
data/music/credits.ogg Normal file

Binary file not shown.

234
data/shaders/crtpi_240.glsl Normal file
View 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

View File

@@ -97,7 +97,6 @@ void main()
#if defined(CURVATURE)
screenScale = vec2(1.0, 1.0); //TextureSize / InputSize;
#endif
//filterWidth = (768.0 / 240.0) / 3.0;
filterWidth = (768.0 / 256.0) / 3.0;
TEX0 = vec2(gl_MultiTexCoord0.x, 1.0-gl_MultiTexCoord0.y)*1.0001;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

BIN
data/sound/logo.wav Normal file

Binary file not shown.

View File

@@ -1,3 +0,0 @@
#!/bin/bash
valgrind --suppressions=valgrind_exceptions --leak-check=full ~/coffee_crisis_arcade_edition/coffee_crisis_arcade_edition_debug > ~/coffee_crisis_arcade_edition/debug.txt 2>&1

View File

View File

@@ -0,0 +1,8 @@
#!/bin/bash
SOURCEPATH=../source/
for i in "$SOURCEPATH"/*.cpp
do
include-what-you-use -D DEBUG -D VERBOSE -std=c++20 -Wall "$i"
done

View File

@@ -5,6 +5,6 @@ SOURCEPATH=../source/
for i in "$SOURCEPATH"/*.cpp
do
include-what-you-use -D DEBUG -D VERBOSE -std=c++20 -Wall "$i"
read -p "Presiona cualquier tecla para continuar..."
read -r -p "Presiona cualquier tecla para continuar..."
clear
done

View File

@@ -0,0 +1,8 @@
*:/home/sergio/gitea/coffee_crisis_arcade_edition/source/stb*
*:/home/sergio/gitea/coffee_crisis_arcade_edition/source/gif.c
*:/home/sergio/gitea/coffee_crisis_arcade_edition/source/jail*
*:/usr/include/*
*:../source/stb*
*:../source/gif.c
*:../source/jail*
*:/usr/include/*

View File

View File

@@ -0,0 +1,53 @@
#!/bin/bash
# Función para mostrar el uso del script
mostrar_uso() {
echo "Uso: $0 [-o opción]"
echo "Opciones:"
echo " w Ejecutar cppcheck con warning, style, performance"
echo " a Ejecutar cppcheck con todas las opciones habilitadas"
echo " u Ejecutar cppcheck para unusedFunction"
}
# Inicializar las variables
opcion=""
# Procesar las opciones
while getopts "o:" opt; do
case $opt in
o)
opcion=$OPTARG
;;
*)
mostrar_uso
exit 1
;;
esac
done
# Ejecutar según la opción seleccionada
case $opcion in
w)
cppcheck --force --enable=warning,style,performance --std=c++20 \
--suppressions-list=./cppcheck_suppressions \
../source/ \
2>./cppcheck-result-warning-style-performance.txt
;;
a)
cppcheck --force --enable=all -I /usr/include --std=c++20 \
--suppress=missingIncludeSystem \
--suppressions-list=./cppcheck_suppressions \
../source/ \
2>./cppcheck-result-all.txt
;;
u)
cppcheck --enable=style --std=c++20 \
--suppressions-list=./cppcheck_suppressions \
../source/ \
2>./cppcheck-result-unusedFunction.txt
;;
*)
mostrar_uso
exit 1
;;
esac

View File

@@ -0,0 +1,6 @@
#!/bin/bash
valgrind --suppressions=valgrind_exceptions \
--leak-check=full \
~/coffee_crisis_arcade_edition/coffee_crisis_arcade_edition_debug \
> ~/coffee_crisis_arcade_edition/debug.txt 2>&1

View File

@@ -1,197 +1,55 @@
#include "animated_sprite.h"
#include <algorithm> // for copy
#include <fstream> // for basic_ostream, operator<<, basic_istream, basic...
#include <iostream> // for cout
#include <iterator> // for back_insert_iterator, back_inserter
#include <sstream> // for basic_stringstream
#include "texture.h" // for Texture
#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 la animación desde un fichero
AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string file_path)
// Carga las animaciones en un vector(Animations) desde un fichero
AnimationsFileBuffer loadAnimationsFromFile(const std::string &file_path)
{
// Inicializa variables
AnimatedFile af;
af.texture = texture;
auto frames_per_row = 0;
auto frame_width = 0;
auto frame_height = 0;
auto max_tiles = 0;
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
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;
// El fichero se puede abrir
if (file.good())
while (std::getline(file, line))
{
// Procesa el fichero linea a linea
#ifdef VERBOSE
std::cout << "Animation loaded: " << file_name << std::endl;
#endif
while (std::getline(file, line))
{
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
Animation buffer;
buffer.counter = 0;
buffer.current_frame = 0;
buffer.completed = false;
buffer.name.clear();
buffer.speed = 5;
buffer.loop = 0;
buffer.frames.clear();
do
{
std::getline(file, line);
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != static_cast<int>(line.npos))
{
if (line.substr(0, pos) == "name")
{
buffer.name = line.substr(pos + 1, line.length());
}
else if (line.substr(0, pos) == "speed")
{
buffer.speed = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "loop")
{
buffer.loop = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frames")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length()));
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 auto num_tile = std::stoi(tmp) > max_tiles ? 0 : std::stoi(tmp);
rect.x = (num_tile % frames_per_row) * frame_width;
rect.y = (num_tile / frames_per_row) * frame_height;
buffer.frames.push_back(rect);
}
}
else
{
#ifdef VERBOSE
std::cout << "Warning: file " << file_name.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
#endif
}
}
} while (line != "[/animation]");
// Añade la animación al vector de animaciones
af.animations.push_back(buffer);
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
else
{
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "frames_per_row")
{
frames_per_row = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_width")
{
frame_width = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_height")
{
frame_height = std::stoi(line.substr(pos + 1, line.length()));
}
else
{
#ifdef VERBOSE
std::cout << "Warning: file " << file_name.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
#endif
}
// Normaliza valores
if (frames_per_row == 0 && frame_width > 0)
{
frames_per_row = texture->getWidth() / frame_width;
}
if (max_tiles == 0 && frame_width > 0 && frame_height > 0)
{
const auto w = texture->getWidth() / frame_width;
const auto h = texture->getHeight() / frame_height;
max_tiles = w * h;
}
}
}
}
// Cierra el fichero
file.close();
}
// El fichero no se puede abrir
else
{
#ifdef VERBOSE
std::cout << "Warning: Unable to open " << file_name.c_str() << " file" << std::endl;
#endif
if (!line.empty())
buffer.push_back(line);
}
return af;
return buffer;
}
// Constructor
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file, std::vector<std::string> *buffer)
: MovingSprite(texture),
current_animation_(0)
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path)
: MovingSprite(texture)
{
// Carga las animaciones
if (!file.empty())
if (!file_path.empty())
{
AnimatedFile as = loadAnimationFromFile(texture, file);
// Copia los datos de las animaciones
std::copy(as.animations.begin(), as.animations.end(), std::back_inserter(animations_));
}
else if (buffer)
{
loadFromVector(buffer);
AnimationsFileBuffer v = loadAnimationsFromFile(file_path);
loadFromAnimationsFileBuffer(v);
}
}
// Constructor
AnimatedSprite::AnimatedSprite(const AnimatedFile *animation)
: MovingSprite(animation->texture),
current_animation_(0)
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer &animations)
: MovingSprite(texture)
{
// Copia los datos de las animaciones
std::copy(animation->animations.begin(), animation->animations.end(), std::back_inserter(animations_));
}
// Destructor
AnimatedSprite::~AnimatedSprite()
{
animations_.clear();
if (!animations.empty())
{
loadFromAnimationsFileBuffer(animations);
}
}
// Obtiene el indice de la animación a partir del nombre
@@ -207,9 +65,7 @@ int AnimatedSprite::getIndex(const std::string &name)
return index;
}
}
#ifdef VERBOSE
std::cout << "** Warning: could not find \"" << name.c_str() << "\" animation" << std::endl;
#endif
return -1;
}
@@ -250,235 +106,12 @@ void AnimatedSprite::animate()
}
}
// Obtiene el número de frames de la animación actual
int AnimatedSprite::getNumFrames()
{
return (int)animations_[current_animation_].frames.size();
}
// Establece el frame actual de la animación
void AnimatedSprite::setCurrentFrame(int num)
{
// Descarta valores fuera de rango
if (num >= (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
setSpriteClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
}
// Establece el valor del contador
void AnimatedSprite::setAnimationCounter(const std::string &name, int num)
{
animations_[getIndex(name)].counter = num;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(const std::string &name, int speed)
{
animations_[getIndex(name)].counter = speed;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(int index, int speed)
{
animations_[index].counter = speed;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(const std::string &name, int loop)
{
animations_[getIndex(name)].loop = loop;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(int index, int loop)
{
animations_[index].loop = loop;
}
// Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(const std::string &name, bool value)
{
animations_[getIndex(name)].completed = value;
}
// OLD - Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(int index, bool value)
{
animations_[index].completed = value;
}
// Comprueba si ha terminado la animación
bool AnimatedSprite::animationIsCompleted()
{
return animations_[current_animation_].completed;
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(const std::string &name, Uint8 index)
{
return animations_[getIndex(name)].frames[index];
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF)
{
return animations_[indexA].frames[indexF];
}
// Carga la animación desde un vector
bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
{
// Inicializa variables
auto frames_per_row = 0;
auto frame_width = 0;
auto frame_height = 0;
auto max_tiles = 0;
// Indicador de éxito en el proceso
auto success = true;
std::string line;
// Recorre todo el vector
auto index = 0;
while (index < (int)source->size())
{
// Lee desde el vector
line = source->at(index);
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
Animation buffer;
buffer.counter = 0;
buffer.current_frame = 0;
buffer.completed = false;
buffer.name.clear();
buffer.speed = 5;
buffer.loop = 0;
buffer.frames.clear();
do
{
// Aumenta el indice para leer la siguiente linea
index++;
line = source->at(index);
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != static_cast<int>(line.npos))
{
if (line.substr(0, pos) == "name")
{
buffer.name = line.substr(pos + 1, line.length());
}
else if (line.substr(0, pos) == "speed")
{
buffer.speed = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "loop")
{
buffer.loop = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frames")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length()));
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) > max_tiles ? 0 : std::stoi(tmp);
rect.x = (num_tile % frames_per_row) * frame_width;
rect.y = (num_tile / frames_per_row) * frame_height;
buffer.frames.push_back(rect);
}
}
else
{
#ifdef VERBOSE
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
#endif
success = false;
}
}
} while (line != "[/animation]");
// Añade la animación al vector de animaciones
animations_.push_back(buffer);
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
else
{
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "frames_per_row")
{
frames_per_row = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_width")
{
frame_width = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_height")
{
frame_height = std::stoi(line.substr(pos + 1, line.length()));
}
else
{
#ifdef VERBOSE
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
#endif
success = false;
}
// Normaliza valores
if (frames_per_row == 0 && frame_width > 0)
{
frames_per_row = texture_->getWidth() / frame_width;
}
if (max_tiles == 0 && frame_width > 0 && frame_height > 0)
{
const int w = texture_->getWidth() / frame_width;
const int h = texture_->getHeight() / frame_height;
max_tiles = w * h;
}
}
}
// Una vez procesada la linea, aumenta el indice para pasar a la siguiente
index++;
}
// Pone un valor por defecto
setPos((SDL_Rect){0, 0, frame_width, frame_height});
return success;
}
// Establece la animacion actual
void AnimatedSprite::setCurrentAnimation(const std::string &name)
{
@@ -512,21 +145,6 @@ void AnimatedSprite::update()
MovingSprite::update();
}
// Establece el rectangulo para un frame de una animación
void AnimatedSprite::setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h)
{
animations_[index_animation].frames.push_back({x, y, w, h});
}
// OLD - Establece el contador para todas las animaciones
void AnimatedSprite::setAnimationCounter(int value)
{
for (auto &a : animations_)
{
a.counter = value;
}
}
// Reinicia la animación
void AnimatedSprite::resetAnimation()
{
@@ -534,3 +152,99 @@ void AnimatedSprite::resetAnimation()
animations_[current_animation_].counter = 0;
animations_[current_animation_].completed = false;
}
// Carga la animación desde un vector de cadenas
void AnimatedSprite::loadFromAnimationsFileBuffer(const AnimationsFileBuffer &source)
{
int frame_width = 1;
int frame_height = 1;
int frames_per_row = 1;
int max_tiles = 1;
size_t index = 0;
while (index < source.size())
{
std::string line = source.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]")
{
Animation animation;
do
{
index++;
line = source.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);
}

View File

@@ -1,12 +1,11 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint8
#include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "moving_sprite.h" // for MovingSprite
class Texture;
#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 Animation
{
@@ -17,82 +16,51 @@ struct Animation
bool completed; // Indica si ha finalizado la animación
int current_frame; // Frame actual
int counter; // Contador para las animaciones
Animation() : name(std::string()), speed(5), loop(0), completed(false), current_frame(0), counter(0) {}
};
struct AnimatedFile
{
std::vector<Animation> animations; // Vector con las diferentes animaciones
std::shared_ptr<Texture> texture; // Textura con los graficos para el sprite
};
using AnimationsFileBuffer = std::vector<std::string>;
// Carga la animación desde un fichero
AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string filePath);
// Carga las animaciones en un vector(Animations) desde un fichero
AnimationsFileBuffer loadAnimationsFromFile(const std::string &file_path);
class AnimatedSprite : public MovingSprite
{
protected:
// Variables
std::vector<Animation> animations_; // Vector con las diferentes animaciones
int current_animation_; // Animacion activa
public:
// Constructor
explicit AnimatedSprite(std::shared_ptr<Texture> texture = nullptr, const std::string &file = std::string(), std::vector<std::string> *buffer = nullptr);
explicit AnimatedSprite(const AnimatedFile *animation);
// Destructor
virtual ~AnimatedSprite();
int current_animation_ = 0; // Animacion activa
// Calcula el frame correspondiente a la animación actual
void animate();
// Obtiene el número de frames de la animación actual
int getNumFrames();
// Carga la animación desde un vector de cadenas
void loadFromAnimationsFileBuffer(const AnimationsFileBuffer &source);
// Establece el frame actual de la animación
void setCurrentFrame(int num);
public:
// Constructor
AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path);
AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer &animations);
explicit AnimatedSprite(std::shared_ptr<Texture> texture)
: MovingSprite(texture) {}
// Establece el valor del contador
void setAnimationCounter(const std::string &name, int num);
// Destructor
virtual ~AnimatedSprite() = default;
// Establece la velocidad de una animación
void setAnimationSpeed(const std::string &name, int speed);
void setAnimationSpeed(int index, int speed);
// Establece el frame al que vuelve la animación al finalizar
void setAnimationLoop(const std::string &name, int loop);
void setAnimationLoop(int index, int loop);
// Establece el valor de la variable
void setAnimationCompleted(const std::string &name, bool value);
void setAnimationCompleted(int index, bool value);
// Actualiza las variables del objeto
void update() override;
// Comprueba si ha terminado la animación
bool animationIsCompleted();
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect getAnimationClip(const std::string &name = "default", Uint8 index = 0);
SDL_Rect getAnimationClip(int indexA = 0, Uint8 indexF = 0);
// Obtiene el indice de la animación a partir del nombre
int getIndex(const std::string &name);
// Carga la animación desde un vector
bool loadFromVector(std::vector<std::string> *source);
// Establece la animacion actual
void setCurrentAnimation(const std::string &name = "default");
void setCurrentAnimation(int index = 0);
// Actualiza las variables del objeto
void update() override;
// OLD - Establece el rectangulo para un frame de una animación
void setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h);
// OLD - Establece el contador para todas las animaciones
void setAnimationCounter(int value);
// Reinicia la animación
void resetAnimation();
};

View File

@@ -1,8 +1,9 @@
#include "asset.h"
#include <SDL2/SDL_rwops.h> // for SDL_RWFromFile, SDL_RWclose, SDL_RWops
#include <SDL2/SDL_stdinc.h> // for SDL_max
#include <stddef.h> // for size_t
#include <iostream> // for basic_ostream, operator<<, cout, endl
#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;
@@ -25,44 +26,31 @@ Asset *Asset::get()
return Asset::asset_;
}
// Constructor
Asset::Asset(const std::string &executable_path)
: executable_path_(executable_path.substr(0, executable_path.find_last_of("\\/")))
{
longest_name_ = 0;
}
// Añade un elemento a la lista
void Asset::add(const std::string &file, AssetType type, bool required, bool absolute)
{
AssetItem ai;
ai.file = absolute ? file : executable_path_ + file;
ai.type = type;
ai.required = required;
file_list_.push_back(ai);
const std::string file_name = file.substr(file.find_last_of("\\/") + 1);
longest_name_ = SDL_max(longest_name_, file_name.size());
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 el fichero de un elemento de la lista a partir de una cadena
// Devuelve la ruta completa a un fichero a partir de una cadena
std::string Asset::get(const std::string &text) const
{
for (const auto &f : file_list_)
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())
{
const size_t last_index = f.file.find_last_of("/") + 1;
const std::string file = f.file.substr(last_index, std::string::npos);
if (file == text)
{
return f.file;
}
return it->file;
}
else
{
std::cout << "Warning: file " << text << " not found" << std::endl;
return "";
}
#ifdef VERBOSE
std::cout << "Warning: file " << text.c_str() << " not found" << std::endl;
#endif
return "";
}
// Comprueba que existen todos los elementos
@@ -70,12 +58,10 @@ bool Asset::check() const
{
bool success = true;
#ifdef VERBOSE
std::cout << "\n** Checking files" << std::endl;
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;
#endif
// 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)
@@ -94,9 +80,7 @@ bool Asset::check() const
// Si hay ficheros de ese tipo, comprueba si existen
if (any)
{
#ifdef VERBOSE
std::cout << "\n>> " << getTypeName(static_cast<AssetType>(type)).c_str() << " FILES" << std::endl;
#endif
for (const auto &f : file_list_)
{
@@ -105,13 +89,13 @@ bool Asset::check() const
success &= checkFile(f.file);
}
}
if (success)
std::cout << " All files are OK." << std::endl;
}
}
// Resultado
#ifdef VERBOSE
std::cout << (success ? "\n** All files OK.\n" : "\n** A file is missing. Exiting.\n") << std::endl;
#endif
// Resultado
std::cout << (success ? "\n** CHECKING FILES COMPLETED.\n" : "\n** CHECKING FILES FAILED.\n") << std::endl;
return success;
}
@@ -119,26 +103,12 @@ bool Asset::check() const
// Comprueba que existe un fichero
bool Asset::checkFile(const std::string &path) const
{
auto success = false;
std::ifstream file(path);
bool success = file.good();
file.close();
// Comprueba si existe el fichero
auto file = SDL_RWFromFile(path.c_str(), "rb");
if (file)
{
success = true;
SDL_RWclose(file);
}
#ifdef VERBOSE
const std::string file_name = path.substr(path.find_last_of("\\/") + 1);
std::cout.setf(std::ios::left, std::ios::adjustfield);
std::cout << "Checking file: ";
std::cout.width(longest_name_ + 2);
std::cout.fill('.');
std::cout << file_name;
std::cout << (success ? " [OK]" : " [ERROR]") << std::endl;
#endif
if (!success)
printWithDots("Checking file : ", getFileName(path), "[ ERROR ]");
return success;
}

View File

@@ -1,7 +1,8 @@
#pragma once
#include <string> // for string, basic_string
#include <vector> // for vector
#include <string> // para string, basic_string
#include <vector> // para vector
#include "utils.h"
enum class AssetType : int
{
@@ -27,14 +28,17 @@ private:
// Estructura para definir un item
struct AssetItem
{
std::string file; // Ruta del fichero desde la raiz del directorio
enum AssetType type; // Indica el tipo de recurso
bool required; // Indica si es un fichero que debe de existir
// bool absolute; // Indica si la ruta que se ha proporcionado es una ruta absoluta
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_; // Contiene la longitud del nombre de fichero mas largo
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
@@ -45,7 +49,8 @@ private:
std::string getTypeName(AssetType type) const;
// Constructor
explicit Asset(const std::string &executable_path);
explicit Asset(const std::string &executable_path)
: executable_path_(getPath(executable_path)) {}
// Destructor
~Asset() = default;
@@ -63,7 +68,7 @@ public:
// Añade un elemento a la lista
void add(const std::string &file, AssetType type, bool required = true, bool absolute = false);
// Devuelve un elemento de la lista a partir de una cadena
// 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

View File

@@ -1,80 +1,92 @@
#include "background.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <algorithm> // for clamp, max
#include "asset.h" // for Asset
#include "moving_sprite.h" // for MovingSprite
#include "param.h" // for param
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <algorithm> // Para clamp, max
#include "moving_sprite.h" // Para MovingSprite
#include "param.h" // Para Param, ParamBackground, param
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "sprite.h" // Para Sprite
#include "texture.h" // Para Texture
// Constructor
Background::Background(SDL_Renderer *renderer)
: renderer_(renderer),
buildings_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_buildings.png"))),
top_clouds_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_clouds1.png"))),
bottom_clouds_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_clouds2.png"))),
grass_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_grass.png"))),
gradients_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_sky_colors.png")))
Background::Background()
: renderer_(Screen::get()->getRenderer()),
buildings_texture_(Resource::get()->getTexture("game_buildings.png")),
top_clouds_texture_(Resource::get()->getTexture("game_clouds1.png")),
bottom_clouds_texture_(Resource::get()->getTexture("game_clouds2.png")),
grass_texture_(Resource::get()->getTexture("game_grass.png")),
gradients_texture_(Resource::get()->getTexture("game_sky_colors.png")),
rect_({0, 0, gradients_texture_->getWidth() / 2, gradients_texture_->getHeight() / 2}),
src_rect_({0, 0, 320, 240}),
dst_rect_({0, 0, 320, 240}),
base_(rect_.h),
color_(Color(param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b)),
alpha_color_text_(param.background.attenuate_alpha),
alpha_color_text_temp_(param.background.attenuate_alpha)
{
// Inicializa variables
gradient_number_ = 0;
alpha_ = 0;
clouds_speed_ = 0;
transition_ = 0;
counter_ = 0;
rect_ = {0, 0, gradients_texture_->getWidth() / 2, gradients_texture_->getHeight() / 2};
src_rect_ = {0, 0, 320, 240};
dst_rect_ = {0, 0, 320, 240};
base_ = rect_.h;
color_ = {param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b};
alpha_color_text_ = alpha_color_text_temp_ = param.background.attenuate_alpha;
gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h};
gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h};
gradient_rect_[3] = {rect_.w, rect_.h, rect_.w, rect_.h};
const int top_clouds_texture_height = top_clouds_texture_->getHeight() / 4;
const int bottom_clouds_texture_height = bottom_clouds_texture_->getHeight() / 4;
for (int i = 0; i < 4; ++i)
{
top_clouds_rect_[i] = {0, i * top_clouds_texture_height, top_clouds_texture_->getWidth(), top_clouds_texture_height};
bottom_clouds_rect_[i] = {0, i * bottom_clouds_texture_height, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_height};
gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h};
gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h};
gradient_rect_[3] = {rect_.w, rect_.h, rect_.w, rect_.h};
const int top_clouds_texture_height = top_clouds_texture_->getHeight() / 4;
const int bottom_clouds_texture_height = bottom_clouds_texture_->getHeight() / 4;
for (int i = 0; i < 4; ++i)
{
top_clouds_rect_[i] = {0, i * top_clouds_texture_height, top_clouds_texture_->getWidth(), top_clouds_texture_height};
bottom_clouds_rect_[i] = {0, i * bottom_clouds_texture_height, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_height};
}
}
// Crea los sprites
const int top_clouds_y = base_ - 165;
const int bottom_clouds_y = base_ - 101;
constexpr float top_clouds_speed = 0.1f;
constexpr float bottom_clouds_speed = 0.05f;
top_clouds_sprite_a_ = std::make_unique<MovingSprite>(0, top_clouds_y, rect_.w, top_clouds_texture_->getHeight(), -top_clouds_speed, 0.0f, 0.0f, 0.0f, top_clouds_texture_);
top_clouds_sprite_b_ = std::make_unique<MovingSprite>(rect_.w, top_clouds_y, rect_.w, top_clouds_texture_->getHeight(), -top_clouds_speed, 0.0f, 0.0f, 0.0f, top_clouds_texture_);
{
const int top_clouds_y = base_ - 165;
const int bottom_clouds_y = base_ - 101;
bottom_clouds_sprite_a_ = std::make_unique<MovingSprite>(0, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight(), -bottom_clouds_speed, 0.0f, 0.0f, 0.0f, bottom_clouds_texture_);
bottom_clouds_sprite_b_ = std::make_unique<MovingSprite>(rect_.w, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight(), -bottom_clouds_speed, 0.0f, 0.0f, 0.0f, bottom_clouds_texture_);
top_clouds_sprite_a_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_Rect){0, top_clouds_y, rect_.w, top_clouds_texture_->getHeight()});
top_clouds_sprite_b_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_Rect){rect_.w, top_clouds_y, rect_.w, top_clouds_texture_->getHeight()});
buildings_sprite_ = std::make_unique<Sprite>(0, 0, buildings_texture_->getWidth(), buildings_texture_->getHeight(), buildings_texture_);
gradient_sprite_ = std::make_unique<Sprite>(0, 0, rect_.w, rect_.h, gradients_texture_);
grass_sprite_ = std::make_unique<Sprite>(0, 0, grass_texture_->getWidth(), grass_texture_->getHeight() / 2, grass_texture_);
bottom_clouds_sprite_a_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_Rect){0, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight()});
bottom_clouds_sprite_b_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_Rect){rect_.w, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight()});
buildings_sprite_ = std::make_unique<Sprite>(buildings_texture_, 0, 0, buildings_texture_->getWidth(), buildings_texture_->getHeight());
gradient_sprite_ = std::make_unique<Sprite>(gradients_texture_, 0, 0, rect_.w, rect_.h);
grass_sprite_ = std::make_unique<Sprite>(grass_texture_, 0, 0, grass_texture_->getWidth(), grass_texture_->getHeight() / 2);
}
// Inicializa objetos
top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
buildings_sprite_->setPosY(base_ - buildings_sprite_->getHeight());
grass_sprite_->setPosY(base_ - grass_sprite_->getHeight());
{
constexpr float top_clouds_speed = 0.1f;
constexpr float bottom_clouds_speed = 0.05f;
top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
top_clouds_sprite_a_->setVelX(-top_clouds_speed);
top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
top_clouds_sprite_b_->setVelX(-top_clouds_speed);
bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottom_clouds_sprite_a_->setVelX(-bottom_clouds_speed);
bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottom_clouds_sprite_b_->setVelX(-bottom_clouds_speed);
buildings_sprite_->setY(base_ - buildings_sprite_->getHeight());
grass_sprite_->setY(base_ - grass_sprite_->getHeight());
}
// Crea la textura para componer el fondo
canvas_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(canvas_, SDL_BLENDMODE_BLEND);
// Crea la textura para atenuar el fondo
color_texture_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
color_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND);
setColor(color_);
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_);
@@ -103,7 +115,7 @@ void Background::update()
alpha_ = std::max((255 - (int)(255 * transition_)), 0);
// Incrementa el contador
counter_++;
++counter_;
// Compone todos los elementos del fondo en la textura
fillCanvas();
@@ -235,18 +247,6 @@ void Background::setPos(SDL_Rect pos)
src_rect_.h = pos.h;
}
// Ajusta el valor de la variable
void Background::setSrcRect(SDL_Rect value)
{
src_rect_ = value;
}
// Ajusta el valor de la variable
void Background::setDstRect(SDL_Rect value)
{
dst_rect_ = value;
}
// Establece el color_ de atenuación
void Background::setColor(Color color)
{
@@ -297,10 +297,10 @@ void Background::updateClouds()
bottom_clouds_sprite_b_->setVelX(clouds_speed_ / 2);
// Mueve las nubes
top_clouds_sprite_a_->move();
top_clouds_sprite_b_->move();
bottom_clouds_sprite_a_->move();
bottom_clouds_sprite_b_->move();
top_clouds_sprite_a_->update();
top_clouds_sprite_b_->update();
bottom_clouds_sprite_a_->update();
bottom_clouds_sprite_b_->update();
// Calcula el offset de las nubes
if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth())

View File

@@ -1,9 +1,9 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <memory> // for unique_ptr, shared_ptr
#include "utils.h" // for Color
#include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture
#include <memory> // para unique_ptr, shared_ptr
#include "utils.h" // para Color
class MovingSprite;
class Sprite;
class Texture;
@@ -32,12 +32,6 @@ class Texture;
- setTransition(float value)
Porcentaje (entre 0.0f (textura actual) y 1.0f (textura siguiente)) para mostrar entre la textura de fondo actual y la siguiente
- setSrcRect(SDL_Rect value)
Rectangulo de la textura de fondo que se desea mostrar
- setDstRecr(SDL_Rect value)
Rectangulo de destino donde se mostrará el rectángulo antrior. Automaticamente modifica srcRect para coincidor en tamaño con el destino.
- setColor(Color color)
Establece el color de la textura de superposición
@@ -74,11 +68,11 @@ private:
SDL_Rect gradient_rect_[4]; // Vector con las coordenadas de los 4 degradados para el cielo
SDL_Rect top_clouds_rect_[4]; // Vector con las coordenadas de los 4 nubes de arriba
SDL_Rect bottom_clouds_rect_[4]; // Vector con las coordenadas de los 4 nubes de abajo
int gradient_number_; // Indica el número de degradado de fondo que se va a dibujar
int alpha_; // Transparencia entre los dos degradados
float clouds_speed_; // Velocidad a la que se desplazan las nubes
float transition_; // Nivel de transición del fondo 0..1
int counter_; // Contador interno
int gradient_number_ = 0; // Indica el número de degradado de fondo que se va a dibujar
int alpha_ = 0; // Transparencia entre los dos degradados
float clouds_speed_ = 0; // Velocidad a la que se desplazan las nubes
float transition_ = 0; // Nivel de transición del fondo 0..1
int counter_ = 0; // Contador interno
SDL_Rect rect_; // Tamaño del objeto fondo
SDL_Rect src_rect_; // Parte del objeto fondo que se va a dibujará en pantalla
SDL_Rect dst_rect_; // Posición donde dibujar la parte del objeto fondo que se dibujará en pantalla
@@ -107,7 +101,7 @@ private:
public:
// Constructor
explicit Background(SDL_Renderer *renderer);
Background();
// Destructor
~Background();
@@ -133,12 +127,6 @@ public:
// Ajusta el valor de la variable
void setTransition(float value);
// Ajusta el valor de la variable
void setSrcRect(SDL_Rect value);
// Ajusta el valor de la variable
void setDstRect(SDL_Rect value);
// Establece el color de atenuación
void setColor(Color color);

File diff suppressed because it is too large Load Diff

View File

@@ -1,42 +1,39 @@
#pragma once
#include <SDL2/SDL_stdinc.h> // for Uint8, Uint16, Uint32
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
#include <vector> // for vector
#include "animated_sprite.h" // for AnimatedSprite
#include "utils.h" // for Circle
class Texture;
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_stdinc.h> // Para Uint8, Uint16, Uint32
#include <memory> // Para shared_ptr, unique_ptr
#include <string> // Para string
#include <vector> // Para vector
#include "animated_sprite.h" // Para AnimatedSprite
#include "utils.h" // Para Circle
class Texture; // lines 9-9
// Cantidad de elementos del vector con los valores de la deformación del globo al rebotar
constexpr int MAX_BOUNCE = 10;
// Tipos de globo
constexpr int BALLOON_1 = 1;
constexpr int BALLOON_2 = 2;
constexpr int BALLOON_3 = 3;
constexpr int BALLOON_4 = 4;
constexpr int HEXAGON_1 = 5;
constexpr int HEXAGON_2 = 6;
constexpr int HEXAGON_3 = 7;
constexpr int HEXAGON_4 = 8;
constexpr int POWER_BALL = 9;
// Puntos de globo
constexpr int BALLOON_SCORE_1 = 50;
constexpr int BALLOON_SCORE_2 = 100;
constexpr int BALLOON_SCORE_3 = 200;
constexpr int BALLOON_SCORE_4 = 400;
constexpr int BALLOON_SCORE[] = {50, 100, 200, 400};
constexpr int BALLOON_POWER[] = {1, 3, 7, 15};
constexpr int BALLOON_MENACE[] = {1, 2, 4, 8};
constexpr int BALLOON_SIZE[] = {10, 16, 26, 48, 49};
// Tamaños de globo
constexpr int BALLOON_SIZE_1 = 1;
constexpr int BALLOON_SIZE_2 = 2;
constexpr int BALLOON_SIZE_3 = 3;
constexpr int BALLOON_SIZE_4 = 4;
enum class BalloonSize : Uint8
{
SIZE1 = 0,
SIZE2 = 1,
SIZE3 = 2,
SIZE4 = 3,
};
// Clases de globo
constexpr int BALLOON_CLASS = 0;
constexpr int HEXAGON_CLASS = 1;
enum class BalloonType : Uint8
{
BALLOON = 0,
FLOATER = 1,
POWERBALL = 2,
};
// Velocidad del globo
constexpr float BALLOON_VELX_POSITIVE = 0.7f;
@@ -47,21 +44,8 @@ constexpr int BALLOON_MOVING_ANIMATION = 0;
constexpr int BALLOON_POP_ANIMATION = 1;
constexpr int BALLOON_BORN_ANIMATION = 2;
// Cantidad posible de globos
constexpr int MAX_BALLOONS = 100;
// Velocidades a las que se mueven los globos
constexpr float BALLOON_SPEED_1 = 0.60f;
constexpr float BALLOON_SPEED_2 = 0.70f;
constexpr float BALLOON_SPEED_3 = 0.80f;
constexpr float BALLOON_SPEED_4 = 0.90f;
constexpr float BALLOON_SPEED_5 = 1.00f;
// Tamaño de los globos
constexpr int BALLOON_WIDTH_1 = 10;
constexpr int BALLOON_WIDTH_2 = 16;
constexpr int BALLOON_WIDTH_3 = 26;
constexpr int BALLOON_WIDTH_4 = 46;
constexpr float BALLOON_SPEED[] = {0.60f, 0.70f, 0.80f, 0.90f, 1.00f};
// PowerBall
constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10;
@@ -71,61 +55,79 @@ constexpr int POWERBALL_COUNTER = 8;
class Balloon
{
private:
// Estructura para las variables para el efecto de los rebotes
// Estructura para el efecto de los rebotes en los globos
struct Bouncing
{
bool enabled; // Si el efecto está activo
Uint8 counter; // Countador para el efecto
Uint8 speed; // Velocidad a la que transcurre el efecto
float zoomW; // Zoom aplicado a la anchura
float zoomH; // Zoom aplicado a la altura
float despX; // Desplazamiento de pixeles en el eje X antes de pintar el objeto con zoom
float despY; // Desplazamiento de pixeles en el eje Y antes de pintar el objeto con zoom
std::vector<float> w; // Vector con los valores de zoom para el ancho del globo
std::vector<float> h; // Vector con los valores de zoom para el alto del globo
};
bool enabled = false; // Si el efecto está activo
Uint8 counter = 0; // Contador para el efecto
Uint8 speed = 2; // Velocidad a la que transcurre el efecto
float zoomW = 1.0f; // Zoom aplicado a la anchura
float zoomH = 1.0f; // Zoom aplicado a la altura
float despX = 0.0f; // Desplazamiento de pixeles en el eje X antes de pintar el objeto con zoom
float despY = 0.0f; // Desplazamiento de pixeles en el eje Y antes de pintar el objeto con zoom
float w[MAX_BOUNCE] = {1.10f, 1.05f, 1.00f, 0.95f, 0.90f, 0.95f, 1.00f, 1.02f, 1.05f, 1.02f}; // Vector con los valores de zoom para el ancho del globo
float h[MAX_BOUNCE] = {0.90f, 0.95f, 1.00f, 1.05f, 1.10f, 1.05f, 1.00f, 0.98f, 0.95f, 0.98f}; // Vector con los valores de zoom para el alto del globo
// Constructor por defecto
Bouncing() = default;
// Método reset
void reset()
{
counter = 0;
zoomW = 1.0f;
zoomH = 1.0f;
despX = 0.0f;
despY = 0.0f;
}
} bouncing_;
// Objetos y punteros
std::unique_ptr<AnimatedSprite> sprite_; // Sprite del objeto globo
// Variables
float pos_x_; // Posición en el eje X
float pos_y_; // Posición en el eje Y
Uint8 width_; // Ancho
Uint8 height_; // Alto
float vel_x_; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
float vel_y_; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
float gravity_; // Aceleración en el eje Y. Modifica la velocidad
float default_vel_y_; // Velocidad inicial que tienen al rebotar contra el suelo
float max_vel_y_; // Máxima velocidad que puede alcanzar el objeto en el eje Y
bool being_created_; // Indica si el globo se está creando
bool blinking_; // Indica si el globo está intermitente
bool enabled_; // Indica si el globo esta activo
bool invulnerable_; // Indica si el globo es invulnerable
bool stopped_; // Indica si el globo está parado
bool visible_; // Indica si el globo es visible
Circle collider_; // Circulo de colisión del objeto
Uint16 creation_counter_; // Temporizador para controlar el estado "creandose"
Uint16 creation_counter_ini_; // Valor inicial para el temporizador para controlar el estado "creandose"
Uint16 score_; // Puntos que da el globo al ser destruido
Uint16 stopped_counter_; // Contador para controlar el estado "parado"
Uint8 kind_; // Tipo de globo
Uint8 menace_; // Cantidad de amenaza que genera el globo
Uint32 counter_; // Contador interno
float travel_y_; // Distancia que ha de recorrer el globo en el eje Y antes de que se le aplique la gravedad
float speed_; // Velocidad a la que se mueven los globos
Uint8 size_; // Tamaño del globo
Uint8 power_; // Cantidad de poder que alberga el globo
Bouncing bouncing_; // Contiene las variables para el efecto de rebote
float x_; // Posición en el eje X
float y_; // Posición en el eje Y
Uint8 w_; // Ancho
Uint8 h_; // Alto
float vx_; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
float vy_; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
float gravity_; // Aceleración en el eje Y. Modifica la velocidad
float default_vy_; // Velocidad inicial que tienen al rebotar contra el suelo
float max_vy_; // Máxima velocidad que puede alcanzar el objeto en el eje Y
bool being_created_; // Indica si el globo se está creando
bool enabled_ = true; // Indica si el globo esta activo
bool invulnerable_; // Indica si el globo es invulnerable
bool stopped_; // Indica si el globo está parado
bool use_reversed_colors_ = false; // Indica si se ha de usar el color secundario del globo como color principal
Circle collider_; // Circulo de colisión del objeto
Uint16 creation_counter_; // Temporizador para controlar el estado "creandose"
Uint16 creation_counter_ini_; // Valor inicial para el temporizador para controlar el estado "creandose"
Uint16 score_; // Puntos que da el globo al ser destruido
BalloonType type_; // Clase de globo
BalloonSize size_; // Tamaño del globo
Uint8 menace_; // Cantidad de amenaza que genera el globo
Uint32 counter_ = 0; // Contador interno
float travel_y_ = 1.0f; // Distancia que ha de recorrer el globo en el eje Y antes de que se le aplique la gravedad
float speed_; // Velocidad a la que se mueven los globos
Uint8 power_; // Cantidad de poder que alberga el globo
SDL_Rect play_area_; // Zona por donde se puede mover el globo
// Alinea el circulo de colisión con la posición del objeto globo
void updateColliders();
void shiftColliders();
// Alinea el sprite con la posición del objeto globo
void shiftSprite();
// Establece el nivel de zoom del sprite
void zoomSprite();
// Activa el efecto
void bounceStart();
void enableBounce();
// Detiene el efecto
void bounceStop();
void disableBounce();
// Aplica el efecto
void updateBounce();
@@ -134,20 +136,27 @@ private:
void updateState();
// Establece la animación correspondiente
void updateAnimation();
// Establece el valor de la variable
void setBeingCreated(bool value);
void setAnimation();
public:
// Constructor
Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr<Texture> texture, std::vector<std::string> *animation);
Balloon(
float x,
float y,
BalloonType type,
BalloonSize size,
float vel_x,
float speed,
Uint16 creation_timer,
SDL_Rect play_area,
std::shared_ptr<Texture> texture,
const std::vector<std::string> &animation);
// Destructor
~Balloon() = default;
// Centra el globo en la posición X
void allignTo(int x);
void alignTo(int x);
// Pinta el globo en la pantalla
void render();
@@ -164,87 +173,39 @@ public:
// Actualiza al globo a su posicion, animación y controla los contadores
void update();
// Comprueba si el globo está habilitado
bool isEnabled() const;
// Detiene el globo
void stop();
// Obtiene del valor de la variable
float getPosX() const;
// Pone el globo en movimiento
void start();
// Obtiene del valor de la variable
float getPosY() const;
// Pone el color alternativo en el globo
void useReverseColor();
// Obtiene del valor de la variable
float getVelY() const;
// Pone el color normal en el globo
void useNormalColor();
// Obtiene del valor de la variable
int getWidth() const;
// Getters
float getPosX() const { return x_; }
float getPosY() const { return y_; }
int getWidth() const { return w_; }
int getHeight() const { return h_; }
BalloonSize getSize() const { return size_; }
BalloonType getType() const { return type_; }
Uint16 getScore() const { return score_; }
Circle &getCollider() { return collider_; }
Uint8 getMenace() const { return isEnabled() ? menace_ : 0; }
Uint8 getPower() const { return power_; }
bool isStopped() const { return stopped_; }
bool isPowerBall() const { return type_ == BalloonType::POWERBALL; }
bool isInvulnerable() const { return invulnerable_; }
bool isBeingCreated() const { return being_created_; }
bool isEnabled() const { return enabled_; }
bool isUsingReversedColor() { return use_reversed_colors_; }
bool canBePopped() const { return !isBeingCreated(); }
// Obtiene del valor de la variable
int getHeight() const;
// Establece el valor de la variable
void setVelY(float vel_y);
// Establece el valor de la variable
void setSpeed(float speed);
// Obtiene del valor de la variable
int getKind() const;
// Obtiene del valor de la variable
Uint8 getSize() const;
// Obtiene la clase a la que pertenece el globo
Uint8 getClass() const;
// Establece el valor de la variable
void setStop(bool value);
// Obtiene del valor de la variable
bool isStopped() const;
// Establece el valor de la variable
void setBlink(bool value);
// Obtiene del valor de la variable
bool isBlinking() const;
// Establece el valor de la variable
void setVisible(bool value);
// Obtiene del valor de la variable
bool isVisible() const;
// Establece el valor de la variable
void setInvulnerable(bool value);
// Obtiene del valor de la variable
bool isInvulnerable() const;
// Obtiene del valor de la variable
bool isBeingCreated() const;
// Establece el valor de la variable
void setStoppedTimer(Uint16 time);
// Obtiene del valor de la variable
Uint16 getStoppedTimer() const;
// Obtiene del valor de la variable
Uint16 getScore() const;
// Obtiene el circulo de colisión
Circle &getCollider();
// Obtiene le valor de la variable
Uint8 getMenace() const;
// Obtiene le valor de la variable
Uint8 getPower() const;
// Indica si el globo se puede explotar
bool canBePopped() const;
// Indica si el globo se puede destruir
bool canBeDestroyed() const;
// Setters
void setVelY(float vel_y) { vy_ = vel_y; }
void setSpeed(float speed) { speed_ = speed; }
void setInvulnerable(bool value) { invulnerable_ = value; }
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,46 +1,50 @@
#pragma once
#include "balloon.h" // para BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE
#include <vector>
constexpr int NUMBER_OF_BALLOON_FORMATIONS = 100;
constexpr int MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION = 50;
constexpr int NUMBER_OF_SETS_PER_POOL = 10;
constexpr int NUMBER_OF_STAGES = 10;
// Estructuras
struct BalloonFormationParams
{
int x; // Posición en el eje X donde crear al enemigo
int y; // Posición en el eje Y donde crear al enemigo
float vel_x; // Velocidad inicial en el eje X
int kind; // Tipo de enemigo
int creation_counter; // Temporizador para la creación del enemigo
int x = 0; // Posición en el eje X donde crear el globo
int y = 0; // Posición en el eje Y donde crear el globo
float vel_x = 0.0f; // Velocidad inicial en el eje X
BalloonType type = BalloonType::BALLOON; // Tipo de globo
BalloonSize size = BalloonSize::SIZE1; // Tamaño de globo
int creation_counter = 0; // Temporizador para la creación del globo
// Constructor por defecto
BalloonFormationParams() = default;
// Constructor con parámetros
BalloonFormationParams(int x_val, int y_val, float vel_x_val, BalloonType type_val, BalloonSize size_val, int creation_counter_val)
: x(x_val), y(y_val), vel_x(vel_x_val), type(type_val), size(size_val), creation_counter(creation_counter_val) {}
};
struct BalloonFormationUnit // Contiene la información de una formación enemiga
struct BalloonFormationUnit
{
int number_of_balloons; // Cantidad de enemigos que forman la formación
BalloonFormationParams init[MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION]; // Vector con todas las inicializaciones de los enemigos de la formación
int number_of_balloons; // Cantidad de globos que forman la formación
std::vector<BalloonFormationParams> init; // Vector con todas las inicializaciones de los globos de la formación
// Constructor
BalloonFormationUnit(int num_balloons, const std::vector<BalloonFormationParams> &init_params)
: number_of_balloons(num_balloons), init(init_params) {}
// Default constructor
BalloonFormationUnit() : number_of_balloons(0), init() {}
};
struct BalloonFormationPool
{
BalloonFormationUnit *set[10]; // Conjunto de formaciones de globos
};
using BalloonFormationPool = std::vector<const BalloonFormationUnit *>;
struct Stage // Contiene todas las variables relacionadas con una fase
{
BalloonFormationPool *balloon_pool; // El conjunto de formaciones de globos de la fase
int power_to_complete; // Cantidad de poder que se necesita para completar la fase
int max_menace; // Umbral máximo de amenaza de la fase
int min_menace; // Umbral mínimo de amenaza de la fase
int number; // Número de fase
};
// Clase BalloonFormations, para gestionar las formaciones de globos
class BalloonFormations
{
private:
// Variables
Stage stage_[10]; // Variable con los datos de cada pantalla
BalloonFormationUnit balloon_formation_[NUMBER_OF_BALLOON_FORMATIONS]; // Vector con todas las formaciones enemigas
BalloonFormationPool balloon_formation_pool_[10]; // Variable con los diferentes conjuntos de formaciones enemigas
std::vector<BalloonFormationUnit> balloon_formation_; // Vector con todas las formaciones enemigas
std::vector<BalloonFormationPool> balloon_formation_pool_; // Variable con los diferentes conjuntos de formaciones enemigas
// Inicializa las formaciones enemigas
void initBalloonFormations();
@@ -48,16 +52,19 @@ private:
// Inicializa los conjuntos de formaciones
void initBalloonFormationPools();
// Inicializa las fases del juego
void initGameStages();
public:
// Constructor
BalloonFormations();
BalloonFormations()
{
initBalloonFormations();
initBalloonFormationPools();
}
// Destructor
~BalloonFormations() = default;
// Devuelve una fase
Stage getStage(int index) const;
// Getters
const BalloonFormationPool &getPool(int pool) { return balloon_formation_pool_.at(pool); }
const BalloonFormationUnit &getSet(int pool, int set) { return *balloon_formation_pool_.at(pool).at(set); }
const BalloonFormationUnit &getSet(int set) const { return balloon_formation_.at(set); }
};

374
source/balloon_manager.cpp Normal file
View File

@@ -0,0 +1,374 @@
#include "balloon_manager.h"
#include <stdlib.h> // Para rand
#include <algorithm> // Para remove_if
#include <numeric> // Para accumulate
#include "balloon.h" // Para Balloon, BALLOON_SCORE, BALLOON_VELX...
#include "balloon_formations.h" // Para BalloonFormationParams, BalloonForma...
#include "explosions.h" // Para Explosions
#include "jail_audio.h" // Para JA_PlaySound
#include "param.h" // Para Param, ParamGame, param
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "stage.h" // Para power
#include "texture.h" // Para Texture
#include "utils.h" // Para Zone, BLOCK, Color, flash_color
// Constructor
BalloonManager::BalloonManager()
: explosions_(std::make_unique<Explosions>()),
balloon_formations_(std::make_unique<BalloonFormations>()) { init(); }
// Inicializa
void BalloonManager::init()
{
// Texturas - Globos
balloon_textures_.emplace_back(Resource::get()->getTexture("balloon1.png"));
balloon_textures_.emplace_back(Resource::get()->getTexture("balloon2.png"));
balloon_textures_.emplace_back(Resource::get()->getTexture("balloon3.png"));
balloon_textures_.emplace_back(Resource::get()->getTexture("balloon4.png"));
balloon_textures_.emplace_back(Resource::get()->getTexture("powerball.png"));
// Animaciones -- Globos
balloon_animations_.emplace_back(Resource::get()->getAnimation("balloon1.ani"));
balloon_animations_.emplace_back(Resource::get()->getAnimation("balloon2.ani"));
balloon_animations_.emplace_back(Resource::get()->getAnimation("balloon3.ani"));
balloon_animations_.emplace_back(Resource::get()->getAnimation("balloon4.ani"));
balloon_animations_.emplace_back(Resource::get()->getAnimation("powerball.ani"));
// Texturas - Explosiones
explosions_textures_.emplace_back(Resource::get()->getTexture("explosion1.png"));
explosions_textures_.emplace_back(Resource::get()->getTexture("explosion2.png"));
explosions_textures_.emplace_back(Resource::get()->getTexture("explosion3.png"));
explosions_textures_.emplace_back(Resource::get()->getTexture("explosion4.png"));
// Animaciones -- Explosiones
explosions_animations_.emplace_back(Resource::get()->getAnimation("explosion1.ani"));
explosions_animations_.emplace_back(Resource::get()->getAnimation("explosion2.ani"));
explosions_animations_.emplace_back(Resource::get()->getAnimation("explosion3.ani"));
explosions_animations_.emplace_back(Resource::get()->getAnimation("explosion4.ani"));
// Añade texturas
explosions_->addTexture(1, explosions_textures_[0], explosions_animations_[0]);
explosions_->addTexture(2, explosions_textures_[1], explosions_animations_[1]);
explosions_->addTexture(3, explosions_textures_[2], explosions_animations_[2]);
explosions_->addTexture(4, explosions_textures_[3], explosions_animations_[3]);
}
// Actualiza
void BalloonManager::update()
{
for (auto balloon : balloons_)
{
balloon->update();
}
updateBalloonDeployCounter();
explosions_->update();
}
// Renderiza los objetos
void BalloonManager::render()
{
for (auto &balloon : balloons_)
{
balloon->render();
}
explosions_->render();
}
// Crea una formación de enemigos
void BalloonManager::deployBalloonFormation(int stage)
{
// Solo despliega una formación enemiga si ha pasado cierto tiempo desde la última
if (balloon_deploy_counter_ == 0)
{
// En este punto se decide entre crear una powerball o una formación enemiga
if ((rand() % 100 < 15) && (canPowerBallBeCreated()))
{
// Crea una powerball
createPowerBall();
// Da un poco de margen para que se creen mas enemigos
balloon_deploy_counter_ = 10;
}
else
{
// Decrementa el contador de despliegues enemigos de la PowerBall
power_ball_counter_ = (power_ball_counter_ > 0) ? (power_ball_counter_ - 1) : 0;
// Elige una formación enemiga la azar
auto formation = rand() % 10;
// Evita repetir la ultima formación enemiga desplegada
if (formation == last_balloon_deploy_)
{
++formation %= 10;
}
last_balloon_deploy_ = formation;
const auto set = balloon_formations_->getSet(stage, formation);
const auto numEnemies = set.number_of_balloons;
for (int i = 0; i < numEnemies; ++i)
{
auto p = set.init[i];
createBalloon(p.x, p.y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter);
}
balloon_deploy_counter_ = 300;
}
}
}
// Crea una formación de enemigos específica
void BalloonManager::deploySet(int set_number)
{
const auto set = balloon_formations_->getSet(set_number);
const auto numEnemies = set.number_of_balloons;
for (int i = 0; i < numEnemies; ++i)
{
auto p = set.init[i];
createBalloon(p.x, p.y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter);
}
}
// Crea una formación de enemigos específica
void BalloonManager::deploySet(int set_number, int y)
{
const auto set = balloon_formations_->getSet(set_number);
const auto numEnemies = set.number_of_balloons;
for (int i = 0; i < numEnemies; ++i)
{
auto p = set.init[i];
createBalloon(p.x, y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter);
}
}
// Vacia del vector de globos los globos que ya no sirven
void BalloonManager::freeBalloons()
{
auto it = std::remove_if(balloons_.begin(), balloons_.end(), [](const auto &balloon)
{ return !balloon->isEnabled(); });
balloons_.erase(it, balloons_.end());
}
// Actualiza la variable enemyDeployCounter
void BalloonManager::updateBalloonDeployCounter()
{
if (balloon_deploy_counter_ > 0)
{
--balloon_deploy_counter_;
}
}
// Indica si se puede crear una powerball
bool BalloonManager::canPowerBallBeCreated() { return (!power_ball_enabled_) && (calculateScreenPower() > POWERBALL_SCREENPOWER_MINIMUM) && (power_ball_counter_ == 0); }
// Calcula el poder actual de los globos en pantalla
int BalloonManager::calculateScreenPower()
{
return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon)
{ return sum + (balloon->isEnabled() ? balloon->getPower() : 0); });
}
// Crea un globo nuevo en el vector de globos
std::shared_ptr<Balloon> BalloonManager::createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int creation_timer)
{
const int index = static_cast<int>(size);
balloons_.emplace_back(std::make_shared<Balloon>(x, y, type, size, velx, speed, creation_timer, play_area_, balloon_textures_.at(index), balloon_animations_.at(index)));
return balloons_.back();
}
// Crea un globo a partir de otro globo
void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction)
{
const float vx = direction == "LEFT" ? BALLOON_VELX_NEGATIVE : BALLOON_VELX_POSITIVE;
const auto lower_size = static_cast<BalloonSize>(static_cast<int>(balloon->getSize()) - 1);
auto b = createBalloon(0, balloon->getPosY(), balloon->getType(), lower_size, vx, balloon_speed_, 0);
const int x = direction == "LEFT" ? balloon->getPosX() + (balloon->getWidth() / 3) : balloon->getPosX() + 2 * (balloon->getWidth() / 3);
b->alignTo(x);
b->setVelY(b->getType() == BalloonType::BALLOON ? -2.50f : BALLOON_VELX_NEGATIVE * 2.0f);
if (balloon->isStopped())
{
b->stop();
}
if (balloon->isUsingReversedColor())
{
b->useReverseColor();
}
}
// Crea una PowerBall
void BalloonManager::createPowerBall()
{
constexpr int values = 6;
constexpr int pos_y = -BALLOON_SIZE[4];
constexpr int creation_time = 0;
const auto left = param.game.play_area.rect.x;
const auto center = param.game.play_area.center_x - (BALLOON_SIZE[4] / 2);
const auto right = param.game.play_area.rect.w - BALLOON_SIZE[4];
const auto luck = rand() % values;
const int x[values] = {left, left, center, center, right, right};
const float vx[values] = {BALLOON_VELX_POSITIVE, BALLOON_VELX_POSITIVE, BALLOON_VELX_POSITIVE, BALLOON_VELX_NEGATIVE, BALLOON_VELX_NEGATIVE, BALLOON_VELX_NEGATIVE};
balloons_.emplace_back(std::make_unique<Balloon>(x[luck], pos_y, BalloonType::POWERBALL, BalloonSize::SIZE4, vx[luck], balloon_speed_, creation_time, play_area_, balloon_textures_[4], balloon_animations_[4]));
power_ball_enabled_ = true;
power_ball_counter_ = POWERBALL_COUNTER;
}
// Establece la velocidad de los globos
void BalloonManager::setBalloonSpeed(float speed)
{
balloon_speed_ = speed;
for (auto &balloon : balloons_)
{
balloon->setSpeed(speed);
}
}
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
int BalloonManager::popBalloon(std::shared_ptr<Balloon> balloon)
{
Stage::addPower(1);
int score = 0;
if (balloon->getType() == BalloonType::POWERBALL)
{
score = destroyAllBalloons();
power_ball_enabled_ = false;
balloon_deploy_counter_ = 20;
}
else
{
score = balloon->getScore();
if (balloon->getSize() != BalloonSize::SIZE1)
{
createChildBalloon(balloon, "LEFT");
createChildBalloon(balloon, "RIGHT");
}
// Agrega la explosión y elimina el globo
explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize()));
balloon->pop();
}
return score;
}
// Explosiona un globo. Lo destruye = no crea otros globos
int BalloonManager::destroyBalloon(std::shared_ptr<Balloon> &balloon)
{
int score = 0;
// Calcula la puntuación y el poder que generaria el globo en caso de romperlo a él y a sus hijos
switch (balloon->getSize())
{
case BalloonSize::SIZE4:
score = BALLOON_SCORE[3] + (2 * BALLOON_SCORE[2]) + (4 * BALLOON_SCORE[1]) + (8 * BALLOON_SCORE[0]);
break;
case BalloonSize::SIZE3:
score = BALLOON_SCORE[2] + (2 * BALLOON_SCORE[1]) + (4 * BALLOON_SCORE[0]);
break;
case BalloonSize::SIZE2:
score = BALLOON_SCORE[1] + (2 * BALLOON_SCORE[0]);
break;
case BalloonSize::SIZE1:
score = BALLOON_SCORE[0];
break;
default:
score = 0;
break;
}
// Aumenta el poder de la fase
Stage::addPower(balloon->getPower());
// Destruye el globo
explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize()));
balloon->pop();
return score;
}
// Destruye todos los globos
int BalloonManager::destroyAllBalloons()
{
int score = 0;
for (auto &balloon : balloons_)
{
score += destroyBalloon(balloon);
}
balloon_deploy_counter_ = 300;
JA_PlaySound(Resource::get()->getSound("powerball.wav"));
Screen::get()->flash(flash_color, 3);
Screen::get()->shake();
return score;
}
// Detiene todos los globos
void BalloonManager::stopAllBalloons()
{
for (auto &balloon : balloons_)
{
balloon->stop();
}
}
// Pone en marcha todos los globos
void BalloonManager::startAllBalloons()
{
for (auto &balloon : balloons_)
{
if (!balloon->isBeingCreated())
{
balloon->start();
}
}
}
// Cambia el color de todos los globos
void BalloonManager::reverseColorsToAllBalloons()
{
for (auto &balloon : balloons_)
{
if (balloon->isStopped())
{
balloon->useReverseColor();
}
}
}
// Cambia el color de todos los globos
void BalloonManager::normalColorsToAllBalloons()
{
for (auto &balloon : balloons_)
{
balloon->useNormalColor();
}
}
// Recarga las texturas
void BalloonManager::reLoad()
{
for (auto &texture : balloon_textures_)
{
texture->reLoad();
}
}
// Crea dos globos gordos
void BalloonManager::createTwoBigBalloons()
{
deploySet(1);
}
// Obtiene el nivel de ameza actual generado por los globos
int BalloonManager::getMenace()
{
return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon)
{ return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); });
}

122
source/balloon_manager.h Normal file
View File

@@ -0,0 +1,122 @@
#pragma once
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <memory> // Para shared_ptr, unique_ptr
#include <string> // Para string
#include <vector> // Para vector
#include "balloon.h" // Para BALLOON_SPEED, Balloon
#include "balloon_formations.h" // Para BalloonFormations
#include "explosions.h" // Para Explosions
#include "param.h" // Para Param, ParamGame, param
#include "utils.h" // Para Zone
class Texture; // lines 10-10
using Balloons = std::vector<std::shared_ptr<Balloon>>;
class BalloonManager
{
private:
Balloons balloons_; // Vector con los globos
std::unique_ptr<Explosions> explosions_; // Objeto para dibujar explosiones
std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para gestionar las oleadas enemigas
std::vector<std::shared_ptr<Texture>> balloon_textures_; // Vector con las texturas de los globos
std::vector<std::shared_ptr<Texture>> explosions_textures_; // Vector con las texturas de las explosiones
std::vector<std::vector<std::string>> balloon_animations_; // Vector con las animaciones de los globos
std::vector<std::vector<std::string>> explosions_animations_; // Vector con las animaciones de las explosiones
float balloon_speed_ = BALLOON_SPEED[0]; // Velocidad a la que se mueven los enemigos
float default_balloon_speed_ = BALLOON_SPEED[0]; // Velocidad base de los enemigos, sin incrementar
int balloon_deploy_counter_ = 0; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero
bool power_ball_enabled_ = false; // Indica si hay una powerball ya activa
int power_ball_counter_ = 0; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
int last_balloon_deploy_ = 0; // Guarda cual ha sido la última formación desplegada para no repetir;
SDL_Rect play_area_ = param.game.play_area.rect; // Zona por donde se moveran los globos
// Inicializa
void init();
public:
// Constructor
BalloonManager();
// Destructor
~BalloonManager() = default;
// Actualiza
void update();
// Renderiza los globos
void render();
// Vacia del vector de globos los globos que ya no sirven
void freeBalloons();
// Crea una formación de enemigos al azar
void deployBalloonFormation(int stage);
// Crea una formación de enemigos específica
void deploySet(int set);
void deploySet(int set, int y);
// Actualiza la variable enemyDeployCounter
void updateBalloonDeployCounter();
// Indica si se puede crear una powerball
bool canPowerBallBeCreated();
// Calcula el poder actual de los globos en pantalla
int calculateScreenPower();
// Crea un globo nuevo en el vector de globos
std::shared_ptr<Balloon> createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int creation_timer);
// Crea un globo a partir de otro globo
void createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction);
// Crea una PowerBall
void createPowerBall();
// Establece la velocidad de los globos
void setBalloonSpeed(float speed);
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
int popBalloon(std::shared_ptr<Balloon> balloon);
// Explosiona un globo. Lo destruye = no crea otros globos
int destroyBalloon(std::shared_ptr<Balloon> &balloon);
// Destruye todos los globos
int destroyAllBalloons();
// Detiene todos los globos
void stopAllBalloons();
// Pone en marcha todos los globos
void startAllBalloons();
// Cambia el color de todos los globos
void reverseColorsToAllBalloons();
// Cambia el color de todos los globos
void normalColorsToAllBalloons();
// Recarga las texturas
void reLoad();
// Crea dos globos gordos
void createTwoBigBalloons();
// Obtiene el nivel de ameza actual generado por los globos
int getMenace();
// Getters
float getBalloonSpeed() const { return balloon_speed_; }
Balloons &getBalloons() { return balloons_; }
// Setters
void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; }
void resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); }
void setPlayArea(SDL_Rect play_area) { play_area_ = play_area; }
};

View File

@@ -1,36 +1,27 @@
#include "bullet.h"
#include <memory> // for unique_ptr, make_unique, shared_ptr
#include "param.h" // for param
#include "sprite.h" // for Sprite
class Texture;
constexpr int BULLET_WIDTH = 12;
constexpr int BULLET_HEIGHT = 12;
constexpr int BULLET_VELY = -3;
constexpr int BULLET_VELX_LEFT = -2;
constexpr int BULLET_VELX_RIGHT = 2;
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <memory> // Para unique_ptr, make_unique, shared_ptr
#include "param.h" // Para Param, ParamGame, param
#include "sprite.h" // Para Sprite
class Texture; // lines 5-5
// Constructor
Bullet::Bullet(int x, int y, BulletType kind, bool powered_up, int owner, SDL_Rect *play_area, std::shared_ptr<Texture> texture)
: sprite_(std::make_unique<Sprite>(SDL_Rect{x, y, BULLET_WIDTH, BULLET_HEIGHT}, texture)),
Bullet::Bullet(int x, int y, BulletType bullet_type, bool powered_up, int owner, std::shared_ptr<Texture> texture)
: sprite_(std::make_unique<Sprite>(texture, SDL_Rect{x, y, BULLET_WIDTH_, BULLET_HEIGHT_})),
pos_x_(x),
pos_y_(y),
width_(BULLET_WIDTH),
height_(BULLET_HEIGHT),
vel_x_(0),
vel_y_(BULLET_VELY),
kind_(kind),
owner_(owner),
play_area_(play_area)
bullet_type_(bullet_type),
owner_(owner)
{
vel_x_ = (kind_ == BulletType::LEFT) ? BULLET_VELX_LEFT : (kind_ == BulletType::RIGHT) ? BULLET_VELX_RIGHT
: 0;
vel_x_ = (bullet_type_ == BulletType::LEFT) ? BULLET_VEL_X_LEFT_
: (bullet_type_ == BulletType::RIGHT) ? BULLET_VEL_X_RIGHT_
: 0;
auto sprite_offset = powered_up ? 3 : 0;
auto kind_index = static_cast<int>(kind);
sprite_->setSpriteClip((kind_index + sprite_offset) * width_, 0, sprite_->getWidth(), sprite_->getHeight());
int sprite_offset = powered_up ? 3 : 0;
int offset = (static_cast<int>(bullet_type) + sprite_offset) * BULLET_WIDTH_;
sprite_->setSpriteClip(offset, 0, BULLET_WIDTH_, BULLET_HEIGHT_);
collider_.r = width_ / 2;
collider_.r = BULLET_WIDTH_ / 2;
shiftColliders();
}
@@ -44,21 +35,20 @@ void Bullet::render()
BulletMoveStatus Bullet::move()
{
pos_x_ += vel_x_;
if (pos_x_ < param.game.play_area.rect.x - width_ || pos_x_ > play_area_->w)
if (pos_x_ < param.game.play_area.rect.x - BULLET_WIDTH_ || pos_x_ > param.game.play_area.rect.w)
{
disable();
return BulletMoveStatus::OUT;
}
pos_y_ += vel_y_;
if (pos_y_ < param.game.play_area.rect.y - height_)
pos_y_ += BULLET_VEL_Y_;
if (pos_y_ < param.game.play_area.rect.y - BULLET_HEIGHT_)
{
disable();
return BulletMoveStatus::OUT;
}
sprite_->setPosX(pos_x_);
sprite_->setPosY(pos_y_);
shiftSprite();
shiftColliders();
return BulletMoveStatus::OK;
@@ -66,42 +56,12 @@ BulletMoveStatus Bullet::move()
bool Bullet::isEnabled() const
{
return kind_ != BulletType::NONE;
return bullet_type_ != BulletType::NONE;
}
void Bullet::disable()
{
kind_ = BulletType::NONE;
}
int Bullet::getPosX() const
{
return pos_x_;
}
int Bullet::getPosY() const
{
return pos_y_;
}
void Bullet::setPosX(int x)
{
pos_x_ = x;
}
void Bullet::setPosY(int y)
{
pos_y_ = y;
}
int Bullet::getVelY() const
{
return vel_y_;
}
BulletType Bullet::getKind() const
{
return kind_;
bullet_type_ = BulletType::NONE;
}
int Bullet::getOwner() const
@@ -119,3 +79,9 @@ void Bullet::shiftColliders()
collider_.x = pos_x_ + collider_.r;
collider_.y = pos_y_ + collider_.r;
}
void Bullet::shiftSprite()
{
sprite_->setX(pos_x_);
sprite_->setY(pos_y_);
}

View File

@@ -1,14 +1,13 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint8
#include <memory> // for shared_ptr, unique_ptr
#include "sprite.h" // for Sprite
#include "utils.h" // for Circle
class Texture;
#include <SDL2/SDL_stdinc.h> // Para Uint8
#include <memory> // Para shared_ptr, unique_ptr
#include "sprite.h" // Para Sprite
#include "utils.h" // Para Circle
class Texture; // lines 8-8
// Enumeración para los diferentes tipos de balas
enum class BulletType
// Tipos de balas
enum class BulletType : Uint8
{
UP,
LEFT,
@@ -16,7 +15,7 @@ enum class BulletType
NONE
};
// Enumeración para los resultados del movimiento de la bala
// Resultado del movimiento de la bala
enum class BulletMoveStatus : Uint8
{
OK = 0,
@@ -27,26 +26,29 @@ enum class BulletMoveStatus : Uint8
class Bullet
{
private:
// Constantes
static constexpr int BULLET_WIDTH_ = 12;
static constexpr int BULLET_HEIGHT_ = 12;
static constexpr int BULLET_VEL_Y_ = -3;
static constexpr int BULLET_VEL_X_LEFT_ = -2;
static constexpr int BULLET_VEL_X_RIGHT_ = 2;
std::unique_ptr<Sprite> sprite_; // Sprite con los gráficos y métodos de pintado
int pos_x_; // Posición en el eje X
int pos_y_; // Posición en el eje Y
Uint8 width_; // Ancho del objeto
Uint8 height_; // Alto del objeto
int pos_x_; // Posición en el eje X
int pos_y_; // Posición en el eje Y
int vel_x_; // Velocidad en el eje X
int vel_y_; // Velocidad en el eje Y
BulletType kind_; // Tipo de objeto
int owner_; // Identificador del dueño del objeto
Circle collider_; // Círculo de colisión del objeto
SDL_Rect *play_area_; // Rectángulo con la zona de juego
BulletType bullet_type_; // Tipo de objeto
int owner_; // Identificador del dueño del objeto
Circle collider_; // Círculo de colisión del objeto
void shiftColliders(); // Alinea el círculo de colisión con el objeto
void shiftSprite(); // Alinea el sprite con el objeto
public:
// Constructor
Bullet(int x, int y, BulletType kind, bool powered_up, int owner, SDL_Rect *play_area, std::shared_ptr<Texture> texture);
Bullet(int x, int y, BulletType bullet_type, bool powered_up, int owner, std::shared_ptr<Texture> texture);
// Destructor
~Bullet() = default;
@@ -63,17 +65,7 @@ public:
// Deshabilita el objeto
void disable();
// Obtiene la posición
int getPosX() const;
int getPosY() const;
// Establece la posición
void setPosX(int x);
void setPosY(int y);
// Obtiene parámetros
int getVelY() const;
BulletType getKind() const;
int getOwner() const;
Circle &getCollider();
};

471
source/credits.cpp Normal file
View File

@@ -0,0 +1,471 @@
#include "credits.h"
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <algorithm>
#include <cstdlib>
#include <string> // Para basic_string, string
#include <vector> // Para vector
#include "balloon_manager.h" // Para BalloonManager
#include "global_inputs.h" // Para check
#include "input.h" // Para Input
#include "jail_audio.h" // Para JA_PlayMusic, JA_StopMusic
#include "param.h" // Para Param, ParamGame, param
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, name, Options, options
#include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
#include "utils.h" // Para Color, no_color, shdw_txt_color, Zone
#include "player.h"
#include "fade.h"
#include "lang.h"
// Textos
constexpr const char TEXT_COPYRIGHT[] = "@2020,2024 JailDesigner";
// Constructor
Credits::Credits()
: balloon_manager_(std::make_unique<BalloonManager>()),
text_texture_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::DIAGONAL)),
fade_in_(std::make_unique<Fade>()),
fade_out_(std::make_unique<Fade>())
{
if (!text_texture_)
{
throw std::runtime_error("Failed to create SDL texture for text.");
}
section::name = section::Name::CREDITS;
//top_black_rect_ = {play_area_.x, 0, play_area_.w, black_bars_size_};
//bottom_black_rect_ = {play_area_.x, param.game.game_area.rect.h - black_bars_size_, play_area_.w, black_bars_size_};
balloon_manager_->setPlayArea(play_area_);
fade_in_->setColor(fade_color.r, fade_color.g, fade_color.b);
fade_in_->setType(FadeType::FULLSCREEN);
fade_in_->setPost(50);
fade_in_->setMode(FadeMode::IN);
fade_in_->activate();
fade_out_->setColor(0, 0, 0);
fade_out_->setType(FadeType::FULLSCREEN);
fade_out_->setPost(400);
initPlayers();
SDL_SetTextureBlendMode(text_texture_, SDL_BLENDMODE_BLEND);
fillTextTexture();
steps_ = std::abs((top_black_rect_.h - param.game.game_area.center_y - 1) + ((left_black_rect_.w - param.game.game_area.center_x) / 4));
}
// Destructor
Credits::~Credits()
{
SDL_DestroyTexture(text_texture_);
resetVolume();
}
// Bucle principal
void Credits::run()
{
while (section::name == section::Name::CREDITS)
{
checkInput();
update();
checkEvents(); // Tiene que ir antes del render
render();
}
}
// Actualiza las variables
void Credits::update()
{
if (SDL_GetTicks() - ticks_ > ticks_speed_)
{
ticks_ = SDL_GetTicks();
tiled_bg_->update();
balloon_manager_->update();
updateTextureDstRects();
throwBalloons();
for (auto &player : players_)
{
player->update();
}
updateAllFades();
Screen::get()->update();
globalInputs::update();
++counter_;
}
}
// Dibuja Credits::en patalla
void Credits::render()
{
// Prepara para empezar a dibujar en la textura de juego
Screen::get()->start();
// Limpia la pantalla
Screen::get()->clean();
// Dibuja el fondo, los globos y los jugadores
tiled_bg_->render();
balloon_manager_->render();
for (auto const &player : players_)
{
player->render();
}
// Dibuja los titulos de credito
SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &credits_rect_src_, &credits_rect_dst_);
// Dibuja el mini_logo
SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_);
// Dibuja los rectangulos negros
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 255);
SDL_RenderFillRect(Screen::get()->getRenderer(), &top_black_rect_);
SDL_RenderFillRect(Screen::get()->getRenderer(), &bottom_black_rect_);
SDL_RenderFillRect(Screen::get()->getRenderer(), &left_black_rect_);
SDL_RenderFillRect(Screen::get()->getRenderer(), &right_black_rect_);
// Si el mini_logo está en su destino, lo dibuja encima de lo anterior
if (mini_logo_on_position_)
{
SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_);
}
// Dibuja el fade sobre el resto de elementos
fade_in_->render();
fade_out_->render();
// Vuelca el contenido del renderizador en pantalla
Screen::get()->blit();
}
// Comprueba el manejador de eventos
void Credits::checkEvents()
{
SDL_Event event;
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(&event))
{
// Evento de salida de la aplicación
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
}
}
// Comprueba las entradas
void Credits::checkInput()
{
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
if (Input::get()->checkAnyButtonPressed())
{
if (mini_logo_on_position_)
{
// Si el mini_logo ha llegado a su posición final, al pulsar cualquier tecla se activa el fundido
fading_ = true;
}
else
{
// Si todavía estan los creditos en marcha, se pasan solos a toda pastilla
want_to_pass_ = true;
ticks_speed_ = 1;
}
}
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check();
}
// Crea la textura con el texto
void Credits::fillTextTexture()
{
auto text = Resource::get()->getText("smb2");
SDL_SetRenderTarget(Screen::get()->getRenderer(), text_texture_);
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 0);
SDL_RenderClear(Screen::get()->getRenderer());
std::vector<std::string> texts = {
lang::getText(121),
lang::getText(122),
lang::getText(123),
lang::getText(124),
"JAILDESIGNER",
"JAILDOCTOR (INTRO)",
"ERIC MATYAS (SOUNDIMAGE.ORG)",
"WWW.THEMOTIONMONKEY.CO.UK",
"WWW.KENNEY.NL",
"JAILDOCTOR"};
const int space_post_title = 3 + text->getCharacterSize();
const int space_pre_title = text->getCharacterSize() * 4;
const int texts_height = 1 * text->getCharacterSize() + 7 * space_post_title + 3 * space_pre_title;
credits_rect_dst_.h = credits_rect_src_.h = texts_height;
int y = (param.game.height - texts_height) / 2;
y = 0;
text->setPalette(1);
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(0), 1, no_color, 1, shdw_txt_color);
text->setPalette(0);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(4), 1, no_color, 1, shdw_txt_color);
y += space_pre_title;
text->setPalette(1);
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(1), 1, no_color, 1, shdw_txt_color);
text->setPalette(0);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(4), 1, no_color, 1, shdw_txt_color);
y += space_pre_title;
text->setPalette(1);
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(2), 1, no_color, 1, shdw_txt_color);
text->setPalette(0);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(5), 1, no_color, 1, shdw_txt_color);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(6), 1, no_color, 1, shdw_txt_color);
y += space_pre_title;
text->setPalette(1);
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(3), 1, no_color, 1, shdw_txt_color);
text->setPalette(0);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(7), 1, no_color, 1, shdw_txt_color);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(8), 1, no_color, 1, shdw_txt_color);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(9), 1, no_color, 1, shdw_txt_color);
// Mini logo
y += space_pre_title;
mini_logo_rect_src_.y = y;
auto mini_logo_sprite = std::make_unique<Sprite>(Resource::get()->getTexture("logo_jailgames_mini.png"));
mini_logo_sprite->setPosition(1 + param.game.game_area.center_x - mini_logo_sprite->getWidth() / 2, 1 + y);
Resource::get()->getTexture("logo_jailgames_mini.png")->setColor(shdw_txt_color.r, shdw_txt_color.g, shdw_txt_color.b);
mini_logo_sprite->render();
mini_logo_sprite->setPosition(param.game.game_area.center_x - mini_logo_sprite->getWidth() / 2, y);
Resource::get()->getTexture("logo_jailgames_mini.png")->setColor(255, 255, 255);
mini_logo_sprite->render();
// Texto con el copyright
y += mini_logo_sprite->getHeight() + 3;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXT_COPYRIGHT, 1, no_color, 1, shdw_txt_color);
// Resetea el renderizador
SDL_SetRenderTarget(Screen::get()->getRenderer(), nullptr);
// Actualiza las variables
mini_logo_rect_dst_.h = mini_logo_rect_src_.h = mini_logo_sprite->getHeight() + 3 + text->getCharacterSize();
credits_rect_dst_.y = param.game.game_area.rect.h;
mini_logo_rect_dst_.y = credits_rect_dst_.y + credits_rect_dst_.h + 30;
mini_logo_final_pos_ = param.game.game_area.center_y - mini_logo_rect_src_.h / 2;
}
// Actualiza el destino de los rectangulos de las texturas
void Credits::updateTextureDstRects()
{
if (counter_ % 10 == 0)
{
// Comprueba la posición de la textura con los titulos de credito
if (credits_rect_dst_.y + credits_rect_dst_.h > play_area_.y)
{
--credits_rect_dst_.y;
}
// Comprueba la posición de la textura con el mini_logo
if (mini_logo_rect_dst_.y == mini_logo_final_pos_)
{
mini_logo_on_position_ = true;
// Si el jugador quiere pasar los titulos de credito, el fade se inicia solo
if (want_to_pass_)
{
fading_ = true;
}
// Se activa el contador para evitar que la sección sea infinita
if (counter_prevent_endless_ == 1000)
{
fading_ = true;
}
else
{
++counter_prevent_endless_;
}
}
else
{
--mini_logo_rect_dst_.y;
}
}
}
// Tira globos al escenario
void Credits::throwBalloons()
{
constexpr int speed = 200;
const std::vector<int> sets = {0, 63, 25, 67, 17, 75, 13, 50};
if (counter_ > ((sets.size() - 1) * speed) * 3)
{
return;
}
if (counter_ % speed == 0)
{
const int index = (counter_ / speed) % sets.size();
balloon_manager_->deploySet(sets.at(index), -60);
}
if (counter_ % (speed * 4) == 0 && counter_ > 0)
{
balloon_manager_->createPowerBall();
}
}
// Inicializa los jugadores
void Credits::initPlayers()
{
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures; // Vector con todas las texturas de los jugadores;
std::vector<std::vector<std::string>> player_animations; // Vector con las animaciones del jugador
// Texturas - Player1
{
std::vector<std::shared_ptr<Texture>> player_texture;
player_texture.emplace_back(Resource::get()->getTexture("player1.gif"));
player_texture.emplace_back(Resource::get()->getTexture("player1_power.png"));
player_textures.push_back(player_texture);
}
// Texturas - Player2
{
std::vector<std::shared_ptr<Texture>> player_texture;
player_texture.emplace_back(Resource::get()->getTexture("player2.gif"));
player_texture.emplace_back(Resource::get()->getTexture("player2_power.png"));
player_textures.push_back(player_texture);
}
// Animaciones -- Jugador
{
player_animations.emplace_back(Resource::get()->getAnimation("player.ani"));
player_animations.emplace_back(Resource::get()->getAnimation("player_power.ani"));
}
// Crea los dos jugadores
constexpr int player_width = 30;
const int y = play_area_.y + play_area_.h - player_width;
constexpr bool demo = false;
constexpr int away_distance = 700;
players_.emplace_back(std::make_unique<Player>(1, play_area_.x - away_distance - player_width, y, demo, play_area_, player_textures.at(0), player_animations));
players_.back()->setWalkingState(PlayerState::WALKING_RIGHT);
players_.back()->setPlayingState(PlayerState::CREDITS);
players_.back()->setInvulnerable(false);
players_.emplace_back(std::make_unique<Player>(2, play_area_.x + play_area_.w + away_distance, y, demo, play_area_, player_textures.at(1), player_animations));
players_.back()->setWalkingState(PlayerState::WALKING_LEFT);
players_.back()->setPlayingState(PlayerState::CREDITS);
players_.back()->setInvulnerable(false);
}
// Actualiza los rectangulos negros
void Credits::updateBlackRects()
{
static int current_step = steps_;
if (top_black_rect_.h != param.game.game_area.center_y - 1 && bottom_black_rect_.y != param.game.game_area.center_y + 1)
{
// Si los rectangulos superior e inferior no han llegado al centro
if (counter_ % 4 == 0)
{
// Incrementa la altura del rectangulo superior
top_black_rect_.h = std::min(top_black_rect_.h + 1, param.game.game_area.center_y - 1);
// Incrementa la altura y modifica la posición del rectangulo inferior
++bottom_black_rect_.h;
bottom_black_rect_.y = std::max(bottom_black_rect_.y - 1, param.game.game_area.center_y + 1);
--current_step;
setVolume(static_cast<int>(initial_volume_ * current_step / steps_));
}
}
else
{
// Si los rectangulos superior e inferior han llegado al centro
if (left_black_rect_.w != param.game.game_area.center_x && right_black_rect_.x != param.game.game_area.center_x)
{
// Si los rectangulos izquierdo y derecho no han llegado al centro
// Incrementa la anchura del rectangulo situado a la izquierda
left_black_rect_.w = std::min(left_black_rect_.w + 4, param.game.game_area.center_x);
// Incrementa la anchura y modifica la posición del rectangulo situado a la derecha
right_black_rect_.w += 4;
right_black_rect_.x = std::max(right_black_rect_.x - 4, param.game.game_area.center_x);
--current_step;
setVolume(static_cast<int>(initial_volume_ * current_step / steps_));
}
else
{
// Si los rectangulos izquierdo y derecho han llegado al centro
setVolume(0);
JA_StopMusic();
if (counter_pre_fade_ == 400)
{
fade_out_->activate();
}
else
{
++counter_pre_fade_;
}
}
}
}
// Actualiza el estado de fade
void Credits::updateAllFades()
{
if (fading_)
{
updateBlackRects();
}
fade_in_->update();
if (fade_in_->hasEnded())
{
if (JA_GetMusicState() == JA_MUSIC_INVALID || JA_GetMusicState() == JA_MUSIC_STOPPED)
{
JA_PlayMusic(Resource::get()->getMusic("credits.ogg"));
}
}
fade_out_->update();
if (fade_out_->hasEnded())
{
section::name = section::Name::LOGO;
}
}
// Establece el nivel de volumen
void Credits::setVolume(int amount)
{
options.audio.music.volume = std::clamp(amount, 0, 100);
JA_SetMusicVolume(to_JA_volume(options.audio.music.volume));
}
// Reestablece el nivel de volumen
void Credits::resetVolume()
{
options.audio.music.volume = initial_volume_;
JA_SetMusicVolume(to_JA_volume(options.audio.music.volume));
}

100
source/credits.h Normal file
View File

@@ -0,0 +1,100 @@
#pragma once
#include <SDL2/SDL_render.h> // Para SDL_Texture
#include <SDL2/SDL_stdinc.h> // Para Uint32
#include <memory> // Para unique_ptr
#include "param.h"
#include "options.h"
class BalloonManager;
class TiledBG;
class Player;
class Fade;
constexpr int PLAY_AREA_HEIGHT = 200;
class Credits
{
private:
// Objetos
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
SDL_Texture *text_texture_; // Textura con el texto
std::unique_ptr<TiledBG> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo
std::unique_ptr<Fade> fade_in_; // Objeto para realizar el fundido de entrada
std::unique_ptr<Fade> fade_out_; // Objeto para realizar el fundido de salida
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
// Variables
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticks_speed_ = 15; // Velocidad del bucle update
Uint32 counter_ = 0; // Contador para la lógica de la clase
Uint32 counter_pre_fade_ = 0; // Contador para activar el fundido final
Uint32 counter_prevent_endless_ = 0; // Contador para evitar que el juego se quede para siempre en los creditos
int black_bars_size_ = (param.game.game_area.rect.h - PLAY_AREA_HEIGHT) / 2; // Tamaño de las barras negras
int mini_logo_final_pos_ = 0; // Ubicación donde se detiene el minilogo
bool fading_ = false; // Indica si se está realizando el fade final
bool want_to_pass_ = false; // Indica si el jugador quiere saltarse los titulos de crédito
bool mini_logo_on_position_ = false; // Indica si el minilogo ya se ha quedado en su posición
int initial_volume_ = options.audio.music.volume; // Volumen actual al crear el objeto
int steps_ = 0; // Cantidad de pasos a dar para ir reduciendo el audio
// Rectangulos
SDL_Rect credits_rect_src_ = param.game.game_area.rect; // Rectangulo con el texto de los créditos (origen)
SDL_Rect credits_rect_dst_ = param.game.game_area.rect; // Rectangulo con el texto de los créditos (destino)
SDL_Rect mini_logo_rect_src_ = param.game.game_area.rect; // Rectangulo con el mini logo de JailGames y el texto de copyright (origen)
SDL_Rect mini_logo_rect_dst_ = param.game.game_area.rect; // Rectangulo con el mini logo de JailGames y el texto de copyright (destino)
SDL_Rect play_area_ = {
param.game.game_area.rect.x,
param.game.game_area.rect.y + black_bars_size_,
param.game.game_area.rect.w,
PLAY_AREA_HEIGHT}; // Area visible para los creditos
SDL_Rect top_black_rect_ = {play_area_.x, param.game.game_area.rect.y, play_area_.w, black_bars_size_}; // Rectangulo negro superior
SDL_Rect bottom_black_rect_ = {play_area_.x, param.game.game_area.rect.h - black_bars_size_, play_area_.w, black_bars_size_}; // Rectangulo negro inferior
SDL_Rect left_black_rect_ = {play_area_.x, param.game.game_area.center_y - 1, 0, 2}; // Rectangulo negro situado a la izquierda
SDL_Rect right_black_rect_ = {play_area_.x + play_area_.w, param.game.game_area.center_y - 1, 0, 2}; // Rectangulo negro situado a la derecha
// Actualiza las variables
void update();
// Dibuja en pantalla
void render();
// Comprueba el manejador de eventos
void checkEvents();
// Comprueba las entradas
void checkInput();
// Crea la textura con el texto
void fillTextTexture();
// Actualiza el destino de los rectangulos de las texturas
void updateTextureDstRects();
// Tira globos al escenario
void throwBalloons();
// Inicializa los jugadores
void initPlayers();
// Actualiza los rectangulos negros
void updateBlackRects();
// Actualiza el estado de fade
void updateAllFades();
// Establece el nivel de volumen
void setVolume(int amount);
// Reestablece el nivel de volumen
void resetVolume();
public:
// Constructor
Credits();
// Destructor
~Credits();
// Bucle principal
void run();
};

View File

@@ -1,7 +1,7 @@
#include "dbgtxt.h"
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_rwops.h> // for SDL_RWFromMem
#include <SDL2/SDL_surface.h> // for SDL_LoadBMP_RW
#include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_rwops.h> // para SDL_RWFromMem
#include <SDL2/SDL_surface.h> // para SDL_LoadBMP_RW
namespace
{

View File

@@ -1,7 +1,7 @@
#pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint8
#include <SDL2/SDL_render.h> // para SDL_Renderer
#include <SDL2/SDL_stdinc.h> // para Uint8
void dbg_init(SDL_Renderer *renderer);
void dbg_print(int x, int y, const char *text, Uint8 r, Uint8 g, Uint8 b);

View File

@@ -1,58 +1,26 @@
#include "define_buttons.h"
#include <utility> // for move
#include "input.h" // for Input, InputType
#include "lang.h" // for getText
#include "options.h" // for options
#include "param.h" // for param
#include "section.h" // for Name, Options, name, options
#include "text.h" // for Text
#include "utils.h" // for OptionsController, Options, Param, ParamGame
#include "input.h" // Para Input, InputType
#include "lang.h" // Para getText
#include "options.h" // Para OptionsController, Options, options
#include "param.h" // Para Param, param, ParamGame, ParamTitle
#include "resource.h" // Para Resource
#include "section.h" // Para Name, Options, name, options
#include "text.h" // Para Text
// Constructor
DefineButtons::DefineButtons(std::unique_ptr<Text> text_)
: text_(std::move(text_))
DefineButtons::DefineButtons()
: input_(Input::get()),
text_(Resource::get()->getText("8bithud"))
{
// Copia punteros a los objetos
input_ = Input::get();
// Inicializa variables
enabled_ = false;
x_ = param.game.width / 2;
y_ = param.title.press_start_position;
index_controller_ = 0;
index_button_ = 0;
buttons_.clear();
DefineButtonsButton button;
button.label = lang::getText(95);
button.input = InputType::FIRE_LEFT;
button.button = SDL_CONTROLLER_BUTTON_X;
buttons_.push_back(button);
button.label = lang::getText(96);
button.input = InputType::FIRE_CENTER;
button.button = SDL_CONTROLLER_BUTTON_Y;
buttons_.push_back(button);
button.label = lang::getText(97);
button.input = InputType::FIRE_RIGHT;
button.button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
buttons_.push_back(button);
button.label = lang::getText(98);
button.input = InputType::START;
button.button = SDL_CONTROLLER_BUTTON_START;
buttons_.push_back(button);
button.label = lang::getText(99);
button.input = InputType::EXIT;
button.button = SDL_CONTROLLER_BUTTON_BACK;
buttons_.push_back(button);
clearButtons();
for (int i = 0; i < input_->getNumControllers(); ++i)
{
controller_names_.push_back(input_->getControllerName(i));
controller_names_.emplace_back(input_->getControllerName(i));
}
}
@@ -61,38 +29,40 @@ void DefineButtons::render()
{
if (enabled_)
{
text_->writeCentered(x_, y_ - 10, lang::getText(100) + std::to_string(options.controller[index_controller_].player_id));
text_->writeCentered(x_, y_, controller_names_[index_controller_]);
text_->writeCentered(x_, y_ + 10, buttons_[index_button_].label);
text_->writeCentered(x_, y_ - 10, lang::getText(100) + std::to_string(options.controllers.at(index_controller_).player_id));
text_->writeCentered(x_, y_, controller_names_.at(index_controller_));
text_->writeCentered(x_, y_ + 10, buttons_.at(index_button_).label);
}
}
// Comprueba el botón que se ha pulsado
void DefineButtons::doControllerButtonDown(SDL_ControllerButtonEvent *event)
void DefineButtons::doControllerButtonDown(const SDL_ControllerButtonEvent &event)
{
int i = input_->getJoyIndex(event->which);
// Solo pillamos botones del mando que toca
if (i != index_controller_)
// Solo pilla botones del mando que toca
if (input_->getJoyIndex(event.which) != static_cast<int>(index_controller_))
{
return;
}
buttons_[index_button_].button = (SDL_GameControllerButton)event->button;
incIndexButton();
const auto button = static_cast<SDL_GameControllerButton>(event.button);
if (checkButtonNotInUse(button))
{
buttons_.at(index_button_).button = button;
incIndexButton();
}
}
// Asigna los botones definidos al input_
void DefineButtons::bindButtons()
{
for (int i = 0; i < (int)buttons_.size(); ++i)
for (const auto &button : buttons_)
{
input_->bindGameControllerButton(index_controller_, buttons_[i].input, buttons_[i].button);
input_->bindGameControllerButton(index_controller_, button.input, button.button);
}
}
// Comprueba las entradas
void DefineButtons::checkInput()
// Comprueba los eventos
void DefineButtons::checkEvents()
{
if (enabled_)
{
@@ -106,16 +76,14 @@ void DefineButtons::checkInput()
case SDL_QUIT:
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_NORMAL;
section::options = section::Options::QUIT_WITH_KEYBOARD;
break;
}
case SDL_CONTROLLERBUTTONDOWN:
{
doControllerButtonDown(&event.cbutton);
doControllerButtonDown(event.cbutton);
break;
}
default:
break;
}
@@ -131,6 +99,7 @@ bool DefineButtons::enable(int index)
enabled_ = true;
index_controller_ = index;
index_button_ = 0;
clearButtons();
return true;
}
@@ -138,18 +107,15 @@ bool DefineButtons::enable(int index)
}
// Comprueba si está habilitado
bool DefineButtons::isEnabled()
{
return enabled_;
}
bool DefineButtons::isEnabled() { return enabled_; }
// Incrementa el indice de los botones
void DefineButtons::incIndexButton()
{
index_button_++;
++index_button_;
// Comprueba si ha finalizado
if (index_button_ == (int)buttons_.size())
if (index_button_ == buttons_.size())
{
// Asigna los botones definidos al input_
bindButtons();
@@ -157,11 +123,7 @@ void DefineButtons::incIndexButton()
// Guarda los cambios en las opciones
saveBindingsToOptions();
//input_->allActive(index_controller_);
// Reinicia variables
index_button_ = 0;
index_controller_ = 0;
// Deshabilita
enabled_ = false;
}
}
@@ -170,17 +132,34 @@ void DefineButtons::incIndexButton()
void DefineButtons::saveBindingsToOptions()
{
// Modifica las opciones para colocar los valores asignados
options.controller[index_controller_].name = input_->getControllerName(index_controller_);
for (int j = 0; j < (int)options.controller[index_controller_].inputs.size(); ++j)
auto &controller = options.controllers.at(index_controller_);
controller.name = input_->getControllerName(index_controller_);
for (size_t j = 0; j < controller.inputs.size(); ++j)
{
options.controller[index_controller_].buttons[j] = input_->getControllerBinding(index_controller_, options.controller[index_controller_].inputs[j]);
controller.buttons.at(j) = input_->getControllerBinding(index_controller_, controller.inputs.at(j));
}
}
// Intercambia los jugadores asignados a los dos primeros mandos
void DefineButtons::swapControllers()
// Comprueba que un botón no esté ya asignado
bool DefineButtons::checkButtonNotInUse(SDL_GameControllerButton button)
{
const int temp = options.controller[0].player_id;
options.controller[0].player_id = options.controller[1].player_id;
options.controller[1].player_id = temp;
for (const auto &b : buttons_)
{
if (b.button == button)
{
return false;
}
}
return true;
}
// Limpia la asignación de botones
void DefineButtons::clearButtons()
{
buttons_.clear();
buttons_.emplace_back(lang::getText(95), InputType::FIRE_LEFT, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(96), InputType::FIRE_CENTER, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(97), InputType::FIRE_RIGHT, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(98), InputType::START, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(99), InputType::SERVICE, SDL_CONTROLLER_BUTTON_INVALID);
}

View File

@@ -1,19 +1,24 @@
#pragma once
#include <SDL2/SDL_events.h> // for SDL_ControllerButtonEvent
#include <SDL2/SDL_gamecontroller.h> // for SDL_GameControllerButton
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
#include <vector> // for vector
class Input;
class Text;
enum class InputType : int;
#include <SDL2/SDL_events.h> // Para SDL_ControllerButtonEvent
#include <SDL2/SDL_gamecontroller.h> // Para SDL_GameControllerButton
#include <stddef.h> // Para size_t
#include <memory> // Para shared_ptr, unique_ptr
#include <string> // Para string
#include <vector> // Para vector
class Input; // lines 8-8
class Text; // lines 9-9
enum class InputType : int; // lines 10-10
struct DefineButtonsButton
{
std::string label; // Texto en pantalla para el botón
InputType input; // Input asociado
SDL_GameControllerButton button; // Botón del mando correspondiente
// Constructor
DefineButtonsButton(const std::string &lbl, InputType inp, SDL_GameControllerButton btn)
: label(lbl), input(inp), button(btn) {}
};
// Clase Bullet
@@ -25,19 +30,19 @@ private:
std::shared_ptr<Text> text_; // Objeto para escribir texto
// Variables
bool enabled_; // Indica si el objeto está habilitado
bool enabled_ = false; // Indica si el objeto está habilitado
int x_; // Posición donde dibujar el texto
int y_; // Posición donde dibujar el texto
std::vector<DefineButtonsButton> buttons_; // Vector con las nuevas definiciones de botones/acciones
int index_controller_; // Indice del controlador a reasignar
int index_button_; // Indice para saber qué bot´çon se está definiendo
size_t index_controller_ = 0; // Indice del controlador a reasignar
size_t index_button_ = 0; // Indice para saber qué botón se está definiendo
std::vector<std::string> controller_names_; // Nombres de los mandos
// Incrementa el indice de los botones
void incIndexButton();
// Comprueba el botón que se ha pulsado
void doControllerButtonDown(SDL_ControllerButtonEvent *event);
void doControllerButtonDown(const SDL_ControllerButtonEvent &event);
// Asigna los botones definidos al input
void bindButtons();
@@ -45,9 +50,15 @@ private:
// Guarda los cambios en las opciones
void saveBindingsToOptions();
// Comprueba que un botón no esté ya asignado
bool checkButtonNotInUse(SDL_GameControllerButton button);
// Limpia la asignación de botones
void clearButtons();
public:
// Constructor
explicit DefineButtons(std::unique_ptr<Text> text);
DefineButtons();
// Destructor
~DefineButtons() = default;
@@ -55,15 +66,12 @@ public:
// Dibuja el objeto en pantalla
void render();
// Comprueba las entradas
void checkInput();
// Comprueba los eventos
void checkEvents();
// Habilita el objeto
bool enable(int index);
// Comprueba si está habilitado
bool isEnabled();
// Intercambia los jugadores asignados a los dos primeros mandos
void swapControllers();
};

View File

@@ -1,44 +1,50 @@
// IWYU pragma: no_include <bits/chrono.h>
#include "director.h"
#include <SDL2/SDL.h> // for SDL_Init, SDL_Quit, SDL_INIT_EV...
#include <SDL2/SDL_audio.h> // for AUDIO_S16
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_error.h> // for SDL_GetError
#include <SDL2/SDL_gamecontroller.h> // for SDL_CONTROLLER_BUTTON_B, SDL_CO...
#include <SDL2/SDL_hints.h> // for SDL_SetHint, SDL_HINT_RENDER_DR...
#include <SDL2/SDL_scancode.h> // for SDL_SCANCODE_0, SDL_SCANCODE_DOWN
#include <SDL2/SDL_stdinc.h> // for SDL_bool, Uint32
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <errno.h> // for errno, EEXIST, EACCES, ENAMETOO...
#include <stdio.h> // for printf, perror
#include <string.h> // for strcmp
#include <sys/stat.h> // for mkdir, stat, S_IRWXU
#include <unistd.h> // for getuid
#include <cstdlib> // for exit, EXIT_FAILURE, rand, srand
#include <iostream> // for basic_ostream, operator<<, cout
#include <memory> // for make_unique, unique_ptr
#include <string> // for operator+, allocator, char_traits
#include "asset.h" // for Asset, AssetType
#include "dbgtxt.h" // for dbg_init
#include "game.h" // for Game, GAME_MODE_DEMO_OFF, GAME_...
#include "global_inputs.h" // for init
#include "hiscore_table.h" // for HiScoreTable
#include "input.h" // for Input, InputType
#include "instructions.h" // for Instructions
#include "intro.h" // for Intro
#include "jail_audio.h" // for JA_LoadMusic, JA_LoadSound, JA_...
#include "lang.h" // for Code, loadFromFile
#include "logo.h" // for Logo
#include "manage_hiscore_table.h" // for ManageHiScoreTable
#include "on_screen_help.h" // for OnScreenHelp
#include "options.h" // for options, loadOptionsFile, saveO...
#include "param.h" // for param, loadParamsFromFile
#include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options
#include "title.h" // for Title
#include "utils.h" // for MusicFile, SoundFile, Options
#include <SDL2/SDL.h> // Para SDL_Init, SDL_Quit, SDL_INIT_EV...
#include <SDL2/SDL_audio.h> // Para AUDIO_S16
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_error.h> // Para SDL_GetError
#include <SDL2/SDL_gamecontroller.h> // Para SDL_CONTROLLER_BUTTON_B, SDL_CO...
#include <SDL2/SDL_hints.h> // Para SDL_SetHint, SDL_HINT_RENDER_DR...
#include <SDL2/SDL_scancode.h> // Para SDL_SCANCODE_0, SDL_SCANCODE_DOWN
#include <SDL2/SDL_stdinc.h> // Para SDL_bool, Uint32
#include <chrono> // Para duration, system_clock
#include <errno.h> // Para errno, EEXIST, EACCES, ENAMETOO...
#include <stdio.h> // Para printf, perror
#include <sys/stat.h> // Para mkdir, stat, S_IRWXU
#include <unistd.h> // Para getuid
#include <algorithm> // Para min
#include <cstdlib> // Para exit, EXIT_FAILURE, size_t, rand
#include <iostream> // Para basic_ostream, operator<<, basi...
#include <memory> // Para make_unique, unique_ptr
#include <stdexcept> // Para runtime_error
#include <string> // Para operator+, char_traits, allocator
#include <vector> // Para vector
#include "asset.h" // Para Asset, AssetType
#include "credits.h" // Para Credits
#include "dbgtxt.h" // Para dbg_init
#include "game.h" // Para Game, GAME_MODE_DEMO_OFF, GAME_...
#include "global_inputs.h" // Para init
#include "hiscore_table.h" // Para HiScoreTable
#include "input.h" // Para Input, InputType
#include "instructions.h" // Para Instructions
#include "intro.h" // Para Intro
#include "jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundV...
#include "lang.h" // Para Code, loadFromFile
#include "logo.h" // Para Logo
#include "manage_hiscore_table.h" // Para ManageHiScoreTable
#include "notifier.h" // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp
#include "options.h" // Para Options, OptionsController, opt...
#include "param.h" // Para Param, ParamGame, param, loadPa...
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, Options, name, options
#include "title.h" // Para Title
#include "utils.h" // Para Overrides, overrides
#ifndef _WIN32
#include <pwd.h> // for getpwuid, passwd
#include <pwd.h> // para getpwuid, passwd
#endif
// Constructor
@@ -49,80 +55,74 @@ Director::Director(int argc, const char *argv[])
section::options = section::Options::GAME_PLAY_1P;
#elif DEBUG
section::name = section::Name::LOGO;
#else
#else // NORMAL GAME
section::name = section::Name::LOGO;
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
#endif
#ifndef VERBOSE
// Deshabilita todos los std::cout
std::ostream null_stream(nullptr);
orig_buf = std::cout.rdbuf(null_stream.rdbuf());
#endif
std::cout << "Game start" << std::endl;
// Inicia la semilla aleatoria
unsigned int seed = static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count());
std::srand(seed);
// Comprueba los parametros del programa
checkProgramArguments(argc, argv);
// Crea la carpeta del sistema donde guardar datos
// Crea la carpeta del sistema donde guardar los datos persistentes
createSystemFolder("jailgames");
createSystemFolder("jailgames/coffee_crisis_arcade_edition");
// Crea el objeto que controla los ficheros de recursos
Asset::init(executable_path_);
// Si falta algún fichero no inicia el programa
if (!setFileList())
{
exit(EXIT_FAILURE);
}
// Carga el fichero de configuración
loadOptionsFile(Asset::get()->get("config.txt"));
// Carga los parametros para configurar el juego
#ifdef ANBERNIC
const std::string paramFilePath = asset->get("param_320x240.txt");
#else
const std::string paramFilePath = param_file_argument_ == "--320x240" ? Asset::get()->get("param_320x240.txt") : Asset::get()->get("param_320x256.txt");
#endif
loadParams(paramFilePath);
// Carga el fichero de puntuaciones
auto manager = std::make_unique<ManageHiScoreTable>(&options.game.hi_score_table);
manager->loadFromFile(Asset::get()->get("score.bin"));
// Inicializa SDL
initSDL();
// Inicializa JailAudio
initJailAudio();
// Inicializa el texto de debug
dbg_init(renderer_);
// Crea los objetos
lang::loadFromFile(getLangFile((lang::Code)options.game.language));
Input::init(Asset::get()->get("gamecontrollerdb.txt"));
initInput();
Screen::init(window_, renderer_);
OnScreenHelp::init();
// Carga los sonidos del juego
loadSounds();
// Carga las musicas del juego
loadMusics();
globalInputs::init();
init();
}
Director::~Director()
{
close();
std::cout << "\nBye!" << std::endl;
}
// Inicializa todo
void Director::init()
{
Asset::init(executable_path_); // Crea el objeto que controla los ficheros de recursos
setFileList(); // Crea el indice de ficheros
loadOptionsFile(Asset::get()->get("config.txt")); // Carga el fichero de configuración
loadParams(); // Carga los parametros
loadScoreFile(); // Carga el fichero de puntuaciones
// Inicializa y crea el resto de objetos
initSDL();
initJailAudio();
dbg_init(renderer_);
lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language)));
Screen::init(window_, renderer_);
Resource::init();
Input::init(Asset::get()->get("gamecontrollerdb.txt"));
bindInputs();
Notifier::init(std::string(), Resource::get()->getText("8bithud"));
OnScreenHelp::init();
}
// Cierra todo
void Director::close()
{
saveOptionsFile(Asset::get()->get("config.txt"));
Asset::destroy();
Resource::destroy();
Input::destroy();
Screen::destroy();
Notifier::destroy();
OnScreenHelp::destroy();
sounds_.clear();
musics_.clear();
JA_Quit();
SDL_DestroyRenderer(renderer_);
SDL_DestroyWindow(window_);
@@ -130,12 +130,35 @@ Director::~Director()
SDL_Quit();
}
/// Inicializa el objeto input
void Director::initInput()
// Carga los parametros
void Director::loadParams()
{
// Busca si hay mandos conectados
Input::get()->discoverGameControllers();
// Carga los parametros para configurar el juego
#ifdef ANBERNIC
const std::string paramFilePath = asset->get("param_320x240.txt");
#else
const std::string paramFilePath = overrides.param_file == "--320x240" ? Asset::get()->get("param_320x240.txt") : Asset::get()->get("param_320x256.txt");
#endif
loadParamsFromFile(paramFilePath);
}
// Carga el fichero de puntuaciones
void Director::loadScoreFile()
{
auto manager = std::make_unique<ManageHiScoreTable>(options.game.hi_score_table);
if (overrides.clear_hi_score_table)
{
manager->clear();
}
else
{
manager->loadFromFile(Asset::get()->get("score.bin"));
}
}
// Asigna los botones y teclas al objeto Input
void Director::bindInputs()
{
// Teclado - Movimiento del jugador
Input::get()->bindKey(InputType::UP, SDL_SCANCODE_UP);
Input::get()->bindKey(InputType::DOWN, SDL_SCANCODE_DOWN);
@@ -157,7 +180,8 @@ void Director::initInput()
Input::get()->bindKey(InputType::WINDOW_FULLSCREEN, SDL_SCANCODE_F3);
Input::get()->bindKey(InputType::VIDEO_SHADERS, SDL_SCANCODE_F4);
Input::get()->bindKey(InputType::MUTE, SDL_SCANCODE_F5);
Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F6);
Input::get()->bindKey(InputType::CHANGE_LANG, SDL_SCANCODE_F6);
Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F7);
Input::get()->bindKey(InputType::RESET, SDL_SCANCODE_F10);
// Asigna botones a inputs
@@ -178,27 +202,23 @@ void Director::initInput()
// Mando - Control del programa
Input::get()->bindGameControllerButton(i, InputType::SERVICE, SDL_CONTROLLER_BUTTON_BACK);
Input::get()->bindGameControllerButton(i, InputType::EXIT, InputType::START);
Input::get()->bindGameControllerButton(i, InputType::PAUSE, InputType::FIRE_RIGHT);
Input::get()->bindGameControllerButton(i, InputType::VIDEO_SHADERS, InputType::FIRE_LEFT);
Input::get()->bindGameControllerButton(i, InputType::MUTE, InputType::LEFT);
Input::get()->bindGameControllerButton(i, InputType::SHOWINFO, InputType::RIGHT);
Input::get()->bindGameControllerButton(i, InputType::RESET, InputType::FIRE_CENTER);
Input::get()->bindGameControllerButton(i, InputType::CONFIG, InputType::DOWN);
Input::get()->bindGameControllerButton(i, InputType::SWAP_CONTROLLERS, InputType::UP);
}
// Mapea las asignaciones a los botones desde el archivo de configuración, si se da el caso
for (int i = 0; i < num_gamepads; ++i)
for (int index = 0; index < (int)options.controller.size(); ++index)
if (Input::get()->getControllerName(i) == options.controller[index].name)
const size_t max_controllers = std::min(2, num_gamepads);
for (size_t i = 0; i < max_controllers; ++i)
{
for (auto &controller : options.controllers)
{
if (Input::get()->getControllerName(i) == controller.name)
{
options.controller[index].plugged = true;
for (int j = 0; j < (int)options.controller[index].inputs.size(); ++j)
for (size_t j = 0; j < controller.inputs.size(); ++j)
{
Input::get()->bindGameControllerButton(i, options.controller[index].inputs[j], options.controller[index].buttons[j]);
Input::get()->bindGameControllerButton(i, controller.inputs.at(j), controller.buttons.at(j));
}
}
}
}
// Asigna botones a inputs desde otros inputs
for (int i = 0; i < num_gamepads; ++i)
@@ -213,25 +233,41 @@ void Director::initInput()
Input::get()->bindGameControllerButton(i, InputType::SWAP_CONTROLLERS, InputType::UP);
}
// Guarda las asignaciones de botones en las opciones
for (int i = 0; i < num_gamepads; ++i)
// Guarda las asignaciones de botones en las opciones de los dos primeros mandos
for (size_t i = 0; i < max_controllers; ++i)
{
options.controller[i].name = Input::get()->getControllerName(i);
for (int j = 0; j < (int)options.controller[i].inputs.size(); ++j)
// Variables asociadas al mando
options.controllers.at(i).index = i;
options.controllers.at(i).name = Input::get()->getControllerName(i);
options.controllers.at(i).plugged = true;
// Asignaciones de botones
for (size_t j = 0; j < options.controllers.at(i).inputs.size(); ++j)
{
options.controller[i].buttons[j] = Input::get()->getControllerBinding(i, options.controller[i].inputs[j]);
options.controllers.at(i).buttons.at(j) = Input::get()->getControllerBinding(i, options.controllers.at(i).inputs.at(j));
}
}
// Asegura que algún jugador tenga el teclado asignado
if (getPlayerWhoUsesKeyboard() == 0)
{
setKeyboardToPlayer(1);
}
}
// Inicializa JailAudio
void Director::initJailAudio()
{
JA_Init(48000, AUDIO_S16, 2);
JA_EnableMusic(options.audio.music.enabled);
JA_EnableSound(options.audio.sound.enabled);
JA_SetMusicVolume(options.audio.music.volume);
JA_SetSoundVolume(options.audio.sound.volume);
if (options.audio.enabled)
{
JA_SetMusicVolume(to_JA_volume(options.audio.music.volume));
JA_SetSoundVolume(to_JA_volume(options.audio.sound.volume));
}
else
{
JA_SetMusicVolume(0);
JA_SetSoundVolume(0);
}
}
// Arranca SDL y crea la ventana
@@ -243,54 +279,45 @@ bool Director::initSDL()
// Inicializa SDL
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
#ifdef VERBOSE
std::cout << "SDL could not initialize!\nSDL Error: " << SDL_GetError() << std::endl;
#endif
success = false;
}
else
{
// Inicia el generador de numeros aleatorios
std::srand(static_cast<unsigned int>(SDL_GetTicks()));
#ifdef VERBOSE
/*
// Muestra información de la pantalla
/*std::cout << "\nDisplay modes list:" << std::endl;
std::cout << "\nDisplay modes list:" << std::endl;
for (int i = 0; i < SDL_GetNumDisplayModes(0); ++i)
{
SDL_DisplayMode DM;
SDL_GetDisplayMode(0,i,&DM);
std::cout << " - " + std::to_string(DM.w) + "x" + std::to_string(DM.h) + " @ " + std::to_string(DM.refresh_rate) + "Hz" << std::endl;
}*/
std::cout << " - " << DM.w << "x" << DM.h << " @ " << DM.refresh_rate << "Hz" << std::endl;
}
*/
SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode(0, &DM);
std::cout << "\nCurrent display mode: " + std::to_string(DM.w) + "x" + std::to_string(DM.h) + " @ " + std::to_string(DM.refresh_rate) + "Hz" << std::endl;
std::cout << "Window resolution : " + std::to_string(param.game.width) + "x" + std::to_string(param.game.height) + " x" + std::to_string(options.video.window.size) << std::endl;
#endif
std::cout << "\nCurrent display mode: " << DM.w << "x" << DM.h << " @ " << DM.refresh_rate << "Hz" << std::endl;
std::cout << "Window resolution : " << param.game.width << "x" << param.game.height << " x" << options.video.window.size << std::endl;
// Establece el filtro de la textura
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(static_cast<int>(options.video.filter)).c_str()))
{
#ifdef VERBOSE
std::cout << "Warning: texture filtering not enabled!\n";
#endif
}
#ifndef NO_SHADERS
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"))
{
#ifdef VERBOSE
std::cout << "Warning: opengl not enabled!\n";
#endif // VERBOSE
}
#endif // NO_SHADERS
// Crea la ventana
#endif
// Crea la ventana
window_ = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, param.game.width * options.video.window.size, param.game.height * options.video.window.size, SDL_WINDOW_HIDDEN);
if (!window_)
{
#ifdef VERBOSE
std::cout << "Window could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
#endif
success = false;
}
else
@@ -301,42 +328,35 @@ bool Director::initSDL()
{
flags = SDL_RENDERER_PRESENTVSYNC;
}
#ifndef NO_SHADERS
// La aceleración se activa según el define
flags = flags | SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
#endif
renderer_ = SDL_CreateRenderer(window_, -1, flags);
if (!renderer_)
{
#ifdef VERBOSE
std::cout << "Renderer could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
#endif
success = false;
}
else
{
// Inicializa el color de renderizado
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
// Establece el tamaño del buffer de renderizado
SDL_RenderSetLogicalSize(renderer_, param.game.width, param.game.height);
SDL_RenderSetIntegerScale(renderer_, static_cast<SDL_bool>(options.video.integer_scale));
// Establece el modo de mezcla
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
}
}
}
#ifdef VERBOSE
std::cout << std::endl;
#endif
return success;
}
// Crea el indice de ficheros
bool Director::setFileList()
void Director::setFileList()
{
#ifdef MACOS_BUNDLE
const std::string prefix = "/../Resources";
@@ -357,6 +377,7 @@ bool Director::setFileList()
Asset::get()->add(prefix + "/data/music/intro.ogg", AssetType::MUSIC);
Asset::get()->add(prefix + "/data/music/playing.ogg", AssetType::MUSIC);
Asset::get()->add(prefix + "/data/music/title.ogg", AssetType::MUSIC);
Asset::get()->add(prefix + "/data/music/credits.ogg", AssetType::MUSIC);
// Sonidos
Asset::get()->add(prefix + "/data/sound/balloon.wav", AssetType::SOUND);
@@ -375,113 +396,134 @@ bool Director::setFileList()
Asset::get()->add(prefix + "/data/sound/clock.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/powerball.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/notify.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/logo.wav", AssetType::SOUND);
// Shaders
Asset::get()->add(prefix + "/data/shaders/crtpi.glsl", AssetType::DATA);
Asset::get()->add(prefix + "/data/shaders/crtpi_256.glsl", AssetType::DATA);
Asset::get()->add(prefix + "/data/shaders/crtpi_240.glsl", AssetType::DATA);
// Texturas
Asset::get()->add(prefix + "/data/gfx/controllers/controllers.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon1.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon1.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon2.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon3.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon3.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon4.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon4.ani", AssetType::ANIMATION);
{ // Controllers
Asset::get()->add(prefix + "/data/gfx/controllers/controllers.png", AssetType::BITMAP);
}
Asset::get()->add(prefix + "/data/gfx/balloon/explosion1.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion1.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion2.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion3.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion3.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion4.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion4.ani", AssetType::ANIMATION);
{ // Balloons
Asset::get()->add(prefix + "/data/gfx/balloon/balloon1.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon1.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon2.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon3.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon3.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon4.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon4.ani", AssetType::ANIMATION);
}
Asset::get()->add(prefix + "/data/gfx/balloon/powerball.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/powerball.ani", AssetType::ANIMATION);
{ // Explosions
Asset::get()->add(prefix + "/data/gfx/balloon/explosion1.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion1.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion2.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion3.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion3.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion4.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion4.ani", AssetType::ANIMATION);
}
Asset::get()->add(prefix + "/data/gfx/bullet/bullet.png", AssetType::BITMAP);
{ // Power Ball
Asset::get()->add(prefix + "/data/gfx/balloon/powerball.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/powerball.ani", AssetType::ANIMATION);
}
Asset::get()->add(prefix + "/data/gfx/game/game_buildings.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_clouds1.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_clouds2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_grass.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_power_meter.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_sky_colors.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_text.png", AssetType::BITMAP);
{ // Bala
Asset::get()->add(prefix + "/data/gfx/bullet/bullet.png", AssetType::BITMAP);
}
Asset::get()->add(prefix + "/data/gfx/intro/intro.png", AssetType::BITMAP);
{ // Juego
Asset::get()->add(prefix + "/data/gfx/game/game_buildings.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_clouds1.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_clouds2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_grass.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_power_meter.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_sky_colors.png", AssetType::BITMAP);
}
Asset::get()->add(prefix + "/data/gfx/logo/logo_jailgames.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/logo/logo_jailgames_mini.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/logo/logo_since_1998.png", AssetType::BITMAP);
{ // Intro
Asset::get()->add(prefix + "/data/gfx/intro/intro.png", AssetType::BITMAP);
}
Asset::get()->add(prefix + "/data/gfx/item/item_points1_disk.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_points1_disk.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_points2_gavina.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_points2_gavina.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_points3_pacmar.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_points3_pacmar.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_clock.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_clock.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.ani", AssetType::ANIMATION);
{ // Logo
Asset::get()->add(prefix + "/data/gfx/logo/logo_jailgames.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/logo/logo_jailgames_mini.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/logo/logo_since_1998.png", AssetType::BITMAP);
}
Asset::get()->add(prefix + "/data/gfx/title/title_bg_tile.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_coffee.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_crisis.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_arcade_edition.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_dust.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_dust.ani", AssetType::ANIMATION);
{ // Items
Asset::get()->add(prefix + "/data/gfx/item/item_points1_disk.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_points1_disk.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_points2_gavina.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_points2_gavina.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_points3_pacmar.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_points3_pacmar.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_clock.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_clock.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.ani", AssetType::ANIMATION);
}
Asset::get()->add(prefix + "/data/gfx/player/player1.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/player/player1_pal1.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_pal2.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_pal3.gif", AssetType::PALETTE);
{ // Titulo
Asset::get()->add(prefix + "/data/gfx/title/title_bg_tile.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_coffee.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_crisis.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_arcade_edition.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_dust.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_dust.ani", AssetType::ANIMATION);
}
Asset::get()->add(prefix + "/data/gfx/player/player2.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/player/player2_pal1.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_pal2.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_pal3.gif", AssetType::PALETTE);
{ // Jugador 1
Asset::get()->add(prefix + "/data/gfx/player/player1.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/player/player1_one_coffee_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_two_coffee_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_all_white_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_power.png", AssetType::BITMAP);
}
Asset::get()->add(prefix + "/data/gfx/player/player.ani", AssetType::ANIMATION);
{ // Jugador 2
Asset::get()->add(prefix + "/data/gfx/player/player2.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/player/player2_one_coffee_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_two_coffee_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_all_white_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_power.png", AssetType::BITMAP);
}
Asset::get()->add(prefix + "/data/gfx/player/player_power.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/player/player_power_pal.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player_power.ani", AssetType::ANIMATION);
{ // Animaciones del jugador
Asset::get()->add(prefix + "/data/gfx/player/player.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/player/player_power.ani", AssetType::ANIMATION);
}
// Fuentes de texto
Asset::get()->add(prefix + "/data/font/8bithud.png", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/8bithud.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/8bithud.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia.png", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia_big2.png", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/nokia.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia2.png", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia2.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia_big2.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/smb2_big.png", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/smb2_big.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/smb2.gif", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/smb2_pal1.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/font/smb2.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/smb2_palette1.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/font/smb2.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/04b_25.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/04b_25.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/04b_25_2x.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/04b_25_2x.txt", AssetType::FONT);
// Textos
Asset::get()->add(prefix + "/data/lang/es_ES.txt", AssetType::LANG);
Asset::get()->add(prefix + "/data/lang/en_UK.txt", AssetType::LANG);
Asset::get()->add(prefix + "/data/lang/ba_BA.txt", AssetType::LANG);
return Asset::get()->check();
}
// Carga los parametros para configurar el juego
void Director::loadParams(const std::string &file_path)
{
loadParamsFromFile(file_path);
// Si falta algun fichero, sale del programa
if (!Asset::get()->check())
throw std::runtime_error("Falta algun fichero");
}
// Comprueba los parametros del programa
@@ -490,15 +532,18 @@ void Director::checkProgramArguments(int argc, const char *argv[])
// Establece la ruta del programa
executable_path_ = argv[0];
// Valores por defecto
param_file_argument_.clear();
// Comprueba el resto de parámetros
for (int i = 1; i < argc; ++i)
{
if (strcmp(argv[i], "--320x240") == 0)
std::string arg = argv[i];
if (arg == "--320x240")
{
param_file_argument_ = argv[i];
overrides.param_file = arg;
}
else if (arg == "--clear_score")
{
overrides.clear_hi_score_table = true;
}
}
}
@@ -563,38 +608,6 @@ void Director::createSystemFolder(const std::string &folder)
}
}
// Carga los sonidos del juego
void Director::loadSounds()
{
// Obtiene la lista con las rutas a los ficheros de sonidos
auto list = Asset::get()->getListByType(AssetType::SOUND);
sounds_.clear();
for (const auto &l : list)
{
auto last_index = l.find_last_of('/') + 1;
auto name = l.substr(last_index);
sounds_.emplace_back(SoundFile{name, JA_LoadSound(l.c_str())});
}
}
// Carga las musicas del juego
void Director::loadMusics()
{
// Obtiene la lista con las rutas a los ficheros musicales
auto list = Asset::get()->getListByType(AssetType::MUSIC);
musics_.clear();
for (const auto &l : list)
{
auto last_index = l.find_last_of('/') + 1;
auto name = l.substr(last_index);
musics_.emplace_back(MusicFile{name, JA_LoadMusic(l.c_str())});
}
}
// Ejecuta la sección con el logo
void Director::runLogo()
{
@@ -605,14 +618,14 @@ void Director::runLogo()
// Ejecuta la sección con la secuencia de introducción
void Director::runIntro()
{
auto intro = std::make_unique<Intro>(getMusic(musics_, "intro.ogg"));
auto intro = std::make_unique<Intro>();
intro->run();
}
// Ejecuta la sección con el título del juego
void Director::runTitle()
{
auto title = std::make_unique<Title>(getMusic(musics_, "title.ogg"));
auto title = std::make_unique<Title>();
title->run();
}
@@ -620,22 +633,33 @@ void Director::runTitle()
void Director::runGame()
{
const auto player_id = section::options == section::Options::GAME_PLAY_1P ? 1 : 2;
#ifdef DEBUG
constexpr auto current_stage = 0;
auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_OFF, getMusic(musics_, "playing.ogg"));
#else
constexpr auto current_stage = 0;
#endif
auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_OFF);
game->run();
}
// Ejecuta la sección donde se muestran las instrucciones
void Director::runInstructions()
{
auto instructions = std::make_unique<Instructions>(getMusic(musics_, "title.ogg"));
auto instructions = std::make_unique<Instructions>();
instructions->run();
}
// Ejecuta la sección donde se muestran los creditos del programa
void Director::runCredits()
{
auto credits = std::make_unique<Credits>();
credits->run();
}
// Ejecuta la sección donde se muestra la tabla de puntuaciones
void Director::runHiScoreTable()
{
auto hi_score_table = std::make_unique<HiScoreTable>(getMusic(musics_, "title.ogg"));
auto hi_score_table = std::make_unique<HiScoreTable>();
hi_score_table->run();
}
@@ -644,10 +668,20 @@ void Director::runDemoGame()
{
const auto player_id = (rand() % 2) + 1;
constexpr auto current_stage = 0;
auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_ON, nullptr);
auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_ON);
game->run();
}
// Ejecuta la sección init
void Director::runInit()
{
if (section::options == section::Options::RELOAD)
{
Resource::get()->reload();
}
section::name = section::Name::LOGO;
}
int Director::run()
{
// Bucle principal
@@ -656,44 +690,64 @@ int Director::run()
switch (section::name)
{
case section::Name::INIT:
section::name = section::Name::LOGO;
runInit();
break;
case section::Name::LOGO:
runLogo();
break;
case section::Name::INTRO:
runIntro();
break;
case section::Name::TITLE:
runTitle();
break;
case section::Name::GAME:
runGame();
break;
case section::Name::HI_SCORE_TABLE:
runHiScoreTable();
break;
case section::Name::GAME_DEMO:
runDemoGame();
break;
case section::Name::INSTRUCTIONS:
runInstructions();
break;
case section::Name::CREDITS:
runCredits();
break;
default:
break;
}
}
const int return_code = section::options == section::Options::QUIT_NORMAL ? 0 : 1;
return return_code;
std::string return_code;
switch (section::options)
{
case section::Options::QUIT_WITH_KEYBOARD:
return_code = "with keyboard";
break;
case section::Options::QUIT_WITH_CONTROLLER:
return_code = "with controller";
break;
default:
return_code = "from event";
break;
}
std::cout << "\nGame end " << return_code << std::endl;
#ifndef VERBOSE
// Habilita de nuevo los std::cout
std::cout.rdbuf(orig_buf);
#endif
#ifdef ARCADE
// Comprueba si ha de apagar el sistema
if (section::options == section::Options::QUIT_WITH_CONTROLLER)
shutdownSystem();
#endif
return (section::options == section::Options::QUIT_WITH_CONTROLLER) ? 1 : 0;
}
// Obtiene una fichero a partir de un lang::Code
@@ -704,18 +758,35 @@ std::string Director::getLangFile(lang::Code code)
case lang::Code::ba_BA:
return Asset::get()->get("ba_BA.txt");
break;
case lang::Code::es_ES:
return Asset::get()->get("es_ES.txt");
break;
case lang::Code::en_UK:
return Asset::get()->get("en_UK.txt");
break;
default:
break;
}
return Asset::get()->get("en_UK.txt");
}
#ifdef ARCADE
// Apaga el sistema
void Director::shutdownSystem()
{
#ifdef _WIN32
// Apaga el sistema en Windows
system("shutdown /s /t 0");
#elif __APPLE__
// Apaga el sistema en macOS
system("sudo shutdown -h now");
#elif __linux__
// Apaga el sistema en Linux
system("shutdown -h now");
#else
// Sistema operativo no compatible
#error "Sistema operativo no soportado"
#endif
}
#endif // ARCADE

View File

@@ -1,12 +1,12 @@
#pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_video.h> // for SDL_Window
#include <string> // for string
#include <vector> // for vector
namespace lang { enum class Code : int; }
struct MusicFile;
struct SoundFile;
#include <SDL2/SDL_render.h> // Para SDL_Renderer
#include <SDL2/SDL_video.h> // Para SDL_Window
#include <string> // Para string
namespace lang
{
enum class Code : int;
} // lines 9-9
// Textos
constexpr char WINDOW_CAPTION[] = "Coffee Crisis Arcade Edition";
@@ -15,15 +15,15 @@ class Director
{
private:
// 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
#ifndef VERBOSE
std::streambuf *orig_buf; // Puntero al buffer de flujo original para restaurar std::cout
#endif
// Variables
std::string executable_path_; // Path del ejecutable
std::string system_folder_; // Carpeta del sistema donde guardar datos
std::string param_file_argument_; // Argumento para gestionar el fichero con los parametros del programa
std::vector<SoundFile> sounds_; // Vector con los sonidos
std::vector<MusicFile> musics_; // Vector con las musicas
std::string executable_path_; // Path del ejecutable
std::string system_folder_; // Carpeta del sistema donde guardar datos
// Inicializa jail_audio
void initJailAudio();
@@ -31,20 +31,11 @@ private:
// Arranca SDL y crea la ventana
bool initSDL();
// Inicializa el objeto input
void initInput();
// Carga los parametros para configurar el juego
void loadParams(const std::string &file_path);
// Asigna los botones y teclas al objeto Input
void bindInputs();
// Crea el indice de ficheros
bool setFileList();
// Carga los sonidos del juego
void loadSounds();
// Carga las musicas del juego
void loadMusics();
void setFileList();
// Comprueba los parametros del programa
void checkProgramArguments(int argc, const char *argv[]);
@@ -67,14 +58,36 @@ private:
// Ejecuta la sección donde se muestran las instrucciones
void runInstructions();
// Ejecuta la sección donde se muestran los creditos del programa
void runCredits();
// Ejecuta la sección donde se muestra la tabla de puntuaciones
void runHiScoreTable();
// Ejecuta el juego en modo demo
void runDemoGame();
// Ejecuta la sección init
void runInit();
// Obtiene una fichero a partir de un lang::Code
std::string getLangFile(lang::Code code);
#ifdef ARCADE
// Apaga el sistema
void shutdownSystem();
#endif
// Inicializa todo
void init();
// Cierra todo
void close();
// Carga los parametros
void loadParams();
// Carga el fichero de puntuaciones
void loadScoreFile();
public:
// Constructor

View File

@@ -1,5 +1,6 @@
#include "enter_name.h"
#include <algorithm> // for max, min
#include <stddef.h> // Para size_t
#include <algorithm> // Para max, min
// Constructor
EnterName::EnterName()
@@ -15,8 +16,8 @@ void EnterName::init()
// Inicia la lista de caracteres permitidos
character_list_ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()";
pos_ = 0;
num_characters_ = (int)character_list_.size();
position_ = 0;
num_characters_ = static_cast<int>(character_list_.size());
// Pone la lista de indices para que refleje el nombre
updateCharacterIndex();
@@ -26,26 +27,27 @@ void EnterName::init()
}
// Incrementa la posición
void EnterName::incPos()
void EnterName::incPosition()
{
pos_++;
pos_ = std::min(pos_, NAME_LENGHT - 1);
position_++;
position_ = std::min(position_, NAME_LENGHT - 1);
checkIfPositionHasBeenUsed();
}
// Decrementa la posición
void EnterName::decPos()
void EnterName::decPosition()
{
pos_--;
pos_ = std::max(pos_, 0);
--position_;
position_ = std::max(position_, 0);
}
// Incrementa el índice
void EnterName::incIndex()
{
++character_index_[pos_];
if (character_index_[pos_] >= num_characters_)
++character_index_[position_];
if (character_index_[position_] >= num_characters_)
{
character_index_[pos_] = 0;
character_index_[position_] = 0;
}
updateName();
}
@@ -53,15 +55,15 @@ void EnterName::incIndex()
// Decrementa el índice
void EnterName::decIndex()
{
--character_index_[pos_];
if (character_index_[pos_] < 0)
--character_index_[position_];
if (character_index_[position_] < 0)
{
character_index_[pos_] = num_characters_ - 1;
character_index_[position_] = num_characters_ - 1;
}
updateName();
}
// Actualiza la variable
// Actualiza el nombre a partir de la lista de índices
void EnterName::updateName()
{
name_.clear();
@@ -74,29 +76,27 @@ void EnterName::updateName()
// Actualiza la variable
void EnterName::updateCharacterIndex()
{
// Rellena de espacios
for (int i = 0; i < NAME_LENGHT; ++i)
// Rellena de espacios y marca como no usados
for (size_t i = 0; i < NAME_LENGHT; ++i)
{
character_index_[i] = 0;
position_has_been_used_[i] = false;
}
// Coloca los índices en funcion de los caracteres que forman el nombre
for (int i = 0; i < (int)name_.size(); ++i)
// Coloca los índices en función de los caracteres que forman el nombre
for (size_t i = 0; i < name_.size(); ++i)
{
character_index_[i] = findIndex(name_.at(i));
position_has_been_used_[i] = true;
}
}
// Encuentra el indice de un caracter en "character_list_"
int EnterName::findIndex(char character)
int EnterName::findIndex(char character) const
{
for (int i = 0; i < (int)character_list_.size(); ++i)
{
if (character == character_list_[i])
{
for (size_t i = 0; i < character_list_.size(); ++i)
if (character == character_list_.at(i))
return i;
}
}
return 0;
}
@@ -107,7 +107,19 @@ std::string EnterName::getName() const
}
// Obtiene la posición que se está editando
int EnterName::getPos() const
int EnterName::getPosition() const
{
return pos_;
return position_;
}
// Comprueba la posición y copia el caracter si es necesario
void EnterName::checkIfPositionHasBeenUsed()
{
auto used = position_has_been_used_[position_];
if (!used && position_ > 0)
character_index_[position_] = character_index_[position_ - 1];
position_has_been_used_[position_] = true;
updateName();
}

View File

@@ -2,7 +2,7 @@
#include <string>
constexpr int NAME_LENGHT = 8;
constexpr int NAME_LENGHT = 6;
/*
Un array, "characterList", contiene la lista de caracteres
@@ -16,20 +16,24 @@ constexpr int NAME_LENGHT = 8;
class EnterName
{
private:
std::string character_list_; // Lista de todos los caracteres permitidos
std::string name_; // Nombre introducido
int pos_; // Posición a editar del nombre
int num_characters_; // Cantidad de caracteres de la lista de caracteres
int character_index_[NAME_LENGHT]; // Indice de la lista para cada uno de los caracteres que forman el nombre
std::string character_list_; // Lista de todos los caracteres permitidos
std::string name_; // Nombre introducido
int position_; // Posición a editar del nombre
int num_characters_; // Cantidad de caracteres de la lista de caracteres
int character_index_[NAME_LENGHT]; // Indice de la lista para cada uno de los caracteres que forman el nombre
bool position_has_been_used_[NAME_LENGHT]; // Indica si en esa posición se ha puesto ya alguna letra. Se utiliza para replicar la letra anterior la primera vez
// Actualiza la variable
// Actualiza el nombre a partir de la lista de índices
void updateName();
// Actualiza la variable
void updateCharacterIndex();
// Encuentra el indice de un caracter en "characterList"
int findIndex(char character);
int findIndex(char character) const;
// Comprueba la posición y copia el caracter si es necesario
void checkIfPositionHasBeenUsed();
public:
// Constructor
@@ -42,10 +46,10 @@ public:
void init();
// Incrementa la posición
void incPos();
void incPosition();
// Decrementa la posición
void decPos();
void decPosition();
// Incrementa el índice
void incIndex();
@@ -57,5 +61,5 @@ public:
std::string getName() const;
// Obtiene la posición que se está editando
int getPos() const;
int getPosition() const;
};

View File

@@ -1,20 +1,6 @@
#include "explosions.h"
#include <utility> // for move
#include "animated_sprite.h" // for AnimatedSprite
class Texture; // lines 3-3
// Constructor
Explosions::Explosions()
{
textures_.clear();
explosions_.clear();
}
// Destructor
Explosions::~Explosions()
{
explosions_.clear();
}
#include "animated_sprite.h" // Para AnimatedSprite
class Texture; // lines 4-4
// Actualiza la lógica de la clase
void Explosions::update()
@@ -38,22 +24,17 @@ void Explosions::render()
}
// Añade texturas al objeto
void Explosions::addTexture(int size, std::shared_ptr<Texture> texture, std::vector<std::string> *animation)
void Explosions::addTexture(int size, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
{
ExplosionTexture temp;
temp.size = size;
temp.texture = texture;
temp.animation = animation;
textures_.push_back(temp);
textures_.emplace_back(ExplosionTexture(size, texture, animation));
}
// Añade una explosión
void Explosions::add(int x, int y, int size)
{
const int index = getIndexBySize(size);
auto sprite = std::make_unique<AnimatedSprite>(textures_[index].texture, "", textures_[index].animation);
sprite->setPos(x, y);
explosions_.push_back(std::move(sprite));
const auto index = getIndexBySize(size);
explosions_.emplace_back(std::make_unique<AnimatedSprite>(textures_[index].texture, textures_[index].animation));
explosions_.back()->setPos(x, y);
}
// Vacia el vector de elementos finalizados

View File

@@ -1,16 +1,20 @@
#pragma once
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
#include <vector> // for vector
class AnimatedSprite;
class Texture;
#include <memory> // Para unique_ptr, shared_ptr
#include <string> // Para string
#include <vector> // Para vector
#include "animated_sprite.h" // Para AnimatedSprite
class Texture; // lines 7-7
struct ExplosionTexture
{
std::shared_ptr<Texture> texture; // Textura para la explosión
std::vector<std::string> *animation; // Animación para la textura
int size; // Tamaño de la explosión
int size; // Tamaño de la explosión
std::shared_ptr<Texture> texture; // Textura para la explosión
std::vector<std::string> animation; // Animación para la textura
// Constructor
ExplosionTexture(int sz, std::shared_ptr<Texture> tex, const std::vector<std::string> &anim)
: size(sz), texture(tex), animation(anim) {}
};
// Clase explosions
@@ -29,10 +33,10 @@ private:
public:
// Constructor
Explosions();
Explosions() = default;
// Destructor
~Explosions();
~Explosions() = default;
// Actualiza la lógica de la clase
void update();
@@ -41,7 +45,7 @@ public:
void render();
// Añade texturas al objeto
void addTexture(int size, std::shared_ptr<Texture> texture, std::vector<std::string> *animation);
void addTexture(int size, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation);
// Añade una explosión
void add(int x, int y, int size);

View File

@@ -1,14 +1,14 @@
#include "fade.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND, SDL_BLENDMODE_NONE
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <stdlib.h> // for rand
#include <algorithm> // for min, max
#include "param.h" // for param
#include "utils.h" // for Param, ParamGame, ParamFade
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND, SDL_BLENDMODE_NONE
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <stdlib.h> // Para rand
#include <algorithm> // Para min, max
#include "param.h" // Para Param, param, ParamGame, ParamFade
#include "screen.h" // Para Screen
// Constructor
Fade::Fade(SDL_Renderer *renderer)
: renderer_(renderer)
Fade::Fade()
: renderer_(Screen::get()->getRenderer())
{
// Crea la textura donde dibujar el fade
backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);

View File

@@ -1,9 +1,9 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint8, Uint16
#include <vector> // for vector
#include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // para Uint8, Uint16
#include <vector> // para vector
// Tipos de fundido
enum class FadeType : Uint8
@@ -54,7 +54,7 @@ private:
public:
// Constructor
explicit Fade(SDL_Renderer *renderer);
Fade();
// Destructor
~Fade();

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +1,29 @@
#pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
#include <vector> // for vector
#include "balloon.h" // for Balloon
#include "player.h" // for Player
#include "utils.h" // for DemoKeys, Color, HiScoreEntry
class Asset;
class Background;
class BalloonFormations;
class Bullet;
class Explosions;
class Fade;
class Input;
class Item;
class Scoreboard;
class Screen;
class SmartSprite;
class Text;
class Texture;
enum class BulletType; // lines 26-26
struct JA_Music_t; // lines 27-27
struct JA_Sound_t; // lines 28-28
#include <SDL2/SDL_render.h> // Para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // Para Uint32, Uint8
#include <memory> // Para shared_ptr, unique_ptr
#include <string> // Para string
#include <vector> // Para vector
#include "manage_hiscore_table.h" // Para HiScoreEntry
#include "options.h" // Para Options, OptionsGame, options
#include "player.h" // Para Player
#include "utils.h" // Para Demo
class Asset; // lines 13-13
class Background; // lines 14-14
class BalloonManager;
class Bullet; // lines 15-15
class Fade; // lines 16-16
class Input; // lines 17-17
class Item; // lines 18-18
class PathSprite; // lines 19-19
class Scoreboard; // lines 20-20
class Screen; // lines 21-21
class SmartSprite; // lines 22-22
class Texture; // lines 23-23
enum class BulletType : Uint8; // lines 24-24
enum class ItemType; // lines 25-25
struct Path; // lines 26-26
// Modo demo
constexpr bool GAME_MODE_DEMO_OFF = false;
@@ -31,26 +31,6 @@ constexpr bool GAME_MODE_DEMO_ON = true;
// Cantidad de elementos a escribir en los ficheros de datos
constexpr int TOTAL_SCORE_DATA = 3;
constexpr int TOTAL_DEMO_DATA = 2000;
// Contadores
constexpr int STAGE_COUNTER = 200;
constexpr int HELP_COUNTER = 1000;
constexpr int GAME_COMPLETED_START_FADE = 500;
constexpr int GAME_COMPLETED_END = 700;
constexpr int GAME_OVER_COUNTER = 350;
// Porcentaje de aparición de los objetos
constexpr int ITEM_POINTS_1_DISK_ODDS = 10;
constexpr int ITEM_POINTS_2_GAVINA_ODDS = 6;
constexpr int ITEM_POINTS_3_PACMAR_ODDS = 3;
constexpr int ITEM_CLOCK_ODDS = 5;
constexpr int ITEM_COFFEE_ODDS = 5;
constexpr int ITEM_POWER_BALL_ODDS = 0;
constexpr int ITEM_COFFEE_MACHINE_ODDS = 4;
// Valores para las variables asociadas a los objetos
constexpr int TIME_STOPPED_COUNTER = 300;
/*
Esta clase gestiona un estado del programa. Se encarga de toda la parte en la
@@ -82,6 +62,31 @@ constexpr int TIME_STOPPED_COUNTER = 300;
class Game
{
private:
// Enum
enum class GameState
{
PLAYING,
COMPLETED,
GAME_OVER,
};
// Contadores
static constexpr int HELP_COUNTER_ = 1000;
static constexpr int GAME_COMPLETED_START_FADE_ = 500;
static constexpr int GAME_COMPLETED_END_ = 700;
static constexpr int GAME_OVER_COUNTER_ = 350;
static constexpr int TIME_STOPPED_COUNTER_ = 360;
// Porcentaje de aparición de los objetos
static constexpr int ITEM_POINTS_1_DISK_ODDS_ = 10;
static constexpr int ITEM_POINTS_2_GAVINA_ODDS_ = 6;
static constexpr int ITEM_POINTS_3_PACMAR_ODDS_ = 3;
static constexpr int ITEM_CLOCK_ODDS_ = 5;
static constexpr int ITEM_COFFEE_ODDS_ = 5;
static constexpr int ITEM_POWER_BALL_ODDS_ = 0;
static constexpr int ITEM_COFFEE_MACHINE_ODDS_ = 4;
// Estructuras
struct Helper
{
bool need_coffee; // Indica si se necesitan cafes
@@ -94,15 +99,19 @@ private:
int item_clock_odds; // Probabilidad de aparición del objeto
int item_coffee_odds; // Probabilidad de aparición del objeto
int item_coffee_machine_odds; // Probabilidad de aparición del objeto
};
struct Demo
{
bool enabled; // Indica si está activo el modo demo
bool recording; // Indica si está activado el modo para grabar la demo
int counter; // Contador para el modo demo
DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo
DemoKeys data_file[2][TOTAL_DEMO_DATA]; // Vector con diferentes sets de datos con los movimientos para la demo
// Constructor con valores predeterminados
Helper()
: need_coffee(false),
need_coffee_machine(false),
need_power_ball(false),
counter(HELP_COUNTER_),
item_disk_odds(ITEM_POINTS_1_DISK_ODDS_),
item_gavina_odds(ITEM_POINTS_2_GAVINA_ODDS_),
item_pacmar_odds(ITEM_POINTS_3_PACMAR_ODDS_),
item_clock_odds(ITEM_CLOCK_ODDS_),
item_coffee_odds(ITEM_COFFEE_ODDS_),
item_coffee_machine_odds(ITEM_COFFEE_MACHINE_ODDS_) {}
};
// Objetos y punteros
@@ -112,98 +121,52 @@ private:
Input *input_; // Manejador de entrada
Scoreboard *scoreboard_; // Objeto para dibujar el marcador
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::unique_ptr<Explosions> explosions_; // Objeto para dibujar explosiones
std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para gestionar las oleadas enemigas
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
SDL_Texture *canvas_; // Textura para dibujar la zona de juego
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
std::vector<std::shared_ptr<Balloon>> balloons_; // Vector con los globos
std::vector<std::unique_ptr<Bullet>> bullets_; // Vector con las balas
std::vector<std::unique_ptr<Item>> items_; // Vector con los items
std::vector<SmartSprite *> smart_sprites_; // Vector con los smartsprites
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
std::vector<std::unique_ptr<Bullet>> bullets_; // Vector con las balas
std::vector<std::unique_ptr<Item>> items_; // Vector con los items
std::vector<std::unique_ptr<SmartSprite>> smart_sprites_; // Vector con los smartsprites
std::vector<std::unique_ptr<PathSprite>> path_sprites_; // Vector con los smartsprites
std::shared_ptr<Texture> bullet_texture_; // Textura para las balas
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
std::vector<std::shared_ptr<Texture>> balloon_textures_; // Vector con las texturas de los globos
std::vector<std::shared_ptr<Texture>> explosions_textures_; // Vector con las texturas de las explosiones
std::vector<std::shared_ptr<Texture>> player1_textures_; // Vector con las texturas del jugador
std::vector<std::shared_ptr<Texture>> player2_textures_; // Vector con las texturas del jugador
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures_; // Vector con todas las texturas de los jugadores;
std::shared_ptr<Texture> game_text_texture_; // Textura para los sprites con textos
std::vector<std::shared_ptr<Texture>> game_text_textures_; // Vector con las texturas para los sprites con textos
std::vector<std::vector<std::string> *> item_animations_; // Vector con las animaciones de los items
std::vector<std::vector<std::string> *> player_animations_; // Vector con las animaciones del jugador
std::vector<std::vector<std::string> *> balloon_animations_; // Vector con las animaciones de los globos
std::vector<std::vector<std::string> *> explosions_animations_; // Vector con las animaciones de las explosiones
std::vector<std::vector<std::string>> item_animations_; // Vector con las animaciones de los items
std::vector<std::vector<std::string>> player_animations_; // Vector con las animaciones del jugador
std::unique_ptr<Text> text_; // Fuente para los textos del juego
std::unique_ptr<Text> text_big_; // Fuente de texto grande
std::unique_ptr<Text> text_nokia2_; // Otra fuente de texto para mensajes
std::unique_ptr<Text> text_nokia2_big_; // Y la versión en grande
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::shared_ptr<SmartSprite> p1000_sprite_; // Sprite con el texto 1.000
std::shared_ptr<SmartSprite> p2500_sprite_; // Sprite con el texto 2.500
std::shared_ptr<SmartSprite> p5000_sprite_; // Sprite con el texto 5.000
JA_Sound_t *balloon_sound_; // Sonido para la explosión del globo
JA_Sound_t *bullet_sound_; // Sonido para los disparos
JA_Sound_t *player_collision_sound_; // Sonido para la colisión del jugador con un enemigo
JA_Sound_t *hi_score_sound_; // Sonido para cuando se alcanza la máxima puntuación
JA_Sound_t *item_drop_sound_; // Sonido para cuando se genera un item
JA_Sound_t *item_pick_up_sound_; // Sonido para cuando se recoge un item
JA_Sound_t *coffee_out_sound_; // Sonido para cuando el jugador pierde el café al recibir un impacto
JA_Sound_t *stage_change_sound_; // Sonido para cuando se cambia de fase
JA_Sound_t *bubble1_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble2_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble3_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble4_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *clock_sound_; // Sonido para cuando se detiene el tiempo con el item reloj
JA_Sound_t *power_ball_sound_; // Sonido para cuando se explota una Power Ball
JA_Sound_t *coffee_machine_sound_; // Sonido para cuando la máquina de café toca el suelo
JA_Music_t *music_; // Musica de fondo
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados
// Variables
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
bool hi_score_achieved_; // Indica si se ha superado la puntuación máxima
HiScoreEntry hi_score_; // Máxima puntuación y nombre de quien la ostenta
int current_stage_; // Indica la fase actual
int stage_bitmap_counter_; // Contador para el tiempo visible del texto de Stage
float stage_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto
float get_ready_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto
int game_over_counter_; // Contador para el estado de fin de partida
int menace_current_; // Nivel de amenaza actual
int menace_threshold_; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
bool time_stopped_; // Indica si el tiempo está detenido
int time_stopped_counter_; // Temporizador para llevar la cuenta del tiempo detenido
int counter_; // Contador para el juego
int balloons_popped_; // Lleva la cuenta de los globos explotados
int last_ballon_deploy_; // Guarda cual ha sido la última formación desplegada para no repetir;
int balloon_deploy_counter_; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero
float balloon_speed_; // Velocidad a la que se mueven los enemigos
float default_balloon_speed_; // Velocidad base de los enemigos, sin incrementar
Helper helper_; // Variable para gestionar las ayudas
bool power_ball_enabled_; // Indica si hay una powerball ya activa
int power_ball_counter_; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
bool coffee_machine_enabled_; // Indica si hay una máquina de café en el terreno de juego
bool game_completed_; // Indica si se ha completado la partida, llegando al final de la ultima pantalla
int game_completed_counter_; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos
GameDifficulty difficulty_; // Dificultad del juego
float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
Color difficulty_color_; // Color asociado a la dificultad
int last_stage_reached_; // Contiene el número de la última pantalla que se ha alcanzado
Demo demo_; // Variable con todas las variables relacionadas con el modo demo
int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
bool paused_; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade)
int current_power_; // Poder actual almacenado para completar la fase
HiScoreEntry hi_score_ = HiScoreEntry(
options.game.hi_score_table[0].name,
options.game.hi_score_table[0].score); // Máxima puntuación y nombre de quien la ostenta
Demo demo_; // Variable con todas las variables relacionadas con el modo demo
GameDifficulty difficulty_ = options.game.difficulty; // Dificultad del juego
Helper helper_; // Variable para gestionar las ayudas
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
bool coffee_machine_enabled_ = false; // Indica si hay una máquina de café en el terreno de juego
bool hi_score_achieved_ = false; // Indica si se ha superado la puntuación máxima
bool paused_ = false; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade)
float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
int counter_ = 0; // Contador para el juego
int game_completed_counter_ = 0; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos
int game_over_counter_ = GAME_OVER_COUNTER_; // Contador para el estado de fin de partida
int time_stopped_counter_ = 0; // Temporizador para llevar la cuenta del tiempo detenido
int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
int menace_current_ = 0; // Nivel de amenaza actual
int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
GameState state_ = GameState::PLAYING; // Estado
#ifdef DEBUG
bool auto_pop_balloons_; // Si es true, incrementa automaticamente los globos explotados
bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
#endif
// Actualiza el juego
@@ -215,26 +178,8 @@ private:
// Comprueba los eventos que hay en cola
void checkEvents();
// Inicializa las variables necesarias para la sección 'Game'
void init(int player_id);
// Carga los recursos necesarios para la sección 'Game'
void loadMedia();
// Libera los recursos previamente cargados
void unloadMedia();
// Carga el fichero de datos para la demo
bool loadDemoFile(const std::string &file_path, DemoKeys (*data_file)[TOTAL_DEMO_DATA]);
#ifdef RECORDING
// Guarda el fichero de datos para la demo
bool saveDemoFile(const std::string &file_path);
#endif
// Crea una formación de enemigos
void deployBalloonFormation();
// Aumenta el poder de la fase
void increaseStageCurrentPower(int power);
// Asigna texturas y animaciones
void setResources();
// Actualiza el valor de HiScore en caso necesario
void updateHiScore();
@@ -249,43 +194,10 @@ private:
void updateStage();
// Actualiza el estado de fin de la partida
void updateGameOver();
void updateGameOverState();
// Actualiza los globos
void updateBalloons();
// Pinta en pantalla todos los globos activos
void renderBalloons();
// Crea un globo nuevo en el vector de globos
std::shared_ptr<Balloon> createBalloon(float x, int y, int kind, float velx, float speed, int stopped_counter);
// Crea una PowerBall
void createPowerBall();
// Establece la velocidad de los globos
void setBalloonSpeed(float speed);
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
void updateBalloonSpeed();
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
void popBalloon(std::shared_ptr<Balloon> balloon);
// Explosiona un globo. Lo destruye
void destroyBalloon(std::shared_ptr<Balloon> &balloon);
// Destruye todos los globos
void destroyAllBalloons();
// Detiene todos los globos
void stopAllBalloons(int time);
// Pone en marcha todos los globos
void startAllBalloons();
// Vacia el vector de globos
void freeBalloons();
// Destruye todos los items
void destroyAllItems();
// Comprueba la colisión entre el jugador y los globos activos
bool checkPlayerBalloonCollision(std::shared_ptr<Player> &player);
@@ -315,67 +227,52 @@ private:
void renderItems();
// Devuelve un item en función del azar
int dropItem();
ItemType dropItem();
// Crea un objeto item
void createItem(int kind, float x, float y);
void createItem(ItemType type, float x, float y);
// Vacia el vector de items
void freeItems();
// Crea un objeto SmartSprite
void createItemScoreSprite(int x, int y, std::shared_ptr<SmartSprite> sprite);
// Crea un objeto PathSprite
void createItemText(int x, std::shared_ptr<Texture> texture);
// Crea un objeto PathSprite
void createMessage(const std::vector<Path> &paths, std::shared_ptr<Texture> texture);
// Vacia el vector de smartsprites
void freeSmartSprites();
// Crea un SmartSprite para arrojar el item café al recibir un impacto
// Vacia el vector de pathsprites
void freePathSprites();
// Crea un SpriteSmart para arrojar el item café al recibir un impacto
void throwCoffee(int x, int y);
// Actualiza los SmartSprites
// Actualiza los SpriteSmarts
void updateSmartSprites();
// Pinta los SmartSprites activos
// Pinta los SpriteSmarts activos
void renderSmartSprites();
// Actualiza los PathSprites
void updatePathSprites();
// Pinta los PathSprites activos
void renderPathSprites();
// Acciones a realizar cuando el jugador muere
void killPlayer(std::shared_ptr<Player> &player);
// Calcula y establece el valor de amenaza en funcion de los globos activos
void evaluateAndSetMenace();
// Obtiene el valor de la variable
int getMenace() const;
// Establece el valor de la variable
void setTimeStopped(bool value);
// Obtiene el valor de la variable
bool isTimeStopped() const;
// Establece el valor de la variable
void setTimeStoppedCounter(int value);
// Incrementa el valor de la variable
void incTimeStoppedCounter(int value);
// Actualiza la variable EnemyDeployCounter
void updateBalloonDeployCounter();
// Actualiza y comprueba el valor de la variable
void updateTimeStoppedCounter();
// Gestiona el nivel de amenaza
void updateMenace();
void updateTimeStopped();
// Actualiza el fondo
void updateBackground();
// Gestiona la entrada durante el juego
void checkInput();
// Pinta diferentes mensajes en la pantalla
void renderMessages();
// Inicializa las variables que contienen puntos de ruta para mover objetos
void initPaths();
// Habilita el efecto del item de detener el tiempo
void enableTimeStopItem();
@@ -383,18 +280,6 @@ private:
// Deshabilita el efecto del item de detener el tiempo
void disableTimeStopItem();
// Indica si se puede crear una powerball
bool canPowerBallBeCreated();
// Calcula el poder actual de los globos en pantalla
int calculateScreenPower();
// Inicializa las variables que contienen puntos de ruta para mover objetos
void initPaths();
// Actualiza el tramo final de juego, una vez completado
void updateGameCompleted();
// Actualiza las variables de ayuda
void updateHelper();
@@ -407,12 +292,6 @@ private:
// Comprueba si todos los jugadores han terminado de jugar
bool allPlayersAreNotPlaying();
// Carga las animaciones
void loadAnimations(std::string file_path, std::vector<std::string> *buffer);
// Elimina todos los objetos contenidos en vectores
void deleteAllVectorObjects();
// Recarga las texturas
void reloadTextures();
@@ -443,9 +322,90 @@ private:
// Obtiene un controlador a partir del "id" del jugador
int getController(int playerId);
// Gestiona la entrada durante el juego
void checkInput();
// Verifica si alguno de los controladores ha solicitado una pausa y actualiza el estado de pausa del juego.
void checkPauseInput();
// Gestiona las entradas de los jugadores en el modo demo, incluyendo movimientos y disparos automáticos.
void handleDemoMode();
// Procesa las entradas para un jugador específico durante el modo demo.
void handleDemoPlayerInput(const std::shared_ptr<Player> &player, int index);
// Maneja el disparo de un jugador, incluyendo la creación de balas y la gestión del tiempo de espera entre disparos.
void handleFireInput(const std::shared_ptr<Player> &player, BulletType bulletType);
// Gestiona las entradas de todos los jugadores en el modo normal (fuera del modo demo).
void handlePlayersInput();
// Maneja las entradas de movimiento y disparo para un jugador en modo normal.
void handleNormalPlayerInput(const std::shared_ptr<Player> &player);
// Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado.
void handleFireInputs(const std::shared_ptr<Player> &player, bool autofire, int controllerIndex);
// Maneja la continuación del jugador cuando no está jugando, permitiendo que continúe si se pulsa el botón de inicio.
void handlePlayerContinue(const std::shared_ptr<Player> &player);
// Procesa las entradas para la introducción del nombre del jugador.
void handleNameInput(const std::shared_ptr<Player> &player);
// Inicializa las variables para el modo DEMO
void initDemo(int player_id);
// Calcula el poder total necesario para completar el juego
void setTotalPower();
// Inicializa el marcador
void initScoreboard();
// Inicializa las opciones relacionadas con la dificultad
void initDifficultyVars();
// Inicializa los jugadores
void initPlayers(int player_id);
// Pausa la música
void pauseMusic();
// Reanuda la música
void resumeMusic();
// Detiene la música
void stopMusic();
// Actualiza las variables durante el modo demo
void updateDemo();
#ifdef RECORDING
// Actualiza las variables durante el modo de grabación
void updateRecording();
#endif
// Actualiza las variables durante el transcurso normal del juego
void updateGame();
// Gestiona eventos para el estado del final del juego
void updateCompletedState();
// Comprueba el estado del juego
void checkState();
// Vacía los vectores de elementos deshabilitados
void cleanVectors();
// Gestiona el nivel de amenaza
void updateMenace();
// Calcula y establece el valor de amenaza en funcion de los globos activos
void evaluateAndSetMenace();
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
void checkAndUpdateBalloonSpeed();
public:
// Constructor
Game(int playerID, int current_stage, bool demo, JA_Music_t *music);
Game(int playerID, int current_stage, bool demo);
// Destructor
~Game();

View File

@@ -1,54 +1,38 @@
#include "game_logo.h"
#include <SDL2/SDL_render.h> // for SDL_FLIP_HORIZONTAL
#include <algorithm> // for max
#include "animated_sprite.h" // for AnimatedSprite
#include "asset.h" // for Asset
#include "jail_audio.h" // for JA_DeleteSound, JA_LoadSound, JA_PlaySound
#include "param.h" // for param
#include "screen.h" // for Screen
#include "smart_sprite.h" // for SmartSprite
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include "utils.h" // for Param, ParamGame, ParamTitle
#include <SDL2/SDL_render.h> // Para SDL_FLIP_HORIZONTAL
#include <algorithm> // Para max
#include "animated_sprite.h" // Para AnimatedSprite
#include "jail_audio.h" // Para JA_PlaySound
#include "param.h" // Para Param, param, ParamGame, ParamTitle
#include "resource.h" // Para Resource
#include "smart_sprite.h" // Para SmartSprite
#include "sprite.h" // Para Sprite
#include "texture.h" // Para Texture
// Constructor
GameLogo::GameLogo(int x, int y)
: dust_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_dust.png"))),
coffee_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_coffee.png"))),
crisis_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_crisis.png"))),
arcade_edition_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_arcade_edition.png"))),
dust_left_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Asset::get()->get("title_dust.ani"))),
dust_right_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Asset::get()->get("title_dust.ani"))),
: dust_texture_(Resource::get()->getTexture("title_dust.png")),
coffee_texture_(Resource::get()->getTexture("title_coffee.png")),
crisis_texture_(Resource::get()->getTexture("title_crisis.png")),
arcade_edition_texture_(Resource::get()->getTexture("title_arcade_edition.png")),
dust_left_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Resource::get()->getAnimation("title_dust.ani"))),
dust_right_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Resource::get()->getAnimation("title_dust.ani"))),
coffee_sprite_(std::make_unique<SmartSprite>(coffee_texture_)),
crisis_sprite_(std::make_unique<SmartSprite>(crisis_texture_)),
arcade_edition_sprite_(std::make_unique<Sprite>((param.game.width - arcade_edition_texture_->getWidth()) / 2, param.title.arcade_edition_position, arcade_edition_texture_->getWidth(), arcade_edition_texture_->getHeight(), arcade_edition_texture_)),
crash_sound_(JA_LoadSound(Asset::get()->get("title.wav").c_str())),
arcade_edition_sprite_(std::make_unique<Sprite>(arcade_edition_texture_, (param.game.width - arcade_edition_texture_->getWidth()) / 2, param.title.arcade_edition_position, arcade_edition_texture_->getWidth(), arcade_edition_texture_->getHeight())),
x_(x),
y_(y)
{
// Inicializa las variables
init();
}
// Destructor
GameLogo::~GameLogo()
{
JA_DeleteSound(crash_sound_);
}
y_(y) { }
// Inicializa las variables
void GameLogo::init()
{
const auto xp = x_ - coffee_sprite_->getWidth() / 2;
const auto xp = x_ - coffee_texture_->getWidth() / 2;
const auto desp = getInitialVerticalDesp();
// Variables
status_ = Status::DISABLED;
coffee_crisis_status_ = Status::DISABLED;
arcade_edition_status_ = Status::DISABLED;
shake_.desp = 1;
shake_.delay = 2;
shake_.lenght = 8;
@@ -56,8 +40,9 @@ void GameLogo::init()
shake_.counter = shake_.delay;
shake_.origin = xp;
zoom_ = 3.0f;
// Inicializa el bitmap de 'Coffee'
coffee_sprite_->init();
coffee_sprite_->setPosX(xp);
coffee_sprite_->setPosY(y_ - coffee_texture_->getHeight() - desp);
coffee_sprite_->setWidth(coffee_texture_->getWidth());
@@ -73,7 +58,6 @@ void GameLogo::init()
coffee_sprite_->setDestY(y_ - coffee_texture_->getHeight());
// Inicializa el bitmap de 'Crisis'
crisis_sprite_->init();
crisis_sprite_->setPosX(xp + 15);
crisis_sprite_->setPosY(y_ + desp);
crisis_sprite_->setWidth(crisis_texture_->getWidth());
@@ -102,6 +86,9 @@ void GameLogo::init()
dust_left_sprite_->setPosY(y_);
dust_left_sprite_->setWidth(16);
dust_left_sprite_->setHeight(16);
// Inicializa el bitmap de 'Arcade Edition'
arcade_edition_sprite_->setZoom(zoom_);
}
// Pinta la clase en pantalla
@@ -111,7 +98,7 @@ void GameLogo::render()
coffee_sprite_->render();
crisis_sprite_->render();
if (status_ == Status::FINISHED)
if (arcade_edition_status_ != Status::DISABLED)
{
arcade_edition_sprite_->render();
}
@@ -124,22 +111,27 @@ void GameLogo::render()
// Actualiza la lógica de la clase
void GameLogo::update()
{
if (status_ == Status::MOVING)
switch (coffee_crisis_status_)
{
case Status::MOVING:
{
coffee_sprite_->update();
crisis_sprite_->update();
// Si los objetos han llegado a su destino, cambiamos de Sección
// Si los objetos han llegado a su destino, cambia el estado
if (coffee_sprite_->hasFinished() && crisis_sprite_->hasFinished())
{
status_ = Status::SHAKING;
coffee_crisis_status_ = Status::SHAKING;
arcade_edition_status_ = Status::MOVING;
// Reproduce el efecto sonoro
JA_PlaySound(crash_sound_);
JA_PlaySound(Resource::get()->getSound("title.wav"));
}
break;
}
else if (status_ == Status::SHAKING)
case Status::SHAKING:
{
// Agita el logo
if (shake_.remaining > 0)
@@ -161,17 +153,43 @@ void GameLogo::update()
{
coffee_sprite_->setPosX(shake_.origin);
crisis_sprite_->setPosX(shake_.origin + 15);
status_ = Status::FINISHED;
coffee_crisis_status_ = Status::FINISHED;
}
dust_right_sprite_->update();
dust_left_sprite_->update();
break;
}
else if (status_ == Status::FINISHED)
case Status::FINISHED:
{
dust_right_sprite_->update();
dust_left_sprite_->update();
break;
}
default:
break;
}
switch (arcade_edition_status_)
{
case Status::MOVING:
{
zoom_ -= 0.1f;
arcade_edition_sprite_->setZoom(zoom_);
if (zoom_ <= 1.0f)
{
arcade_edition_status_ = Status::FINISHED;
zoom_ = 1.0f;
}
break;
}
default:
break;
}
}
@@ -179,13 +197,13 @@ void GameLogo::update()
void GameLogo::enable()
{
init();
status_ = Status::MOVING;
coffee_crisis_status_ = Status::MOVING;
}
// Indica si ha terminado la animación
bool GameLogo::hasFinished() const
{
return status_ == Status::FINISHED;
return coffee_crisis_status_ == Status::FINISHED && arcade_edition_status_ == Status::FINISHED;
}
// Recarga las texturas
@@ -194,6 +212,7 @@ void GameLogo::reLoad()
dust_texture_->reLoad();
coffee_texture_->reLoad();
crisis_texture_->reLoad();
arcade_edition_texture_->reLoad();
}
// Calcula el desplazamiento vertical inicial

View File

@@ -1,11 +1,10 @@
#pragma once
#include <memory> // for unique_ptr, shared_ptr
class AnimatedSprite;
class SmartSprite;
class Sprite;
class Texture;
struct JA_Sound_t; // lines 10-10
#include <memory> // Para unique_ptr, shared_ptr
#include "animated_sprite.h" // Para AnimatedSprite
#include "smart_sprite.h" // Para SmartSprite
#include "sprite.h" // Para Sprite
class Texture; // lines 7-7
// Clase GameLogo
class GameLogo
@@ -43,14 +42,14 @@ private:
std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite con los graficos de "Arcade Edition"
JA_Sound_t *crash_sound_; // Sonido con el impacto del título
// Variables
int x_; // Posición donde dibujar el logo
int y_; // Posición donde dibujar el logo
int x_; // Posición donde dibujar el logo
int y_; // Posición donde dibujar el logo
float zoom_; // Zoom aplicado al texto "ARCADE EDITION"
Status status_; // Estado en el que se encuentra la clase
Shake shake_; // Estructura para generar el efecto de agitación
Status coffee_crisis_status_ = Status::DISABLED; // Estado en el que se encuentra el texto "COFFEE CRISIS"
Status arcade_edition_status_ = Status::DISABLED; // Estado en el que se encuentra el texto "ARCADE_EDITION"
Shake shake_; // Estructura para generar el efecto de agitación
// Inicializa las variables
void init();
@@ -63,7 +62,7 @@ public:
GameLogo(int x, int y);
// Destructor
~GameLogo();
~GameLogo() = default;
// Pinta la clase en pantalla
void render();

View File

@@ -1,41 +1,42 @@
#include "global_inputs.h"
#include <string> // for basic_string, operator+
#include "input.h" // for Input, inputs_e, INPUT_DO_NOT_ALLOW_REPEAT
#include "jail_audio.h" // for JA_EnableMusic, JA_EnableSound
#include "lang.h" // for getText
#include "options.h" // for options
#include "on_screen_help.h"
#include "screen.h" // for Screen
#include "section.h" // for SectionOptions, name, SectionName, options
#include "utils.h" // for OptionsAudio, Options, OptionsMusic, boolToOnOff
#include <string> // Para operator+, string
#include "input.h" // Para Input, InputType, INPUT_DO_NOT_ALLOW_REPEAT
#include "asset.h"
#include "jail_audio.h" // Para JA_EnableMusic, JA_EnableSound
#include "lang.h" // Para getText
#include "notifier.h" // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp
#include "options.h" // Para Options, OptionsAudio, options, OptionsM...
#include "section.h" // Para Name, Options, name, options
#include "utils.h" // Para boolToOnOff, stringInVector
#include "screen.h"
namespace globalInputs
{
// Variables
std::vector<int> service_pressed_counter;
// Inicializa variables
void init()
{
const auto num_inputs = Input::get()->getNumControllers() + 1;
service_pressed_counter.reserve(num_inputs);
for (int i = 0; i < num_inputs; ++i)
{
service_pressed_counter.push_back(0);
}
}
int service_pressed_counter = 0;
bool service_pressed = false;
// Termina
void quit(section::Options code)
{
if (Screen::get()->notificationsAreActive())
const std::string exit_code = "QUIT";
auto code_found = stringInVector(Notifier::get()->getCodes(), exit_code);
if (code_found)
{
// Si la notificación de salir está activa, cambia de sección
section::name = section::Name::QUIT;
section::options = code;
}
else
{
Screen::get()->showNotification(lang::getText(94));
// Si la notificación de salir no está activa, muestra la notificación
#ifdef ARCADE
const int index = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94;
Notifier::get()->showText({lang::getText(index), std::string()}, -1, exit_code);
#else
Notifier::get()->showText({lang::getText(94), std::string()}, -1, exit_code);
#endif
}
}
@@ -43,95 +44,225 @@ namespace globalInputs
void reset()
{
section::name = section::Name::INIT;
Screen::get()->showNotification("Reset");
Notifier::get()->showText({"Reset"});
}
// Activa o desactiva el audio
void switchAudio()
void toggleAudio()
{
options.audio.sound.enabled = options.audio.music.enabled = !options.audio.music.enabled;
JA_EnableMusic(options.audio.music.enabled);
JA_EnableSound(options.audio.sound.enabled);
Screen::get()->showNotification("Audio " + boolToOnOff(options.audio.music.enabled));
options.audio.enabled = !options.audio.enabled;
if (options.audio.enabled)
{
JA_SetMusicVolume(to_JA_volume(options.audio.music.volume));
JA_SetSoundVolume(to_JA_volume(options.audio.sound.volume));
}
else
{
JA_SetMusicVolume(0);
JA_SetSoundVolume(0);
}
Notifier::get()->showText({"Audio " + boolToOnOff(options.audio.enabled)});
}
// Obtiene una fichero a partir de un lang::Code
std::string getLangFile(lang::Code code)
{
switch (code)
{
case lang::Code::ba_BA:
return Asset::get()->get("ba_BA.txt");
break;
case lang::Code::es_ES:
return Asset::get()->get("es_ES.txt");
break;
default:
return Asset::get()->get("en_UK.txt");
break;
}
}
// Obtiene una cadena a partir de un lang::Code
std::string getLangName(lang::Code code)
{
switch (code)
{
case lang::Code::ba_BA:
return "ba_BA";
break;
case lang::Code::es_ES:
return "es_ES";
break;
default:
return "en_UK";
break;
}
}
// Cambia el idioma
void changeLang()
{
options.game.language = lang::change(options.game.language);
lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language)));
section::name = section::Name::INIT;
section::options = section::Options::RELOAD;
Notifier::get()->showText({getLangName(options.game.language)});
}
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
void check()
{
// Comprueba si se sale con el teclado
if (Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
// Teclado
{
quit(section::Options::QUIT_NORMAL);
return;
}
// Comprueba si se va a resetear el juego
else if (Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{
reset();
return;
}
else if (Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{
switchAudio();
return;
}
else if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{
service_pressed_counter[0]++;
if (service_pressed_counter[0] >= 3000)
#ifndef ARCADE
// Comprueba el teclado para cambiar entre pantalla completa y ventana
if (Input::get()->checkInput(InputType::WINDOW_FULLSCREEN, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
OnScreenHelp::get()->toggleState();
service_pressed_counter[0] = 0;
}
return;
}
else
{
service_pressed_counter[0] = 0;
}
for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{
// Comprueba si se sale con el mando
if (Input::get()->checkModInput(InputType::SERVICE, InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{
quit(section::Options::QUIT_SHUTDOWN);
Screen::get()->toggleVideoMode();
const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen";
Notifier::get()->showText({mode + " mode"});
return;
}
// Comprueba si se va a resetear el juego
else if (Input::get()->checkModInput(InputType::SERVICE, InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
// Comprueba el teclado para decrementar el tamaño de la ventana
if (Input::get()->checkInput(InputType::WINDOW_DEC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->decWindowSize();
const std::string size = std::to_string(options.video.window.size);
Notifier::get()->showText({"Window size x" + size});
return;
}
// Comprueba el teclado para incrementar el tamaño de la ventana
if (Input::get()->checkInput(InputType::WINDOW_INC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->incWindowSize();
const std::string size = std::to_string(options.video.window.size);
Notifier::get()->showText({"Window size x" + size});
return;
}
#endif
// Salir
if (Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
quit(section::Options::QUIT_WITH_KEYBOARD);
return;
}
// Reset
if (Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
reset();
return;
}
// Comprueba si se va a activar o desactivar el audio
else if (Input::get()->checkModInput(InputType::SERVICE, InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
// Audio
if (Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
switchAudio();
toggleAudio();
return;
}
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
// Idioma
if (Input::get()->checkInput(InputType::CHANGE_LANG, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
service_pressed_counter[i + 1]++;
changeLang();
return;
}
if (service_pressed_counter[i + 1] >= 3000)
// Shaders
if (Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->toggleShaders();
return;
}
#ifdef DEBUG
// Comprueba el teclado para mostrar la información de debug
if (Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->toggleDebugInfo();
return;
}
#endif
// OnScreenHelp
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
service_pressed = true;
return;
}
}
// Mandos
{
for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{
// Salir
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
OnScreenHelp::get()->toggleState();
service_pressed_counter[i + 1] = 0;
quit(section::Options::QUIT_WITH_CONTROLLER);
return;
}
// Reset
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
reset();
return;
}
// Audio
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
toggleAudio();
return;
}
// Shaders
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
Screen::get()->toggleShaders();
return;
}
#ifdef DEBUG
// Debug Info
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
Screen::get()->toggleDebugInfo();
return;
}
#endif
// OnScreenHelp
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
service_pressed = true;
return;
}
return;
}
else
{
service_pressed_counter[i + 1] = 0;
}
}
}
// Actualiza variables
void update()
{
if (service_pressed)
{
++service_pressed_counter;
if (service_pressed_counter >= 200)
{
OnScreenHelp::get()->toggleState();
service_pressed_counter = 0;
}
}
else
{
service_pressed_counter = 0;
}
service_pressed = false;
}
}

View File

@@ -1,11 +1,12 @@
#include <vector>
namespace globalInputs
{
extern std::vector<int> service_pressed_counter;
// Inicializa variables
void init();
extern int service_pressed_counter;
extern bool service_pressed;
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
void check();
// Actualiza variables
void update();
}

View File

@@ -1,51 +1,43 @@
#include "hiscore_table.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
#include <algorithm> // for max
#include <vector> // for vector
#include "asset.h" // for Asset
#include "background.h" // for Background
#include "fade.h" // for Fade, FadeMode, FadeType
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_GetMusicState, JA_Music_state
#include "lang.h" // for getText
#include "options.h" // for options
#include "param.h" // for param
#include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options
#include "text.h" // for Text, TEXT_CENTER, TEXT_SHADOW, TEXT...
#include "utils.h" // for Param, ParamGame, Color, HiScoreEntry
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <algorithm> // Para max
#include <vector> // Para vector
#include "background.h" // Para Background
#include "fade.h" // Para Fade, FadeMode, FadeType
#include "global_inputs.h" // Para check
#include "input.h" // Para Input
#include "jail_audio.h" // Para JA_GetMusicState, JA_Music_state
#include "lang.h" // Para getText
#include "manage_hiscore_table.h" // Para HiScoreEntry
#include "options.h" // Para Options, OptionsGame, options
#include "param.h" // Para Param, param, ParamGame, ParamFade
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, name, Options, options
#include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW
#include "utils.h" // Para Color, Zone, fade_color, orange_color
// Constructor
HiScoreTable::HiScoreTable(JA_Music_t *music)
: music_(music)
HiScoreTable::HiScoreTable()
: renderer_(Screen::get()->getRenderer()),
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
fade_(std::make_unique<Fade>()),
background_(std::make_unique<Background>()),
text_(Resource::get()->getText("smb2")),
counter_(0),
ticks_(0),
view_area_({0, 0, param.game.width, param.game.height}),
fade_mode_(FadeMode::IN)
{
// Copia punteros
renderer_ = Screen::get()->getRenderer();
// Objetos
fade_ = std::make_unique<Fade>(renderer_);
background_ = std::make_unique<Background>(renderer_);
text_ = std::make_unique<Text>(Asset::get()->get("smb2.gif"), Asset::get()->get("smb2.txt"), renderer_);
// Crea un backbuffer para el renderizador
backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
// Inicializa variables
// Inicializa el resto de variables
section::name = section::Name::HI_SCORE_TABLE;
ticks_ = 0;
ticks_speed_ = 15;
counter_ = 0;
counter_end_ = 800;
view_area_ = {0, 0, param.game.width, param.game.height};
fade_mode_ = FadeMode::IN;
// Inicializa objetos
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
background_->setPos(param.game.game_area.rect);
background_->setCloudsSpeed(-0.1f);
background_->setGradientNumber(1);
@@ -69,8 +61,9 @@ HiScoreTable::~HiScoreTable()
// Actualiza las variables
void HiScoreTable::update()
{
// Actualiza las variables
if (SDL_GetTicks() - ticks_ > ticks_speed_)
constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();
@@ -78,12 +71,15 @@ void HiScoreTable::update()
// Mantiene la música sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{
JA_PlayMusic(music_);
JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
}
// Actualiza el objeto screen
Screen::get()->update();
// Actualiza las variables de globalInputs
globalInputs::update();
// Actualiza el fondo
background_->update();
@@ -95,11 +91,11 @@ void HiScoreTable::update()
if (counter_ == 150)
{
background_->setColor({0, 0, 0});
background_->setColor(Color(0, 0, 0));
background_->setAlpha(96);
}
if (counter_ == counter_end_)
if (counter_ == COUNTER_END_)
{
fade_->activate();
}
@@ -188,6 +184,7 @@ void HiScoreTable::checkEvents()
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
@@ -214,9 +211,6 @@ void HiScoreTable::checkInput()
return;
}
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check();
}

View File

@@ -1,15 +1,14 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint16, Uint32, Uint8
#include <memory> // for unique_ptr
#include <string> // for string
#include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // para Uint16, Uint32, Uint8
#include <memory> // para unique_ptr
#include <string> // para string
class Background; // lines 8-8
class Fade; // lines 9-9
class Text; // lines 10-10
enum class FadeMode : Uint8; // lines 11-11
struct JA_Music_t; // lines 12-12
/*
Esta clase gestiona un estado del programa. Se encarga de mostrar la tabla con las puntuaciones
@@ -25,20 +24,20 @@ struct JA_Music_t; // lines 12-12
class HiScoreTable
{
private:
// Constantes
static constexpr Uint16 COUNTER_END_ = 800; // Valor final para el contador
// Objetos y punteros
SDL_Renderer *renderer_; // El renderizador de la ventana
SDL_Texture *backbuffer_; // Textura para usar como backbuffer
JA_Music_t *music_; // Musica de fondo
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::unique_ptr<Text> text_; // Objeto para escribir texto
std::shared_ptr<Text> text_; // Objeto para escribir texto
// Variables
Uint16 counter_; // Contador
Uint16 counter_end_; // Valor final para el contador
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla
FadeMode fade_mode_; // Modo de fade a utilizar
@@ -68,7 +67,7 @@ private:
public:
// Constructor
explicit HiScoreTable(JA_Music_t *music);
HiScoreTable();
// Destructor
~HiScoreTable();

View File

@@ -1,9 +1,13 @@
#include "input.h"
#include <SDL2/SDL.h> // for SDL_INIT_GAMECONTROLLER, SDL_InitSubS...
#include <SDL2/SDL_error.h> // for SDL_GetError
#include <SDL2/SDL_events.h> // for SDL_ENABLE
#include <SDL2/SDL_keyboard.h> // for SDL_GetKeyboardState
#include <iostream> // for basic_ostream, operator<<, cout, basi...
#include <SDL2/SDL.h> // Para SDL_INIT_GAMECONTROLLER, SDL_InitSubS...
#include <SDL2/SDL_error.h> // Para SDL_GetError
#include <SDL2/SDL_events.h> // Para SDL_ENABLE
#include <SDL2/SDL_keyboard.h> // Para SDL_GetKeyboardState
#include <algorithm> // Para find
#include <iostream> // Para basic_ostream, operator<<, cout, endl
#include <iterator> // Para distance
#include <unordered_map> // Para unordered_map, operator==, _Node_cons...
#include <utility> // Para pair
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Input *Input::input_ = nullptr;
@@ -28,49 +32,23 @@ Input *Input::get()
// Constructor
Input::Input(const std::string &game_controller_db_path)
: game_controller_db_path_(game_controller_db_path),
enabled_(true)
: game_controller_db_path_(game_controller_db_path)
{
// Busca si hay mandos conectados
discoverGameControllers();
// Inicializa las vectores
KeyBindings kb;
kb.scancode = 0;
kb.active = false;
key_bindings_.resize(static_cast<int>(InputType::NUMBER_OF_INPUTS), kb);
ControllerBindings gcb;
gcb.button = SDL_CONTROLLER_BUTTON_INVALID;
gcb.active = false;
controller_bindings_.resize(num_gamepads_);
for (int i = 0; i < num_gamepads_; ++i)
{
controller_bindings_[i].resize(static_cast<int>(InputType::NUMBER_OF_INPUTS), gcb);
}
// Listado de los inputs usados para jugar, excluyendo botones para la interfaz
game_inputs_.clear();
game_inputs_.push_back(InputType::FIRE_LEFT);
game_inputs_.push_back(InputType::FIRE_CENTER);
game_inputs_.push_back(InputType::FIRE_RIGHT);
game_inputs_.push_back(InputType::UP);
game_inputs_.push_back(InputType::DOWN);
game_inputs_.push_back(InputType::LEFT);
game_inputs_.push_back(InputType::RIGHT);
// Inicializa los vectores
key_bindings_.resize(static_cast<int>(InputType::NUMBER_OF_INPUTS), KeyBindings());
controller_bindings_.resize(num_gamepads_, std::vector<ControllerBindings>(static_cast<int>(InputType::NUMBER_OF_INPUTS), ControllerBindings()));
// Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
button_inputs_.clear();
button_inputs_.push_back(InputType::FIRE_LEFT);
button_inputs_.push_back(InputType::FIRE_CENTER);
button_inputs_.push_back(InputType::FIRE_RIGHT);
button_inputs_.push_back(InputType::START);
button_inputs_ = {InputType::FIRE_LEFT, InputType::FIRE_CENTER, InputType::FIRE_RIGHT, InputType::START};
}
// Asigna inputs a teclas
void Input::bindKey(InputType input, SDL_Scancode code)
{
key_bindings_[static_cast<int>(input)].scancode = code;
key_bindings_.at(static_cast<int>(input)).scancode = code;
}
// Asigna inputs a botones del mando
@@ -78,7 +56,7 @@ void Input::bindGameControllerButton(int controller_index, InputType input, SDL_
{
if (controller_index < num_gamepads_)
{
controller_bindings_[controller_index][static_cast<int>(input)].button = button;
controller_bindings_.at(controller_index).at(static_cast<int>(input)).button = button;
}
}
@@ -87,41 +65,24 @@ void Input::bindGameControllerButton(int controller_index, InputType input_targe
{
if (controller_index < num_gamepads_)
{
controller_bindings_[controller_index][static_cast<int>(input_target)].button = controller_bindings_[controller_index][static_cast<int>(input_source)].button;
controller_bindings_.at(controller_index).at(static_cast<int>(input_target)).button = controller_bindings_.at(controller_index).at(static_cast<int>(input_source)).button;
}
}
// Comprueba si un input esta activo
bool Input::checkInput(InputType input, bool repeat, int device, int controller_index)
bool Input::checkInput(InputType input, bool repeat, InputDeviceToUse device, int controller_index)
{
if (!enabled_)
{
return false;
}
bool success_keyboard = false;
bool success_controller = false;
const int input_index = static_cast<int>(input);
if (device == INPUT_USE_ANY)
{
controller_index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY)
{
const Uint8 *keyStates = SDL_GetKeyboardState(nullptr);
if (repeat)
{
if (keyStates[key_bindings_[input_index].scancode] != 0)
{
success_keyboard = true;
}
else
{
success_keyboard = false;
}
success_keyboard = keyStates[key_bindings_[input_index].scancode] != 0;
}
else
{
@@ -142,151 +103,29 @@ bool Input::checkInput(InputType input, bool repeat, int device, int controller_
if (keyStates[key_bindings_[input_index].scancode] == 0)
{
key_bindings_[input_index].active = false;
success_keyboard = false;
}
else
{
success_keyboard = false;
}
}
}
}
if (gameControllerFound() && controller_index < num_gamepads_)
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY))
{
success_controller = checkAxisInput(input, controller_index);
if (!success_controller)
{
if (repeat)
{
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{
success_controller = true;
}
else
{
success_controller = false;
}
}
else
{
if (!controller_bindings_[controller_index][input_index].active)
{
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{
controller_bindings_[controller_index][input_index].active = true;
success_controller = true;
}
else
{
success_controller = false;
}
}
else
{
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) == 0)
{
controller_bindings_[controller_index][input_index].active = false;
success_controller = false;
}
else
{
success_controller = false;
}
}
}
}
}
return (success_keyboard || success_controller);
}
// Comprueba si un input con modificador esta activo
bool Input::checkModInput(InputType input_mod, InputType input, bool repeat, int device, int controller_index)
{
if (!enabled_ || controller_index >= num_gamepads_ || !checkInput(input_mod, INPUT_ALLOW_REPEAT, device, controller_index))
{
return false;
}
bool success_keyboard = false;
bool success_controller = false;
const int input_index = static_cast<int>(input);
if (device == INPUT_USE_ANY)
{
controller_index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
{
const Uint8 *keyStates = SDL_GetKeyboardState(nullptr);
if (repeat)
{
if (keyStates[key_bindings_[input_index].scancode] != 0)
{
success_keyboard = true;
}
else
{
success_keyboard = false;
}
}
else
{
if (!key_bindings_[input_index].active)
{
if (keyStates[key_bindings_[input_index].scancode] != 0)
{
key_bindings_[input_index].active = true;
success_keyboard = true;
}
else
{
success_keyboard = false;
}
}
else
{
if (keyStates[key_bindings_[input_index].scancode] == 0)
{
key_bindings_[input_index].active = false;
success_keyboard = false;
}
else
{
success_keyboard = false;
}
}
}
}
if (gameControllerFound() && controller_index < num_gamepads_)
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY))
if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_)
if ((device == InputDeviceToUse::CONTROLLER) || (device == InputDeviceToUse::ANY))
{
success_controller = checkAxisInput(input, controller_index);
if (!success_controller)
{
if (repeat)
{
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{
success_controller = true;
}
else
{
success_controller = false;
}
success_controller = SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) != 0;
}
else
{
if (!controller_bindings_[controller_index][input_index].active)
if (!controller_bindings_.at(controller_index).at(input_index).active)
{
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
if (SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) != 0)
{
controller_bindings_[controller_index][input_index].active = true;
controller_bindings_.at(controller_index).at(input_index).active = true;
success_controller = true;
}
else
@@ -296,15 +135,11 @@ bool Input::checkModInput(InputType input_mod, InputType input, bool repeat, int
}
else
{
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) == 0)
if (SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) == 0)
{
controller_bindings_[controller_index][input_index].active = false;
success_controller = false;
}
else
{
success_controller = false;
controller_bindings_.at(controller_index).at(input_index).active = false;
}
success_controller = false;
}
}
}
@@ -314,14 +149,9 @@ bool Input::checkModInput(InputType input_mod, InputType input, bool repeat, int
}
// Comprueba si hay almenos un input activo
bool Input::checkAnyInput(int device, int controller_index)
bool Input::checkAnyInput(InputDeviceToUse device, int controller_index)
{
if (device == INPUT_USE_ANY)
{
controller_index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY)
{
const Uint8 *mKeystates = SDL_GetKeyboardState(nullptr);
@@ -337,7 +167,7 @@ bool Input::checkAnyInput(int device, int controller_index)
if (gameControllerFound())
{
if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_ANY)
if (device == InputDeviceToUse::CONTROLLER || device == InputDeviceToUse::ANY)
{
for (int i = 0; i < (int)controller_bindings_.size(); ++i)
{
@@ -357,7 +187,7 @@ bool Input::checkAnyInput(int device, int controller_index)
int Input::checkAnyButtonPressed(bool repeat)
{
// Si está pulsado el botón de servicio, ningún botón se puede considerar pulsado
if (checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_ANY))
if (checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::ANY))
{
return 0;
}
@@ -366,7 +196,7 @@ int Input::checkAnyButtonPressed(bool repeat)
for (auto bi : button_inputs_)
{
// Comprueba el teclado
if (checkInput(bi, repeat, INPUT_USE_KEYBOARD))
if (checkInput(bi, repeat, InputDeviceToUse::KEYBOARD))
{
return 1;
}
@@ -374,7 +204,7 @@ int Input::checkAnyButtonPressed(bool repeat)
// Comprueba los mandos
for (int i = 0; i < num_gamepads_; ++i)
{
if (checkInput(bi, repeat, INPUT_USE_GAMECONTROLLER, i))
if (checkInput(bi, repeat, InputDeviceToUse::CONTROLLER, i))
{
return i + 1;
}
@@ -396,11 +226,7 @@ bool Input::discoverGameControllers()
if (SDL_GameControllerAddMappingsFromFile(game_controller_db_path_.c_str()) < 0)
{
#ifdef VERBOSE
{
std::cout << "Error, could not load " << game_controller_db_path_.c_str() << " file: " << SDL_GetError() << std::endl;
}
#endif
std::cout << "Error, could not load " << game_controller_db_path_.c_str() << " file: " << SDL_GetError() << std::endl;
}
num_joysticks_ = SDL_NumJoysticks();
@@ -410,7 +236,7 @@ bool Input::discoverGameControllers()
joysticks_.clear();
for (int i = 0; i < num_joysticks_; ++i)
{
SDL_Joystick *joy = SDL_JoystickOpen(i);
auto joy = SDL_JoystickOpen(i);
joysticks_.push_back(joy);
if (SDL_IsGameController(i))
{
@@ -418,12 +244,8 @@ bool Input::discoverGameControllers()
}
}
#ifdef VERBOSE
{
std::cout << "\nChecking for game controllers...\n";
std::cout << num_joysticks_ << " joysticks found, " << num_gamepads_ << " are gamepads\n";
}
#endif
std::cout << "\n** LOOKING FOR GAME CONTROLLERS" << std::endl;
std::cout << "Gamepads found: " << num_gamepads_ << std::endl;
if (num_gamepads_ > 0)
{
@@ -437,46 +259,30 @@ bool Input::discoverGameControllers()
{
connected_controllers_.push_back(pad);
const std::string name = SDL_GameControllerNameForIndex(i);
#ifdef VERBOSE
{
std::cout << name << std::endl;
}
#endif
std::cout << "#" << i << ": " << name << std::endl;
controller_names_.push_back(name);
}
else
{
#ifdef VERBOSE
{
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
}
#endif
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
}
}
SDL_GameControllerEventState(SDL_ENABLE);
}
std::cout << "\n** FINISHED LOOKING FOR GAME CONTROLLERS" << std::endl;
return found;
}
// Comprueba si hay algun mando conectado
bool Input::gameControllerFound()
{
return num_gamepads_ > 0 ? true : false;
}
bool Input::gameControllerFound() { return num_gamepads_ > 0 ? true : false; }
// Obten el nombre de un mando de juego
std::string Input::getControllerName(int controller_index) const
{
return num_gamepads_ > 0 ? controller_names_[controller_index] : "";
}
std::string Input::getControllerName(int controller_index) const { return num_gamepads_ > 0 ? controller_names_.at(controller_index) : std::string(); }
// Obten el número de mandos conectados
int Input::getNumControllers() const
{
return num_gamepads_;
}
int Input::getNumControllers() const { return num_gamepads_; }
// Obtiene el indice del controlador a partir de un event.id
int Input::getJoyIndex(int id) const
@@ -492,14 +298,14 @@ int Input::getJoyIndex(int id) const
}
// Muestra por consola los controles asignados
void Input::printBindings(int device, int controller_index) const
void Input::printBindings(InputDeviceToUse device, int controller_index) const
{
if (device == INPUT_USE_ANY || device == INPUT_USE_KEYBOARD)
if (device == InputDeviceToUse::ANY || device == InputDeviceToUse::KEYBOARD)
{
return;
}
if (device == INPUT_USE_GAMECONTROLLER)
if (device == InputDeviceToUse::CONTROLLER)
{
if (controller_index >= num_gamepads_)
{
@@ -507,13 +313,12 @@ void Input::printBindings(int device, int controller_index) const
}
// Muestra el nombre del mando
std::cout << "\n"
<< controller_names_[controller_index] << std::endl;
std::cout << "\n" + controller_names_.at(controller_index) << std::endl;
// Muestra los botones asignados
for (auto bi : button_inputs_)
{
std::cout << to_string(bi) << " : " << controller_bindings_[controller_index][static_cast<int>(bi)].button << std::endl;
std::cout << to_string(bi) << " : " << controller_bindings_.at(controller_index).at(static_cast<int>(bi)).button << std::endl;
}
}
}
@@ -527,116 +332,58 @@ SDL_GameControllerButton Input::getControllerBinding(int controller_index, Input
// Obtiene el indice a partir del nombre del mando
int Input::getIndexByName(const std::string &name) const
{
for (int i = 0; i < num_gamepads_; ++i)
{
if (controller_names_[i] == name)
{
return i;
}
}
return -1;
auto it = std::find(controller_names_.begin(), controller_names_.end(), name);
return it != controller_names_.end() ? std::distance(controller_names_.begin(), it) : -1;
}
// Convierte un InputType a std::string
std::string Input::to_string(InputType input) const
{
if (input == InputType::FIRE_LEFT)
switch (input)
{
case InputType::FIRE_LEFT:
return "input_fire_left";
}
if (input == InputType::FIRE_CENTER)
{
case InputType::FIRE_CENTER:
return "input_fire_center";
}
if (input == InputType::FIRE_RIGHT)
{
case InputType::FIRE_RIGHT:
return "input_fire_right";
}
if (input == InputType::START)
{
case InputType::START:
return "input_start";
}
if (input == InputType::SERVICE)
{
case InputType::SERVICE:
return "input_service";
default:
return "";
}
return "";
}
// Convierte un std::string a InputType
InputType Input::to_inputs_e(const std::string &name) const
{
if (name == "input_fire_left")
{
return InputType::FIRE_LEFT;
}
static const std::unordered_map<std::string, InputType> inputMap = {
{"input_fire_left", InputType::FIRE_LEFT},
{"input_fire_center", InputType::FIRE_CENTER},
{"input_fire_right", InputType::FIRE_RIGHT},
{"input_start", InputType::START},
{"input_service", InputType::SERVICE}};
if (name == "input_fire_center")
{
return InputType::FIRE_CENTER;
}
if (name == "input_fire_right")
{
return InputType::FIRE_RIGHT;
}
if (name == "input_start")
{
return InputType::START;
}
if (name == "input_service")
{
return InputType::SERVICE;
}
return InputType::NONE;
auto it = inputMap.find(name);
return it != inputMap.end() ? it->second : InputType::NONE;
}
// Comprueba el eje del mando
bool Input::checkAxisInput(InputType input, int controller_index) const
{
bool success = false;
switch (input)
{
case InputType::LEFT:
if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -30000)
{
success = true;
}
break;
return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -30000;
case InputType::RIGHT:
if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > 30000)
{
success = true;
}
break;
return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > 30000;
case InputType::UP:
if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -30000)
{
success = true;
}
break;
return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -30000;
case InputType::DOWN:
if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > 30000)
{
success = true;
}
break;
return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > 30000;
default:
break;
return false;
}
return success;
}

View File

@@ -1,19 +1,19 @@
#pragma once
#include <SDL2/SDL_gamecontroller.h> // for SDL_GameControllerButton, SDL_G...
#include <SDL2/SDL_joystick.h> // for SDL_Joystick
#include <SDL2/SDL_scancode.h> // for SDL_Scancode
#include <SDL2/SDL_stdinc.h> // for Uint8
#include <string> // for string, basic_string
#include <vector> // for vector
#include <SDL2/SDL_gamecontroller.h> // para SDL_GameControllerButton, SDL_G...
#include <SDL2/SDL_joystick.h> // para SDL_Joystick
#include <SDL2/SDL_scancode.h> // para SDL_Scancode
#include <SDL2/SDL_stdinc.h> // para Uint8
#include <string> // para string, basic_string
#include <vector> // para vector
/*
connectedControllers es un vector donde estan todos los mandos encontrados [0 .. n]
checkInput requiere de un indice para comprobar las pulsaciónes de un controlador en concreto [0 .. n]
device contiene el tipo de dispositivo a comprobar:
INPUT_USE_KEYBOARD solo mirará el teclado
INPUT_USE_GAMECONTROLLER solo mirará el controlador especificado (Si no se especifica, el primero)
INPUT_USE_ANY mirará tanto el teclado como el PRIMER controlador
InputDeviceToUse::KEYBOARD solo mirará el teclado
InputDeviceToUse::CONTROLLER solo mirará el controlador especificado (Si no se especifica, el primero)
InputDeviceToUse::ANY mirará tanto el teclado como el PRIMER controlador
*/
enum class InputType : int
@@ -40,6 +40,7 @@ enum class InputType : int
VIDEO_SHADERS,
RESET,
MUTE,
CHANGE_LANG,
SHOWINFO,
CONFIG,
SWAP_CONTROLLERS,
@@ -52,9 +53,12 @@ enum class InputType : int
constexpr bool INPUT_ALLOW_REPEAT = true;
constexpr bool INPUT_DO_NOT_ALLOW_REPEAT = false;
constexpr int INPUT_USE_KEYBOARD = 0;
constexpr int INPUT_USE_GAMECONTROLLER = 1;
constexpr int INPUT_USE_ANY = 2;
enum class InputDeviceToUse : int
{
KEYBOARD = 0,
CONTROLLER = 1,
ANY = 2,
};
class Input
{
@@ -66,12 +70,20 @@ private:
{
Uint8 scancode; // Scancode asociado
bool active; // Indica si está activo
// Constructor
explicit KeyBindings(Uint8 sc = 0, bool act = false)
: scancode(sc), active(act) {}
};
struct ControllerBindings
{
SDL_GameControllerButton button; // GameControllerButton asociado
bool active; // Indica si está activo
// Constructor
explicit ControllerBindings(SDL_GameControllerButton btn = SDL_CONTROLLER_BUTTON_INVALID, bool act = false)
: button(btn), active(act) {}
};
// Variables
@@ -80,12 +92,10 @@ private:
std::vector<KeyBindings> key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<std::vector<ControllerBindings>> controller_bindings_; // Vector con los botones asociadas a los inputs predefinidos para cada mando
std::vector<std::string> controller_names_; // Vector con los nombres de los mandos
std::vector<InputType> game_inputs_; // Inputs usados para jugar, normalmente direcciones y botones
std::vector<InputType> button_inputs_; // Inputs asignados al jugador y a botones, excluyendo direcciones
int num_joysticks_; // Número de joysticks conectados
int num_gamepads_; // Número de mandos conectados
int num_joysticks_ = 0; // Número de joysticks conectados
int num_gamepads_ = 0; // Número de mandos conectados
std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt
bool enabled_; // Indica si está habilitado
// Comprueba el eje del mando
bool checkAxisInput(InputType input, int controller_index = 0) const;
@@ -114,13 +124,10 @@ public:
void bindGameControllerButton(int controller_index, InputType inputTarget, InputType inputSource);
// Comprueba si un input esta activo
bool checkInput(InputType input, bool repeat = true, int device = INPUT_USE_ANY, int controller_index = 0);
// Comprueba si un input con modificador esta activo
bool checkModInput(InputType input_mod, InputType input, bool repeat = true, int device = INPUT_USE_ANY, int controller_index = 0);
bool checkInput(InputType input, bool repeat = true, InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0);
// Comprueba si hay almenos un input activo
bool checkAnyInput(int device = INPUT_USE_ANY, int controller_index = 0);
bool checkAnyInput(InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0);
// Comprueba si hay algún botón pulsado
int checkAnyButtonPressed(bool repeat = INPUT_DO_NOT_ALLOW_REPEAT);
@@ -141,7 +148,7 @@ public:
int getJoyIndex(int id) const;
// Muestra por consola los controles asignados
void printBindings(int device = INPUT_USE_KEYBOARD, int controller_index = 0) const;
void printBindings(InputDeviceToUse device = InputDeviceToUse::KEYBOARD, int controller_index = 0) const;
// Obtiene el SDL_GameControllerButton asignado a un input
SDL_GameControllerButton getControllerBinding(int controller_index, InputType input) const;

View File

@@ -1,56 +1,42 @@
#include "instructions.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
#include <algorithm> // for max
#include <utility> // for move
#include "asset.h" // for Asset
#include "fade.h" // for Fade, FadeMode, FadeType
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_GetMusicState, JA_Music_state
#include "lang.h" // for getText
#include "param.h" // for param
#include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options
#include "sprite.h" // for Sprite
#include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR, TEXT_...
#include "texture.h" // for Texture
#include "tiled_bg.h" // for Tiledbg, TILED_MODE_STATIC
#include "utils.h" // for Param, ParamGame, Color, shdw_txt_color
struct JA_Music_t; // lines 22-22
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <algorithm> // Para max
#include <utility> // Para move
#include "fade.h" // Para Fade, FadeMode, FadeType
#include "global_inputs.h" // Para check
#include "input.h" // Para Input
#include "jail_audio.h" // Para JA_GetMusicState, JA_Music_state
#include "lang.h" // Para getText
#include "param.h" // Para Param, param, ParamGame, ParamFade
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, name, Options, options
#include "sprite.h" // Para Sprite
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR, TEXT_...
#include "texture.h" // Para Texture
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
#include "utils.h" // Para Color, shdw_txt_color, Zone, no_color
// Constructor
Instructions::Instructions(JA_Music_t *music)
: music_(music)
Instructions::Instructions()
: renderer_(Screen::get()->getRenderer()),
texture_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
text_(Resource::get()->getText("smb2")),
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::STATIC)),
fade_(std::make_unique<Fade>())
{
// Copia los punteros
renderer_ = Screen::get()->getRenderer();
// Crea objetos
text_ = std::make_unique<Text>(Asset::get()->get("smb2.gif"), Asset::get()->get("smb2.txt"), renderer_);
tiled_bg_ = std::make_unique<Tiledbg>(Asset::get()->get("title_bg_tile.png"), (SDL_Rect){0, 0, param.game.width, param.game.height}, TILED_MODE_STATIC);
fade_ = std::make_unique<Fade>(renderer_);
// Crea un backbuffer para el renderizador
backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
// Configura las texturas
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
// Crea una textura para el texto fijo
texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
// Inicializa variables
section::name = section::Name::INSTRUCTIONS;
ticks_ = 0;
ticks_speed_ = 15;
counter_ = 0;
counter_end_ = 700;
view_ = {0, 0, param.game.width, param.game.height};
sprite_pos_ = {0, 0};
item_space_ = 2;
view_ = param.game.game_area.rect;
// Inicializa objetos
fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
@@ -80,26 +66,17 @@ Instructions::~Instructions()
void Instructions::iniSprites()
{
// Inicializa las texturas
auto item1 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_points1_disk.png"));
item_textures_.push_back(item1);
auto item2 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_points2_gavina.png"));
item_textures_.push_back(item2);
auto item3 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_points3_pacmar.png"));
item_textures_.push_back(item3);
auto item4 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_clock.png"));
item_textures_.push_back(item4);
auto item5 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_coffee.png"));
item_textures_.push_back(item5);
item_textures_.emplace_back(Resource::get()->getTexture("item_points1_disk.png"));
item_textures_.emplace_back(Resource::get()->getTexture("item_points2_gavina.png"));
item_textures_.emplace_back(Resource::get()->getTexture("item_points3_pacmar.png"));
item_textures_.emplace_back(Resource::get()->getTexture("item_clock.png"));
item_textures_.emplace_back(Resource::get()->getTexture("item_coffee.png"));
// Inicializa los sprites
for (int i = 0; i < (int)item_textures_.size(); ++i)
{
auto sprite = std::make_unique<Sprite>(0, 0, param.game.item_size, param.game.item_size, item_textures_[i]);
sprite->setPos((SDL_Point){sprite_pos_.x, sprite_pos_.y + ((param.game.item_size + item_space_) * i)});
auto sprite = std::make_unique<Sprite>(item_textures_[i], 0, 0, param.game.item_size, param.game.item_size);
sprite->setPosition((SDL_Point){sprite_pos_.x, sprite_pos_.y + ((param.game.item_size + item_space_) * i)});
sprites_.push_back(std::move(sprite));
}
}
@@ -223,19 +200,25 @@ void Instructions::fillBackbuffer()
// Actualiza las variables
void Instructions::update()
{
// Actualiza las variables
if (SDL_GetTicks() - ticks_ > ticks_speed_)
constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();
// Mantiene la música sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
JA_PlayMusic(music_);
{
JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
}
// Actualiza el objeto screen
Screen::get()->update();
// Actualiza las variables de globalInputs
globalInputs::update();
// Incrementa el contador
counter_++;
@@ -306,6 +289,7 @@ void Instructions::checkEvents()
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
@@ -332,9 +316,6 @@ void Instructions::checkInput()
return;
}
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check();
}

View File

@@ -1,16 +1,15 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Texture, SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr, shared_ptr
#include <vector> // for vector
class Fade;
class Sprite;
class Text;
class Texture;
class Tiledbg;
struct JA_Music_t; // lines 14-14
#include <SDL2/SDL_rect.h> // Para SDL_Point, SDL_Rect
#include <SDL2/SDL_render.h> // Para SDL_Texture, SDL_Renderer
#include <SDL2/SDL_stdinc.h> // Para Uint32
#include <memory> // Para unique_ptr, shared_ptr
#include <vector> // Para vector
class Fade; // lines 8-8
class Sprite; // lines 9-9
class Text; // lines 10-10
class Texture; // lines 11-11
class TiledBG; // lines 12-12
/*
Esta clase gestiona un estado del programa. Se encarga de poner en pantalla
@@ -30,25 +29,23 @@ class Instructions
{
private:
// Objetos y punteros
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
std::vector<std::unique_ptr<Sprite>> sprites_; // Vector con los sprites de los items
std::unique_ptr<Text> text_; // Objeto para escribir texto
std::unique_ptr<Tiledbg> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
SDL_Renderer *renderer_; // El renderizador de la ventana
JA_Music_t *music_; // Musica de fondo
SDL_Texture *texture_; // Textura fija con el texto
SDL_Texture *backbuffer_; // Textura para usar como backbuffer
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
std::vector<std::unique_ptr<Sprite>> sprites_; // Vector con los sprites de los items
std::shared_ptr<Text> text_; // Objeto para escribir texto
std::unique_ptr<TiledBG> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
// Variables
int counter_; // Contador
int counter_end_; // Valor final para el contador
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
SDL_Rect view_; // Vista del backbuffer que se va amostrar por pantalla
SDL_Point sprite_pos_; // Posición del primer sprite
int item_space_; // Espacio entre los items
int counter_ = 0; // Contador
int counter_end_ = 700; // Valor final para el contador
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
SDL_Rect view_; // Vista del backbuffer que se va amostrar por pantalla
SDL_Point sprite_pos_ = {0, 0}; // Posición del primer sprite
int item_space_ = 2; // Espacio entre los items
// Actualiza las variables
void update();
@@ -79,7 +76,7 @@ private:
public:
// Constructor
explicit Instructions(JA_Music_t *music);
Instructions();
// Destructor
~Instructions();

View File

@@ -1,40 +1,31 @@
#include "intro.h"
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
#include <utility> // for move
#include "asset.h" // for Asset
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_StopMusic, JA_PlayMusic
#include "lang.h" // for getText
#include "param.h" // for param
#include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options
#include "smart_sprite.h" // for SmartSprite
#include "text.h" // for Text
#include "texture.h" // for Texture
#include "utils.h" // for Param, ParamGame, Zone, BLOCK, Color
#include "writer.h" // for Writer
struct JA_Music_t; // lines 19-19
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <utility> // Para move
#include "global_inputs.h" // Para check
#include "input.h" // Para Input
#include "jail_audio.h" // Para JA_StopMusic, JA_PlayMusic
#include "lang.h" // Para getText
#include "param.h" // Para Param, ParamGame, param
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, name, Options, options
#include "smart_sprite.h" // Para SmartSprite
#include "text.h" // Para Text
#include "texture.h" // Para Texture
#include "utils.h" // Para Zone, BLOCK, Color, bg_color
#include "writer.h" // Para Writer
// Constructor
Intro::Intro(JA_Music_t *music)
: music_(music)
Intro::Intro()
: texture_(Resource::get()->getTexture("intro.png")),
text_(Resource::get()->getText("nokia"))
{
// Copia los punteros
auto renderer = Screen::get()->getRenderer();
// Reserva memoria para los objetos
texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("intro.png"));
text_ = std::make_shared<Text>(Asset::get()->get("nokia.png"), Asset::get()->get("nokia.txt"), renderer);
// Inicializa variables
section::name = section::Name::INTRO;
section::options = section::Options::NONE;
ticks_ = 0;
ticks_speed_ = 15;
scene_ = 1;
// Inicializa los bitmaps de la intro
constexpr int totalBitmaps = 6;
@@ -148,9 +139,7 @@ Intro::Intro(JA_Music_t *music)
texts_[8]->setSpeed(16);
for (auto &text : texts_)
{
text->center(param.game.game_area.center_x);
}
}
// Recarga todas las texturas
@@ -173,15 +162,14 @@ void Intro::checkEvents()
case SDL_QUIT:
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
case SDL_WINDOWEVENT:
{
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
reloadTextures();
}
break;
}
@@ -203,9 +191,6 @@ void Intro::checkInput()
return;
}
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check();
}
@@ -374,7 +359,9 @@ void Intro::updateScenes()
// Actualiza las variables del objeto
void Intro::update()
{
if (SDL_GetTicks() - ticks_ > ticks_speed_)
constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();
@@ -395,6 +382,9 @@ void Intro::update()
// Actualiza las escenas de la intro
updateScenes();
// Actualiza las variables de globalInputs
globalInputs::update();
}
}
@@ -425,7 +415,7 @@ void Intro::render()
// Bucle principal
void Intro::run()
{
JA_PlayMusic(music_, 0);
JA_PlayMusic(Resource::get()->getMusic("intro.ogg"), 0);
while (section::name == section::Name::INTRO)
{

View File

@@ -1,13 +1,12 @@
#pragma once
#include <SDL2/SDL_stdinc.h> // for Uint32, Uint8
#include <memory> // for unique_ptr, shared_ptr
#include <vector> // for vector
#include "smart_sprite.h" // for SmartSprite
#include "writer.h" // for Writer
class Text;
class Texture;
struct JA_Music_t; // lines 11-11
#include <SDL2/SDL_stdinc.h> // Para Uint32
#include <memory> // Para unique_ptr, shared_ptr
#include <vector> // Para vector
#include "smart_sprite.h" // Para SmartSprite
#include "writer.h" // Para Writer
class Text; // lines 8-8
class Texture; // lines 9-9
/*
Esta clase gestiona un estado del programa. Se encarga de mostrar la secuencia
@@ -26,10 +25,8 @@ private:
std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro
// Variables
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint8 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
JA_Music_t *music_; // Musica para la intro
int scene_; // Indica que escena está activa
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
int scene_ = 1; // Indica que escena está activa
// Actualiza las variables del objeto
void update();
@@ -51,7 +48,7 @@ private:
public:
// Constructor
explicit Intro(JA_Music_t *music);
Intro();
// Destructor
~Intro() = default;

View File

@@ -1,31 +1,30 @@
#include "item.h"
#include <stdlib.h> // for rand
#include "animated_sprite.h" // for AnimatedSprite
#include "param.h" // for param
class Texture;
#include <stdlib.h> // Para rand
#include <algorithm> // Para clamp
#include "animated_sprite.h" // Para AnimatedSprite
#include "param.h" // Para Param, ParamGame, param
class Texture; // lines 6-6
// Constructor
Item::Item(int kind, float x, float y, SDL_Rect *play_area, std::shared_ptr<Texture> texture, std::vector<std::string> *animation)
: sprite_(std::make_unique<AnimatedSprite>(texture, "", animation)),
accel_x_(0.0f),
floor_collision_(false),
kind_(kind),
enabled_(true),
play_area_(play_area),
time_to_live_(600)
Item::Item(ItemType type, float x, float y, SDL_Rect &play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
type_(type),
play_area_(play_area)
{
if (kind == ITEM_COFFEE_MACHINE)
switch (type)
{
case ItemType::COFFEE_MACHINE:
{
width_ = 28;
height_ = 37;
pos_x_ = (((int)x + (play_area->w / 2)) % (play_area->w - width_ - 5)) + 2;
pos_x_ = ((static_cast<int>(x) + (play_area.w / 2)) % (play_area.w - width_ - 5)) + 2;
pos_y_ = -height_;
vel_x_ = 0.0f;
vel_y_ = -0.1f;
accel_y_ = 0.1f;
collider_.r = 10;
break;
}
else
default:
{
width_ = 20;
height_ = 20;
@@ -35,36 +34,30 @@ Item::Item(int kind, float x, float y, SDL_Rect *play_area, std::shared_ptr<Text
vel_y_ = -4.0f;
accel_y_ = 0.2f;
collider_.r = width_ / 2;
break;
}
}
sprite_->setPosX(pos_x_);
sprite_->setPosY(pos_y_);
// Actualiza el sprite
shiftSprite();
shiftColliders();
}
// Centra el objeto en la posición X
void Item::allignTo(int x)
void Item::alignTo(int x)
{
pos_x_ = float(x - (width_ / 2));
const float min_x = param.game.play_area.rect.x + 1;
const float max_x = play_area_.w - width_ - 1;
if (pos_x_ < param.game.play_area.rect.x)
{
pos_x_ = param.game.play_area.rect.x + 1;
}
else if ((pos_x_ + width_) > play_area_->w)
{
pos_x_ = float(play_area_->w - width_ - 1);
}
pos_x_ = x - (width_ / 2);
// Posición X,Y del sprite
sprite_->setPosX(int(pos_x_));
sprite_->setPosY(int(pos_y_));
// Ajusta para que no quede fuera de la zona de juego
pos_x_ = std::clamp(pos_x_, min_x, max_x);
// Alinea el circulo de colisión con el objeto
// Actualiza el sprite
shiftSprite();
shiftColliders();
}
// Pinta el objeto en la pantalla
void Item::render()
{
if (enabled_)
@@ -80,7 +73,6 @@ void Item::render()
}
}
// Actualiza la posición y estados del objeto
void Item::move()
{
floor_collision_ = false;
@@ -93,129 +85,90 @@ void Item::move()
vel_x_ += accel_x_;
vel_y_ += accel_y_;
// Si queda fuera de pantalla, corregimos su posición y cambiamos su sentido
if ((pos_x_ < param.game.play_area.rect.x) || (pos_x_ + width_ > play_area_->w))
{
// Corregir posición
pos_x_ -= vel_x_;
// Comprueba los laterales de la zona de juego
const float min_x = param.game.play_area.rect.x;
const float max_x = play_area_.w - width_;
pos_x_ = std::clamp(pos_x_, min_x, max_x);
// Invertir sentido
// Si toca el borde lateral, invierte la velocidad horizontal
if (pos_x_ == min_x || pos_x_ == max_x)
{
vel_x_ = -vel_x_;
}
// Si se sale por arriba rebota (excepto la maquina de café)
if ((pos_y_ < param.game.play_area.rect.y) && !(kind_ == ITEM_COFFEE_MACHINE))
// Si colisiona por arriba, rebota (excepto la máquina de café)
if ((pos_y_ < param.game.play_area.rect.y) && !(type_ == ItemType::COFFEE_MACHINE))
{
// Corrige
pos_y_ = param.game.play_area.rect.y;
// Invierte el sentido
// Invierte la velocidad
vel_y_ = -vel_y_;
}
// Si el objeto se sale por la parte inferior
if (pos_y_ + height_ > play_area_->h)
// Si colisiona con la parte inferior
if (pos_y_ > play_area_.h - height_)
{
// Detiene el objeto
vel_y_ = 0;
vel_x_ = 0;
accel_x_ = 0;
accel_y_ = 0;
pos_y_ = play_area_->h - height_;
if (kind_ == ITEM_COFFEE_MACHINE)
// Corrige la posición
pos_y_ = play_area_.h - height_;
if (type_ == ItemType::COFFEE_MACHINE)
{
// Si es una máquina de café, detiene el objeto
vel_y_ = vel_x_ = accel_x_ = accel_y_ = 0;
floor_collision_ = true;
}
else
{
// Si no es una máquina de café
if (vel_y_ < 1.0f)
{
// Si la velocidad vertical es baja, detiene el objeto
vel_y_ = vel_x_ = accel_x_ = accel_y_ = 0;
}
else
{
// Si la velocidad vertical es alta, el objeto rebota y pierde velocidad
vel_y_ *= -0.5f;
vel_x_ *= 0.75f;
}
}
}
// Actualiza la posición del sprite
sprite_->setPosX(int(pos_x_));
sprite_->setPosY(int(pos_y_));
shiftSprite();
shiftColliders();
}
// Pone a cero todos los valores del objeto
void Item::disable()
{
enabled_ = false;
}
void Item::disable() { enabled_ = false; }
// Actualiza el objeto a su posicion, animación y controla los contadores
void Item::update()
{
move();
sprite_->animate();
sprite_->update();
updateTimeToLive();
checkTimeToLive();
}
// Actualiza el contador
void Item::updateTimeToLive()
{
if (time_to_live_ > 0)
{
time_to_live_--;
}
}
// Comprueba si el objeto sigue vivo
void Item::checkTimeToLive()
{
if (time_to_live_ == 0)
else
{
disable();
}
}
// Obtiene del valor de la variable
float Item::getPosX()
{
return pos_x_;
}
// Obtiene del valor de la variable
float Item::getPosY()
{
return pos_y_;
}
// Obtiene del valor de la variable
int Item::getWidth()
{
return width_;
}
// Obtiene del valor de la variable
int Item::getHeight()
{
return height_;
}
// Obtiene del valor de la variable
int Item::getClass()
{
return kind_;
}
// Obtiene el valor de la variable
bool Item::isEnabled()
{
return enabled_;
}
// Obtiene el circulo de colisión
Circle &Item::getCollider()
{
return collider_;
}
// Alinea el circulo de colisión con la posición del objeto
void Item::shiftColliders()
{
collider_.x = int(pos_x_ + (width_ / 2));
collider_.y = int(pos_y_ + (height_ / 2));
collider_.x = static_cast<int>(pos_x_ + (width_ / 2));
collider_.y = static_cast<int>(pos_y_ + (height_ / 2));
}
// Informa si el objeto ha colisionado con el suelo
bool Item::isOnFloor()
void Item::shiftSprite()
{
return floor_collision_;
sprite_->setPosX(pos_x_);
sprite_->setPosY(pos_y_);
}

View File

@@ -1,98 +1,155 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint16
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
#include <vector> // for vector
#include "animated_sprite.h" // for AnimatedSprite
#include "utils.h" // for Circle
#include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_stdinc.h> // para Uint16
#include <memory> // para shared_ptr, unique_ptr
#include <string> // para string
#include <vector> // para vector
#include "animated_sprite.h" // para SpriteAnimated
#include "utils.h" // para Circle
class Texture;
// Tipos de objetos
constexpr int ITEM_POINTS_1_DISK = 1;
constexpr int ITEM_POINTS_2_GAVINA = 2;
constexpr int ITEM_POINTS_3_PACMAR = 3;
constexpr int ITEM_CLOCK = 4;
constexpr int ITEM_COFFEE = 5;
constexpr int ITEM_COFFEE_MACHINE = 6;
constexpr int ITEM_NULL = 7;
/**
* @brief Tipos de objetos disponibles en el juego.
*
* Esta enumeración define los diferentes tipos de objetos que pueden existir en el juego,
* cada uno con un identificador único.
*/
enum class ItemType : int
{
DISK = 1, /**< Disco */
GAVINA = 2, /**< Gavina */
PACMAR = 3, /**< Pacman */
CLOCK = 4, /**< Reloj */
COFFEE = 5, /**< Café */
COFFEE_MACHINE = 6,/**< Máquina de café */
NONE = 7, /**< Ninguno */
};
// Clase Item
/**
* @brief Clase Item.
*
* Esta clase representa un objeto en el juego, con sus propiedades y métodos para gestionar su comportamiento.
*/
class Item
{
private:
// Objetos y punteros
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los graficos del objeto
std::unique_ptr<AnimatedSprite> sprite_; /**< Sprite con los gráficos del objeto */
// Variables
float pos_x_; // Posición X del objeto
float pos_y_; // Posición Y del objeto
int width_; // Ancho del objeto
int height_; // Alto del objeto
float vel_x_; // Velocidad en el eje X
float vel_y_; // Velocidad en el eje Y
float accel_x_; // Aceleración en el eje X
float accel_y_; // Aceleración en el eje Y
bool floor_collision_; // Indica si el objeto colisiona con el suelo
int kind_; // Especifica el tipo de objeto que es
bool enabled_; // Especifica si el objeto está habilitado
Circle collider_; // Circulo de colisión del objeto
SDL_Rect *play_area_; // Rectangulo con la zona de juego
Uint16 time_to_live_; // Temporizador con el tiempo que el objeto está presente
float pos_x_; /**< Posición X del objeto */
float pos_y_; /**< Posición Y del objeto */
int width_; /**< Ancho del objeto */
int height_; /**< Alto del objeto */
float vel_x_; /**< Velocidad en el eje X */
float vel_y_; /**< Velocidad en el eje Y */
float accel_x_ = 0.0f; /**< Aceleración en el eje X */
float accel_y_; /**< Aceleración en el eje Y */
bool floor_collision_ = false; /**< Indica si el objeto colisiona con el suelo */
ItemType type_; /**< Especifica el tipo de objeto que es */
bool enabled_ = true; /**< Especifica si el objeto está habilitado */
Circle collider_; /**< Círculo de colisión del objeto */
SDL_Rect play_area_; /**< Rectángulo con la zona de juego */
Uint16 time_to_live_ = 600; /**< Temporizador con el tiempo que el objeto está presente */
// Alinea el circulo de colisión con la posición del objeto
/**
* @brief Alinea el círculo de colisión con la posición del objeto.
*
* Esta función ajusta la posición del círculo de colisión para que coincida con la posición del objeto.
* Actualiza las coordenadas X e Y del colisionador basándose en las coordenadas del objeto.
*/
void shiftColliders();
// Actualiza la posición y estados del objeto
/**
* @brief Coloca el sprite en la posición del objeto.
*
* Esta función ajusta la posición del sprite para que coincida con la posición del objeto.
* Actualiza las coordenadas X e Y del sprite basándose en las coordenadas del objeto.
*/
void shiftSprite();
/**
* @brief Actualiza la posición y estados del objeto.
*
* Esta función actualiza la posición del objeto basándose en su velocidad y aceleración.
* Controla las colisiones con los límites del área de juego, ajustando la posición y la velocidad en consecuencia.
* También actualiza la posición del sprite y el colisionador del objeto.
*/
void move();
// Actualiza el contador
/**
* @brief Actualiza el contador de tiempo de vida del objeto.
*
* Esta función decrementa el contador de tiempo de vida del objeto.
* Si el tiempo de vida es mayor a 0, se decrementa en 1.
* Si el tiempo de vida es 0 o menos, se desactiva el objeto llamando a la función `disable()`.
*/
void updateTimeToLive();
// Comprueba si el objeto sigue vivo
void checkTimeToLive();
public:
// Constructor
Item(int kind, float x, float y, SDL_Rect *play_area, std::shared_ptr<Texture> texture, std::vector<std::string> *animation);
/**
* @brief Constructor de la clase Item.
*
* Este constructor inicializa un objeto Item con el tipo especificado, posición inicial, área de juego, textura y animación.
*
* @param type El tipo de objeto (ItemType).
* @param x La posición X inicial del objeto.
* @param y La posición Y inicial del objeto.
* @param play_area El área de juego donde el objeto se moverá.
* @param texture La textura del objeto.
* @param animation La animación asociada al objeto.
*/
Item(ItemType type, float x, float y, SDL_Rect &play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation);
// Destructor
/**
* @brief Destructor de la clase Item.
*
* Este destructor libera los recursos asociados con el objeto Item.
*/
~Item() = default;
// Centra el objeto en la posición X
void allignTo(int x);
/**
* @brief Centra el objeto en la posición X.
*
* Esta función ajusta la posición X del objeto para que esté centrado en la posición X especificada.
* Además, asegura que el objeto no se salga de los límites del área de juego.
*
* @param x La posición X en la que se desea centrar el objeto.
*/
void alignTo(int x);
// Pinta el objeto en la pantalla
/**
* @brief Pinta el objeto en la pantalla.
*
* Esta función renderiza el objeto en la pantalla si está habilitado.
* Si el tiempo de vida (`time_to_live_`) es mayor que 200, renderiza el sprite.
* Si el tiempo de vida es menor o igual a 200, renderiza el sprite de forma intermitente, basándose en un cálculo de módulo.
*/
void render();
// Pone a cero todos los valores del objeto
/**
* @brief Pone a cero todos los valores del objeto.
*
* Esta función desactiva el objeto estableciendo su estado `enabled_` a `false`.
*/
void disable();
// Actualiza al objeto a su posicion, animación y controla los contadores
/**
* @brief Actualiza el objeto a su posición, animación y controla los contadores.
*
* Esta función mueve el objeto, actualiza su animación y controla el contador de tiempo de vida.
* Llama a las funciones `move()`, `sprite_->update()` y `updateTimeToLive()`.
*/
void update();
// Obtiene del valor de la variable
float getPosX();
// Obtiene del valor de la variable
float getPosY();
// Obtiene del valor de la variable
int getWidth();
// Obtiene del valor de la variable
int getHeight();
// Obtiene del valor de la variable
int getClass();
// Obtiene el valor de la variable
bool isEnabled();
// Obtiene el circulo de colisión
Circle &getCollider();
// Informa si el objeto ha colisionado con el suelo
bool isOnFloor();
// Getters
float getPosX() const { return pos_x_; }
float getPosY() const { return pos_y_; }
int getWidth() const { return width_; }
int getHeight() const { return height_; }
ItemType getType() const { return type_; }
bool isEnabled() const { return enabled_; }
bool isOnFloor() const { return floor_collision_; }
Circle &getCollider() { return collider_; }
};

View File

@@ -1,74 +1,91 @@
#ifndef JA_USESDLMIXER
#include "jail_audio.h"
#include <stdint.h> // for uint8_t
#include <stdio.h> // for NULL, fseek, fclose, fopen, fread, ftell, FILE
#include <stdlib.h> // for free, malloc
#include "stb_vorbis.c" // for stb_vorbis_decode_memory
#include <stdint.h> // para uint8_t
#include <stdio.h> // para NULL, fseek, fclose, fopen, fread, ftell, FILE
#include <stdlib.h> // para free, malloc
#include "stb_vorbis.c" // para stb_vorbis_decode_memory
#define JA_MAX_SIMULTANEOUS_CHANNELS 5
struct JA_Sound_t {
Uint32 length {0};
Uint8* buffer {NULL};
struct JA_Sound_t
{
Uint32 length{0};
Uint8 *buffer{NULL};
};
struct JA_Channel_t {
JA_Sound_t *sound;
int pos {0};
int times {0};
JA_Channel_state state { JA_CHANNEL_FREE };
struct JA_Channel_t
{
JA_Sound_t *sound;
int pos{0};
int times{0};
JA_Channel_state state{JA_CHANNEL_FREE};
};
struct JA_Music_t {
int samples {0};
int pos {0};
int times {0};
short* output {NULL};
JA_Music_state state {JA_MUSIC_INVALID};
struct JA_Music_t
{
int samples{0};
int pos{0};
int times{0};
short *output{NULL};
JA_Music_state state{JA_MUSIC_INVALID};
};
JA_Music_t *current_music{NULL};
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
JA_Music_t *current_music{NULL};
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
int JA_freq {48000};
SDL_AudioFormat JA_format {AUDIO_S16};
Uint8 JA_channels {2};
int JA_musicVolume = 128;
int JA_soundVolume = 64;
bool JA_musicEnabled = true;
bool JA_soundEnabled = true;
int JA_freq{48000};
SDL_AudioFormat JA_format{AUDIO_S16};
Uint8 JA_channels{2};
int JA_musicVolume = 128;
int JA_soundVolume = 64;
bool JA_musicEnabled = true;
bool JA_soundEnabled = true;
SDL_AudioDeviceID sdlAudioDevice = 0;
void audioCallback(void * userdata, uint8_t * stream, int len) {
void audioCallback(void *userdata, uint8_t *stream, int len)
{
SDL_memset(stream, 0, len);
if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING) {
const int size = SDL_min(len, current_music->samples*2-current_music->pos);
SDL_MixAudioFormat(stream, (Uint8*)(current_music->output+current_music->pos), AUDIO_S16, size, JA_musicVolume);
current_music->pos += size/2;
if (size < len) {
if (current_music->times != 0) {
SDL_MixAudioFormat(stream+size, (Uint8*)current_music->output, AUDIO_S16, len-size, JA_musicVolume);
current_music->pos = (len-size)/2;
if (current_music->times > 0) current_music->times--;
} else {
if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING)
{
const int size = SDL_min(len, current_music->samples * 2 - current_music->pos);
SDL_MixAudioFormat(stream, (Uint8 *)(current_music->output + current_music->pos), AUDIO_S16, size, JA_musicVolume);
current_music->pos += size / 2;
if (size < len)
{
if (current_music->times != 0)
{
SDL_MixAudioFormat(stream + size, (Uint8 *)current_music->output, AUDIO_S16, len - size, JA_musicVolume);
current_music->pos = (len - size) / 2;
if (current_music->times > 0)
current_music->times--;
}
else
{
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
}
}
// Mixar els channels mi amol
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state == JA_CHANNEL_PLAYING) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
{
if (channels[i].state == JA_CHANNEL_PLAYING)
{
const int size = SDL_min(len, channels[i].sound->length - channels[i].pos);
SDL_MixAudioFormat(stream, channels[i].sound->buffer + channels[i].pos, AUDIO_S16, size, JA_soundVolume);
channels[i].pos += size;
if (size < len) {
if (channels[i].times != 0) {
SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len-size, JA_soundVolume);
channels[i].pos = len-size;
if (channels[i].times > 0) channels[i].times--;
} else {
if (size < len)
{
if (channels[i].times != 0)
{
SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len - size, JA_soundVolume);
channels[i].pos = len - size;
if (channels[i].times > 0)
channels[i].times--;
}
else
{
JA_StopChannel(i);
}
}
@@ -76,23 +93,28 @@ void audioCallback(void * userdata, uint8_t * stream, int len) {
}
}
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) {
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels)
{
JA_freq = freq;
JA_format = format;
JA_channels = channels;
SDL_AudioSpec audioSpec{JA_freq, JA_format, JA_channels, 0, 1024, 0, 0, audioCallback, NULL};
if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice);
if (sdlAudioDevice != 0)
SDL_CloseAudioDevice(sdlAudioDevice);
sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
SDL_PauseAudioDevice(sdlAudioDevice, 0);
}
void JA_Quit() {
void JA_Quit()
{
SDL_PauseAudioDevice(sdlAudioDevice, 1);
if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice);
if (sdlAudioDevice != 0)
SDL_CloseAudioDevice(sdlAudioDevice);
sdlAudioDevice = 0;
}
JA_Music_t *JA_LoadMusic(const char* filename) {
JA_Music_t *JA_LoadMusic(const char *filename)
{
int chan, samplerate;
// [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid.
@@ -100,8 +122,9 @@ JA_Music_t *JA_LoadMusic(const char* filename) {
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
Uint8 *buffer = (Uint8*)malloc(fsize + 1);
if (fread(buffer, fsize, 1, f)!=1) return NULL;
Uint8 *buffer = (Uint8 *)malloc(fsize + 1);
if (fread(buffer, fsize, 1, f) != 1)
return NULL;
fclose(f);
JA_Music_t *music = new JA_Music_t();
@@ -109,17 +132,18 @@ JA_Music_t *JA_LoadMusic(const char* filename) {
music->samples = stb_vorbis_decode_memory(buffer, fsize, &chan, &samplerate, &music->output);
free(buffer);
// [RZC 28/08/22] Abans el descomprimiem mentre el teniem obert
// music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output);
// music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output);
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq);
if (cvt.needed) {
if (cvt.needed)
{
cvt.len = music->samples * chan * 2;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
cvt.buf = (Uint8 *)SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, music->output, cvt.len);
SDL_ConvertAudio(&cvt);
free(music->output);
music->output = (short*)cvt.buf;
music->output = (short *)cvt.buf;
}
music->pos = 0;
music->state = JA_MUSIC_STOPPED;
@@ -129,9 +153,11 @@ JA_Music_t *JA_LoadMusic(const char* filename) {
void JA_PlayMusic(JA_Music_t *music, const int loop)
{
if (!JA_musicEnabled) return;
if (!JA_musicEnabled || !music)
return;
if (current_music != NULL) {
if (current_music != NULL)
{
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
@@ -143,67 +169,78 @@ void JA_PlayMusic(JA_Music_t *music, const int loop)
void JA_PauseMusic()
{
if (!JA_musicEnabled) return;
if (!JA_musicEnabled)
return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID)
return;
current_music->state = JA_MUSIC_PAUSED;
}
void JA_ResumeMusic()
{
if (!JA_musicEnabled) return;
if (!JA_musicEnabled)
return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID)
return;
current_music->state = JA_MUSIC_PLAYING;
}
void JA_StopMusic()
{
if (!JA_musicEnabled) return;
if (!JA_musicEnabled)
return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID)
return;
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
JA_Music_state JA_GetMusicState() {
if (!JA_musicEnabled) return JA_MUSIC_DISABLED;
JA_Music_state JA_GetMusicState()
{
if (!JA_musicEnabled)
return JA_MUSIC_DISABLED;
if (current_music == NULL) return JA_MUSIC_INVALID;
if (current_music == NULL)
return JA_MUSIC_INVALID;
return current_music->state;
}
void JA_DeleteMusic(JA_Music_t *music) {
if (current_music == music) current_music = NULL;
void JA_DeleteMusic(JA_Music_t *music)
{
if (current_music == music)
current_music = NULL;
free(music->output);
delete music;
}
int JA_SetMusicVolume(int volume)
{
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume;
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0
: volume;
return JA_musicVolume;
}
void JA_EnableMusic(const bool value)
{
if (!value && current_music != NULL && current_music->state==JA_MUSIC_PLAYING) JA_StopMusic();
if (!value && current_music != NULL && current_music->state == JA_MUSIC_PLAYING)
JA_StopMusic();
JA_musicEnabled = value;
}
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length) {
JA_Sound_t *JA_NewSound(Uint8 *buffer, Uint32 length)
{
JA_Sound_t *sound = new JA_Sound_t();
sound->buffer = buffer;
sound->length = length;
return sound;
}
JA_Sound_t *JA_LoadSound(const char* filename) {
JA_Sound_t *JA_LoadSound(const char *filename)
{
JA_Sound_t *sound = new JA_Sound_t();
SDL_AudioSpec wavSpec;
SDL_LoadWAV(filename, &wavSpec, &sound->buffer, &sound->length);
@@ -211,7 +248,7 @@ JA_Sound_t *JA_LoadSound(const char* filename) {
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq);
cvt.len = sound->length;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
cvt.buf = (Uint8 *)SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, sound->buffer, sound->length);
SDL_ConvertAudio(&cvt);
SDL_FreeWAV(sound->buffer);
@@ -223,11 +260,16 @@ JA_Sound_t *JA_LoadSound(const char* filename) {
int JA_PlaySound(JA_Sound_t *sound, const int loop)
{
if (!JA_soundEnabled) return 0;
if (!JA_soundEnabled || !sound)
return 0;
int channel = 0;
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; }
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0;
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE)
{
channel++;
}
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS)
channel = 0;
channels[channel].sound = sound;
channels[channel].times = loop;
@@ -238,8 +280,10 @@ int JA_PlaySound(JA_Sound_t *sound, const int loop)
void JA_DeleteSound(JA_Sound_t *sound)
{
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].sound == sound) JA_StopChannel(i);
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
{
if (channels[i].sound == sound)
JA_StopChannel(i);
}
SDL_free(sound->buffer);
delete sound;
@@ -247,41 +291,60 @@ void JA_DeleteSound(JA_Sound_t *sound)
void JA_PauseChannel(const int channel)
{
if (!JA_soundEnabled) return;
if (!JA_soundEnabled)
return;
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state == JA_CHANNEL_PLAYING) channels[i].state = JA_CHANNEL_PAUSED;
if (channel == -1)
{
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
{
if (channels[i].state == JA_CHANNEL_PLAYING)
channels[i].state = JA_CHANNEL_PAUSED;
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state == JA_CHANNEL_PLAYING) channels[channel].state = JA_CHANNEL_PAUSED;
}
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
{
if (channels[channel].state == JA_CHANNEL_PLAYING)
channels[channel].state = JA_CHANNEL_PAUSED;
}
}
void JA_ResumeChannel(const int channel)
{
if (!JA_soundEnabled) return;
if (!JA_soundEnabled)
return;
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state == JA_CHANNEL_PAUSED) channels[i].state = JA_CHANNEL_PLAYING;
if (channel == -1)
{
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
{
if (channels[i].state == JA_CHANNEL_PAUSED)
channels[i].state = JA_CHANNEL_PLAYING;
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state == JA_CHANNEL_PAUSED) channels[channel].state = JA_CHANNEL_PLAYING;
}
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
{
if (channels[channel].state == JA_CHANNEL_PAUSED)
channels[channel].state = JA_CHANNEL_PLAYING;
}
}
void JA_StopChannel(const int channel)
{
if (!JA_soundEnabled) return;
if (!JA_soundEnabled)
return;
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channel == -1)
{
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
{
channels[i].state = JA_CHANNEL_FREE;
channels[i].pos = 0;
channels[i].sound = NULL;
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
}
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
{
channels[channel].state = JA_CHANNEL_FREE;
channels[channel].pos = 0;
channels[channel].sound = NULL;
@@ -290,15 +353,18 @@ void JA_StopChannel(const int channel)
JA_Channel_state JA_GetChannelState(const int channel)
{
if (!JA_soundEnabled) return JA_SOUND_DISABLED;
if (!JA_soundEnabled)
return JA_SOUND_DISABLED;
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS)
return JA_CHANNEL_INVALID;
return channels[channel].state;
}
int JA_SetSoundVolume(int volume)
{
JA_soundVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume;
JA_soundVolume = volume > 128 ? 128 : volume < 0 ? 0
: volume;
return JA_soundVolume;
}
@@ -306,15 +372,17 @@ void JA_EnableSound(const bool value)
{
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
{
if (channels[i].state == JA_CHANNEL_PLAYING) JA_StopChannel(i);
if (channels[i].state == JA_CHANNEL_PLAYING)
JA_StopChannel(i);
}
JA_soundEnabled = value;
}
int JA_SetVolume(int volume)
{
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume;
JA_soundVolume = JA_musicVolume/2;
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0
: volume;
JA_soundVolume = JA_musicVolume / 2;
return JA_musicVolume;
}

View File

@@ -1,17 +1,31 @@
#pragma once
#include <SDL2/SDL_audio.h> // for SDL_AudioFormat
#include <SDL2/SDL_stdinc.h> // for Uint32, Uint8
struct JA_Music_t; // lines 5-5
struct JA_Sound_t; // lines 6-6
#include <SDL2/SDL_audio.h> // para SDL_AudioFormat
#include <SDL2/SDL_stdinc.h> // para Uint32, Uint8
struct JA_Music_t; // lines 5-5
struct JA_Sound_t; // lines 6-6
enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED, JA_SOUND_DISABLED };
enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED, JA_MUSIC_DISABLED };
enum JA_Channel_state
{
JA_CHANNEL_INVALID,
JA_CHANNEL_FREE,
JA_CHANNEL_PLAYING,
JA_CHANNEL_PAUSED,
JA_SOUND_DISABLED
};
enum JA_Music_state
{
JA_MUSIC_INVALID,
JA_MUSIC_PLAYING,
JA_MUSIC_PAUSED,
JA_MUSIC_STOPPED,
JA_MUSIC_DISABLED
};
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels);
void JA_Quit();
JA_Music_t *JA_LoadMusic(const char* filename);
JA_Music_t *JA_LoadMusic(const char *filename);
void JA_PlayMusic(JA_Music_t *music, const int loop = -1);
void JA_PauseMusic();
void JA_ResumeMusic();
@@ -21,8 +35,8 @@ void JA_DeleteMusic(JA_Music_t *music);
int JA_SetMusicVolume(int volume);
void JA_EnableMusic(const bool value);
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length);
JA_Sound_t *JA_LoadSound(const char* filename);
JA_Sound_t *JA_NewSound(Uint8 *buffer, Uint32 length);
JA_Sound_t *JA_LoadSound(const char *filename);
int JA_PlaySound(JA_Sound_t *sound, const int loop = 0);
void JA_PauseChannel(const int channel);
void JA_ResumeChannel(const int channel);

View File

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

View File

@@ -1,10 +1,10 @@
#ifndef NO_SHADERS
#include "jail_shader.h"
#include <SDL2/SDL_rect.h> // for SDL_Point
#include <stdlib.h> // for NULL, free, malloc, exit
#include <string.h> // for strncmp
#include <iostream> // for basic_ostream, char_traits, operator<<
#include <SDL2/SDL_rect.h> // para SDL_Point
#include <stdlib.h> // para NULL, free, malloc, exit
#include <string.h> // para strncmp
#include <iostream> // para basic_ostream, char_traits, operator<<
#ifdef __APPLE__
#include "CoreFoundation/CoreFoundation.h"
@@ -14,7 +14,7 @@
#include <OpenGL/gl3.h>
#else
#include <OpenGL/gl.h>
#endif //!ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#endif //! ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#else
#include <SDL2/SDL_opengl.h>
#endif
@@ -24,12 +24,12 @@ namespace shader
SDL_Window *win = nullptr;
SDL_Renderer *renderer = nullptr;
GLuint programId = 0;
SDL_Texture* backBuffer = nullptr;
SDL_Point win_size = {320*4, 256*4};
SDL_Texture *backBuffer = nullptr;
SDL_Point win_size = {320 * 4, 256 * 4};
SDL_Point tex_size = {320, 256};
bool usingOpenGL;
#ifndef __APPLE__
#ifndef __APPLE__
// I'm avoiding the use of GLEW or some extensions handler, but that
// doesn't mean you should...
@@ -47,7 +47,8 @@ namespace shader
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
PFNGLUSEPROGRAMPROC glUseProgram;
bool initGLExtensions() {
bool initGLExtensions()
{
glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader");
glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource");
glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader");
@@ -63,55 +64,59 @@ namespace shader
glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram");
return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv &&
glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram &&
glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog &&
glUseProgram;
glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram &&
glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog &&
glUseProgram;
}
#endif
#endif
GLuint compileShader(const char* source, GLuint shaderType) {
GLuint compileShader(const char *source, GLuint shaderType)
{
// Create ID for shader
GLuint result = glCreateShader(shaderType);
// Add define depending on shader type
const char *sources[2] = { shaderType==GL_VERTEX_SHADER?"#define VERTEX\n":"#define FRAGMENT\n", source };
const char *sources[2] = {shaderType == GL_VERTEX_SHADER ? "#define VERTEX\n" : "#define FRAGMENT\n", source};
// Define shader text
glShaderSource(result, 2, sources, NULL);
// Compile shader
glCompileShader(result);
//Check vertex shader for errors
// Check vertex shader for errors
GLint shaderCompiled = GL_FALSE;
glGetShaderiv( result, GL_COMPILE_STATUS, &shaderCompiled );
if( shaderCompiled != GL_TRUE ) {
glGetShaderiv(result, GL_COMPILE_STATUS, &shaderCompiled);
if (shaderCompiled != GL_TRUE)
{
std::cout << "Error en la compilación: " << result << "!" << std::endl;
GLint logLength;
glGetShaderiv(result, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar *log = (GLchar*)malloc(logLength);
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(result, logLength, &logLength, log);
std::cout << "Shader compile log:" << log << std::endl;
free(log);
}
glDeleteShader(result);
result = 0;
// } else {
// std::cout << "Shader compilado correctamente. Id = " << result << std::endl;
// } else {
// std::cout << "Shader compilado correctamente. Id = " << result << std::endl;
}
return result;
}
GLuint compileProgram(const char* vertexShaderSource, const char* fragmentShaderSource) {
GLuint compileProgram(const char *vertexShaderSource, const char *fragmentShaderSource)
{
GLuint programId = 0;
GLuint vtxShaderId, fragShaderId;
programId = glCreateProgram();
vtxShaderId = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
fragShaderId = compileShader(fragmentShaderSource?fragmentShaderSource:vertexShaderSource, GL_FRAGMENT_SHADER);
fragShaderId = compileShader(fragmentShaderSource ? fragmentShaderSource : vertexShaderSource, GL_FRAGMENT_SHADER);
if(vtxShaderId && fragShaderId) {
if (vtxShaderId && fragShaderId)
{
// Associate shader with program
glAttachShader(programId, vtxShaderId);
glAttachShader(programId, fragShaderId);
@@ -121,24 +126,28 @@ namespace shader
// Check the status of the compile/link
GLint logLen;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);
if(logLen > 0) {
char* log = (char*) malloc(logLen * sizeof(char));
if (logLen > 0)
{
char *log = (char *)malloc(logLen * sizeof(char));
// Show any errors as appropriate
glGetProgramInfoLog(programId, logLen, &logLen, log);
std::cout << "Prog Info Log: " << std::endl << log << std::endl;
std::cout << "Prog Info Log: " << std::endl
<< log << std::endl;
free(log);
}
}
if(vtxShaderId) {
if (vtxShaderId)
{
glDeleteShader(vtxShaderId);
}
if(fragShaderId) {
if (fragShaderId)
{
glDeleteShader(fragShaderId);
}
return programId;
}
const bool init(SDL_Window* win, SDL_Texture* backBuffer, const char* vertexShader, const char* fragmentShader)
const bool init(SDL_Window *win, SDL_Texture *backBuffer, const char *vertexShader, const char *fragmentShader)
{
shader::win = win;
shader::renderer = SDL_GetRenderer(win);
@@ -155,19 +164,23 @@ namespace shader
SDL_RendererInfo rendererInfo;
SDL_GetRendererInfo(renderer, &rendererInfo);
if(!strncmp(rendererInfo.name, "opengl", 6)) {
//std::cout << "Es OpenGL!" << std::endl;
#ifndef __APPLE__
if (!initGLExtensions()) {
if (!strncmp(rendererInfo.name, "opengl", 6))
{
// std::cout << "Es OpenGL!" << std::endl;
#ifndef __APPLE__
if (!initGLExtensions())
{
std::cout << "WARNING: No s'han pogut inicialitzar les extensions d'OpenGL!" << std::endl;
usingOpenGL = false;
return false;
}
#endif
#endif
// Compilar el shader y dejarlo listo para usar.
programId = compileProgram(vertexShader, fragmentShader);
//std::cout << "programId = " << programId << std::endl;
} else {
// std::cout << "programId = " << programId << std::endl;
}
else
{
std::cout << "WARNING: El driver del renderer no es OpenGL." << std::endl;
usingOpenGL = false;
return false;
@@ -180,16 +193,18 @@ namespace shader
{
GLint oldProgramId;
// Guarrada para obtener el textureid (en driverdata->texture)
//Detach the texture
// Detach the texture
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderClear(renderer);
if (usingOpenGL) {
if (usingOpenGL)
{
SDL_GL_BindTexture(backBuffer, NULL, NULL);
if(programId != 0) {
glGetIntegerv(GL_CURRENT_PROGRAM,&oldProgramId);
if (programId != 0)
{
glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgramId);
glUseProgram(programId);
}
@@ -210,21 +225,24 @@ namespace shader
glViewport(0, 0, win_size.x, win_size.y);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(minu, minv);
glVertex2f(minx, miny);
glTexCoord2f(maxu, minv);
glVertex2f(maxx, miny);
glTexCoord2f(minu, maxv);
glVertex2f(minx, maxy);
glTexCoord2f(maxu, maxv);
glVertex2f(maxx, maxy);
glTexCoord2f(minu, minv);
glVertex2f(minx, miny);
glTexCoord2f(maxu, minv);
glVertex2f(maxx, miny);
glTexCoord2f(minu, maxv);
glVertex2f(minx, maxy);
glTexCoord2f(maxu, maxv);
glVertex2f(maxx, maxy);
glEnd();
SDL_GL_SwapWindow(win);
if(programId != 0) {
if (programId != 0)
{
glUseProgram(oldProgramId);
}
} else {
}
else
{
SDL_RenderCopy(renderer, backBuffer, NULL, NULL);
SDL_RenderPresent(renderer);
}

View File

@@ -2,8 +2,8 @@
#pragma once
#include <SDL2/SDL_render.h> // for SDL_Texture
#include <SDL2/SDL_video.h> // for SDL_Window
#include <SDL2/SDL_render.h> // para SDL_Texture
#include <SDL2/SDL_video.h> // para SDL_Window
// TIPS:
// =======================================================================
@@ -40,8 +40,8 @@
namespace shader
{
const bool init(SDL_Window* win, SDL_Texture* backBuffer,
const char* vertexShader, const char* fragmentShader=nullptr);
const bool init(SDL_Window *win, SDL_Texture *backBuffer,
const char *vertexShader, const char *fragmentShader = nullptr);
void render();
}

View File

@@ -1,6 +1,6 @@
#include "lang.h"
#include <fstream> // for basic_ifstream, basic_istream, ifstream
#include <vector> // for vector
#include <fstream> // para basic_ifstream, basic_istream, ifstream
#include <vector> // para vector
namespace lang
{
@@ -40,4 +40,12 @@ namespace lang
{
return texts.at(index);
}
// Cambia el idioma seleccionado al siguiente idioma disponible
Code change(Code current_lang)
{
auto index = static_cast<int>(current_lang);
index = (index + 1) % 3;
return static_cast<Code>(index);
}
}

View File

@@ -1,6 +1,6 @@
#pragma once
#include <string> // for string
#include <string> // para string
namespace lang
{
@@ -16,4 +16,7 @@ namespace lang
// Obtiene la cadena de texto del indice
std::string getText(int index);
// Cambia el idioma seleccionado al siguiente idioma disponible
Code change(Code current_lang);
}

View File

@@ -1,60 +1,65 @@
#include "logo.h"
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
#include <utility> // for move
#include "asset.h" // for Asset
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_StopMusic
#include "param.h" // for param
#include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <utility> // Para move
#include "global_inputs.h" // Para check
#include "input.h" // Para Input
#include "jail_audio.h" // Para JA_StopMusic
#include "param.h" // Para Param, ParamGame, param
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, name, Options, options
#include "sprite.h" // Para Sprite
#include "texture.h" // Para Texture
#include "utils.h" // Para Color, Zone
// Constructor
Logo::Logo()
: since_texture_(Resource::get()->getTexture("logo_since_1998.png")),
since_sprite_(std::make_unique<Sprite>(since_texture_)),
jail_texture_(Resource::get()->getTexture("logo_jailgames.png")),
ticks_(0)
{
// Copia la dirección de los objetos
SDL_Renderer *renderer = Screen::get()->getRenderer();
// Reserva memoria para los punteros
jail_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("logo_jailgames.png"));
since_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("logo_since_1998.png"));
since_sprite_ = std::make_unique<Sprite>((param.game.width - since_texture_->getWidth()) / 2, 83 + jail_texture_->getHeight() + 5, since_texture_->getWidth(), since_texture_->getHeight(), since_texture_);
// Inicializa variables
counter_ = 0;
section::name = section::Name::LOGO;
ticks_ = 0;
dest_.x = param.game.game_area.center_x - jail_texture_->getWidth() / 2;
dest_.y = param.game.game_area.center_y - jail_texture_->getHeight() / 2;
since_sprite_->setPosY(dest_.y + jail_texture_->getHeight() + 5);
since_sprite_->setPosition({(param.game.width - since_texture_->getWidth()) / 2, 83 + jail_texture_->getHeight() + 5, since_texture_->getWidth(), since_texture_->getHeight()});
since_sprite_->setY(dest_.y + jail_texture_->getHeight() + 5);
since_sprite_->setSpriteClip(0, 0, since_texture_->getWidth(), since_texture_->getHeight());
since_texture_->setColor(0x00, 0x00, 0x00); // Esto en linux no hace nada ??
// Crea los sprites de cada linea
for (int i = 0; i < jail_texture_->getHeight(); ++i)
{
auto temp = std::make_unique<Sprite>(0, i, jail_texture_->getWidth(), 1, jail_texture_);
auto temp = std::make_unique<Sprite>(jail_texture_, 0, i, jail_texture_->getWidth(), 1);
temp->setSpriteClip(0, i, jail_texture_->getWidth(), 1);
const int posX = (i % 2 == 0) ? param.game.width + (i * 3) : -jail_texture_->getWidth() - (i * 3);
temp->setPosX(posX);
temp->setPosY(dest_.y + i);
temp->setX(posX);
temp->setY(dest_.y + i);
jail_sprite_.push_back(std::move(temp));
}
// Inicializa el vector de colores
color_.push_back({0x00, 0x00, 0x00}); // Black
color_.push_back({0x00, 0x00, 0xd8}); // Blue
color_.push_back({0xd8, 0x00, 0x00}); // Red
color_.push_back({0xd8, 0x00, 0xd8}); // Magenta
color_.push_back({0x00, 0xd8, 0x00}); // Green
color_.push_back({0x00, 0xd8, 0xd8}); // Cyan
color_.push_back({0xd8, 0xd8, 0x00}); // Yellow
color_.push_back({0xFF, 0xFF, 0xFF}); // Bright white
color_.push_back(Color(0x00, 0x00, 0x00)); // Black
color_.push_back(Color(0x00, 0x00, 0xd8)); // Blue
color_.push_back(Color(0xd8, 0x00, 0x00)); // Red
color_.push_back(Color(0xd8, 0x00, 0xd8)); // Magenta
color_.push_back(Color(0x00, 0xd8, 0x00)); // Green
color_.push_back(Color(0x00, 0xd8, 0xd8)); // Cyan
color_.push_back(Color(0xd8, 0xd8, 0x00)); // Yellow
color_.push_back(Color(0xFF, 0xFF, 0xFF)); // Bright white
}
// Destructor
Logo::~Logo()
{
jail_texture_->setColor(255, 255, 255);
since_texture_->setColor(255, 255, 255);
JA_PauseChannel(-1);
}
// Recarga todas las texturas
@@ -75,6 +80,7 @@ void Logo::checkEvents()
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
@@ -101,9 +107,6 @@ void Logo::checkInput()
return;
}
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check();
}
@@ -111,26 +114,31 @@ void Logo::checkInput()
// Gestiona el logo de JAILGAME
void Logo::updateJAILGAMES()
{
if (counter_ == 30)
{
JA_PlaySound(Resource::get()->getSound("logo.wav"));
}
if (counter_ > 30)
{
for (int i = 0; i < (int)jail_sprite_.size(); ++i)
{
if (jail_sprite_[i]->getIntPosX() != dest_.x)
if (jail_sprite_[i]->getX() != dest_.x)
{
if (i % 2 == 0)
{
jail_sprite_[i]->incPosX(-SPEED);
if (jail_sprite_[i]->getIntPosX() < dest_.x)
jail_sprite_[i]->incX(-SPEED);
if (jail_sprite_[i]->getX() < dest_.x)
{
jail_sprite_[i]->setPosX(dest_.x);
jail_sprite_[i]->setX(dest_.x);
}
}
else
{
jail_sprite_[i]->incPosX(SPEED);
if (jail_sprite_[i]->getIntPosX() > dest_.x)
jail_sprite_[i]->incX(SPEED);
if (jail_sprite_[i]->getX() > dest_.x)
{
jail_sprite_[i]->setPosX(dest_.x);
jail_sprite_[i]->setX(dest_.x);
}
}
}
@@ -166,7 +174,8 @@ void Logo::updateTextureColors()
// Actualiza las variables
void Logo::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
{
// Actualiza el contador de ticks
@@ -192,6 +201,9 @@ void Logo::update()
{
section::name = section::Name::INTRO;
}
// Actualiza las variables de globalInputs
globalInputs::update();
}
}

Some files were not shown because too many files have changed in this diff Show More