167 Commits

Author SHA1 Message Date
84595da13a EnterName: si has plenat tots els slots de lletres, apretar una volta mes el de fixar lletra fixa el nom 2025-02-07 14:15:18 +01:00
01591175ef Pos pense que ja està tot apanyat lo de EnterName i Scoreboard 2025-02-07 13:45:07 +01:00
29bc4a64fd Afegit position_overflow_ per a EnterName i poder plenar tots els slots de lletres 2025-02-07 12:31:59 +01:00
559210652f Treballant en scoreboard::fillPanelTextures 2025-02-06 20:58:15 +01:00
44e4ca490d canvi de pc
treballant en enter name
2025-02-06 14:59:25 +01:00
3cebee2ae4 Implementat control de repetició per als eixos del joystick 2025-02-06 12:36:16 +01:00
270d7d1848 Duplicada la font 04b_25 per a tindre versió gris i versió negra. La gris es la que es por modular amb colors.
Eliminada la font nokia que ja no s'estava utilitzant.
Optimitzada la càrrega de fonts al permetre reutilitzar fitxers .txt de altres fonts
2025-02-06 10:31:32 +01:00
ccf005dce1 Afegit el disparador per a la aparició del enemic nou 2025-02-06 09:59:58 +01:00
5755947ff7 La tabla de puntuació ja mostra amb altre color la puntuació que s'acaba d'afegir
fix: la tabla de punts no guardava a disc el estat de 1CC de cada entrada
2025-02-05 22:52:19 +01:00
6f594b9a1f La tabla de puntuacions ja mostra aquelles aconseguides amb 1CC 2025-02-05 15:15:48 +01:00
7e2021da70 canvi de pc 2025-02-05 10:17:49 +01:00
0a9a92d4b7 El text de la tabla de puntuacion ja ix centrat i el "diferent" es el que fa 10 2025-02-05 09:45:30 +01:00
b01763b749 Dels credits ja passa a la tabla de puntuacions 2025-01-26 21:15:13 +01:00
59b9f61d69 Font nova per a la intro 2025-01-26 21:05:43 +01:00
b9f194a2b1 Afegit efecte d'eixida a les instruccions 2025-01-26 20:16:43 +01:00
59936f13eb Arreglos estetics i de colorets en hiscore_table.cpp 2025-01-26 17:48:10 +01:00
bad0a10328 Ja es mouen els sprites en hiscore_table.cpp, falta decidir-se per un disseny concret 2025-01-25 22:57:49 +01:00
52a0c2b91f Treballant en la nova tabla de records: ja pinta amb sprites 2025-01-25 21:17:45 +01:00
f12a456017 Alguns arreglos en updateTimeStopped() 2025-01-25 18:51:39 +01:00
f39e65afaf Ja no se que he tocat i qué no, cosetes del malo nou 2025-01-25 18:47:06 +01:00
d3183237df Estandaritzats els noms dels fitxers de audio
Eliminat el soroll de TNT que feia ANYS que no existía
2025-01-25 18:15:49 +01:00
60302004f4 Afegits efectes de audio nous
Retocats alguns efectes de audio al afagar items per a no solapar dos audios
2025-01-25 18:11:24 +01:00
e60938cb19 El malo nou ja suca cosetes, falta ajustar un poc els paràmetres 2025-01-25 17:41:45 +01:00
2b3cc719ba Fix del fix: aaaara si que lleva el garbage de la zona negra. Havia posat el clean() on no tocava 2025-01-25 13:14:25 +01:00
d01c91ebde Fix: m'havia carregat el shakeEffect() de la pantalla quan havia shaders, i de paso he vist que el que tenbia fet shakejava també les notificacions i els menus de debug. Ale, ja està tot arreglaet.
Fix: tampoc estava netejant la pantalla, pensava que no feia falta, pero quan SDL replena de negre la finestra en pantalla completa, havia gorrinades
2025-01-24 20:20:50 +01:00
7130f2298a Merge branch 'main' of https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition 2025-01-24 10:44:58 +01:00
380cc17861 Fix: ara apaga el sistem al final del tot, almenys quan ja ha escrit la configuració a disc 2025-01-24 10:43:00 +01:00
a5388873e3 Actualizar README.md 2025-01-05 15:47:51 +01:00
28b37af31d Actualitzada la data de la versió 2025-01-05 14:38:48 +01:00
4d590f79f5 fix: es podia pulsar per a jugar mentre feia el fade cap a la demo 2025-01-05 14:36:38 +01:00
91c8797d7f Screen: optimitzat el circuit de render en pantalla 2025-01-05 14:17:49 +01:00
f207985180 Retocs en el punter del ratolí per al mode ARCADE 2025-01-05 13:44:10 +01:00
a16131335b hi_score_table: actualitzat el fondo amb els elements nous 2025-01-05 13:41:09 +01:00
871e8da642 Corregit el timing de la música en la animació inicial del joc 2025-01-05 13:27:45 +01:00
90b3db8f06 El atenuat de pantalla torna a funcionar. Fade feia dos SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE); que mai tornava a restaurar 2025-01-05 13:07:20 +01:00
668e8e237a Actualitzat README.md 2025-01-05 12:52:14 +01:00
768f466b20 canviat blit() per render() 2025-01-05 10:45:05 +01:00
1f8f9b11ed Segona pasaeta de IWYU 2025-01-05 10:36:17 +01:00
39f61884b0 Pasaeta de IWYU 2025-01-05 10:22:20 +01:00
b1193bd8fd fix: error en la seqüència final de retrocedir en el temps 2025-01-05 09:51:33 +01:00
7f9e2e53e3 Optimitzat el renderitzat dels credits 2025-01-05 09:44:08 +01:00
4cf4c8db6f fix: arreglada la acceleració dels credits sense dependre de vsync 2025-01-05 09:31:57 +01:00
cd806363e8 Modificat el color dels nuvols de la última pantalla
debug: opció de no crear mes globos
2025-01-05 09:22:30 +01:00
198aa45d59 Afegida una lluna i un sol al fondo 2025-01-05 07:32:30 +01:00
0711c8dada fix: al fer el init de stage no es buidava el vector i cada volta afegia mes stages 2025-01-05 07:29:33 +01:00
e1aaad0903 fix: Havia deixat comentat un IF fent proves 2025-01-04 17:01:24 +01:00
b53ee12f56 La powerball ja no es pot destruir fins que no ha fet un rebot 2025-01-04 16:57:50 +01:00
7b6d429bed fix: un vuelo rasante havia trencat els credits 2025-01-04 14:27:37 +01:00
81ee352553 Afegit un lock per evitar que es puga incrementar el poder de la fase
Es necesita almenys un jugador viu per a poder incrementar el poder de la fase
2025-01-04 14:09:10 +01:00
7b8f16610a Afegits estats al fade
Afegida opció de prefade
El modo demo ja comença a meitat del "meollo"
2025-01-04 13:40:22 +01:00
06eb05f065 Canviat un poc el color del segon cel 2025-01-04 12:44:24 +01:00
bccf4c30de Modificada la cadencia de foc sense autofire i arreglades un poc les animacions de cool_down i cooling 2025-01-04 10:47:26 +01:00
5e817ef1d0 Afegit el tamany de la coffee_machine als parametres 2025-01-04 10:04:49 +01:00
eaab646cd3 Modificades les paletes de invulnerabilitat 2025-01-04 09:21:58 +01:00
e887c2a2ab Afegida la opció de crear els globos sense temps de creació en el balloon_manager
Modificat el mode demo per a que la primera oleada estiga ja creada
2025-01-04 00:42:57 +01:00
f573bd02ac El case de les variables en mouse.cpp i mouse.h era incorrecte 2025-01-03 23:57:45 +01:00
b586a117c8 Afegit mouse.cpp per amagar el cursor quan no està moventse 2025-01-03 23:35:48 +01:00
08dfaf7641 Errors tipografics en varios comentaris 2025-01-03 22:48:45 +01:00
ff7f5ea131 Modificada la seqëncia d'inici per a que la musica començe antes 2025-01-03 22:13:46 +01:00
7cc4a2002a Modificat el copyright de 2024 a 2025 2025-01-03 22:04:29 +01:00
de81b798b0 Afegit custom fadeout de so sincronitzat amb el fadeout de video per a quan acaba la partida 2025-01-03 22:02:48 +01:00
5669715285 Input mostra també el numero de joysticks que ha trobat 2025-01-03 21:29:22 +01:00
6531106933 Quedaven mes SDL_Log en jail_audio 2025-01-03 21:28:55 +01:00
51191b1906 Eliminat SDL_Log 2025-01-03 21:21:52 +01:00
6effeb6154 Quan el jugador moria podia quedarse engantxat rebotant en les vores
So aleatori en els rebots del jugador al morir
2025-01-03 20:36:18 +01:00
8c2b1ce649 Separats els estats de joc completat i joc acabat del estat joc jugantse
Al completar el joc, el missatge de game over ja no ix fins que desapareixen els textos anteriors
2025-01-03 19:53:09 +01:00
cc4acecc03 Afegits sons de caminar i de comptador de continuar
Afegits estats al joc i al jugador per a escenificar el inici de la partida
2025-01-03 19:19:22 +01:00
40dfc32e84 Actualitzada la data de la versió 2024-12-31 10:23:01 +01:00
4cd1d91560 Actualitzat jail_audio 2024-12-30 20:08:08 +01:00
e43badd703 Merge branch 'main' of https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition 2024-12-30 20:06:04 +01:00
71dcf9cf87 Afegit coffee.res, coffee.rc i icon.ico per a tindre iconet en windows 2024-12-30 19:56:35 +01:00
3a8521a1da Arreglat windows_release en Makefile 2024-12-30 19:56:00 +01:00
74d9c9a2b9 Commit per a vore qué està passant amb la música 2024-12-30 19:07:13 +01:00
9532caace8 Arreglades les release de windows, linux i raspberry 2024-12-30 13:44:09 +01:00
0bbd14067a Text::writeToTexture no deixava el renderitzador com estava 2024-12-30 13:43:12 +01:00
cfaa143c44 Actualitzat jail_audio 2024-12-30 13:30:06 +01:00
e61daeb92e Modificats els grafics del enemic nou
Afegits nous audios i veus
Completat el comportament del enemic nou
Ampliat el numero máxim de sons simultanis
2024-12-28 21:23:04 +01:00
d57cc15aee Treballant en el enemic nou 2024-12-27 13:38:07 +01:00
de3b18a407 Posat ordre en el Attract Mode 2024-12-26 13:58:25 +01:00
7f444fef33 Fix: mil minibugs relacionats amb el audio 2024-12-26 10:39:48 +01:00
ca18baefd7 Fix: el modo demo desactivava els sons i ja no s'activaven mai mes 2024-12-26 10:05:41 +01:00
b8dca0a46f Fet el fade out del title de video i audio i el fade in del joc de video i audio
Actualitzat jail_audio a la última versió
2024-12-26 10:03:02 +01:00
ca2c48ea17 Au, paca casa. M'he quedat a mitjes fent un fade de audio sincronitzat amb el fade de video en el titol 2024-12-23 13:56:11 +01:00
fb4d0d12db Afegits roidets de colisió per als globos per a certs moments 2024-12-23 12:37:19 +01:00
fb31445731 Comprova al iniciar que el tamany de finestra no siga mes gran que el tamany de la pantalla 2024-12-23 11:22:26 +01:00
cf4f0459b3 Es pot fer la finestra tan gran com deixe la pantalla, es a dir, el factor de zoom ja no va de 1 a 4 sino de 1 a X 2024-12-23 11:13:14 +01:00
fe0900a686 Afegides veus al jugador
Afegit efectes de so al rebotar el jugador quan mor
2024-12-15 20:00:35 +01:00
3367b70cd5 Afegit delay opcional al flash de la classe Screen 2024-12-09 20:06:59 +01:00
7016849587 FIX: afegit StopChannel en lloc de PauseChannel en el destructor del Logo
Retocada la animació del logo del joc en Title
2024-12-09 19:08:22 +01:00
301c059a26 Afegit botó per activar o desactivar el autofire 2024-12-05 12:24:18 +01:00
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
155 changed files with 7856 additions and 5515 deletions

3
.gitignore vendored
View File

@@ -15,4 +15,5 @@ thumbs.db
*score.bin
coffee_crisis*
debug.txt
cppcheck-result*
cppcheck-result*
desktop.ini

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()

243
Makefile
View File

@@ -1,136 +1,63 @@
# Directorios
DIR_ROOT := $(dir $(abspath $(MAKEFILE_LIST)))
DIR_SOURCES:= $(addsuffix /, $(DIR_ROOT)source)
DIR_BIN := $(addsuffix /, $(DIR_ROOT))
DIR_BUILD := $(addsuffix /, $(DIR_ROOT)build)
DIR_ROOT := $(dir $(abspath $(MAKEFILE_LIST)))
DIR_SOURCES := $(addsuffix /, $(DIR_ROOT)source)
DIR_BIN := $(addsuffix /, $(DIR_ROOT))
DIR_BUILD := $(addsuffix /, $(DIR_ROOT)build)
# Variables
TARGET_NAME := coffee_crisis_arcade_edition
TARGET_FILE := $(DIR_BIN)$(TARGET_NAME)
APP_NAME := Coffee Crisis Arcade Edition
RELEASE_FOLDER:= ccae_release
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
VERSION := v0.01
TARGET_NAME := coffee_crisis_arcade_edition
TARGET_FILE := $(DIR_BIN)$(TARGET_NAME)
APP_NAME := Coffee Crisis Arcade Edition
RELEASE_FOLDER := ccae_release
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
RESOURCE_FILE := release/coffee.res
VERSION := 2025-02-07
# Nombres para los ficheros de lanzamiento
WINDOWS_RELEASE := $(TARGET_FILE)-$(VERSION)-win32-x64.zip
MACOS_INTEL_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-intel.dmg
MACOS_APPLE_SILICON_RELEASE:= $(TARGET_FILE)-$(VERSION)-macos-apple-silicon.dmg
LINUX_RELEASE := $(TARGET_FILE)-$(VERSION)-linux.tar.gz
WINDOWS_RELEASE := $(TARGET_NAME)-$(VERSION)-win32-x64.zip
MACOS_INTEL_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-intel.dmg
MACOS_APPLE_SILICON_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-apple-silicon.dmg
LINUX_RELEASE := $(TARGET_FILE)-$(VERSION)-linux.tar.gz
RASPI_RELEASE := $(TARGET_FILE)-$(VERSION)-raspberry.tar.gz
# Includes
INCLUDES:= -I$(DIR_SOURCES)
INCLUDES := -I$(DIR_SOURCES)
# Variables según el sistema operativo
ifeq ($(OS),Windows_NT)
FixPath = $(subst /,\,$1)
SOURCES := source/*.cpp
CXXFLAGS:= -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows
CXXFLAGS_DEBUG:= -std=c++20 -Wall -g
LDFLAGS := -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32
RM = del /Q
MKD:= mkdir
FixPath = $(subst /,\\,$1)
SOURCES := source/*.cpp
CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows
CXXFLAGS_DEBUG := -std=c++20 -Wall -g
LDFLAGS := -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32
RM := del /Q
MKDIR := mkdir
else
FixPath = $1
SOURCES := $(shell find $(DIR_SOURCES) -name '*.cpp')
SOURCES := source/*.cpp
CXXFLAGS:= -std=c++20 -Wall -Os -ffunction-sections -fdata-sections
CXXFLAGS_DEBUG:= -std=c++20 -Wall -g
LDFLAGS := -lSDL2
RM = rm -f
MKD:= mkdir -p
UNAME_S := $(shell uname -s)
FixPath = $1
SOURCES := $(shell find $(DIR_SOURCES) -name '*.cpp')
SOURCES := source/*.cpp
CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections
CXXFLAGS_DEBUG := -std=c++20 -Wall -g
LDFLAGS := -lSDL2
RMFILE := rm -f
RMDIR := rm -rdf
MKDIR := mkdir -p
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
LDFLAGS += -lGL
LDFLAGS += -lGL
endif
ifeq ($(UNAME_S),Darwin)
CXXFLAGS += -Wno-deprecated
CXXFLAGS_DEBUG += -Wno-deprecated
LDFLAGS += -framework OpenGL
CXXFLAGS += -Wno-deprecated
CXXFLAGS_DEBUG += -Wno-deprecated
LDFLAGS += -framework OpenGL
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"
# Reglas para compilación
windows:
@echo off
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE).exe"
windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
$(CXX) $(SOURCES) $(RESOURCE_FILE) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE).exe"
strip -s -R .comment -R .gnu.version "$(TARGET_FILE).exe" --strip-unneeded
windows_rec:
@@ -157,12 +84,13 @@ windows_release:
powershell Copy-Item "release\*.dll" -Destination "$(RELEASE_FOLDER)"
# Compila
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE).exe"
strip -s -R .comment -R .gnu.version "$(RELEASE_FOLDER)/$(TARGET_FILE).exe" --strip-unneeded
windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
$(CXX) $(SOURCES) $(RESOURCE_FILE) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE).exe"
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE).exe" --strip-unneeded
# Crea el fichero .zip
powershell if (Test-Path $(WINDOWS_RELEASE)) {Remove-Item $(WINDOWS_RELEASE)}
powershell Compress-Archive -Path "$(RELEASE_FOLDER)"/* -DestinationPath $(WINDOWS_RELEASE)
powershell if (Test-Path "$(WINDOWS_RELEASE)") {Remove-Item "$(WINDOWS_RELEASE)"}
powershell Compress-Archive -Path "$(RELEASE_FOLDER)"/* -DestinationPath "$(WINDOWS_RELEASE)"
# Elimina la carpeta temporal 'RELEASE_FOLDER'
powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force}
@@ -175,17 +103,17 @@ macos_debug:
macos_release:
# Elimina datos de compilaciones anteriores
rm -rdf "$(RELEASE_FOLDER)"
rm -rdf Frameworks
rm -f tmp.dmg
rm -f "$(MACOS_INTEL_RELEASE)"
rm -f "$(MACOS_APPLE_SILICON_RELEASE)"
$(RMDIR) "$(RELEASE_FOLDER)"
$(RMDIR) Frameworks
$(RMFILE) tmp.dmg
$(RMFILE) "$(MACOS_INTEL_RELEASE)"
$(RMFILE) "$(MACOS_APPLE_SILICON_RELEASE)"
# Crea la carpeta temporal para hacer el trabajo y las carpetas obligatorias para crear una app de macos
mkdir -p "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
mkdir -p "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS"
mkdir -p "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
mkdir -p Frameworks
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS"
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
$(MKDIR) Frameworks
# Copia carpetas y ficheros
cp -R data "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
@@ -200,24 +128,24 @@ macos_release:
ln -s /Applications "$(RELEASE_FOLDER)"/Applications
# Compila la versión para procesadores Intel
$(CXX) $(SOURCES) -D MACOS_BUNDLE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_FILE)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.12
$(CXX) $(SOURCES) -D MACOS_BUNDLE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.12
# Empaqueta el .dmg de la versión Intel
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_INTEL_RELEASE)"
rm -f tmp.dmg
$(RMFILE) tmp.dmg
# Compila la versión para procesadores Apple Silicon
$(CXX) $(SOURCES) -D MACOS_BUNDLE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_FILE)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11
$(CXX) $(SOURCES) -D MACOS_BUNDLE -D SDL_DISABLE_IMMINTRIN_H $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11
# Empaqueta el .dmg de la versión Apple Silicon
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_APPLE_SILICON_RELEASE)"
rm -f tmp.dmg
$(RMFILE) tmp.dmg
# Elimina las carpetas temporales
$(RM) Frameworks
$(RM) "$(RELEASE_FOLDER)"
$(RMDIR) Frameworks
$(RMDIR) "$(RELEASE_FOLDER)"
linux:
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)"
@@ -228,10 +156,10 @@ linux_debug:
linux_release:
# Elimina carpetas previas
$(RM) "$(RELEASE_FOLDER)"
$(RMDIR) "$(RELEASE_FOLDER)"
# Crea la carpeta temporal para realizar el lanzamiento
mkdir -p "$(RELEASE_FOLDER)"
$(MKDIR) "$(RELEASE_FOLDER)"
# Copia ficheros
cp -R data "$(RELEASE_FOLDER)"
@@ -243,22 +171,51 @@ linux_release:
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
# Empaqueta ficheros
$(RM) "$(LINUX_RELEASE)"
cd "$(RELEASE_FOLDER)" && tar -czvf "../$(LINUX_RELEASE)" *
$(RMFILE) "$(LINUX_RELEASE)"
cd "$(RELEASE_FOLDER)" && tar -czvf "$(LINUX_RELEASE)" *
# Elimina la carpeta temporal
$(RM) "$(RELEASE_FOLDER)"
$(RMDIR) "$(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"
raspi_release:
# Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)"
# Crea la carpeta temporal para realizar el lanzamiento
$(MKDIR) "$(RELEASE_FOLDER)"
# Copia ficheros
cp -R data "$(RELEASE_FOLDER)"
cp LICENSE "$(RELEASE_FOLDER)"
cp README.md "$(RELEASE_FOLDER)"
# Complia
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
# Empaqueta ficheros
$(RMFILE) "$(LINUX_RELEASE)"
cd "$(RELEASE_FOLDER)" && tar -czvf "$(RASPI_RELEASE)" *
# Elimina la carpeta temporal
$(RMDIR) "$(RELEASE_FOLDER)"
anbernic:
# Elimina carpetas previas
$(RM) "$(RELEASE_FOLDER)"_anbernic
$(RMDIR) "$(RELEASE_FOLDER)"_anbernic
# Crea la carpeta temporal para realizar el lanzamiento
mkdir -p "$(RELEASE_FOLDER)"_anbernic
$(MKDIR) "$(RELEASE_FOLDER)"_anbernic
# Copia ficheros
cp -R data "$(RELEASE_FOLDER)"_anbernic
# Complia
$(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
# Compila
$(CXX) $(SOURCES) -D ANBERNIC -D NO_SHADERS -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(RELEASE_FOLDER)_anbernic/$(TARGET_NAME)

View File

@@ -1,39 +1,73 @@
# Coffee Crisis Arcade Edition
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.
**¡La batalla definitiva pel cafè està ací!**
Coffee Crisis Arcade Edition és una versió ampliada i millorada del aclamat Coffee Crisis. Aquesta versió porta l'acció cooperativa al següent nivell, amb:
- **Mode multijugador** per a dues persones.
- **Nous gràfics** que revitalitzen l'experiència arcade clàssica.
- **Moltes sorpreses** per descobrir en cada partida.
Defensa el teu cafè contra les bambolles gegants en aquest trepidant joc d'arcade! 🍵
<p align="center">
<img src="https://php.sustancia.synology.me/images/ccae_title.png" alt="Titol"
<img src="https://php.sustancia.synology.me/images/ccae_title.png" alt="Títol" width="60%" />
</p>
## 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:
* **Fletxes**: Mou al personatge
* **Q, W, E**: Disparar a la esquerra, al centre i a la dreta respectivament
El joc està optimitzat per a ser jugat amb un mando de jocs, encara que un dels jugadors pot utilitzar el teclat.
### Controls del teclat:
- **Fletxes**: Mou al personatge.
- **Q, W, E**: Disparar a l'esquerra, al centre i a la dreta, respectivament.
> Nota: El joc suporta nomes un jugador amb teclat.
<p align="center">
<img src="https://php.sustancia.synology.me/images/ccae1.png" alt="Joc"
<img src="https://php.sustancia.synology.me/images/ccae1.png" alt="Joc" width="45%" />
<img src="https://php.sustancia.synology.me/images/ccae3.png" alt="Joc" width="45%" />
</p>
## Altres tecles
- **Tecla ESC**: Tancar el joc
- **Tecla F1**: Fa la finestra mes xicoteta
- **Tecla F2**: Fa la finestra mes gran
- **Tecla F3**: Alterna entre el mode de pantalla completa i el de finestra
- **Tecla F4**: Activa o desactiva els shaders
- **Tecla F10**: Reset
| Tecla | Funció |
|-------------|----------------------------------------------|
| **ESC** | Tancar el joc |
| **F1** | Fa la finestra més xicoteta |
| **F2** | Fa la finestra més gran |
| **F3** | Alterna entre mode de pantalla completa i finestra |
| **F4** | Activa o desactiva els shaders |
| **F5** | Activa o desactiva l'àudio |
| **F6** | Activa o desactiva el dispar automàtic |
| **F7** | Canvia l'idioma del joc i reinicia |
| **F10** | Reset del joc |
<p align="center">
<img src="https://php.sustancia.synology.me/images/ccae2.png" alt="Joc"
<img src="https://php.sustancia.synology.me/images/ccae2.png" alt="Joc" width="50%" />
</p>
## Com instal·lar i jugar
1. Descarrega el joc des de [l'apartat de llançaments](https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition/releases).
2. Descomprimix i executa l'arxiu `coffee_crisis_arcade_edition.exe`.
3. Gaudeix del joc!
## Agraïments
Vull expressar la meua gratitud a **ChatGPT** i **GitHub Copilot**. Gràcies per ser un suport constant en el desenvolupament d'aquest joc!
També vull agrair a tots els jugadors que fan que aquest projecte valgui la pena. 🕹️❤️
## Com contribuir
Accepte contribucions! Si tens una idea o vols ajudar:
1. Fes un fork d'aquest repositori.
2. Crea una branca nova amb els teus canvis.
3. Fes un pull request.
## Llicència
Aquest joc està subjecte a una llicència [MIT](https://opensource.org/licenses/MIT). Consulta el fitxer LICENSE per a més detalls.
## Agraiments
A chatGPT i sobretot a Copilot. Gracies per estar sempre quan vos he necesitat.

View File

@@ -1,12 +1,14 @@
## GAME
game.item_size 20 # Tamaño de los items del juego
game.coffee_machine_w 28 # Ancho de la máquina de café
game.coffee_machine_h 37 # Alto de la máquina de café
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 30 # Duración en segundos para introducir el nombre al finalizar la partida
game.enter_name_seconds 60 # Duración en segundos para introducir el nombre al finalizar la partida
## FADE
fade.num_squares_width 160
@@ -14,7 +16,7 @@ fade.num_squares_height 120
fade.random_squares_delay 1
fade.random_squares_mult 500
fade.post_duration 80
fade.venetian_size 16
fade.venetian_size 12
## SCOREBOARD
scoreboard.x 0

View File

@@ -1,13 +1,14 @@
## GAME
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 30 # Duración en segundos para introducir el nombre al finalizar la partida
game.game_text.dest_y
game.item_size 20 # Tamaño de los items del juego
game.coffee_machine_w 28 # Ancho de la máquina de café
game.coffee_machine_h 37 # Alto de la máquina de café
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
@@ -15,7 +16,7 @@ fade.num_squares_height 128
fade.random_squares_delay 1
fade.random_squares_mult 500
fade.post_duration 80
fade.venetian_size 16
fade.venetian_size 12
## SCOREBOARD
scoreboard.x 0

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
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

BIN
data/font/04b_25_grey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
data/font/04b_25_metal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -1,194 +0,0 @@
# box width
10
# box height
10
# 32 espacio ( )
5
# 33 !
4
# 34 "
5
# 35 #
7
# 36 $
7
# 37 %
8
# 38 &
8
# 39 '
3
# 40 (
5
# 41 )
5
# 42 *
7
# 43 +
7
# 44 ,
4
# 45 -
6
# 46 .
4
# 47 /
5
# 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
6
# 75 K
8
# 76 L
6
# 77 M
9
# 78 N
8
# 79 O
8
# 80 P
7
# 81 Q
8
# 82 R
7
# 83 S
6
# 84 T
8
# 85 U
7
# 86 V
8
# 87 W
9
# 88 X
8
# 89 Y
8
# 90 Z
7
# 91 [
4
# 92 \
5
# 93 ]
4
# 94 ^
5
# 95 _
8
# 96 `
4
# 97 a
7
# 98 b
7
# 99 c
6
# 100 d
7
# 101 e
7
# 102 f
5
# 103 g
7
# 104 h
7
# 105 i
4
# 106 j
5
# 107 k
7
# 108 l
4
# 109 m
10
# 110 n
7
# 111 o
7
# 112 p
7
# 113 q
7
# 114 r
6
# 115 s
6
# 116 t
5
# 117 u
7
# 118 v
7
# 119 w
9
# 120 x
7
# 121 y
7
# 122 z
7
# 123 { -> ñ
7
# 124 | -> ç
7
# 125 }
0
# 126 ~
0

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: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,9 +1,9 @@
frame_width=46
frame_height=46
frame_width=49
frame_height=49
[animation]
name=powerball
speed=10
loop=-1
frames=0
frames=1
[/animation]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

BIN
data/gfx/game/game_moon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
data/gfx/game/game_sun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 B

View File

@@ -0,0 +1,9 @@
frame_width=20
frame_height=20
[animation]
name=default
speed=10
loop=0
frames=0,1
[/animation]

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 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

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

16
data/gfx/tabe/tabe.ani Normal file
View File

@@ -0,0 +1,16 @@
frame_width=32
frame_height=32
[animation]
name=fly
speed=2
loop=0
frames=0,1
[/animation]
[animation]
name=hit
speed=2
loop=0
frames=2,3
[/animation]

BIN
data/gfx/tabe/tabe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -32,7 +32,7 @@ IDIOMA
[ CANCELAR ]
## 11 - INSTRUCCIONES
OBJECTIU
Objectiu
## 12 - INSTRUCCIONES
HAS D'EXPLOTAR
@@ -47,7 +47,7 @@ LA DIFICULTAT AUGMENTA
A MESURA QUE VAS PUNTUANT
## 16 - INSTRUCCIONES
OBJECTES
Objectes
## 17 - INSTRUCCIONES
1.000 PUNTS
@@ -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
@@ -347,4 +347,28 @@ Per favor
espere
## 116 - NOTIFICACIONES
Torna a polsar per apagar el sistema
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
@@ -347,4 +347,28 @@ Please
wait
## 116 - NOTIFICACIONES
Press again to shutdown system
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
@@ -347,4 +347,28 @@ Por favor
espere
## 94 - NOTIFICACIONES
Pulsa otra vez para apagar el sistema
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;

Binary file not shown.

BIN
data/sound/debian_drop.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
data/sound/game_start.wav Normal file

Binary file not shown.

BIN
data/sound/logo.wav Normal file

Binary file not shown.

BIN
data/sound/tabe.wav Normal file

Binary file not shown.

BIN
data/sound/tabe_hit.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
data/sound/voice_coffee.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
data/sound/voice_no.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
data/sound/walk.wav Normal file

Binary file not shown.

View File

@@ -1,20 +0,0 @@
#!/bin/bash
# warning,style,performance
#cppcheck --force --enable=warning,style,performance --std=c++20 \
# --suppressions-list=/home/sergio/gitea/coffee_crisis_arcade_edition/linux-utils/cppcheck_suppressions \
# /home/sergio/gitea/coffee_crisis_arcade_edition/source/ \
# 2>/home/sergio/cppcheck-result-warning-style-performance.txt
# all
#cppcheck --force --enable=all -I /usr/include --std=c++20 \
#--suppress=missingIncludeSystem \
#--suppressions-list=/home/sergio/gitea/coffee_crisis_arcade_edition/linux-utils/cppcheck_suppressions \
#/home/sergio/gitea/coffee_crisis_arcade_edition/source/ \
#2>/home/sergio/cppcheck-result-all.txt
# unusedFunction
cppcheck --enable=style --std=c++20 \
--suppressions-list=./cppcheck_suppressions \
../source/ \
2>/home/sergio/cppcheck-result-all.txt

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

2
release/coffee.rc Normal file
View File

@@ -0,0 +1,2 @@
// coffee.rc
IDI_ICON1 ICON "icon.ico"

BIN
release/coffee.res Normal file

Binary file not shown.

BIN
release/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -2,12 +2,13 @@
#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
#include <cmath>
#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()
@@ -18,16 +19,22 @@ Background::Background()
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")),
sun_texture_(Resource::get()->getTexture("game_sun.png")),
moon_texture_(Resource::get()->getTexture("game_moon.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)),
attenuate_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)
{
// Precalcula rutas
createSunPath();
createMoonPath();
// Inicializa variables
{
gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
@@ -55,9 +62,11 @@ Background::Background()
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());
buildings_sprite_ = std::make_unique<Sprite>(buildings_texture_);
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);
sun_sprite_ = std::make_unique<Sprite>(sun_texture_);
moon_sprite_ = std::make_unique<Sprite>(moon_texture_);
}
// Inicializa objetos
@@ -79,6 +88,8 @@ Background::Background()
buildings_sprite_->setY(base_ - buildings_sprite_->getHeight());
grass_sprite_->setY(base_ - grass_sprite_->getHeight());
sun_sprite_->setPosition(sun_path_.front());
moon_sprite_->setPosition(moon_path_.front());
}
// Crea la textura para componer el fondo
@@ -88,7 +99,7 @@ Background::Background()
// Crea la textura para atenuar el fondo
color_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND);
setColor(color_);
setColor(attenuate_color_);
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_);
}
@@ -103,7 +114,7 @@ Background::~Background()
void Background::update()
{
// Actualiza el valor de alpha_
updateAlphaColorText();
updateAlphaColorTexture();
// Actualiza las nubes
updateClouds();
@@ -114,6 +125,10 @@ void Background::update()
// Calcula el valor de alpha_
alpha_ = std::max((255 - (int)(255 * transition_)), 0);
// Mueve el sol
sun_sprite_->setPosition(sun_path_.at(sun_index_));
moon_sprite_->setPosition(moon_path_.at(moon_index_));
// Incrementa el contador
++counter_;
@@ -181,6 +196,10 @@ void Background::fillCanvas()
// Dibuja el gradiente de fondo
renderGradient();
// Dibuja los astros
sun_sprite_->render();
moon_sprite_->render();
// Dibuja las nubes de arriba
renderTopClouds();
@@ -250,13 +269,13 @@ void Background::setPos(SDL_Rect pos)
// Establece el color_ de atenuación
void Background::setColor(Color color)
{
color_ = color;
attenuate_color_ = color;
// Colorea la textura
auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, color_texture_);
SDL_SetRenderDrawColor(renderer_, color_.r, color_.g, color_.b, 255);
SDL_SetRenderDrawColor(renderer_, attenuate_color_.r, attenuate_color_.g, attenuate_color_.b, 255);
SDL_RenderClear(renderer_);
SDL_SetRenderTarget(renderer_, temp);
@@ -274,7 +293,7 @@ void Background::setAlpha(int alpha)
}
// Actualiza el valor de alpha_
void Background::updateAlphaColorText()
void Background::updateAlphaColorTexture()
{
if (alpha_color_text_ == alpha_color_text_temp_)
{
@@ -322,4 +341,58 @@ void Background::updateClouds()
{
bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth());
}
}
// Precalcula el vector con el recorrido del sol
void Background::createSunPath()
{
constexpr int CENTER_X = 170;
const int center_y = base_ - 80;
constexpr int RADIUS = 120;
// Generar puntos de la curva desde 90 a 180 grados
for (double theta = M_PI / 2; theta <= M_PI; theta += 0.01)
{
int x = CENTER_X + static_cast<int>(RADIUS * cos(theta));
int y = center_y - static_cast<int>(RADIUS * sin(theta));
sun_path_.push_back({x, y});
}
// Agregar puntos en línea recta después de la curva
constexpr int EXTRA_PIXELS = 40;
SDL_Point last_point = sun_path_.back();
for (int i = 1; i <= EXTRA_PIXELS; ++i)
{
sun_path_.push_back({last_point.x, last_point.y + i});
}
}
// Precalcula el vector con el recorrido de la luna
void Background::createMoonPath()
{
constexpr int CENTER_X = 100;
const int center_y = base_ - 50;
constexpr int RADIUS = 140;
// Generar puntos de la curva desde 0 a 90 grados
for (double theta = 0; theta <= M_PI / 2; theta += 0.01)
{
int x = CENTER_X + static_cast<int>(RADIUS * cos(theta));
int y = center_y - static_cast<int>(RADIUS * sin(theta));
moon_path_.push_back({x, y});
}
}
// Establece la posición del sol
void Background::setSunProgression(float progress)
{
progress = std::clamp(progress, 0.0f, 1.0f);
sun_index_ = static_cast<size_t>(progress * (sun_path_.size() - 1));
}
// Establece la posición de la luna
void Background::setMoonProgression(float progress)
{
progress = std::clamp(progress, 0.0f, 1.0f);
moon_index_ = static_cast<size_t>(progress * (moon_path_.size() - 1));
}

View File

@@ -1,12 +1,14 @@
#pragma once
#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;
#include <SDL2/SDL_rect.h> // Para SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // Para SDL_Texture, SDL_Renderer
#include <stddef.h> // Para size_t
#include <memory> // Para unique_ptr, shared_ptr
#include <vector> // Para vector
#include "utils.h" // Para Color
class MovingSprite; // lines 7-7
class Sprite; // lines 8-8
class Texture; // lines 9-9
/*
Esta clase es la encargada de dibujar el fondo que aparece durante la sección
@@ -51,6 +53,8 @@ private:
std::shared_ptr<Texture> bottom_clouds_texture_; // Textura con las nubes de fondo
std::shared_ptr<Texture> grass_texture_; // Textura con la hierba del suelo
std::shared_ptr<Texture> gradients_texture_; // Textura con los diferentes colores de fondo del juego
std::shared_ptr<Texture> sun_texture_; // Textura con el sol
std::shared_ptr<Texture> moon_texture_; // Textura con la luna
std::unique_ptr<MovingSprite> top_clouds_sprite_a_; // Sprite para las nubes superiores
std::unique_ptr<MovingSprite> top_clouds_sprite_b_; // Sprite para las nubes superiores
@@ -60,26 +64,32 @@ private:
std::unique_ptr<Sprite> buildings_sprite_; // Sprite con los edificios de fondo
std::unique_ptr<Sprite> gradient_sprite_; // Sprite con los graficos del degradado de color de fondo
std::unique_ptr<Sprite> grass_sprite_; // Sprite para la hierba
std::unique_ptr<Sprite> sun_sprite_; // Sprite para el sol
std::unique_ptr<Sprite> moon_sprite_; // Sprite para la luna
SDL_Texture *canvas_; // Textura para componer el fondo
SDL_Texture *color_texture_; // Textura para atenuar el fondo
// Variables
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_ = 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
int base_; // Linea de fondo coincidente con el area inferior de la zona de juego
Color color_; // Color para atenuar el fondo
int alpha_color_text_; // Alpha para atenuar el fondo
int alpha_color_text_temp_; // Valor temporal para hacer la transición de alpha
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_ = 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
int base_; // Linea de fondo coincidente con el area inferior de la zona de juego
Color attenuate_color_; // Color para atenuar el fondo
int alpha_color_text_; // Alpha para atenuar el fondo
int alpha_color_text_temp_; // Valor temporal para hacer la transición de alpha
std::vector<SDL_Point> sun_path_; // Vector con el recorrido del sol
std::vector<SDL_Point> moon_path_; // Vector con el recorrido de la luna
size_t sun_index_ = 0; // Posición del vector del recorrido del sol
size_t moon_index_ = 0; // Posición del vector del recorrido de la luna
// Dibuja el gradiente de fondo
void renderGradient();
@@ -94,11 +104,17 @@ private:
void fillCanvas();
// Actualiza el valor de alpha
void updateAlphaColorText();
void updateAlphaColorTexture();
// Actualiza las nubes
void updateClouds();
// Precalcula el vector con el recorrido del sol
void createSunPath();
// Precalcula el vector con el recorrido de la luna
void createMoonPath();
public:
// Constructor
Background();
@@ -132,4 +148,10 @@ public:
// Establece la transparencia de la atenuación
void setAlpha(int alpha);
// Establece la posición del sol
void setSunProgression(float progress);
// Establece la posición de la luna
void setMoonProgression(float progress);
};

View File

@@ -5,9 +5,11 @@
#include "param.h" // Para Param, param, ParamBalloon, ParamGame
#include "sprite.h" // Para Sprite
#include "texture.h" // Para Texture
#include "resource.h"
#include "jail_audio.h"
// Constructor
Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
Balloon::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)
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
x_(x),
y_(y),
@@ -19,7 +21,8 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
creation_counter_ini_(creation_timer),
type_(type),
size_(size),
speed_(speed)
speed_(speed),
play_area_(play_area)
{
switch (type_)
{
@@ -28,13 +31,14 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
vy_ = 0;
max_vy_ = 3.0f;
const int size = static_cast<int>(size_);
gravity_ = param.balloon.at(size).grav;
default_vy_ = param.balloon.at(size).vel;
h_ = w_ = BALLOON_SIZE[size];
power_ = BALLOON_POWER[size];
menace_ = BALLOON_MENACE[size];
score_ = BALLOON_SCORE[size];
const int index = static_cast<int>(size_);
gravity_ = param.balloon.at(index).grav;
default_vy_ = param.balloon.at(index).vel;
h_ = w_ = BALLOON_SIZE[index];
power_ = BALLOON_POWER[index];
menace_ = BALLOON_MENACE[index];
score_ = BALLOON_SCORE[index];
sound_ = BALLOON_SOUND[index];
break;
}
@@ -44,28 +48,29 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
default_vy_ = max_vy_ = vy_ = fabs(vx_ * 2.0f);
gravity_ = 0.00f;
const int size = static_cast<int>(size_);
h_ = w_ = BALLOON_SIZE[size];
power_ = BALLOON_POWER[size];
menace_ = BALLOON_MENACE[size];
score_ = BALLOON_SCORE[size];
const int index = static_cast<int>(size_);
h_ = w_ = BALLOON_SIZE[index];
power_ = BALLOON_POWER[index];
menace_ = BALLOON_MENACE[index];
score_ = BALLOON_SCORE[index];
sound_ = BALLOON_SOUND[index];
break;
}
case BalloonType::POWERBALL:
{
const int size = 3;
h_ = w_ = BALLOON_SIZE[size];
constexpr int index = 3;
h_ = w_ = BALLOON_SIZE[4];
sound_ = BALLOON_SOUND[3];
power_ = score_ = menace_ = 0;
vy_ = 0;
max_vy_ = 3.0f;
gravity_ = param.balloon.at(size).grav;
default_vy_ = param.balloon.at(size).vel;
gravity_ = param.balloon.at(index).grav;
default_vy_ = param.balloon.at(index).vel;
sprite_->disableRotate();
sprite_->setRotateSpeed(0);
sprite_->setRotate(creation_timer <= 0);
sprite_->setRotateAmount(vx_ > 0.0f ? 2.0 : -2.0);
break;
@@ -92,40 +97,53 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
void Balloon::alignTo(int x)
{
x_ = static_cast<float>(x - (w_ / 2));
const int min_x = param.game.play_area.rect.x;
const int max_x = param.game.play_area.rect.w - w_;
const int min_x = play_area_.x;
const int max_x = play_area_.w - w_;
x_ = std::clamp(x_, static_cast<float>(min_x), static_cast<float>(max_x));
}
// Pinta el globo en la pantalla
void Balloon::render()
{
if (isBeingCreated())
if (type_ == BalloonType::POWERBALL)
{
// Aplica alpha blending
sprite_->getTexture()->setAlpha(255 - (int)((float)creation_counter_ * (255.0f / (float)creation_counter_ini_)));
sprite_->render();
sprite_->getTexture()->setAlpha(255);
// Renderiza el fondo azul
{
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
sp->setSpriteClip(0, 0, BALLOON_SIZE[4], BALLOON_SIZE[4]);
sp->render();
}
// Renderiza la estrella
if (!invulnerable_)
{
SDL_Point p = {24, 24};
sprite_->setRotatingCenter(&p);
sprite_->render();
}
// Añade la máscara del borde y los reflejos
{
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
sp->setSpriteClip(BALLOON_SIZE[4] * 2, 0, BALLOON_SIZE[4], BALLOON_SIZE[4]);
sp->render();
}
}
else
{
if (bouncing_.enabled)
// Renderizado para el resto de globos
if (isBeingCreated())
{
// Aplica efecto de bouncing
sprite_->setPos(x_ + bouncing_.despX, y_ + bouncing_.despY);
// Renderizado con transparencia
sprite_->getTexture()->setAlpha(255 - (int)((float)creation_counter_ * (255.0f / (float)creation_counter_ini_)));
sprite_->render();
sprite_->setPos(x_ - bouncing_.despX, y_ - bouncing_.despY);
sprite_->getTexture()->setAlpha(255);
}
else
{
// Renderizado normal
sprite_->render();
}
// Añade la máscara del borde a la PowerBall
if (type_ == BalloonType::POWERBALL && !isBeingCreated())
{
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
sp->setSpriteClip(BALLOON_SIZE[3], 0, BALLOON_SIZE[3], BALLOON_SIZE[3]);
sp->render();
}
}
}
@@ -140,40 +158,55 @@ void Balloon::move()
// Colisión en las partes laterales de la zona de juego
const int clip = 2;
const float min_x = param.game.play_area.rect.x - clip;
const float max_x = param.game.play_area.rect.w - w_ + clip;
const float min_x = play_area_.x - clip;
const float max_x = play_area_.x + play_area_.w - w_ + clip;
if (x_ < min_x || x_ > max_x)
{
playSound();
x_ = std::clamp(x_, min_x, max_x);
vx_ = -vx_;
// Activa el efecto de rebote o invierte la rotación
if (type_ == BalloonType::POWERBALL)
{
sprite_->switchRotate();
}
else
{
enableBounce();
}
}
// Mueve el globo en vertical
y_ += vy_ * speed_;
// Colisión en la parte superior de la zona de juego
const int min_y = param.game.play_area.rect.y;
if (y_ < min_y)
// Colisión en la parte superior solo si el globo va de subida
if (vy_ < 0)
{
y_ = min_y;
vy_ = -vy_;
if (type_ != BalloonType::POWERBALL)
const int min_y = play_area_.y;
if (y_ < min_y)
{
playSound();
y_ = min_y;
vy_ = -vy_;
enableBounce();
}
}
// Colisión en la parte inferior de la zona de juego
const int max_y = param.game.play_area.rect.h - h_;
const int max_y = play_area_.y + play_area_.h - h_;
if (y_ > max_y)
{
playSound();
y_ = max_y;
vy_ = -default_vy_;
if (type_ != BalloonType::POWERBALL)
{
enableBounce();
}
else
{
setInvulnerable(false);
}
}
/*
@@ -200,18 +233,6 @@ void Balloon::move()
}
}
// Deshabilita el globo y pone a cero todos los valores
void Balloon::disable()
{
enabled_ = false;
}
// Explosiona el globo
void Balloon::pop()
{
disable();
}
// Actualiza al globo a su posicion, animación y controla los contadores
void Balloon::update()
{
@@ -243,8 +264,8 @@ void Balloon::updateState()
x_ += vx_;
// Comprueba no se salga por los laterales
const int min_x = param.game.play_area.rect.x;
const int max_x = param.game.play_area.rect.w - w_;
const int min_x = play_area_.x;
const int max_x = play_area_.w - w_;
if (x_ < min_x || x_ > max_x)
{
@@ -296,110 +317,24 @@ void Balloon::setAnimation()
sprite_->setCurrentAnimation(isBeingCreated() ? creating_animation : normal_animation);
}
// Comprueba si el globo está habilitado
bool Balloon::isEnabled() const
{
return enabled_;
}
// Obtiene del valor de la variable
float Balloon::getPosX() const
{
return x_;
}
// Obtiene del valor de la variable
float Balloon::getPosY() const
{
return y_;
}
// Obtiene del valor de la variable
int Balloon::getWidth() const
{
return w_;
}
// Obtiene del valor de la variable
int Balloon::getHeight() const
{
return h_;
}
// Establece el valor de la variable
void Balloon::setVelY(float vel_y)
{
vy_ = vel_y;
}
// Establece el valor de la variable
void Balloon::setSpeed(float speed)
{
speed_ = speed;
}
// Obtiene el tamaño del globo
BalloonSize Balloon::getSize() const
{
return size_;
}
// Obtiene el tipo de globo
BalloonType Balloon::getType() const
{
return type_;
}
// Detiene el globo
void Balloon::stop()
{
stopped_ = true;
if (type_ == BalloonType::POWERBALL)
sprite_->disableRotate();
if (isPowerBall())
{
sprite_->setRotate(!stopped_);
}
}
// Pone el globo en movimiento
void Balloon::start()
{
stopped_ = false;
if (type_ == BalloonType::POWERBALL)
sprite_->enableRotate();
}
// Obtiene del valor de la variable
bool Balloon::isStopped() const
{
return stopped_;
}
// Establece el valor de la variable
void Balloon::setInvulnerable(bool value)
{
invulnerable_ = value;
}
// Obtiene del valor de la variable
bool Balloon::isInvulnerable() const
{
return invulnerable_;
}
// Obtiene del valor de la variable
bool Balloon::isBeingCreated() const
{
return being_created_;
}
// Obtiene del valor de la variable
Uint16 Balloon::getScore() const
{
return score_;
}
// Obtiene el circulo de colisión
Circle &Balloon::getCollider()
{
return collider_;
if (isPowerBall())
{
sprite_->setRotate(!stopped_);
}
}
// Alinea el circulo de colisión con la posición del objeto globo
@@ -423,18 +358,6 @@ void Balloon::zoomSprite()
sprite_->setZoomH(bouncing_.zoomH);
}
// Obtiene le valor de la variable
Uint8 Balloon::getMenace() const
{
return isEnabled() ? menace_ : 0;
}
// Obtiene le valor de la variable
Uint8 Balloon::getPower() const
{
return power_;
}
// Activa el efecto
void Balloon::enableBounce()
{
@@ -462,27 +385,13 @@ void Balloon::updateBounce()
zoomSprite();
const auto spriteClip = sprite_->getSpriteClip();
bouncing_.despX = spriteClip.w * (1.0f - bouncing_.zoomW);
bouncing_.despY = spriteClip.h * (1.0f - bouncing_.zoomH);
if (++bouncing_.counter / bouncing_.speed >= MAX_BOUNCE)
{
disableBounce();
}
}
}
// Indica si el globo se puede explotar
bool Balloon::canBePopped() const
{
return isEnabled() && !isBeingCreated();
}
// Indica si el globo se puede destruir
bool Balloon::canBeDestroyed() const
{
return isEnabled();
}
// Pone el color alternativo en el globo
void Balloon::useReverseColor()
{
@@ -500,8 +409,11 @@ void Balloon::useNormalColor()
setAnimation();
}
// Indica si está usando el color alternativo
bool Balloon::isUsingReversedColor()
// Reproduce el sonido al rebotar
void Balloon::playSound()
{
return use_reversed_colors_;
if (sound_enabled_)
{
JA_PlaySound(Resource::get()->getSound(sound_));
}
}

View File

@@ -1,12 +1,13 @@
#pragma once
#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 10-10
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;
@@ -15,7 +16,8 @@ constexpr int MAX_BOUNCE = 10;
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, 46};
constexpr int BALLOON_SIZE[] = {10, 16, 26, 48, 49};
const std::string BALLOON_SOUND[] = {"bubble1.wav", "bubble2.wav", "bubble3.wav", "bubble4.wav"};
// Tamaños de globo
enum class BalloonSize : Uint8
@@ -111,6 +113,9 @@ private:
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
std::string sound_; // Archivo de sonido que hace el globo al rebotar
bool sound_enabled_ = false; // Indica si ha de sonar el sonido del globo al rebotar
// Alinea el circulo de colisión con la posición del objeto globo
void shiftColliders();
@@ -136,9 +141,22 @@ private:
// Establece la animación correspondiente
void setAnimation();
// Reproduce el sonido al rebotar
void playSound();
public:
// Constructor
Balloon(float x, float y, BalloonType type, BalloonSize size, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr<Texture> texture, const 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;
@@ -152,84 +170,44 @@ public:
// Actualiza la posición y estados del globo
void move();
// Deshabilita el globo y pone a cero todos los valores
void disable();
// Explosiona el globo
void pop();
// Actualiza al globo a su posicion, animación y controla los contadores
void update();
// Comprueba si el globo está habilitado
bool isEnabled() const;
// Obtiene del valor de la variable
float getPosX() const;
// Obtiene del valor de la variable
float getPosY() const;
// Obtiene del valor de la variable
int getWidth() const;
// 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 el tamaño del globo
BalloonSize getSize() const;
// Obtiene el tipo de globo
BalloonType getType() const;
// Detiene el globo
void stop();
// Pone el globo en movimiento
void start();
// Obtiene del valor de la variable
bool isStopped() 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;
// 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;
// Pone el color alternativo en el globo
void useReverseColor();
// Pone el color normal en el globo
void useNormalColor();
// Indica si está usando el color alternativo
bool isUsingReversedColor();
// 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(); }
// Setters
void setVelY(float vel_y) { vy_ = vel_y; }
void setSpeed(float speed) { speed_ = speed; }
void setInvulnerable(bool value) { invulnerable_ = value; }
void setSound(bool value) { sound_enabled_ = value; }
void disable() { enabled_ = false; }
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
#pragma once
#include "balloon.h"
#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 = 0; // Posición en el eje X donde crear el globo
@@ -25,34 +25,26 @@ struct BalloonFormationParams
: 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 globos que forman la formación
BalloonFormationParams init[MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION]; // Vector con todas las inicializaciones de los globos 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[NUMBER_OF_SETS_PER_POOL]; // 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_[NUMBER_OF_STAGES]; // Variable con los datos de cada pantalla
BalloonFormationUnit balloon_formation_[NUMBER_OF_BALLOON_FORMATIONS]; // Vector con todas las formaciones enemigas
BalloonFormationPool balloon_formation_pool_[NUMBER_OF_STAGES]; // 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();
@@ -60,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); }
};

417
source/balloon_manager.cpp Normal file
View File

@@ -0,0 +1,417 @@
#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 num_enemies = set.number_of_balloons;
for (int i = 0; i < num_enemies; ++i)
{
auto p = set.init[i];
createBalloon(
p.x,
p.y,
p.type,
p.size,
p.vel_x,
balloon_speed_,
(creation_time_enabled_) ? p.creation_counter : 0);
}
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 num_enemies = set.number_of_balloons;
for (int i = 0; i < num_enemies; ++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 num_enemies = set.number_of_balloons;
for (int i = 0; i < num_enemies; ++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)
{
if (can_deploy_balloons_)
{
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();
}
return nullptr;
}
// Crea un globo a partir de otro globo
void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction)
{
if (can_deploy_balloons_)
{
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()
{
if (can_deploy_balloons_)
{
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]));
balloons_.back()->setInvulnerable(true);
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->disable();
}
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->disable();
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("power_ball_explosion.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);
}
// Crea una disposición de globos aleatoria
void BalloonManager::createRandomBalloons()
{
const int num_balloons = 2 + rand() % 4;
for (int i = 0; i < num_balloons; ++i)
{
const float x = param.game.game_area.rect.x + (rand() % param.game.game_area.rect.w) - BALLOON_SIZE[3];
const int y = param.game.game_area.rect.y + (rand() % 50);
const BalloonSize size = static_cast<BalloonSize>(rand() % 4);
const float vel_x = (rand() % 2 == 0) ? BALLOON_VELX_POSITIVE : BALLOON_VELX_NEGATIVE;
const int creation_counter = 0;
createBalloon(x, y, BalloonType::BALLOON, size, vel_x, balloon_speed_, creation_counter);
}
}
// 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); });
}
// Establece el sonido de los globos
void BalloonManager::setSounds(bool value)
{
for (auto &balloon : balloons_)
{
balloon->setSound(value);
}
}

133
source/balloon_manager.h Normal file
View File

@@ -0,0 +1,133 @@
#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
bool creation_time_enabled_ = true; // Indica si los globos se crean con tiempo
bool can_deploy_balloons_ = true; // Indica si creará 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();
// Crea una disposición de globos aleatoria
void createRandomBalloons();
// Obtiene el nivel de ameza actual generado por los globos
int getMenace();
// Establece el sonido de los globos
void setSounds(bool value);
// Getters
float getBalloonSpeed() const { return balloon_speed_; }
Balloons &getBalloons() { return balloons_; }
int getNumBalloons() const { return balloons_.size(); }
// 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; }
void setCreationTimeEnabled(bool value) { creation_time_enabled_ = value; }
void setDeployBalloons(bool value) { can_deploy_balloons_ = value; }
};

497
source/credits.cpp Normal file
View File

@@ -0,0 +1,497 @@
// IWYU pragma: no_include <bits/std_abs.h>
#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_timer.h> // Para SDL_GetTicks
#include <algorithm> // Para max, min, clamp
#include <cstdlib> // Para abs
#include <stdexcept> // Para runtime_error
#include <string> // Para basic_string, string
#include <vector> // Para vector
#include "balloon_manager.h" // Para BalloonManager
#include "fade.h" // Para Fade, FadeType, FadeMode
#include "global_inputs.h" // Para check, update
#include "input.h" // Para Input
#include "jail_audio.h" // Para JA_GetMusicState, JA_SetMusicVolume
#include "lang.h" // Para getText
#include "mouse.h" // Para handleEvent
#include "param.h" // Para Param, ParamGame, param
#include "player.h" // Para Player, PlayerState
#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_SHADOW
#include "texture.h" // Para Texture
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
#include "utils.h" // Para Color, Zone, shdw_txt_color, no_color
// Textos
constexpr const char TEXT_COPYRIGHT[] = "@2020,2025 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)),
canvas_(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;
balloon_manager_->setPlayArea(play_area_);
fade_in_->setColor(fade_color.r, fade_color.g, fade_color.b);
fade_in_->setType(FadeType::FULLSCREEN);
fade_in_->setPostDuration(50);
fade_in_->setMode(FadeMode::IN);
fade_in_->activate();
fade_out_->setColor(0, 0, 0);
fade_out_->setType(FadeType::FULLSCREEN);
fade_out_->setPostDuration(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_);
SDL_DestroyTexture(canvas_);
resetVolume();
JA_StopMusic();
}
// 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()
{
constexpr Uint32 TICKS_SPEED_ = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED_)
{
ticks_ = SDL_GetTicks();
const int repeat = want_to_pass_ ? 4 : 1;
for (int i = 0; i < repeat; ++i)
{
tiled_bg_->update();
balloon_manager_->update();
updateTextureDstRects();
throwBalloons();
for (auto &player : players_)
{
player->update();
}
updateAllFades();
++counter_;
}
Screen::get()->update();
globalInputs::update();
fillCanvas();
}
}
// Dibuja Credits::en patalla
void Credits::render()
{
// Prepara para empezar a dibujar en la textura de juego
Screen::get()->start();
// Copia la textura con la zona de juego a la pantalla
SDL_RenderCopy(Screen::get()->getRenderer(), canvas_, nullptr, nullptr);
// Vuelca el contenido del renderizador en pantalla
Screen::get()->render();
}
// 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 el cursor
Mouse::handleEvent(event);
}
}
// 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;
}
}
// 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;
}
// Dibuja todos los sprites en la textura
void Credits::fillCanvas()
{
// Cambia el destino del renderizador
auto temp = SDL_GetRenderTarget(Screen::get()->getRenderer());
SDL_SetRenderTarget(Screen::get()->getRenderer(), canvas_);
// 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();
// Deja el renderizador apuntando donde estaba
SDL_SetRenderTarget(Screen::get()->getRenderer(), temp);
}
// 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::HI_SCORE_TABLE;
}
}
// 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));
}

106
source/credits.h Normal file
View File

@@ -0,0 +1,106 @@
#pragma once
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_render.h> // Para SDL_Texture
#include <SDL2/SDL_stdinc.h> // Para Uint32
#include <memory> // Para unique_ptr, shared_ptr
#include <vector> // Para vector
#include "options.h" // Para Options, OptionsAudio, OptionsMusic
#include "param.h" // Para Param, ParamGame, param
#include "utils.h" // Para Zone
class BalloonManager; // lines 8-8
class Fade; // lines 11-11
class Player; // lines 10-10
class TiledBG; // lines 9-9
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
SDL_Texture *canvas_; // Textura donde dibujarlo todo
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 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();
// Dibuja todos los sprites en la textura
void fillCanvas();
// 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,26 +1,22 @@
#include "define_buttons.h"
#include <utility> // Para move
#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 "section.h" // Para Name, Options, name, options
#include "text.h" // Para Text
#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_)
DefineButtons::DefineButtons()
: input_(Input::get()),
text_(std::move(text_))
text_(Resource::get()->getText("8bithud"))
{
// Inicializa variables
x_ = param.game.width / 2;
y_ = param.title.press_start_position;
buttons_.emplace_back(lang::getText(95), InputType::FIRE_LEFT, SDL_CONTROLLER_BUTTON_X);
buttons_.emplace_back(lang::getText(96), InputType::FIRE_CENTER, SDL_CONTROLLER_BUTTON_Y);
buttons_.emplace_back(lang::getText(97), InputType::FIRE_RIGHT, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
buttons_.emplace_back(lang::getText(98), InputType::START, SDL_CONTROLLER_BUTTON_START);
buttons_.emplace_back(lang::getText(99), InputType::EXIT, SDL_CONTROLLER_BUTTON_BACK);
clearButtons();
for (int i = 0; i < input_->getNumControllers(); ++i)
{
@@ -33,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_)
{
@@ -81,13 +79,11 @@ void DefineButtons::checkInput()
section::options = section::Options::QUIT_WITH_KEYBOARD;
break;
}
case SDL_CONTROLLERBUTTONDOWN:
{
doControllerButtonDown(&event.cbutton);
doControllerButtonDown(event.cbutton);
break;
}
default:
break;
}
@@ -103,6 +99,7 @@ bool DefineButtons::enable(int index)
enabled_ = true;
index_controller_ = index;
index_button_ = 0;
clearButtons();
return true;
}
@@ -110,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();
@@ -129,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;
}
}
@@ -142,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,13 +1,14 @@
#pragma once
#include <SDL2/SDL_events.h> // para SDL_ControllerButtonEvent
#include <SDL2/SDL_gamecontroller.h> // para SDL_GameControllerButton
#include <memory> // para shared_ptr, unique_ptr
#include <string> // para string
#include <vector> // para 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
{
@@ -33,15 +34,15 @@ private:
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_ = 0; // Indice del controlador a reasignar
int index_button_ = 0; // 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();
@@ -49,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;
@@ -59,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,3 +1,4 @@
// IWYU pragma: no_include <bits/chrono.h>
#include "director.h"
#include <SDL2/SDL.h> // Para SDL_Init, SDL_Quit, SDL_INIT_EV...
#include <SDL2/SDL_audio.h> // Para AUDIO_S16
@@ -7,44 +8,42 @@
#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 <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <errno.h> // Para errno, EEXIST, EACCES, ENAMETOO...
#include <stdio.h> // Para printf, perror
#include <string.h> // Para strcmp
#include <sys/stat.h> // Para mkdir, stat, S_IRWXU
#include <unistd.h> // Para getuid
#include <cstdlib> // Para exit, EXIT_FAILURE, rand, srand
#include <iostream> // Para basic_ostream, operator<<, cout
#include <memory> // Para make_unique, unique_ptr, make_s...
#include <stdexcept> // Para runtime_error
#include <string> // Para operator+, allocator, char_traits
#include <vector> // Para vector
#include "asset.h" // Para Asset, AssetType
#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_EnableMusic, JA_EnableSound
#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, options, OptionsContro...
#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 "text.h" // Para Text
#include "title.h" // Para Title
#include "utils.h" // Para Overrides, overrides
#ifndef _WIN32
#include <pwd.h> // para getpwuid, passwd
#include <pwd.h> // Para getpwuid, passwd
#endif
#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 <chrono> // Para chrono
#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 "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, options, OptionsContro...
#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
// Constructor
Director::Director(int argc, const char *argv[])
@@ -54,8 +53,9 @@ 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
@@ -66,71 +66,50 @@ Director::Director(int argc, const char *argv[])
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_);
// Crea el indice de ficheros
setFileList();
// 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 = overrides.param_file == "--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);
if (overrides.clear_hi_score_table)
{
manager->clear();
}
else
{
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));
Screen::init(window_, renderer_);
Resource::init();
Input::init(Asset::get()->get("gamecontrollerdb.txt"));
bindInputs();
auto notifier_text = std::make_shared<Text>(Resource::get()->getTexture("8bithud.png"), Resource::get()->getTextFile("8bithud.txt"));
Notifier::init(std::string(), notifier_text, Asset::get()->get("notify.wav"));
OnScreenHelp::init();
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"));
@@ -141,12 +120,42 @@ Director::~Director()
Notifier::destroy();
OnScreenHelp::destroy();
JA_Quit();
SDL_DestroyRenderer(renderer_);
SDL_DestroyWindow(window_);
SDL_Quit();
std::cout << "\nBye!" << std::endl;
#ifdef ARCADE
shutdownSystem(section::options == section::Options::QUIT_WITH_CONTROLLER);
#endif
}
// Carga los parametros
void Director::loadParams()
{
// 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
@@ -173,7 +182,9 @@ void Director::bindInputs()
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::AUTO_FIRE, SDL_SCANCODE_F6);
Input::get()->bindKey(InputType::CHANGE_LANG, SDL_SCANCODE_F7);
Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F8);
Input::get()->bindKey(InputType::RESET, SDL_SCANCODE_F10);
// Asigna botones a inputs
@@ -194,27 +205,23 @@ void Director::bindInputs()
// 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)
@@ -229,25 +236,41 @@ void Director::bindInputs()
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
@@ -264,35 +287,43 @@ bool Director::initSDL()
}
else
{
// Inicia el generador de numeros aleatorios
std::srand(static_cast<unsigned int>(SDL_GetTicks()));
/*
// 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;
}
*/
// Obtiene información sobre la pantalla
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;
// Calcula el máximo factor de zoom que se puede aplicar a la pantalla
options.video.window.max_size = std::min(DM.w / param.game.width, DM.h / param.game.height);
options.video.window.size = std::min(options.video.window.size, options.video.window.max_size);
// Muestra información sobre el tamaño de la pantalla y de la ventana de juego
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()))
{
std::cout << "Warning: texture filtering not enabled!\n";
}
#ifndef NO_SHADERS
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"))
{
std::cout << "Warning: opengl not enabled!\n";
}
#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_)
{
@@ -307,10 +338,12 @@ 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_)
@@ -320,14 +353,9 @@ bool Director::initSDL()
}
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);
}
}
@@ -359,6 +387,7 @@ void 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);
@@ -367,19 +396,32 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/sound/bubble3.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/bubble4.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/bullet.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/coffeeout.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/hiscore.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/itemdrop.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/itempickup.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/player_collision.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/stage_change.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/title.wav", AssetType::SOUND);
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/coffee_out.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/continue_clock.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/game_start.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/hi_score_achieved.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/item_drop.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/item_pickup.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/logo.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/notify.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/player_collision.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/power_ball_explosion.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/stage_change.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/tabe.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/title.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/voice_coffee.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/voice_get_ready.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/voice_no.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/voice_power_up.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/walk.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/debian_drop.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/debian_pickup.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/tabe_hit.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
@@ -418,6 +460,11 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/gfx/bullet/bullet.png", AssetType::BITMAP);
}
{ // Tabe
Asset::get()->add(prefix + "/data/gfx/tabe/tabe.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/tabe/tabe.ani", AssetType::ANIMATION);
}
{ // 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);
@@ -425,15 +472,8 @@ void Director::setFileList()
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);
}
{ // Game Text
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_1000_points.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_2500_points.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_5000_points.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_powerup.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_one_hit.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_stop.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_sun.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_moon.png", AssetType::BITMAP);
}
{ // Intro
@@ -457,6 +497,8 @@ void Director::setFileList()
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_debian.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_debian.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);
}
@@ -472,17 +514,17 @@ void Director::setFileList()
{ // 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_1_coffee_palette.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_2_coffee_palette.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_invencible_palette.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_power.png", AssetType::BITMAP);
}
{ // 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_1_coffee_palette.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_2_coffee_palette.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_invencible_palette.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_power.png", AssetType::BITMAP);
}
@@ -494,17 +536,15 @@ void Director::setFileList()
// Fuentes de texto
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::BITMAP);
Asset::get()->add(prefix + "/data/font/nokia_big2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/nokia.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia2.png", AssetType::BITMAP);
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::BITMAP);
Asset::get()->add(prefix + "/data/font/smb2_big.txt", AssetType::FONT);
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);
Asset::get()->add(prefix + "/data/font/04b_25_metal.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/04b_25_grey.png", AssetType::BITMAP);
// Textos
Asset::get()->add(prefix + "/data/lang/es_ES.txt", AssetType::LANG);
@@ -516,40 +556,22 @@ void Director::setFileList()
throw std::runtime_error("Falta algun fichero");
}
// Carga los parametros para configurar el juego
void Director::loadParams(const std::string &file_path)
{
loadParamsFromFile(file_path);
}
// Comprueba los parametros del programa
void Director::checkProgramArguments(int argc, const char *argv[])
{
const std::vector<std::string> argument_list = {"--h", "--320x240", "--clear_score"};
// Establece la ruta del programa
executable_path_ = argv[0];
// Comprueba el resto de parámetros
for (int i = 1; i < argc; ++i)
{
if (strcmp(argv[i], "--h") == 0)
{
for (const auto &argument : argument_list)
{
std::cout << argument << std::endl;
}
// std::exit(EXIT_SUCCESS);
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
}
std::string arg = argv[i];
if (strcmp(argv[i], "--320x240") == 0)
if (arg == "--320x240")
{
overrides.param_file = argv[i];
overrides.param_file = arg;
}
if (strcmp(argv[i], "--clear_score") == 0)
else if (arg == "--clear_score")
{
overrides.clear_hi_score_table = true;
}
@@ -641,7 +663,11 @@ 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;
#else
constexpr auto current_stage = 0;
#endif
auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_OFF);
game->run();
}
@@ -653,6 +679,13 @@ void Director::runInstructions()
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()
{
@@ -669,6 +702,16 @@ void Director::runDemoGame()
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
@@ -677,50 +720,51 @@ 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;
}
}
#ifdef ARCADE
// Comprueba si ha de apagar el sistema
if (section::options == section::Options::QUIT_WITH_CONTROLLER)
shutdownSystem();
#endif
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;
}
const auto return_code = (section::options == section::Options::QUIT_WITH_KEYBOARD) ? "with keyboard" : (section::options == section::Options::QUIT_WITH_CONTROLLER) ? "with controller"
: "from event";
std::cout << "\nGame end " << return_code << std::endl;
#ifndef VERBOSE
@@ -739,15 +783,12 @@ 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;
}
@@ -757,20 +798,23 @@ std::string Director::getLangFile(lang::Code code)
#ifdef ARCADE
// Apaga el sistema
void Director::shutdownSystem()
void Director::shutdownSystem(bool shouldShutdown)
{
if (shouldShutdown)
{
#ifdef _WIN32
// Apaga el sistema en Windows
system("shutdown /s /t 0");
// Apaga el sistema en Windows
system("shutdown /s /t 5");
#elif __APPLE__
// Apaga el sistema en macOS
system("sudo shutdown -h now");
// Apaga el sistema en macOS
system("sudo shutdown -h +0.1");
#elif __linux__
// Apaga el sistema en Linux
system("shutdown -h now");
// Apaga el sistema en Linux
system("sleep 5; shutdown -h now");
#else
// Sistema operativo no compatible
#error "Sistema operativo no soportado"
#endif
}
}
#endif // ARCADE
#endif // ARCADE

View File

@@ -34,9 +34,6 @@ private:
// Asigna los botones y teclas al objeto Input
void bindInputs();
// Carga los parametros para configurar el juego
void loadParams(const std::string &file_path);
// Crea el indice de ficheros
void setFileList();
@@ -61,19 +58,37 @@ 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();
void shutdownSystem(bool shouldShutdown);
#endif
// Inicializa todo
void init();
// Cierra todo
void close();
// Carga los parametros
void loadParams();
// Carga el fichero de puntuaciones
void loadScoreFile();
public:
// Constructor
Director(int argc, const char *argv[]);

View File

@@ -1,93 +1,164 @@
#include "enter_name.h"
#include "utils.h"
#include <stddef.h> // Para size_t
#include <algorithm> // Para max, min
#include <cassert> // Para assert
#include <iostream>
// Constructor
EnterName::EnterName()
{
init();
}
: character_list_(" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()") {}
// Inicializa el objeto
void EnterName::init()
void EnterName::init(const std::string &name)
{
// Obtiene el puntero al nombre
name_ = "A";
// No se pasa ningún nombre
if (name == "")
{
name_ = "A";
position_ = 0;
position_overflow_ = false;
}
// Se pasa un nombre
else
{
name_ = name;
position_ = name_.length();
position_overflow_ = position_ >= NAME_LENGHT ? true : false;
}
// Inicia la lista de caracteres permitidos
character_list_ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()";
position_ = 0;
num_characters_ = static_cast<int>(character_list_.size());
// Pone la lista de indices para que refleje el nombre
updateCharacterIndex();
// Actualiza el nombre para que ocupe 8 espacios
updateName();
// Inicializa el vector de indices con el nombre y espacios
initCharacterIndex(name_);
}
// Incrementa la posición
void EnterName::incPosition()
{
position_++;
position_ = std::min(position_, NAME_LENGHT - 1);
checkIfPositionHasBeenUsed();
if (position_overflow_)
{
// Si ya estamos en overflow, no incrementamos más.
return;
}
++position_;
if (position_ >= NAME_LENGHT)
{
position_ = NAME_LENGHT; // Mantenemos en el índice máximo válido.
position_overflow_ = true; // Activamos el flag de overflow.
}
else
{
// Copiamos el índice del carácter anterior si es posible.
if (position_ > 0 && position_ < NAME_LENGHT)
{
character_index_[position_] = character_index_[position_ - 1];
}
else
{
// Si position_ es 0, inicializamos el carácter actual.
character_index_[position_] = 0;
}
}
updateNameFromCharacterIndex();
}
// Decrementa la posición
void EnterName::decPosition()
{
--position_;
position_ = std::max(position_, 0);
if (position_overflow_)
{
// Si estaba en overflow, lo desactivamos y mantenemos position_ en el máximo.
position_overflow_ = false;
position_ = NAME_LENGHT - 1;
}
else
{
if (position_ > 0)
{
--position_;
// Limpiamos el carácter siguiente si el índice es válido.
if (position_ + 1 < NAME_LENGHT)
{
character_index_[position_ + 1] = 0;
}
}
else
{
// Si position_ es 0, aseguramos que no vaya a ser negativo y limpiamos el carácter actual.
position_ = 0;
character_index_[position_] = 0;
}
// Si position_ es menor que NAME_LENGHT, aseguramos que el overflow esté desactivado.
if (position_ < NAME_LENGHT)
{
position_overflow_ = false;
}
}
updateNameFromCharacterIndex();
}
// Incrementa el índice
void EnterName::incIndex()
{
if (position_overflow_)
{
return;
}
++character_index_[position_];
if (character_index_[position_] >= num_characters_)
if (character_index_[position_] >= static_cast<int>(character_list_.size()))
{
character_index_[position_] = 0;
}
updateName();
updateNameFromCharacterIndex();
}
// Decrementa el índice
void EnterName::decIndex()
{
if (position_overflow_)
{
return;
}
--character_index_[position_];
if (character_index_[position_] < 0)
{
character_index_[position_] = num_characters_ - 1;
character_index_[position_] = character_list_.size() - 1;
}
updateName();
updateNameFromCharacterIndex();
}
// Actualiza el nombre a partir de la lista de índices
void EnterName::updateName()
void EnterName::updateNameFromCharacterIndex()
{
name_.clear();
for (int i = 0; i < NAME_LENGHT; ++i)
{
name_.push_back(character_list_[character_index_[i]]);
}
name_ = trim(name_);
}
// Actualiza la variable
void EnterName::updateCharacterIndex()
void EnterName::initCharacterIndex(const std::string &name)
{
// Rellena de espacios y marca como no usados
// Rellena de espacios
for (size_t i = 0; i < NAME_LENGHT; ++i)
{
character_index_[i] = 0;
position_has_been_used_[i] = false;
}
// Coloca los índices en función de los caracteres que forman el nombre
for (size_t i = 0; i < name_.size(); ++i)
for (size_t i = 0; i < name.substr(0, NAME_LENGHT).size(); ++i)
{
character_index_[i] = findIndex(name_.at(i));
position_has_been_used_[i] = true;
character_index_[i] = findIndex(name.at(i));
}
}
@@ -98,28 +169,4 @@ int EnterName::findIndex(char character) const
if (character == character_list_.at(i))
return i;
return 0;
}
// Obtiene el nombre
std::string EnterName::getName() const
{
return name_;
}
// Obtiene la posición que se está editando
int EnterName::getPosition() const
{
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

@@ -1,8 +1,9 @@
#pragma once
#include <string>
#include "utils.h"
constexpr int NAME_LENGHT = 8;
constexpr int NAME_LENGHT = 6;
/*
Un array, "characterList", contiene la lista de caracteres
@@ -16,25 +17,21 @@ constexpr int NAME_LENGHT = 8;
class EnterName
{
private:
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
std::string character_list_; // Lista de todos los caracteres permitidos
std::string name_; // Nombre introducido
int position_ = 0; // Posición a editar del nombre
bool position_overflow_ = false; // Indica si hemos incrementado la posición más allá del límite
int character_index_[NAME_LENGHT]; // Indice de la lista para cada uno de los caracteres que forman el nombre
// Actualiza el nombre a partir de la lista de índices
void updateName();
void updateNameFromCharacterIndex();
// Actualiza la variable
void updateCharacterIndex();
void initCharacterIndex(const std::string &name);
// Encuentra el indice de un caracter en "characterList"
int findIndex(char character) const;
// Comprueba la posición y copia el caracter si es necesario
void checkIfPositionHasBeenUsed();
public:
// Constructor
EnterName();
@@ -43,7 +40,7 @@ public:
~EnterName() = default;
// Inicializa el objeto
void init();
void init(const std::string &name = "");
// Incrementa la posición
void incPosition();
@@ -57,9 +54,9 @@ public:
// Decrementa el índice
void decIndex();
// Obtiene el nombre
std::string getName() const;
// Obtiene la posición que se está editando
int getPosition() const;
// Getters
std::string getFinalName() const { return trim(name_.substr(0, position_)); }
std::string getCurrentName() const { return trim(name_); }
int getPosition() const { return position_; }
bool getPositionOverflow() const { return position_overflow_; }
};

View File

@@ -30,15 +30,15 @@ void Fade::init()
{
type_ = FadeType::CENTER;
mode_ = FadeMode::OUT;
enabled_ = false;
finished_ = false;
counter_ = 0;
r_ = 0;
g_ = 0;
b_ = 0;
a_ = 0;
post_duration_ = 20;
post_duration_ = 0;
post_counter_ = 0;
pre_duration_ = 0;
pre_counter_ = 0;
num_squares_width_ = param.fade.num_squares_width;
num_squares_height_ = param.fade.num_squares_height;
fade_random_squares_delay_ = param.fade.random_squares_delay;
@@ -48,15 +48,14 @@ void Fade::init()
// Resetea algunas variables para volver a hacer el fade sin perder ciertos parametros
void Fade::reset()
{
enabled_ = false;
finished_ = false;
state_ = FadeState::NOT_ENABLED;
counter_ = 0;
}
// Pinta una transición en pantalla
void Fade::render()
{
if (enabled_ || finished_)
if (state_ != FadeState::NOT_ENABLED)
{
SDL_RenderCopy(renderer_, backbuffer_, nullptr, nullptr);
}
@@ -65,7 +64,20 @@ void Fade::render()
// Actualiza las variables internas
void Fade::update()
{
if (enabled_)
if (state_ == FadeState::PRE)
{
// Actualiza el contador
if (pre_counter_ == pre_duration_)
{
state_ = FadeState::FADING;
}
else
{
pre_counter_++;
}
}
if (state_ == FadeState::FADING)
{
switch (type_)
{
@@ -79,7 +91,7 @@ void Fade::update()
// Comprueba si ha terminado
if (counter_ >= 255 / 4)
{
finished_ = true;
state_ = FadeState::POST;
}
break;
@@ -100,6 +112,8 @@ void Fade::update()
SDL_RenderFillRect(renderer_, &rect1_);
SDL_RenderFillRect(renderer_, &rect2_);
value_ = calculateValue(0, counter_, i);
}
// Deja el renderizador como estaba
@@ -108,7 +122,7 @@ void Fade::update()
// Comprueba si ha terminado
if ((counter_ * 4) > param.game.height)
{
finished_ = true;
state_ = FadeState::POST;
a_ = 255;
}
break;
@@ -118,10 +132,11 @@ void Fade::update()
{
if (counter_ % fade_random_squares_delay_ == 0)
{
// Dibuja sobre el backbuffer_
// Cambia el renderizador al backbuffer_ y modifica sus opciones
auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, backbuffer_);
SDL_BlendMode blend_mode;
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
@@ -133,16 +148,17 @@ void Fade::update()
SDL_RenderFillRect(renderer_, &square_[index2]);
}
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
// Deja el renderizador como estaba
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
SDL_SetRenderTarget(renderer_, temp);
}
value_ = calculateValue(0, static_cast<int>(num_squares_width_ * num_squares_height_), static_cast<int>(counter_ * fade_random_squares_mult_ / fade_random_squares_delay_));
// Comprueba si ha terminado
if (counter_ * fade_random_squares_mult_ / fade_random_squares_delay_ >= num_squares_width_ * num_squares_height_)
{
finished_ = true;
state_ = FadeState::POST;
}
break;
@@ -150,64 +166,88 @@ void Fade::update()
case FadeType::VENETIAN:
{
// Counter debe ir de 0 a 150
// Counter debe ir de 0 a 150 <-- comprobar si esto es aún cierto
if (square_.back().h < param.fade.venetian_size)
{
// Dibuja sobre el backbuffer_
auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, backbuffer_);
SDL_BlendMode blend_mode;
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
for (auto rect : square_)
// Dibuja el cuadrado correspondiente
for (const auto rect : square_)
{
SDL_RenderFillRect(renderer_, &rect);
}
// Deja el renderizador como estaba
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
SDL_SetRenderTarget(renderer_, temp);
const auto h = counter_ / 3;
for (int i = 0; i < (int)square_.size(); ++i)
// Modifica el tamaño de los rectangulos
const auto h = counter_ / 2;
for (size_t i = 0; i < square_.size(); ++i)
{
// A partir del segundo rectangulo se pinta en función del anterior
square_[i].h = i == 0 ? h : std::max(square_[i - 1].h - 3, 0);
square_.at(i).h = i == 0 ? h : std::max(square_.at(i - 1).h - 2, 0);
}
int completed = 0;
for (const auto &square : square_)
{
if (square.h >= param.fade.venetian_size)
{
++completed;
}
}
value_ = calculateValue(0, square_.size() - 1, completed);
}
else
{
finished_ = true;
state_ = FadeState::POST;
}
break;
}
default:
break;
}
if (finished_)
{
// Actualiza el contador
post_counter_ == post_duration_ ? enabled_ = false : post_counter_++;
// Deja el backbuffer_ todo del mismo color
cleanBackbuffer(r_, g_, b_, a_);
}
counter_++;
}
if (state_ == FadeState::POST)
{
// Actualiza el contador
if (post_counter_ == post_duration_)
{
state_ = FadeState::FINISHED;
}
else
{
post_counter_++;
}
// Deja el backbuffer_ todo del mismo color
cleanBackbuffer(r_, g_, b_, a_);
}
}
// Activa el fade
void Fade::activate()
{
// Si ya está habilitado, no hay que volverlo a activar
if (enabled_)
if (state_ != FadeState::NOT_ENABLED)
{
return;
}
enabled_ = true;
finished_ = false;
state_ = FadeState::PRE;
counter_ = 0;
post_counter_ = 0;
pre_counter_ = 0;
switch (type_)
{
@@ -251,12 +291,8 @@ void Fade::activate()
}
// Limpia la textura
auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, backbuffer_);
a_ = mode_ == FadeMode::OUT ? 0 : 255;
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
SDL_RenderClear(renderer_);
SDL_SetRenderTarget(renderer_, temp);
cleanBackbuffer(r_, g_, b_, a_);
// Deja el color listo para usar
a_ = mode_ == FadeMode::OUT ? 255 : 0;
@@ -266,12 +302,16 @@ void Fade::activate()
case FadeType::VENETIAN:
{
cleanBackbuffer(0, 0, 0, 0);
rect1_ = {0, 0, param.game.width, 0};
square_.clear();
a_ = 255;
// Limpia la textura
a_ = mode_ == FadeMode::OUT ? 0 : 255;
cleanBackbuffer(r_, g_, b_, a_);
// Deja el color listo para usar
a_ = mode_ == FadeMode::OUT ? 255 : 0;
// Añade los cuadrados al vector
square_.clear();
rect1_ = {0, 0, param.game.width, 0};
const int max = param.game.height / param.fade.venetian_size;
for (int i = 0; i < max; ++i)
@@ -285,31 +325,6 @@ void Fade::activate()
}
}
// Comprueba si está activo
bool Fade::isEnabled() const
{
return enabled_;
}
// Comprueba si ha terminado la transicion
bool Fade::hasEnded() const
{
// Ha terminado cuando ha finalizado la transición y se ha deshabilitado
return !enabled_ && finished_;
}
// Establece el tipo de fade
void Fade::setType(FadeType type)
{
type_ = type;
}
// Establece el modo de fade
void Fade::setMode(FadeMode mode)
{
mode_ = mode;
}
// Establece el color del fade
void Fade::setColor(Uint8 r, Uint8 g, Uint8 b)
{
@@ -318,12 +333,6 @@ void Fade::setColor(Uint8 r, Uint8 g, Uint8 b)
b_ = b;
}
// Establece la duración posterior
void Fade::setPost(int value)
{
post_duration_ = value;
}
// Limpia el backbuffer
void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
@@ -337,4 +346,20 @@ void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
// Vuelve a dejar el renderizador como estaba
SDL_SetRenderTarget(renderer_, temp);
}
// Calcula el valor del estado del fade
int Fade::calculateValue(int min, int max, int current)
{
if (current < min)
{
return 0;
}
if (current > max)
{
return 100;
}
return static_cast<int>(100.0 * (current - min) / (max - min));
}

View File

@@ -21,6 +21,16 @@ enum class FadeMode : Uint8
OUT = 1,
};
// Estados del objeto
enum class FadeState : Uint8
{
NOT_ENABLED = 0,
PRE = 1,
FADING = 2,
POST = 3,
FINISHED = 4,
};
// Clase Fade
class Fade
{
@@ -30,21 +40,23 @@ private:
SDL_Texture *backbuffer_; // Textura para usar como backbuffer con SDL_TEXTUREACCESS_TARGET
// Variables
FadeType type_; // Tipo de fade a realizar
FadeMode mode_; // Modo de fade a realizar
Uint16 counter_; // Contador interno
bool enabled_; // Indica si el fade está activo
bool finished_; // Indica si ha terminado la transición
Uint8 r_, g_, b_, a_; // Colores para el fade
SDL_Rect rect1_; // Rectangulo usado para crear los efectos de transición
SDL_Rect rect2_; // Rectangulo usado para crear los efectos de transición
int num_squares_width_; // Cantidad total de cuadraditos en horizontal para el FadeType::RANDOM_SQUARE
int num_squares_height_; // Cantidad total de cuadraditos en vertical para el FadeType::RANDOM_SQUARE
std::vector<SDL_Rect> square_; // Vector con los indices de los cuadrados para el FadeType::RANDOM_SQUARE
int fade_random_squares_delay_; // Duración entre cada pintado de cuadrados
int fade_random_squares_mult_; // Cantidad de cuadrados que se pintaran cada vez
int post_duration_; // Duración posterior del fade tras finalizar
int post_counter_; // Contador para la duración posterior
FadeType type_; // Tipo de fade a realizar
FadeMode mode_; // Modo de fade a realizar
FadeState state_ = FadeState::NOT_ENABLED; // Estado actual del objeto
Uint16 counter_; // Contador interno
Uint8 r_, g_, b_, a_; // Colores para el fade
SDL_Rect rect1_; // Rectangulo usado para crear los efectos de transición
SDL_Rect rect2_; // Rectangulo usado para crear los efectos de transición
int num_squares_width_; // Cantidad total de cuadraditos en horizontal para el FadeType::RANDOM_SQUARE
int num_squares_height_; // Cantidad total de cuadraditos en vertical para el FadeType::RANDOM_SQUARE
std::vector<SDL_Rect> square_; // Vector con los indices de los cuadrados para el FadeType::RANDOM_SQUARE
int fade_random_squares_delay_; // Duración entre cada pintado de cuadrados
int fade_random_squares_mult_; // Cantidad de cuadrados que se pintaran cada vez
int post_duration_ = 0; // Duración posterior del fade tras finalizar
int post_counter_ = 0; // Contador para la duración posterior
int pre_duration_ = 0; // Duración previa del fade antes de iniciar
int pre_counter_ = 0; // Contador para la duración previa
int value_ = 0; // Estado actual del fade entre 0 y 100
// Inicializa las variables
void init();
@@ -52,6 +64,9 @@ private:
// Limpia el backbuffer
void cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
// Calcula el valor del estado del fade
int calculateValue(int min, int max, int current);
public:
// Constructor
Fade();
@@ -71,21 +86,17 @@ public:
// Activa el fade
void activate();
// Comprueba si ha terminado la transicion
bool hasEnded() const;
// Comprueba si está activo
bool isEnabled() const;
// Establece el tipo de fade
void setType(FadeType type);
// Establece el modo de fade
void setMode(FadeMode mode);
// Establece el color del fade
void setColor(Uint8 r, Uint8 g, Uint8 b);
// Establece la duración posterior
void setPost(int value);
// Getters
int getValue() const { return value_; }
bool isEnabled() const { return state_ != FadeState::NOT_ENABLED; }
bool hasEnded() const { return state_ == FadeState::FINISHED; }
// Setters
void setType(FadeType type) { type_ = type; }
void setMode(FadeMode mode) { mode_ = mode; }
void setPostDuration(int value) { post_duration_ = value; }
void setPreDuration(int value) { pre_duration_ = value; }
};

File diff suppressed because it is too large Load Diff

View File

@@ -5,27 +5,26 @@
#include <memory> // Para shared_ptr, unique_ptr
#include <string> // Para string
#include <vector> // Para vector
#include "balloon.h" // Para Balloon
#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 12-12
class Background; // lines 13-13
class BalloonFormations; // lines 14-14
class Bullet; // lines 15-15
class Explosions; // lines 16-16
class Fade; // lines 17-17
class Input; // lines 18-18
class Item; // lines 19-19
class PathSprite; // lines 20-20
class Scoreboard; // lines 21-21
class Screen; // lines 22-22
class SmartSprite; // lines 23-23
class Text; // lines 24-24
class Texture; // lines 25-25
enum class BulletType : Uint8; // lines 26-26
enum class ItemType; // lines 27-27
class Asset; // lines 13-13
class Background; // lines 14-14
class BalloonManager;
class Tabe;
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;
@@ -64,10 +63,18 @@ constexpr int TOTAL_SCORE_DATA = 3;
class Game
{
private:
// Constantes
// Enum
enum class GameState
{
FADE_IN,
ENTERING_PLAYER,
SHOWING_GET_READY_MESSAGE,
PLAYING,
COMPLETED,
GAME_OVER,
};
// Contadores
static constexpr int STAGE_COUNTER_ = 200;
static constexpr int HELP_COUNTER_ = 1000;
static constexpr int GAME_COMPLETED_START_FADE_ = 500;
static constexpr int GAME_COMPLETED_END_ = 700;
@@ -118,14 +125,11 @@ 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<std::unique_ptr<SmartSprite>> smart_sprites_; // Vector con los smartsprites
@@ -133,58 +137,40 @@ private:
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::vector<std::shared_ptr<Texture>>> player_textures_; // Vector con todas las texturas de los jugadores;
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::unique_ptr<Fade> fade_in_; // Objeto para renderizar fades
std::unique_ptr<Fade> fade_out_; // Objeto para renderizar fades
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
std::unique_ptr<Tabe> tabe_; // Objeto para gestionar el Tabe Volaor
std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados
// Variables
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
int current_stage_; // Indica la fase actual
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
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 game_completed_ = false; // Indica si se ha completado la partida, llegando al final de la ultima pantalla
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)
bool power_ball_enabled_ = false; // Indica si hay una powerball ya activa
float balloon_speed_; // Velocidad a la que se mueven los enemigos
float default_balloon_speed_; // Velocidad base de los enemigos, sin incrementar
float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
float get_ready_bitmap_path_[STAGE_COUNTER_]; // Vector con los puntos X por donde se desplaza el texto
int stage_bitmap_path_[STAGE_COUNTER_]; // Vector con los puntos Y por donde se desplaza el texto
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
int balloons_popped_ = 0; // Lleva la cuenta de los globos explotados
int counter_ = 0; // Contador para el juego
int current_power_ = 0; // Poder actual almacenado para completar la fase
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 last_balloon_deploy_ = 0; // Guarda cual ha sido la última formación desplegada para no repetir;
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
int power_ball_counter_ = 0; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
int stage_bitmap_counter_ = STAGE_COUNTER_; // Contador para el tiempo visible del texto de Stage
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::FADE_IN; // Estado
#ifdef DEBUG
bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
#endif
@@ -201,12 +187,6 @@ private:
// Asigna texturas y animaciones
void setResources();
// Crea una formación de enemigos
void deployBalloonFormation();
// Aumenta el poder de la fase
void increaseStageCurrentPower(int power);
// Actualiza el valor de HiScore en caso necesario
void updateHiScore();
@@ -220,52 +200,10 @@ private:
void updateStage();
// Actualiza el estado de fin de la partida
void updateGameOver();
void updateGameStateGameOver();
// 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, BalloonType type, BalloonSize size, float velx, float speed, int stopped_counter);
// 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);
// 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();
// 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();
// 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);
@@ -273,11 +211,11 @@ private:
// Comprueba la colisión entre el jugador y los items
void checkPlayerItemCollision(std::shared_ptr<Player> &player);
// Comprueba la colisión entre las balas y los globos
void checkBulletBalloonCollision();
// Comprueba y procesa la colisión de las balas
void checkBulletCollision();
// Mueve las balas activas
void moveBullets();
void updateBullets();
// Pinta las balas activas
void renderBullets();
@@ -304,7 +242,10 @@ private:
void freeItems();
// Crea un objeto PathSprite
void createPathSprite(int x, std::shared_ptr<Texture> texture);
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();
@@ -330,42 +271,21 @@ private:
// 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();
// Actualiza la variable EnemyDeployCounter
void updateBalloonDeployCounter();
// Actualiza y comprueba el valor de la variable
void updateTimeStopped();
// Gestiona el nivel de amenaza
void updateMenace();
// Actualiza el fondo
void updateBackground();
// Inicializa las variables que contienen puntos de ruta para mover objetos
void initPaths();
// Pinta diferentes mensajes en la pantalla
void renderMessages();
// Habilita el efecto del item de detener el tiempo
void enableTimeStopItem();
// 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();
// Actualiza el tramo final de juego, una vez completado
void updateGameCompleted();
// Actualiza las variables de ayuda
void updateHelper();
@@ -390,11 +310,8 @@ private:
// Pausa el juego
void pause(bool value);
// Comprueba si la música ha de estar sonando
void checkMusicStatus();
// Añade una puntuación a la tabla de records
void addScoreToScoreBoard(const std::string &name, int score);
void addScoreToScoreBoard(const std::shared_ptr<Player> &player);
// Saca del estado de GAME OVER al jugador si el otro está activo
void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index);
@@ -453,18 +370,57 @@ private:
// Inicializa los jugadores
void initPlayers(int player_id);
// Crea dos globos gordos
void createTwoBigBalloons();
// Pausa la música
void pauseMusic();
// Reanuda la música
void resumeMusic();
// Hace sonar la música
void playMusic();
// 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 dicho estado
void updateGameStateFadeIn();
// Actualiza las variables durante dicho estado
void updateGameStateEnteringPlayer();
// Actualiza las variables durante dicho estado
void updateGameStateShowingGetReadyMessage();
// Actualiza las variables durante el transcurso normal del juego
void updateGameStatePlaying();
// Gestiona eventos para el estado del final del juego
void updateGameStateCompleted();
// 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();
// Cambia el estado del juego
void setState(GameState state);
public:
// Constructor
Game(int playerID, int current_stage, bool demo);

View File

@@ -5,9 +5,15 @@
#include "jail_audio.h" // Para JA_PlaySound
#include "param.h" // Para Param, param, ParamGame, ParamTitle
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "smart_sprite.h" // Para SmartSprite
#include "sprite.h" // Para Sprite
#include "texture.h" // Para Texture
#include "utils.h" // Para Color
constexpr int ZOOM_FACTOR = 5;
constexpr int FLASH_DELAY = 3;
constexpr int FLASH_LENGHT = FLASH_DELAY + 3;
// Constructor
GameLogo::GameLogo(int x, int y)
@@ -15,36 +21,25 @@ GameLogo::GameLogo(int x, int y)
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>(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();
}
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;
shake_.desp = 1;
shake_.delay = 2;
shake_.lenght = 8;
shake_.remaining = shake_.lenght;
shake_.counter = shake_.delay;
shake_.origin = xp;
coffee_crisis_status_ = Status::DISABLED;
arcade_edition_status_ = Status::DISABLED;
shake_.init(1, 2, 8, xp);
zoom_ = 3.0f * ZOOM_FACTOR;
// Inicializa el bitmap de 'Coffee'
coffee_sprite_->setPosX(xp);
@@ -90,6 +85,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
@@ -99,7 +97,7 @@ void GameLogo::render()
coffee_sprite_->render();
crisis_sprite_->render();
if (status_ == Status::FINISHED)
if (arcade_edition_status_ != Status::DISABLED)
{
arcade_edition_sprite_->render();
}
@@ -112,20 +110,22 @@ void GameLogo::render()
// Actualiza la lógica de la clase
void GameLogo::update()
{
switch (status_)
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;
// Reproduce el efecto sonoro
JA_PlaySound(Resource::get()->getSound("title.wav"));
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
Screen::get()->shake();
}
break;
@@ -133,7 +133,7 @@ void GameLogo::update()
case Status::SHAKING:
{
// Agita el logo
// Agita "COFFEE CRISIS"
if (shake_.remaining > 0)
{
if (shake_.counter > 0)
@@ -153,7 +153,8 @@ void GameLogo::update()
{
coffee_sprite_->setPosX(shake_.origin);
crisis_sprite_->setPosX(shake_.origin + 15);
status_ = Status::FINISHED;
coffee_crisis_status_ = Status::FINISHED;
arcade_edition_status_ = Status::MOVING;
}
dust_right_sprite_->update();
@@ -173,19 +174,74 @@ void GameLogo::update()
default:
break;
}
switch (arcade_edition_status_)
{
case Status::MOVING:
{
zoom_ -= 0.1f * ZOOM_FACTOR;
arcade_edition_sprite_->setZoom(zoom_);
if (zoom_ <= 1.0f)
{
arcade_edition_status_ = Status::SHAKING;
zoom_ = 1.0f;
arcade_edition_sprite_->setZoom(zoom_);
shake_.init(1, 2, 8, arcade_edition_sprite_->getX());
JA_PlaySound(Resource::get()->getSound("title.wav"));
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
Screen::get()->shake();
}
break;
}
case Status::SHAKING:
{
// Agita "ARCADE EDITION"
if (shake_.remaining > 0)
{
if (shake_.counter > 0)
{
shake_.counter--;
}
else
{
shake_.counter = shake_.delay;
const auto desp = shake_.remaining % 2 == 0 ? shake_.desp * (-1) : shake_.desp;
arcade_edition_sprite_->setX(shake_.origin + desp);
shake_.remaining--;
}
}
else
{
arcade_edition_sprite_->setX(shake_.origin);
arcade_edition_status_ = Status::FINISHED;
}
break;
}
default:
break;
}
if (coffee_crisis_status_ == Status::FINISHED &&
arcade_edition_status_ == Status::FINISHED &&
post_finished_counter_ > 0)
{
--post_finished_counter_;
}
}
// Activa la clase
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 post_finished_counter_ == 0;
}
// Recarga las texturas
@@ -194,6 +250,7 @@ void GameLogo::reLoad()
dust_texture_->reLoad();
coffee_texture_->reLoad();
crisis_texture_->reLoad();
arcade_edition_texture_->reLoad();
}
// Calcula el desplazamiento vertical inicial

View File

@@ -20,12 +20,30 @@ private:
struct Shake
{
int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x
int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse
int counter; // Contador para el retraso
int lenght; // Cantidad de desplazamientos a realizar
int remaining; // Cantidad de desplazamientos pendientes a realizar
int origin; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
int desp = 1; // Pixels de desplazamiento para agitar la pantalla en el eje x
int delay = 2; // Retraso entre cada desplazamiento de la pantalla al agitarse
int lenght = 8; // Cantidad de desplazamientos a realizar
int remaining = lenght; // Cantidad de desplazamientos pendientes a realizar
int counter = delay; // Contador para el retraso
int origin; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
// Constructor por defect
Shake() = default;
// Constructor
Shake(int d, int de, int l, int o)
: desp(d), delay(de), lenght(l), remaining(l), counter(de), origin(o) {}
// Inicializa los miembros
void init(int d, int de, int l, int o)
{
desp = d;
delay = de;
lenght = l;
remaining = l;
counter = de;
origin = o;
}
};
// Objetos y punteros
@@ -43,11 +61,14 @@ private:
std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite con los graficos de "Arcade Edition"
// 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"
int post_finished_counter_ = 1; // Contador final una vez terminada las animaciones de los logos
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();

View File

@@ -1,29 +1,22 @@
#include "global_inputs.h"
#include <string> // Para operator+, string
#include "input.h" // Para Input, InputType, INPUT_DO_NOT_ALLOW_REPEAT
#include "jail_audio.h" // Para JA_EnableMusic, JA_EnableSound
#include "lang.h" // Para getText
#include <string> // Para operator+, string, to_string, basic_string
#include <vector> // Para vector
#include "asset.h" // Para Asset
#include "input.h" // Para Input, InputDeviceToUse, InputType, INPU...
#include "jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundVolume
#include "lang.h" // Para Code, getText, change, loadFromFile
#include "notifier.h" // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp
#include "options.h" // Para Options, OptionsAudio, options, OptionsM...
#include "options.h" // Para Options, options, OptionsGame, OptionsAudio
#include "screen.h" // Para Screen, ScreenVideoMode
#include "section.h" // Para Name, Options, name, options
#include "utils.h" // Para boolToOnOff, stringInVector
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)
@@ -32,16 +25,18 @@ namespace globalInputs
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
{
// 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);
Notifier::get()->showText({lang::getText(index), std::string()}, -1, exit_code);
#else
Notifier::get()->showText(lang::getText(94), std::string(), -1, exit_code);
Notifier::get()->showText({lang::getText(94), std::string()}, -1, exit_code);
#endif
}
}
@@ -50,95 +45,239 @@ namespace globalInputs
void reset()
{
section::name = section::Name::INIT;
Notifier::get()->showText("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);
Notifier::get()->showText("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)});
}
// Cambia el modo de disparo
void toggleFireMode()
{
options.game.autofire = !options.game.autofire;
Notifier::get()->showText({"Autofire " + boolToOnOff(options.game.autofire)});
}
// 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_WITH_KEYBOARD);
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_WITH_CONTROLLER);
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))
// Autofire
if (Input::get()->checkInput(InputType::AUTO_FIRE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
service_pressed_counter[i + 1]++;
toggleFireMode();
return;
}
if (service_pressed_counter[i + 1] >= 3000)
// Idioma
if (Input::get()->checkInput(InputType::CHANGE_LANG, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
changeLang();
return;
}
// 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;
}
}

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