196 Commits

Author SHA1 Message Date
ff7aef827c migracio a OpenGL 3.3 Core Profile completada 2025-10-02 18:24:18 +02:00
6ff7ccf69a migrat a OpenGL 3.3 Core Profile 2025-10-02 18:15:39 +02:00
e347e04d33 fix: arreglat bug en jail_shader.cpp que no aplicava be el tamany de la textura amb filtros al canviar el tamany de la finestra si arrancaves el joc sense filtros activats 2025-10-02 17:24:40 +02:00
7946ea54a6 unificats els shaders glsl en un sol fitxer
corregida la inicialització de opengl i shaders
2025-10-02 17:11:38 +02:00
79033346c0 migrat fitxer de config a v2 2025-10-02 16:35:11 +02:00
62b73d6f41 bug fix: si desapareixia la maquina de cafe, ja no eixia mes 2025-10-02 12:04:17 +02:00
218ddabb5e bug fix: no eixien pacos 2025-10-02 08:28:15 +02:00
427f40632a scoreboard.cpp: animació de SCORE a ENTER_NAME 2025-10-01 21:31:42 +02:00
a29b4d4379 scoreboard.cpp: modificada la easing function de desplaçament vertical a easeInOutSine 2025-10-01 20:10:42 +02:00
d851cdd2fe scoreboard.cpp: afegit un setMode() com deu mana 2025-10-01 20:06:08 +02:00
3354d00814 Transició acabada, encara que hi ha un desfase de 1 pixel 2025-10-01 19:34:23 +02:00
7bd7ba84e0 scoreboard.cpp: treballant en transicio de ENTER_NAME a SHOW_NAME 2025-10-01 19:11:58 +02:00
6ad34eaf57 finalitzada la implementació del carrusel 2025-10-01 18:49:11 +02:00
b4f2251508 animacio al pixel del carrusel feta, falla el color que no transiciona 2025-10-01 18:36:14 +02:00
473a52f986 treballant en la animacio alpixel del carrusel 2025-10-01 18:05:00 +02:00
bcdd48d622 carrusel funcional i acabat 2025-10-01 17:49:29 +02:00
6985569573 el carrusel ara es mou amb esquerra i dreta en lloc de amb amunt i avall 2025-10-01 17:13:52 +02:00
5db43e674d Color: afegit metode LERP() 2025-10-01 14:11:32 +02:00
34baa3c97d treballan en el carrusel per a posar el nom 2025-10-01 14:00:56 +02:00
bddb790fe2 creat bullet_manager.cpp 2025-09-30 20:41:35 +02:00
6fae12ba02 fix: la ultima tarjeta de la intro no tenia temps de repos 2025-09-30 19:59:38 +02:00
4e083a8cdb item.cpp: afegida rotació 2025-09-30 14:16:25 +02:00
cbe4315701 moving_sprite.cpp: afegit umbral a stopRotate() 2025-09-30 14:11:58 +02:00
49d561b583 moving_sprite.cpp: afegida funcio per a escalar la velocitat de rotacio 2025-09-30 13:59:13 +02:00
6e56a6fd79 moving_sprite.cpp: afegits nous metodes per controlar la rotació 2025-09-30 13:47:48 +02:00
267d9647e0 moving_sprite.cpp: la variable rotate.speed ja no es gastava 2025-09-30 13:38:06 +02:00
13b3702d00 eliminat param.game.item_size 2025-09-30 13:23:50 +02:00
4500845dcd muguda la logica de demo de utils.cpp a demo.cpp 2025-09-30 12:58:32 +02:00
a4abc02f88 nou: modificat el valor de velocitat en la creació dels globos verds. i tornat a deixar com estava 2025-09-30 12:42:38 +02:00
a0fb6934b0 corregit: en el mode demo no calculava correctament el estat del fondo 2025-09-30 09:56:32 +02:00
19645445b2 corregit: els fills dels globos verds eixien taronja 2025-09-30 08:47:49 +02:00
efe8628a3c corregit: el log de CREATING PLAYER TEXTURES en resource.cpp 2025-09-29 14:22:44 +02:00
c98cb0d29f repensada la forma d'asignar fitxers de demo als jugadors
refets els fitxers de demo i afegit un tercer fitxer
2025-09-29 14:00:10 +02:00
c16fc1bae5 corregit: el mode demo ja funciona correctament 2025-09-29 12:47:13 +02:00
fa0af1179a corregit: no trobava version.h 2025-09-29 07:54:46 +02:00
d1e4a5eb07 eliminat tot el define NO_AUDIO del codi 2025-09-27 00:33:05 +02:00
e18d1b186a player.h: eliminat codi mort 2025-09-27 00:22:46 +02:00
d056a5e336 nou: afegida versió de git en la pantalla de carrega 2025-09-27 00:20:46 +02:00
b9e26aa755 corregit: flags estatics en credits.cpp i title.cpp 2025-09-26 23:48:08 +02:00
b2afef2226 corregit: flags estatics en hiscore_tale.cpp 2025-09-26 23:40:37 +02:00
c400aa96c0 corregit: flags estatics en game.cpp 2025-09-26 23:36:49 +02:00
8818954dcd afegit define rapidet per a renderer metal basic en macos 2025-09-26 22:45:14 +02:00
b92e5df98b nou: sonidos de bala diferent per a cada jugador 2025-09-26 20:48:22 +02:00
83871273ec nou: bales de colors diferents per a cada jugador 2025-09-26 20:37:00 +02:00
0459b39366 screen.cpp: getDisplayInfo()
resource.cpp: afegida info del display en la pantalla de carrega
2025-09-26 19:42:39 +02:00
5bb0ff19bc corregit: asset::checkFile() fallava desde fora del directori 2025-09-26 19:16:25 +02:00
a867b3cf4d integrat empaquetador de recursos en el makefile 2025-09-26 18:16:48 +02:00
8a6ce8e66d organitzat player.h 2025-09-26 17:37:29 +02:00
a40f04a739 nou: musiqueta i veu per al game over i timings ajustats 2025-09-26 17:20:35 +02:00
0c670fd344 novetat: canvi de color de les bales quan queda poc powerUp 2025-09-26 14:13:52 +02:00
35f4bf690c corregit: bug en Audio::fadeOutMusic quan la musica no es reproduia en bucle 2025-09-25 21:21:39 +02:00
abeaf47f96 corregit: timing de les celebracions del final 2025-09-25 19:48:58 +02:00
6498c35628 corregit audio i timing del game over 2025-09-25 19:36:40 +02:00
d1c6af02db corregit: la musica del joc soles sonava la primera volta 2025-09-25 19:19:46 +02:00
5edef17d84 nou: musica al completar el joc 2025-09-25 19:10:46 +02:00
e4532fcef2 nou: ruidet per a quan acabes de posar el nom 2025-09-25 18:18:39 +02:00
7a8d66c29d nou: quan arribes a la maxima puntuació, posa un lletreret 2025-09-25 17:52:49 +02:00
54292c9f8f fix: warning de override 2025-09-25 16:58:01 +02:00
3897553704 eliminat el vector precalculat en tiled_bg per al moviment circular 2025-09-25 08:08:29 +02:00
308f5c20fb corregit en background.cpp la desaceleració final, millorada amb funció de suavitzat i arreglades les velocitats dels nuvols que no variaven amb el pas del joc 2025-09-24 21:54:38 +02:00
987dcd0205 fix: el audio del logo.cpp soles sonava la primera volta 2025-09-24 20:54:45 +02:00
d56f23544c corregit menu_renderer.cpp, de vegades es modificava el ample del menu al canviar les opcions 2025-09-24 20:46:07 +02:00
c79a846b29 migrat service_menu.cpp a deltaTime 2025-09-24 19:34:08 +02:00
ad39d55e79 style: static auto *const SCREEN = Screen::get(); 2025-09-24 18:57:10 +02:00
853ef426f0 corregit el START PROMPT en title.cpp que no resetejava el contador de parpadeig 2025-09-24 18:51:36 +02:00
cadf7de3d8 tiled_bg.cpp, afegit changeSpeedTo() 2025-09-24 18:44:37 +02:00
ec65ff9acb corregit audio de timeStopItem 2025-09-24 18:26:39 +02:00
d077374883 migrat a deltaTime screen.cpp i notifier.cpp 2025-09-24 18:08:50 +02:00
40a2b2cc00 afegit TODO per al proxim dia 2025-09-24 14:02:30 +02:00
b3f3f151da corregits alguns parametres de ms a s 2025-09-24 13:56:12 +02:00
3fdd61655a corregit throwCoffee() i el rolling del jugador 2025-09-24 13:24:05 +02:00
504727b95f corregit del delay entre formacions 2025-09-24 13:09:54 +02:00
ff5446fcdf corregit createItemText() 2025-09-24 12:41:41 +02:00
545eb70082 corregida la creacio de globos 2025-09-24 12:37:21 +02:00
232a23a5dd corregida velocitat_y en createChild() 2025-09-24 11:42:48 +02:00
c9a29e26dd revisant la seccio game: bales, items e inici 2025-09-24 11:37:23 +02:00
2977869ab5 revisat tabe.cpp, item.cpp i game.cpp 2025-09-24 09:37:23 +02:00
6a223b68ba revisant title.cpp (falla el jugador) 2025-09-23 14:13:48 +02:00
3fafff026b revisat balloon_formationc.cpp i credits.cpp 2025-09-23 14:03:07 +02:00
159528adc9 revisat credits.cpp, player.cpp, balloon.cpp i balloon_manager.cpp 2025-09-23 13:42:09 +02:00
6c8f231b34 revisat instructions.cpp 2025-09-23 12:10:16 +02:00
c5d6d77ebf revisat hiscore_table.cpp 2025-09-23 11:24:29 +02:00
5e73327b2f revisat intro.cpp, path_sprite i writer.cpp 2025-09-23 11:13:15 +02:00
720d286dcf revisat logo.cpp 2025-09-23 09:11:29 +02:00
dd13a2bd7c revisat background, game_logo, smart sprite, tiled_bg 2025-09-23 09:00:00 +02:00
1a6ef79466 revisat moving i animated sprite 2025-09-23 08:29:29 +02:00
8f83a1d13e magic numbers: moving_sprite.cpp i game_logo.cpp 2025-09-22 13:57:58 +02:00
9edfe6877f magic numbers: item.cpp 2025-09-22 13:14:23 +02:00
91b26631c6 magic numbers: bullet.cpp 2025-09-22 12:14:09 +02:00
331a690b78 fix: balloon_manager.cpp conflicto al crear los globos y detener el tiempo 2025-09-22 10:13:12 +02:00
5e3946e28b fix: no inicialitzava be animated_sprite 2025-09-22 10:03:38 +02:00
d4a0189dc8 arreglant balloon.cpp per a deltaTime pur 2025-09-19 14:15:44 +02:00
568b941990 eliminats metodes frame-based obsolets 2025-09-19 09:56:25 +02:00
49a3989ecf magic numbers: game.cpp 2025-09-19 09:11:10 +02:00
af7cb01ead magic numbers: game.cpp 2025-09-19 07:33:27 +02:00
5c82916650 magic numbers: game.cpp i player.cpp 2025-09-18 14:17:54 +02:00
0c0518adac magic numbers: game.cpp i player.cpp (en progres) 2025-09-18 13:15:43 +02:00
cb7b290818 magic numbers: game.cpp 2025-09-17 14:20:13 +02:00
ae30c9b34f magic numbers: title.cpp 2025-09-17 13:53:31 +02:00
9acd9aa631 magic numbers: intro.cpp 2025-09-17 13:25:16 +02:00
577510ff8c magic numbers: logo.cpp 2025-09-17 13:01:43 +02:00
66566913f6 delta-time: game.cpp (funciona pero va un poc massa ràpid) 2025-09-16 22:56:00 +02:00
3e6cc9dfab delta-time: explosions.cpp 2025-09-16 22:43:16 +02:00
a15e29344f delta-time: balloon.cpp
delta-time: balloon_manager.cpp
delta-time: credits.cpp
2025-09-16 22:38:48 +02:00
a96a17e11b delta-time: tabe.cpp 2025-09-16 20:29:35 +02:00
e0f6a424a9 delta-time: bullet.cpp 2025-09-16 20:26:22 +02:00
49e30f947a delta-time: title.cpp 2025-09-16 20:23:10 +02:00
470a07d28c delta-time: player.cpp 2025-09-16 19:21:44 +02:00
65716fce20 delta-time: tiled_bg.cpp 2025-09-16 17:35:03 +02:00
dfa66b0e95 delta-time: game_logo.cpp
delta-time: smart_sprite.cpp
2025-09-16 17:19:05 +02:00
3d9ffe356e Elimina .claude 2025-09-16 17:18:39 +02:00
19768cb72b delta-time: animated_sprite.cpp 2025-09-16 16:51:31 +02:00
26e0fd7247 delta-time: moving_sprite.cpp 2025-09-16 16:37:39 +02:00
e2fd470ad3 migració a delta time 2025-09-16 12:23:02 +02:00
a72ae0a5fc migració a delta time 2025-09-16 12:06:49 +02:00
7579594c22 migració a delta time 2025-09-16 10:48:22 +02:00
6c702e7e23 Logo: convertit per a usar delta time 2025-09-16 08:40:41 +02:00
fb9c78eb49 warning: balloon_manager.cpp varios ordres de inicialització mal 2025-08-27 10:27:18 +02:00
62f65cbd5a warning: balloon_manager.cpp varios ordres de inicialització mal 2025-08-27 10:19:30 +02:00
057d3dcfee bug fix: en la tabla de puntuacions, no apareix la estreleta al completar el joc amb 1CC
bug fix: posant nom al completar el joc, si "passes" el mostrar el nom, mata al jugador en lloc de fer que se'n vaja

Resol #92 i #98
2025-08-26 08:21:33 +02:00
c85336a4d0 fix: el tabe podia spawnejar-se en la seqüencia final.
Resol #89
2025-08-24 18:54:20 +02:00
e4702e4e24 bug fix: Audio::fadeOutMusic no ha de fer fade si la musica no sona 2025-08-24 17:39:07 +02:00
928335576c corregida la llista de inicialització en clang-format
creat Balloon::Config per a inicialitzar globos
2025-08-24 17:16:49 +02:00
fe950e6f17 bug fix: en el modo demo la powerball feia ruido.
Resol #84
2025-08-24 14:57:08 +02:00
6e81b6e60c Merge branch 'main' of https://gitea.sustancia.synology.me/jaildesigner/coffee_crisis_arcade_edition 2025-08-24 14:37:32 +02:00
74f6fe3501 Afegit outline al text 2x
corregit el marcador durant el Player::State::RECOVER
2025-08-24 14:37:30 +02:00
dfdb679054 Merge branch 'main' of https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition 2025-08-24 10:51:10 +02:00
26ed479306 delete 2025-08-24 10:51:07 +02:00
32e9da55ef Afegit so de service_menu_back
Retocats els audios de service menu
Afegit so a ENTER NAME
Arreglos visuals a ENTER NAME
2025-08-23 21:06:20 +02:00
610083578e style: eliminat soroll de drop item amb maquina de café
Quan ix una maquina de café ja no se sent el so de drop item
per a millorar l'experiència sonora del joc.

Resol #91
2025-08-23 20:05:16 +02:00
7250073d60 actualitzat LICENSE 2025-08-19 16:45:00 +02:00
dfa06870e4 actualitzat makefile per a linux 2025-08-19 16:42:40 +02:00
81f3a25143 afegit makefile per a macos 2025-08-19 16:39:39 +02:00
5aca95f3d2 neteja de temporals al acabar 2025-08-19 16:29:52 +02:00
7b193605e6 refet makefile i eliminades *.dll 2025-08-19 14:09:11 +02:00
089a5b15d7 actualitzat Makefile per a windows 2025-08-19 14:01:32 +02:00
e6a14ca57d eliminat el log del codi 2025-08-19 13:55:22 +02:00
467d609c28 debug 2025-08-19 13:50:11 +02:00
e03c798000 afegits logs peer a la carrega de musica i sons 2025-08-19 13:46:07 +02:00
52d76b7338 arreglos pa NO integrar jail_audio en ResourceHelper 2025-08-19 13:36:03 +02:00
83ee9c2649 integrat animated_sprite amb ResourceHelper 2025-08-19 13:25:12 +02:00
43788bb01a faltaven mes integracions de texture amb ResourceHelper 2025-08-19 13:22:38 +02:00
58cf78e1e3 integracions de texture.cpp amb ResourceHelper 2025-08-19 13:13:27 +02:00
6bf8490776 integrades mes clases amb ResourceHelper
mogudes les dades de la demo a resource.pack
2025-08-19 13:08:37 +02:00
8cfe28922c integrat Text amb ResourceHelper 2025-08-19 12:45:53 +02:00
63990c75c2 modificat texture.cpp per a gastar ResourceHelper 2025-08-19 12:41:08 +02:00
94dca528ab fix assets.txt 2025-08-19 10:13:12 +02:00
4b6b89ceb2 integrat Asset amb ResourceHelper 2025-08-19 10:06:52 +02:00
ed077c1da5 treballant en resources.pack 2025-08-19 09:46:19 +02:00
2819b3628e el fitxer de parametres es guarda en options/config.txt 2025-08-17 21:42:26 +02:00
1e9e664012 creat param_red.txt
afegides guardes en setParams
2025-08-17 21:29:49 +02:00
0c8b39cee7 els items ja no tenen vel_x = 0 2025-08-17 20:42:55 +02:00
d7b3af5ab8 en el modo demo asignava cafes al jugador que no jugava i eixia saludant amb la camisa que no toca 2025-08-17 20:22:53 +02:00
5e5227305f arreglat bug en el estat pre del fade 2025-08-17 20:17:55 +02:00
3fc15a9512 afegit el fade RANDOM_SQAURE2
canviat els timings del fade a milisegons
2025-08-17 19:34:48 +02:00
e774e0e8ad modificat el efecte de invulnerabilitat per a que vaja menguant 2025-08-17 17:21:03 +02:00
a95776e6c7 retocat el audio de recover 2025-08-17 17:01:49 +02:00
0428ff26d5 options.h ara gasta defaults.h 2025-08-17 16:28:30 +02:00
fc3e2deb1f Item fix: alguns items es quedaven engantxats en la part de dalt 2025-08-17 16:18:48 +02:00
65ca17f938 afegit i parametritzat outline per als textos dels items 2025-08-17 16:07:16 +02:00
ff2a51a507 noves coses chules en la clase text 2025-08-17 14:25:17 +02:00
fe0083abd4 afagit a param el color de la camiseta per defecte 2025-08-17 13:25:10 +02:00
1c058694fd afegit a param el color de outline dels jugadors 2025-08-17 12:58:20 +02:00
cb0c3266d5 proposta 1 de versio RC2 2025-08-17 10:54:45 +02:00
8ddc5d94f1 clang-tidy 2025-08-17 10:20:41 +02:00
b359a73d50 He tornat a deixar el progres del fondo que fa tope en la ultima fase, no en el final del joc 2025-08-17 08:20:38 +02:00
142603db71 hi_score_table: faltava posar el fondo en modo manual
game: redefinides les prioritats de dibuixat -> jugadors altra volta al front
2025-08-17 08:08:48 +02:00
1ec272f017 . 2025-08-17 01:10:57 +02:00
327987447d passant linters a vore si trobe variables sense inicialitzar 2025-08-17 00:23:59 +02:00
ada5025c65 claude: arreglos d'estil 2025-08-16 19:48:32 +02:00
1ced698093 ja guarda la configuració del mando amb els boto-triggers 2025-08-16 18:13:55 +02:00
2a4c47a6ca ja permet mapejar botons tipo trigger 2025-08-16 18:03:32 +02:00
6102504d32 parametrizats els colors de les camisetes dels jugadors quan pillen café 2025-08-16 13:12:22 +02:00
a123b3aa93 afegit window_message a param 2025-08-16 11:24:28 +02:00
81d486f2d3 afegit defaults.h amb els valors per defecte de Param 2025-08-16 10:29:30 +02:00
0c10898bdc Tabe: afegit a Param 2025-08-16 09:54:34 +02:00
a3cd404545 retocs en els fitxers de configuració 2025-08-16 09:44:06 +02:00
5c708fc60a eliminat codi mort 2025-08-16 09:33:40 +02:00
960ee367df fix: els globos apareixien un frame mal situats al crearse desde un pare 2025-08-15 13:09:07 +02:00
a7519fc372 afegit AnimatedSprite::getCurrentAnimationFrame()
fix: player2.gif faltava el outline
noves veus i arreglo d'altres
style: fitxer de config
2025-08-15 11:09:17 +02:00
a983269080 animacions noves de recuperació per als jugadors 2025-08-15 06:38:52 +02:00
3964503f1c game fix: la velocitat dels globos dins de la fase actual muntava al primer globo explotat
game fix: al trencar una powerball ja no eixien mes globos
style: renombrades variables i funcions
2025-08-14 20:41:44 +02:00
8fcb7d1eb5 eliminat un warning en systemes unix 2025-08-14 18:05:36 +02:00
3e68afa4be game.cpp: llevat codi comentat mort de feia temps 2025-08-14 13:58:24 +02:00
ca6edcccc0 Afegida animacioneta pa quan continues 2025-08-14 12:55:29 +02:00
a388005968 Afegit lletreret de "gracies" al continuar 2025-08-14 12:37:39 +02:00
ea7628259a la IA havia trencat el recorregut de la lluna 2025-08-14 12:20:34 +02:00
a13e024934 fix: la IA havia trencat el indicador de fases restants 2025-08-14 11:36:29 +02:00
4cc5102d70 Stage ja carrega desde fitxer la informació de les fases 2025-08-14 11:14:54 +02:00
b2139d8e06 treballant en Background i Stage 2025-08-14 09:53:01 +02:00
ea3e704d34 posant ordre en Stage i Background 2025-08-13 14:04:24 +02:00
d5ab5748a7 actualitzat makefile per a linux desktop 2025-08-11 21:39:43 +02:00
e950eb335d YE! ACTUALIZAT MAKEFILE PA WINDOWS ALTRA VOLTA. PUTA IA 2025-08-11 20:30:59 +02:00
e667063767 actualitzat makefile per a linux 2025-08-11 20:28:16 +02:00
3534e4cc54 actualitzat makefile per a windows 2025-08-11 20:27:40 +02:00
685b04c840 afegits nous iconos per a la aplicació
afegit script en python per a crear els iconos
2025-08-11 19:12:17 +02:00
219 changed files with 12118 additions and 6643 deletions

View File

@@ -6,7 +6,16 @@ BreakBeforeBraces: Attach # Llaves en la misma línea
AllowShortIfStatementsOnASingleLine: true
AllowShortBlocksOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AlignOperands: false
AlignOperands: DontAlign
AlignAfterOpenBracket: DontAlign
BinPackArguments: false
BinPackParameters: false
ContinuationIndentWidth: 4
ConstructorInitializerIndentWidth: 4
IndentWrappedFunctionNames: false
Cpp11BracedListStyle: true
BreakConstructorInitializers: BeforeColon
AllowAllConstructorInitializersOnNextLine: false
PackConstructorInitializers: Never
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false

View File

@@ -1,8 +1,21 @@
Checks: >
readability-*,
modernize-*,
performance-*,
bugprone-unchecked-optional-access,
bugprone-sizeof-expression,
bugprone-suspicious-missing-comma,
bugprone-suspicious-index,
bugprone-undefined-memory-manipulation,
bugprone-use-after-move,
bugprone-out-of-bound-access,
-readability-identifier-length,
-readability-magic-numbers
-readability-magic-numbers,
-bugprone-narrowing-conversions,
-performance-enum-size,
-performance-inefficient-string-concatenation,
-bugprone-integer-division,
-bugprone-easily-swappable-parameters,
WarningsAsErrors: '*'
# Solo incluir archivos de tu código fuente

2
.gitignore vendored
View File

@@ -1,4 +1,5 @@
.vscode
.claude
build/
data/config/config.txt
*.DS_Store
@@ -17,3 +18,4 @@ debug.txt
cppcheck-result*
desktop.ini
ccae_release/
resources.pack

View File

@@ -14,6 +14,22 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
cmake_policy(SET CMP0072 NEW)
set(OpenGL_GL_PREFERENCE GLVND)
# --- GENERACIÓN DE VERSIÓN AUTOMÁTICA ---
find_package(Git QUIET)
if(GIT_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --short=7 HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
else()
set(GIT_HASH "unknown")
endif()
# Configurar archivo de versión
configure_file(${CMAKE_SOURCE_DIR}/source/version.h.in ${CMAKE_BINARY_DIR}/version.h @ONLY)
# --- 1. LISTA EXPLÍCITA DE FUENTES ---
set(APP_SOURCES
@@ -28,6 +44,9 @@ set(APP_SOURCES
source/main.cpp
source/param.cpp
source/resource.cpp
source/resource_helper.cpp
source/resource_loader.cpp
source/resource_pack.cpp
source/screen.cpp
source/text.cpp
source/writer.cpp
@@ -45,6 +64,7 @@ set(APP_SOURCES
source/balloon_manager.cpp
source/balloon.cpp
source/bullet.cpp
source/bullet_manager.cpp
source/enter_name.cpp
source/explosions.cpp
source/game_logo.cpp
@@ -76,6 +96,7 @@ set(APP_SOURCES
# --- Otros ---
source/color.cpp
source/demo.cpp
source/define_buttons.cpp
source/difficulty.cpp
source/input_types.cpp
@@ -89,28 +110,29 @@ set(APP_SOURCES
# Fuentes de librerías de terceros
set(EXTERNAL_SOURCES
source/external/jail_shader.cpp
source/external/jail_audio.cpp
source/external/json.hpp
source/external/gif.cpp
)
# Añadir jail_audio.cpp solo si el audio está habilitado
if(NOT DISABLE_AUDIO)
list(APPEND EXTERNAL_SOURCES source/external/jail_audio.cpp)
endif()
# Fuentes del sistema de renderizado
set(RENDERING_SOURCES
source/rendering/opengl/opengl_shader.cpp
)
# Configuración de SDL3
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
message(STATUS "SDL3 encontrado: ${SDL3_INCLUDE_DIRS}")
# --- 2. AÑADIR EJECUTABLE ---
add_executable(${PROJECT_NAME} ${APP_SOURCES} ${EXTERNAL_SOURCES})
add_executable(${PROJECT_NAME} ${APP_SOURCES} ${EXTERNAL_SOURCES} ${RENDERING_SOURCES})
# --- 3. DIRECTORIOS DE INCLUSIÓN ---
target_include_directories(${PROJECT_NAME} PUBLIC
"${CMAKE_SOURCE_DIR}/source"
"${CMAKE_SOURCE_DIR}/source/external"
"${CMAKE_SOURCE_DIR}/source/rendering"
"${CMAKE_BINARY_DIR}"
)
# Enlazar la librería SDL3
@@ -125,16 +147,9 @@ target_compile_options(${PROJECT_NAME} PRIVATE $<$<CONFIG:RELEASE>:-Os -ffunctio
# Definir _DEBUG en modo Debug
target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:DEBUG>:_DEBUG>)
# Opción para habilitar/deshabilitar audio
option(DISABLE_AUDIO "Disable audio system" OFF)
# Descomentar la siguiente línea para activar el modo grabación de demos
# target_compile_definitions(${PROJECT_NAME} PRIVATE RECORDING)
# Definir NO_AUDIO si la opción está activada
if(DISABLE_AUDIO)
target_compile_definitions(${PROJECT_NAME} PRIVATE NO_AUDIO)
message(STATUS "Audio deshabilitado - NO_AUDIO definido")
else()
message(STATUS "Audio habilitado")
endif()
# Configuración específica para cada plataforma
if(WIN32)

22
LICENSE
View File

@@ -1 +1,21 @@
GNU General Public License v3.0 only
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License
Copyright (c) 2025 Coffee Crisis Arcade Edition
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
You are free to:
- Share — copy and redistribute the material in any medium or format
- Adapt — remix, transform, and build upon the material
Under the following terms:
- Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
- NonCommercial — You may not use the material for commercial purposes.
- ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
To view a copy of this license, visit:
https://creativecommons.org/licenses/by-nc-sa/4.0/
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

231
Makefile
View File

@@ -3,6 +3,7 @@ DIR_ROOT := $(dir $(abspath $(MAKEFILE_LIST)))
DIR_SOURCES := $(addsuffix /, $(DIR_ROOT)source)
DIR_BIN := $(addsuffix /, $(DIR_ROOT))
DIR_BUILD := $(addsuffix /, $(DIR_ROOT)build)
DIR_TOOLS := $(addsuffix /, $(DIR_ROOT)tools)
# Variables
TARGET_NAME := coffee_crisis_arcade_edition
@@ -11,7 +12,33 @@ APP_NAME := Coffee Crisis Arcade Edition
RELEASE_FOLDER := ccae_release
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
RESOURCE_FILE := release/coffee.res
VERSION := 2025-08-10
# Variables para herramienta de empaquetado
ifeq ($(OS),Windows_NT)
PACK_TOOL := $(DIR_TOOLS)pack_resources.exe
PACK_CXX := $(CXX)
else
PACK_TOOL := $(DIR_TOOLS)pack_resources
PACK_CXX := $(CXX)
endif
PACK_SOURCES := $(DIR_TOOLS)pack_resources.cpp $(DIR_SOURCES)resource_pack.cpp
PACK_INCLUDES := -I$(DIR_ROOT)
# Versión automática basada en la fecha actual (específica por SO)
ifeq ($(OS),Windows_NT)
VERSION := $(shell powershell -Command "Get-Date -Format 'yyyy-MM-dd'")
else
VERSION := $(shell date +%Y-%m-%d)
endif
# Variables específicas para Windows (usando APP_NAME)
ifeq ($(OS),Windows_NT)
WIN_TARGET_FILE := $(DIR_BIN)$(APP_NAME)
WIN_RELEASE_FILE := $(RELEASE_FOLDER)/$(APP_NAME)
else
WIN_TARGET_FILE := $(TARGET_FILE)
WIN_RELEASE_FILE := $(RELEASE_FILE)
endif
# Nombres para los ficheros de lanzamiento
WINDOWS_RELEASE := $(TARGET_NAME)-$(VERSION)-win32-x64.zip
@@ -56,6 +83,9 @@ APP_SOURCES := \
source/path_sprite.cpp \
source/player.cpp \
source/resource.cpp \
source/resource_helper.cpp \
source/resource_loader.cpp \
source/resource_pack.cpp \
source/scoreboard.cpp \
source/screen.cpp \
source/sections/credits.cpp \
@@ -89,7 +119,7 @@ INCLUDES := -Isource -Isource/external
# Variables según el sistema operativo
ifeq ($(OS),Windows_NT)
FixPath = $(subst /,\\,$1)
CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows -DWINDOWS_BUILD
CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -static-libgcc -Wl,-Bstatic -lpthread -Wl,-Bdynamic -Wl,-subsystem,windows -DWINDOWS_BUILD
CXXFLAGS_DEBUG := -std=c++20 -Wall -g -D_DEBUG -DWINDOWS_BUILD
LDFLAGS := -lmingw32 -lws2_32 -lSDL3 -lopengl32
RM := del /Q
@@ -117,30 +147,48 @@ else
endif
endif
# Reglas para herramienta de empaquetado y resources.pack
$(PACK_TOOL): $(PACK_SOURCES)
@echo "Compilando herramienta de empaquetado..."
$(PACK_CXX) -std=c++17 -Wall -Os $(PACK_INCLUDES) $(PACK_SOURCES) -o $(PACK_TOOL)
@echo "✓ Herramienta de empaquetado lista: $(PACK_TOOL)"
pack_tool: $(PACK_TOOL)
resources.pack: $(PACK_TOOL)
@echo "Generando resources.pack desde directorio data/..."
$(PACK_TOOL) data resources.pack
@echo "✓ resources.pack generado exitosamente"
# Reglas para compilación
windows:
@echo off
@echo Compilando para Windows con nombre: "$(APP_NAME).exe"
windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
$(CXX) $(APP_SOURCES) $(RESOURCE_FILE) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE).exe"
strip -s -R .comment -R .gnu.version "$(TARGET_FILE).exe" --strip-unneeded
$(CXX) $(APP_SOURCES) $(RESOURCE_FILE) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_TARGET_FILE).exe"
strip -s -R .comment -R .gnu.version "$(WIN_TARGET_FILE).exe" --strip-unneeded
windows_rec:
@echo off
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRECORDING $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)_rec.exe"
@echo Compilando version de grabacion para Windows: "$(APP_NAME)_rec.exe"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRECORDING $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_TARGET_FILE)_rec.exe"
windows_debug:
@echo off
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug.exe"
@echo Compilando version debug para Windows: "$(APP_NAME)_debug.exe"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(WIN_TARGET_FILE)_debug.exe"
windows_release:
windows_release: resources.pack
@echo off
@echo Creando release para Windows - Version: $(VERSION)
# Crea carpeta temporal 'RELEASE_FOLDER'
powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force}
powershell if (-not (Test-Path "$(RELEASE_FOLDER)")) {New-Item "$(RELEASE_FOLDER)" -ItemType Directory}
# Copia la carpeta 'data'
powershell Copy-Item -Path "data" -Destination "$(RELEASE_FOLDER)" -recurse -Force
# Copia la carpeta 'config' y el archivo 'resources.pack'
powershell Copy-Item -Path "config" -Destination "$(RELEASE_FOLDER)" -recurse -Force
powershell Copy-Item -Path "resources.pack" -Destination "$(RELEASE_FOLDER)"
# Copia los ficheros que estan en la raíz del proyecto
powershell Copy-Item "LICENSE" -Destination "$(RELEASE_FOLDER)"
@@ -149,23 +197,27 @@ windows_release:
# Compila
windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
$(CXX) $(APP_SOURCES) $(RESOURCE_FILE) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE).exe"
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE).exe" --strip-unneeded
$(CXX) $(APP_SOURCES) $(RESOURCE_FILE) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_RELEASE_FILE).exe"
strip -s -R .comment -R .gnu.version "$(WIN_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)"
@echo Release creado: $(WINDOWS_RELEASE)
# Elimina la carpeta temporal 'RELEASE_FOLDER'
powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force}
macos:
@echo "Compilando para macOS: $(TARGET_NAME)"
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)"
macos_debug:
@echo "Compilando version debug para macOS: $(TARGET_NAME)_debug"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
macos_release:
macos_release: resources.pack
@echo "Creando release para macOS - Version: $(VERSION)"
# Elimina datos de compilaciones anteriores
$(RMDIR) "$(RELEASE_FOLDER)"
$(RMDIR) Frameworks
@@ -180,7 +232,8 @@ macos_release:
$(MKDIR) Frameworks
# Copia carpetas y ficheros
cp -R data "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp -R config "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp resources.pack "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp -R release/frameworks/SDL3.xcframework "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
cp -R release/frameworks/SDL3.xcframework Frameworks
cp release/*.icns "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
@@ -202,6 +255,7 @@ ifdef ENABLE_MACOS_X86_64
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_INTEL_RELEASE)"
$(RMFILE) tmp.dmg
@echo "Release Intel creado: $(MACOS_INTEL_RELEASE)"
endif
# Compila la versión para procesadores Apple Silicon
@@ -214,19 +268,23 @@ endif
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_APPLE_SILICON_RELEASE)"
$(RMFILE) tmp.dmg
@echo "Release Apple Silicon creado: $(MACOS_APPLE_SILICON_RELEASE)"
# Elimina las carpetas temporales
$(RMDIR) Frameworks
$(RMDIR) "$(RELEASE_FOLDER)"
linux:
@echo "Compilando para Linux: $(TARGET_NAME)"
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)"
strip -s -R .comment -R .gnu.version "$(TARGET_FILE)" --strip-unneeded
linux_debug:
@echo "Compilando version debug para Linux: $(TARGET_NAME)_debug"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
linux_release:
linux_release: resources.pack
@echo "Creando release para Linux - Version: $(VERSION)"
# Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)"
@@ -234,7 +292,8 @@ linux_release:
$(MKDIR) "$(RELEASE_FOLDER)"
# Copia ficheros
cp -R data "$(RELEASE_FOLDER)"
cp -R config "$(RELEASE_FOLDER)"
cp resources.pack "$(RELEASE_FOLDER)"
cp LICENSE "$(RELEASE_FOLDER)"
cp README.md "$(RELEASE_FOLDER)"
@@ -245,18 +304,118 @@ linux_release:
# Empaqueta ficheros
$(RMFILE) "$(LINUX_RELEASE)"
tar -czvf "$(LINUX_RELEASE)" -C "$(RELEASE_FOLDER)" .
@echo "Release creado: $(LINUX_RELEASE)"
# Elimina la carpeta temporal
$(RMDIR) "$(RELEASE_FOLDER)"
linux_release_desktop: resources.pack
@echo "Creando release con integracion desktop para Linux - Version: $(VERSION)"
# Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)"
# Crea la estructura de directorios estándar para Linux
$(MKDIR) "$(RELEASE_FOLDER)/$(TARGET_NAME)"
$(MKDIR) "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin"
$(MKDIR) "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications"
$(MKDIR) "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps"
$(MKDIR) "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/$(TARGET_NAME)"
# Copia ficheros del juego
cp -R config "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/$(TARGET_NAME)/"
cp resources.pack "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/$(TARGET_NAME)/"
cp LICENSE "$(RELEASE_FOLDER)/$(TARGET_NAME)/"
cp README.md "$(RELEASE_FOLDER)/$(TARGET_NAME)/"
# Compila el ejecutable
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)"
strip -s -R .comment -R .gnu.version "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)" --strip-unneeded
# Crea el archivo .desktop
@echo '[Desktop Entry]' > "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
@echo 'Version=1.0' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
@echo 'Type=Application' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
@echo 'Name=$(APP_NAME)' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
@echo 'Comment=Arcade action game - defend Earth from alien invasion!' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
@echo 'Exec=/opt/$(TARGET_NAME)/bin/$(TARGET_NAME)' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
@echo 'Icon=$(TARGET_NAME)' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
@echo 'Path=/opt/$(TARGET_NAME)/share/$(TARGET_NAME)' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
@echo 'Terminal=false' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
@echo 'StartupNotify=true' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
@echo 'Categories=Game;ArcadeGame;' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
@echo 'Keywords=arcade;action;shooter;retro;' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
# Copia el icono (si existe) y lo redimensiona si es necesario
@if [ -f "release/icon.png" ]; then \
if command -v magick >/dev/null 2>&1; then \
magick "release/icon.png" -resize 256x256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
echo "Icono redimensionado de release/icon.png (usando ImageMagick)"; \
elif command -v convert >/dev/null 2>&1; then \
convert "release/icon.png" -resize 256x256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
echo "Icono redimensionado de release/icon.png (usando ImageMagick legacy)"; \
elif command -v ffmpeg >/dev/null 2>&1; then \
ffmpeg -i "release/icon.png" -vf scale=256:256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png" -y -loglevel quiet; \
echo "Icono redimensionado de release/icon.png (usando ffmpeg)"; \
else \
cp "release/icon.png" "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
echo "Icono copiado sin redimensionar (instalar ImageMagick o ffmpeg para redimensionado automatico)"; \
fi; \
elif [ -f "release/coffee.png" ]; then \
cp "release/coffee.png" "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
echo "Icono copiado desde release/coffee.png"; \
else \
echo "Advertencia: No se encontró release/icon.png ni release/coffee.png - crear icono manualmente"; \
fi
# Crea script de instalación
@echo '#!/bin/bash' > "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'echo "Instalando $(APP_NAME)..."' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'sudo mkdir -p /opt/$(TARGET_NAME)' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'sudo cp -R bin /opt/$(TARGET_NAME)/' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'sudo cp -R share /opt/$(TARGET_NAME)/' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'sudo cp LICENSE /opt/$(TARGET_NAME)/' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'sudo cp README.md /opt/$(TARGET_NAME)/' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'sudo mkdir -p /usr/share/applications' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'sudo mkdir -p /usr/share/icons/hicolor/256x256/apps' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'sudo cp /opt/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop /usr/share/applications/' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'sudo cp /opt/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png /usr/share/icons/hicolor/256x256/apps/' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'sudo update-desktop-database /usr/share/applications 2>/dev/null || true' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'sudo gtk-update-icon-cache /usr/share/icons/hicolor 2>/dev/null || true' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'echo "$(APP_NAME) instalado correctamente!"' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
@echo 'echo "Ya puedes encontrarlo en el menu de aplicaciones en la categoria Juegos."' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
chmod +x "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
# Crea script de desinstalación
@echo '#!/bin/bash' > "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
@echo 'echo "Desinstalando $(APP_NAME)..."' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
@echo 'sudo rm -rf /opt/$(TARGET_NAME)' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
@echo 'sudo rm -f /usr/share/applications/$(TARGET_NAME).desktop' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
@echo 'sudo rm -f /usr/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
@echo 'sudo update-desktop-database /usr/share/applications 2>/dev/null || true' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
@echo 'sudo gtk-update-icon-cache /usr/share/icons/hicolor 2>/dev/null || true' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
@echo 'echo "$(APP_NAME) desinstalado correctamente."' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
chmod +x "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
# Empaqueta ficheros
$(RMFILE) "$(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz"
tar -czvf "$(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz" -C "$(RELEASE_FOLDER)" .
@echo "Release con integracion desktop creado: $(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz"
@echo "Para instalar: extraer y ejecutar ./$(TARGET_NAME)/install.sh"
# Elimina la carpeta temporal
$(RMDIR) "$(RELEASE_FOLDER)"
raspi:
@echo "Compilando para Raspberry Pi: $(TARGET_NAME)"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(TARGET_FILE)
strip -s -R .comment -R .gnu.version $(TARGET_FILE) --strip-unneeded
raspi_debug:
@echo "Compilando version debug para Raspberry Pi: $(TARGET_NAME)_debug"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE -DDEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
raspi_release:
raspi_release: resources.pack
@echo "Creando release para Raspberry Pi - Version: $(VERSION)"
# Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)"
@@ -264,7 +423,8 @@ raspi_release:
$(MKDIR) "$(RELEASE_FOLDER)"
# Copia ficheros
cp -R data "$(RELEASE_FOLDER)"
cp -R config "$(RELEASE_FOLDER)"
cp resources.pack "$(RELEASE_FOLDER)"
cp LICENSE "$(RELEASE_FOLDER)"
cp README.md "$(RELEASE_FOLDER)"
@@ -275,11 +435,13 @@ raspi_release:
# Empaqueta ficheros
$(RMFILE) "$(RASPI_RELEASE)"
tar -czvf "$(RASPI_RELEASE)" -C "$(RELEASE_FOLDER)" .
@echo "Release creado: $(RASPI_RELEASE)"
# Elimina la carpeta temporal
$(RMDIR) "$(RELEASE_FOLDER)"
anbernic:
anbernic: resources.pack
@echo "Compilando para Anbernic: $(TARGET_NAME)"
# Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)"_anbernic
@@ -287,13 +449,42 @@ anbernic:
$(MKDIR) "$(RELEASE_FOLDER)"_anbernic
# Copia ficheros
cp -R data "$(RELEASE_FOLDER)"_anbernic
cp -R config "$(RELEASE_FOLDER)"_anbernic
cp resources.pack "$(RELEASE_FOLDER)"_anbernic
# Compila
$(CXX) $(APP_SOURCES) $(INCLUDES) -DANBERNIC -DNO_SHADERS -DARCADE -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(RELEASE_FOLDER)_anbernic/$(TARGET_NAME)
# Opción para deshabilitar audio (equivalente a la opción DISABLE_AUDIO de CMake)
no_audio:
@echo "Compilando sin audio: $(TARGET_NAME)_no_audio"
$(CXX) $(filter-out source/external/jail_audio.cpp,$(APP_SOURCES)) $(INCLUDES) -DNO_AUDIO $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)_no_audio"
.PHONY: windows windows_rec windows_debug windows_release macos macos_debug macos_release linux linux_debug linux_release raspi raspi_debug raspi_release anbernic no_audio
# Regla para mostrar la versión actual
show_version:
@echo "Version actual: $(VERSION)"
# Regla de ayuda
help:
@echo "Makefile para Coffee Crisis Arcade Edition"
@echo "Comandos disponibles:"
@echo " windows - Compilar para Windows"
@echo " windows_debug - Compilar debug para Windows"
@echo " windows_release - Crear release completo para Windows"
@echo " linux - Compilar para Linux"
@echo " linux_debug - Compilar debug para Linux"
@echo " linux_release - Crear release basico para Linux"
@echo " linux_release_desktop - Crear release con integracion desktop para Linux"
@echo " macos - Compilar para macOS"
@echo " macos_debug - Compilar debug para macOS"
@echo " macos_release - Crear release completo para macOS"
@echo " raspi - Compilar para Raspberry Pi"
@echo " raspi_release - Crear release completo para Raspberry Pi"
@echo " anbernic - Compilar para Anbernic"
@echo " no_audio - Compilar sin sistema de audio"
@echo " pack_tool - Compilar herramienta de empaquetado"
@echo " resources.pack - Generar pack de recursos desde data/"
@echo " show_version - Mostrar version actual ($(VERSION))"
@echo " help - Mostrar esta ayuda"
.PHONY: windows windows_rec windows_debug windows_release macos macos_debug macos_release linux linux_debug linux_release linux_release_desktop raspi raspi_debug raspi_release anbernic no_audio show_version help pack_tool

61
TODO.md Normal file
View File

@@ -0,0 +1,61 @@
# TODO
## Tareas pendientes
- [ ] Revisar todas las variables static de los métodos para ver si se resetean correctamente
## Mejoras arquitecturales (refactoring)
### Eliminar variables static locales y usar patrones profesionales:
**Opción 1: Máquina de Estados**
```cpp
class GameCompletedState {
bool start_celebrations_done = false;
bool end_celebrations_done = false;
float timer = 0.0f;
public:
void reset() {
start_celebrations_done = false;
end_celebrations_done = false;
timer = 0.0f;
}
void update(float deltaTime) {
timer += deltaTime;
// lógica aquí
}
};
```
**Opción 2: Sistema de Eventos/Callbacks**
```cpp
// Al entrar en COMPLETED state
eventSystem.scheduleEvent(6.0f, []{ startCelebrations(); });
eventSystem.scheduleEvent(14.0f, []{ endCelebrations(); });
```
**Opción 3: Flags como miembros privados**
```cpp
class Game {
private:
struct GameOverState {
bool game_over_triggered = false;
bool start_celebrations_triggered = false;
bool end_celebrations_triggered = false;
void reset() {
game_over_triggered = false;
start_celebrations_triggered = false;
end_celebrations_triggered = false;
}
} game_over_state_;
};
```
**Ventajas:**
- Más fáciles de testear
- Más fáciles de debugear
- Más fáciles de entender y mantener
- No tienen "estado oculto"

View File

@@ -1,41 +1,49 @@
# Coffee Crisis - Asset Configuration
# Coffee Crisis Arcade Edition - Asset Configuration
# Formato: TIPO|RUTA [|OPCIONES]
# Opciones: optional, absolute (separadas por comas)
# Variables: ${PREFIX}, ${SYSTEM_FOLDER}
# Archivos de configuración del sistema (absolutos y opcionales)
DATA|${SYSTEM_FOLDER}/config.txt|optional,absolute
DATA|${SYSTEM_FOLDER}/config_v2.txt|optional,absolute
DATA|${SYSTEM_FOLDER}/controllers.json|optional,absolute
DATA|${SYSTEM_FOLDER}/score.bin|optional,absolute
# Archivos de configuración del juego
DATA|${PREFIX}/data/config/param_320x240.txt
DATA|${PREFIX}/data/config/param_320x256.txt
DEMODATA|${PREFIX}/data/config/demo1.bin
DEMODATA|${PREFIX}/data/config/demo2.bin
DATA|${PREFIX}/data/config/gamecontrollerdb.txt
DATA|${PREFIX}/data/config/formations.txt
DATA|${PREFIX}/data/config/pools.txt
DATA|${PREFIX}/config/formations.txt
DATA|${PREFIX}/config/gamecontrollerdb.txt
DATA|${PREFIX}/config/param_320x240.txt
DATA|${PREFIX}/config/param_320x256.txt
DATA|${PREFIX}/config/param_red.txt
DATA|${PREFIX}/config/pools.txt
DATA|${PREFIX}/config/stages.txt
# Archivos con los datos de la demo
DEMODATA|${PREFIX}/data/demo/demo1.bin
DEMODATA|${PREFIX}/data/demo/demo2.bin
DEMODATA|${PREFIX}/data/demo/demo3.bin
# Música
MUSIC|${PREFIX}/data/music/congratulations.ogg
MUSIC|${PREFIX}/data/music/credits.ogg
MUSIC|${PREFIX}/data/music/intro.ogg
MUSIC|${PREFIX}/data/music/playing.ogg
MUSIC|${PREFIX}/data/music/title.ogg
MUSIC|${PREFIX}/data/music/credits.ogg
# Sonidos
SOUND|${PREFIX}/data/sound/balloon_pop0.wav
SOUND|${PREFIX}/data/sound/balloon_pop1.wav
SOUND|${PREFIX}/data/sound/balloon_pop2.wav
SOUND|${PREFIX}/data/sound/balloon_pop3.wav
SOUND|${PREFIX}/data/sound/balloon_bounce0.wav
SOUND|${PREFIX}/data/sound/balloon_bounce1.wav
SOUND|${PREFIX}/data/sound/balloon_bounce2.wav
SOUND|${PREFIX}/data/sound/balloon_bounce3.wav
SOUND|${PREFIX}/data/sound/bullet.wav
SOUND|${PREFIX}/data/sound/balloon_pop0.wav
SOUND|${PREFIX}/data/sound/balloon_pop1.wav
SOUND|${PREFIX}/data/sound/balloon_pop2.wav
SOUND|${PREFIX}/data/sound/balloon_pop3.wav
SOUND|${PREFIX}/data/sound/bullet1p.wav
SOUND|${PREFIX}/data/sound/bullet2p.wav
SOUND|${PREFIX}/data/sound/clock.wav
SOUND|${PREFIX}/data/sound/coffee_out.wav
SOUND|${PREFIX}/data/sound/continue_clock.wav
SOUND|${PREFIX}/data/sound/credit.wav
SOUND|${PREFIX}/data/sound/debian_drop.wav
SOUND|${PREFIX}/data/sound/debian_pickup.wav
SOUND|${PREFIX}/data/sound/hi_score_achieved.wav
@@ -43,10 +51,12 @@ SOUND|${PREFIX}/data/sound/item_drop.wav
SOUND|${PREFIX}/data/sound/item_pickup.wav
SOUND|${PREFIX}/data/sound/jump.wav
SOUND|${PREFIX}/data/sound/logo.wav
SOUND|${PREFIX}/data/sound/name_input_accept.wav
SOUND|${PREFIX}/data/sound/notify.wav
SOUND|${PREFIX}/data/sound/player_collision.wav
SOUND|${PREFIX}/data/sound/power_ball_explosion.wav
SOUND|${PREFIX}/data/sound/service_menu_adjust.wav
SOUND|${PREFIX}/data/sound/service_menu_back.wav
SOUND|${PREFIX}/data/sound/service_menu_move.wav
SOUND|${PREFIX}/data/sound/service_menu_select.wav
SOUND|${PREFIX}/data/sound/stage_change.wav
@@ -55,57 +65,60 @@ SOUND|${PREFIX}/data/sound/tabe.wav
SOUND|${PREFIX}/data/sound/title.wav
SOUND|${PREFIX}/data/sound/voice_aw_aw_aw.wav
SOUND|${PREFIX}/data/sound/voice_coffee.wav
SOUND|${PREFIX}/data/sound/voice_credit_thankyou.wav
SOUND|${PREFIX}/data/sound/voice_game_over.wav
SOUND|${PREFIX}/data/sound/voice_get_ready.wav
SOUND|${PREFIX}/data/sound/voice_no.wav
SOUND|${PREFIX}/data/sound/voice_power_up.wav
SOUND|${PREFIX}/data/sound/voice_recover.wav
SOUND|${PREFIX}/data/sound/voice_thankyou.wav
SOUND|${PREFIX}/data/sound/walk.wav
# Shaders
DATA|${PREFIX}/data/shaders/crtpi_256.glsl
DATA|${PREFIX}/data/shaders/crtpi_240.glsl
DATA|${PREFIX}/data/shaders/crtpi_vertex.glsl
DATA|${PREFIX}/data/shaders/crtpi_fragment.glsl
# Texturas - Balloons
BITMAP|${PREFIX}/data/gfx/balloon/balloon0.png
ANIMATION|${PREFIX}/data/gfx/balloon/balloon0.ani
BITMAP|${PREFIX}/data/gfx/balloon/balloon1.png
ANIMATION|${PREFIX}/data/gfx/balloon/balloon1.ani
BITMAP|${PREFIX}/data/gfx/balloon/balloon2.png
ANIMATION|${PREFIX}/data/gfx/balloon/balloon2.ani
BITMAP|${PREFIX}/data/gfx/balloon/balloon3.png
ANIMATION|${PREFIX}/data/gfx/balloon/balloon3.ani
BITMAP|${PREFIX}/data/gfx/balloon/balloon0.png
BITMAP|${PREFIX}/data/gfx/balloon/balloon1.png
BITMAP|${PREFIX}/data/gfx/balloon/balloon2.png
BITMAP|${PREFIX}/data/gfx/balloon/balloon3.png
# Texturas - Explosiones
BITMAP|${PREFIX}/data/gfx/balloon/explosion0.png
ANIMATION|${PREFIX}/data/gfx/balloon/explosion0.ani
BITMAP|${PREFIX}/data/gfx/balloon/explosion1.png
ANIMATION|${PREFIX}/data/gfx/balloon/explosion1.ani
BITMAP|${PREFIX}/data/gfx/balloon/explosion2.png
ANIMATION|${PREFIX}/data/gfx/balloon/explosion2.ani
BITMAP|${PREFIX}/data/gfx/balloon/explosion3.png
ANIMATION|${PREFIX}/data/gfx/balloon/explosion3.ani
BITMAP|${PREFIX}/data/gfx/balloon/explosion0.png
BITMAP|${PREFIX}/data/gfx/balloon/explosion1.png
BITMAP|${PREFIX}/data/gfx/balloon/explosion2.png
BITMAP|${PREFIX}/data/gfx/balloon/explosion3.png
# Texturas - Power Ball
BITMAP|${PREFIX}/data/gfx/balloon/powerball.png
ANIMATION|${PREFIX}/data/gfx/balloon/powerball.ani
BITMAP|${PREFIX}/data/gfx/balloon/powerball.png
# Texturas - Bala
BITMAP|${PREFIX}/data/gfx/bullet/bullet.png
ANIMATION|${PREFIX}/data/gfx/bullet/bullet.ani
BITMAP|${PREFIX}/data/gfx/bullet/bullet.png
# Texturas - Tabe
BITMAP|${PREFIX}/data/gfx/tabe/tabe.png
ANIMATION|${PREFIX}/data/gfx/tabe/tabe.ani
BITMAP|${PREFIX}/data/gfx/tabe/tabe.png
# Texturas - Juego
BITMAP|${PREFIX}/data/gfx/game/game_buildings.png
BITMAP|${PREFIX}/data/gfx/game/game_clouds1.png
BITMAP|${PREFIX}/data/gfx/game/game_clouds2.png
BITMAP|${PREFIX}/data/gfx/game/game_grass.png
BITMAP|${PREFIX}/data/gfx/game/game_moon.png
BITMAP|${PREFIX}/data/gfx/game/game_power_meter.png
BITMAP|${PREFIX}/data/gfx/game/game_sky_colors.png
BITMAP|${PREFIX}/data/gfx/game/game_sun.png
BITMAP|${PREFIX}/data/gfx/game/game_moon.png
# Texturas - Intro
BITMAP|${PREFIX}/data/gfx/intro/intro1.png
@@ -116,75 +129,77 @@ BITMAP|${PREFIX}/data/gfx/intro/intro5.png
BITMAP|${PREFIX}/data/gfx/intro/intro6.png
# Texturas - Logo
BITMAP|${PREFIX}/data/gfx/logo/logo_jailgames.png
BITMAP|${PREFIX}/data/gfx/logo/logo_jailgames_mini.png
BITMAP|${PREFIX}/data/gfx/logo/logo_jailgames.png
BITMAP|${PREFIX}/data/gfx/logo/logo_since_1998.png
# Texturas - Items
BITMAP|${PREFIX}/data/gfx/item/item_points1_disk.png
ANIMATION|${PREFIX}/data/gfx/item/item_clock.ani
ANIMATION|${PREFIX}/data/gfx/item/item_coffee_machine.ani
ANIMATION|${PREFIX}/data/gfx/item/item_coffee.ani
ANIMATION|${PREFIX}/data/gfx/item/item_debian.ani
ANIMATION|${PREFIX}/data/gfx/item/item_points1_disk.ani
BITMAP|${PREFIX}/data/gfx/item/item_points2_gavina.png
ANIMATION|${PREFIX}/data/gfx/item/item_points2_gavina.ani
BITMAP|${PREFIX}/data/gfx/item/item_points3_pacmar.png
ANIMATION|${PREFIX}/data/gfx/item/item_points3_pacmar.ani
BITMAP|${PREFIX}/data/gfx/item/item_clock.png
ANIMATION|${PREFIX}/data/gfx/item/item_clock.ani
BITMAP|${PREFIX}/data/gfx/item/item_coffee.png
ANIMATION|${PREFIX}/data/gfx/item/item_coffee.ani
BITMAP|${PREFIX}/data/gfx/item/item_debian.png
ANIMATION|${PREFIX}/data/gfx/item/item_debian.ani
BITMAP|${PREFIX}/data/gfx/item/item_coffee_machine.png
ANIMATION|${PREFIX}/data/gfx/item/item_coffee_machine.ani
BITMAP|${PREFIX}/data/gfx/item/item_coffee.png
BITMAP|${PREFIX}/data/gfx/item/item_debian.png
BITMAP|${PREFIX}/data/gfx/item/item_points1_disk.png
BITMAP|${PREFIX}/data/gfx/item/item_points2_gavina.png
BITMAP|${PREFIX}/data/gfx/item/item_points3_pacmar.png
# Texturas - Titulo
ANIMATION|${PREFIX}/data/gfx/title/title_dust.ani
BITMAP|${PREFIX}/data/gfx/title/title_arcade_edition.png
BITMAP|${PREFIX}/data/gfx/title/title_bg_tile.png
BITMAP|${PREFIX}/data/gfx/title/title_coffee.png
BITMAP|${PREFIX}/data/gfx/title/title_crisis.png
BITMAP|${PREFIX}/data/gfx/title/title_arcade_edition.png
BITMAP|${PREFIX}/data/gfx/title/title_dust.png
ANIMATION|${PREFIX}/data/gfx/title/title_dust.ani
# Texturas - Jugador 1
BITMAP|${PREFIX}/data/gfx/player/player1_power.png
BITMAP|${PREFIX}/data/gfx/player/player1.gif
PALETTE|${PREFIX}/data/gfx/player/player1_coffee1.pal
PALETTE|${PREFIX}/data/gfx/player/player1_coffee2.pal
PALETTE|${PREFIX}/data/gfx/player/player1_invencible.pal
BITMAP|${PREFIX}/data/gfx/player/player1_power.png
# Texturas - Jugador 2
BITMAP|${PREFIX}/data/gfx/player/player2_power.png
BITMAP|${PREFIX}/data/gfx/player/player2.gif
PALETTE|${PREFIX}/data/gfx/player/player2_coffee1.pal
PALETTE|${PREFIX}/data/gfx/player/player2_coffee2.pal
PALETTE|${PREFIX}/data/gfx/player/player2_invencible.pal
BITMAP|${PREFIX}/data/gfx/player/player2_power.png
# Animaciones del jugador
ANIMATION|${PREFIX}/data/gfx/player/player.ani
ANIMATION|${PREFIX}/data/gfx/player/player_power.ani
ANIMATION|${PREFIX}/data/gfx/player/player.ani
# Texturas - Golpe del jugador
BITMAP|${PREFIX}/data/gfx/player/hit.png
# Fuentes de texto
BITMAP|${PREFIX}/data/font/8bithud.png
FONT|${PREFIX}/data/font/8bithud.txt
BITMAP|${PREFIX}/data/font/aseprite.png
FONT|${PREFIX}/data/font/aseprite.txt
BITMAP|${PREFIX}/data/font/smb2.png
BITMAP|${PREFIX}/data/font/smb2_grad.png
FONT|${PREFIX}/data/font/smb2.txt
BITMAP|${PREFIX}/data/font/04b_25.png
FONT|${PREFIX}/data/font/04b_25.txt
BITMAP|${PREFIX}/data/font/04b_25_2x.png
FONT|${PREFIX}/data/font/04b_25_2x.txt
BITMAP|${PREFIX}/data/font/04b_25_metal.png
BITMAP|${PREFIX}/data/font/04b_25_grey.png
BITMAP|${PREFIX}/data/font/04b_25_flat.png
BITMAP|${PREFIX}/data/font/04b_25_reversed.png
BITMAP|${PREFIX}/data/font/04b_25_2x_white.png
BITMAP|${PREFIX}/data/font/04b_25_flat_2x.png
BITMAP|${PREFIX}/data/font/04b_25_flat.png
BITMAP|${PREFIX}/data/font/04b_25_grey.png
BITMAP|${PREFIX}/data/font/04b_25_metal.png
BITMAP|${PREFIX}/data/font/04b_25_reversed_2x.png
BITMAP|${PREFIX}/data/font/04b_25_reversed.png
BITMAP|${PREFIX}/data/font/04b_25_white.png
BITMAP|${PREFIX}/data/font/04b_25.png
BITMAP|${PREFIX}/data/font/8bithud.png
BITMAP|${PREFIX}/data/font/aseprite.png
BITMAP|${PREFIX}/data/font/smb2_grad.png
BITMAP|${PREFIX}/data/font/smb2.png
FONT|${PREFIX}/data/font/04b_25_2x.txt
FONT|${PREFIX}/data/font/04b_25.txt
FONT|${PREFIX}/data/font/8bithud.txt
FONT|${PREFIX}/data/font/aseprite.txt
FONT|${PREFIX}/data/font/smb2.txt
# Idiomas
LANG|${PREFIX}/data/lang/es_ES.json
LANG|${PREFIX}/data/lang/en_UK.json
LANG|${PREFIX}/data/lang/ba_BA.json
LANG|${PREFIX}/data/lang/en_UK.json
LANG|${PREFIX}/data/lang/es_ES.json

277
config/formations.txt Normal file
View File

@@ -0,0 +1,277 @@
# Coffee Crisis Arcade Edition - Archivo de configuración de formaciones de globos
# Formato por línea: x, desp, y, vel_x, tipo, tamaño, retraso_tiempo_creacion
# Variables disponibles:
# X0_0, X0_50, X0_100, X1_0, X1_100, X2_0, X2_100, X3_0, X3_100
# X3_25, X3_75, DEFAULT_POS_Y
# SMALL, MEDIUM, LARGE, EXTRALARGE
# RIGHT, LEFT
formation: 0
# Dos enemigos BALLOON3 uno a cada extremo
X3_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.0000
X3_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.0000
formation: 1
# Dos enemigos BALLOON3 uno a cada cuarto. Ambos van hacia el centro
X3_25, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.0000
X3_75, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.0000
formation: 2
# Cuatro enemigos BALLOON1 uno detrás del otro. A la izquierda y hacia el centro
X1_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.5000
X1_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.3333
X1_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.1667
X1_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.0000
formation: 3
# Cuatro enemigos BALLOON1 uno detrás del otro. A la derecha y hacia el centro
X1_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.5000
X1_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.3333
X1_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.1667
X1_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.0000
formation: 4
# Tres enemigos BALLOON2. 0, 25, 50. Hacia la derecha
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.3333
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.1667
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.0000
formation: 5
# Tres enemigos BALLOON2. 50, 75, 100. Hacia la izquierda
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.3333
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.1667
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.0000
formation: 6
# Tres enemigos BALLOON2. 0, 0, 0. Hacia la derecha
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.3333
X2_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.1667
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.0000
formation: 7
# Tres enemigos BALLOON2. 100, 100, 100. Hacia la izquierda
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.3333
X2_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.1667
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.0000
formation: 8
# Seis enemigos BALLOON0. 0, 0, 0, 0, 0, 0. Hacia la derecha
X0_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.8333
X0_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.6667
X0_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.5000
X0_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.3333
X0_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.1667
X0_0, 5, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.0000
formation: 9
# Seis enemigos BALLOON0. 100, 100, 100, 100, 100, 100. Hacia la izquierda
X0_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.8333
X0_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.6667
X0_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.5000
X0_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.3333
X0_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.1667
X0_100, -5, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.0000
formation: 10
# Tres enemigos BALLOON3 seguidos desde la izquierda. Hacia la derecha
X3_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.5000
X3_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.2500
X3_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.0000
formation: 11
# Tres enemigos BALLOON3 seguidos desde la derecha. Hacia la izquierda
X3_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.5000
X3_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.2500
X3_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.0000
formation: 12
# Seis enemigos BALLOON1 uno detrás del otro. A la izquierda y hacia el centro
X1_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.8333
X1_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.6667
X1_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.5000
X1_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.3333
X1_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.1667
X1_0, 5, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.0000
formation: 13
# Seis enemigos BALLOON1 uno detrás del otro. A la derecha y hacia el centro
X1_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.8333
X1_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.6667
X1_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.5000
X1_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.3333
X1_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.1667
X1_100, -5, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.0000
formation: 14
# Cinco enemigos BALLOON2. Hacia la derecha. Separados
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.6667
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.5000
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.3333
X2_0, 6, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.1667
X2_0, 8, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.0000
formation: 15
# Cinco enemigos BALLOON2. Hacia la izquierda. Separados
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.6667
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.5000
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.3333
X2_100, -6, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.1667
X2_100, -8, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.0000
formation: 16
# Cinco enemigos BALLOON2. Hacia la derecha. Juntos
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.6667
X2_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.5000
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.3333
X2_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.1667
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.0000
formation: 17
# Cinco enemigos BALLOON2. Hacia la izquierda. Juntos
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.6667
X2_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.5000
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.3333
X2_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.1667
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.0000
formation: 18
# Doce enemigos BALLOON0. Hacia la derecha. Juntos
X0_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.8333
X0_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.6667
X0_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.5000
X0_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.3333
X0_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.1667
X0_0, 5, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.0000
X0_0, 6, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.8333
X0_0, 7, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.6667
X0_0, 8, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.5000
X0_0, 9, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.3333
X0_0, 10, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.1667
X0_0, 11, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.0000
formation: 19
# Doce enemigos BALLOON0. Hacia la izquierda. Juntos
X0_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.8333
X0_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.6667
X0_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.5000
X0_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.3333
X0_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.1667
X0_100, -5, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.0000
X0_100, -6, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.8333
X0_100, -7, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.6667
X0_100, -8, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.5000
X0_100, -9, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.3333
X0_100, -10, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.1667
X0_100, -11, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.0000
formation: 20
# Cuatro enemigos BALLOON3 seguidos desde la izquierda/derecha. Simétricos
X3_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.0000
X3_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.0000
X3_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.0000
X3_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.0000
formation: 21
# Diez enemigos BALLOON1 uno detrás del otro. Izquierda/derecha. Simétricos
X1_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.2000
X1_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.1500
X1_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.1000
X1_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.0500
X1_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.0000
X1_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.2000
X1_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.1500
X1_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.1000
X1_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.0500
X1_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.0000
formation: 22
# Diez enemigos BALLOON2. Hacia la derecha/izquierda. Separados. Simétricos
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.6667
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.5000
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.3333
X2_0, 6, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.1667
X2_0, 8, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.0000
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.6667
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.5000
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.3333
X2_100, -6, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.1667
X2_100, -8, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.0000
formation: 23
# Diez enemigos BALLOON2. Hacia la derecha. Juntos. Simétricos
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.6667
X2_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.5000
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.3333
X2_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.1667
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.0000
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.6667
X2_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.5000
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.3333
X2_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.1667
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.0000
formation: 24
# Treinta enemigos BALLOON0. Del centro hacia los extremos. Juntos. Simétricos
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.0000
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.0833
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.1667
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.2500
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.3333
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.4167
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.5000
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.5833
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.6667
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.7500
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.8333
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.9167
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.0000
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.0833
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.1667
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.0000
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.0833
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.1667
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.2500
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.3333
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.4167
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.5000
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.5833
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.6667
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.7500
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.8333
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.9167
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.0000
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.0833
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.1667
formation: 25
# Treinta enemigos BALLOON0. Del centro hacia adentro. Juntos. Simétricos
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.1667
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.0833
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.0000
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.9167
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.8333
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.7500
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.6667
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.5833
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.5000
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.4167
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.3333
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.2500
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.1667
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.0833
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.0000
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.1667
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.0833
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.0000
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.9167
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.8333
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.7500
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.6667
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.5833
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.5000
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.4167
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.3333
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.2500
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.1667
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.0833
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.0000

150
config/param_320x240.txt Normal file
View File

@@ -0,0 +1,150 @@
# Coffee Crisis Arcade Edition - Fichero de parametros
# Formato: PARAMETRO VALOR
# --- GAME ---
game.item_text_outline_color E0E0E0F0 # Color del outline del texto de los items (RGBA hex)
game.width 320 # Ancho de la resolución nativa del juego (en píxeles)
game.height 240 # Alto de la resolución nativa del juego (en píxeles)
game.play_area.rect.x 0 # Posición X de la zona jugable
game.play_area.rect.y 0 # Posición Y de la zona jugable
game.play_area.rect.w 320 # Ancho de la zona jugable
game.play_area.rect.h 200 # Alto de la zona jugable
game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
# --- FADE ---
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido
fade.num_squares_width 64 # Número de cuadrados en el eje X para el fundido
fade.num_squares_height 48 # Número de cuadrados en el eje Y para el fundido
fade.random_squares_duration_ms 1200 # Duración del fade en milisegundos
fade.post_duration_ms 500 # Duración tras el fundido en milisegundos
fade.venetian_size 12 # Tamaño de las bandas para el efecto veneciano (en píxeles)
# --- SCOREBOARD ---
scoreboard.rect.x 0 # Posición X del marcador
scoreboard.rect.y 216 # Posición Y del marcador
scoreboard.rect.w 320 # Ancho del marcador
scoreboard.rect.h 40 # Alto del marcador
scoreboard.separator_autocolor true # ¿El separador usa color automático?
scoreboard.separator_color 0D1A2B # Color del separador (hexadecimal)
scoreboard.easy_color 4B692F # Color para la dificultad fácil
scoreboard.normal_color 2E3F47 # Color para la dificultad normal
scoreboard.hard_color 76428A # Color para la dificultad difícil
scoreboard.text_autocolor true # ¿El texto usa color automático?
scoreboard.text_color1 FFFFFF # Color principal del texto del marcador
scoreboard.text_color2 FFFFFF # Color secundario del texto del marcador
scoreboard.skip_countdown_value 8 # Valor para saltar la cuenta atrás (segundos)
# --- TITLE ---
title.press_start_position 180 # Posición Y del texto "Press Start"
title.title_duration 14 # Duración de la pantalla de título (segundos)
title.arcade_edition_position 123 # Posición Y del subtítulo "Arcade Edition"
title.title_c_c_position 80 # Posición Y del título principal
title.bg_color 41526F # Color de fondo en la sección titulo
# --- BACKGROUND ---
background.attenuate_color FFFFFF00 # Color de atenuación del fondo (RGBA hexadecimal)
# --- BALLOONS --- (deltaTime en segundos: vel en pixels/s, grav en pixels/s²)
balloon.settings[0].vel 165.0f # Velocidad inicial del globo 1 (pixels/s)
balloon.settings[0].grav 320.0f # Gravedad aplicada al globo 1 (pixels/s²)
balloon.settings[1].vel 222.0f # Velocidad inicial del globo 2 (pixels/s)
balloon.settings[1].grav 360.0f # Gravedad aplicada al globo 2 (pixels/s²)
balloon.settings[2].vel 282.0f # Velocidad inicial del globo 3 (pixels/s)
balloon.settings[2].grav 360.0f # Gravedad aplicada al globo 3 (pixels/s²)
balloon.settings[3].vel 327.0f # Velocidad inicial del globo 4 (pixels/s)
balloon.settings[3].grav 360.0f # Gravedad aplicada al globo 4 (pixels/s²)
balloon.color[0] blue # Color de creación del globo normal
balloon.color[1] orange # Color del globo normal
balloon.color[2] red # Color de creación del globo que rebota
balloon.color[3] green # Color del globo que rebota
balloon.bouncing_sound false # Indica si los globos hacer sonido al rebotar
# --- NOTIFICATION ---
notification.pos_v TOP # Posición vertical de la notificación (TOP/BOTTOM)
notification.pos_h LEFT # Posición horizontal de la notificación (LEFT/RIGHT)
notification.sound false # ¿La notificación reproduce sonido?
notification.color 303030 # Color de fondo de la notificación (hexadecimal)
# --- SERVICE MENU ---
service_menu.title_color 99FF62 # Color del título del menú de servicio
service_menu.text_color FFFFFF # Color del texto del menú de servicio
service_menu.selected_color FFDC44 # Color de la opción seleccionada en el menú de servicio
service_menu.bg_color 000F00F5 # Color de fondo del menú de servicio (RGBA hexadecimal)
service_menu.drop_shadow false # ¿El menú de servicio tiene sombra?
service_menu.window_message.bg_color 141E32F0 # Color de fondo de ventanas de mensaje (RGBA hexadecimal)
service_menu.window_message.border_color 6496C8FF # Color del borde de ventanas de mensaje (RGBA hexadecimal)
service_menu.window_message.title_color 6496C8FF # Color del título en ventanas de mensaje (RGBA hexadecimal)
service_menu.window_message.text_color DCDCDCFF # Color del texto en ventanas de mensaje (RGBA hexadecimal)
service_menu.window_message.padding 15.0f # Espaciado interno de ventanas de mensaje (píxeles)
service_menu.window_message.line_spacing 5.0f # Espaciado entre líneas de texto (píxeles)
service_menu.window_message.title_separator_spacing 20.0f # Espaciado entre título y contenido (píxeles)
service_menu.window_message.min_width 200.0f # Ancho mínimo de ventanas de mensaje (píxeles)
service_menu.window_message.min_height 32.0f # Alto mínimo de ventanas de mensaje (píxeles)
service_menu.window_message.max_width_ratio 0.8f # Ratio máximo de ancho respecto a pantalla (0.0-1.0)
service_menu.window_message.max_height_ratio 0.8f # Ratio máximo de alto respecto a pantalla (0.0-1.0)
service_menu.window_message.text_safety_margin 15.0f # Margen de seguridad para el texto (píxeles)
service_menu.window_message.animation_duration 0.3f # Duración de animaciones de ventanas (segundos)
# --- INTRO ---
intro.bg_color 4664BD # Color de fondo de la intro
intro.card_color CBDBFC # Color de las tarjetas en la intro
intro.shadow_color 00000080 # Color de la sombra de las tarjetas en la intro
intro.text_distance_from_bottom 48 # Posicion del texto
# --- DEBUG ---
debug.color 00FFFF # Color para elementos de depuración
# --- RESOURCE ---
resource.color FFFFFF # Color de recurso 1
resource.color FFFFFF # Color de recurso 2
# --- TABE ---
tabe.min_spawn_time 2.0f # Tiempo mínimo en minutos para que aparezca el Tabe
tabe.max_spawn_time 3.0f # Tiempo máximo en minutos para que aparezca el Tabe
# --- PLAYER ---
# Jugador 1 - Camiseta por defecto
player.default_shirt[0].darkest 028ECFFF # Tono más oscuro - bordes y contornos (Jugador 1, por defecto)
player.default_shirt[0].dark 0297DBFF # Tono oscuro - sombras (Jugador 1, por defecto)
player.default_shirt[0].base 029FE8FF # Tono principal - color base (Jugador 1, por defecto)
player.default_shirt[0].light 03A9F4FF # Tono claro - zonas iluminadas (Jugador 1, por defecto)
# Jugador 2 - Camiseta por defecto
player.default_shirt[1].darkest 8E8E8EFF # Tono más oscuro - bordes y contornos (Jugador 2, por defecto)
player.default_shirt[1].dark AEADADFF # Tono oscuro - sombras (Jugador 2, por defecto)
player.default_shirt[1].base E4E4E4FF # Tono principal - color base (Jugador 2, por defecto)
player.default_shirt[1].light F7F1F1FF # Tono claro - zonas iluminadas (Jugador 2, por defecto)
# Jugador 1 - Camiseta con 1 café
player.one_coffee_shirt[0].darkest 3D9C70FF # Tono más oscuro - bordes y contornos (Jugador 1, 1 café)
player.one_coffee_shirt[0].dark 4FA370FF # Tono oscuro - sombras (Jugador 1, 1 café)
player.one_coffee_shirt[0].base 5DDE70FF # Tono principal - color base (Jugador 1, 1 café)
player.one_coffee_shirt[0].light 7DF25CFF # Tono claro - zonas iluminadas (Jugador 1, 1 café)
# Jugador 1 - Camiseta con 2 cafés
player.two_coffee_shirt[0].darkest D6A41AFF # Tono más oscuro - bordes y contornos (Jugador 1, 2 cafés)
player.two_coffee_shirt[0].dark E3AE1BFF # Tono oscuro - sombras (Jugador 1, 2 cafés)
player.two_coffee_shirt[0].base EFB71DFF # Tono principal - color base (Jugador 1, 2 cafés)
player.two_coffee_shirt[0].light FCC11EFF # Tono claro - zonas iluminadas (Jugador 1, 2 cafés)
# Jugador 2 - Camiseta con 1 café
player.one_coffee_shirt[1].darkest 2E8B57FF # Tono más oscuro - bordes y contornos (Jugador 2, 1 café)
player.one_coffee_shirt[1].dark 3CB371FF # Tono oscuro - sombras (Jugador 2, 1 café)
player.one_coffee_shirt[1].base 48D181FF # Tono principal - color base (Jugador 2, 1 café)
player.one_coffee_shirt[1].light 55EF8DFF # Tono claro - zonas iluminadas (Jugador 2, 1 café)
# Jugador 2 - Camiseta con 2 cafés
player.two_coffee_shirt[1].darkest E08500FF # Tono más oscuro - bordes y contornos (Jugador 2, 2 cafés)
player.two_coffee_shirt[1].dark FA7D00FF # Tono oscuro - sombras (Jugador 2, 2 cafés)
player.two_coffee_shirt[1].base FAA200FF # Tono principal - color base (Jugador 2, 2 cafés)
player.two_coffee_shirt[1].light FA8500FF # Tono claro - zonas iluminadas (Jugador 2, 2 cafés)
# Colores de contorno de los jugadores
player.outline_color[0] 66323FFF # Color del contorno del sprite del Jugador 1
player.outline_color[1] 422028FF # Color del contorno del sprite del Jugador 2

150
config/param_320x256.txt Normal file
View File

@@ -0,0 +1,150 @@
# Coffee Crisis Arcade Edition - Fichero de parametros
# Formato: PARAMETRO VALOR
# --- GAME ---
game.item_size 20 # Tamaño de los items del juego (en píxeles)
game.item_text_outline_color E0E0E0F0 # Color del outline del texto de los items (RGBA hex)
game.width 320 # Ancho de la resolución nativa del juego (en píxeles)
game.height 256 # Alto de la resolución nativa del juego (en píxeles)
game.play_area.rect.x 0 # Posición X de la zona jugable
game.play_area.rect.y 0 # Posición Y de la zona jugable
game.play_area.rect.w 320 # Ancho de la zona jugable
game.play_area.rect.h 216 # Alto de la zona jugable
game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
# --- FADE ---
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido
fade.num_squares_width 64 # Número de cuadrados en el eje X para el fundido
fade.num_squares_height 48 # Número de cuadrados en el eje Y para el fundido
fade.random_squares_duration_ms 1200 # Duración del fade en milisegundos
fade.post_duration_ms 500 # Duración tras el fundido en milisegundos
fade.venetian_size 12 # Tamaño de las bandas para el efecto veneciano (en píxeles)
# --- SCOREBOARD ---
scoreboard.rect.x 0 # Posición X del marcador
scoreboard.rect.y 216 # Posición Y del marcador
scoreboard.rect.w 320 # Ancho del marcador
scoreboard.rect.h 40 # Alto del marcador
scoreboard.separator_autocolor true # ¿El separador usa color automático?
scoreboard.separator_color 0D1A2B # Color del separador (hexadecimal)
scoreboard.easy_color 4B692F # Color para la dificultad fácil
scoreboard.normal_color 2E3F47 # Color para la dificultad normal
scoreboard.hard_color 76428A # Color para la dificultad difícil
scoreboard.text_autocolor true # ¿El texto usa color automático?
scoreboard.text_color1 FFFFFF # Color principal del texto del marcador
scoreboard.text_color2 FFFFFF # Color secundario del texto del marcador
scoreboard.skip_countdown_value 8 # Valor para saltar la cuenta atrás (segundos)
# --- TITLE ---
title.press_start_position 180 # Posición Y del texto "Press Start"
title.title_duration 14 # Duración de la pantalla de título (segundos)
title.arcade_edition_position 123 # Posición Y del subtítulo "Arcade Edition"
title.title_c_c_position 80 # Posición Y del título principal
title.bg_color 41526F # Color de fondo en la sección titulo
# --- BACKGROUND ---
background.attenuate_color FFFFFF00 # Color de atenuación del fondo (RGBA hexadecimal)
# --- BALLOONS --- (deltaTime en segundos: vel en pixels/s, grav en pixels/s²)
balloon.settings[0].vel 165.0f # Velocidad inicial del globo 1 (pixels/s)
balloon.settings[0].grav 320.0f # Gravedad aplicada al globo 1 (pixels/s²)
balloon.settings[1].vel 222.0f # Velocidad inicial del globo 2 (pixels/s)
balloon.settings[1].grav 360.0f # Gravedad aplicada al globo 2 (pixels/s²)
balloon.settings[2].vel 282.0f # Velocidad inicial del globo 3 (pixels/s)
balloon.settings[2].grav 360.0f # Gravedad aplicada al globo 3 (pixels/s²)
balloon.settings[3].vel 327.0f # Velocidad inicial del globo 4 (pixels/s)
balloon.settings[3].grav 360.0f # Gravedad aplicada al globo 4 (pixels/s²)
balloon.color[0] blue # Color de creación del globo normal
balloon.color[1] orange # Color del globo normal
balloon.color[2] red # Color de creación del globo que rebota
balloon.color[3] green # Color del globo que rebota
balloon.bouncing_sound false # Indica si los globos hacer sonido al rebotar
# --- NOTIFICATION ---
notification.pos_v TOP # Posición vertical de la notificación (TOP/BOTTOM)
notification.pos_h LEFT # Posición horizontal de la notificación (LEFT/RIGHT)
notification.sound false # ¿La notificación reproduce sonido?
notification.color 303030 # Color de fondo de la notificación (hexadecimal)
# --- SERVICE MENU ---
service_menu.title_color 99FF62 # Color del título del menú de servicio
service_menu.text_color FFFFFF # Color del texto del menú de servicio
service_menu.selected_color FFDC44 # Color de la opción seleccionada en el menú de servicio
service_menu.bg_color 000F00F5 # Color de fondo del menú de servicio (RGBA hexadecimal)
service_menu.drop_shadow false # ¿El menú de servicio tiene sombra?
service_menu.window_message.bg_color 141E32F0 # Color de fondo de ventanas de mensaje (RGBA hexadecimal)
service_menu.window_message.border_color 6496C8FF # Color del borde de ventanas de mensaje (RGBA hexadecimal)
service_menu.window_message.title_color 6496C8FF # Color del título en ventanas de mensaje (RGBA hexadecimal)
service_menu.window_message.text_color DCDCDCFF # Color del texto en ventanas de mensaje (RGBA hexadecimal)
service_menu.window_message.padding 15.0f # Espaciado interno de ventanas de mensaje (píxeles)
service_menu.window_message.line_spacing 5.0f # Espaciado entre líneas de texto (píxeles)
service_menu.window_message.title_separator_spacing 20.0f # Espaciado entre título y contenido (píxeles)
service_menu.window_message.min_width 200.0f # Ancho mínimo de ventanas de mensaje (píxeles)
service_menu.window_message.min_height 32.0f # Alto mínimo de ventanas de mensaje (píxeles)
service_menu.window_message.max_width_ratio 0.8f # Ratio máximo de ancho respecto a pantalla (0.0-1.0)
service_menu.window_message.max_height_ratio 0.8f # Ratio máximo de alto respecto a pantalla (0.0-1.0)
service_menu.window_message.text_safety_margin 15.0f # Margen de seguridad para el texto (píxeles)
service_menu.window_message.animation_duration 0.3f # Duración de animaciones de ventanas (segundos)
# --- INTRO ---
intro.bg_color 4664BD # Color de fondo de la intro
intro.card_color CBDBFC # Color de las tarjetas en la intro
intro.shadow_color 00000080 # Color de la sombra de las tarjetas en la intro
intro.text_distance_from_bottom 48 # Posición del texto desde la parte inferior
# --- DEBUG ---
debug.color 00FFFF # Color para elementos de depuración
# --- RESOURCE ---
resource.color FFFFFF # Color de recursos
# --- TABE ---
tabe.min_spawn_time 2.0f # Tiempo mínimo en segundos para que aparezca el Tabe
tabe.max_spawn_time 3.0f # Tiempo máximo en segundos para que aparezca el Tabe
# --- PLAYER ---
# Jugador 1 - Camiseta por defecto
player.default_shirt[0].darkest 028ECFFF # Tono más oscuro - bordes y contornos (Jugador 1, por defecto)
player.default_shirt[0].dark 0297DBFF # Tono oscuro - sombras (Jugador 1, por defecto)
player.default_shirt[0].base 029FE8FF # Tono principal - color base (Jugador 1, por defecto)
player.default_shirt[0].light 03A9F4FF # Tono claro - zonas iluminadas (Jugador 1, por defecto)
# Jugador 2 - Camiseta por defecto
player.default_shirt[1].darkest 8E8E8EFF # Tono más oscuro - bordes y contornos (Jugador 2, por defecto)
player.default_shirt[1].dark AEADADFF # Tono oscuro - sombras (Jugador 2, por defecto)
player.default_shirt[1].base E4E4E4FF # Tono principal - color base (Jugador 2, por defecto)
player.default_shirt[1].light F7F1F1FF # Tono claro - zonas iluminadas (Jugador 2, por defecto)
# Jugador 1 - Camiseta con 1 café
player.one_coffee_shirt[0].darkest 3D9C70FF # Tono más oscuro - bordes y contornos (Jugador 1, 1 café)
player.one_coffee_shirt[0].dark 4FA370FF # Tono oscuro - sombras (Jugador 1, 1 café)
player.one_coffee_shirt[0].base 5DDE70FF # Tono principal - color base (Jugador 1, 1 café)
player.one_coffee_shirt[0].light 7DF25CFF # Tono claro - zonas iluminadas (Jugador 1, 1 café)
# Jugador 1 - Camiseta con 2 cafés
player.two_coffee_shirt[0].darkest D6A41AFF # Tono más oscuro - bordes y contornos (Jugador 1, 2 cafés)
player.two_coffee_shirt[0].dark E3AE1BFF # Tono oscuro - sombras (Jugador 1, 2 cafés)
player.two_coffee_shirt[0].base EFB71DFF # Tono principal - color base (Jugador 1, 2 cafés)
player.two_coffee_shirt[0].light FCC11EFF # Tono claro - zonas iluminadas (Jugador 1, 2 cafés)
# Jugador 2 - Camiseta con 1 café
player.one_coffee_shirt[1].darkest 2E8B57FF # Tono más oscuro - bordes y contornos (Jugador 2, 1 café)
player.one_coffee_shirt[1].dark 3CB371FF # Tono oscuro - sombras (Jugador 2, 1 café)
player.one_coffee_shirt[1].base 48D181FF # Tono principal - color base (Jugador 2, 1 café)
player.one_coffee_shirt[1].light 55EF8DFF # Tono claro - zonas iluminadas (Jugador 2, 1 café)
# Jugador 2 - Camiseta con 2 cafés
player.two_coffee_shirt[1].darkest E08500FF # Tono más oscuro - bordes y contornos (Jugador 2, 2 cafés)
player.two_coffee_shirt[1].dark FA7D00FF # Tono oscuro - sombras (Jugador 2, 2 cafés)
player.two_coffee_shirt[1].base FAA200FF # Tono principal - color base (Jugador 2, 2 cafés)
player.two_coffee_shirt[1].light FA8500FF # Tono claro - zonas iluminadas (Jugador 2, 2 cafés)
# Colores de contorno de los jugadores
player.outline_color[0] 66323FFF # Color del contorno del sprite del Jugador 1
player.outline_color[1] 422028FF # Color del contorno del sprite del Jugador 2

150
config/param_red.txt Normal file
View File

@@ -0,0 +1,150 @@
# Coffee Crisis Arcade Edition - Fichero de parametros - RED THEME
# Formato: PARAMETRO VALOR
# --- GAME ---
game.item_size 20 # Tamaño de los items del juego (en píxeles)
game.item_text_outline_color FFB8B8F0 # Color del outline del texto de los items (RGBA hex) - Rojo claro
game.width 320 # Ancho de la resolución nativa del juego (en píxeles)
game.height 256 # Alto de la resolución nativa del juego (en píxeles)
game.play_area.rect.x 0 # Posición X de la zona jugable
game.play_area.rect.y 0 # Posición Y de la zona jugable
game.play_area.rect.w 320 # Ancho de la zona jugable
game.play_area.rect.h 216 # Alto de la zona jugable
game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
# --- FADE ---
fade.color 5C1F1F # Color hexadecimal para el efecto de fundido - Rojo oscuro
fade.num_squares_width 64 # Número de cuadrados en el eje X para el fundido
fade.num_squares_height 48 # Número de cuadrados en el eje Y para el fundido
fade.random_squares_duration_ms 1200 # Duración del fade en milisegundos
fade.post_duration_ms 500 # Duración tras el fundido en milisegundos
fade.venetian_size 12 # Tamaño de las bandas para el efecto veneciano (en píxeles)
# --- SCOREBOARD ---
scoreboard.rect.x 0 # Posición X del marcador
scoreboard.rect.y 216 # Posición Y del marcador
scoreboard.rect.w 320 # Ancho del marcador
scoreboard.rect.h 40 # Alto del marcador
scoreboard.separator_autocolor true # ¿El separador usa color automático?
scoreboard.separator_color 2B0D0D # Color del separador - Rojo muy oscuro
scoreboard.easy_color 8B4A2F # Color para la dificultad fácil - Marrón rojizo
scoreboard.normal_color 6B2F2F # Color para la dificultad normal - Rojo medio
scoreboard.hard_color A73030 # Color para la dificultad difícil - Rojo fuerte
scoreboard.text_autocolor true # ¿El texto usa color automático?
scoreboard.text_color1 FFE6E6 # Color principal del texto del marcador - Blanco rosado
scoreboard.text_color2 FFE6E6 # Color secundario del texto del marcador - Blanco rosado
scoreboard.skip_countdown_value 8 # Valor para saltar la cuenta atrás (segundos)
# --- TITLE ---
title.press_start_position 180 # Posición Y del texto "Press Start"
title.title_duration 800 # Duración de la pantalla de título (frames)
title.arcade_edition_position 123 # Posición Y del subtítulo "Arcade Edition"
title.title_c_c_position 80 # Posición Y del título principal
title.bg_color 8B4A3A # Color de fondo en la sección titulo - Marrón rojizo
# --- BACKGROUND ---
background.attenuate_color FF4A3A40 # Color de atenuación del fondo (RGBA hexadecimal) - Blanco rosado
# --- BALLOONS ---
balloon.settings[0].vel 2.75f # Velocidad inicial del globo 1
balloon.settings[0].grav 0.09f # Gravedad aplicada al globo 1
balloon.settings[1].vel 3.70f # Velocidad inicial del globo 2
balloon.settings[1].grav 0.10f # Gravedad aplicada al globo 2
balloon.settings[2].vel 4.70f # Velocidad inicial del globo 3
balloon.settings[2].grav 0.10f # Gravedad aplicada al globo 3
balloon.settings[3].vel 5.45f # Velocidad inicial del globo 4
balloon.settings[3].grav 0.10f # Gravedad aplicada al globo 4
balloon.color[0] orange # Color de creación del globo normal
balloon.color[1] red # Color del globo normal
balloon.color[2] blue # Color de creación del globo que rebota
balloon.color[3] green # Color del globo que rebota
balloon.bouncing_sound false # Indica si los globos hacer sonido al rebotar
# --- NOTIFICATION ---
notification.pos_v TOP # Posición vertical de la notificación (TOP/BOTTOM)
notification.pos_h LEFT # Posición horizontal de la notificación (LEFT/RIGHT)
notification.sound false # ¿La notificación reproduce sonido?
notification.color 4D1A1A # Color de fondo de la notificación - Rojo oscuro
# --- SERVICE MENU ---
service_menu.title_color FF9966 # Color del título del menú de servicio - Naranja claro
service_menu.text_color FFE6E6 # Color del texto del menú de servicio - Blanco rosado
service_menu.selected_color FFB366 # Color de la opción seleccionada - Naranja dorado
service_menu.bg_color 331A0AF5 # Color de fondo del menú de servicio - Marrón rojizo oscuro con alpha
service_menu.drop_shadow false # ¿El menú de servicio tiene sombra?
service_menu.window_message.bg_color 4D1A1AF0 # Color de fondo de ventanas - Rojo oscuro con alpha
service_menu.window_message.border_color CC6633FF # Color del borde de ventanas - Naranja rojizo
service_menu.window_message.title_color CC6633FF # Color del título en ventanas - Naranja rojizo
service_menu.window_message.text_color FFE6E6FF # Color del texto en ventanas - Blanco rosado
service_menu.window_message.padding 15.0f # Espaciado interno de ventanas de mensaje (píxeles)
service_menu.window_message.line_spacing 5.0f # Espaciado entre líneas de texto (píxeles)
service_menu.window_message.title_separator_spacing 20.0f # Espaciado entre título y contenido (píxeles)
service_menu.window_message.min_width 200.0f # Ancho mínimo de ventanas de mensaje (píxeles)
service_menu.window_message.min_height 32.0f # Alto mínimo de ventanas de mensaje (píxeles)
service_menu.window_message.max_width_ratio 0.8f # Ratio máximo de ancho respecto a pantalla (0.0-1.0)
service_menu.window_message.max_height_ratio 0.8f # Ratio máximo de alto respecto a pantalla (0.0-1.0)
service_menu.window_message.text_safety_margin 15.0f # Margen de seguridad para el texto (píxeles)
service_menu.window_message.animation_duration 0.3f # Duración de animaciones de ventanas (segundos)
# --- INTRO ---
intro.bg_color B8664D # Color de fondo de la intro - Naranja tierra
intro.card_color FFE6CC # Color de las tarjetas en la intro - Crema rojizo
intro.shadow_color 66000080 # Color de la sombra de las tarjetas - Rojo muy oscuro con alpha
intro.text_distance_from_bottom 48 # Posición del texto desde la parte inferior
# --- DEBUG ---
debug.color FF6666 # Color para elementos de depuración - Rojo claro
# --- RESOURCE ---
resource.color FFE6E6 # Color de recursos - Blanco rosado
# --- TABE ---
tabe.min_spawn_time 2.0f # Tiempo mínimo en segundos para que aparezca el Tabe
tabe.max_spawn_time 3.0f # Tiempo máximo en segundos para que aparezca el Tabe
# --- PLAYER ---
# Jugador 1 - Camiseta por defecto (tonos rojos)
player.default_shirt[0].darkest B33030FF # Tono más oscuro - Rojo fuerte
player.default_shirt[0].dark CC4040FF # Tono oscuro - Rojo medio
player.default_shirt[0].base E65050FF # Tono principal - Rojo claro
player.default_shirt[0].light FF6666FF # Tono claro - Rojo muy claro
# Jugador 2 - Camiseta por defecto (tonos naranjas)
player.default_shirt[1].darkest B36030FF # Tono más oscuro - Naranja oscuro
player.default_shirt[1].dark CC7540FF # Tono oscuro - Naranja medio
player.default_shirt[1].base E68A50FF # Tono principal - Naranja claro
player.default_shirt[1].light FF9966FF # Tono claro - Naranja muy claro
# Jugador 1 - Camiseta con 1 café (tonos rojizos más intensos)
player.one_coffee_shirt[0].darkest 8B2635FF # Tono más oscuro - Rojo granate
player.one_coffee_shirt[0].dark A53040FF # Tono oscuro - Rojo granate claro
player.one_coffee_shirt[0].base BF3A50FF # Tono principal - Rojo vibrante
player.one_coffee_shirt[0].light D94460FF # Tono claro - Rojo vibrante claro
# Jugador 1 - Camiseta con 2 cafés (tonos naranja dorado)
player.two_coffee_shirt[0].darkest CC6600FF # Tono más oscuro - Naranja dorado oscuro
player.two_coffee_shirt[0].dark E6750AFF # Tono oscuro - Naranja dorado
player.two_coffee_shirt[0].base FF8514FF # Tono principal - Naranja dorado claro
player.two_coffee_shirt[0].light FF991EFF # Tono claro - Naranja dorado muy claro
# Jugador 2 - Camiseta con 1 café (tonos terracotas)
player.one_coffee_shirt[1].darkest A0472DFF # Tono más oscuro - Terracota oscuro
player.one_coffee_shirt[1].dark B8553AFF # Tono oscuro - Terracota medio
player.one_coffee_shirt[1].base D06347FF # Tono principal - Terracota claro
player.one_coffee_shirt[1].light E87154FF # Tono claro - Terracota muy claro
# Jugador 2 - Camiseta con 2 cafés (tonos naranjas cálidos)
player.two_coffee_shirt[1].darkest CC5500FF # Tono más oscuro - Naranja intenso
player.two_coffee_shirt[1].dark E66600FF # Tono oscuro - Naranja fuerte
player.two_coffee_shirt[1].base FF7700FF # Tono principal - Naranja brillante
player.two_coffee_shirt[1].light FF8800FF # Tono claro - Naranja muy brillante
# Colores de contorno de los jugadores
player.outline_color[0] 994D33FF # Color del contorno del Jugador 1 - Marrón rojizo
player.outline_color[1] 664433FF # Color del contorno del Jugador 2 - Marrón tierra

34
config/pools.txt Normal file
View File

@@ -0,0 +1,34 @@
# Coffee Crisis Arcade Edition - Archivo de configuración de pools de formaciones de globos
# Formato: POOL: <id> FORMATIONS: <id1>, <id2>, <id3>, ...
# Los IDs de formación pueden repetirse
# Los pools no necesitan estar ordenados ni ser consecutivos
# Pool para la fase 1
POOL: 0 FORMATIONS: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
# Pool para la fase 2
POOL: 1 FORMATIONS: 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
# Pool para la fase 3
POOL: 2 FORMATIONS: 0, 1, 2, 3, 4, 55, 56, 57, 58, 59
# Pool para la fase 4
POOL: 3 FORMATIONS: 50, 51, 52, 53, 54, 5, 6, 7, 8, 9
# Pool para la fase 5
POOL: 4 FORMATIONS: 60, 61, 62, 63, 64, 65, 66, 67, 68, 69
# Pool para la fase 6
POOL: 5 FORMATIONS: 10, 61, 12, 63, 14, 65, 16, 67, 18, 69
# Pool para la fase 7
POOL: 6 FORMATIONS: 60, 11, 62, 13, 64, 15, 66, 17, 68, 19
# Pool para la fase 8
POOL: 7 FORMATIONS: 20, 21, 22, 23, 24, 65, 66, 67, 68, 69
# Pool para la fase 9
POOL: 8 FORMATIONS: 70, 71, 72, 73, 74, 15, 16, 17, 18, 19
# Pool para la fase 10
POOL: 9 FORMATIONS: 20, 21, 22, 23, 24, 70, 71, 72, 73, 74

19
config/stages.txt Normal file
View File

@@ -0,0 +1,19 @@
# Coffee Crisis Arcade Edition - Archivo de configuración de fases
# Formato: power_to_complete,min_menace,max_menace,name
# Líneas que empiezan con # son comentarios y se ignoran
# Fases iniciales - Tutorial y aprendizaje
200, 11, 19, Tutorial
300, 15, 23, Primeros pasos
# Fases intermedias - Incremento de dificultad
400, 19, 27, Intensificación
400, 19, 27, Persistencia
400, 23, 31, Desafío medio
400, 23, 31, Resistencia
# Fases avanzadas - Desafío final
600, 27, 35, Aproximación final
600, 27, 35, Penúltimo obstáculo
700, 31, 39, Clímax
950, 35, 47, Maestría

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,277 +0,0 @@
# Archivo de configuración de formaciones de globos
# Formato por línea: x, desp, y, vel_x, tipo, tamaño, retraso_tiempo_creacion
# Variables disponibles:
# X0_0, X0_50, X0_100, X1_0, X1_100, X2_0, X2_100, X3_0, X3_100
# X3_25, X3_75, DEFAULT_POS_Y
# SMALL, MEDIUM, LARGE, EXTRALARGE
# RIGHT, LEFT
formation: 0
# Dos enemigos BALLOON3 uno a cada extremo
X3_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0
X3_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0
formation: 1
# Dos enemigos BALLOON3 uno a cada cuarto. Ambos van hacia el centro
X3_25, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0
X3_75, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0
formation: 2
# Cuatro enemigos BALLOON1 uno detrás del otro. A la izquierda y hacia el centro
X1_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 30
X1_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 20
X1_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 10
X1_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0
formation: 3
# Cuatro enemigos BALLOON1 uno detrás del otro. A la derecha y hacia el centro
X1_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 30
X1_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 20
X1_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 10
X1_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0
formation: 4
# Tres enemigos BALLOON2. 0, 25, 50. Hacia la derecha
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 20
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 10
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0
formation: 5
# Tres enemigos BALLOON2. 50, 75, 100. Hacia la izquierda
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 20
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 10
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0
formation: 6
# Tres enemigos BALLOON2. 0, 0, 0. Hacia la derecha
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 20
X2_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 10
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0
formation: 7
# Tres enemigos BALLOON2. 100, 100, 100. Hacia la izquierda
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 20
X2_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 10
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0
formation: 8
# Seis enemigos BALLOON0. 0, 0, 0, 0, 0, 0. Hacia la derecha
X0_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 50
X0_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 40
X0_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 30
X0_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 20
X0_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 10
X0_0, 5, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0
formation: 9
# Seis enemigos BALLOON0. 100, 100, 100, 100, 100, 100. Hacia la izquierda
X0_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 50
X0_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 40
X0_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 30
X0_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 20
X0_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 10
X0_100, -5, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0
formation: 10
# Tres enemigos BALLOON3 seguidos desde la izquierda. Hacia la derecha
X3_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 30
X3_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 15
X3_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0
formation: 11
# Tres enemigos BALLOON3 seguidos desde la derecha. Hacia la izquierda
X3_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 30
X3_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 15
X3_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0
formation: 12
# Seis enemigos BALLOON1 uno detrás del otro. A la izquierda y hacia el centro
X1_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 50
X1_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 40
X1_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 30
X1_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 20
X1_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 10
X1_0, 5, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0
formation: 13
# Seis enemigos BALLOON1 uno detrás del otro. A la derecha y hacia el centro
X1_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 50
X1_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 40
X1_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 30
X1_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 20
X1_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 10
X1_100, -5, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0
formation: 14
# Cinco enemigos BALLOON2. Hacia la derecha. Separados
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 40
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 30
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 20
X2_0, 6, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 10
X2_0, 8, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0
formation: 15
# Cinco enemigos BALLOON2. Hacia la izquierda. Separados
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 40
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 30
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 20
X2_100, -6, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 10
X2_100, -8, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0
formation: 16
# Cinco enemigos BALLOON2. Hacia la derecha. Juntos
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 40
X2_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 30
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 20
X2_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 10
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0
formation: 17
# Cinco enemigos BALLOON2. Hacia la izquierda. Juntos
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 40
X2_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 30
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 20
X2_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 10
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0
formation: 18
# Doce enemigos BALLOON0. Hacia la derecha. Juntos
X0_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 110
X0_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 100
X0_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 90
X0_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 80
X0_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 70
X0_0, 5, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 60
X0_0, 6, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 50
X0_0, 7, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 40
X0_0, 8, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 30
X0_0, 9, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 20
X0_0, 10, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 10
X0_0, 11, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0
formation: 19
# Doce enemigos BALLOON0. Hacia la izquierda. Juntos
X0_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 110
X0_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 100
X0_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 90
X0_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 80
X0_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 70
X0_100, -5, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 60
X0_100, -6, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 50
X0_100, -7, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 40
X0_100, -8, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 30
X0_100, -9, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 20
X0_100, -10, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 10
X0_100, -11, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0
formation: 20
# Cuatro enemigos BALLOON3 seguidos desde la izquierda/derecha. Simétricos
X3_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0
X3_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0
X3_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0
X3_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0
formation: 21
# Diez enemigos BALLOON1 uno detrás del otro. Izquierda/derecha. Simétricos
X1_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 12
X1_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 9
X1_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 6
X1_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 3
X1_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0
X1_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 12
X1_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 9
X1_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 6
X1_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 3
X1_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0
formation: 22
# Diez enemigos BALLOON2. Hacia la derecha/izquierda. Separados. Simétricos
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 40
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 30
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 20
X2_0, 6, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 10
X2_0, 8, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 40
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 30
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 20
X2_100, -6, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 10
X2_100, -8, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0
formation: 23
# Diez enemigos BALLOON2. Hacia la derecha. Juntos. Simétricos
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 40
X2_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 30
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 20
X2_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 10
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 40
X2_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 30
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 20
X2_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 10
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0
formation: 24
# Treinta enemigos BALLOON0. Del centro hacia los extremos. Juntos. Simétricos
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 5
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 10
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 15
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 20
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 25
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 30
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 35
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 40
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 45
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 50
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 55
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 60
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 65
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 70
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 5
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 10
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 15
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 20
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 25
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 30
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 35
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 40
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 45
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 50
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 55
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 60
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 65
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 70
formation: 25
# Treinta enemigos BALLOON0. Del centro hacia adentro. Juntos. Simétricos
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 70
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 65
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 60
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 55
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 50
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 45
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 40
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 35
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 30
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 25
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 20
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 15
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 10
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 5
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 70
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 65
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 60
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 55
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 50
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 45
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 40
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 35
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 30
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 25
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 20
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 15
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 10
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 5
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0

View File

@@ -1,89 +0,0 @@
## --- GAME ---
game.item_size 20 # Tamaño de los items del juego (en píxeles)
game.width 320 # Ancho de la resolución nativa del juego (en píxeles)
game.height 240 # Alto de la resolución nativa del juego (en píxeles)
game.play_area.rect.x 0 # Posición X de la zona jugable
game.play_area.rect.y 0 # Posición Y de la zona jugable
game.play_area.rect.w 320 # Ancho de la zona jugable
game.play_area.rect.h 200 # Alto de la zona jugable
game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
## --- FADE ---
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido
fade.num_squares_width 160 # Número de cuadrados en el eje X para el fundido
fade.num_squares_height 120 # Número de cuadrados en el eje Y para el fundido
fade.random_squares_delay 1 # Delay entre aparición de cuadrados aleatorios (frames)
fade.random_squares_mult 500 # Multiplicador para la velocidad de aparición aleatoria
fade.post_duration 80 # Duración tras el fundido (frames)
fade.venetian_size 12 # Tamaño de las bandas para el efecto veneciano (en píxeles)
## --- SCOREBOARD ---
scoreboard.rect.x 0 # Posición X del marcador
scoreboard.rect.y 216 # Posición Y del marcador
scoreboard.rect.w 320 # Ancho del marcador
scoreboard.rect.h 40 # Alto del marcador
scoreboard.separator_autocolor true # ¿El separador usa color automático?
scoreboard.separator_color 0D1A2B # Color del separador (hexadecimal)
scoreboard.easy_color 4B692F # Color para la dificultad fácil
scoreboard.normal_color 2E3F47 # Color para la dificultad normal
scoreboard.hard_color 76428A # Color para la dificultad difícil
scoreboard.text_autocolor true # ¿El texto usa color automático?
scoreboard.text_color1 FFFFFF # Color principal del texto del marcador
scoreboard.text_color2 FFFFFF # Color secundario del texto del marcador
scoreboard.skip_countdown_value 8 # Valor para saltar la cuenta atrás (segundos)
## --- TITLE ---
title.press_start_position 180 # Posición Y del texto "Press Start"
title.title_duration 800 # Duración de la pantalla de título (frames)
title.arcade_edition_position 123 # Posición Y del subtítulo "Arcade Edition"
title.title_c_c_position 80 # Posición Y del título principal
title.bg_color 41526F # Color de fondo en la sección titulo
## --- BACKGROUND ---
background.attenuate_color FFFFFF00 # Color de atenuación del fondo (RGBA hexadecimal)
## --- BALLOONS ---
balloon.settings[0].vel 2.75f # Velocidad inicial del globo 1
balloon.settings[0].grav 0.09f # Gravedad aplicada al globo 1
balloon.settings[1].vel 3.70f # Velocidad inicial del globo 2
balloon.settings[1].grav 0.10f # Gravedad aplicada al globo 2
balloon.settings[2].vel 4.70f # Velocidad inicial del globo 3
balloon.settings[2].grav 0.10f # Gravedad aplicada al globo 3
balloon.settings[3].vel 5.45f # Velocidad inicial del globo 4
balloon.settings[3].grav 0.10f # Gravedad aplicada al globo 4
balloon.color[0] blue # Color de creación del globo normal
balloon.color[1] orange # Color del globo normal
balloon.color[2] red # Color de creación del globo que rebota
balloon.color[3] green # Color del globo que rebota
balloon.bouncing_sound false # Indica si los globos hacer sonido al rebotar
## --- NOTIFICATION ---
notification.pos_v TOP # Posición vertical de la notificación (TOP/BOTTOM)
notification.pos_h LEFT # Posición horizontal de la notificación (LEFT/RIGHT)
notification.sound false # ¿La notificación reproduce sonido?
notification.color 303030 # Color de fondo de la notificación (hexadecimal)
## --- SERVICE MENU ---
service_menu.title_color 99FF62 # Color del título del menú de servicio
service_menu.text_color FFFFFF # Color del texto del menú de servicio
service_menu.selected_color FFDC44 # Color de la opción seleccionada en el menú de servicio
service_menu.bg_color 003000F5 # Color de fondo del menú de servicio (RGBA hexadecimal)
service_menu.drop_shadow false # ¿El menú de servicio tiene sombra?
## --- INTRO ---
intro.bg_color 4664BD # Color de fondo de la intro
intro.card_color CBDBFC # Color de las tarjetas en la intro
intro.shadow_color 00000080 # Color de la sombra de las tarjetas en la intro
intro.text_distance_from_bottom 48 # Posicion del texto
## --- DEBUG ---
debug.color 00FFFF # Color para elementos de depuración
## --- RESOURCE ---
resource.color FFFFFF # Color de recurso 1
resource.color FFFFFF # Color de recurso 2

View File

@@ -1,89 +0,0 @@
## --- GAME ---
game.item_size 20 # Tamaño de los items del juego (en píxeles)
game.width 320 # Ancho de la resolución nativa del juego (en píxeles)
game.height 256 # Alto de la resolución nativa del juego (en píxeles)
game.play_area.rect.x 0 # Posición X de la zona jugable
game.play_area.rect.y 0 # Posición Y de la zona jugable
game.play_area.rect.w 320 # Ancho de la zona jugable
game.play_area.rect.h 216 # Alto de la zona jugable
game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
## --- FADE ---
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido
fade.num_squares_width 160 # Número de cuadrados en el eje X para el fundido
fade.num_squares_height 128 # Número de cuadrados en el eje Y para el fundido
fade.random_squares_delay 1 # Delay entre aparición de cuadrados aleatorios (frames)
fade.random_squares_mult 500 # Multiplicador para la velocidad de aparición aleatoria
fade.post_duration 80 # Duración tras el fundido (frames)
fade.venetian_size 12 # Tamaño de las bandas para el efecto veneciano (en píxeles)
## --- SCOREBOARD ---
scoreboard.rect.x 0 # Posición X del marcador
scoreboard.rect.y 216 # Posición Y del marcador
scoreboard.rect.w 320 # Ancho del marcador
scoreboard.rect.h 40 # Alto del marcador
scoreboard.separator_autocolor true # ¿El separador usa color automático?
scoreboard.separator_color 0D1A2B # Color del separador (hexadecimal)
scoreboard.easy_color 4B692F # Color para la dificultad fácil
scoreboard.normal_color 2E3F47 # Color para la dificultad normal
scoreboard.hard_color 76428A # Color para la dificultad difícil
scoreboard.text_autocolor true # ¿El texto usa color automático?
scoreboard.text_color1 FFFFFF # Color principal del texto del marcador
scoreboard.text_color2 FFFFFF # Color secundario del texto del marcador
scoreboard.skip_countdown_value 8 # Valor para saltar la cuenta atrás (segundos)
## --- TITLE ---
title.press_start_position 180 # Posición Y del texto "Press Start"
title.title_duration 800 # Duración de la pantalla de título (frames)
title.arcade_edition_position 123 # Posición Y del subtítulo "Arcade Edition"
title.title_c_c_position 80 # Posición Y del título principal
title.bg_color 41526F # Color de fondo en la sección titulo
## --- BACKGROUND ---
background.attenuate_color FFFFFF00 # Color de atenuación del fondo (RGBA hexadecimal)
## --- BALLOONS ---
balloon.settings[0].vel 2.75f # Velocidad inicial del globo 1
balloon.settings[0].grav 0.09f # Gravedad aplicada al globo 1
balloon.settings[1].vel 3.70f # Velocidad inicial del globo 2
balloon.settings[1].grav 0.10f # Gravedad aplicada al globo 2
balloon.settings[2].vel 4.70f # Velocidad inicial del globo 3
balloon.settings[2].grav 0.10f # Gravedad aplicada al globo 3
balloon.settings[3].vel 5.45f # Velocidad inicial del globo 4
balloon.settings[3].grav 0.10f # Gravedad aplicada al globo 4
balloon.color[0] blue # Color de creación del globo normal
balloon.color[1] orange # Color del globo normal
balloon.color[2] red # Color de creación del globo que rebota
balloon.color[3] green # Color del globo que rebota
balloon.bouncing_sound false # Indica si los globos hacer sonido al rebotar
## --- NOTIFICATION ---
notification.pos_v TOP # Posición vertical de la notificación (TOP/BOTTOM)
notification.pos_h LEFT # Posición horizontal de la notificación (LEFT/RIGHT)
notification.sound false # ¿La notificación reproduce sonido?
notification.color 303030 # Color de fondo de la notificación (hexadecimal)
## --- SERVICE MENU ---
service_menu.title_color 99FF62 # Color del título del menú de servicio
service_menu.text_color FFFFFF # Color del texto del menú de servicio
service_menu.selected_color FFDC44 # Color de la opción seleccionada en el menú de servicio
service_menu.bg_color 000F00F5 # Color de fondo del menú de servicio (RGBA hexadecimal)
service_menu.drop_shadow false # ¿El menú de servicio tiene sombra?
## --- INTRO ---
intro.bg_color 4664BD # Color de fondo de la intro
intro.card_color CBDBFC # Color de las tarjetas en la intro
intro.shadow_color 00000080 # Color de la sombra de las tarjetas en la intro
intro.text_distance_from_bottom 48 # Posicion del texto
## --- DEBUG ---
debug.color 00FFFF # Color para elementos de depuración
## --- RESOURCE ---
resource.color FFFFFF # Color de recurso 1
resource.color FFFFFF # Color de recurso 2

View File

@@ -1,34 +0,0 @@
# Archivo de configuración de pools de formaciones de globos
# Formato: POOL: <id> FORMATIONS: <id1>, <id2>, <id3>, ...
# Los IDs de formación pueden repetirse
# Los pools no necesitan estar ordenados ni ser consecutivos
# Pool para la fase 1
POOL: 0 FORMATIONS: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
# Pool para la fase 2
POOL: 1 FORMATIONS: 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
# Pool para la fase 3
POOL: 2 FORMATIONS: 0, 1, 2, 3, 4, 55, 56, 57, 58, 59
# Pool para la fase 4
POOL: 3 FORMATIONS: 50, 51, 52, 53, 54, 5, 6, 7, 8, 9
# Pool para la fase 5
POOL: 4 FORMATIONS: 60, 61, 62, 63, 64, 65, 66, 67, 68, 69
# Pool para la fase 6
POOL: 5 FORMATIONS: 10, 61, 12, 63, 14, 65, 16, 67, 18, 69
# Pool para la fase 7
POOL: 6 FORMATIONS: 60, 11, 62, 13, 64, 15, 66, 17, 68, 19
# Pool para la fase 8
POOL: 7 FORMATIONS: 20, 21, 22, 23, 24, 65, 66, 67, 68, 69
# Pool para la fase 9
POOL: 8 FORMATIONS: 70, 71, 72, 73, 74, 15, 16, 17, 18, 19
# Pool para la fase 10
POOL: 9 FORMATIONS: 20, 21, 22, 23, 24, 70, 71, 72, 73, 74

BIN
data/demo/demo1.bin Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
data/demo/demo2.bin Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
data/demo/demo3.bin Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
data/font/04b_25_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 872 B

After

Width:  |  Height:  |  Size: 882 B

View File

@@ -3,28 +3,28 @@ frame_height=10
[animation]
name=orange
speed=10
speed=0.1667
loop=0
frames=0,1,2,3,4,5,6,7,8,9
[/animation]
[animation]
name=blue
speed=20
speed=0.3333
loop=0
frames=10,11,12,13,14,15,16,17,18,19
[/animation]
[animation]
name=green
speed=10
speed=0.1667
loop=0
frames=20,21,22,23,24,25,26,27,28,29
[/animation]
[animation]
name=red
speed=20
speed=0.3333
loop=0
frames=30,31,32,33,34,35,36,37,38,39
[/animation]

View File

@@ -3,28 +3,28 @@ frame_height=16
[animation]
name=orange
speed=10
speed=0.1667
loop=0
frames=0,1,2,3,4,5,6,7,8,9
[/animation]
[animation]
name=blue
speed=20
speed=0.3333
loop=0
frames=10,11,12,13,14,15,16,17,18,19
[/animation]
[animation]
name=green
speed=10
speed=0.1667
loop=0
frames=20,21,22,23,24,25,26,27,28,29
[/animation]
[animation]
name=red
speed=20
speed=0.3333
loop=0
frames=30,31,32,33,34,35,36,37,38,39
[/animation]

View File

@@ -3,28 +3,28 @@ frame_height=26
[animation]
name=orange
speed=10
speed=0.1667
loop=0
frames=0,1,2,3,4,5,6,7,8,9
[/animation]
[animation]
name=blue
speed=20
speed=0.3333
loop=0
frames=10,11,12,13,14,15,16,17,18,19
[/animation]
[animation]
name=green
speed=10
speed=0.1667
loop=0
frames=20,21,22,23,24,25,26,27,28,29
[/animation]
[animation]
name=red
speed=20
speed=0.3333
loop=0
frames=30,31,32,33,34,35,36,37,38,39
[/animation]

View File

@@ -3,28 +3,28 @@ frame_height=48
[animation]
name=orange
speed=10
speed=0.1667
loop=0
frames=0,1,2,3,4,5,6,7,8,9
[/animation]
[animation]
name=blue
speed=20
speed=0.3333
loop=0
frames=10,11,12,13,14,15,16,17,18,19
[/animation]
[animation]
name=green
speed=10
speed=0.1667
loop=0
frames=20,21,22,23,24,25,26,27,28,29
[/animation]
[animation]
name=red
speed=20
speed=0.3333
loop=0
frames=30,31,32,33,34,35,36,37,38,39
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=10
[animation]
name=default
speed=5
speed=0.0833
loop=-1
frames=0,1,2,3,4,5,6,7,8,9
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=16
[animation]
name=default
speed=5
speed=0.0833
loop=-1
frames=0,1,2,3,4,5,6,7,8,9
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=26
[animation]
name=default
speed=5
speed=0.0833
loop=-1
frames=0,1,2,3,4,5,6,7,8,9
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=48
[animation]
name=default
speed=5
speed=0.0833
loop=-1
frames=0,1,2,3,4,5,6,7,8,9
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=49
[animation]
name=powerball
speed=10
speed=0.0167
loop=-1
frames=1
[/animation]

View File

@@ -2,43 +2,85 @@ frame_width=12
frame_height=12
[animation]
name=normal_up
speed=5
loop=0
frames=0,1,2
name=yellow_up
speed=20
loop=-1
frames=0
[/animation]
[animation]
name=normal_left
speed=5
loop=0
frames=3,4,5,5,4,3
name=yellow_left
speed=20
loop=-1
frames=1
[/animation]
[animation]
name=normal_right
speed=5
loop=0
frames=6,7,8,8,7,6
name=yellow_right
speed=20
loop=-1
frames=2
[/animation]
[animation]
name=powered_up
speed=5
loop=0
frames=9,10,11,11,10,9
name=green_up
speed=20
loop=-1
frames=3
[/animation]
[animation]
name=powered_left
speed=5
loop=0
frames=12,13,14,14,13,12
name=green_left
speed=20
loop=-1
frames=4
[/animation]
[animation]
name=powered_right
speed=5
loop=0
frames=15,16,17,17,26,15
name=green_right
speed=20
loop=-1
frames=5
[/animation]
[animation]
name=red_up
speed=20
loop=-1
frames=6
[/animation]
[animation]
name=red_left
speed=20
loop=-1
frames=7
[/animation]
[animation]
name=red_right
speed=20
loop=-1
frames=8
[/animation]
[animation]
name=purple_up
speed=20
loop=-1
frames=9
[/animation]
[animation]
name=purple_left
speed=20
loop=-1
frames=10
[/animation]
[animation]
name=purple_right
speed=20
loop=-1
frames=11
[/animation]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -3,7 +3,7 @@ frame_height=20
[animation]
name=default
speed=8
speed=0.1333
loop=0
frames=0,0,1
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=20
[animation]
name=default
speed=8
speed=0.1333
loop=0
frames=0,0,1
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=39
[animation]
name=default
speed=6
speed=0.1
loop=0
frames=0,1,2,3,4,5,6,7,8
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=20
[animation]
name=default
speed=8
speed=0.1333
loop=0
frames=0,0,1
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=20
[animation]
name=default
speed=8
speed=0.1333
loop=0
frames=0,0,1
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=20
[animation]
name=default
speed=8
speed=0.1333
loop=0
frames=0,0,1
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=20
[animation]
name=default
speed=8
speed=0.1333
loop=0
frames=0,0,1
[/animation]

View File

@@ -3,126 +3,133 @@ frame_height=32
[animation]
name=walk
speed=5
speed=0.0833
loop=0
frames=0,1,2,3
[/animation]
[animation]
name=stand
speed=10
speed=0.167
loop=0
frames=4,5,6,7
[/animation]
[animation]
name=walk-fire-side
speed=5
speed=0.0833
loop=0
frames=8,9,10,11
[/animation]
[animation]
name=walk-recoil-side
speed=5
speed=0.0833
loop=0
frames=12,13,14,15
[/animation]
[animation]
name=walk-cool-side
speed=5
speed=0.0833
loop=0
frames=16,17,18,19
[/animation]
[animation]
name=stand-fire-side
speed=5
speed=0.0833
loop=0
frames=20
[/animation]
[animation]
name=stand-recoil-side
speed=5
speed=0.0833
loop=0
frames=21
[/animation]
[animation]
name=stand-cool-side
speed=5
speed=0.0833
loop=0
frames=22
[/animation]
[animation]
name=walk-fire-center
speed=5
speed=0.0833
loop=0
frames=23,24,25,26
[/animation]
[animation]
name=walk-recoil-center
speed=5
speed=0.0833
loop=0
frames=27,28,29,30
[/animation]
[animation]
name=walk-cool-center
speed=5
speed=0.0833
loop=0
frames=31,32,33,34
[/animation]
[animation]
name=stand-fire-center
speed=5
speed=0.0833
loop=0
frames=35
[/animation]
[animation]
name=stand-recoil-center
speed=5
speed=0.0833
loop=0
frames=36
[/animation]
[animation]
name=stand-cool-center
speed=5
speed=0.0833
loop=0
frames=37
[/animation]
[animation]
name=rolling
speed=10
speed=0.167
loop=0
frames=38,39,40,41
[/animation]
[animation]
name=celebration
speed=10
loop=-1
speed=0.167
loop=0
frames=42,42,42,42,42,42,43,44,45,46,46,46,46,46,46,45,45,45,46,46,46,45,45,45,44,43,42,42,42
[/animation]
[animation]
name=dizzy
speed=5
speed=0.0833
loop=0
frames=47,48,49,50,51,52,53
[/animation]
[animation]
name=hello
speed=3
name=recover
speed=0.05
loop=-1
frames=54,55,56,57,58,59,60,61,62,63,64,64,64,64,64,64,64,64,64,64,64,64,64,65,66,67,68,69,70,71,72,73,73,72,71,70,70,71,72,73,73,72,71,70,70,71,72,73,73,72,71,70,70,71,72,73,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54
frames=54,54,54,54,55,56,57,58,58,58,59,60,61,58,59,60,61,58,59,60,61,62,62,62,62
[/animation]
[animation]
name=hello
speed=0.05
loop=-1
frames=63,64,65,66,67,68,69,70,71,72,73,73,73,73,73,73,73,73,73,73,73,73,73,74,75,76,77,78,79,80,81,82,82,81,80,79,79,80,81,82,82,81,80,79,79,80,81,82,82,81,80,79,79,80,81,82,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63
[/animation]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -3,7 +3,7 @@ frame_height=44
[animation]
name=default
speed=5
speed=0.0833
loop=0
frames=0,1,2,3
[/animation]

View File

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

View File

@@ -3,7 +3,7 @@ frame_height=16
[animation]
name=default
speed=8
speed=0.1333
loop=-1
frames=0,1,2,3,4,5,6
[/animation]

View File

@@ -26,6 +26,8 @@
"[GAME_TEXT] 6": "Temps!",
"[GAME_TEXT] 7": "Endavant!",
"[GAME_TEXT] 8": "1.000.000 de punts!",
"[GAME_TEXT] THANK_YOU": "Gracies!",
"[GAME_TEXT] NEW_RECORD": "Nou record!",
"[HIGHSCORE_TABLE] CAPTION": "Millors puntuacions",

View File

@@ -25,6 +25,8 @@
"[GAME_TEXT] 6": "Stop!",
"[GAME_TEXT] 7": "Get Ready!",
"[GAME_TEXT] 8": "1,000,000 points!",
"[GAME_TEXT] THANK_YOU": "Thank you!",
"[GAME_TEXT] NEW_RECORD": "New record!",
"[HIGHSCORE_TABLE] CAPTION": "Best scores",

View File

@@ -25,6 +25,8 @@
"[GAME_TEXT] 6": "Tiempo!",
"[GAME_TEXT] 7": "Adelante!",
"[GAME_TEXT] 8": "1.000.000 de puntos!",
"[GAME_TEXT] THANK_YOU": "Gracias!",
"[GAME_TEXT] NEW_RECORD": "Nuevo record!",
"[HIGHSCORE_TABLE] CAPTION": "Mejores puntuaciones",

Binary file not shown.

View File

@@ -1,234 +0,0 @@
/*
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

@@ -1,234 +0,0 @@
/*
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 / 256.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, 256.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

@@ -0,0 +1,157 @@
#version 330 core
// Configuración
#define SCANLINES
#define MULTISAMPLE
#define GAMMA
//#define FAKE_GAMMA
//#define CURVATURE
//#define SHARPER
#define MASK_TYPE 2
#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
// Inputs desde vertex shader
in vec2 vTexCoord;
in float vFilterWidth;
#if defined(CURVATURE)
in vec2 vScreenScale;
#endif
// Output
out vec4 FragColor;
// Uniforms
uniform sampler2D Texture;
uniform vec2 TextureSize;
#if defined(CURVATURE)
vec2 Distort(vec2 coord)
{
vec2 CURVATURE_DISTORTION = vec2(CURVATURE_X, CURVATURE_Y);
vec2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION);
coord *= vScreenScale;
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);
else
{
coord += vec2(0.5);
coord /= vScreenScale;
}
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 - vFilterWidth);
scanLineWeight += CalcScanLineWeight(dy + vFilterWidth);
scanLineWeight *= 0.3333333;
#endif
return scanLineWeight;
}
void main()
{
#if defined(CURVATURE)
vec2 texcoord = Distort(vTexCoord);
if (texcoord.x < 0.0) {
FragColor = vec4(0.0);
return;
}
#else
vec2 texcoord = vTexCoord;
#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 = texture(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
FragColor = vec4(colour, 1.0);
#elif MASK_TYPE == 1
float whichMask = fract(gl_FragCoord.x * 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);
FragColor = vec4(colour * mask, 1.0);
#elif MASK_TYPE == 2
float whichMask = fract(gl_FragCoord.x * 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;
FragColor = vec4(colour * mask, 1.0);
#endif
}

View File

@@ -0,0 +1,48 @@
#version 330 core
// Configuración
#define SCANLINES
#define MULTISAMPLE
#define GAMMA
//#define FAKE_GAMMA
//#define CURVATURE
//#define SHARPER
#define MASK_TYPE 2
#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
// Inputs (desde VAO)
layout(location = 0) in vec2 aPosition;
layout(location = 1) in vec2 aTexCoord;
// Outputs al fragment shader
out vec2 vTexCoord;
out float vFilterWidth;
#if defined(CURVATURE)
out vec2 vScreenScale;
#endif
// Uniforms
uniform vec2 TextureSize;
void main()
{
#if defined(CURVATURE)
vScreenScale = vec2(1.0, 1.0);
#endif
// Calcula filterWidth dinámicamente basándose en la altura de la textura
vFilterWidth = (768.0 / TextureSize.y) / 3.0;
// Pasar coordenadas de textura (invertir Y para SDL)
vTexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y) * 1.0001;
// Posición del vértice (ya en espacio de clip [-1, 1])
gl_Position = vec4(aPosition, 0.0, 1.0);
}

BIN
data/sound/bullet2p.wav Normal file

Binary file not shown.

BIN
data/sound/credit.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

43
development_guidelines.md Normal file
View File

@@ -0,0 +1,43 @@
# Directrices de Desarrollo - Coffee Crisis Arcade Edition
## Directrices Principales Confirmadas
### 1. **Sistema Temporal**
- **TODO migrado de frame based a time based**
- **Delta time en segundos (float)**
- **Unidades de tiempo: SOLO segundos** (no frames, no milisegundos)
### 2. **Contadores y Timers**
- **CRECIENTES**: para sistemas con múltiples eventos temporales (timeline)
- Patrón: `elapsed_time += deltaTime; if (elapsed_time >= EVENT_TIME) { /* acción */ }`
- **DECRECIENTES**: para contadores con diferentes valores de inicialización
- Patrón: `timer -= deltaTime; if (timer <= 0.0f) { /* acción */ timer = DURATION; }`
### 3. **Números Mágicos**
- **Definidos en constantes**
- **Preferencia**: cabecera de la clase
- **Excepción**: si es algo local a un método específico
## Problemas Pendientes de Reparación (game.cpp)
### ❌ PENDIENTES
1. **param.fade.post_duration_ms verification** (líneas 89, 1671)
2. **setRotateSpeed verification** (línea 797)
3. **TOTAL_DEMO_DATA - 200 magic number** (línea 1669)
4. **Comprehensive magic number search** - Buscar 100, 150, 200, 250, 300, 400, 500, 1000
### 4. **Velocidades y Aceleraciones**
- **Velocidades**: pixels/segundo
- **Aceleraciones**: pixels/segundo²
### 5. **Documentación de Conversiones**
- **Comentarios explicativos** en cambios críticos de timing
- Documentar conversiones frame→tiempo en el código
### 6. **Patrón de Constantes**
- Crear constantes para valores repetidos (evitar duplicación)
- Nombres descriptivos para constantes de tiempo
---
**Estado**: Directrices completas confirmadas

View File

@@ -0,0 +1,15 @@
#!/bin/bash
# 🏁 Ruta base del proyecto
BASE_DIR="/home/sergio/gitea/coffee_crisis_arcade_edition"
# 📁 Ruta al build
BUILD_DIR="$BASE_DIR/build"
# 📄 Archivo de mapping personalizado
MAPPING_FILE="$BASE_DIR/linux_utils/sdl3_mapping.imp"
# 📦 Generar compile_commands.json
echo "🔧 Generando compile_commands.json..."
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -S "$BASE_DIR" -B "$BUILD_DIR"

44
linux_utils/run_clang-tidy.sh Executable file
View File

@@ -0,0 +1,44 @@
#!/bin/bash
# Script para ejecutar clang-tidy en múltiples directorios
# Uso: ./run_clang-tidy.sh
# Lista de rutas donde ejecutar clang-tidy
PATHS=(
"/home/sergio/gitea/coffee_crisis_arcade_edition/source"
"/home/sergio/gitea/coffee_crisis_arcade_edition/source/sections"
"/home/sergio/gitea/coffee_crisis_arcade_edition/source/ui"
)
# Ruta del directorio build (relativa desde donde se ejecuta el script)
BUILD_DIR="/home/sergio/gitea/coffee_crisis_arcade_edition/build/"
# Función para procesar un directorio
process_directory() {
local dir="$1"
echo "=== Procesando directorio: $dir ==="
# Verificar que el directorio existe
if [[ ! -d "$dir" ]]; then
echo "Error: El directorio $dir no existe"
return 1
fi
# Cambiar al directorio y ejecutar find con -maxdepth 1 para un solo nivel
cd "$dir" || return 1
# Buscar archivos .cpp, .h, .hpp solo en el nivel actual (no subdirectorios)
find . -maxdepth 1 \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) | \
xargs -P4 -I{} bash -c 'echo "Procesando: {}"; clang-tidy {} -p '"$BUILD_DIR"' --fix'
echo "=== Completado: $dir ==="
echo
}
# Procesar cada directorio en la lista
for path in "${PATHS[@]}"; do
process_directory "$path"
done
echo "¡Proceso completado para todos los directorios!"

Binary file not shown.

150
release/create_icons.py Normal file
View File

@@ -0,0 +1,150 @@
#!/usr/bin/env python3
import os
import sys
import shutil
import subprocess
from pathlib import Path
def check_dependencies():
"""Verifica que ImageMagick esté instalado"""
try:
subprocess.run(['magick', '--version'], capture_output=True, check=True)
except (subprocess.CalledProcessError, FileNotFoundError):
print("Error: ImageMagick no está instalado o no se encuentra en el PATH")
print("Instala ImageMagick desde: https://imagemagick.org/script/download.php")
sys.exit(1)
# Verificar iconutil solo en macOS
if sys.platform == 'darwin':
try:
# iconutil no tiene --version, mejor usar which o probar con -h
result = subprocess.run(['which', 'iconutil'], capture_output=True, check=True)
if result.returncode == 0:
print("✓ iconutil disponible - se crearán archivos .ico e .icns")
except (subprocess.CalledProcessError, FileNotFoundError):
print("Error: iconutil no está disponible (solo funciona en macOS)")
print("Solo se creará el archivo .ico")
else:
print(" Sistema no-macOS detectado - solo se creará archivo .ico")
def create_icons(input_file):
"""Crea archivos .icns e .ico a partir de un PNG"""
# Verificar que el archivo existe
if not os.path.isfile(input_file):
print(f"Error: El archivo {input_file} no existe.")
return False
# Obtener información del archivo
file_path = Path(input_file)
file_dir = file_path.parent
file_name = file_path.stem # Nombre sin extensión
file_extension = file_path.suffix
if file_extension.lower() not in ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']:
print(f"Advertencia: {file_extension} puede no ser compatible. Se recomienda usar PNG.")
# Crear archivo .ico usando el método simplificado
ico_output = file_dir / f"{file_name}.ico"
try:
print(f"Creando {ico_output}...")
subprocess.run([
'magick', str(input_file),
'-define', 'icon:auto-resize=256,128,64,48,32,16',
str(ico_output)
], check=True)
print(f"✓ Archivo .ico creado: {ico_output}")
except subprocess.CalledProcessError as e:
print(f"Error creando archivo .ico: {e}")
return False
# Crear archivo .icns (solo en macOS)
if sys.platform == 'darwin':
try:
# Crear carpeta temporal para iconset
temp_folder = file_dir / "icon.iconset"
# Eliminar carpeta temporal si existe
if temp_folder.exists():
shutil.rmtree(temp_folder)
# Crear carpeta temporal
temp_folder.mkdir(parents=True)
# Definir los tamaños y nombres de archivo para .icns
icon_sizes = [
(16, "icon_16x16.png"),
(32, "icon_16x16@2x.png"),
(32, "icon_32x32.png"),
(64, "icon_32x32@2x.png"),
(128, "icon_128x128.png"),
(256, "icon_128x128@2x.png"),
(256, "icon_256x256.png"),
(512, "icon_256x256@2x.png"),
(512, "icon_512x512.png"),
(1024, "icon_512x512@2x.png")
]
print("Generando imágenes para .icns...")
# Crear cada tamaño de imagen
for size, output_name in icon_sizes:
output_path = temp_folder / output_name
subprocess.run([
'magick', str(input_file),
'-resize', f'{size}x{size}',
str(output_path)
], check=True)
# Crear archivo .icns usando iconutil
icns_output = file_dir / f"{file_name}.icns"
print(f"Creando {icns_output}...")
subprocess.run([
'iconutil', '-c', 'icns',
str(temp_folder),
'-o', str(icns_output)
], check=True)
# Limpiar carpeta temporal
if temp_folder.exists():
shutil.rmtree(temp_folder)
print(f"✓ Archivo .icns creado: {icns_output}")
except subprocess.CalledProcessError as e:
print(f"Error creando archivo .icns: {e}")
# Limpiar carpeta temporal en caso de error
if temp_folder.exists():
shutil.rmtree(temp_folder)
return False
else:
print(" Archivo .icns no creado (solo disponible en macOS)")
return True
def main():
"""Función principal"""
# Verificar argumentos
if len(sys.argv) != 2:
print(f"Uso: {sys.argv[0]} ARCHIVO")
print("Ejemplo: python3 create_icons.py imagen.png")
sys.exit(0)
input_file = sys.argv[1]
# Verificar dependencias
check_dependencies()
# Crear iconos
if create_icons(input_file):
print("\n✅ Proceso completado exitosamente")
else:
print("\n❌ El proceso falló")
sys.exit(1)
if __name__ == "__main__":
main()

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 438 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -9,22 +9,44 @@
#include <stdexcept> // Para runtime_error
#include <utility> // Para pair
#include "resource_helper.h" // Para ResourceHelper
#include "texture.h" // Para Texture
#include "utils.h" // Para printWithDots
// Carga las animaciones en un vector(Animations) desde un fichero
auto loadAnimationsFromFile(const std::string& file_path) -> AnimationsFileBuffer {
std::ifstream file(file_path);
// Intentar cargar desde ResourceHelper primero
auto resource_data = ResourceHelper::loadFile(file_path);
std::istringstream stream;
bool using_resource_data = false;
if (!resource_data.empty()) {
std::string content(resource_data.begin(), resource_data.end());
stream.str(content);
using_resource_data = true;
}
// Fallback a archivo directo
std::ifstream file;
if (!using_resource_data) {
file.open(file_path);
if (!file) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Fichero no encontrado %s", file_path.c_str());
throw std::runtime_error("Fichero no encontrado: " + file_path);
}
}
std::istream& input_stream = using_resource_data ? stream : static_cast<std::istream&>(file);
printWithDots("Animation : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]");
std::vector<std::string> buffer;
std::string line;
while (std::getline(file, line)) {
while (std::getline(input_stream, line)) {
// Eliminar caracteres de retorno de carro (\r) al final de la línea
if (!line.empty() && line.back() == '\r') {
line.pop_back();
}
if (!line.empty()) {
buffer.push_back(line);
}
@@ -35,7 +57,7 @@ auto loadAnimationsFromFile(const std::string& file_path) -> AnimationsFileBuffe
// Constructor
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string& file_path)
: MovingSprite(texture) {
: MovingSprite(std::move(texture)) {
// Carga las animaciones
if (!file_path.empty()) {
auto buffer = loadAnimationsFromFile(file_path);
@@ -45,14 +67,14 @@ AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::stri
// Constructor
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer& animations)
: MovingSprite(texture) {
: MovingSprite(std::move(texture)) {
if (!animations.empty()) {
loadFromAnimationsFileBuffer(animations);
}
}
// Obtiene el índice de la animación a partir del nombre
auto AnimatedSprite::getIndex(const std::string& name) -> int {
auto AnimatedSprite::getAnimationIndex(const std::string& name) -> int {
auto iterator = animation_indices_.find(name);
if (iterator != animation_indices_.end()) {
// Si se encuentra la animación en el mapa, devuelve su índice
@@ -64,33 +86,33 @@ auto AnimatedSprite::getIndex(const std::string& name) -> int {
return -1;
}
// Calcula el frame correspondiente a la animación
void AnimatedSprite::animate() {
// Calcula el frame correspondiente a la animación (time-based)
void AnimatedSprite::animate(float deltaTime) {
if (animations_[current_animation_].speed == 0 || animations_[current_animation_].paused) {
return;
}
// Calcula el frame actual a partir del contador
animations_[current_animation_].current_frame = animations_[current_animation_].counter / animations_[current_animation_].speed;
// Acumular tiempo transcurrido
animations_[current_animation_].time_accumulator += deltaTime;
// Si alcanza el final de la animación, reinicia el contador de la animación
// en función de la variable loop y coloca el nuevo frame
// Verificar si es momento de cambiar frame
if (animations_[current_animation_].time_accumulator >= animations_[current_animation_].speed) {
animations_[current_animation_].time_accumulator -= animations_[current_animation_].speed;
animations_[current_animation_].current_frame++;
// Si alcanza el final de la animación
if (animations_[current_animation_].current_frame >= animations_[current_animation_].frames.size()) {
if (animations_[current_animation_].loop == -1) { // Si no hay loop, deja el último frame
animations_[current_animation_].current_frame = animations_[current_animation_].frames.size();
animations_[current_animation_].current_frame = animations_[current_animation_].frames.size() - 1;
animations_[current_animation_].completed = true;
} else { // Si hay loop, vuelve al frame indicado
animations_[current_animation_].counter = 0;
animations_[current_animation_].time_accumulator = 0.0f;
animations_[current_animation_].current_frame = animations_[current_animation_].loop;
}
}
// En caso contrario
else {
// Escoge el frame correspondiente de la animación
updateSpriteClip();
// Incrementa el contador de la animacion
animations_[current_animation_].counter++;
// Actualizar el sprite clip
updateSpriteClip();
}
}
@@ -101,17 +123,17 @@ auto AnimatedSprite::animationIsCompleted() -> bool {
// Establece la animacion actual
void AnimatedSprite::setCurrentAnimation(const std::string& name, bool reset) {
const auto NEW_ANIMATION = getIndex(name);
const auto NEW_ANIMATION = getAnimationIndex(name);
if (current_animation_ != NEW_ANIMATION) {
const auto OLD_ANIMATION = current_animation_;
current_animation_ = NEW_ANIMATION;
if (reset) {
animations_[current_animation_].current_frame = 0;
animations_[current_animation_].counter = 0;
animations_[current_animation_].time_accumulator = 0.0f;
animations_[current_animation_].completed = false;
} else {
animations_[current_animation_].current_frame = std::min(animations_[OLD_ANIMATION].current_frame, animations_[current_animation_].frames.size() - 1);
animations_[current_animation_].counter = animations_[OLD_ANIMATION].counter;
animations_[current_animation_].time_accumulator = animations_[OLD_ANIMATION].time_accumulator;
animations_[current_animation_].completed = animations_[OLD_ANIMATION].completed;
}
updateSpriteClip();
@@ -126,27 +148,27 @@ void AnimatedSprite::setCurrentAnimation(int index, bool reset) {
current_animation_ = NEW_ANIMATION;
if (reset) {
animations_[current_animation_].current_frame = 0;
animations_[current_animation_].counter = 0;
animations_[current_animation_].time_accumulator = 0.0f;
animations_[current_animation_].completed = false;
} else {
animations_[current_animation_].current_frame = std::min(animations_[OLD_ANIMATION].current_frame, animations_[current_animation_].frames.size());
animations_[current_animation_].counter = animations_[OLD_ANIMATION].counter;
animations_[current_animation_].time_accumulator = animations_[OLD_ANIMATION].time_accumulator;
animations_[current_animation_].completed = animations_[OLD_ANIMATION].completed;
}
updateSpriteClip();
}
}
// Actualiza las variables del objeto
void AnimatedSprite::update() {
animate();
MovingSprite::update();
// Actualiza las variables del objeto (time-based)
void AnimatedSprite::update(float deltaTime) {
animate(deltaTime);
MovingSprite::update(deltaTime);
}
// Reinicia la animación
void AnimatedSprite::resetAnimation() {
animations_[current_animation_].current_frame = 0;
animations_[current_animation_].counter = 0;
animations_[current_animation_].time_accumulator = 0.0f;
animations_[current_animation_].completed = false;
animations_[current_animation_].paused = false;
updateSpriteClip();
@@ -172,11 +194,17 @@ void AnimatedSprite::loadFromAnimationsFileBuffer(const AnimationsFileBuffer& so
// Pone un valor por defecto
setWidth(config.frame_width);
setHeight(config.frame_height);
// Establece el primer frame inmediatamente si hay animaciones
if (!animations_.empty()) {
current_animation_ = 0;
updateSpriteClip();
}
}
// Procesa una línea de configuración
void AnimatedSprite::processConfigLine(const std::string& line, AnimationConfig& config) {
size_t pos = line.find("=");
size_t pos = line.find('=');
if (pos == std::string::npos) {
return;
}
@@ -230,7 +258,7 @@ auto AnimatedSprite::processAnimationBlock(const AnimationsFileBuffer& source, s
// Procesa un parámetro individual de animación
void AnimatedSprite::processAnimationParameter(const std::string& line, Animation& animation, const AnimationConfig& config) {
size_t pos = line.find("=");
size_t pos = line.find('=');
if (pos == std::string::npos) {
return;
}
@@ -241,7 +269,7 @@ void AnimatedSprite::processAnimationParameter(const std::string& line, Animatio
if (key == "name") {
animation.name = value;
} else if (key == "speed") {
animation.speed = std::stoi(value);
animation.speed = std::stof(value);
} else if (key == "loop") {
animation.loop = std::stoi(value);
} else if (key == "frames") {
@@ -268,7 +296,7 @@ void AnimatedSprite::parseFramesParameter(const std::string& frames_str, Animati
}
// Establece la velocidad de la animación
void AnimatedSprite::setAnimationSpeed(size_t value) {
void AnimatedSprite::setAnimationSpeed(float value) {
animations_[current_animation_].speed = value;
}

View File

@@ -7,6 +7,7 @@
#include <memory> // Para allocator, shared_ptr
#include <string> // Para string, hash
#include <unordered_map> // Para unordered_map
#include <utility>
#include <vector> // Para vector
#include "moving_sprite.h" // Para MovingSprite
@@ -14,17 +15,17 @@
// Declaración adelantada
class Texture;
// Estructura de Animación
// --- Estructuras ---
struct Animation {
static constexpr int DEFAULT_SPEED = 5;
static constexpr float DEFAULT_SPEED = 80.0F;
std::string name; // Nombre de la animación
std::vector<SDL_FRect> frames; // Frames que componen la animación
int speed{DEFAULT_SPEED}; // Velocidad de reproducción
float speed{DEFAULT_SPEED}; // Velocidad de reproducción (ms entre frames)
int loop{0}; // Frame de vuelta al terminar (-1 para no repetir)
bool completed{false}; // Indica si la animación ha finalizado
size_t current_frame{0}; // Frame actual en reproducción
int counter{0}; // Contador para la animación
float time_accumulator{0.0f}; // Acumulador de tiempo para animaciones time-based
bool paused{false}; // La animación no avanza
Animation() = default;
@@ -37,47 +38,47 @@ struct AnimationConfig {
int max_tiles = 1;
};
// Alias de tipo para buffer de animaciones
using AnimationsFileBuffer = std::vector<std::string>;
// --- Tipos ---
using AnimationsFileBuffer = std::vector<std::string>; // Buffer de animaciones
// Carga las animaciones desde un fichero en un vector de strings
auto loadAnimationsFromFile(const std::string& file_path) -> AnimationsFileBuffer;
// --- Funciones ---
auto loadAnimationsFromFile(const std::string& file_path) -> AnimationsFileBuffer; // Carga las animaciones desde un fichero
// Clase AnimatedSprite: Sprite animado que hereda de MovingSprite
// --- Clase AnimatedSprite: sprite animado que hereda de MovingSprite ---
class AnimatedSprite : public MovingSprite {
public:
// --- Constructores y destructor ---
AnimatedSprite(std::shared_ptr<Texture> texture, const std::string& file_path);
AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer& animations);
explicit AnimatedSprite(std::shared_ptr<Texture> texture) : MovingSprite(texture) {}
explicit AnimatedSprite(std::shared_ptr<Texture> texture)
: MovingSprite(std::move(texture)) {}
~AnimatedSprite() override = default;
// --- Métodos principales ---
void update() override; // Actualiza la animación
void update(float deltaTime) override; // Actualiza la animación (time-based)
// --- Control de animaciones ---
void setCurrentAnimation(const std::string& name = "default", bool reset = true); // Establece la animación por nombre
void setCurrentAnimation(int index = 0, bool reset = true); // Establece la animación por índice
void resetAnimation(); // Reinicia la animación actual
void setAnimationSpeed(size_t value); // Establece la velocidad de la animación
auto getAnimationSpeed() const -> size_t { return animations_[current_animation_].speed; } // Obtiene la velocidad de la animación actual
void setAnimationSpeed(float value); // Establece la velocidad de la animación
auto getAnimationSpeed() const -> float { return animations_[current_animation_].speed; } // Obtiene la velocidad de la animación actual
void animtionPause() { animations_[current_animation_].paused = true; } // Detiene la animación
void animationResume() { animations_[current_animation_].paused = false; } // Reanuda la animación
auto getCurrentAnimationFrame() const -> size_t { return animations_[current_animation_].current_frame; } // Obtiene el numero de frame de la animación actual
// --- Consultas ---
auto animationIsCompleted() -> bool; // Comprueba si la animación ha terminado
auto getIndex(const std::string& name) -> int; // Obtiene el índice de una animación por nombre
auto getAnimationIndex(const std::string& name) -> int; // Obtiene el índice de una animación por nombre
protected:
// --- Datos de animación ---
// --- Variables de estado ---
std::vector<Animation> animations_; // Vector de animaciones disponibles
std::unordered_map<std::string, int> animation_indices_; // Mapa para búsqueda rápida por nombre
int current_animation_ = 0; // Índice de la animación activa
// --- Mapa para búsqueda rápida de animaciones por nombre ---
std::unordered_map<std::string, int> animation_indices_;
// --- Métodos internos ---
void animate(); // Calcula el frame correspondiente a la animación
void animate(float deltaTime); // Calcula el frame correspondiente a la animación (time-based)
void loadFromAnimationsFileBuffer(const AnimationsFileBuffer& source); // Carga la animación desde un vector de cadenas
void processConfigLine(const std::string& line, AnimationConfig& config); // Procesa una línea de configuración
void updateFrameCalculations(AnimationConfig& config); // Actualiza los cálculos basados en las dimensiones del frame

View File

@@ -2,12 +2,15 @@
#include <SDL3/SDL.h> // Para SDL_LogCategory, SDL_LogInfo, SDL_LogError, SDL_LogWarn
#include <algorithm> // Para std::sort
#include <cstddef> // Para size_t
#include <exception> // Para exception
#include <filesystem> // Para std::filesystem
#include <fstream> // Para basic_istream, basic_ifstream, ifstream, istringstream
#include <sstream> // Para basic_istringstream
#include <stdexcept> // Para runtime_error
#include "resource_helper.h" // Para ResourceHelper
#include "utils.h" // Para getFileName
// Singleton
@@ -92,7 +95,7 @@ void Asset::loadFromFile(const std::string &config_file_path, const std::string
}
try {
std::string type_str = parts[0];
const std::string &type_str = parts[0];
std::string path = parts[1];
// Valores por defecto
@@ -139,6 +142,17 @@ auto Asset::get(const std::string &filename) const -> std::string {
return "";
}
// Carga datos del archivo usando ResourceHelper
auto Asset::loadData(const std::string &filename) const -> std::vector<uint8_t> {
auto it = file_list_.find(filename);
if (it != file_list_.end()) {
return ResourceHelper::loadFile(it->second.file);
}
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: file %s not found for data loading", filename.c_str());
return {};
}
// Verifica si un recurso existe
auto Asset::exists(const std::string &filename) const -> bool {
return file_list_.find(filename) != file_list_.end();
@@ -193,18 +207,28 @@ auto Asset::check() const -> bool {
}
// Comprueba que existe un fichero
auto Asset::checkFile(const std::string &path) -> bool {
auto Asset::checkFile(const std::string &path) const -> bool {
// Construir ruta del pack usando executable_path_
std::string pack_path = executable_path_ + "resources.pack";
bool pack_exists = std::filesystem::exists(pack_path);
if (pack_exists) {
// MODO PACK: Usar ResourceHelper (igual que la carga real)
auto data = ResourceHelper::loadFile(path);
return !data.empty();
} else {
// MODO FILESYSTEM: Verificación directa (modo desarrollo)
std::ifstream file(path);
bool success = file.good();
file.close();
if (!success) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Checking file: %s [ ERROR ]",
getFileName(path).c_str());
"Error: Could not open file: %s", path.c_str());
}
return success;
}
}
// Parsea string a Type
@@ -276,6 +300,9 @@ auto Asset::getListByType(Type type) const -> std::vector<std::string> {
}
}
// Ordenar alfabéticamente para garantizar orden consistente
std::sort(list.begin(), list.end());
return list;
}

View File

@@ -1,25 +1,26 @@
#pragma once
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <cstdint> // Para uint8_t
#include <string> // Para string
#include <unordered_map> // Para unordered_map
#include <utility> // Para move
#include <vector> // Para vector
// Clase Asset: gestor optimizado de recursos (singleton)
// --- Clase Asset: gestor optimizado de recursos (singleton) ---
class Asset {
public:
// Tipos de recursos
// --- Enums ---
enum class Type : int {
BITMAP,
MUSIC,
SOUND,
FONT,
LANG,
DATA,
DEMODATA,
ANIMATION,
PALETTE,
SIZE,
BITMAP, // Imágenes
MUSIC, // Música
SOUND, // Sonidos
FONT, // Fuentes
LANG, // Idiomas
DATA, // Datos
DEMODATA, // Datos de demo
ANIMATION, // Animaciones
PALETTE, // Paletas
SIZE, // Tamaño
};
// --- Métodos de singleton ---
@@ -33,37 +34,41 @@ class Asset {
void add(const std::string &file_path, Type type, bool required = true, bool absolute = false);
void loadFromFile(const std::string &config_file_path, const std::string &prefix = "", const std::string &system_folder = ""); // Con soporte para variables
[[nodiscard]] auto get(const std::string &filename) const -> std::string; // Mantener nombre original
[[nodiscard]] auto loadData(const std::string &filename) const -> std::vector<uint8_t>; // Carga datos del archivo
[[nodiscard]] auto check() const -> bool;
[[nodiscard]] auto getListByType(Type type) const -> std::vector<std::string>;
[[nodiscard]] auto exists(const std::string &filename) const -> bool; // Nueva función para verificar existencia
private:
// --- Estructura interna para almacenar información de cada recurso ---
// --- Estructuras privadas ---
struct Item {
std::string file; // Ruta completa del archivo (mantener nombre original)
std::string file; // Ruta completa del archivo
Type type; // Tipo de recurso
bool required; // Indica si el archivo es obligatorio
Item(std::string path, Type asset_type, bool is_required)
: file(std::move(path)), type(asset_type), required(is_required) {}
: file(std::move(path)),
type(asset_type),
required(is_required) {}
};
// --- Variables internas ---
std::unordered_map<std::string, Item> file_list_; // Mapa para búsqueda O(1) (mantener nombre original)
std::unordered_map<std::string, Item> file_list_; // Mapa para búsqueda O(1)
std::string executable_path_; // Ruta del ejecutable
// --- Métodos internos ---
[[nodiscard]] static auto checkFile(const std::string &path) -> bool;
[[nodiscard]] static auto getTypeName(Type type) -> std::string;
[[nodiscard]] static auto parseAssetType(const std::string &type_str) -> Type;
void addToMap(const std::string &file_path, Type type, bool required, bool absolute);
[[nodiscard]] static auto replaceVariables(const std::string &path, const std::string &prefix, const std::string &system_folder) -> std::string;
static auto parseOptions(const std::string &options, bool &required, bool &absolute) -> void;
[[nodiscard]] auto checkFile(const std::string &path) const -> bool; // Verifica si un archivo existe
[[nodiscard]] static auto getTypeName(Type type) -> std::string; // Obtiene el nombre del tipo
[[nodiscard]] static auto parseAssetType(const std::string &type_str) -> Type; // Convierte string a tipo
void addToMap(const std::string &file_path, Type type, bool required, bool absolute); // Añade archivo al mapa
[[nodiscard]] static auto replaceVariables(const std::string &path, const std::string &prefix, const std::string &system_folder) -> std::string; // Reemplaza variables en la ruta
static auto parseOptions(const std::string &options, bool &required, bool &absolute) -> void; // Parsea opciones
// --- Patrón Singleton ---
explicit Asset(std::string executable_path)
// --- Constructores y destructor privados (singleton) ---
explicit Asset(std::string executable_path) // Constructor privado
: executable_path_(std::move(executable_path)) {}
~Asset() = default;
~Asset() = default; // Destructor privado
static Asset *instance;
// --- Instancia singleton ---
static Asset *instance; // Instancia única de Asset
};

106
source/asset_integrated.cpp Normal file
View File

@@ -0,0 +1,106 @@
#include "asset_integrated.h"
#include <filesystem>
#include <fstream>
#include <iostream>
bool AssetIntegrated::resource_pack_enabled_ = false;
void AssetIntegrated::initWithResourcePack(const std::string &executable_path,
const std::string &resource_pack_path) {
// Inicializar Asset normal
Asset::init(executable_path);
// Inicializar ResourceLoader
auto &loader = ResourceLoader::getInstance();
if (loader.initialize(resource_pack_path, true)) {
resource_pack_enabled_ = true;
std::cout << "Asset system initialized with resource pack: " << resource_pack_path << std::endl;
} else {
resource_pack_enabled_ = false;
std::cout << "Asset system initialized in fallback mode (filesystem)" << std::endl;
}
}
std::vector<uint8_t> AssetIntegrated::loadFile(const std::string &filename) {
if (shouldUseResourcePack(filename) && resource_pack_enabled_) {
// Intentar cargar del pack de recursos
auto &loader = ResourceLoader::getInstance();
// Convertir ruta completa a ruta relativa para el pack
std::string relativePath = filename;
// Si la ruta contiene "data/", extraer la parte relativa
size_t dataPos = filename.find("data/");
if (dataPos != std::string::npos) {
relativePath = filename.substr(dataPos + 5); // +5 para saltar "data/"
}
auto data = loader.loadResource(relativePath);
if (!data.empty()) {
return data;
}
}
// Fallback: cargar del filesystem
std::ifstream file(filename, std::ios::binary | std::ios::ate);
if (!file) {
std::cerr << "Error: Could not open file: " << filename << std::endl;
return {};
}
std::streamsize fileSize = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<uint8_t> data(fileSize);
if (!file.read(reinterpret_cast<char *>(data.data()), fileSize)) {
std::cerr << "Error: Could not read file: " << filename << std::endl;
return {};
}
return data;
}
bool AssetIntegrated::fileExists(const std::string &filename) const {
if (shouldUseResourcePack(filename) && resource_pack_enabled_) {
auto &loader = ResourceLoader::getInstance();
// Convertir ruta completa a ruta relativa para el pack
std::string relativePath = filename;
size_t dataPos = filename.find("data/");
if (dataPos != std::string::npos) {
relativePath = filename.substr(dataPos + 5);
}
if (loader.resourceExists(relativePath)) {
return true;
}
}
// Verificar en filesystem
return std::filesystem::exists(filename);
}
std::string AssetIntegrated::getSystemPath(const std::string &filename) const {
// Los archivos de sistema/config siempre van al filesystem
return filename;
}
bool AssetIntegrated::shouldUseResourcePack(const std::string &filepath) const {
// Los archivos que NO van al pack:
// - Archivos de config/ (ahora están fuera de data/)
// - Archivos con absolute=true en assets.txt
// - Archivos de sistema (${SYSTEM_FOLDER})
if (filepath.find("/config/") != std::string::npos ||
filepath.find("config/") == 0) {
return false;
}
if (filepath.find("/data/") != std::string::npos ||
filepath.find("data/") == 0) {
return true;
}
return false;
}

29
source/asset_integrated.h Normal file
View File

@@ -0,0 +1,29 @@
#pragma once
#include <memory>
#include "asset.h"
#include "resource_loader.h"
// Extensión de Asset que integra ResourceLoader
class AssetIntegrated : public Asset {
public:
// Inicializa Asset con ResourceLoader
static void initWithResourcePack(const std::string &executable_path,
const std::string &resource_pack_path = "resources.pack");
// Carga un archivo usando ResourceLoader como primera opción
std::vector<uint8_t> loadFile(const std::string &filename);
// Verifica si un archivo existe (pack o filesystem)
bool fileExists(const std::string &filename) const;
// Obtiene la ruta completa para archivos del sistema/config
std::string getSystemPath(const std::string &filename) const;
private:
static bool resource_pack_enabled_;
// Determina si un archivo debe cargarse del pack o del filesystem
bool shouldUseResourcePack(const std::string &filepath) const;
};

View File

@@ -4,9 +4,7 @@
#include <algorithm> // Para clamp
#ifndef NO_AUDIO
#include "external/jail_audio.h" // Para JA_FadeOutMusic, JA_Init, JA_PauseM...
#endif
#include "options.h" // Para AudioOptions, audio, MusicOptions
#include "resource.h" // Para Resource
@@ -27,9 +25,7 @@ Audio::Audio() { initSDLAudio(); }
// Destructor
Audio::~Audio() {
#ifndef NO_AUDIO
JA_Quit();
#endif
}
// Método principal
@@ -43,9 +39,7 @@ void Audio::playMusic(const std::string &name, const int loop) {
music_.loop = (loop != 0);
if (music_enabled_ && music_.state != MusicState::PLAYING) {
#ifndef NO_AUDIO
JA_PlayMusic(Resource::get()->getMusic(name), loop);
#endif
music_.state = MusicState::PLAYING;
}
}
@@ -53,9 +47,7 @@ void Audio::playMusic(const std::string &name, const int loop) {
// Pausa la música
void Audio::pauseMusic() {
if (music_enabled_ && music_.state == MusicState::PLAYING) {
#ifndef NO_AUDIO
JA_PauseMusic();
#endif
music_.state = MusicState::PAUSED;
}
}
@@ -63,9 +55,7 @@ void Audio::pauseMusic() {
// Continua la música pausada
void Audio::resumeMusic() {
if (music_enabled_ && music_.state == MusicState::PAUSED) {
#ifndef NO_AUDIO
JA_ResumeMusic();
#endif
music_.state = MusicState::PLAYING;
}
}
@@ -73,9 +63,7 @@ void Audio::resumeMusic() {
// Detiene la música
void Audio::stopMusic() {
if (music_enabled_) {
#ifndef NO_AUDIO
JA_StopMusic();
#endif
music_.state = MusicState::STOPPED;
}
}
@@ -83,27 +71,37 @@ void Audio::stopMusic() {
// Reproduce un sonido
void Audio::playSound(const std::string &name, Group group) const {
if (sound_enabled_) {
#ifndef NO_AUDIO
JA_PlaySound(Resource::get()->getSound(name), 0, static_cast<int>(group));
#endif
}
}
// Detiene todos los sonidos
void Audio::stopAllSounds() const {
if (sound_enabled_) {
#ifndef NO_AUDIO
JA_StopChannel(-1);
#endif
}
}
// Realiza un fundido de salida de la música
void Audio::fadeOutMusic(int milliseconds) const {
if (music_enabled_) {
#ifndef NO_AUDIO
if (music_enabled_ && getRealMusicState() == MusicState::PLAYING) {
JA_FadeOutMusic(milliseconds);
#endif
}
}
// Consulta directamente el estado real de la música en jailaudio
auto Audio::getRealMusicState() const -> MusicState {
JA_Music_state ja_state = JA_GetMusicState();
switch (ja_state) {
case JA_MUSIC_PLAYING:
return MusicState::PLAYING;
case JA_MUSIC_PAUSED:
return MusicState::PAUSED;
case JA_MUSIC_STOPPED:
case JA_MUSIC_INVALID:
case JA_MUSIC_DISABLED:
default:
return MusicState::STOPPED;
}
}
@@ -111,10 +109,8 @@ void Audio::fadeOutMusic(int milliseconds) const {
void Audio::setSoundVolume(int sound_volume, Group group) const {
if (sound_enabled_) {
sound_volume = std::clamp(sound_volume, MIN_VOLUME, MAX_VOLUME);
#ifndef NO_AUDIO
const float CONVERTED_VOLUME = (sound_volume / 100.0F) * (Options::audio.volume / 100.0F);
JA_SetSoundVolume(CONVERTED_VOLUME, static_cast<int>(group));
#endif
}
}
@@ -122,10 +118,8 @@ void Audio::setSoundVolume(int sound_volume, Group group) const {
void Audio::setMusicVolume(int music_volume) const {
if (music_enabled_) {
music_volume = std::clamp(music_volume, MIN_VOLUME, MAX_VOLUME);
#ifndef NO_AUDIO
const float CONVERTED_VOLUME = (music_volume / 100.0F) * (Options::audio.volume / 100.0F);
JA_SetMusicVolume(CONVERTED_VOLUME);
#endif
}
}
@@ -144,7 +138,6 @@ void Audio::enable(bool value) {
// Inicializa SDL Audio
void Audio::initSDLAudio() {
#ifndef NO_AUDIO
if (!SDL_Init(SDL_INIT_AUDIO)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_AUDIO could not initialize! SDL Error: %s", SDL_GetError());
} else {
@@ -153,7 +146,4 @@ void Audio::initSDLAudio() {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "** Audio system initialized successfully");
}
#else
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "** Audio system disabled");
#endif
}

View File

@@ -3,19 +3,26 @@
#include <string> // Para string
#include <utility> // Para move
// Clase Audio: gestor de audio (singleton)
// --- Clase Audio: gestor de audio (singleton) ---
class Audio {
public:
// --- Enums ---
enum class Group : int {
ALL = -1,
GAME = 0,
INTERFACE = 1
ALL = -1, // Todos los grupos
GAME = 0, // Sonidos del juego
INTERFACE = 1 // Sonidos de la interfaz
};
enum class MusicState {
PLAYING, // Reproduciendo música
PAUSED, // Música pausada
STOPPED, // Música detenida
};
// --- Constantes ---
static constexpr int MAX_VOLUME = 100;
static constexpr int MIN_VOLUME = 0;
static constexpr int FREQUENCY = 48000;
static constexpr int MAX_VOLUME = 100; // Volumen máximo
static constexpr int MIN_VOLUME = 0; // Volumen mínimo
static constexpr int FREQUENCY = 48000; // Frecuencia de audio
// --- Métodos de singleton ---
static void init(); // Inicializa el objeto Audio
@@ -59,40 +66,46 @@ class Audio {
void setSoundVolume(int volume, Group group = Group::ALL) const; // Ajustar volumen de efectos
void setMusicVolume(int volume) const; // Ajustar volumen de música
private:
enum class MusicState {
PLAYING,
PAUSED,
STOPPED,
};
// --- Getters para debug ---
bool isEnabled() const { return enabled_; }
bool isSoundEnabled() const { return sound_enabled_; }
bool isMusicEnabled() const { return music_enabled_; }
MusicState getMusicState() const { return music_.state; }
MusicState getRealMusicState() const; // Consulta directamente a jailaudio
const std::string& getCurrentMusicName() const { return music_.name; }
private:
// --- Estructuras privadas ---
struct Music {
MusicState state; // Estado actual de la música (reproduciendo, detenido, en pausa)
std::string name; // Última pista de música reproducida
bool loop; // Indica si la última pista de música se debe reproducir en bucle
// Constructor para inicializar la música con valores predeterminados
Music() : state(MusicState::STOPPED), loop(false) {}
Music()
: state(MusicState::STOPPED),
loop(false) {}
// Constructor para inicializar con valores específicos
Music(MusicState init_state, std::string init_name, bool init_loop)
: state(init_state), name(std::move(init_name)), loop(init_loop) {}
: state(init_state),
name(std::move(init_name)),
loop(init_loop) {}
};
Music music_;
// --- Variables de Estado ---
// --- Variables de estado ---
Music music_; // Estado de la música
bool enabled_ = true; // Estado general del audio
bool sound_enabled_ = true; // Estado de los efectos de sonido
bool music_enabled_ = true; // Estado de la música
// --- Inicializa SDL Audio ---
void initSDLAudio();
// --- Métodos internos ---
void initSDLAudio(); // Inicializa SDL Audio
// --- Patrón Singleton ---
// --- Constructores y destructor privados (singleton) ---
Audio(); // Constructor privado
~Audio(); // Destructor privado
// --- Singleton ---
static Audio *instance;
// --- Instancia singleton ---
static Audio *instance; // Instancia única de Audio
};

View File

@@ -5,6 +5,7 @@
#include <algorithm> // Para clamp, max
#include <cmath> // Para M_PI, cos, sin
#include <utility>
#include "moving_sprite.h" // Para MovingSprite
#include "param.h" // Para Param, ParamBackground, param
@@ -12,9 +13,10 @@
#include "screen.h" // Para Screen
#include "sprite.h" // Para Sprite
#include "texture.h" // Para Texture
#include "utils.h" // Para funciones de easing
// Constructor
Background::Background()
Background::Background(float total_progress_to_complete)
: renderer_(Screen::get()->getRenderer()),
buildings_texture_(Resource::get()->getTexture("game_buildings.png")),
@@ -25,36 +27,56 @@ Background::Background()
sun_texture_(Resource::get()->getTexture("game_sun.png")),
moon_texture_(Resource::get()->getTexture("game_moon.png")),
rect_(SDL_FRect{0, 0, static_cast<float>(gradients_texture_->getWidth() / 2), static_cast<float>(gradients_texture_->getHeight() / 2)}),
src_rect_({0, 0, 320, 240}),
dst_rect_({0, 0, 320, 240}),
base_(rect_.h),
attenuate_color_(Color(param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b)),
alpha_color_text_(param.background.attenuate_color.a),
alpha_color_text_temp_(param.background.attenuate_color.a)
total_progress_to_complete_(total_progress_to_complete),
progress_per_stage_(total_progress_to_complete_ / STAGES),
sun_completion_progress_(total_progress_to_complete_ * SUN_COMPLETION_FACTOR),
minimum_completed_progress_(total_progress_to_complete_ * MINIMUM_COMPLETED_PROGRESS_PERCENTAGE),
{
// Precalcula rutas
rect_(SDL_FRect{0, 0, static_cast<float>(gradients_texture_->getWidth() / 2), static_cast<float>(gradients_texture_->getHeight() / 2)}),
src_rect_({.x = 0, .y = 0, .w = 320, .h = 240}),
dst_rect_({.x = 0, .y = 0, .w = 320, .h = 240}),
attenuate_color_(Color(param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b)),
alpha_color_texture_(param.background.attenuate_color.a),
previous_alpha_color_texture_(param.background.attenuate_color.a),
base_(rect_.h) {
initializePaths();
initializeRects();
initializeSprites();
initializeSpriteProperties();
initializeTextures();
}
// Destructor
Background::~Background() {
SDL_DestroyTexture(canvas_);
SDL_DestroyTexture(color_texture_);
}
// Inicializa las rutas del sol y la luna
void Background::initializePaths() {
createSunPath();
createMoonPath();
}
// Inicializa variables
{
gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h};
gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h};
gradient_rect_[3] = {rect_.w, rect_.h, rect_.w, rect_.h};
// Inicializa los rectángulos de gradientes y nubes
void Background::initializeRects() {
gradient_rect_[0] = {.x = 0, .y = 0, .w = rect_.w, .h = rect_.h};
gradient_rect_[1] = {.x = rect_.w, .y = 0, .w = rect_.w, .h = rect_.h};
gradient_rect_[2] = {.x = 0, .y = rect_.h, .w = rect_.w, .h = rect_.h};
gradient_rect_[3] = {.x = rect_.w, .y = rect_.h, .w = rect_.w, .h = rect_.h};
const float TOP_CLOUDS_TEXTURE_HEIGHT = top_clouds_texture_->getHeight() / 4;
const float BOTTOM_CLOUDS_TEXTURE_HEIGHT = bottom_clouds_texture_->getHeight() / 4;
for (int i = 0; i < 4; ++i) {
top_clouds_rect_[i] = {0, i * TOP_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(top_clouds_texture_->getWidth()), TOP_CLOUDS_TEXTURE_HEIGHT};
bottom_clouds_rect_[i] = {0, i * BOTTOM_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(bottom_clouds_texture_->getWidth()), BOTTOM_CLOUDS_TEXTURE_HEIGHT};
}
}
// Crea los sprites
{
for (int i = 0; i < 4; ++i) {
top_clouds_rect_[i] = {.x = 0, .y = i * TOP_CLOUDS_TEXTURE_HEIGHT, .w = static_cast<float>(top_clouds_texture_->getWidth()), .h = TOP_CLOUDS_TEXTURE_HEIGHT};
bottom_clouds_rect_[i] = {.x = 0, .y = i * BOTTOM_CLOUDS_TEXTURE_HEIGHT, .w = static_cast<float>(bottom_clouds_texture_->getWidth()), .h = BOTTOM_CLOUDS_TEXTURE_HEIGHT};
}
}
// Crea los sprites
void Background::initializeSprites() {
const float TOP_CLOUDS_Y = base_ - 165;
const float BOTTOM_CLOUDS_Y = base_ - 101;
@@ -69,73 +91,280 @@ Background::Background()
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
{
constexpr float TOP_CLOUDS_SPEED = 0.1F;
constexpr float BOTTOM_CLOUDS_SPEED = 0.05F;
// Configura las propiedades iniciales de los sprites
void Background::initializeSpriteProperties() {
// Velocidades iniciales que coinciden con updateCloudsSpeed() cuando progress=0
constexpr float INITIAL_TOP_CLOUDS_SPEED_PX_PER_S = 0.05F * 60.0F; // 3.0 píxeles/segundo (coincide con CLOUDS_INITIAL_SPEED)
constexpr float INITIAL_BOTTOM_CLOUDS_SPEED_PX_PER_S = 0.05F * 60.0F / 2.0F; // 1.5 píxeles/segundo (mitad de velocidad)
top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
top_clouds_sprite_a_->setVelX(-TOP_CLOUDS_SPEED);
top_clouds_sprite_a_->setVelX(-INITIAL_TOP_CLOUDS_SPEED_PX_PER_S);
top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
top_clouds_sprite_b_->setVelX(-TOP_CLOUDS_SPEED);
top_clouds_sprite_b_->setVelX(-INITIAL_TOP_CLOUDS_SPEED_PX_PER_S);
bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottom_clouds_sprite_a_->setVelX(-BOTTOM_CLOUDS_SPEED);
bottom_clouds_sprite_a_->setVelX(-INITIAL_BOTTOM_CLOUDS_SPEED_PX_PER_S);
bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottom_clouds_sprite_b_->setVelX(-BOTTOM_CLOUDS_SPEED);
bottom_clouds_sprite_b_->setVelX(-INITIAL_BOTTOM_CLOUDS_SPEED_PX_PER_S);
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
// Inicializa las texturas de renderizado
void Background::initializeTextures() {
canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(canvas_, SDL_BLENDMODE_BLEND);
// Crea la textura para atenuar el fondo
color_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND);
setColor(attenuate_color_);
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_);
}
// Destructor
Background::~Background() {
SDL_DestroyTexture(canvas_);
SDL_DestroyTexture(color_texture_);
SDL_SetTextureAlphaMod(color_texture_, alpha_color_texture_);
}
// Actualiza la lógica del objeto
void Background::update() {
// Actualiza el valor de alpha_
void Background::update(float delta_time) {
// Actualiza la progresión y calcula transiciones
if (!manual_mode_) {
updateProgression(delta_time);
}
// Actualiza el valor de alpha
updateAlphaColorTexture();
// Actualiza las nubes
updateClouds();
updateClouds(delta_time);
// Calcula el frame de la hierba
grass_sprite_->setSpriteClip(0, (10 * (counter_ / 20 % 2)), 320, 10);
// Actualiza timer de hierba
grass_timer_ += delta_time;
// Calcula el valor de alpha_
// Calcula el frame de la hierba (alterna cada GRASS_FRAME_DURATION ms)
int grass_frame = static_cast<int>(grass_timer_ / GRASS_FRAME_DURATION) % 2;
grass_sprite_->setSpriteClip(0, (10 * grass_frame), 320, 10);
// Calcula el valor de alpha
alpha_ = std::max((255 - (int)(255 * transition_)), 0);
// Mueve el sol
// Mueve el sol y la luna según la progresión
sun_sprite_->setPosition(sun_path_.at(sun_index_));
moon_sprite_->setPosition(moon_path_.at(moon_index_));
// Incrementa el contador
++counter_;
// Compone todos los elementos del fondo en la textura
fillCanvas();
}
// Incrementa la progresión interna
void Background::incrementProgress(float amount) {
if (state_ == State::NORMAL) {
float old_progress = progress_;
progress_ += amount;
progress_ = std::min(progress_, total_progress_to_complete_);
// Notifica el cambio si hay callback y el progreso cambió
if (progress_callback_ && progress_ != old_progress) {
progress_callback_(progress_);
}
}
}
// Establece la progresión absoluta
void Background::setProgress(float absolute_progress) {
float old_progress = progress_;
progress_ = std::clamp(absolute_progress, 0.0F, total_progress_to_complete_);
// Notifica el cambio si hay callback y el progreso cambió
if (progress_callback_ && progress_ != old_progress) {
progress_callback_(progress_);
}
}
// Cambia el estado del fondo
void Background::setState(State new_state) {
// Si entra en estado completado, inicializar variables de transición
if (new_state == State::COMPLETED && state_ != State::COMPLETED) {
completion_initial_progress_ = progress_;
completion_transition_timer_ = 0.0f;
}
state_ = new_state;
}
// Reinicia la progresión
void Background::reset() {
float old_progress = progress_;
progress_ = 0.0F;
state_ = State::NORMAL;
manual_mode_ = false;
gradient_number_ = 0;
transition_ = 0.0F;
sun_index_ = 0;
moon_index_ = 0;
// Resetear variables de transición de completado
completion_transition_timer_ = 0.0f;
completion_initial_progress_ = 0.0f;
// Notifica el cambio si hay callback
if (progress_callback_ && progress_ != old_progress) {
progress_callback_(progress_);
}
}
// Activa/desactiva el modo manual
void Background::setManualMode(bool manual) {
manual_mode_ = manual;
}
// Establece callback para sincronización automática
void Background::setProgressCallback(ProgressCallback callback) {
progress_callback_ = std::move(callback);
}
// Elimina el callback
void Background::removeProgressCallback() {
progress_callback_ = nullptr;
}
// Ajusta la velocidad de las nubes
void Background::setCloudsSpeed(float value) {
clouds_speed_ = value;
// En modo manual, aplicar la velocidad directamente
// Las nubes inferiores van a la mitad de velocidad que las superiores
top_clouds_sprite_a_->setVelX(value);
top_clouds_sprite_b_->setVelX(value);
bottom_clouds_sprite_a_->setVelX(value / 2.0F);
bottom_clouds_sprite_b_->setVelX(value / 2.0F);
}
// Establece el degradado de fondo
void Background::setGradientNumber(int value) {
gradient_number_ = value % STAGES;
}
// Ajusta la transición entre texturas
void Background::setTransition(float value) {
transition_ = std::clamp(value, 0.0F, 1.0F);
}
// 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));
}
// Actualiza la progresión y calcula las transiciones
void Background::updateProgression(float delta_time) {
// Si el juego está completado, hacer transición suave con easing
if (state_ == State::COMPLETED) {
completion_transition_timer_ += delta_time;
// Calcular progreso normalizado de la transición (0.0 a 1.0)
float t = std::min(completion_transition_timer_ / COMPLETION_TRANSITION_DURATION_S, 1.0f);
if (t < 1.0f) {
// Usar easeOutCubic para transición suave (rápido al inicio, lento al final)
float eased_t = easeOutCubic(static_cast<double>(t));
// Interpolación desde progreso inicial hasta mínimo
float progress_range = completion_initial_progress_ - minimum_completed_progress_;
progress_ = completion_initial_progress_ - (progress_range * eased_t);
} else {
// Transición completada, fijar al valor mínimo
progress_ = minimum_completed_progress_;
}
}
// Calcula la transición de los diferentes fondos
const float GRADIENT_NUMBER_FLOAT = std::min(progress_ / progress_per_stage_, 3.0F);
const float PERCENT = GRADIENT_NUMBER_FLOAT - static_cast<int>(GRADIENT_NUMBER_FLOAT);
gradient_number_ = static_cast<size_t>(GRADIENT_NUMBER_FLOAT);
transition_ = PERCENT;
// Calcula la posición del sol
const float SUN_PROGRESSION = std::min(progress_ / sun_completion_progress_, 1.0F);
sun_index_ = static_cast<size_t>(SUN_PROGRESSION * (sun_path_.size() - 1));
// Calcula la posición de la luna
const float MOON_PROGRESSION = std::min(progress_ / total_progress_to_complete_, 1.0F);
moon_index_ = static_cast<size_t>(MOON_PROGRESSION * (moon_path_.size() - 1));
// Actualiza la velocidad de las nubes
updateCloudsSpeed();
}
// Actualiza la velocidad de las nubes según el estado y progresión
void Background::updateCloudsSpeed() {
// Cálculo de velocidad según progreso (convertido de frame-based a time-based)
constexpr float CLOUDS_INITIAL_SPEED_PX_PER_S = 0.05F * 60.0F; // 3.0 píxeles/segundo (era 0.05 px/frame @ 60fps)
constexpr float CLOUDS_TOTAL_SPEED_PX_PER_S = 2.00F * 60.0F; // 120.0 píxeles/segundo (era 2.00 px/frame @ 60fps)
constexpr float CLOUDS_FINAL_SPEED_RANGE_PX_PER_S = CLOUDS_TOTAL_SPEED_PX_PER_S - CLOUDS_INITIAL_SPEED_PX_PER_S; // 117.0 píxeles/segundo
// Velocidad base según progreso (de -3.0 a -120.0 píxeles/segundo, igual que la versión original)
float base_clouds_speed = (-CLOUDS_INITIAL_SPEED_PX_PER_S) +
(-CLOUDS_FINAL_SPEED_RANGE_PX_PER_S * (progress_ / total_progress_to_complete_));
// En estado completado, las nubes se ralentizan gradualmente
if (state_ == State::COMPLETED) {
float completion_factor = (progress_ - minimum_completed_progress_) /
(total_progress_to_complete_ - minimum_completed_progress_);
completion_factor = std::max(0.1F, completion_factor);
base_clouds_speed *= completion_factor;
}
// Aplicar velocidades diferentes para nubes superiores e inferiores
const float TOP_CLOUDS_SPEED = base_clouds_speed;
const float BOTTOM_CLOUDS_SPEED = base_clouds_speed / 2.0F;
// Aplicar las velocidades a los sprites correspondientes
top_clouds_sprite_a_->setVelX(TOP_CLOUDS_SPEED);
top_clouds_sprite_b_->setVelX(TOP_CLOUDS_SPEED);
bottom_clouds_sprite_a_->setVelX(BOTTOM_CLOUDS_SPEED);
bottom_clouds_sprite_b_->setVelX(BOTTOM_CLOUDS_SPEED);
// Guardar la velocidad principal
clouds_speed_ = TOP_CLOUDS_SPEED;
}
// Actualiza las nubes
void Background::updateClouds(float deltaTime) {
// Mueve las nubes
top_clouds_sprite_a_->update(deltaTime);
top_clouds_sprite_b_->update(deltaTime);
bottom_clouds_sprite_a_->update(deltaTime);
bottom_clouds_sprite_b_->update(deltaTime);
// Calcula el offset de las nubes
if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth()) {
top_clouds_sprite_a_->setPosX(top_clouds_sprite_a_->getWidth());
}
if (top_clouds_sprite_b_->getPosX() < -top_clouds_sprite_b_->getWidth()) {
top_clouds_sprite_b_->setPosX(top_clouds_sprite_b_->getWidth());
}
if (bottom_clouds_sprite_a_->getPosX() < -bottom_clouds_sprite_a_->getWidth()) {
bottom_clouds_sprite_a_->setPosX(bottom_clouds_sprite_a_->getWidth());
}
if (bottom_clouds_sprite_b_->getPosX() < -bottom_clouds_sprite_b_->getWidth()) {
bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth());
}
}
// Dibuja el gradiente de fondo
void Background::renderGradient() {
// Dibuja el gradiente de detras
@@ -221,21 +450,6 @@ void Background::render() {
SDL_RenderTexture(renderer_, color_texture_, &src_rect_, &dst_rect_);
}
// Ajusta el valor de la variable
void Background::setCloudsSpeed(float value) {
clouds_speed_ = value;
}
// Ajusta el valor de la variable
void Background::setGradientNumber(int value) {
gradient_number_ = value % 4;
}
// Ajusta el valor de la variable
void Background::setTransition(float value) {
transition_ = std::clamp(value, 0.0F, 1.0F);
}
// Establece la posición del objeto
void Background::setPos(SDL_FRect pos) {
dst_rect_ = pos;
@@ -247,7 +461,7 @@ void Background::setPos(SDL_FRect pos) {
src_rect_.h = pos.h;
}
// Establece el color_ de atenuación
// Establece el color de atenuación
void Background::setColor(Color color) {
attenuate_color_ = color;
@@ -264,52 +478,20 @@ void Background::setColor(Color color) {
// Establece la transparencia de la atenuación
void Background::setAlpha(int alpha) {
// Evita que se asignen valores fuera de rango
alpha_ = std::clamp(alpha, 0, 255);
alpha = std::clamp(alpha, 0, 255);
// Guarda el valor actual y establece el nuevo valor
alpha_color_text_temp_ = alpha_color_text_;
alpha_color_text_ = alpha_;
previous_alpha_color_texture_ = alpha_color_texture_;
alpha_color_texture_ = alpha;
}
// Actualiza el valor de alpha_
// Actualiza el valor de alpha
void Background::updateAlphaColorTexture() {
if (alpha_color_text_ == alpha_color_text_temp_) {
if (alpha_color_texture_ == previous_alpha_color_texture_) {
return;
}
alpha_color_text_ > alpha_color_text_temp_ ? ++alpha_color_text_temp_ : --alpha_color_text_temp_;
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_temp_);
}
// Actualiza las nubes
void Background::updateClouds() {
// Aplica la velocidad calculada a las nubes
top_clouds_sprite_a_->setVelX(clouds_speed_);
top_clouds_sprite_b_->setVelX(clouds_speed_);
bottom_clouds_sprite_a_->setVelX(clouds_speed_ / 2);
bottom_clouds_sprite_b_->setVelX(clouds_speed_ / 2);
// Mueve las nubes
top_clouds_sprite_a_->update();
top_clouds_sprite_b_->update();
bottom_clouds_sprite_a_->update();
bottom_clouds_sprite_b_->update();
// Calcula el offset de las nubes
if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth()) {
top_clouds_sprite_a_->setPosX(top_clouds_sprite_a_->getWidth());
}
if (top_clouds_sprite_b_->getPosX() < -top_clouds_sprite_b_->getWidth()) {
top_clouds_sprite_b_->setPosX(top_clouds_sprite_b_->getWidth());
}
if (bottom_clouds_sprite_a_->getPosX() < -bottom_clouds_sprite_a_->getWidth()) {
bottom_clouds_sprite_a_->setPosX(bottom_clouds_sprite_a_->getWidth());
}
if (bottom_clouds_sprite_b_->getPosX() < -bottom_clouds_sprite_b_->getWidth()) {
bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth());
}
alpha_color_texture_ > previous_alpha_color_texture_ ? ++previous_alpha_color_texture_ : --previous_alpha_color_texture_;
SDL_SetTextureAlphaMod(color_texture_, previous_alpha_color_texture_);
}
// Precalcula el vector con el recorrido del sol
@@ -323,7 +505,7 @@ void Background::createSunPath() {
const int NUM_STEPS = static_cast<int>((M_PI - M_PI / 2) / STEP) + 1;
for (int i = 0; i < NUM_STEPS; ++i) {
double theta = M_PI / 2 + i * STEP;
double theta = M_PI / 2 + (i * STEP);
float x = CENTER_X + (RADIUS * cos(theta));
float y = CENTER_Y - (RADIUS * sin(theta));
sun_path_.push_back({x, y});
@@ -343,26 +525,22 @@ void Background::createMoonPath() {
const float CENTER_Y = base_ - 50;
constexpr float RADIUS = 140;
// Generar puntos de la curva desde 0 a 90 grados
constexpr double STEP = 0.01;
const int NUM_STEPS = static_cast<int>((M_PI / 2 - 0) / STEP) + 1;
const int NUM_STEPS = static_cast<int>((M_PI / 2) / STEP) + 1;
constexpr float FREEZE_PERCENTAGE = 0.2F; // Porcentaje final del recorrido que se mantiene fijo
const int FREEZE_START_INDEX = static_cast<int>(NUM_STEPS * (1.0F - FREEZE_PERCENTAGE));
for (int i = 0; i < NUM_STEPS; ++i) {
double theta = 0 + i * STEP;
double theta = i * STEP;
float x = CENTER_X + (RADIUS * cos(theta));
float y = CENTER_Y - (RADIUS * sin(theta));
if (i >= FREEZE_START_INDEX && !moon_path_.empty()) {
moon_path_.push_back(moon_path_.back()); // Repite el último punto válido
} else {
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

@@ -4,6 +4,7 @@
#include <array> // Para array
#include <cstddef> // Para size_t
#include <functional> // Para function
#include <memory> // Para unique_ptr, shared_ptr
#include <vector> // Para vector
@@ -13,102 +14,128 @@ class MovingSprite;
class Sprite;
class Texture;
/*
Esta clase gestiona el fondo que aparece en la sección jugable.
Usa una textura compuesta y una capa superior con un color sólido cuya opacidad es ajustable.
Su área total está definida por "rect", pero solo se pinta la región "srcRect" en la pantalla en "dstRect".
Métodos clave:
- setCloudsSpeed(float value) -> Define la velocidad de las nubes
- setGradientNumber(int value) -> Ajusta el índice del color de cielo
- setTransition(float value) -> Configura la transición entre texturas
- setColor(Color color) -> Aplica un color de atenuación
- setAlpha(int alpha) -> Ajusta la transparencia de la capa de atenuación
*/
// --- Clase Background: gestiona el fondo de la sección jugable ---
class Background {
public:
// Constructor y Destructor
Background();
~Background();
// --- Enums ---
enum class State {
NORMAL, // Progresión normal del día
COMPLETED // Reducción gradual de la actividad
};
// Actualización y renderizado
void update(); // Actualiza la lógica del objeto
// --- Tipos ---
using ProgressCallback = std::function<void(float)>; // Callback para sincronización
// --- Constructor y destructor ---
Background(float total_progress_to_complete = 6100.0F); // Constructor principal
~Background(); // Destructor
// --- Métodos principales ---
void update(float delta_time); // Actualiza la lógica del objeto
void render(); // Dibuja el objeto
void reset(); // Reinicia la progresión
// Configuración de posición
// --- Configuración ---
void setPos(SDL_FRect pos); // Establece la posición del objeto
// Configuración de animaciones y efectos
void setCloudsSpeed(float value); // Ajusta la velocidad de desplazamiento de las nubes
void setGradientNumber(int value); // Establece el degradado de fondo a usar
void setTransition(float value); // Ajusta la transición entre texturas de fondo
// Configuración de efectos visuales
void setState(State new_state); // Cambia el estado del fondo
void setProgressCallback(ProgressCallback callback); // Establece callback para sincronización
void removeProgressCallback(); // Elimina el callback
void setManualMode(bool manual); // Activa/desactiva el modo manual
void setCloudsSpeed(float value); // Ajusta la velocidad de las nubes
void setGradientNumber(int value); // Establece el degradado de fondo
void setTransition(float value); // Ajusta la transición entre texturas
void setSunProgression(float progress); // Establece la posición del sol
void setMoonProgression(float progress); // Establece la posición de la luna
void setColor(Color color); // Establece el color de atenuación
void setAlpha(int alpha); // Ajusta la transparencia del fondo
// Configuración del sol y la luna
void setSunProgression(float progress); // Establece la posición del sol
void setMoonProgression(float progress); // Establece la posición de la luna
// --- Control de progresión ---
void incrementProgress(float amount = 1.0F); // Incrementa la progresión interna
void setProgress(float absolute_progress); // Establece la progresión absoluta
// --- Getters ---
[[nodiscard]] auto getProgress() const -> float { return progress_; } // Obtiene el progreso actual
[[nodiscard]] auto getState() const -> State { return state_; } // Obtiene el estado actual
[[nodiscard]] auto getCurrentGradient() const -> int { return static_cast<int>(gradient_number_); } // Obtiene el gradiente actual
private:
// Objetos y punteros
// --- Constantes ---
static constexpr size_t STAGES = 4; // Número de etapas
static constexpr float MINIMUM_COMPLETED_PROGRESS_PERCENTAGE = 0.05F; // Porcentaje mínimo completado (10%)
static constexpr float SUN_COMPLETION_FACTOR = 0.5F; // Factor de completado del sol
static constexpr float COMPLETION_TRANSITION_DURATION_S = 3.0F; // Duración de la transición de completado en segundos
// --- Objetos y punteros ---
SDL_Renderer *renderer_; // Renderizador de la ventana
// Texturas
std::shared_ptr<Texture> buildings_texture_;
std::shared_ptr<Texture> top_clouds_texture_;
std::shared_ptr<Texture> bottom_clouds_texture_;
std::shared_ptr<Texture> grass_texture_;
std::shared_ptr<Texture> gradients_texture_;
std::shared_ptr<Texture> sun_texture_;
std::shared_ptr<Texture> moon_texture_;
// Sprites
std::unique_ptr<MovingSprite> top_clouds_sprite_a_;
std::unique_ptr<MovingSprite> top_clouds_sprite_b_;
std::unique_ptr<MovingSprite> bottom_clouds_sprite_a_;
std::unique_ptr<MovingSprite> bottom_clouds_sprite_b_;
std::unique_ptr<Sprite> buildings_sprite_;
std::unique_ptr<Sprite> gradient_sprite_;
std::unique_ptr<Sprite> grass_sprite_;
std::unique_ptr<Sprite> sun_sprite_;
std::unique_ptr<Sprite> moon_sprite_;
// Buffers de renderizado
SDL_Texture *canvas_; // Textura para componer el fondo
SDL_Texture *color_texture_; // Textura para atenuar el fondo
std::shared_ptr<Texture> buildings_texture_; // Textura de edificios
std::shared_ptr<Texture> top_clouds_texture_; // Textura de nubes superiores
std::shared_ptr<Texture> bottom_clouds_texture_; // Textura de nubes inferiores
std::shared_ptr<Texture> grass_texture_; // Textura de hierba
std::shared_ptr<Texture> gradients_texture_; // Textura de gradientes
std::shared_ptr<Texture> sun_texture_; // Textura del sol
std::shared_ptr<Texture> moon_texture_; // Textura de la luna
std::unique_ptr<MovingSprite> top_clouds_sprite_a_; // Sprite de nubes superiores A
std::unique_ptr<MovingSprite> top_clouds_sprite_b_; // Sprite de nubes superiores B
std::unique_ptr<MovingSprite> bottom_clouds_sprite_a_; // Sprite de nubes inferiores A
std::unique_ptr<MovingSprite> bottom_clouds_sprite_b_; // Sprite de nubes inferiores B
std::unique_ptr<Sprite> buildings_sprite_; // Sprite de edificios
std::unique_ptr<Sprite> gradient_sprite_; // Sprite de gradiente
std::unique_ptr<Sprite> grass_sprite_; // Sprite de hierba
std::unique_ptr<Sprite> sun_sprite_; // Sprite del sol
std::unique_ptr<Sprite> moon_sprite_; // Sprite de la luna
// Variables de control
std::array<SDL_FRect, 4> gradient_rect_;
std::array<SDL_FRect, 4> top_clouds_rect_;
std::array<SDL_FRect, 4> bottom_clouds_rect_;
int gradient_number_ = 0;
int alpha_ = 0;
float clouds_speed_ = 0;
float transition_ = 0;
int counter_ = 0;
SDL_FRect rect_;
SDL_FRect src_rect_;
SDL_FRect dst_rect_;
int base_;
Color attenuate_color_;
int alpha_color_text_;
int alpha_color_text_temp_;
std::vector<SDL_FPoint> sun_path_;
std::vector<SDL_FPoint> moon_path_;
size_t sun_index_ = 0;
size_t moon_index_ = 0;
// --- Variables de configuración ---
const float total_progress_to_complete_; // Progreso total para completar
const float progress_per_stage_; // Progreso por etapa
const float sun_completion_progress_; // Progreso de completado del sol
const float minimum_completed_progress_; // Progreso mínimo calculado dinámicamente
ProgressCallback progress_callback_; // Callback para notificar cambios de progreso
// Métodos internos
// --- Variables de estado ---
std::vector<SDL_FPoint> sun_path_; // Recorrido del sol
std::vector<SDL_FPoint> moon_path_; // Recorrido de la luna
std::array<SDL_FRect, STAGES> gradient_rect_; // Fondos degradados
std::array<SDL_FRect, 4> top_clouds_rect_; // Nubes superiores
std::array<SDL_FRect, 4> bottom_clouds_rect_; // Nubes inferiores
SDL_FRect rect_; // Tamaño del objeto
SDL_FRect src_rect_; // Parte del objeto para copiar en pantalla
SDL_FRect dst_rect_; // Posición en pantalla donde se copia el objeto
Color attenuate_color_; // Color de atenuación
State state_ = State::NORMAL; // Estado actual
float progress_ = 0.0F; // Progresión interna
float clouds_speed_ = 0; // Velocidad de las nubes
float transition_ = 0; // Porcentaje de transición
size_t gradient_number_ = 0; // Índice de fondo degradado
float grass_timer_ = 0.0f; // Timer para animación de hierba (ms)
static constexpr float GRASS_FRAME_DURATION = 333.34f; // Duración por frame de hierba (20 frames * 16.67ms)
size_t alpha_color_texture_ = 0; // Transparencia de atenuación
size_t previous_alpha_color_texture_ = 0; // Transparencia anterior
size_t sun_index_ = 0; // Índice del recorrido del sol
size_t moon_index_ = 0; // Índice del recorrido de la luna
int base_ = 0; // Posición base del fondo
Uint8 alpha_ = 0; // Transparencia entre fases
bool manual_mode_ = false; // Si está en modo manual
// --- Variables para transición suave de completado ---
float completion_transition_timer_ = 0.0f; // Timer para la transición de completado
float completion_initial_progress_ = 0.0f; // Progreso inicial al entrar en estado completado
// --- Métodos internos ---
void initializePaths(); // Inicializa las rutas del sol y la luna
void initializeRects(); // Inicializa los rectángulos de gradientes y nubes
void initializeSprites(); // Crea los sprites
void initializeSpriteProperties(); // Configura las propiedades iniciales de los sprites
void initializeTextures(); // Inicializa las texturas de renderizado
void updateProgression(float delta_time); // Actualiza la progresión y calcula transiciones
void updateCloudsSpeed(); // Actualiza la velocidad de las nubes según el estado
void renderGradient(); // Dibuja el gradiente de fondo
void renderTopClouds(); // Dibuja las nubes superiores
void renderBottomClouds(); // Dibuja las nubes inferiores
void fillCanvas(); // Compone todos los elementos en la textura
void updateAlphaColorTexture(); // Actualiza el alpha de la textura de atenuación
void updateClouds(); // Actualiza el movimiento de las nubes
void updateClouds(float deltaTime); // Actualiza el movimiento de las nubes (time-based)
void createSunPath(); // Precalcula el recorrido del sol
void createMoonPath(); // Precalcula el recorrido de la luna
};

View File

@@ -11,24 +11,25 @@
#include "texture.h" // Para Texture
// Constructor
Balloon::Balloon(float x, float y, Type type, Size size, float vel_x, float speed, Uint16 creation_timer, SDL_FRect play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
x_(x),
y_(y),
vx_(vel_x),
being_created_(creation_timer > 0),
invulnerable_(creation_timer > 0),
stopped_(creation_timer > 0),
creation_counter_(creation_timer),
creation_counter_ini_(creation_timer),
type_(type),
size_(size),
speed_(speed),
play_area_(play_area) {
Balloon::Balloon(const Config& config)
: sprite_(std::make_unique<AnimatedSprite>(config.texture, config.animation)),
x_(config.x),
y_(config.y),
vx_(config.vel_x),
being_created_(config.creation_counter > 0),
invulnerable_(config.creation_counter > 0),
stopped_(config.creation_counter > 0),
creation_counter_(config.creation_counter),
creation_counter_ini_(config.creation_counter),
type_(config.type),
size_(config.size),
game_tempo_(config.game_tempo),
play_area_(config.play_area),
sound_(config.sound) {
switch (type_) {
case Type::BALLOON: {
vy_ = 0;
max_vy_ = 3.0F;
max_vy_ = 3.0F * 60.0F; // Convert from frames to seconds (180 pixels/s)
const int INDEX = static_cast<int>(size_);
gravity_ = param.balloon.settings.at(INDEX).grav;
@@ -37,14 +38,13 @@ Balloon::Balloon(float x, float y, Type type, Size size, float vel_x, float spee
power_ = POWER.at(INDEX);
menace_ = MENACE.at(INDEX);
score_ = SCORE.at(INDEX);
bouncing_sound_ = BOUNCING_SOUND.at(INDEX);
popping_sound_ = POPPING_SOUND.at(INDEX);
sound_.bouncing_file = BOUNCING_SOUND.at(INDEX);
sound_.popping_file = POPPING_SOUND.at(INDEX);
break;
}
case Type::FLOATER: {
default_vy_ = max_vy_ = vy_ = fabs(vx_ * 2.0F);
default_vy_ = max_vy_ = vy_ = std::fabs(vx_ * 2.0F);
gravity_ = 0.00F;
const int INDEX = static_cast<int>(size_);
@@ -52,27 +52,25 @@ Balloon::Balloon(float x, float y, Type type, Size size, float vel_x, float spee
power_ = POWER.at(INDEX);
menace_ = MENACE.at(INDEX);
score_ = SCORE.at(INDEX);
bouncing_sound_ = BOUNCING_SOUND.at(INDEX);
popping_sound_ = POPPING_SOUND.at(INDEX);
sound_.bouncing_file = BOUNCING_SOUND.at(INDEX);
sound_.popping_file = POPPING_SOUND.at(INDEX);
break;
}
case Type::POWERBALL: {
constexpr int INDEX = 3;
h_ = w_ = WIDTH.at(4);
bouncing_sound_ = BOUNCING_SOUND.at(3);
popping_sound_ = "power_ball_explosion.wav";
sound_.bouncing_file = BOUNCING_SOUND.at(3);
sound_.popping_file = "power_ball_explosion.wav";
power_ = score_ = menace_ = 0;
vy_ = 0;
max_vy_ = 3.0F;
max_vy_ = 3.0F * 60.0F; // Convert from frames to seconds (180 pixels/s)
gravity_ = param.balloon.settings.at(INDEX).grav;
default_vy_ = param.balloon.settings.at(INDEX).vel;
sprite_->setRotate(creation_timer <= 0);
sprite_->setRotateAmount(vx_ > 0.0F ? 2.0 : -2.0);
sprite_->setRotate(config.creation_counter <= 0);
sprite_->setRotateAmount(vx_ > 0.0F ? 120.0 : -120.0); // Convert from 2 degrees/frame to 120 degrees/second
break;
}
@@ -91,14 +89,19 @@ Balloon::Balloon(float x, float y, Type type, Size size, float vel_x, float spee
// Establece la animación a usar
setAnimation();
// Si no se está creando (creation_counter = 0), asegurar estado activo
if (!being_created_) {
start();
setInvulnerable(false);
}
}
// Centra el globo en la posición X
void Balloon::alignTo(int x) {
x_ = static_cast<float>(x - (w_ / 2));
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));
const float MIN_X = play_area_.x;
const float MAX_X = play_area_.w - w_;
x_ = std::clamp(x - (w_ / 2), MIN_X, MAX_X);
}
// Pinta el globo en la pantalla
@@ -138,19 +141,20 @@ void Balloon::render() {
}
}
// Actualiza la posición y estados del globo
void Balloon::move() {
// Actualiza la posición y estados del globo (time-based)
void Balloon::move(float deltaTime) {
if (isStopped()) {
return;
}
handleHorizontalMovement();
handleVerticalMovement();
applyGravity();
handleHorizontalMovement(deltaTime);
handleVerticalMovement(deltaTime);
applyGravity(deltaTime);
}
void Balloon::handleHorizontalMovement() {
x_ += vx_ * speed_;
void Balloon::handleHorizontalMovement(float deltaTime) {
// DeltaTime en segundos: velocidad (pixels/s) * tempo * tiempo (s)
x_ += vx_ * game_tempo_ * deltaTime;
const int CLIP = 2;
const float MIN_X = play_area_.x - CLIP;
@@ -161,8 +165,9 @@ void Balloon::handleHorizontalMovement() {
}
}
void Balloon::handleVerticalMovement() {
y_ += vy_ * speed_;
void Balloon::handleVerticalMovement(float deltaTime) {
// DeltaTime en segundos: velocidad (pixels/s) * tempo * tiempo (s)
y_ += vy_ * game_tempo_ * deltaTime;
if (shouldCheckTopCollision()) {
handleTopCollision();
@@ -217,41 +222,37 @@ void Balloon::handleBottomCollision() {
}
}
void Balloon::applyGravity() {
/*
Para aplicar la gravedad, el diseño original la aplicaba en cada iteración del bucle
Al añadir el modificador de velocidad se reduce la distancia que recorre el objeto y por
tanto recibe mas gravedad. Para solucionarlo se va a aplicar la gravedad cuando se haya
recorrido una distancia igual a la velocidad en Y, que era el cálculo inicial
*/
travel_y_ += speed_;
if (travel_y_ >= 1.0F) {
travel_y_ -= 1.0F;
vy_ += gravity_;
}
void Balloon::applyGravity(float deltaTime) {
// DeltaTime en segundos: aceleración (pixels/s²) * tempo * tiempo (s)
vy_ += gravity_ * game_tempo_ * deltaTime;
}
void Balloon::playBouncingSound() {
if (bouncing_sound_enabled_) {
playSound(bouncing_sound_);
if (sound_.enabled && sound_.bouncing_enabled) {
Audio::get()->playSound(sound_.bouncing_file);
}
}
// Actualiza al globo a su posicion, animación y controla los contadores
void Balloon::update() {
move();
updateState();
void Balloon::playPoppingSound() {
if (sound_.enabled && sound_.poping_enabled) {
Audio::get()->playSound(sound_.popping_file);
}
}
// Actualiza al globo a su posicion, animación y controla los contadores (time-based)
void Balloon::update(float deltaTime) {
move(deltaTime);
updateState(deltaTime);
updateBounceEffect();
shiftSprite();
shiftColliders();
sprite_->update();
++counter_;
sprite_->update(deltaTime);
// Contador interno con deltaTime en segundos
counter_ += deltaTime;
}
// Actualiza los estados del globo
void Balloon::updateState() {
// Actualiza los estados del globo (time-based)
void Balloon::updateState(float deltaTime) {
// Si se está creando
if (isBeingCreated()) {
// Actualiza el valor de las variables
@@ -260,9 +261,14 @@ void Balloon::updateState() {
if (creation_counter_ > 0) {
// Desplaza lentamente el globo hacia abajo y hacia un lado
if (creation_counter_ % 10 == 0) {
// Cada 10/60 segundos (equivalente a 10 frames a 60fps)
movement_accumulator_ += deltaTime;
constexpr float MOVEMENT_INTERVAL_S = 10.0f / 60.0f; // 10 frames = ~0.167s
if (movement_accumulator_ >= MOVEMENT_INTERVAL_S) {
movement_accumulator_ -= MOVEMENT_INTERVAL_S;
y_++;
x_ += vx_;
x_ += vx_ / 60.0f; // Convierte de pixels/segundo a pixels/frame para movimiento discreto
// Comprueba no se salga por los laterales
const int MIN_X = play_area_.x;
@@ -270,11 +276,12 @@ void Balloon::updateState() {
if (x_ < MIN_X || x_ > MAX_X) {
// Corrige y cambia el sentido de la velocidad
x_ -= vx_;
x_ -= vx_ / 60.0f;
vx_ = -vx_;
}
}
--creation_counter_;
creation_counter_ -= deltaTime;
if (creation_counter_ < 0) creation_counter_ = 0;
}
else {
@@ -308,11 +315,14 @@ void Balloon::setAnimation() {
}
// Establece el frame de animación
std::string chosen_animation;
if (use_reversed_colors_) {
sprite_->setCurrentAnimation(creating_animation);
chosen_animation = creating_animation;
} else {
sprite_->setCurrentAnimation(isBeingCreated() ? creating_animation : normal_animation);
chosen_animation = isBeingCreated() ? creating_animation : normal_animation;
}
sprite_->setCurrentAnimation(chosen_animation);
}
// Detiene el globo
@@ -369,23 +379,8 @@ void Balloon::useNormalColor() {
setAnimation();
}
// Reproduce sonido
void Balloon::playSound(const std::string &name) const {
if (!sound_enabled_) {
return;
}
static auto *audio_ = Audio::get();
audio_->playSound(name);
}
// Explota el globo
void Balloon::pop(bool should_sound) {
if (should_sound) {
if (poping_sound_enabled_) {
playSound(popping_sound_);
}
}
if (should_sound) { playPoppingSound(); }
enabled_ = false;
}

View File

@@ -25,51 +25,74 @@ class Balloon {
static constexpr std::array<int, 5> WIDTH = {10, 16, 26, 48, 49};
static constexpr std::array<std::string_view, 4> BOUNCING_SOUND = {
"balloon_bounce0.wav", "balloon_bounce1.wav", "balloon_bounce2.wav", "balloon_bounce3.wav"};
"balloon_bounce0.wav",
"balloon_bounce1.wav",
"balloon_bounce2.wav",
"balloon_bounce3.wav"};
static constexpr std::array<std::string_view, 4> POPPING_SOUND = {
"balloon_pop0.wav", "balloon_pop1.wav", "balloon_pop2.wav", "balloon_pop3.wav"};
"balloon_pop0.wav",
"balloon_pop1.wav",
"balloon_pop2.wav",
"balloon_pop3.wav"};
static constexpr float VELX_POSITIVE = 0.7F;
static constexpr float VELX_NEGATIVE = -0.7F;
// Velocidades horizontales en pixels/segundo (convertidas desde 0.7 pixels/frame a 60fps)
static constexpr float VELX_POSITIVE = 0.7F * 60.0F; // 42 pixels/segundo
static constexpr float VELX_NEGATIVE = -0.7F * 60.0F; // -42 pixels/segundo
static constexpr std::array<float, 5> SPEED = {0.60F, 0.70F, 0.80F, 0.90F, 1.00F};
// Multiplicadores de tempo del juego (sin cambios, son puros multiplicadores)
static constexpr std::array<float, 5> GAME_TEMPO = {0.60F, 0.70F, 0.80F, 0.90F, 1.00F};
static constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10;
static constexpr int POWERBALL_COUNTER = 8;
// --- Enums ---
enum class Size : Uint8 {
SMALL = 0,
MEDIUM = 1,
LARGE = 2,
EXTRALARGE = 3,
SMALL = 0, // Tamaño pequeño
MEDIUM = 1, // Tamaño mediano
LARGE = 2, // Tamaño grande
EXTRALARGE = 3, // Tamaño extra grande
};
enum class Type : Uint8 {
BALLOON = 0,
FLOATER = 1,
POWERBALL = 2,
BALLOON = 0, // Globo normal
FLOATER = 1, // Globo flotante
POWERBALL = 2, // Globo de poder
};
// --- Estructura para manejo de sonido ---
struct Sound {
std::string bouncing_file; // Archivo de sonido al rebotar
std::string popping_file; // Archivo de sonido al explotar
bool bouncing_enabled = false; // Si debe sonar el globo al rebotar
bool poping_enabled = true; // Si debe sonar el globo al explotar
bool enabled = true; // Indica si los globos deben hacer algun sonido
};
// --- Estructura de configuración para inicialización ---
struct Config {
float x = 0.0F;
float y = 0.0F;
Type type = Type::BALLOON;
Size size = Size::EXTRALARGE;
float vel_x = VELX_POSITIVE;
float game_tempo = GAME_TEMPO.at(0);
float creation_counter = 0.0f;
SDL_FRect play_area = {.x = 0.0F, .y = 0.0F, .w = 0.0F, .h = 0.0F};
std::shared_ptr<Texture> texture = nullptr;
std::vector<std::string> animation;
Sound sound;
};
// --- Constructores y destructor ---
Balloon(
float x,
float y,
Type type,
Size size,
float vel_x,
float speed,
Uint16 creation_timer,
SDL_FRect play_area,
std::shared_ptr<Texture> texture,
const std::vector<std::string>& animation);
Balloon(const Config& config);
~Balloon() = default;
// --- Métodos principales ---
void alignTo(int x); // Centra el globo en la posición X
void render(); // Pinta el globo en la pantalla
void move(); // Actualiza la posición y estados del globo
void update(); // Actualiza el globo (posición, animación, contadores)
void move(float deltaTime); // Actualiza la posición y estados del globo (time-based)
void update(float deltaTime); // Actualiza el globo (posición, animación, contadores) (time-based)
void stop(); // Detiene el globo
void start(); // Pone el globo en movimiento
void pop(bool should_sound = false); // Explota el globo
@@ -99,11 +122,13 @@ class Balloon {
// --- Setters ---
void setVelY(float vel_y) { vy_ = vel_y; }
void setSpeed(float speed) { speed_ = speed; }
void setVelX(float vel_x) { vx_ = vel_x; }
void alterVelX(float percent) {vx_ *= percent; }
void setGameTempo(float tempo) { game_tempo_ = tempo; }
void setInvulnerable(bool value) { invulnerable_ = value; }
void setBouncingSound(bool value) { bouncing_sound_enabled_ = value; }
void setPoppingSound(bool value) { poping_sound_enabled_ = value; }
void setSound(bool value) { sound_enabled_ = value; }
void setBouncingSound(bool value) { sound_.bouncing_enabled = value; }
void setPoppingSound(bool value) { sound_.poping_enabled = value; }
void setSound(bool value) { sound_.enabled = value; }
private:
// --- Estructura para el efecto de rebote ---
@@ -113,10 +138,28 @@ class Balloon {
// Tablas de valores predefinidos para el efecto de rebote
static constexpr std::array<float, BOUNCE_FRAMES> HORIZONTAL_ZOOM_VALUES = {
1.10F, 1.05F, 1.00F, 0.95F, 0.90F, 0.95F, 1.00F, 1.02F, 1.05F, 1.02F};
1.10F,
1.05F,
1.00F,
0.95F,
0.90F,
0.95F,
1.00F,
1.02F,
1.05F,
1.02F};
static constexpr std::array<float, BOUNCE_FRAMES> VERTICAL_ZOOM_VALUES = {
0.90F, 0.95F, 1.00F, 1.05F, 1.10F, 1.05F, 1.00F, 0.98F, 0.95F, 0.98F};
0.90F,
0.95F,
1.00F,
1.05F,
1.10F,
1.05F,
1.00F,
0.98F,
0.95F,
0.98F};
// Estado del efecto
bool enabled_ = false; // Si el efecto está activo
@@ -217,22 +260,18 @@ class Balloon {
bool stopped_; // Si el globo está parado
bool use_reversed_colors_ = false; // Si se usa el color alternativo
Circle collider_; // Círculo de colisión
Uint16 creation_counter_; // Temporizador de creación
Uint16 creation_counter_ini_; // Valor inicial del temporizador de creación
float creation_counter_; // Temporizador de creación
float creation_counter_ini_; // Valor inicial del temporizador de creación
Uint16 score_; // Puntos al destruir el globo
Type type_; // Tipo de globo
Size size_; // Tamaño de globo
Uint8 menace_; // Amenaza que genera el globo
Uint32 counter_ = 0; // Contador interno
float travel_y_ = 1.0F; // Distancia a recorrer en Y antes de aplicar gravedad
float speed_; // Velocidad del globo
float game_tempo_; // Multiplicador de tempo del juego
float movement_accumulator_ = 0.0f; // Acumulador para movimiento durante creación (deltaTime)
Uint8 power_; // Poder que alberga el globo
SDL_FRect play_area_; // Zona de movimiento del globo
std::string bouncing_sound_; // Archivo de sonido al rebotar
std::string popping_sound_; // Archivo de sonido al explotar
bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar
bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar
bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido
Sound sound_; // Configuración de sonido del globo
BounceEffect bounce_effect_; // Efecto de rebote
// --- Posicionamiento y transformación ---
@@ -241,13 +280,13 @@ class Balloon {
// --- Animación y sonido ---
void setAnimation(); // Establece la animación correspondiente
void playSound(const std::string& name) const; // Reproduce un sonido por nombre
void playBouncingSound(); // Reproduce el sonido de rebote
void playPoppingSound(); // Reproduce el sonido de reventar
// --- Movimiento y física ---
void handleHorizontalMovement(); // Maneja el movimiento horizontal
void handleVerticalMovement(); // Maneja el movimiento vertical
void applyGravity(); // Aplica la gravedad al objeto
void handleHorizontalMovement(float deltaTime); // Maneja el movimiento horizontal (time-based)
void handleVerticalMovement(float deltaTime); // Maneja el movimiento vertical (time-based)
void applyGravity(float deltaTime); // Aplica la gravedad al objeto (time-based)
// --- Rebote ---
void enableBounceEffect(); // Activa el efecto de rebote
@@ -262,5 +301,5 @@ class Balloon {
void handleBottomCollision(); // Maneja la colisión inferior
// --- Lógica de estado ---
void updateState(); // Actualiza los estados del globo
void updateState(float deltaTime); // Actualiza los estados del globo (time-based)
};

View File

@@ -155,7 +155,7 @@ auto BalloonFormations::parseBalloonLine(const std::string& line, const std::map
return std::nullopt;
}
int creation_time = DEFAULT_CREATION_TIME + evaluateExpression(tokens.at(6), variables);
float creation_time = CREATION_TIME + evaluateExpression(tokens.at(6), variables); // Base time + offset from formations.txt
return SpawnParams(x + offset, y, vel_x, type, size, creation_time);
} catch (const std::exception&) {
@@ -168,7 +168,7 @@ auto BalloonFormations::evaluateExpression(const std::string& expr, const std::m
// Si es un número directo
if ((std::isdigit(trimmed_expr.at(0)) != 0) || (trimmed_expr.at(0) == '-' && trimmed_expr.length() > 1)) {
return std::stoi(trimmed_expr);
return std::stof(trimmed_expr);
}
// Si es una variable simple
@@ -205,7 +205,7 @@ auto BalloonFormations::evaluateSimpleExpression(const std::string& expr, const
}
// Si no se encuentra operador, intentar como variable o número
return variables.find(expr) != variables.end() ? variables.at(expr) : std::stoi(expr);
return variables.find(expr) != variables.end() ? variables.at(expr) : std::stof(expr);
}
auto BalloonFormations::trim(const std::string& str) -> std::string {
@@ -235,10 +235,10 @@ void BalloonFormations::createFloaterVariants() {
#ifdef _DEBUG
void BalloonFormations::addTestFormation() {
std::vector<SpawnParams> test_params = {
{10, -BLOCK, 0, Balloon::Type::FLOATER, Balloon::Size::SMALL, 200},
{50, -BLOCK, 0, Balloon::Type::FLOATER, Balloon::Size::MEDIUM, 200},
{90, -BLOCK, 0, Balloon::Type::FLOATER, Balloon::Size::LARGE, 200},
{140, -BLOCK, 0, Balloon::Type::FLOATER, Balloon::Size::EXTRALARGE, 200}};
{10, -BLOCK, 0, Balloon::Type::FLOATER, Balloon::Size::SMALL, 3.334f}, // 200 frames ÷ 60fps = 3.334s
{50, -BLOCK, 0, Balloon::Type::FLOATER, Balloon::Size::MEDIUM, 3.334f}, // 200 frames ÷ 60fps = 3.334s
{90, -BLOCK, 0, Balloon::Type::FLOATER, Balloon::Size::LARGE, 3.334f}, // 200 frames ÷ 60fps = 3.334s
{140, -BLOCK, 0, Balloon::Type::FLOATER, Balloon::Size::EXTRALARGE, 3.334f}}; // 200 frames ÷ 60fps = 3.334s
formations_.at(99) = Formation(test_params);
}

View File

@@ -13,21 +13,26 @@
// --- Clase BalloonFormations ---
class BalloonFormations {
public:
// --- Estructuras de datos ---
// --- Estructuras ---
struct SpawnParams {
int x = 0; // Posición en el eje X donde crear el globo
int y = 0; // Posición en el eje Y donde crear el globo
float x = 0; // Posición en el eje X donde crear el globo
float y = 0; // Posición en el eje Y donde crear el globo
float vel_x = 0.0F; // Velocidad inicial en el eje X
Balloon::Type type = Balloon::Type::BALLOON; // Tipo de globo
Balloon::Size size = Balloon::Size::SMALL; // Tamaño de globo
int creation_counter = 0; // Temporizador para la creación del globo
float creation_counter = 0.0f; // Temporizador para la creación del globo
// Constructor por defecto
SpawnParams() = default;
// Constructor con parámetros
SpawnParams(int x, int y, float vel_x, Balloon::Type type, Balloon::Size size, int creation_counter)
: x(x), y(y), vel_x(vel_x), type(type), size(size), creation_counter(creation_counter) {}
SpawnParams(float x, float y, float vel_x, Balloon::Type type, Balloon::Size size, float creation_counter)
: x(x),
y(y),
vel_x(vel_x),
type(type),
size(size),
creation_counter(creation_counter) {}
};
struct Formation {
@@ -41,8 +46,8 @@ class BalloonFormations {
Formation() = default;
};
// Vector de índices a formaciones
using Pool = std::vector<int>;
// --- Types ---
using Pool = std::vector<int>; // Vector de índices a formaciones
// --- Constructor y destructor ---
BalloonFormations() {
@@ -77,30 +82,23 @@ class BalloonFormations {
private:
// --- Constantes ---
static constexpr int BALLOON_SPAWN_HEIGHT = 208; // Altura desde el suelo en la que aparecen los globos
static constexpr int DEFAULT_CREATION_TIME = 200; // Tiempo base de creación de los globos para las formaciones
static constexpr float CREATION_TIME = 5.0f; // Tiempo base de creación de los globos en segundos (300 frames ÷ 60fps = 5.0s)
static constexpr float DEFAULT_CREATION_TIME = 3.334f; // Tiempo base de creación de los globos en segundos (200 frames ÷ 60fps = 3.334s)
// --- Datos ---
// --- Variables ---
std::vector<Formation> formations_; // Vector con todas las formaciones disponibles
std::vector<Pool> pools_; // Vector de pools, cada pool contiene índices a formaciones
// --- Inicialización de formaciones ---
// --- Métodos internos ---
void initFormations(); // Inicializa la lista principal de formaciones de globos disponibles
void initFormationPools(); // Carga los pools desde archivo de configuración
// --- Carga y análisis de datos ---
auto loadFormationsFromFile(const std::string& filename, const std::map<std::string, float>& variables) -> bool;
auto parseBalloonLine(const std::string& line, const std::map<std::string, float>& variables) -> std::optional<SpawnParams>;
auto loadPoolsFromFile(const std::string& filename) -> bool; // Nueva función para cargar pools
auto parsePoolLine(const std::string& line) -> std::optional<std::pair<int, std::vector<int>>>; // Nueva función para parsear líneas de pools
// --- Evaluación de expresiones ---
auto evaluateExpression(const std::string& expr, const std::map<std::string, float>& variables) -> float;
auto evaluateSimpleExpression(const std::string& expr, const std::map<std::string, float>& variables) -> float;
// --- Utilidades ---
static auto trim(const std::string& str) -> std::string;
// --- Generación de variantes ---
void createFloaterVariants();
void loadDefaultFormations();
void loadDefaultPools(); // Nueva función para pools por defecto

View File

@@ -12,13 +12,14 @@
#include "param.h" // Para Param, ParamGame, param
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "stage.h" // Para addPower
#include "stage_interface.h" // Para IStageInfo
#include "utils.h"
// Constructor
BalloonManager::BalloonManager()
BalloonManager::BalloonManager(IStageInfo* stage_info)
: explosions_(std::make_unique<Explosions>()),
balloon_formations_(std::make_unique<BalloonFormations>()) { init(); }
balloon_formations_(std::make_unique<BalloonFormations>()),
stage_info_(stage_info) { init(); }
// Inicializa
void BalloonManager::init() {
@@ -61,18 +62,18 @@ void BalloonManager::init() {
explosions_->addTexture(3, explosions_textures_.at(3), explosions_animations_.at(3));
}
// Actualiza
void BalloonManager::update() {
for (auto balloon : balloons_) {
balloon->update();
// Actualiza (time-based)
void BalloonManager::update(float deltaTime) {
for (const auto& balloon : balloons_) {
balloon->update(deltaTime);
}
updateBalloonDeployCounter();
explosions_->update();
updateBalloonDeployCounter(deltaTime);
explosions_->update(deltaTime);
}
// Renderiza los objetos
void BalloonManager::render() {
for (auto &balloon : balloons_) {
for (auto& balloon : balloons_) {
balloon->render();
}
explosions_->render();
@@ -80,12 +81,12 @@ void BalloonManager::render() {
// Crea una formación de globos
void BalloonManager::deployRandomFormation(int stage) {
// Solo despliega una formación enemiga si ha pasado cierto tiempo desde la última
if (balloon_deploy_counter_ == 0) {
// Solo despliega una formación enemiga si el timer ha llegado a cero
if (balloon_deploy_counter_ <= 0.0f) {
// En este punto se decide entre crear una powerball o una formación enemiga
if ((rand() % 100 < 15) && (canPowerBallBeCreated())) {
createPowerBall(); // Crea una powerball
balloon_deploy_counter_ = 10; // Da un poco de margen para que se creen mas globos
balloon_deploy_counter_ = POWERBALL_DEPLOY_DELAY; // Resetea con pequeño retraso
} else {
// Decrementa el contador de despliegues de globos necesarios para la siguiente PowerBall
if (power_ball_counter_ > 0) {
@@ -106,11 +107,19 @@ void BalloonManager::deployRandomFormation(int stage) {
// Crea los globos de la formación
const auto BALLOONS = balloon_formations_->getFormationFromPool(stage, formation_id).balloons;
for (auto balloon : BALLOONS) {
createBalloon(balloon.x, balloon.y, balloon.type, balloon.size, balloon.vel_x, balloon_speed_, (creation_time_enabled_) ? balloon.creation_counter : 0);
Balloon::Config config = {
.x = balloon.x,
.y = balloon.y,
.type = balloon.type,
.size = balloon.size,
.vel_x = balloon.vel_x,
.game_tempo = balloon_speed_,
.creation_counter = creation_time_enabled_ ? balloon.creation_counter : 0.0f};
createBalloon(config);
}
// Reinicia el contador para el próximo despliegue
balloon_deploy_counter_ = 300;
// Reinicia el timer para el próximo despliegue
balloon_deploy_counter_ = DEFAULT_BALLOON_DEPLOY_DELAY;
}
}
}
@@ -119,29 +128,44 @@ void BalloonManager::deployRandomFormation(int stage) {
void BalloonManager::deployFormation(int formation_id) {
const auto BALLOONS = balloon_formations_->getFormation(formation_id).balloons;
for (auto balloon : BALLOONS) {
createBalloon(balloon.x, balloon.y, balloon.type, balloon.size, balloon.vel_x, balloon_speed_, balloon.creation_counter);
Balloon::Config config = {
.x = balloon.x,
.y = balloon.y,
.type = balloon.type,
.size = balloon.size,
.vel_x = balloon.vel_x,
.game_tempo = balloon_speed_,
.creation_counter = balloon.creation_counter};
createBalloon(config);
}
}
// Crea una formación de globos específica a una altura determinada
void BalloonManager::deployFormation(int formation_id, int y) {
void BalloonManager::deployFormation(int formation_id, float y) {
const auto BALLOONS = balloon_formations_->getFormation(formation_id).balloons;
for (auto balloon : BALLOONS) {
createBalloon(balloon.x, y, balloon.type, balloon.size, balloon.vel_x, balloon_speed_, balloon.creation_counter);
Balloon::Config config = {
.x = balloon.x,
.y = y,
.type = balloon.type,
.size = balloon.size,
.vel_x = balloon.vel_x,
.game_tempo = balloon_speed_,
.creation_counter = balloon.creation_counter};
createBalloon(config);
}
}
// 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());
auto result = std::ranges::remove_if(balloons_, [](const auto& balloon) { return !balloon->isEnabled(); });
balloons_.erase(result.begin(), balloons_.end());
}
// Actualiza la variable enemyDeployCounter
void BalloonManager::updateBalloonDeployCounter() {
if (balloon_deploy_counter_ > 0) {
--balloon_deploy_counter_;
}
// Actualiza el timer de despliegue de globos (time-based)
void BalloonManager::updateBalloonDeployCounter(float deltaTime) {
// DeltaTime en segundos - timer decrementa hasta llegar a cero
balloon_deploy_counter_ -= deltaTime;
}
// Indica si se puede crear una powerball
@@ -149,17 +173,20 @@ auto BalloonManager::canPowerBallBeCreated() -> bool { return (!power_ball_enabl
// Calcula el poder actual de los globos en pantalla
auto BalloonManager::calculateScreenPower() -> int {
return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon) { return sum + (balloon->isEnabled() ? balloon->getPower() : 0); });
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
auto BalloonManager::createBalloon(float x, int y, Balloon::Type type, Balloon::Size size, float velx, float speed, int creation_timer) -> std::shared_ptr<Balloon> {
auto BalloonManager::createBalloon(Balloon::Config config) -> std::shared_ptr<Balloon> {
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)));
balloons_.back()->setSound(sound_enabled_);
balloons_.back()->setBouncingSound(bouncing_sound_enabled_);
balloons_.back()->setPoppingSound(poping_sound_enabled_);
const int INDEX = static_cast<int>(config.size);
config.play_area = play_area_;
config.texture = balloon_textures_.at(INDEX);
config.animation = balloon_animations_.at(INDEX);
config.sound.enabled = sound_enabled_;
config.sound.bouncing_enabled = bouncing_sound_enabled_;
config.sound.poping_enabled = poping_sound_enabled_;
balloons_.emplace_back(std::make_shared<Balloon>(config));
return balloons_.back();
}
@@ -167,30 +194,49 @@ auto BalloonManager::createBalloon(float x, int y, Balloon::Type type, Balloon::
}
// Crea un globo a partir de otro globo
void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction) {
void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon>& balloon, const std::string& direction) {
if (can_deploy_balloons_) {
// Calcula parametros
const float VX = direction == "LEFT" ? Balloon::VELX_NEGATIVE : Balloon::VELX_POSITIVE;
const auto SIZE = static_cast<Balloon::Size>(static_cast<int>(balloon->getSize()) - 1);
const int PARENT_HEIGHT = balloon->getHeight();
const int CHILD_HEIGHT = Balloon::WIDTH.at(static_cast<int>(balloon->getSize()) - 1);
const int Y = balloon->getPosY() + (PARENT_HEIGHT - CHILD_HEIGHT) / 2;
const int X = direction == "LEFT" ? balloon->getPosX() + (balloon->getWidth() / 3) : balloon->getPosX() + 2 * (balloon->getWidth() / 3);
const int CHILD_WIDTH = CHILD_HEIGHT;
const float X = direction == "LEFT" ? balloon->getPosX() + (balloon->getWidth() / 3) : balloon->getPosX() + (2 * (balloon->getWidth() / 3));
const float MIN_X = play_area_.x;
const float MAX_X = play_area_.w - CHILD_WIDTH;
Balloon::Config config = {
.x = std::clamp(X - (CHILD_WIDTH / 2), MIN_X, MAX_X),
.y = balloon->getPosY() + ((PARENT_HEIGHT - CHILD_HEIGHT) / 2),
.type = balloon->getType(),
.size = static_cast<Balloon::Size>(static_cast<int>(balloon->getSize()) - 1),
.vel_x = direction == "LEFT" ? Balloon::VELX_NEGATIVE : Balloon::VELX_POSITIVE,
.game_tempo = balloon_speed_,
.creation_counter = 0};
// Crea el globo
auto b = createBalloon(0, Y, balloon->getType(), SIZE, VX, balloon_speed_, 0);
auto b = createBalloon(config);
// Establece parametros
b->alignTo(X);
b->setVelY(b->getType() == Balloon::Type::BALLOON ? -2.50F : Balloon::VELX_NEGATIVE * 2.0F);
constexpr float VEL_Y_BALLOON_PER_S = -150.0F;
switch (b->getType()) {
case Balloon::Type::BALLOON: {
b->setVelY(VEL_Y_BALLOON_PER_S);
break;
}
case Balloon::Type::FLOATER: {
const float MODIFIER = (rand() % 2 == 0) ? 1.0F : 1.0F;
b->setVelY(Balloon::VELX_NEGATIVE * 2.0F * MODIFIER);
(rand() % 2 == 0) ? b->alterVelX(1.0F) : b->alterVelX(1.0F);
break;
}
default:
break;
}
// Herencia de estados
if (balloon->isStopped()) {
b->stop();
}
if (balloon->isUsingReversedColor()) {
b->useReverseColor();
}
if (balloon->isStopped()) { b->stop(); }
if (balloon->isUsingReversedColor()) { b->useReverseColor(); }
}
}
@@ -198,18 +244,32 @@ void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon,
void BalloonManager::createPowerBall() {
if (can_deploy_balloons_) {
constexpr int VALUES = 6;
constexpr float POS_Y = -Balloon::WIDTH.at(4);
constexpr int CREATION_TIME = 0;
const int LUCK = rand() % VALUES;
const float LEFT = param.game.play_area.rect.x;
const float CENTER = param.game.play_area.center_x - (Balloon::WIDTH.at(4) / 2);
const float RIGHT = param.game.play_area.rect.w - Balloon::WIDTH.at(4);
const int LUCK = rand() % VALUES;
const std::array<float, VALUES> POS_X = {LEFT, LEFT, CENTER, CENTER, RIGHT, RIGHT};
const std::array<float, VALUES> VEL_X = {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>(POS_X[LUCK], POS_Y, Balloon::Type::POWERBALL, Balloon::Size::EXTRALARGE, VEL_X[LUCK], balloon_speed_, CREATION_TIME, play_area_, balloon_textures_[4], balloon_animations_[4]));
Balloon::Config config = {
.x = POS_X.at(LUCK),
.y = -Balloon::WIDTH.at(4),
.type = Balloon::Type::POWERBALL,
.size = Balloon::Size::EXTRALARGE,
.vel_x = VEL_X.at(LUCK),
.game_tempo = balloon_speed_,
.creation_counter = 0,
.play_area = play_area_,
.texture = balloon_textures_.at(4),
.animation = balloon_animations_.at(4),
.sound = {
.bouncing_enabled = bouncing_sound_enabled_,
.poping_enabled = poping_sound_enabled_,
.enabled = sound_enabled_}};
balloons_.emplace_back(std::make_unique<Balloon>(config));
balloons_.back()->setInvulnerable(true);
power_ball_enabled_ = true;
@@ -220,21 +280,21 @@ void BalloonManager::createPowerBall() {
// Establece la velocidad de los globos
void BalloonManager::setBalloonSpeed(float speed) {
balloon_speed_ = speed;
for (auto &balloon : balloons_) {
balloon->setSpeed(speed);
for (auto& balloon : balloons_) {
balloon->setGameTempo(speed);
}
}
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
auto BalloonManager::popBalloon(std::shared_ptr<Balloon> balloon) -> int {
Stage::addPower(1);
auto BalloonManager::popBalloon(const std::shared_ptr<Balloon>& balloon) -> int {
stage_info_->addPower(1);
int score = 0;
if (balloon->getType() == Balloon::Type::POWERBALL) {
balloon->pop(true);
score = destroyAllBalloons();
power_ball_enabled_ = false;
balloon_deploy_counter_ = 20;
balloon_deploy_counter_ = BALLOON_POP_DELAY; // Resetea con retraso
} else {
score = balloon->getScore();
if (balloon->getSize() != Balloon::Size::SMALL) {
@@ -251,7 +311,7 @@ auto BalloonManager::popBalloon(std::shared_ptr<Balloon> balloon) -> int {
}
// Explosiona un globo. Lo destruye = no crea otros globos
auto BalloonManager::destroyBalloon(std::shared_ptr<Balloon> &balloon) -> int {
auto BalloonManager::destroyBalloon(std::shared_ptr<Balloon>& balloon) -> int {
int score = 0;
// Calcula la puntuación y el poder que generaria el globo en caso de romperlo a él y a sus hijos
@@ -274,7 +334,7 @@ auto BalloonManager::destroyBalloon(std::shared_ptr<Balloon> &balloon) -> int {
}
// Aumenta el poder de la fase
Stage::addPower(balloon->getPower());
stage_info_->addPower(balloon->getPower());
// Destruye el globo
explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize()));
@@ -286,12 +346,12 @@ auto BalloonManager::destroyBalloon(std::shared_ptr<Balloon> &balloon) -> int {
// Destruye todos los globos
auto BalloonManager::destroyAllBalloons() -> int {
int score = 0;
for (auto &balloon : balloons_) {
for (auto& balloon : balloons_) {
score += destroyBalloon(balloon);
}
balloon_deploy_counter_ = 300;
Screen::get()->flash(FLASH_COLOR, 3);
balloon_deploy_counter_ = DEFAULT_BALLOON_DEPLOY_DELAY;
Screen::get()->flash(Colors::FLASH, 0.05F);
Screen::get()->shake();
return score;
@@ -299,14 +359,16 @@ auto BalloonManager::destroyAllBalloons() -> int {
// Detiene todos los globos
void BalloonManager::stopAllBalloons() {
for (auto &balloon : balloons_) {
for (auto& balloon : balloons_) {
if (!balloon->isBeingCreated()) {
balloon->stop();
}
}
}
// Pone en marcha todos los globos
void BalloonManager::startAllBalloons() {
for (auto &balloon : balloons_) {
for (auto& balloon : balloons_) {
if (!balloon->isBeingCreated()) {
balloon->start();
}
@@ -315,7 +377,7 @@ void BalloonManager::startAllBalloons() {
// Cambia el color de todos los globos
void BalloonManager::reverseColorsToAllBalloons() {
for (auto &balloon : balloons_) {
for (auto& balloon : balloons_) {
if (balloon->isStopped()) {
balloon->useReverseColor();
}
@@ -324,7 +386,7 @@ void BalloonManager::reverseColorsToAllBalloons() {
// Cambia el color de todos los globos
void BalloonManager::normalColorsToAllBalloons() {
for (auto &balloon : balloons_) {
for (auto& balloon : balloons_) {
balloon->useNormalColor();
}
}
@@ -334,28 +396,15 @@ void BalloonManager::createTwoBigBalloons() {
deployFormation(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() % static_cast<int>(param.game.game_area.rect.w)) - Balloon::WIDTH.at(3);
const int Y = param.game.game_area.rect.y + (rand() % 50);
const auto SIZE = static_cast<Balloon::Size>(rand() % 4);
const float VEL_X = (rand() % 2 == 0) ? Balloon::VELX_POSITIVE : Balloon::VELX_NEGATIVE;
const int CREATION_COUNTER = 0;
createBalloon(X, Y, Balloon::Type::BALLOON, SIZE, VEL_X, balloon_speed_, CREATION_COUNTER);
}
}
// Obtiene el nivel de ameza actual generado por los globos
auto BalloonManager::getMenace() -> int {
return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon) { return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); });
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) {
sound_enabled_ = value;
for (auto &balloon : balloons_) {
for (auto& balloon : balloons_) {
balloon->setSound(value);
}
}
@@ -363,14 +412,14 @@ void BalloonManager::setSounds(bool value) {
// Activa o desactiva los sonidos de rebote los globos
void BalloonManager::setBouncingSounds(bool value) {
bouncing_sound_enabled_ = value;
for (auto &balloon : balloons_) {
for (auto& balloon : balloons_) {
balloon->setBouncingSound(value);
}
}
// Activa o desactiva los sonidos de los globos al explotar
void BalloonManager::setPoppingSounds(bool value) {
poping_sound_enabled_ = value;
for (auto &balloon : balloons_) {
for (auto& balloon : balloons_) {
balloon->setPoppingSound(value);
}
}

View File

@@ -12,98 +12,104 @@
#include "balloon_formations.h" // Para BalloonFormations
#include "explosions.h" // Para Explosions
#include "param.h" // Para Param, ParamGame, param
#include "stage_interface.h" // Para IStageInfo
#include "utils.h" // Para Zone
class Texture;
// --- Types ---
using Balloons = std::vector<std::shared_ptr<Balloon>>;
// Clase BalloonManager
// --- Clase BalloonManager: gestiona todos los globos del juego ---
class BalloonManager {
public:
// Constructor y Destructor
BalloonManager();
// --- Constructor y destructor ---
BalloonManager(IStageInfo *stage_info);
~BalloonManager() = default;
// Actualización y Renderizado
void update(); // Actualiza el estado de los globos
// --- Métodos principales ---
void update(float deltaTime); // Actualiza el estado de los globos (time-based)
void render(); // Renderiza los globos en pantalla
// Gestión de globos
// --- Gestión de globos ---
void freeBalloons(); // Libera globos que ya no sirven
// Creación de formaciones enemigas
// --- Creación de formaciones enemigas ---
void deployRandomFormation(int stage); // Crea una formación de globos aleatoria
void deployFormation(int formation_id); // Crea una formación específica
void deployFormation(int formation_id, int y); // Crea una formación específica con coordenadas
void deployFormation(int formation_id, float y); // Crea una formación específica con coordenadas
// Creación de globos
auto createBalloon(float x, int y, Balloon::Type type, Balloon::Size size, float velx, float speed, int creation_timer) -> std::shared_ptr<Balloon>; // Crea un nuevo globo
// --- Creación de globos ---
auto createBalloon(Balloon::Config config) -> std::shared_ptr<Balloon>; // Crea un nuevo globo
void createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction); // Crea un globo a partir de otro
void createPowerBall(); // Crea una PowerBall
void createTwoBigBalloons(); // Crea dos globos grandes
void createRandomBalloons(); // Crea una disposición aleatoria de globos
// Control de velocidad y despliegue
// --- Control de velocidad y despliegue ---
void setBalloonSpeed(float speed); // Ajusta la velocidad de los globos
void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; }; // Establece la velocidad base
void resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); }; // Restablece la velocidad de los globos
void updateBalloonDeployCounter(); // Actualiza el contador de despliegue
void updateBalloonDeployCounter(float deltaTime); // Actualiza el contador de despliegue (time-based)
auto canPowerBallBeCreated() -> bool; // Indica si se puede crear una PowerBall
auto calculateScreenPower() -> int; // Calcula el poder de los globos en pantalla
// Manipulación de globos existentes
auto popBalloon(std::shared_ptr<Balloon> balloon) -> int; // Explosiona un globo, creando otros si aplica
// --- Manipulación de globos existentes ---
auto popBalloon(const std::shared_ptr<Balloon> &balloon) -> int; // Explosiona un globo, creando otros si aplica
auto destroyBalloon(std::shared_ptr<Balloon> &balloon) -> int; // Explosiona un globo sin crear otros
auto destroyAllBalloons() -> int; // Destruye todos los globos
void stopAllBalloons(); // Detiene el movimiento de los globos
void startAllBalloons(); // Reactiva el movimiento de los globos
// Cambios de apariencia
// --- Cambios de apariencia ---
void reverseColorsToAllBalloons(); // Invierte los colores de los globos
void normalColorsToAllBalloons(); // Restaura los colores originales
// Configuración de sonido
// --- Configuración de sonido ---
void setSounds(bool value); // Activa o desactiva los sonidos de los globos
void setBouncingSounds(bool value); // Activa o desactiva los sonidos de rebote los globos
void setPoppingSounds(bool value); // Activa o desactiva los sonidos de los globos al explotar
// Configuración de juego
// --- Configuración de juego ---
void setPlayArea(SDL_FRect play_area) { play_area_ = play_area; }; // Define el área de juego
void setCreationTimeEnabled(bool value) { creation_time_enabled_ = value; }; // Activa o desactiva el tiempo de creación de globos
void enableBalloonDeployment(bool value) { can_deploy_balloons_ = value; }; // Activa o desactiva la generación de globos
// Obtención de información
// --- Getters ---
auto getMenace() -> int; // Obtiene el nivel de amenaza generado por los globos
[[nodiscard]] auto getBalloonSpeed() const -> float { return balloon_speed_; }
auto getBalloons() -> Balloons & { return balloons_; }
[[nodiscard]] auto getNumBalloons() const -> int { return balloons_.size(); }
private:
// --- Constantes ---
static constexpr float DEFAULT_BALLOON_DEPLOY_DELAY = 5.0f; // 300 frames = 5 segundos
static constexpr float POWERBALL_DEPLOY_DELAY = 0.167f; // 10 frames = 0.167 segundos
static constexpr float BALLOON_POP_DELAY = 0.333f; // 20 frames = 0.333 segundos
// --- Objetos y punteros ---
Balloons balloons_; // Vector con los globos activos
std::unique_ptr<Explosions> explosions_; // Objeto para gestionar explosiones
std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para manejar formaciones enemigas
std::vector<std::shared_ptr<Texture>> balloon_textures_; // Texturas de los globos
std::vector<std::shared_ptr<Texture>> explosions_textures_; // Texturas de explosiones
std::vector<std::vector<std::string>> balloon_animations_; // Animaciones de los globos
std::vector<std::vector<std::string>> explosions_animations_; // Animaciones de las explosiones
IStageInfo *stage_info_; // Informacion de la pantalla actual
// Variables de control de globos
float balloon_speed_ = Balloon::SPEED.at(0);
float default_balloon_speed_ = Balloon::SPEED.at(0);
int balloon_deploy_counter_ = 0;
bool power_ball_enabled_ = false;
// --- Variables de estado ---
SDL_FRect play_area_ = param.game.play_area.rect;
float balloon_speed_ = Balloon::GAME_TEMPO.at(0);
float default_balloon_speed_ = Balloon::GAME_TEMPO.at(0);
float balloon_deploy_counter_ = 0;
int power_ball_counter_ = 0;
int last_balloon_deploy_ = 0;
SDL_FRect play_area_ = param.game.play_area.rect;
bool power_ball_enabled_ = false;
bool creation_time_enabled_ = true;
bool can_deploy_balloons_ = true;
bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar
bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar
bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido
// Metodos privados
// --- Métodos internos ---
void init();
};

View File

@@ -4,46 +4,64 @@
#include <string> // Para char_traits, basic_string, operator+, string
#include "param.h" // Para Param, ParamGame, param
#include "player.h" // Para Player::Id
#include "resource.h" // Para Resource
// Constructor
Bullet::Bullet(float x, float y, BulletType bullet_type, bool powered, Player::Id owner)
Bullet::Bullet(float x, float y, Type type, Color color, int owner)
: sprite_(std::make_unique<AnimatedSprite>(Resource::get()->getTexture("bullet.png"), Resource::get()->getAnimation("bullet.ani"))),
type_(type),
owner_(owner),
pos_x_(x),
pos_y_(y),
bullet_type_(bullet_type),
owner_(owner) {
vel_x_ = calculateVelocity(bullet_type_);
sprite_->setCurrentAnimation(buildAnimationString(bullet_type_, powered));
pos_y_(y) {
vel_x_ = calculateVelocity(type_);
sprite_->setCurrentAnimation(buildAnimationString(type_, color));
collider_.r = WIDTH / 2;
shiftColliders();
}
// Calcula la velocidad horizontal de la bala basada en su tipo
auto Bullet::calculateVelocity(BulletType bullet_type) -> float {
switch (bullet_type) {
case BulletType::LEFT:
auto Bullet::calculateVelocity(Type type) -> float {
switch (type) {
case Type::LEFT:
return VEL_X_LEFT;
case BulletType::RIGHT:
case Type::RIGHT:
return VEL_X_RIGHT;
default:
return VEL_X_CENTER;
}
}
// Construye el string de animación basado en el tipo de bala y si está potenciada
auto Bullet::buildAnimationString(BulletType bullet_type, bool powered) -> std::string {
std::string animation_string = powered ? "powered_" : "normal_";
// Construye el string de animación basado en el tipo de bala y color específico
auto Bullet::buildAnimationString(Type type, Color color) -> std::string {
std::string animation_string;
switch (bullet_type) {
case BulletType::UP:
// Mapear color a string específico
switch (color) {
case Color::YELLOW:
animation_string = "yellow_";
break;
case Color::GREEN:
animation_string = "green_";
break;
case Color::RED:
animation_string = "red_";
break;
case Color::PURPLE:
animation_string = "purple_";
break;
}
// Añadir dirección
switch (type) {
case Type::UP:
animation_string += "up";
break;
case BulletType::LEFT:
case Type::LEFT:
animation_string += "left";
break;
case BulletType::RIGHT:
case Type::RIGHT:
animation_string += "right";
break;
default:
@@ -53,48 +71,48 @@ auto Bullet::buildAnimationString(BulletType bullet_type, bool powered) -> std::
return animation_string;
}
// Implementación de render (llama al render del sprite_)
// Implementación de render
void Bullet::render() {
if (bullet_type_ != BulletType::NONE) {
if (type_ != Type::NONE) {
sprite_->render();
}
}
// Actualiza el estado del objeto
auto Bullet::update() -> BulletMoveStatus {
sprite_->update();
return move();
auto Bullet::update(float deltaTime) -> MoveStatus {
sprite_->update(deltaTime);
return move(deltaTime);
}
// Implementación del movimiento usando BulletMoveStatus
auto Bullet::move() -> BulletMoveStatus {
pos_x_ += vel_x_;
// Implementación del movimiento usando MoveStatus
auto Bullet::move(float deltaTime) -> MoveStatus {
pos_x_ += vel_x_ * deltaTime;
if (pos_x_ < param.game.play_area.rect.x - WIDTH || pos_x_ > param.game.play_area.rect.w) {
disable();
return BulletMoveStatus::OUT;
return MoveStatus::OUT;
}
pos_y_ += VEL_Y;
pos_y_ += VEL_Y * deltaTime;
if (pos_y_ < param.game.play_area.rect.y - HEIGHT) {
disable();
return BulletMoveStatus::OUT;
return MoveStatus::OUT;
}
shiftSprite();
shiftColliders();
return BulletMoveStatus::OK;
return MoveStatus::OK;
}
auto Bullet::isEnabled() const -> bool {
return bullet_type_ != BulletType::NONE;
return type_ != Type::NONE;
}
void Bullet::disable() {
bullet_type_ = BulletType::NONE;
type_ = Type::NONE;
}
auto Bullet::getOwner() const -> Player::Id {
auto Bullet::getOwner() const -> int {
return owner_;
}

View File

@@ -6,68 +6,71 @@
#include <string> // Para string
#include "animated_sprite.h" // Para AnimatedSprite
#include "player.h" // Para Player
#include "utils.h" // Para Circle
// Tipos de balas
enum class BulletType : Uint8 {
UP,
LEFT,
RIGHT,
NONE
};
// Resultado del movimiento de la bala
enum class BulletMoveStatus : Uint8 {
OK = 0,
OUT = 1
};
// Clase Bullet
// --- Clase Bullet: representa una bala del jugador ---
class Bullet {
public:
// Constantes
static constexpr float WIDTH = 12.0F;
static constexpr float HEIGHT = 12.0F;
// --- Constantes ---
static constexpr float WIDTH = 12.0F; // Anchura de la bala
static constexpr float HEIGHT = 12.0F; // Altura de la bala
// Constructor y Destructor
Bullet(float x, float y, BulletType bullet_type, bool powered, Player::Id owner);
~Bullet() = default;
// --- Enums ---
enum class Type : Uint8 {
UP, // Bala hacia arriba
LEFT, // Bala hacia la izquierda
RIGHT, // Bala hacia la derecha
NONE // Sin bala
};
// Métodos principales
enum class MoveStatus : Uint8 {
OK = 0, // Movimiento normal
OUT = 1 // Fuera de los límites
};
enum class Color : Uint8 {
YELLOW,
GREEN,
RED,
PURPLE
};
// --- Constructor y destructor ---
Bullet(float x, float y, Type type, Color color, int owner); // Constructor principal
~Bullet() = default; // Destructor
// --- Métodos principales ---
void render(); // Dibuja la bala en pantalla
auto update() -> BulletMoveStatus; // Actualiza el estado del objeto
// Estado de la bala
[[nodiscard]] auto isEnabled() const -> bool; // Comprueba si está activa
auto update(float deltaTime) -> MoveStatus; // Actualiza el estado del objeto (time-based)
void disable(); // Desactiva la bala
// Getters
[[nodiscard]] auto getOwner() const -> Player::Id; // Devuelve el identificador del dueño
auto getCollider() -> Circle &; // Devuelve el círculo de colisión
// --- Getters ---
[[nodiscard]] auto isEnabled() const -> bool; // Comprueba si está activa
[[nodiscard]] auto getOwner() const -> int; // Devuelve el identificador del dueño
auto getCollider() -> Circle&; // Devuelve el círculo de colisión
private:
// Constantes
static constexpr float VEL_Y = -3.0F;
static constexpr float VEL_X_LEFT = -2.0F;
static constexpr float VEL_X_RIGHT = 2.0F;
static constexpr float VEL_X_CENTER = 0.0F;
// --- Constantes ---
static constexpr float VEL_Y = -180.0F; // Velocidad vertical (pixels/segundo) - era -0.18F pixels/ms
static constexpr float VEL_X_LEFT = -120.0F; // Velocidad izquierda (pixels/segundo) - era -0.12F pixels/ms
static constexpr float VEL_X_RIGHT = 120.0F; // Velocidad derecha (pixels/segundo) - era 0.12F pixels/ms
static constexpr float VEL_X_CENTER = 0.0F; // Velocidad central
// Propiedades
// --- Objetos y punteros ---
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos
// --- Variables de estado ---
Circle collider_; // Círculo de colisión
Type type_; // Tipo de bala
int owner_; // Identificador del jugador
float pos_x_; // Posición en el eje X
float pos_y_; // Posición en el eje Y
float vel_x_; // Velocidad en el eje X
BulletType bullet_type_; // Tipo de bala
Player::Id owner_; // Identificador del dueño
Circle collider_; // Círculo de colisión
// Métodos internos
// --- Métodos internos ---
void shiftColliders(); // Ajusta el círculo de colisión
void shiftSprite(); // Ajusta el sprite
auto move() -> BulletMoveStatus; // Mueve la bala y devuelve su estado
static auto calculateVelocity(BulletType bullet_type) -> float; // Calcula la velocidad horizontal de la bala basada en su tipo
static auto buildAnimationString(BulletType bullet_type, bool powered) -> std::string; // Construye el string de animación basado en el tipo de bala y si está potenciada
auto move(float deltaTime) -> MoveStatus; // Mueve la bala y devuelve su estado (time-based)
static auto calculateVelocity(Type type) -> float; // Calcula la velocidad horizontal de la bala
static auto buildAnimationString(Type type, Color color) -> std::string; // Construye el string de animación
};

109
source/bullet_manager.cpp Normal file
View File

@@ -0,0 +1,109 @@
#include "bullet_manager.h"
#include <algorithm> // Para remove_if
#include "bullet.h" // Para Bullet
#include "param.h" // Para param
#include "player.h" // Para Player
// Constructor
BulletManager::BulletManager()
: play_area_(param.game.play_area.rect) {
}
// Actualiza el estado de todas las balas
void BulletManager::update(float deltaTime) {
for (auto& bullet : bullets_) {
if (bullet->isEnabled()) {
processBulletUpdate(bullet, deltaTime);
}
}
}
// Renderiza todas las balas activas
void BulletManager::render() {
for (auto& bullet : bullets_) {
if (bullet->isEnabled()) {
bullet->render();
}
}
}
// Crea una nueva bala
void BulletManager::createBullet(int x, int y, Bullet::Type type, Bullet::Color color, int owner) {
bullets_.emplace_back(std::make_shared<Bullet>(x, y, type, color, owner));
}
// Libera balas que ya no están habilitadas
void BulletManager::freeBullets() {
if (!bullets_.empty()) {
// Elimina las balas deshabilitadas del vector
bullets_.erase(
std::remove_if(bullets_.begin(), bullets_.end(),
[](const std::shared_ptr<Bullet>& bullet) {
return !bullet->isEnabled();
}),
bullets_.end());
}
}
// Elimina todas las balas
void BulletManager::clearAllBullets() {
bullets_.clear();
}
// Verifica colisiones de todas las balas
void BulletManager::checkCollisions() {
for (auto& bullet : bullets_) {
if (!bullet->isEnabled()) {
continue;
}
// Verifica colisión con Tabe
if (tabe_collision_callback_ && tabe_collision_callback_(bullet)) {
break; // Sale del bucle si hubo colisión
}
// Verifica colisión con globos
if (balloon_collision_callback_ && balloon_collision_callback_(bullet)) {
break; // Sale del bucle si hubo colisión
}
}
}
// Establece el callback para colisión con Tabe
void BulletManager::setTabeCollisionCallback(CollisionCallback callback) {
tabe_collision_callback_ = callback;
}
// Establece el callback para colisión con globos
void BulletManager::setBalloonCollisionCallback(CollisionCallback callback) {
balloon_collision_callback_ = callback;
}
// Establece el callback para balas fuera de límites
void BulletManager::setOutOfBoundsCallback(OutOfBoundsCallback callback) {
out_of_bounds_callback_ = callback;
}
// --- Métodos privados ---
// Procesa la actualización individual de una bala
void BulletManager::processBulletUpdate(const std::shared_ptr<Bullet>& bullet, float deltaTime) {
auto status = bullet->update(deltaTime);
// Si la bala salió de los límites, llama al callback
if (status == Bullet::MoveStatus::OUT && out_of_bounds_callback_) {
out_of_bounds_callback_(bullet);
}
}
// Verifica si la bala está fuera de los límites del área de juego
auto BulletManager::isBulletOutOfBounds(const std::shared_ptr<Bullet>& bullet) -> bool {
auto collider = bullet->getCollider();
return (collider.x < play_area_.x ||
collider.x > play_area_.x + play_area_.w ||
collider.y < play_area_.y ||
collider.y > play_area_.y + play_area_.h);
}

79
source/bullet_manager.h Normal file
View File

@@ -0,0 +1,79 @@
#pragma once
#include <SDL3/SDL.h> // Para SDL_FRect
#include <functional> // Para function
#include <memory> // Para shared_ptr, unique_ptr
#include <vector> // Para vector
#include "bullet.h" // Para Bullet
#include "utils.h" // Para Circle
// --- Types ---
using Bullets = std::vector<std::shared_ptr<Bullet>>;
// --- Forward declarations ---
class Player;
// --- Clase BulletManager: gestiona todas las balas del juego ---
//
// Esta clase se encarga de la gestión completa de las balas del juego,
// incluyendo su creación, actualización, renderizado y colisiones.
//
// Funcionalidades principales:
// • Gestión del ciclo de vida: creación, actualización y destrucción de balas
// • Renderizado: dibuja todas las balas activas en pantalla
// • Detección de colisiones: mediante sistema de callbacks
// • Limpieza automática: elimina balas deshabilitadas del contenedor
// • Configuración flexible: permite ajustar parámetros de las balas
//
// La clase utiliza un sistema de callbacks para manejar las colisiones,
// permitiendo que la lógica específica del juego permanezca en Game.
class BulletManager {
public:
// --- Types para callbacks ---
using CollisionCallback = std::function<bool(const std::shared_ptr<Bullet>&)>;
using OutOfBoundsCallback = std::function<void(const std::shared_ptr<Bullet>&)>;
// --- Constructor y destructor ---
BulletManager();
~BulletManager() = default;
// --- Métodos principales ---
void update(float deltaTime); // Actualiza el estado de las balas (time-based)
void render(); // Renderiza las balas en pantalla
// --- Gestión de balas ---
void createBullet(int x, int y, Bullet::Type type, Bullet::Color color, int owner); // Crea una nueva bala
void freeBullets(); // Libera balas que ya no sirven
void clearAllBullets(); // Elimina todas las balas
// --- Detección de colisiones ---
void checkCollisions(); // Verifica colisiones de todas las balas
void setTabeCollisionCallback(CollisionCallback callback); // Establece callback para colisión con Tabe
void setBalloonCollisionCallback(CollisionCallback callback); // Establece callback para colisión con globos
void setOutOfBoundsCallback(OutOfBoundsCallback callback); // Establece callback para balas fuera de límites
// --- Configuración ---
void setPlayArea(SDL_FRect play_area) { play_area_ = play_area; }; // Define el área de juego
// --- Getters ---
auto getBullets() -> Bullets& { return bullets_; } // Obtiene referencia al vector de balas
[[nodiscard]] auto getNumBullets() const -> int { return bullets_.size(); } // Obtiene el número de balas activas
private:
// --- Objetos y punteros ---
Bullets bullets_; // Vector con las balas activas
// --- Variables de configuración ---
SDL_FRect play_area_; // Área de juego para límites
// --- Callbacks para colisiones ---
CollisionCallback tabe_collision_callback_; // Callback para colisión con Tabe
CollisionCallback balloon_collision_callback_; // Callback para colisión con globos
OutOfBoundsCallback out_of_bounds_callback_; // Callback para balas fuera de límites
// --- Métodos internos ---
void processBulletUpdate(const std::shared_ptr<Bullet>& bullet, float deltaTime); // Procesa actualización individual
auto isBulletOutOfBounds(const std::shared_ptr<Bullet>& bullet) -> bool; // Verifica si la bala está fuera de límites
};

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