Compare commits
23 Commits
6102504d32
...
2025-08-17
| Author | SHA1 | Date | |
|---|---|---|---|
| 2819b3628e | |||
| 1e9e664012 | |||
| 0c8b39cee7 | |||
| d7b3af5ab8 | |||
| 5e5227305f | |||
| 3fc15a9512 | |||
| e774e0e8ad | |||
| a95776e6c7 | |||
| 0428ff26d5 | |||
| fc3e2deb1f | |||
| 65ca17f938 | |||
| ff2a51a507 | |||
| fe0083abd4 | |||
| 1c058694fd | |||
| cb0c3266d5 | |||
| 8ddc5d94f1 | |||
| b359a73d50 | |||
| 142603db71 | |||
| 1ec272f017 | |||
| 327987447d | |||
| ada5025c65 | |||
| 1ced698093 | |||
| 2a4c47a6ca |
@@ -6,7 +6,14 @@ BreakBeforeBraces: Attach # Llaves en la misma línea
|
|||||||
AllowShortIfStatementsOnASingleLine: true
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
AllowShortBlocksOnASingleLine: true
|
AllowShortBlocksOnASingleLine: true
|
||||||
AllowShortFunctionsOnASingleLine: All
|
AllowShortFunctionsOnASingleLine: All
|
||||||
AlignOperands: false
|
AlignOperands: DontAlign
|
||||||
AlignAfterOpenBracket: DontAlign
|
AlignAfterOpenBracket: DontAlign
|
||||||
BinPackArguments: false
|
BinPackArguments: false
|
||||||
BinPackParameters: false
|
BinPackParameters: false
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
AllowAllArgumentsOnNextLine: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
|||||||
15
.clang-tidy
15
.clang-tidy
@@ -1,8 +1,21 @@
|
|||||||
Checks: >
|
Checks: >
|
||||||
readability-*,
|
readability-*,
|
||||||
modernize-*,
|
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-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: '*'
|
WarningsAsErrors: '*'
|
||||||
# Solo incluir archivos de tu código fuente
|
# Solo incluir archivos de tu código fuente
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ DATA|${PREFIX}/data/config/formations.txt
|
|||||||
DATA|${PREFIX}/data/config/gamecontrollerdb.txt
|
DATA|${PREFIX}/data/config/gamecontrollerdb.txt
|
||||||
DATA|${PREFIX}/data/config/param_320x240.txt
|
DATA|${PREFIX}/data/config/param_320x240.txt
|
||||||
DATA|${PREFIX}/data/config/param_320x256.txt
|
DATA|${PREFIX}/data/config/param_320x256.txt
|
||||||
|
DATA|${PREFIX}/data/config/param_red.txt
|
||||||
DATA|${PREFIX}/data/config/pools.txt
|
DATA|${PREFIX}/data/config/pools.txt
|
||||||
DATA|${PREFIX}/data/config/stages.txt
|
DATA|${PREFIX}/data/config/stages.txt
|
||||||
DEMODATA|${PREFIX}/data/config/demo1.bin
|
DEMODATA|${PREFIX}/data/config/demo1.bin
|
||||||
@@ -56,12 +57,12 @@ SOUND|${PREFIX}/data/sound/tabe_hit.wav
|
|||||||
SOUND|${PREFIX}/data/sound/tabe.wav
|
SOUND|${PREFIX}/data/sound/tabe.wav
|
||||||
SOUND|${PREFIX}/data/sound/title.wav
|
SOUND|${PREFIX}/data/sound/title.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_aw_aw_aw.wav
|
SOUND|${PREFIX}/data/sound/voice_aw_aw_aw.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_brbrbr.wav
|
|
||||||
SOUND|${PREFIX}/data/sound/voice_coffee.wav
|
SOUND|${PREFIX}/data/sound/voice_coffee.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_credit_thankyou.wav
|
SOUND|${PREFIX}/data/sound/voice_credit_thankyou.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_get_ready.wav
|
SOUND|${PREFIX}/data/sound/voice_get_ready.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_no.wav
|
SOUND|${PREFIX}/data/sound/voice_no.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_power_up.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/voice_thankyou.wav
|
||||||
SOUND|${PREFIX}/data/sound/walk.wav
|
SOUND|${PREFIX}/data/sound/walk.wav
|
||||||
|
|
||||||
@@ -177,6 +178,7 @@ BITMAP|${PREFIX}/data/font/04b_25_grey.png
|
|||||||
BITMAP|${PREFIX}/data/font/04b_25_metal.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_2x.png
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_reversed.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/04b_25.png
|
||||||
BITMAP|${PREFIX}/data/font/8bithud.png
|
BITMAP|${PREFIX}/data/font/8bithud.png
|
||||||
BITMAP|${PREFIX}/data/font/aseprite.png
|
BITMAP|${PREFIX}/data/font/aseprite.png
|
||||||
|
|||||||
@@ -2,26 +2,26 @@
|
|||||||
# Formato: PARAMETRO VALOR
|
# Formato: PARAMETRO VALOR
|
||||||
|
|
||||||
# --- GAME ---
|
# --- GAME ---
|
||||||
game.item_size 20 # Tamaño de los items del juego (en píxeles)
|
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.item_text_outline_color E0E0E0F0 # Color del outline del texto de los items (RGBA hex)
|
||||||
game.height 240 # Alto de la resolución nativa del juego (en píxeles)
|
game.width 320 # Ancho de la resolución nativa del juego (en píxeles)
|
||||||
game.play_area.rect.x 0 # Posición X de la zona jugable
|
game.height 240 # Alto de la resolución nativa del juego (en píxeles)
|
||||||
game.play_area.rect.y 0 # Posición Y de la zona jugable
|
game.play_area.rect.x 0 # Posición X de la zona jugable
|
||||||
game.play_area.rect.w 320 # Ancho de la zona jugable
|
game.play_area.rect.y 0 # Posición Y de la zona jugable
|
||||||
game.play_area.rect.h 200 # Alto de la zona jugable
|
game.play_area.rect.w 320 # Ancho 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.play_area.rect.h 200 # Alto de la zona jugable
|
||||||
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
|
game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
|
||||||
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
|
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
|
||||||
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
|
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 ---
|
||||||
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido
|
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_width 64 # 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.num_squares_height 48 # 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_duration_ms 1200 # Duración del fade en milisegundos
|
||||||
fade.random_squares_mult 500 # Multiplicador para la velocidad de aparición aleatoria
|
fade.post_duration_ms 500 # Duración tras el fundido en milisegundos
|
||||||
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)
|
||||||
fade.venetian_size 12 # Tamaño de las bandas para el efecto veneciano (en píxeles)
|
|
||||||
|
|
||||||
# --- SCOREBOARD ---
|
# --- SCOREBOARD ---
|
||||||
scoreboard.rect.x 0 # Posición X del marcador
|
scoreboard.rect.x 0 # Posición X del marcador
|
||||||
@@ -84,8 +84,8 @@ service_menu.window_message.title_color 6496C8FF # Color del tít
|
|||||||
service_menu.window_message.text_color DCDCDCFF # Color del texto 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.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.line_spacing 5.0f # Espaciado entre líneas de texto (píxeles)
|
||||||
service_menu.window_message.title_separator_spacing 10.0f # Espaciado entre título y contenido (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 250.0f # Ancho mínimo de ventanas de mensaje (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.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_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.max_height_ratio 0.8f # Ratio máximo de alto respecto a pantalla (0.0-1.0)
|
||||||
@@ -110,6 +110,18 @@ 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
|
tabe.max_spawn_time 3.0f # Tiempo máximo en minutos para que aparezca el Tabe
|
||||||
|
|
||||||
# --- PLAYER ---
|
# --- 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é
|
# 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].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].dark 4FA370FF # Tono oscuro - sombras (Jugador 1, 1 café)
|
||||||
@@ -132,4 +144,8 @@ player.one_coffee_shirt[1].light 55EF8DFF # Tono claro - zonas iluminadas
|
|||||||
player.two_coffee_shirt[1].darkest E08500FF # Tono más oscuro - bordes y contornos (Jugador 2, 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].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].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)
|
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
|
||||||
@@ -2,26 +2,26 @@
|
|||||||
# Formato: PARAMETRO VALOR
|
# Formato: PARAMETRO VALOR
|
||||||
|
|
||||||
# --- GAME ---
|
# --- GAME ---
|
||||||
game.item_size 20 # Tamaño de los items del juego (en píxeles)
|
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.item_text_outline_color E0E0E0F0 # Color del outline del texto de los items (RGBA hex)
|
||||||
game.height 256 # Alto de la resolución nativa del juego (en píxeles)
|
game.width 320 # Ancho de la resolución nativa del juego (en píxeles)
|
||||||
game.play_area.rect.x 0 # Posición X de la zona jugable
|
game.height 256 # Alto de la resolución nativa del juego (en píxeles)
|
||||||
game.play_area.rect.y 0 # Posición Y de la zona jugable
|
game.play_area.rect.x 0 # Posición X de la zona jugable
|
||||||
game.play_area.rect.w 320 # Ancho de la zona jugable
|
game.play_area.rect.y 0 # Posición Y de la zona jugable
|
||||||
game.play_area.rect.h 216 # Alto de la zona jugable
|
game.play_area.rect.w 320 # Ancho 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.play_area.rect.h 216 # Alto de la zona jugable
|
||||||
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
|
game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
|
||||||
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
|
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
|
||||||
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
|
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 ---
|
||||||
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido
|
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_width 64 # 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.num_squares_height 48 # 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_duration_ms 1200 # Duración del fade en milisegundos
|
||||||
fade.random_squares_mult 500 # Multiplicador para la velocidad de aparición aleatoria
|
fade.post_duration_ms 500 # Duración tras el fundido en milisegundos
|
||||||
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)
|
||||||
fade.venetian_size 12 # Tamaño de las bandas para el efecto veneciano (en píxeles)
|
|
||||||
|
|
||||||
# --- SCOREBOARD ---
|
# --- SCOREBOARD ---
|
||||||
scoreboard.rect.x 0 # Posición X del marcador
|
scoreboard.rect.x 0 # Posición X del marcador
|
||||||
@@ -84,8 +84,8 @@ service_menu.window_message.title_color 6496C8FF # Color del tít
|
|||||||
service_menu.window_message.text_color DCDCDCFF # Color del texto 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.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.line_spacing 5.0f # Espaciado entre líneas de texto (píxeles)
|
||||||
service_menu.window_message.title_separator_spacing 10.0f # Espaciado entre título y contenido (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 250.0f # Ancho mínimo de ventanas de mensaje (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.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_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.max_height_ratio 0.8f # Ratio máximo de alto respecto a pantalla (0.0-1.0)
|
||||||
@@ -109,6 +109,18 @@ tabe.min_spawn_time 2.0f # Tiempo mínimo en segundos para que aparezca el Ta
|
|||||||
tabe.max_spawn_time 3.0f # Tiempo máximo en segundos para que aparezca el Tabe
|
tabe.max_spawn_time 3.0f # Tiempo máximo en segundos para que aparezca el Tabe
|
||||||
|
|
||||||
# --- PLAYER ---
|
# --- 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é
|
# 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].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].dark 4FA370FF # Tono oscuro - sombras (Jugador 1, 1 café)
|
||||||
@@ -131,4 +143,8 @@ player.one_coffee_shirt[1].light 55EF8DFF # Tono claro - zonas iluminadas
|
|||||||
player.two_coffee_shirt[1].darkest E08500FF # Tono más oscuro - bordes y contornos (Jugador 2, 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].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].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)
|
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
data/config/param_red.txt
Normal file
150
data/config/param_red.txt
Normal 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
|
||||||
BIN
data/font/04b_25_white.png
Normal file
BIN
data/font/04b_25_white.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
BIN
data/sound/voice_recover.wav
Normal file
BIN
data/sound/voice_recover.wav
Normal file
Binary file not shown.
BIN
define_buttons.o
Normal file
BIN
define_buttons.o
Normal file
Binary file not shown.
15
linux_utils/generate_compile_commands_json.sh
Executable file
15
linux_utils/generate_compile_commands_json.sh
Executable 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
44
linux_utils/run_clang-tidy.sh
Executable 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!"
|
||||||
@@ -35,7 +35,7 @@ auto loadAnimationsFromFile(const std::string& file_path) -> AnimationsFileBuffe
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string& file_path)
|
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string& file_path)
|
||||||
: MovingSprite(texture) {
|
: MovingSprite(std::move(texture)) {
|
||||||
// Carga las animaciones
|
// Carga las animaciones
|
||||||
if (!file_path.empty()) {
|
if (!file_path.empty()) {
|
||||||
auto buffer = loadAnimationsFromFile(file_path);
|
auto buffer = loadAnimationsFromFile(file_path);
|
||||||
@@ -45,7 +45,7 @@ AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::stri
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer& animations)
|
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer& animations)
|
||||||
: MovingSprite(texture) {
|
: MovingSprite(std::move(texture)) {
|
||||||
if (!animations.empty()) {
|
if (!animations.empty()) {
|
||||||
loadFromAnimationsFileBuffer(animations);
|
loadFromAnimationsFileBuffer(animations);
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ void AnimatedSprite::loadFromAnimationsFileBuffer(const AnimationsFileBuffer& so
|
|||||||
|
|
||||||
// Procesa una línea de configuración
|
// Procesa una línea de configuración
|
||||||
void AnimatedSprite::processConfigLine(const std::string& line, AnimationConfig& config) {
|
void AnimatedSprite::processConfigLine(const std::string& line, AnimationConfig& config) {
|
||||||
size_t pos = line.find("=");
|
size_t pos = line.find('=');
|
||||||
if (pos == std::string::npos) {
|
if (pos == std::string::npos) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -230,7 +230,7 @@ auto AnimatedSprite::processAnimationBlock(const AnimationsFileBuffer& source, s
|
|||||||
|
|
||||||
// Procesa un parámetro individual de animación
|
// Procesa un parámetro individual de animación
|
||||||
void AnimatedSprite::processAnimationParameter(const std::string& line, Animation& animation, const AnimationConfig& config) {
|
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) {
|
if (pos == std::string::npos) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,14 +7,15 @@
|
|||||||
#include <memory> // Para allocator, shared_ptr
|
#include <memory> // Para allocator, shared_ptr
|
||||||
#include <string> // Para string, hash
|
#include <string> // Para string, hash
|
||||||
#include <unordered_map> // Para unordered_map
|
#include <unordered_map> // Para unordered_map
|
||||||
#include <vector> // Para vector
|
#include <utility>
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "moving_sprite.h" // Para MovingSprite
|
#include "moving_sprite.h" // Para MovingSprite
|
||||||
|
|
||||||
// Declaración adelantada
|
// Declaración adelantada
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Estructura de Animación
|
// --- Estructuras ---
|
||||||
struct Animation {
|
struct Animation {
|
||||||
static constexpr int DEFAULT_SPEED = 5;
|
static constexpr int DEFAULT_SPEED = 5;
|
||||||
|
|
||||||
@@ -37,19 +38,19 @@ struct AnimationConfig {
|
|||||||
int max_tiles = 1;
|
int max_tiles = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Alias de tipo para buffer de animaciones
|
// --- Tipos ---
|
||||||
using AnimationsFileBuffer = std::vector<std::string>;
|
using AnimationsFileBuffer = std::vector<std::string>; // Buffer de animaciones
|
||||||
|
|
||||||
// Carga las animaciones desde un fichero en un vector de strings
|
// --- Funciones ---
|
||||||
auto loadAnimationsFromFile(const std::string& file_path) -> AnimationsFileBuffer;
|
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 {
|
class AnimatedSprite : public MovingSprite {
|
||||||
public:
|
public:
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
AnimatedSprite(std::shared_ptr<Texture> texture, const std::string& file_path);
|
AnimatedSprite(std::shared_ptr<Texture> texture, const std::string& file_path);
|
||||||
AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer& animations);
|
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;
|
~AnimatedSprite() override = default;
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
@@ -70,12 +71,10 @@ class AnimatedSprite : public MovingSprite {
|
|||||||
auto getAnimationIndex(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:
|
protected:
|
||||||
// --- Datos de animación ---
|
// --- Variables de estado ---
|
||||||
std::vector<Animation> animations_; // Vector de animaciones disponibles
|
std::vector<Animation> animations_; // Vector de animaciones disponibles
|
||||||
int current_animation_ = 0; // Índice de la animación activa
|
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 ---
|
// --- Métodos internos ---
|
||||||
void animate(); // Calcula el frame correspondiente a la animación
|
void animate(); // Calcula el frame correspondiente a la animación
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ void Asset::loadFromFile(const std::string &config_file_path, const std::string
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::string type_str = parts[0];
|
const std::string &type_str = parts[0];
|
||||||
std::string path = parts[1];
|
std::string path = parts[1];
|
||||||
|
|
||||||
// Valores por defecto
|
// Valores por defecto
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string> // Para string
|
||||||
#include <unordered_map>
|
#include <unordered_map> // Para unordered_map
|
||||||
#include <utility>
|
#include <utility> // Para move
|
||||||
#include <vector>
|
#include <vector> // Para vector
|
||||||
|
|
||||||
// Clase Asset: gestor optimizado de recursos (singleton)
|
// --- Clase Asset: gestor optimizado de recursos (singleton) ---
|
||||||
class Asset {
|
class Asset {
|
||||||
public:
|
public:
|
||||||
// Tipos de recursos
|
// --- Enums ---
|
||||||
enum class Type : int {
|
enum class Type : int {
|
||||||
BITMAP,
|
BITMAP, // Imágenes
|
||||||
MUSIC,
|
MUSIC, // Música
|
||||||
SOUND,
|
SOUND, // Sonidos
|
||||||
FONT,
|
FONT, // Fuentes
|
||||||
LANG,
|
LANG, // Idiomas
|
||||||
DATA,
|
DATA, // Datos
|
||||||
DEMODATA,
|
DEMODATA, // Datos de demo
|
||||||
ANIMATION,
|
ANIMATION, // Animaciones
|
||||||
PALETTE,
|
PALETTE, // Paletas
|
||||||
SIZE,
|
SIZE, // Tamaño
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Métodos de singleton ---
|
// --- Métodos de singleton ---
|
||||||
@@ -38,9 +38,9 @@ class Asset {
|
|||||||
[[nodiscard]] auto exists(const std::string &filename) const -> bool; // Nueva función para verificar existencia
|
[[nodiscard]] auto exists(const std::string &filename) const -> bool; // Nueva función para verificar existencia
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Estructura interna para almacenar información de cada recurso ---
|
// --- Estructuras privadas ---
|
||||||
struct Item {
|
struct Item {
|
||||||
std::string file; // Ruta completa del archivo (mantener nombre original)
|
std::string file; // Ruta completa del archivo
|
||||||
Type type; // Tipo de recurso
|
Type type; // Tipo de recurso
|
||||||
bool required; // Indica si el archivo es obligatorio
|
bool required; // Indica si el archivo es obligatorio
|
||||||
|
|
||||||
@@ -49,21 +49,22 @@ class Asset {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// --- Variables internas ---
|
// --- 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
|
std::string executable_path_; // Ruta del ejecutable
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
[[nodiscard]] static auto checkFile(const std::string &path) -> bool;
|
[[nodiscard]] static auto checkFile(const std::string &path) -> bool; // Verifica si un archivo existe
|
||||||
[[nodiscard]] static auto getTypeName(Type type) -> std::string;
|
[[nodiscard]] static auto getTypeName(Type type) -> std::string; // Obtiene el nombre del tipo
|
||||||
[[nodiscard]] static auto parseAssetType(const std::string &type_str) -> Type;
|
[[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);
|
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;
|
[[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;
|
static auto parseOptions(const std::string &options, bool &required, bool &absolute) -> void; // Parsea opciones
|
||||||
|
|
||||||
// --- Patrón Singleton ---
|
// --- Constructores y destructor privados (singleton) ---
|
||||||
explicit Asset(std::string executable_path)
|
explicit Asset(std::string executable_path) // Constructor privado
|
||||||
: executable_path_(std::move(executable_path)) {}
|
: executable_path_(std::move(executable_path)) {}
|
||||||
~Asset() = default;
|
~Asset() = default; // Destructor privado
|
||||||
|
|
||||||
static Asset *instance;
|
// --- Instancia singleton ---
|
||||||
|
static Asset *instance; // Instancia única de Asset
|
||||||
};
|
};
|
||||||
@@ -3,19 +3,20 @@
|
|||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <utility> // Para move
|
#include <utility> // Para move
|
||||||
|
|
||||||
// Clase Audio: gestor de audio (singleton)
|
// --- Clase Audio: gestor de audio (singleton) ---
|
||||||
class Audio {
|
class Audio {
|
||||||
public:
|
public:
|
||||||
|
// --- Enums ---
|
||||||
enum class Group : int {
|
enum class Group : int {
|
||||||
ALL = -1,
|
ALL = -1, // Todos los grupos
|
||||||
GAME = 0,
|
GAME = 0, // Sonidos del juego
|
||||||
INTERFACE = 1
|
INTERFACE = 1 // Sonidos de la interfaz
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr int MAX_VOLUME = 100;
|
static constexpr int MAX_VOLUME = 100; // Volumen máximo
|
||||||
static constexpr int MIN_VOLUME = 0;
|
static constexpr int MIN_VOLUME = 0; // Volumen mínimo
|
||||||
static constexpr int FREQUENCY = 48000;
|
static constexpr int FREQUENCY = 48000; // Frecuencia de audio
|
||||||
|
|
||||||
// --- Métodos de singleton ---
|
// --- Métodos de singleton ---
|
||||||
static void init(); // Inicializa el objeto Audio
|
static void init(); // Inicializa el objeto Audio
|
||||||
@@ -60,12 +61,14 @@ class Audio {
|
|||||||
void setMusicVolume(int volume) const; // Ajustar volumen de música
|
void setMusicVolume(int volume) const; // Ajustar volumen de música
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// --- Enums privados ---
|
||||||
enum class MusicState {
|
enum class MusicState {
|
||||||
PLAYING,
|
PLAYING, // Reproduciendo música
|
||||||
PAUSED,
|
PAUSED, // Música pausada
|
||||||
STOPPED,
|
STOPPED, // Música detenida
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- Estructuras privadas ---
|
||||||
struct Music {
|
struct Music {
|
||||||
MusicState state; // Estado actual de la música (reproduciendo, detenido, en pausa)
|
MusicState state; // Estado actual de la música (reproduciendo, detenido, en pausa)
|
||||||
std::string name; // Última pista de música reproducida
|
std::string name; // Última pista de música reproducida
|
||||||
@@ -79,20 +82,19 @@ class Audio {
|
|||||||
: 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 ---
|
||||||
|
Music music_; // Estado de la música
|
||||||
// --- Variables de Estado ---
|
|
||||||
bool enabled_ = true; // Estado general del audio
|
bool enabled_ = true; // Estado general del audio
|
||||||
bool sound_enabled_ = true; // Estado de los efectos de sonido
|
bool sound_enabled_ = true; // Estado de los efectos de sonido
|
||||||
bool music_enabled_ = true; // Estado de la música
|
bool music_enabled_ = true; // Estado de la música
|
||||||
|
|
||||||
// --- Inicializa SDL Audio ---
|
// --- Métodos internos ---
|
||||||
void initSDLAudio();
|
void initSDLAudio(); // Inicializa SDL Audio
|
||||||
|
|
||||||
// --- Patrón Singleton ---
|
// --- Constructores y destructor privados (singleton) ---
|
||||||
Audio(); // Constructor privado
|
Audio(); // Constructor privado
|
||||||
~Audio(); // Destructor privado
|
~Audio(); // Destructor privado
|
||||||
|
|
||||||
// --- Singleton ---
|
// --- Instancia singleton ---
|
||||||
static Audio *instance;
|
static Audio *instance; // Instancia única de Audio
|
||||||
};
|
};
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <algorithm> // Para clamp, max
|
#include <algorithm> // Para clamp, max
|
||||||
#include <cmath> // Para M_PI, cos, sin
|
#include <cmath> // Para M_PI, cos, sin
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "moving_sprite.h" // Para MovingSprite
|
#include "moving_sprite.h" // Para MovingSprite
|
||||||
#include "param.h" // Para Param, ParamBackground, param
|
#include "param.h" // Para Param, ParamBackground, param
|
||||||
@@ -15,11 +16,7 @@
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Background::Background(float total_progress_to_complete)
|
Background::Background(float total_progress_to_complete)
|
||||||
: total_progress_to_complete_(total_progress_to_complete),
|
: renderer_(Screen::get()->getRenderer()),
|
||||||
progress_per_stage_(total_progress_to_complete_ / STAGES),
|
|
||||||
sun_completion_progress_(total_progress_to_complete_ * SUN_COMPLETION_FACTOR),
|
|
||||||
|
|
||||||
renderer_(Screen::get()->getRenderer()),
|
|
||||||
|
|
||||||
buildings_texture_(Resource::get()->getTexture("game_buildings.png")),
|
buildings_texture_(Resource::get()->getTexture("game_buildings.png")),
|
||||||
top_clouds_texture_(Resource::get()->getTexture("game_clouds1.png")),
|
top_clouds_texture_(Resource::get()->getTexture("game_clouds1.png")),
|
||||||
@@ -29,9 +26,13 @@ Background::Background(float total_progress_to_complete)
|
|||||||
sun_texture_(Resource::get()->getTexture("game_sun.png")),
|
sun_texture_(Resource::get()->getTexture("game_sun.png")),
|
||||||
moon_texture_(Resource::get()->getTexture("game_moon.png")),
|
moon_texture_(Resource::get()->getTexture("game_moon.png")),
|
||||||
|
|
||||||
|
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),
|
||||||
|
|
||||||
rect_(SDL_FRect{0, 0, static_cast<float>(gradients_texture_->getWidth() / 2), static_cast<float>(gradients_texture_->getHeight() / 2)}),
|
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}),
|
src_rect_({.x = 0, .y = 0, .w = 320, .h = 240}),
|
||||||
dst_rect_({0, 0, 320, 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)),
|
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),
|
alpha_color_texture_(param.background.attenuate_color.a),
|
||||||
@@ -58,17 +59,17 @@ void Background::initializePaths() {
|
|||||||
|
|
||||||
// Inicializa los rectángulos de gradientes y nubes
|
// Inicializa los rectángulos de gradientes y nubes
|
||||||
void Background::initializeRects() {
|
void Background::initializeRects() {
|
||||||
gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
|
gradient_rect_[0] = {.x = 0, .y = 0, .w = rect_.w, .h = rect_.h};
|
||||||
gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h};
|
gradient_rect_[1] = {.x = rect_.w, .y = 0, .w = rect_.w, .h = rect_.h};
|
||||||
gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h};
|
gradient_rect_[2] = {.x = 0, .y = rect_.h, .w = rect_.w, .h = rect_.h};
|
||||||
gradient_rect_[3] = {rect_.w, rect_.h, rect_.w, 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 TOP_CLOUDS_TEXTURE_HEIGHT = top_clouds_texture_->getHeight() / 4;
|
||||||
const float BOTTOM_CLOUDS_TEXTURE_HEIGHT = bottom_clouds_texture_->getHeight() / 4;
|
const float BOTTOM_CLOUDS_TEXTURE_HEIGHT = bottom_clouds_texture_->getHeight() / 4;
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
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};
|
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] = {0, i * BOTTOM_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(bottom_clouds_texture_->getWidth()), BOTTOM_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};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +172,7 @@ void Background::incrementProgress(float amount) {
|
|||||||
// Establece la progresión absoluta
|
// Establece la progresión absoluta
|
||||||
void Background::setProgress(float absolute_progress) {
|
void Background::setProgress(float absolute_progress) {
|
||||||
float old_progress = progress_;
|
float old_progress = progress_;
|
||||||
progress_ = std::clamp(absolute_progress, 0.0f, total_progress_to_complete_);
|
progress_ = std::clamp(absolute_progress, 0.0F, total_progress_to_complete_);
|
||||||
|
|
||||||
// Notifica el cambio si hay callback y el progreso cambió
|
// Notifica el cambio si hay callback y el progreso cambió
|
||||||
if (progress_callback_ && progress_ != old_progress) {
|
if (progress_callback_ && progress_ != old_progress) {
|
||||||
@@ -187,11 +188,11 @@ void Background::setState(State new_state) {
|
|||||||
// Reinicia la progresión
|
// Reinicia la progresión
|
||||||
void Background::reset() {
|
void Background::reset() {
|
||||||
float old_progress = progress_;
|
float old_progress = progress_;
|
||||||
progress_ = 0.0f;
|
progress_ = 0.0F;
|
||||||
state_ = State::NORMAL;
|
state_ = State::NORMAL;
|
||||||
manual_mode_ = false;
|
manual_mode_ = false;
|
||||||
gradient_number_ = 0;
|
gradient_number_ = 0;
|
||||||
transition_ = 0.0f;
|
transition_ = 0.0F;
|
||||||
sun_index_ = 0;
|
sun_index_ = 0;
|
||||||
moon_index_ = 0;
|
moon_index_ = 0;
|
||||||
|
|
||||||
@@ -208,7 +209,7 @@ void Background::setManualMode(bool manual) {
|
|||||||
|
|
||||||
// Establece callback para sincronización automática
|
// Establece callback para sincronización automática
|
||||||
void Background::setProgressCallback(ProgressCallback callback) {
|
void Background::setProgressCallback(ProgressCallback callback) {
|
||||||
progress_callback_ = callback;
|
progress_callback_ = std::move(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Elimina el callback
|
// Elimina el callback
|
||||||
@@ -224,8 +225,8 @@ void Background::setCloudsSpeed(float value) {
|
|||||||
// Las nubes inferiores van a la mitad de velocidad que las superiores
|
// Las nubes inferiores van a la mitad de velocidad que las superiores
|
||||||
top_clouds_sprite_a_->setVelX(value);
|
top_clouds_sprite_a_->setVelX(value);
|
||||||
top_clouds_sprite_b_->setVelX(value);
|
top_clouds_sprite_b_->setVelX(value);
|
||||||
bottom_clouds_sprite_a_->setVelX(value / 2.0f);
|
bottom_clouds_sprite_a_->setVelX(value / 2.0F);
|
||||||
bottom_clouds_sprite_b_->setVelX(value / 2.0f);
|
bottom_clouds_sprite_b_->setVelX(value / 2.0F);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el degradado de fondo
|
// Establece el degradado de fondo
|
||||||
@@ -262,19 +263,19 @@ void Background::updateProgression() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calcula la transición de los diferentes fondos
|
// Calcula la transición de los diferentes fondos
|
||||||
const float gradient_number_float = std::min(progress_ / progress_per_stage_, 3.0F);
|
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);
|
const float PERCENT = GRADIENT_NUMBER_FLOAT - static_cast<int>(GRADIENT_NUMBER_FLOAT);
|
||||||
|
|
||||||
gradient_number_ = static_cast<size_t>(gradient_number_float);
|
gradient_number_ = static_cast<size_t>(GRADIENT_NUMBER_FLOAT);
|
||||||
transition_ = percent;
|
transition_ = PERCENT;
|
||||||
|
|
||||||
// Calcula la posición del sol
|
// Calcula la posición del sol
|
||||||
const float sun_progression = std::min(progress_ / sun_completion_progress_, 1.0f);
|
const float SUN_PROGRESSION = std::min(progress_ / sun_completion_progress_, 1.0F);
|
||||||
sun_index_ = static_cast<size_t>(sun_progression * (sun_path_.size() - 1));
|
sun_index_ = static_cast<size_t>(SUN_PROGRESSION * (sun_path_.size() - 1));
|
||||||
|
|
||||||
// Calcula la posición de la luna
|
// Calcula la posición de la luna
|
||||||
const float moon_progression = std::min(progress_ / total_progress_to_complete_, 1.0f);
|
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));
|
moon_index_ = static_cast<size_t>(MOON_PROGRESSION * (moon_path_.size() - 1));
|
||||||
|
|
||||||
// Actualiza la velocidad de las nubes
|
// Actualiza la velocidad de las nubes
|
||||||
updateCloudsSpeed();
|
updateCloudsSpeed();
|
||||||
@@ -294,22 +295,22 @@ void Background::updateCloudsSpeed() {
|
|||||||
if (state_ == State::COMPLETED) {
|
if (state_ == State::COMPLETED) {
|
||||||
float completion_factor = (progress_ - MINIMUM_COMPLETED_PROGRESS) /
|
float completion_factor = (progress_ - MINIMUM_COMPLETED_PROGRESS) /
|
||||||
(total_progress_to_complete_ - MINIMUM_COMPLETED_PROGRESS);
|
(total_progress_to_complete_ - MINIMUM_COMPLETED_PROGRESS);
|
||||||
completion_factor = std::max(0.1f, completion_factor);
|
completion_factor = std::max(0.1F, completion_factor);
|
||||||
base_clouds_speed *= completion_factor;
|
base_clouds_speed *= completion_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aplicar velocidades diferentes para nubes superiores e inferiores
|
// Aplicar velocidades diferentes para nubes superiores e inferiores
|
||||||
const float top_clouds_speed = base_clouds_speed;
|
const float TOP_CLOUDS_SPEED = base_clouds_speed;
|
||||||
const float bottom_clouds_speed = base_clouds_speed / 2.0f;
|
const float BOTTOM_CLOUDS_SPEED = base_clouds_speed / 2.0F;
|
||||||
|
|
||||||
// Aplicar las velocidades a los sprites correspondientes
|
// Aplicar las velocidades a los sprites correspondientes
|
||||||
top_clouds_sprite_a_->setVelX(top_clouds_speed);
|
top_clouds_sprite_a_->setVelX(TOP_CLOUDS_SPEED);
|
||||||
top_clouds_sprite_b_->setVelX(top_clouds_speed);
|
top_clouds_sprite_b_->setVelX(TOP_CLOUDS_SPEED);
|
||||||
bottom_clouds_sprite_a_->setVelX(bottom_clouds_speed);
|
bottom_clouds_sprite_a_->setVelX(BOTTOM_CLOUDS_SPEED);
|
||||||
bottom_clouds_sprite_b_->setVelX(bottom_clouds_speed);
|
bottom_clouds_sprite_b_->setVelX(BOTTOM_CLOUDS_SPEED);
|
||||||
|
|
||||||
// Guardar la velocidad principal
|
// Guardar la velocidad principal
|
||||||
clouds_speed_ = top_clouds_speed;
|
clouds_speed_ = TOP_CLOUDS_SPEED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las nubes
|
// Actualiza las nubes
|
||||||
@@ -478,7 +479,7 @@ void Background::createSunPath() {
|
|||||||
const int NUM_STEPS = static_cast<int>((M_PI - M_PI / 2) / STEP) + 1;
|
const int NUM_STEPS = static_cast<int>((M_PI - M_PI / 2) / STEP) + 1;
|
||||||
|
|
||||||
for (int i = 0; i < NUM_STEPS; ++i) {
|
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 x = CENTER_X + (RADIUS * cos(theta));
|
||||||
float y = CENTER_Y - (RADIUS * sin(theta));
|
float y = CENTER_Y - (RADIUS * sin(theta));
|
||||||
sun_path_.push_back({x, y});
|
sun_path_.push_back({x, y});
|
||||||
@@ -501,9 +502,9 @@ void Background::createMoonPath() {
|
|||||||
constexpr double STEP = 0.01;
|
constexpr double STEP = 0.01;
|
||||||
const int NUM_STEPS = static_cast<int>((M_PI / 2) / 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
|
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));
|
const int FREEZE_START_INDEX = static_cast<int>(NUM_STEPS * (1.0F - FREEZE_PERCENTAGE));
|
||||||
|
|
||||||
for (int i = 0; i < NUM_STEPS; ++i) {
|
for (int i = 0; i < NUM_STEPS; ++i) {
|
||||||
double theta = i * STEP;
|
double theta = i * STEP;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <array> // Para array
|
#include <array> // Para array
|
||||||
#include <cstddef> // Para size_t
|
#include <cstddef> // Para size_t
|
||||||
#include <functional> // Para std::function
|
#include <functional> // Para function
|
||||||
#include <memory> // Para unique_ptr, shared_ptr
|
#include <memory> // Para unique_ptr, shared_ptr
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
@@ -14,140 +14,109 @@ class MovingSprite;
|
|||||||
class Sprite;
|
class Sprite;
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
/*
|
// --- Clase Background: gestiona el fondo de la sección jugable ---
|
||||||
Esta clase gestiona el fondo que aparece en la sección jugable.
|
|
||||||
|
|
||||||
Maneja internamente su progresión a través de diferentes estados del día/noche,
|
|
||||||
controlando las transiciones entre gradientes, posiciones del sol/luna y velocidad de nubes.
|
|
||||||
|
|
||||||
Estados:
|
|
||||||
- NORMAL: Progresión normal del día
|
|
||||||
- COMPLETED: Reducción gradual de la actividad (nubes más lentas)
|
|
||||||
|
|
||||||
Métodos clave:
|
|
||||||
- incrementProgress() -> Avanza la progresión del fondo
|
|
||||||
- setState() -> Cambia el estado del fondo
|
|
||||||
- setColor/setAlpha -> Efectos de atenuación
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Background {
|
class Background {
|
||||||
public:
|
public:
|
||||||
// Enumeración de estados
|
// --- Enums ---
|
||||||
enum class State {
|
enum class State {
|
||||||
NORMAL,
|
NORMAL, // Progresión normal del día
|
||||||
COMPLETED
|
COMPLETED // Reducción gradual de la actividad
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructor y Destructor
|
// --- Tipos ---
|
||||||
Background(float total_progress_to_complete = 6100.0f);
|
using ProgressCallback = std::function<void(float)>; // Callback para sincronización
|
||||||
~Background();
|
|
||||||
|
|
||||||
// Actualización y renderizado
|
// --- Constructor y destructor ---
|
||||||
|
Background(float total_progress_to_complete = 6100.0F); // Constructor principal
|
||||||
|
~Background(); // Destructor
|
||||||
|
|
||||||
|
// --- Métodos principales ---
|
||||||
void update(); // Actualiza la lógica del objeto
|
void update(); // Actualiza la lógica del objeto
|
||||||
void render(); // Dibuja el 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
|
void setPos(SDL_FRect pos); // Establece la posición del objeto
|
||||||
|
void setState(State new_state); // Cambia el estado del fondo
|
||||||
// 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
|
|
||||||
void setState(State new_state); // Cambia el estado del fondo
|
|
||||||
void reset(); // Reinicia la progresión
|
|
||||||
|
|
||||||
// Sistema de callback para sincronización automática
|
|
||||||
using ProgressCallback = std::function<void(float)>;
|
|
||||||
void setProgressCallback(ProgressCallback callback); // Establece callback para sincronización
|
void setProgressCallback(ProgressCallback callback); // Establece callback para sincronización
|
||||||
void removeProgressCallback(); // Elimina el callback
|
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 manual (para uso fuera del juego principal)
|
// --- Control de progresión ---
|
||||||
void setManualMode(bool manual); // Activa/desactiva el modo manual
|
void incrementProgress(float amount = 1.0F); // Incrementa la progresión interna
|
||||||
void setCloudsSpeed(float value); // Ajusta la velocidad de las nubes
|
void setProgress(float absolute_progress); // Establece la progresión absoluta
|
||||||
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
|
|
||||||
|
|
||||||
// Configuración de efectos visuales
|
// --- Getters ---
|
||||||
void setColor(Color color); // Establece el color de atenuación
|
[[nodiscard]] auto getProgress() const -> float { return progress_; } // Obtiene el progreso actual
|
||||||
void setAlpha(int alpha); // Ajusta la transparencia del fondo
|
[[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
|
||||||
// Getters para información del estado
|
|
||||||
float getProgress() const { return progress_; }
|
|
||||||
State getState() const { return state_; }
|
|
||||||
int getCurrentGradient() const { return static_cast<int>(gradient_number_); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Constantes de configuración
|
// --- Constantes ---
|
||||||
static constexpr size_t STAGES = 4;
|
static constexpr size_t STAGES = 4; // Número de etapas
|
||||||
static constexpr float COMPLETED_REDUCTION_RATE = 25.0f;
|
static constexpr float COMPLETED_REDUCTION_RATE = 25.0F; // Tasa de reducción completada
|
||||||
static constexpr float MINIMUM_COMPLETED_PROGRESS = 200.0f;
|
static constexpr float MINIMUM_COMPLETED_PROGRESS = 200.0F; // Progreso mínimo completado
|
||||||
static constexpr float SUN_COMPLETION_FACTOR = 0.5f; // El sol completa su recorrido a la mitad del progreso total
|
static constexpr float SUN_COMPLETION_FACTOR = 0.5F; // Factor de completado del sol
|
||||||
|
|
||||||
// Configuración paramétrica
|
// --- Objetos y punteros ---
|
||||||
const float total_progress_to_complete_;
|
SDL_Renderer *renderer_; // Renderizador de la ventana
|
||||||
const float progress_per_stage_;
|
SDL_Texture *canvas_; // Textura para componer el fondo
|
||||||
const float sun_completion_progress_;
|
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
|
||||||
|
|
||||||
// Objetos y punteros
|
// --- Variables de configuración ---
|
||||||
SDL_Renderer *renderer_; // Renderizador de la ventana
|
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
|
||||||
|
ProgressCallback progress_callback_; // Callback para notificar cambios de progreso
|
||||||
|
|
||||||
// Texturas
|
// --- Variables de estado ---
|
||||||
std::shared_ptr<Texture> buildings_texture_;
|
std::vector<SDL_FPoint> sun_path_; // Recorrido del sol
|
||||||
std::shared_ptr<Texture> top_clouds_texture_;
|
std::vector<SDL_FPoint> moon_path_; // Recorrido de la luna
|
||||||
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
|
|
||||||
|
|
||||||
// Variables de estado y progresión
|
|
||||||
State state_ = State::NORMAL;
|
|
||||||
float progress_ = 0.0f; // Progresión interna (0 a total_progress_to_complete_)
|
|
||||||
bool manual_mode_ = false; // Si está en modo manual, no actualiza automáticamente
|
|
||||||
ProgressCallback progress_callback_; // Callback para notificar cambios de progreso
|
|
||||||
|
|
||||||
// Variables de renderizado
|
|
||||||
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
|
|
||||||
std::array<SDL_FRect, STAGES> gradient_rect_; // Fondos degradados
|
std::array<SDL_FRect, STAGES> gradient_rect_; // Fondos degradados
|
||||||
std::array<SDL_FRect, 4> top_clouds_rect_; // Nubes superiores
|
std::array<SDL_FRect, 4> top_clouds_rect_; // Nubes superiores
|
||||||
std::array<SDL_FRect, 4> bottom_clouds_rect_; // Nubes inferiores
|
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
|
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
|
||||||
|
size_t counter_ = 0; // Contador interno
|
||||||
|
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
|
||||||
|
|
||||||
std::vector<SDL_FPoint> sun_path_; // Recorrido del sol
|
// --- Métodos internos ---
|
||||||
std::vector<SDL_FPoint> moon_path_; // Recorrido de la luna
|
|
||||||
|
|
||||||
float clouds_speed_ = 0; // Velocidad de las nubes
|
|
||||||
float transition_ = 0; // Porcentaje de transición
|
|
||||||
|
|
||||||
size_t gradient_number_ = 0; // Índice de fondo degradado
|
|
||||||
size_t counter_ = 0; // Contador interno
|
|
||||||
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
|
|
||||||
|
|
||||||
// Métodos internos
|
|
||||||
void initializePaths(); // Inicializa las rutas del sol y la luna
|
void initializePaths(); // Inicializa las rutas del sol y la luna
|
||||||
void initializeRects(); // Inicializa los rectángulos de gradientes y nubes
|
void initializeRects(); // Inicializa los rectángulos de gradientes y nubes
|
||||||
void initializeSprites(); // Crea los sprites
|
void initializeSprites(); // Crea los sprites
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
|
|
||||||
// Constructor
|
// 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)
|
Balloon::Balloon(float x, float y, Type type, Size size, float vel_x, float speed, Uint16 creation_timer, SDL_FRect play_area, const std::shared_ptr<Texture> &texture, const std::vector<std::string> &animation)
|
||||||
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
|
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
|
||||||
x_(x),
|
x_(x),
|
||||||
y_(y),
|
y_(y),
|
||||||
@@ -44,7 +44,7 @@ Balloon::Balloon(float x, float y, Type type, Size size, float vel_x, float spee
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Type::FLOATER: {
|
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;
|
gravity_ = 0.00F;
|
||||||
|
|
||||||
const int INDEX = static_cast<int>(size_);
|
const int INDEX = static_cast<int>(size_);
|
||||||
|
|||||||
@@ -38,17 +38,18 @@ class Balloon {
|
|||||||
static constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10;
|
static constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10;
|
||||||
static constexpr int POWERBALL_COUNTER = 8;
|
static constexpr int POWERBALL_COUNTER = 8;
|
||||||
|
|
||||||
|
// --- Enums ---
|
||||||
enum class Size : Uint8 {
|
enum class Size : Uint8 {
|
||||||
SMALL = 0,
|
SMALL = 0, // Tamaño pequeño
|
||||||
MEDIUM = 1,
|
MEDIUM = 1, // Tamaño mediano
|
||||||
LARGE = 2,
|
LARGE = 2, // Tamaño grande
|
||||||
EXTRALARGE = 3,
|
EXTRALARGE = 3, // Tamaño extra grande
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Type : Uint8 {
|
enum class Type : Uint8 {
|
||||||
BALLOON = 0,
|
BALLOON = 0, // Globo normal
|
||||||
FLOATER = 1,
|
FLOATER = 1, // Globo flotante
|
||||||
POWERBALL = 2,
|
POWERBALL = 2, // Globo de poder
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
@@ -61,7 +62,7 @@ class Balloon {
|
|||||||
float speed,
|
float speed,
|
||||||
Uint16 creation_timer,
|
Uint16 creation_timer,
|
||||||
SDL_FRect play_area,
|
SDL_FRect play_area,
|
||||||
std::shared_ptr<Texture> texture,
|
const std::shared_ptr<Texture>& texture,
|
||||||
const std::vector<std::string>& animation);
|
const std::vector<std::string>& animation);
|
||||||
~Balloon() = default;
|
~Balloon() = default;
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
// --- Clase BalloonFormations ---
|
// --- Clase BalloonFormations ---
|
||||||
class BalloonFormations {
|
class BalloonFormations {
|
||||||
public:
|
public:
|
||||||
// --- Estructuras de datos ---
|
// --- Estructuras ---
|
||||||
struct SpawnParams {
|
struct SpawnParams {
|
||||||
int x = 0; // Posición en el eje X donde crear el globo
|
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
|
int y = 0; // Posición en el eje Y donde crear el globo
|
||||||
@@ -41,8 +41,8 @@ class BalloonFormations {
|
|||||||
Formation() = default;
|
Formation() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Vector de índices a formaciones
|
// --- Types ---
|
||||||
using Pool = std::vector<int>;
|
using Pool = std::vector<int>; // Vector de índices a formaciones
|
||||||
|
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
BalloonFormations() {
|
BalloonFormations() {
|
||||||
@@ -79,28 +79,20 @@ class BalloonFormations {
|
|||||||
static constexpr int BALLOON_SPAWN_HEIGHT = 208; // Altura desde el suelo en la que aparecen los globos
|
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 int DEFAULT_CREATION_TIME = 200; // Tiempo base de creación de los globos para las formaciones
|
||||||
|
|
||||||
// --- Datos ---
|
// --- Variables ---
|
||||||
std::vector<Formation> formations_; // Vector con todas las formaciones disponibles
|
std::vector<Formation> formations_; // Vector con todas las formaciones disponibles
|
||||||
std::vector<Pool> pools_; // Vector de pools, cada pool contiene índices a formaciones
|
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 initFormations(); // Inicializa la lista principal de formaciones de globos disponibles
|
||||||
void initFormationPools(); // Carga los pools desde archivo de configuración
|
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 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 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 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
|
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 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;
|
auto evaluateSimpleExpression(const std::string& expr, const std::map<std::string, float>& variables) -> float;
|
||||||
|
|
||||||
// --- Utilidades ---
|
|
||||||
static auto trim(const std::string& str) -> std::string;
|
static auto trim(const std::string& str) -> std::string;
|
||||||
|
|
||||||
// --- Generación de variantes ---
|
|
||||||
void createFloaterVariants();
|
void createFloaterVariants();
|
||||||
void loadDefaultFormations();
|
void loadDefaultFormations();
|
||||||
void loadDefaultPools(); // Nueva función para pools por defecto
|
void loadDefaultPools(); // Nueva función para pools por defecto
|
||||||
|
|||||||
@@ -17,9 +17,7 @@
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
BalloonManager::BalloonManager(IStageInfo *stage_info)
|
BalloonManager::BalloonManager(IStageInfo *stage_info)
|
||||||
: explosions_(std::make_unique<Explosions>()),
|
: explosions_(std::make_unique<Explosions>()), balloon_formations_(std::make_unique<BalloonFormations>()), stage_info_(stage_info) { init(); }
|
||||||
balloon_formations_(std::make_unique<BalloonFormations>()),
|
|
||||||
stage_info_(stage_info) { init(); }
|
|
||||||
|
|
||||||
// Inicializa
|
// Inicializa
|
||||||
void BalloonManager::init() {
|
void BalloonManager::init() {
|
||||||
@@ -64,7 +62,7 @@ void BalloonManager::init() {
|
|||||||
|
|
||||||
// Actualiza
|
// Actualiza
|
||||||
void BalloonManager::update() {
|
void BalloonManager::update() {
|
||||||
for (auto balloon : balloons_) {
|
for (const auto &balloon : balloons_) {
|
||||||
balloon->update();
|
balloon->update();
|
||||||
}
|
}
|
||||||
updateBalloonDeployCounter();
|
updateBalloonDeployCounter();
|
||||||
@@ -134,8 +132,8 @@ void BalloonManager::deployFormation(int formation_id, int y) {
|
|||||||
|
|
||||||
// Vacia del vector de globos los globos que ya no sirven
|
// Vacia del vector de globos los globos que ya no sirven
|
||||||
void BalloonManager::freeBalloons() {
|
void BalloonManager::freeBalloons() {
|
||||||
auto it = std::remove_if(balloons_.begin(), balloons_.end(), [](const auto &balloon) { return !balloon->isEnabled(); });
|
auto result = std::ranges::remove_if(balloons_, [](const auto &balloon) { return !balloon->isEnabled(); });
|
||||||
balloons_.erase(it, balloons_.end());
|
balloons_.erase(result.begin(), balloons_.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza la variable enemyDeployCounter
|
// Actualiza la variable enemyDeployCounter
|
||||||
@@ -226,7 +224,7 @@ void BalloonManager::setBalloonSpeed(float speed) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
|
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
|
||||||
auto BalloonManager::popBalloon(std::shared_ptr<Balloon> balloon) -> int {
|
auto BalloonManager::popBalloon(const std::shared_ptr<Balloon> &balloon) -> int {
|
||||||
stage_info_->addPower(1);
|
stage_info_->addPower(1);
|
||||||
int score = 0;
|
int score = 0;
|
||||||
|
|
||||||
@@ -291,7 +289,7 @@ auto BalloonManager::destroyAllBalloons() -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
balloon_deploy_counter_ = 300;
|
balloon_deploy_counter_ = 300;
|
||||||
Screen::get()->flash(FLASH_COLOR, 3);
|
Screen::get()->flash(Colors::FLASH, 3);
|
||||||
Screen::get()->shake();
|
Screen::get()->shake();
|
||||||
|
|
||||||
return score;
|
return score;
|
||||||
@@ -336,7 +334,7 @@ void BalloonManager::createTwoBigBalloons() {
|
|||||||
|
|
||||||
// Crea una disposición de globos aleatoria
|
// Crea una disposición de globos aleatoria
|
||||||
void BalloonManager::createRandomBalloons() {
|
void BalloonManager::createRandomBalloons() {
|
||||||
const int NUM_BALLOONS = 2 + rand() % 4;
|
const int NUM_BALLOONS = 2 + (rand() % 4);
|
||||||
for (int i = 0; i < NUM_BALLOONS; ++i) {
|
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 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 int Y = param.game.game_area.rect.y + (rand() % 50);
|
||||||
|
|||||||
@@ -17,35 +17,36 @@
|
|||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
|
// --- Types ---
|
||||||
using Balloons = std::vector<std::shared_ptr<Balloon>>;
|
using Balloons = std::vector<std::shared_ptr<Balloon>>;
|
||||||
|
|
||||||
// Clase BalloonManager
|
// --- Clase BalloonManager: gestiona todos los globos del juego ---
|
||||||
class BalloonManager {
|
class BalloonManager {
|
||||||
public:
|
public:
|
||||||
// Constructor y Destructor
|
// --- Constructor y destructor ---
|
||||||
BalloonManager(IStageInfo *stage_info);
|
BalloonManager(IStageInfo *stage_info);
|
||||||
~BalloonManager() = default;
|
~BalloonManager() = default;
|
||||||
|
|
||||||
// Actualización y Renderizado
|
// --- Métodos principales ---
|
||||||
void update(); // Actualiza el estado de los globos
|
void update(); // Actualiza el estado de los globos
|
||||||
void render(); // Renderiza los globos en pantalla
|
void render(); // Renderiza los globos en pantalla
|
||||||
|
|
||||||
// Gestión de globos
|
// --- Gestión de globos ---
|
||||||
void freeBalloons(); // Libera globos que ya no sirven
|
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 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); // 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, int y); // Crea una formación específica con coordenadas
|
||||||
|
|
||||||
// Creación de globos
|
// --- 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
|
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
|
||||||
void createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction); // Crea un globo a partir de otro
|
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 createPowerBall(); // Crea una PowerBall
|
||||||
void createTwoBigBalloons(); // Crea dos globos grandes
|
void createTwoBigBalloons(); // Crea dos globos grandes
|
||||||
void createRandomBalloons(); // Crea una disposición aleatoria de globos
|
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 setBalloonSpeed(float speed); // Ajusta la velocidad de los globos
|
||||||
void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; }; // Establece la velocidad base
|
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 resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); }; // Restablece la velocidad de los globos
|
||||||
@@ -53,61 +54,61 @@ class BalloonManager {
|
|||||||
auto canPowerBallBeCreated() -> bool; // Indica si se puede crear una PowerBall
|
auto canPowerBallBeCreated() -> bool; // Indica si se puede crear una PowerBall
|
||||||
auto calculateScreenPower() -> int; // Calcula el poder de los globos en pantalla
|
auto calculateScreenPower() -> int; // Calcula el poder de los globos en pantalla
|
||||||
|
|
||||||
// Manipulación de globos existentes
|
// --- Manipulación de globos existentes ---
|
||||||
auto popBalloon(std::shared_ptr<Balloon> balloon) -> int; // Explosiona un globo, creando otros si aplica
|
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 destroyBalloon(std::shared_ptr<Balloon> &balloon) -> int; // Explosiona un globo sin crear otros
|
||||||
auto destroyAllBalloons() -> int; // Destruye todos los globos
|
auto destroyAllBalloons() -> int; // Destruye todos los globos
|
||||||
void stopAllBalloons(); // Detiene el movimiento de los globos
|
void stopAllBalloons(); // Detiene el movimiento de los globos
|
||||||
void startAllBalloons(); // Reactiva 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 reverseColorsToAllBalloons(); // Invierte los colores de los globos
|
||||||
void normalColorsToAllBalloons(); // Restaura los colores originales
|
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 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 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
|
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 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 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
|
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
|
auto getMenace() -> int; // Obtiene el nivel de amenaza generado por los globos
|
||||||
[[nodiscard]] auto getBalloonSpeed() const -> float { return balloon_speed_; }
|
[[nodiscard]] auto getBalloonSpeed() const -> float { return balloon_speed_; }
|
||||||
auto getBalloons() -> Balloons & { return balloons_; }
|
auto getBalloons() -> Balloons & { return balloons_; }
|
||||||
[[nodiscard]] auto getNumBalloons() const -> int { return balloons_.size(); }
|
[[nodiscard]] auto getNumBalloons() const -> int { return balloons_.size(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// --- Constantes ---
|
||||||
static const int DEFAULT_BALLOON_DEPLOY_COUNTER = 300;
|
static const int DEFAULT_BALLOON_DEPLOY_COUNTER = 300;
|
||||||
|
|
||||||
Balloons balloons_; // Vector con los globos activos
|
// --- Objetos y punteros ---
|
||||||
std::unique_ptr<Explosions> explosions_; // Objeto para gestionar explosiones
|
Balloons balloons_; // Vector con los globos activos
|
||||||
std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para manejar formaciones enemigas
|
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>> balloon_textures_; // Texturas de los globos
|
||||||
std::vector<std::shared_ptr<Texture>> explosions_textures_; // Texturas de explosiones
|
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>> balloon_animations_; // Animaciones de los globos
|
||||||
std::vector<std::vector<std::string>> explosions_animations_; // Animaciones de las explosiones
|
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
|
// --- Variables de estado ---
|
||||||
|
SDL_FRect play_area_ = param.game.play_area.rect;
|
||||||
float balloon_speed_ = Balloon::SPEED.at(0);
|
float balloon_speed_ = Balloon::SPEED.at(0);
|
||||||
float default_balloon_speed_ = Balloon::SPEED.at(0);
|
float default_balloon_speed_ = Balloon::SPEED.at(0);
|
||||||
int balloon_deploy_counter_ = 0;
|
int balloon_deploy_counter_ = 0;
|
||||||
bool power_ball_enabled_ = false;
|
|
||||||
int power_ball_counter_ = 0;
|
int power_ball_counter_ = 0;
|
||||||
int last_balloon_deploy_ = 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 creation_time_enabled_ = true;
|
||||||
bool can_deploy_balloons_ = true;
|
bool can_deploy_balloons_ = true;
|
||||||
bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar
|
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 poping_sound_enabled_ = true; // Si debe sonar el globo al explotar
|
||||||
bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido
|
bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido
|
||||||
IStageInfo *stage_info_; // Informacion de la pantalla actual
|
|
||||||
|
|
||||||
// Metodos privados
|
// --- Métodos internos ---
|
||||||
void init();
|
void init();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
// Constructor
|
// Constructor
|
||||||
Bullet::Bullet(float x, float y, BulletType bullet_type, bool powered, Player::Id owner)
|
Bullet::Bullet(float x, float y, BulletType bullet_type, bool powered, Player::Id owner)
|
||||||
: sprite_(std::make_unique<AnimatedSprite>(Resource::get()->getTexture("bullet.png"), Resource::get()->getAnimation("bullet.ani"))),
|
: sprite_(std::make_unique<AnimatedSprite>(Resource::get()->getTexture("bullet.png"), Resource::get()->getAnimation("bullet.ani"))),
|
||||||
pos_x_(x),
|
|
||||||
pos_y_(y),
|
|
||||||
bullet_type_(bullet_type),
|
bullet_type_(bullet_type),
|
||||||
owner_(owner) {
|
owner_(owner),
|
||||||
|
pos_x_(x),
|
||||||
|
pos_y_(y) {
|
||||||
vel_x_ = calculateVelocity(bullet_type_);
|
vel_x_ = calculateVelocity(bullet_type_);
|
||||||
sprite_->setCurrentAnimation(buildAnimationString(bullet_type_, powered));
|
sprite_->setCurrentAnimation(buildAnimationString(bullet_type_, powered));
|
||||||
|
|
||||||
|
|||||||
@@ -9,65 +9,62 @@
|
|||||||
#include "player.h" // Para Player
|
#include "player.h" // Para Player
|
||||||
#include "utils.h" // Para Circle
|
#include "utils.h" // Para Circle
|
||||||
|
|
||||||
// Tipos de balas
|
// --- Enums ---
|
||||||
enum class BulletType : Uint8 {
|
enum class BulletType : Uint8 {
|
||||||
UP,
|
UP, // Bala hacia arriba
|
||||||
LEFT,
|
LEFT, // Bala hacia la izquierda
|
||||||
RIGHT,
|
RIGHT, // Bala hacia la derecha
|
||||||
NONE
|
NONE // Sin bala
|
||||||
};
|
};
|
||||||
|
|
||||||
// Resultado del movimiento de la bala
|
|
||||||
enum class BulletMoveStatus : Uint8 {
|
enum class BulletMoveStatus : Uint8 {
|
||||||
OK = 0,
|
OK = 0, // Movimiento normal
|
||||||
OUT = 1
|
OUT = 1 // Fuera de los límites
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clase Bullet
|
// --- Clase Bullet: representa una bala del jugador ---
|
||||||
class Bullet {
|
class Bullet {
|
||||||
public:
|
public:
|
||||||
// Constantes
|
// --- Constantes ---
|
||||||
static constexpr float WIDTH = 12.0F;
|
static constexpr float WIDTH = 12.0F; // Anchura de la bala
|
||||||
static constexpr float HEIGHT = 12.0F;
|
static constexpr float HEIGHT = 12.0F; // Altura de la bala
|
||||||
|
|
||||||
// Constructor y Destructor
|
// --- Constructor y destructor ---
|
||||||
Bullet(float x, float y, BulletType bullet_type, bool powered, Player::Id owner);
|
Bullet(float x, float y, BulletType bullet_type, bool powered, Player::Id owner); // Constructor principal
|
||||||
~Bullet() = default;
|
~Bullet() = default; // Destructor
|
||||||
|
|
||||||
// Métodos principales
|
// --- Métodos principales ---
|
||||||
void render(); // Dibuja la bala en pantalla
|
void render(); // Dibuja la bala en pantalla
|
||||||
auto update() -> BulletMoveStatus; // Actualiza el estado del objeto
|
auto update() -> BulletMoveStatus; // Actualiza el estado del objeto
|
||||||
|
void disable(); // Desactiva la bala
|
||||||
|
|
||||||
// Estado de la bala
|
// --- Getters ---
|
||||||
[[nodiscard]] auto isEnabled() const -> bool; // Comprueba si está activa
|
[[nodiscard]] auto isEnabled() const -> bool; // Comprueba si está activa
|
||||||
void disable(); // Desactiva la bala
|
|
||||||
|
|
||||||
// Getters
|
|
||||||
[[nodiscard]] auto getOwner() const -> Player::Id; // Devuelve el identificador del dueño
|
[[nodiscard]] auto getOwner() const -> Player::Id; // Devuelve el identificador del dueño
|
||||||
auto getCollider() -> Circle &; // Devuelve el círculo de colisión
|
auto getCollider() -> Circle &; // Devuelve el círculo de colisión
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Constantes
|
// --- Constantes ---
|
||||||
static constexpr float VEL_Y = -3.0F;
|
static constexpr float VEL_Y = -3.0F; // Velocidad vertical
|
||||||
static constexpr float VEL_X_LEFT = -2.0F;
|
static constexpr float VEL_X_LEFT = -2.0F; // Velocidad izquierda
|
||||||
static constexpr float VEL_X_RIGHT = 2.0F;
|
static constexpr float VEL_X_RIGHT = 2.0F; // Velocidad derecha
|
||||||
static constexpr float VEL_X_CENTER = 0.0F;
|
static constexpr float VEL_X_CENTER = 0.0F; // Velocidad central
|
||||||
|
|
||||||
// Propiedades
|
// --- Objetos y punteros ---
|
||||||
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos
|
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos
|
||||||
|
|
||||||
float pos_x_; // Posición en el eje X
|
// --- Variables de estado ---
|
||||||
float pos_y_; // Posición en el eje Y
|
Circle collider_; // Círculo de colisión
|
||||||
float vel_x_; // Velocidad en el eje X
|
|
||||||
|
|
||||||
BulletType bullet_type_; // Tipo de bala
|
BulletType bullet_type_; // Tipo de bala
|
||||||
Player::Id owner_; // Identificador del dueño
|
Player::Id owner_; // Identificador del dueño
|
||||||
Circle collider_; // Círculo de colisión
|
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
|
||||||
|
|
||||||
// Métodos internos
|
// --- Métodos internos ---
|
||||||
void shiftColliders(); // Ajusta el círculo de colisión
|
void shiftColliders(); // Ajusta el círculo de colisión
|
||||||
void shiftSprite(); // Ajusta el sprite
|
void shiftSprite(); // Ajusta el sprite
|
||||||
auto move() -> BulletMoveStatus; // Mueve la bala y devuelve su estado
|
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 calculateVelocity(BulletType bullet_type) -> float; // Calcula la velocidad horizontal de la bala
|
||||||
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
|
static auto buildAnimationString(BulletType bullet_type, bool powered) -> std::string; // Construye el string de animación
|
||||||
};
|
};
|
||||||
|
|||||||
132
source/color.cpp
132
source/color.cpp
@@ -42,22 +42,8 @@ auto Color::fromHex(const std::string &hex_str) -> Color {
|
|||||||
return Color(r, g, b, a);
|
return Color(r, g, b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene un color del vector de colores imitando al Coche Fantástico
|
// Implementaciones de métodos estáticos de Color
|
||||||
auto getColorLikeKnightRider(const std::vector<Color> &colors, int counter) -> Color {
|
constexpr auto Color::rgbToHsv(Color color) -> HSV {
|
||||||
int cycle_length = colors.size() * 2 - 2;
|
|
||||||
size_t n = counter % cycle_length;
|
|
||||||
|
|
||||||
size_t index;
|
|
||||||
if (n < colors.size()) {
|
|
||||||
index = n; // Avanza: 0,1,2,3
|
|
||||||
} else {
|
|
||||||
index = 2 * (colors.size() - 1) - n; // Retrocede: 2,1
|
|
||||||
}
|
|
||||||
|
|
||||||
return colors[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr auto rgbToHsv(Color color) -> HSV {
|
|
||||||
float r = color.r / 255.0F;
|
float r = color.r / 255.0F;
|
||||||
float g = color.g / 255.0F;
|
float g = color.g / 255.0F;
|
||||||
float b = color.b / 255.0F;
|
float b = color.b / 255.0F;
|
||||||
@@ -84,10 +70,10 @@ constexpr auto rgbToHsv(Color color) -> HSV {
|
|||||||
float s = (max <= 0.0F) ? 0.0F : delta / max;
|
float s = (max <= 0.0F) ? 0.0F : delta / max;
|
||||||
float v = max;
|
float v = max;
|
||||||
|
|
||||||
return {h, s, v};
|
return {.h = h, .s = s, .v = v};
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto hsvToRgb(HSV hsv) -> Color {
|
constexpr auto Color::hsvToRgb(HSV hsv) -> Color {
|
||||||
float c = hsv.v * hsv.s;
|
float c = hsv.v * hsv.s;
|
||||||
float x = c * (1 - std::abs(std::fmod(hsv.h / 60.0F, 2) - 1));
|
float x = c * (1 - std::abs(std::fmod(hsv.h / 60.0F, 2) - 1));
|
||||||
float m = hsv.v - c;
|
float m = hsv.v - c;
|
||||||
@@ -128,55 +114,73 @@ constexpr auto hsvToRgb(HSV hsv) -> Color {
|
|||||||
static_cast<uint8_t>(roundf((b + m) * 255)));
|
static_cast<uint8_t>(roundf((b + m) * 255)));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto generateMirroredCycle(Color base, ColorCycleStyle style) -> ColorCycle {
|
// Implementaciones del namespace Colors
|
||||||
ColorCycle result{};
|
namespace Colors {
|
||||||
HSV base_hsv = rgbToHsv(base);
|
// Obtiene un color del vector de colores imitando al Coche Fantástico
|
||||||
|
auto getColorLikeKnightRider(const std::vector<Color> &colors, int counter) -> Color {
|
||||||
|
int cycle_length = (colors.size() * 2) - 2;
|
||||||
|
size_t n = counter % cycle_length;
|
||||||
|
|
||||||
for (size_t i = 0; i < COLOR_CYCLE_SIZE; ++i) {
|
size_t index;
|
||||||
float t = static_cast<float>(i) / (COLOR_CYCLE_SIZE - 1); // 0 → 1
|
if (n < colors.size()) {
|
||||||
float hue_shift = 0.0F;
|
index = n; // Avanza: 0,1,2,3
|
||||||
float sat_shift = 0.0F;
|
} else {
|
||||||
float val_shift = 0.0F;
|
index = 2 * (colors.size() - 1) - n; // Retrocede: 2,1
|
||||||
|
|
||||||
switch (style) {
|
|
||||||
case ColorCycleStyle::SUBTLE_PULSE:
|
|
||||||
// Solo brillo suave
|
|
||||||
val_shift = 0.07F * sinf(t * M_PI);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ColorCycleStyle::HUE_WAVE:
|
|
||||||
// Oscilación leve de tono
|
|
||||||
hue_shift = 15.0F * (t - 0.5F) * 2.0F;
|
|
||||||
val_shift = 0.05F * sinf(t * M_PI);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ColorCycleStyle::VIBRANT:
|
|
||||||
// Cambios fuertes en tono y brillo
|
|
||||||
hue_shift = 35.0F * sinf(t * M_PI);
|
|
||||||
val_shift = 0.2F * sinf(t * M_PI);
|
|
||||||
sat_shift = -0.2F * sinf(t * M_PI);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ColorCycleStyle::DARKEN_GLOW:
|
|
||||||
// Se oscurece al centro
|
|
||||||
val_shift = -0.15F * sinf(t * M_PI);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ColorCycleStyle::LIGHT_FLASH:
|
|
||||||
// Se ilumina al centro
|
|
||||||
val_shift = 0.25F * sinf(t * M_PI);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HSV adjusted = {
|
return colors[index];
|
||||||
fmodf(base_hsv.h + hue_shift + 360.0F, 360.0F),
|
|
||||||
fminf(1.0F, fmaxf(0.0F, base_hsv.s + sat_shift)),
|
|
||||||
fminf(1.0F, fmaxf(0.0F, base_hsv.v + val_shift))};
|
|
||||||
|
|
||||||
Color c = hsvToRgb(adjusted);
|
|
||||||
result[i] = c;
|
|
||||||
result[2 * COLOR_CYCLE_SIZE - 1 - i] = c; // espejo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
auto generateMirroredCycle(Color base, ColorCycleStyle style) -> Cycle {
|
||||||
|
Cycle result{};
|
||||||
|
HSV base_hsv = Color::rgbToHsv(base);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < CYCLE_SIZE; ++i) {
|
||||||
|
float t = static_cast<float>(i) / (CYCLE_SIZE - 1); // 0 → 1
|
||||||
|
float hue_shift = 0.0F;
|
||||||
|
float sat_shift = 0.0F;
|
||||||
|
float val_shift = 0.0F;
|
||||||
|
|
||||||
|
switch (style) {
|
||||||
|
case ColorCycleStyle::SUBTLE_PULSE:
|
||||||
|
// Solo brillo suave
|
||||||
|
val_shift = 0.07F * sinf(t * M_PI);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ColorCycleStyle::HUE_WAVE:
|
||||||
|
// Oscilación leve de tono
|
||||||
|
hue_shift = 15.0F * (t - 0.5F) * 2.0F;
|
||||||
|
val_shift = 0.05F * sinf(t * M_PI);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ColorCycleStyle::VIBRANT:
|
||||||
|
// Cambios fuertes en tono y brillo
|
||||||
|
hue_shift = 35.0F * sinf(t * M_PI);
|
||||||
|
val_shift = 0.2F * sinf(t * M_PI);
|
||||||
|
sat_shift = -0.2F * sinf(t * M_PI);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ColorCycleStyle::DARKEN_GLOW:
|
||||||
|
// Se oscurece al centro
|
||||||
|
val_shift = -0.15F * sinf(t * M_PI);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ColorCycleStyle::LIGHT_FLASH:
|
||||||
|
// Se ilumina al centro
|
||||||
|
val_shift = 0.25F * sinf(t * M_PI);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
HSV adjusted = {
|
||||||
|
.h = fmodf(base_hsv.h + hue_shift + 360.0F, 360.0F),
|
||||||
|
.s = fminf(1.0F, fmaxf(0.0F, base_hsv.s + sat_shift)),
|
||||||
|
.v = fminf(1.0F, fmaxf(0.0F, base_hsv.v + val_shift))};
|
||||||
|
|
||||||
|
Color c = Color::hsvToRgb(adjusted);
|
||||||
|
result[i] = c;
|
||||||
|
result[(2 * CYCLE_SIZE) - 1 - i] = c; // espejo
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,12 +9,14 @@
|
|||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
// --- Constantes ---
|
// --- Estructura HSV: define un color en formato HSV ---
|
||||||
constexpr size_t COLOR_CYCLE_SIZE = 6; // Mitad del ciclo espejado
|
struct HSV {
|
||||||
|
float h; // Matiz (Hue)
|
||||||
|
float s; // Saturación (Saturation)
|
||||||
|
float v; // Valor (Value)
|
||||||
|
};
|
||||||
|
|
||||||
// --- Estructuras y tipos ---
|
// --- Estructura Color: define un color RGBA ---
|
||||||
|
|
||||||
// Estructura para definir un color RGBA
|
|
||||||
struct Color {
|
struct Color {
|
||||||
private:
|
private:
|
||||||
static constexpr int DEFAULT_LIGHTEN_AMOUNT = 50;
|
static constexpr int DEFAULT_LIGHTEN_AMOUNT = 50;
|
||||||
@@ -62,6 +64,10 @@ struct Color {
|
|||||||
// Método estático para crear Color desde string hexadecimal
|
// Método estático para crear Color desde string hexadecimal
|
||||||
static auto fromHex(const std::string &hex_str) -> Color;
|
static auto fromHex(const std::string &hex_str) -> Color;
|
||||||
|
|
||||||
|
// Conversiones de formato de color
|
||||||
|
[[nodiscard]] constexpr static auto rgbToHsv(Color color) -> HSV;
|
||||||
|
[[nodiscard]] constexpr static auto hsvToRgb(HSV hsv) -> Color;
|
||||||
|
|
||||||
[[nodiscard]] constexpr auto IS_EQUAL_TO(const Color &other) const -> bool {
|
[[nodiscard]] constexpr auto IS_EQUAL_TO(const Color &other) const -> bool {
|
||||||
return r == other.r && g == other.g && b == other.b && a == other.a;
|
return r == other.r && g == other.g && b == other.b && a == other.a;
|
||||||
}
|
}
|
||||||
@@ -83,7 +89,7 @@ struct Color {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convierte el color a un entero de 32 bits en formato RGBA
|
// Convierte el color a un entero de 32 bits en formato RGBA
|
||||||
[[nodiscard]] constexpr auto toUint32() const -> Uint32 {
|
[[nodiscard]] constexpr auto TO_UINT32() const -> Uint32 {
|
||||||
return (static_cast<Uint32>(r) << 24) |
|
return (static_cast<Uint32>(r) << 24) |
|
||||||
(static_cast<Uint32>(g) << 16) |
|
(static_cast<Uint32>(g) << 16) |
|
||||||
(static_cast<Uint32>(b) << 8) |
|
(static_cast<Uint32>(b) << 8) |
|
||||||
@@ -91,12 +97,7 @@ struct Color {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Estructura para definir un color HSV
|
// --- Enum ColorCycleStyle: define estilos de ciclo de color ---
|
||||||
struct HSV {
|
|
||||||
float h, s, v;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para definir el ciclo de color
|
|
||||||
enum class ColorCycleStyle {
|
enum class ColorCycleStyle {
|
||||||
SUBTLE_PULSE, // Variación leve en brillo (por defecto)
|
SUBTLE_PULSE, // Variación leve en brillo (por defecto)
|
||||||
HUE_WAVE, // Variación suave en tono (sin verde)
|
HUE_WAVE, // Variación suave en tono (sin verde)
|
||||||
@@ -105,23 +106,27 @@ enum class ColorCycleStyle {
|
|||||||
LIGHT_FLASH // Ilumina hacia el centro y regresa
|
LIGHT_FLASH // Ilumina hacia el centro y regresa
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Alias ---
|
// --- Namespace Colors: constantes y utilidades de color ---
|
||||||
using ColorCycle = std::array<Color, 2 * COLOR_CYCLE_SIZE>;
|
namespace Colors {
|
||||||
|
// --- Constantes ---
|
||||||
|
constexpr size_t CYCLE_SIZE = 6; // Mitad del ciclo espejado
|
||||||
|
|
||||||
// --- Colores predefinidos ---
|
// --- Alias ---
|
||||||
constexpr Color NO_TEXT_COLOR = Color(0XFF, 0XFF, 0XFF);
|
using Cycle = std::array<Color, 2 * CYCLE_SIZE>;
|
||||||
constexpr Color SHADOW_TEXT_COLOR = Color(0X43, 0X43, 0X4F);
|
|
||||||
constexpr Color TITLE_SHADOW_TEXT_COLOR = Color(0x14, 0x87, 0xc4);
|
|
||||||
constexpr Color ORANGE_TEXT_COLOR = Color(0XFF, 0X7A, 0X00);
|
|
||||||
|
|
||||||
constexpr Color FLASH_COLOR = Color(0XFF, 0XFF, 0XFF);
|
// --- Colores predefinidos ---
|
||||||
|
constexpr Color NO_COLOR_MOD = Color(0XFF, 0XFF, 0XFF);
|
||||||
|
constexpr Color SHADOW_TEXT = Color(0X43, 0X43, 0X4F);
|
||||||
|
constexpr Color TITLE_SHADOW_TEXT = Color(0x14, 0x87, 0xc4);
|
||||||
|
constexpr Color ORANGE_TEXT = Color(0XFF, 0X7A, 0X00);
|
||||||
|
|
||||||
constexpr Color BLUE_SKY_COLOR = Color(0X02, 0X88, 0XD1);
|
constexpr Color FLASH = Color(0XFF, 0XFF, 0XFF);
|
||||||
constexpr Color PINK_SKY_COLOR = Color(0XFF, 0X6B, 0X97);
|
|
||||||
constexpr Color GREEN_SKY_COLOR = Color(0X00, 0X79, 0X6B);
|
|
||||||
|
|
||||||
// --- Funciones ---
|
constexpr Color BLUE_SKY = Color(0X02, 0X88, 0XD1);
|
||||||
auto getColorLikeKnightRider(const std::vector<Color> &colors, int counter) -> Color;
|
constexpr Color PINK_SKY = Color(0XFF, 0X6B, 0X97);
|
||||||
constexpr auto rgbToHsv(Color color) -> HSV;
|
constexpr Color GREEN_SKY = Color(0X00, 0X79, 0X6B);
|
||||||
constexpr auto hsvToRgb(HSV hsv) -> Color;
|
|
||||||
auto generateMirroredCycle(Color base, ColorCycleStyle style = ColorCycleStyle::SUBTLE_PULSE) -> ColorCycle;
|
// --- Funciones ---
|
||||||
|
auto getColorLikeKnightRider(const std::vector<Color> &colors, int counter) -> Color;
|
||||||
|
auto generateMirroredCycle(Color base, ColorCycleStyle style = ColorCycleStyle::SUBTLE_PULSE) -> Cycle;
|
||||||
|
}
|
||||||
@@ -1,47 +1,49 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h> // Para SDL_ScaleMode
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "ui/notifier.h" // Para Notifier::Position
|
#include "ui/notifier.h" // Para Notifier::Position
|
||||||
|
|
||||||
// Configuración centralizada con todos los valores por defecto del juego
|
// --- Namespace GameDefaults: configuración centralizada con valores por defecto del juego ---
|
||||||
namespace GameDefaults {
|
namespace GameDefaults {
|
||||||
|
|
||||||
// --- GAME ---
|
// --- GAME ---
|
||||||
namespace Game {
|
namespace Game {
|
||||||
constexpr float WIDTH = 320.0f;
|
constexpr float WIDTH = 320.0F;
|
||||||
constexpr float HEIGHT = 256.0f;
|
constexpr float HEIGHT = 256.0F;
|
||||||
constexpr float ITEM_SIZE = 20.0f;
|
constexpr float ITEM_SIZE = 20.0F;
|
||||||
constexpr int NAME_ENTRY_IDLE_TIME = 10;
|
constexpr int NAME_ENTRY_IDLE_TIME = 10;
|
||||||
constexpr int NAME_ENTRY_TOTAL_TIME = 60;
|
constexpr int NAME_ENTRY_TOTAL_TIME = 60;
|
||||||
constexpr bool HIT_STOP = false;
|
constexpr bool HIT_STOP = false;
|
||||||
constexpr int HIT_STOP_MS = 500;
|
constexpr int HIT_STOP_MS = 500;
|
||||||
|
constexpr const char* ITEM_TEXT_OUTLINE_COLOR = "FFFFFF00"; // 255, 255, 255, 0
|
||||||
|
|
||||||
// Play area por defecto
|
// Play area por defecto
|
||||||
constexpr float PLAY_AREA_X = 0.0f;
|
constexpr float PLAY_AREA_X = 0.0F;
|
||||||
constexpr float PLAY_AREA_Y = 0.0f;
|
constexpr float PLAY_AREA_Y = 0.0F;
|
||||||
constexpr float PLAY_AREA_W = 320.0f;
|
constexpr float PLAY_AREA_W = 320.0F;
|
||||||
constexpr float PLAY_AREA_H = 216.0f;
|
constexpr float PLAY_AREA_H = 216.0F;
|
||||||
} // namespace Game
|
} // namespace Game
|
||||||
|
|
||||||
// --- FADE ---
|
// --- FADE ---
|
||||||
namespace Fade {
|
namespace Fade {
|
||||||
constexpr const char* COLOR = "1F2B30";
|
constexpr const char* COLOR = "1F2B30";
|
||||||
constexpr float NUM_SQUARES_WIDTH = 160.0f;
|
constexpr float NUM_SQUARES_WIDTH = 160.0F;
|
||||||
constexpr float NUM_SQUARES_HEIGHT = 128.0f;
|
constexpr float NUM_SQUARES_HEIGHT = 128.0F;
|
||||||
constexpr int RANDOM_SQUARES_DELAY = 1;
|
constexpr int RANDOM_SQUARES_DURATION_MS = 1;
|
||||||
constexpr int RANDOM_SQUARES_MULT = 500;
|
constexpr int POST_DURATION_MS = 80;
|
||||||
constexpr int POST_DURATION = 80;
|
constexpr float VENETIAN_SIZE = 12.0F;
|
||||||
constexpr float VENETIAN_SIZE = 12.0f;
|
|
||||||
} // namespace Fade
|
} // namespace Fade
|
||||||
|
|
||||||
// --- SCOREBOARD ---
|
// --- SCOREBOARD ---
|
||||||
namespace Scoreboard {
|
namespace Scoreboard {
|
||||||
constexpr float RECT_X = 0.0f;
|
constexpr float RECT_X = 0.0F;
|
||||||
constexpr float RECT_Y = 216.0f;
|
constexpr float RECT_Y = 216.0F;
|
||||||
constexpr float RECT_W = 320.0f;
|
constexpr float RECT_W = 320.0F;
|
||||||
constexpr float RECT_H = 40.0f;
|
constexpr float RECT_H = 40.0F;
|
||||||
constexpr bool SEPARATOR_AUTOCOLOR = true;
|
constexpr bool SEPARATOR_AUTOCOLOR = true;
|
||||||
constexpr const char* SEPARATOR_COLOR = "0D1A2B";
|
constexpr const char* SEPARATOR_COLOR = "0D1A2B";
|
||||||
constexpr const char* EASY_COLOR = "4B692F";
|
constexpr const char* EASY_COLOR = "4B692F";
|
||||||
@@ -73,18 +75,22 @@ namespace Balloon {
|
|||||||
struct BalloonSettings {
|
struct BalloonSettings {
|
||||||
float vel;
|
float vel;
|
||||||
float grav;
|
float grav;
|
||||||
constexpr BalloonSettings(float v, float g) : vel(v), grav(g) {}
|
constexpr BalloonSettings(float v, float g)
|
||||||
|
: vel(v), grav(g) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr std::array<BalloonSettings, 4> SETTINGS = {{
|
constexpr std::array<BalloonSettings, 4> SETTINGS = {{
|
||||||
BalloonSettings(2.75f, 0.09f), // Globo 0
|
BalloonSettings(2.75F, 0.09F), // Globo 0
|
||||||
BalloonSettings(3.70f, 0.10f), // Globo 1
|
BalloonSettings(3.70F, 0.10F), // Globo 1
|
||||||
BalloonSettings(4.70f, 0.10f), // Globo 2
|
BalloonSettings(4.70F, 0.10F), // Globo 2
|
||||||
BalloonSettings(5.45f, 0.10f) // Globo 3
|
BalloonSettings(5.45F, 0.10F) // Globo 3
|
||||||
}};
|
}};
|
||||||
|
|
||||||
constexpr std::array<const char*, 4> COLORS = {
|
constexpr std::array<const char*, 4> COLORS = {
|
||||||
"blue", "orange", "red", "green"};
|
"blue",
|
||||||
|
"orange",
|
||||||
|
"red",
|
||||||
|
"green"};
|
||||||
|
|
||||||
constexpr bool BOUNCING_SOUND = false;
|
constexpr bool BOUNCING_SOUND = false;
|
||||||
} // namespace Balloon
|
} // namespace Balloon
|
||||||
@@ -111,15 +117,15 @@ constexpr const char* BG_COLOR = "141E32F0"; // Color(20, 30, 50, 240)
|
|||||||
constexpr const char* BORDER_COLOR = "6496C8FF"; // Color(100, 150, 200, 255)
|
constexpr const char* BORDER_COLOR = "6496C8FF"; // Color(100, 150, 200, 255)
|
||||||
constexpr const char* TITLE_COLOR = "6496C8FF"; // Color(100, 150, 200, 255)
|
constexpr const char* TITLE_COLOR = "6496C8FF"; // Color(100, 150, 200, 255)
|
||||||
constexpr const char* TEXT_COLOR = "DCDCDCFF"; // Color(220, 220, 220, 255)
|
constexpr const char* TEXT_COLOR = "DCDCDCFF"; // Color(220, 220, 220, 255)
|
||||||
constexpr float PADDING = 15.0f;
|
constexpr float PADDING = 15.0F;
|
||||||
constexpr float LINE_SPACING = 5.0f;
|
constexpr float LINE_SPACING = 5.0F;
|
||||||
constexpr float TITLE_SEPARATOR_SPACING = 10.0f; // Cambiado a float
|
constexpr float TITLE_SEPARATOR_SPACING = 10.0F; // Cambiado a float
|
||||||
constexpr float MIN_WIDTH = 250.0f;
|
constexpr float MIN_WIDTH = 250.0F;
|
||||||
constexpr float MIN_HEIGHT = 32.0f; // Cambiado a float
|
constexpr float MIN_HEIGHT = 32.0F; // Cambiado a float
|
||||||
constexpr float MAX_WIDTH_RATIO = 0.8f; // Nuevo
|
constexpr float MAX_WIDTH_RATIO = 0.8F; // Nuevo
|
||||||
constexpr float MAX_HEIGHT_RATIO = 0.8f; // Nuevo
|
constexpr float MAX_HEIGHT_RATIO = 0.8F; // Nuevo
|
||||||
constexpr float TEXT_SAFETY_MARGIN = 15.0f;
|
constexpr float TEXT_SAFETY_MARGIN = 15.0F;
|
||||||
constexpr float ANIMATION_DURATION = 0.3f;
|
constexpr float ANIMATION_DURATION = 0.3F;
|
||||||
} // namespace WindowMessage
|
} // namespace WindowMessage
|
||||||
} // namespace ServiceMenu
|
} // namespace ServiceMenu
|
||||||
|
|
||||||
@@ -143,12 +149,26 @@ constexpr const char* COLOR = "FFFFFF";
|
|||||||
|
|
||||||
// --- TABE ---
|
// --- TABE ---
|
||||||
namespace Tabe {
|
namespace Tabe {
|
||||||
constexpr float MIN_SPAWN_TIME = 2.0f;
|
constexpr float MIN_SPAWN_TIME = 2.0F;
|
||||||
constexpr float MAX_SPAWN_TIME = 3.0f;
|
constexpr float MAX_SPAWN_TIME = 3.0F;
|
||||||
} // namespace Tabe
|
} // namespace Tabe
|
||||||
|
|
||||||
// --- PLAYER ---
|
// --- PLAYER ---
|
||||||
namespace Player {
|
namespace Player {
|
||||||
|
namespace DefaultShirt {
|
||||||
|
// Player 0 (Jugador 1)
|
||||||
|
constexpr const char* PLAYER0_DARKEST = "028ECFFF"; // 2, 142, 207, 255
|
||||||
|
constexpr const char* PLAYER0_DARK = "0297DBFF"; // 2, 151, 219, 255
|
||||||
|
constexpr const char* PLAYER0_BASE = "029FE8FF"; // 2, 159, 232, 255
|
||||||
|
constexpr const char* PLAYER0_LIGHT = "03A9F4FF"; // 3, 169, 244, 255
|
||||||
|
|
||||||
|
// Player 1 (Jugador 2)
|
||||||
|
constexpr const char* PLAYER1_DARKEST = "8E8E8EFF"; // 142, 142, 142, 255
|
||||||
|
constexpr const char* PLAYER1_DARK = "AEADADFF"; // 174, 173, 173, 255
|
||||||
|
constexpr const char* PLAYER1_BASE = "E4E4E4FF"; // 228, 228, 228, 255
|
||||||
|
constexpr const char* PLAYER1_LIGHT = "F7F1F1FF"; // 247, 241, 241, 255
|
||||||
|
} // namespace DefaultShirt
|
||||||
|
|
||||||
namespace OneCoffeeShirt {
|
namespace OneCoffeeShirt {
|
||||||
// Player 0 (Jugador 1)
|
// Player 0 (Jugador 1)
|
||||||
constexpr const char* PLAYER0_DARKEST = "3D9C70FF"; // 61, 156, 112, 255
|
constexpr const char* PLAYER0_DARKEST = "3D9C70FF"; // 61, 156, 112, 255
|
||||||
@@ -176,5 +196,45 @@ constexpr const char* PLAYER1_DARK = "FA7D00FF"; // 250, 125, 0, 255
|
|||||||
constexpr const char* PLAYER1_BASE = "FAA200FF"; // 250, 162, 0, 255
|
constexpr const char* PLAYER1_BASE = "FAA200FF"; // 250, 162, 0, 255
|
||||||
constexpr const char* PLAYER1_LIGHT = "FA8500FF"; // 250, 133, 0, 255
|
constexpr const char* PLAYER1_LIGHT = "FA8500FF"; // 250, 133, 0, 255
|
||||||
} // namespace TwoCoffeeShirt
|
} // namespace TwoCoffeeShirt
|
||||||
|
|
||||||
|
namespace OutlineColor {
|
||||||
|
// Player 0 (Jugador 1)
|
||||||
|
constexpr const char* PLAYER0 = "66323FFF";
|
||||||
|
|
||||||
|
// Player 1 (Jugador 2)
|
||||||
|
constexpr const char* PLAYER1 = "422028FF";
|
||||||
|
} // namespace OutlineColor
|
||||||
} // namespace Player
|
} // namespace Player
|
||||||
|
|
||||||
|
// --- OPTIONS ---
|
||||||
|
namespace Options {
|
||||||
|
// Window
|
||||||
|
constexpr const char* WINDOW_CAPTION = "Coffee Crisis Arcade Edition";
|
||||||
|
constexpr int WINDOW_ZOOM = 2;
|
||||||
|
constexpr int WINDOW_MAX_ZOOM = 2;
|
||||||
|
|
||||||
|
// Video
|
||||||
|
constexpr SDL_ScaleMode VIDEO_SCALE_MODE = SDL_ScaleMode::SDL_SCALEMODE_NEAREST;
|
||||||
|
constexpr bool VIDEO_FULLSCREEN = false;
|
||||||
|
constexpr bool VIDEO_VSYNC = true;
|
||||||
|
constexpr bool VIDEO_INTEGER_SCALE = true;
|
||||||
|
constexpr bool VIDEO_SHADERS = false;
|
||||||
|
|
||||||
|
// Music
|
||||||
|
constexpr bool MUSIC_ENABLED = true;
|
||||||
|
constexpr int MUSIC_VOLUME = 100;
|
||||||
|
|
||||||
|
// Sound
|
||||||
|
constexpr bool SOUND_ENABLED = true;
|
||||||
|
constexpr int SOUND_VOLUME = 100;
|
||||||
|
|
||||||
|
// Audio
|
||||||
|
constexpr bool AUDIO_ENABLED = true;
|
||||||
|
constexpr int AUDIO_VOLUME = 100;
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
constexpr bool SETTINGS_AUTOFIRE = true;
|
||||||
|
constexpr bool SETTINGS_SHUTDOWN_ENABLED = false;
|
||||||
|
constexpr const char* PARAMS_FILE = "param_320x256.txt";
|
||||||
|
} // namespace Options
|
||||||
} // namespace GameDefaults
|
} // namespace GameDefaults
|
||||||
@@ -19,7 +19,7 @@ DefineButtons::DefineButtons()
|
|||||||
clearButtons();
|
clearButtons();
|
||||||
|
|
||||||
auto gamepads = input_->getGamepads();
|
auto gamepads = input_->getGamepads();
|
||||||
for (auto gamepad : gamepads) {
|
for (const auto &gamepad : gamepads) {
|
||||||
controller_names_.emplace_back(Input::getControllerName(gamepad));
|
controller_names_.emplace_back(Input::getControllerName(gamepad));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +72,9 @@ void DefineButtons::handleEvents(const SDL_Event &event) {
|
|||||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||||
checkEnd();
|
checkEnd();
|
||||||
break;
|
break;
|
||||||
|
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||||
|
doControllerAxisMotion(event.gaxis);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -86,6 +89,8 @@ auto DefineButtons::enable(Options::Gamepad *options_gamepad) -> bool {
|
|||||||
index_button_ = 0;
|
index_button_ = 0;
|
||||||
message_shown_ = false;
|
message_shown_ = false;
|
||||||
closing_ = false;
|
closing_ = false;
|
||||||
|
l2_was_pressed_ = false;
|
||||||
|
r2_was_pressed_ = false;
|
||||||
clearButtons();
|
clearButtons();
|
||||||
updateWindowMessage();
|
updateWindowMessage();
|
||||||
|
|
||||||
@@ -104,6 +109,8 @@ void DefineButtons::disable() {
|
|||||||
finished_ = false;
|
finished_ = false;
|
||||||
message_shown_ = false;
|
message_shown_ = false;
|
||||||
closing_ = false;
|
closing_ = false;
|
||||||
|
l2_was_pressed_ = false;
|
||||||
|
r2_was_pressed_ = false;
|
||||||
|
|
||||||
if (window_message_) {
|
if (window_message_) {
|
||||||
window_message_->hide();
|
window_message_->hide();
|
||||||
@@ -119,15 +126,65 @@ void DefineButtons::doControllerButtonDown(const SDL_GamepadButtonEvent &event)
|
|||||||
|
|
||||||
const auto BUTTON = static_cast<SDL_GamepadButton>(event.button);
|
const auto BUTTON = static_cast<SDL_GamepadButton>(event.button);
|
||||||
if (checkButtonNotInUse(BUTTON)) {
|
if (checkButtonNotInUse(BUTTON)) {
|
||||||
buttons_.at(index_button_).button = BUTTON;
|
buttons_.at(index_button_).button = static_cast<int>(BUTTON);
|
||||||
incIndexButton();
|
incIndexButton();
|
||||||
updateWindowMessage();
|
updateWindowMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DefineButtons::doControllerAxisMotion(const SDL_GamepadAxisEvent &event) {
|
||||||
|
auto gamepad = input_->getGamepad(event.which);
|
||||||
|
|
||||||
|
if (!gamepad || gamepad != options_gamepad_->instance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solo manejamos L2 y R2 como botones con lógica de transición
|
||||||
|
if (event.axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER) {
|
||||||
|
bool l2_is_pressed_now = event.value > 16384;
|
||||||
|
|
||||||
|
// Solo actuar en la transición de no presionado a presionado
|
||||||
|
if (l2_is_pressed_now && !l2_was_pressed_) {
|
||||||
|
const auto TRIGGER_BUTTON = Input::TRIGGER_L2_AS_BUTTON;
|
||||||
|
if (checkTriggerNotInUse(TRIGGER_BUTTON)) {
|
||||||
|
buttons_.at(index_button_).button = TRIGGER_BUTTON;
|
||||||
|
incIndexButton();
|
||||||
|
updateWindowMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detectar liberación del trigger para llamar checkEnd()
|
||||||
|
if (!l2_is_pressed_now && l2_was_pressed_) {
|
||||||
|
checkEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
l2_was_pressed_ = l2_is_pressed_now;
|
||||||
|
|
||||||
|
} else if (event.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) {
|
||||||
|
bool r2_is_pressed_now = event.value > 16384;
|
||||||
|
|
||||||
|
// Solo actuar en la transición de no presionado a presionado
|
||||||
|
if (r2_is_pressed_now && !r2_was_pressed_) {
|
||||||
|
const auto TRIGGER_BUTTON = Input::TRIGGER_R2_AS_BUTTON;
|
||||||
|
if (checkTriggerNotInUse(TRIGGER_BUTTON)) {
|
||||||
|
buttons_.at(index_button_).button = TRIGGER_BUTTON;
|
||||||
|
incIndexButton();
|
||||||
|
updateWindowMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detectar liberación del trigger para llamar checkEnd()
|
||||||
|
if (!r2_is_pressed_now && r2_was_pressed_) {
|
||||||
|
checkEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
r2_was_pressed_ = r2_is_pressed_now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DefineButtons::bindButtons(Options::Gamepad *options_gamepad) {
|
void DefineButtons::bindButtons(Options::Gamepad *options_gamepad) {
|
||||||
for (const auto &button : buttons_) {
|
for (const auto &button : buttons_) {
|
||||||
Input::bindGameControllerButton(options_gamepad->instance, button.action, button.button);
|
Input::bindGameControllerButton(options_gamepad->instance, button.action, static_cast<SDL_GamepadButton>(button.button));
|
||||||
}
|
}
|
||||||
|
|
||||||
Input::bindGameControllerButton(options_gamepad->instance, Input::Action::SM_SELECT, Input::Action::FIRE_LEFT);
|
Input::bindGameControllerButton(options_gamepad->instance, Input::Action::SM_SELECT, Input::Action::FIRE_LEFT);
|
||||||
@@ -148,13 +205,19 @@ auto DefineButtons::checkButtonNotInUse(SDL_GamepadButton button) -> bool {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto DefineButtons::checkTriggerNotInUse(int trigger_button) -> bool {
|
||||||
|
return std::ranges::all_of(buttons_, [trigger_button](const auto &b) {
|
||||||
|
return b.button != trigger_button;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void DefineButtons::clearButtons() {
|
void DefineButtons::clearButtons() {
|
||||||
buttons_.clear();
|
buttons_.clear();
|
||||||
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_LEFT"), Input::Action::FIRE_LEFT, SDL_GAMEPAD_BUTTON_INVALID);
|
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_LEFT"), Input::Action::FIRE_LEFT, static_cast<int>(SDL_GAMEPAD_BUTTON_INVALID));
|
||||||
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_UP"), Input::Action::FIRE_CENTER, SDL_GAMEPAD_BUTTON_INVALID);
|
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_UP"), Input::Action::FIRE_CENTER, static_cast<int>(SDL_GAMEPAD_BUTTON_INVALID));
|
||||||
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_RIGHT"), Input::Action::FIRE_RIGHT, SDL_GAMEPAD_BUTTON_INVALID);
|
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_RIGHT"), Input::Action::FIRE_RIGHT, static_cast<int>(SDL_GAMEPAD_BUTTON_INVALID));
|
||||||
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] START"), Input::Action::START, SDL_GAMEPAD_BUTTON_INVALID);
|
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] START"), Input::Action::START, static_cast<int>(SDL_GAMEPAD_BUTTON_INVALID));
|
||||||
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] SERVICE_MENU"), Input::Action::SERVICE, SDL_GAMEPAD_BUTTON_INVALID);
|
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] SERVICE_MENU"), Input::Action::SERVICE, static_cast<int>(SDL_GAMEPAD_BUTTON_INVALID));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefineButtons::checkEnd() {
|
void DefineButtons::checkEnd() {
|
||||||
|
|||||||
@@ -15,57 +15,63 @@ namespace Options {
|
|||||||
struct Gamepad;
|
struct Gamepad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Clase DefineButtons: configuración de botones de gamepad ---
|
||||||
class DefineButtons {
|
class DefineButtons {
|
||||||
public:
|
public:
|
||||||
|
// --- Estructuras ---
|
||||||
struct Button {
|
struct Button {
|
||||||
std::string label;
|
std::string label;
|
||||||
Input::Action action;
|
Input::Action action;
|
||||||
SDL_GamepadButton button;
|
int button;
|
||||||
|
|
||||||
Button(std::string label, Input::Action action, SDL_GamepadButton button)
|
Button(std::string label, Input::Action action, int button)
|
||||||
: label(std::move(label)), action(action), button(button) {}
|
: label(std::move(label)), action(action), button(button) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- Constructor y destructor ---
|
||||||
DefineButtons();
|
DefineButtons();
|
||||||
~DefineButtons() = default;
|
~DefineButtons() = default;
|
||||||
|
|
||||||
|
// --- Métodos principales ---
|
||||||
void render();
|
void render();
|
||||||
void update();
|
void update();
|
||||||
void handleEvents(const SDL_Event &event);
|
void handleEvents(const SDL_Event &event);
|
||||||
auto enable(Options::Gamepad *options_gamepad) -> bool;
|
auto enable(Options::Gamepad *options_gamepad) -> bool;
|
||||||
void disable();
|
void disable();
|
||||||
|
|
||||||
|
// --- Getters ---
|
||||||
[[nodiscard]] auto isReadyToClose() const -> bool;
|
[[nodiscard]] auto isReadyToClose() const -> bool;
|
||||||
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
|
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
|
||||||
[[nodiscard]] auto isFinished() const -> bool { return finished_; }
|
[[nodiscard]] auto isFinished() const -> bool { return finished_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Constante para cuánto tiempo mostrar el mensaje (en frames)
|
// --- Constantes ---
|
||||||
static constexpr size_t MESSAGE_DISPLAY_FRAMES = 120; // ~2 segundos a 60fps
|
static constexpr size_t MESSAGE_DISPLAY_FRAMES = 120; // Cuánto tiempo mostrar el mensaje (en frames) ~2 segundos a 60fps
|
||||||
|
|
||||||
// Punteros
|
// --- Objetos y punteros ---
|
||||||
Input *input_ = nullptr; // Entrada del usuario
|
Input *input_ = nullptr; // Entrada del usuario
|
||||||
Options::Gamepad *options_gamepad_ = nullptr; // Opciones del gamepad
|
Options::Gamepad *options_gamepad_ = nullptr; // Opciones del gamepad
|
||||||
std::unique_ptr<WindowMessage> window_message_; // Mensaje de ventana
|
std::unique_ptr<WindowMessage> window_message_; // Mensaje de ventana
|
||||||
|
|
||||||
// Vectores y strings
|
// --- Variables de estado ---
|
||||||
std::vector<Button> buttons_; // Lista de botones
|
std::vector<Button> buttons_; // Lista de botones
|
||||||
std::vector<std::string> controller_names_; // Nombres de los controladores
|
std::vector<std::string> controller_names_; // Nombres de los controladores
|
||||||
|
size_t index_button_ = 0; // Índice del botón seleccionado
|
||||||
|
size_t message_timer_ = 0; // Contador de frames para el mensaje
|
||||||
|
bool enabled_ = false; // Flag para indicar si está activo
|
||||||
|
bool finished_ = false; // Flag para indicar si ha terminado
|
||||||
|
bool closing_ = false; // Flag para indicar que está cerrando
|
||||||
|
bool message_shown_ = false; // Flag para indicar que ya mostró el mensaje
|
||||||
|
bool l2_was_pressed_ = false; // Estado anterior del trigger L2
|
||||||
|
bool r2_was_pressed_ = false; // Estado anterior del trigger R2
|
||||||
|
|
||||||
// size_t
|
// --- Métodos internos ---
|
||||||
size_t index_button_ = 0; // Índice del botón seleccionado
|
|
||||||
size_t message_timer_ = 0; // Contador de frames para el mensaje
|
|
||||||
|
|
||||||
// bools
|
|
||||||
bool enabled_ = false; // Flag para indicar si está activo
|
|
||||||
bool finished_ = false; // Flag para indicar si ha terminado
|
|
||||||
bool closing_ = false; // Flag para indicar que está cerrando
|
|
||||||
bool message_shown_ = false; // Flag para indicar que ya mostró el mensaje
|
|
||||||
|
|
||||||
// Métodos
|
|
||||||
void incIndexButton();
|
void incIndexButton();
|
||||||
void doControllerButtonDown(const SDL_GamepadButtonEvent &event);
|
void doControllerButtonDown(const SDL_GamepadButtonEvent &event);
|
||||||
|
void doControllerAxisMotion(const SDL_GamepadAxisEvent &event);
|
||||||
void bindButtons(Options::Gamepad *options_gamepad);
|
void bindButtons(Options::Gamepad *options_gamepad);
|
||||||
auto checkButtonNotInUse(SDL_GamepadButton button) -> bool;
|
auto checkButtonNotInUse(SDL_GamepadButton button) -> bool;
|
||||||
|
auto checkTriggerNotInUse(int trigger_button) -> bool;
|
||||||
void clearButtons();
|
void clearButtons();
|
||||||
void checkEnd();
|
void checkEnd();
|
||||||
void updateWindowMessage();
|
void updateWindowMessage();
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ static std::vector<Info> difficulties_list;
|
|||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
difficulties_list = {
|
difficulties_list = {
|
||||||
{Code::EASY, "Easy"},
|
{.code = Code::EASY, .name = "Easy"},
|
||||||
{Code::NORMAL, "Normal"},
|
{.code = Code::NORMAL, .name = "Normal"},
|
||||||
{Code::HARD, "Hard"}};
|
{.code = Code::HARD, .name = "Hard"}};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto getDifficulties() -> std::vector<Info>& {
|
auto getDifficulties() -> std::vector<Info>& {
|
||||||
|
|||||||
@@ -1,52 +1,28 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string> // Para string
|
||||||
#include <vector>
|
#include <vector> // Para vector
|
||||||
|
|
||||||
namespace Difficulty {
|
namespace Difficulty {
|
||||||
|
|
||||||
/**
|
// --- Enums ---
|
||||||
* @brief Códigos que identifican unívocamente cada nivel de dificultad.
|
|
||||||
*/
|
|
||||||
enum class Code {
|
enum class Code {
|
||||||
EASY = 0,
|
EASY = 0, // Dificultad fácil
|
||||||
NORMAL = 1,
|
NORMAL = 1, // Dificultad normal
|
||||||
HARD = 2,
|
HARD = 2, // Dificultad difícil
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
// --- Estructuras ---
|
||||||
* @brief Estructura que asocia un código de dificultad con su nombre traducible.
|
|
||||||
*/
|
|
||||||
struct Info {
|
struct Info {
|
||||||
Code code;
|
Code code; // Código de dificultad
|
||||||
std::string name;
|
std::string name; // Nombre traducible
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Interfaz Pública ---
|
// --- Funciones ---
|
||||||
|
void init(); // Inicializa la lista de dificultades con sus valores por defecto
|
||||||
|
|
||||||
/**
|
auto getDifficulties() -> std::vector<Info>&; // Devuelve una referencia al vector de todas las dificultades
|
||||||
* @brief Inicializa la lista de dificultades con sus valores por defecto.
|
auto getNameFromCode(Code code) -> std::string; // Obtiene el nombre de una dificultad a partir de su código
|
||||||
*/
|
auto getCodeFromName(const std::string& name) -> Code; // Obtiene el código de una dificultad a partir de su nombre
|
||||||
void init();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Devuelve una referencia al vector de todas las dificultades para su lectura o modificación.
|
|
||||||
* @return Referencia a `std::vector<Info>&`.
|
|
||||||
*/
|
|
||||||
auto getDifficulties() -> std::vector<Info>&;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Obtiene el nombre de una dificultad a partir de su código.
|
|
||||||
* @param code El código de la dificultad.
|
|
||||||
* @return El nombre de la dificultad.
|
|
||||||
*/
|
|
||||||
auto getNameFromCode(Code code) -> std::string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Obtiene el código de una dificultad a partir de su nombre.
|
|
||||||
* @param name El nombre de la dificultad.
|
|
||||||
* @return El código de la dificultad.
|
|
||||||
*/
|
|
||||||
auto getCodeFromName(const std::string& name) -> Code;
|
|
||||||
|
|
||||||
} // namespace Difficulty
|
} // namespace Difficulty
|
||||||
@@ -124,9 +124,9 @@ void Director::close() {
|
|||||||
void Director::loadParams() {
|
void Director::loadParams() {
|
||||||
// Carga los parametros para configurar el juego
|
// Carga los parametros para configurar el juego
|
||||||
#ifdef ANBERNIC
|
#ifdef ANBERNIC
|
||||||
const std::string paramFilePath = asset->get("param_320x240.txt");
|
const std::string PARAM_FILE_PATH = Asset::get()->get("param_320x240.txt");
|
||||||
#else
|
#else
|
||||||
const std::string PARAM_FILE_PATH = overrides.param_file == "--320x240" ? Asset::get()->get("param_320x240.txt") : Asset::get()->get("param_320x256.txt");
|
const std::string PARAM_FILE_PATH = Asset::get()->get(Options::settings.params_file);
|
||||||
#endif
|
#endif
|
||||||
loadParamsFromFile(PARAM_FILE_PATH);
|
loadParamsFromFile(PARAM_FILE_PATH);
|
||||||
}
|
}
|
||||||
@@ -188,7 +188,7 @@ void Director::createSystemFolder(const std::string &folder) {
|
|||||||
|
|
||||||
if (result != SystemUtils::Result::SUCCESS) {
|
if (result != SystemUtils::Result::SUCCESS) {
|
||||||
std::cerr << "Error creando carpeta del sistema: "
|
std::cerr << "Error creando carpeta del sistema: "
|
||||||
<< SystemUtils::resultToString(result) << std::endl;
|
<< SystemUtils::resultToString(result) << '\n';
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -321,7 +321,7 @@ void Director::shutdownSystem(bool should_shutdown) {
|
|||||||
auto result = SystemShutdown::shutdownSystem(5, true); // 5 segundos, forzar apps
|
auto result = SystemShutdown::shutdownSystem(5, true); // 5 segundos, forzar apps
|
||||||
|
|
||||||
if (result != SystemShutdown::ShutdownResult::SUCCESS) {
|
if (result != SystemShutdown::ShutdownResult::SUCCESS) {
|
||||||
std::cerr << SystemShutdown::resultToString(result) << std::endl;
|
std::cerr << SystemShutdown::resultToString(result) << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ namespace Lang {
|
|||||||
enum class Code : int;
|
enum class Code : int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Clase Director: gestor principal de la aplicación ---
|
||||||
class Director {
|
class Director {
|
||||||
public:
|
public:
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ void EnterName::incPosition() {
|
|||||||
if (position_ >= NAME_SIZE) {
|
if (position_ >= NAME_SIZE) {
|
||||||
position_ = NAME_SIZE; // Mantenemos en el índice máximo válido.
|
position_ = NAME_SIZE; // Mantenemos en el índice máximo válido.
|
||||||
position_overflow_ = true; // Activamos el flag de overflow.
|
position_overflow_ = true; // Activamos el flag de overflow.
|
||||||
} else if (position_ > 0) // No es necesario verificar position_ < MAX_NAME_LENGHT
|
} else if (position_ > 0) // No es necesario verificar position_ < MAX_NAME_LENGTH
|
||||||
{
|
{
|
||||||
// Copiamos el índice del carácter anterior si es posible.
|
// Copiamos el índice del carácter anterior si es posible.
|
||||||
character_index_[position_] = character_index_[position_ - 1];
|
character_index_[position_] = character_index_[position_ - 1];
|
||||||
@@ -74,7 +74,7 @@ void EnterName::decPosition() {
|
|||||||
// character_index_[position_] = 0;
|
// character_index_[position_] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si position_ es menor que NAME_LENGHT, aseguramos que el overflow esté desactivado.
|
// Si position_ es menor que NAME_LENGTH, aseguramos que el overflow esté desactivado.
|
||||||
if (position_ < NAME_SIZE) {
|
if (position_ < NAME_SIZE) {
|
||||||
position_overflow_ = false;
|
position_overflow_ = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
#include "utils.h" // Para trim
|
#include "utils.h" // Para trim
|
||||||
|
|
||||||
// Tamaño máximo del nombre
|
// --- Constantes ---
|
||||||
constexpr size_t NAME_SIZE = 5;
|
constexpr size_t NAME_SIZE = 5; // Tamaño máximo del nombre
|
||||||
|
|
||||||
// Clase EnterName
|
// --- Clase EnterName: gestor de entrada de nombre del jugador ---
|
||||||
class EnterName {
|
class EnterName {
|
||||||
public:
|
public:
|
||||||
EnterName();
|
EnterName();
|
||||||
@@ -29,11 +29,12 @@ class EnterName {
|
|||||||
[[nodiscard]] auto getPositionOverflow() const -> bool { return position_overflow_; } // Indica si la posición excede el límite
|
[[nodiscard]] auto getPositionOverflow() const -> bool { return position_overflow_; } // Indica si la posición excede el límite
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// --- Variables de estado ---
|
||||||
std::string character_list_; // Lista de caracteres permitidos
|
std::string character_list_; // Lista de caracteres permitidos
|
||||||
std::string name_; // Nombre en proceso
|
std::string name_; // Nombre en proceso
|
||||||
|
std::array<int, NAME_SIZE> character_index_; // Índices a "character_list_"
|
||||||
size_t position_ = 0; // Índice del carácter que se edita
|
size_t position_ = 0; // Índice del carácter que se edita
|
||||||
bool position_overflow_ = false; // Flag para exceder límite
|
bool position_overflow_ = false; // Flag para exceder límite
|
||||||
std::array<int, NAME_SIZE> character_index_; // Índices a "character_list_"
|
|
||||||
|
|
||||||
void updateNameFromCharacterIndex(); // Actualiza "name_" según "character_index_"
|
void updateNameFromCharacterIndex(); // Actualiza "name_" según "character_index_"
|
||||||
void initCharacterIndex(const std::string &name); // Inicializa índices desde el nombre
|
void initCharacterIndex(const std::string &name); // Inicializa índices desde el nombre
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ void Explosions::render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Añade texturas al objeto
|
// Añade texturas al objeto
|
||||||
void Explosions::addTexture(int size, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation) {
|
void Explosions::addTexture(int size, const std::shared_ptr<Texture> &texture, const std::vector<std::string> &animation) {
|
||||||
textures_.emplace_back(size, texture, animation);
|
textures_.emplace_back(size, texture, animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory> // Para unique_ptr, shared_ptr
|
#include <memory> // Para unique_ptr, shared_ptr
|
||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <utility>
|
#include <utility> // Para move
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Estructura para almacenar la información de una textura de explosión
|
// --- Estructura ExplosionTexture: almacena información de una textura de explosión ---
|
||||||
struct ExplosionTexture {
|
struct ExplosionTexture {
|
||||||
int size; // Tamaño de la explosión
|
int size; // Tamaño de la explosión
|
||||||
std::shared_ptr<Texture> texture; // Textura para la explosión
|
std::shared_ptr<Texture> texture; // Textura para la explosión
|
||||||
@@ -19,35 +19,27 @@ struct ExplosionTexture {
|
|||||||
: size(sz), texture(std::move(tex)), animation(anim) {}
|
: size(sz), texture(std::move(tex)), animation(anim) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clase Explosions
|
// --- Clase Explosions: gestor de explosiones ---
|
||||||
class Explosions {
|
class Explosions {
|
||||||
public:
|
public:
|
||||||
// Constructor y destructor
|
// --- Constructor y destructor ---
|
||||||
Explosions() = default;
|
Explosions() = default; // Constructor por defecto
|
||||||
~Explosions() = default;
|
~Explosions() = default; // Destructor por defecto
|
||||||
|
|
||||||
// Actualiza la lógica de la clase
|
// --- Métodos principales ---
|
||||||
void update();
|
void update(); // Actualiza la lógica de la clase
|
||||||
|
void render(); // Dibuja el objeto en pantalla
|
||||||
|
|
||||||
// Dibuja el objeto en pantalla
|
// --- Configuración ---
|
||||||
void render();
|
void addTexture(int size, const std::shared_ptr<Texture> &texture, const std::vector<std::string> &animation); // Añade texturas al objeto
|
||||||
|
void add(int x, int y, int size); // Añade una explosión
|
||||||
// Añade texturas al objeto
|
|
||||||
void addTexture(int size, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation);
|
|
||||||
|
|
||||||
// Añade una explosión
|
|
||||||
void add(int x, int y, int size);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Vector con las texturas a utilizar
|
// --- Variables de estado ---
|
||||||
std::vector<ExplosionTexture> textures_;
|
std::vector<ExplosionTexture> textures_; // Vector con las texturas a utilizar
|
||||||
|
std::vector<std::unique_ptr<AnimatedSprite>> explosions_; // Lista con todas las explosiones
|
||||||
|
|
||||||
// Lista con todas las explosiones
|
// --- Métodos internos ---
|
||||||
std::vector<std::unique_ptr<AnimatedSprite>> explosions_;
|
void freeExplosions(); // Vacía el vector de elementos finalizados
|
||||||
|
auto getIndexBySize(int size) -> int; // Busca una textura a partir del tamaño
|
||||||
// Vacia el vector de elementos finalizados
|
|
||||||
void freeExplosions();
|
|
||||||
|
|
||||||
// Busca una textura a partir del tamaño
|
|
||||||
auto getIndexBySize(int size) -> int;
|
|
||||||
};
|
};
|
||||||
483
source/fade.cpp
483
source/fade.cpp
@@ -27,32 +27,40 @@ Fade::~Fade() {
|
|||||||
|
|
||||||
// Inicializa las variables
|
// Inicializa las variables
|
||||||
void Fade::init() {
|
void Fade::init() {
|
||||||
type_ = FadeType::CENTER;
|
type_ = Type::CENTER;
|
||||||
mode_ = FadeMode::OUT;
|
mode_ = Mode::OUT;
|
||||||
counter_ = 0;
|
counter_ = 0;
|
||||||
r_ = 0;
|
r_ = 0;
|
||||||
g_ = 0;
|
g_ = 0;
|
||||||
b_ = 0;
|
b_ = 0;
|
||||||
a_ = 0;
|
a_ = 0;
|
||||||
post_duration_ = 0;
|
post_duration_ = 0;
|
||||||
post_counter_ = 0;
|
post_start_time_ = 0;
|
||||||
pre_duration_ = 0;
|
pre_duration_ = 0;
|
||||||
pre_counter_ = 0;
|
pre_start_time_ = 0;
|
||||||
num_squares_width_ = param.fade.num_squares_width;
|
num_squares_width_ = param.fade.num_squares_width;
|
||||||
num_squares_height_ = param.fade.num_squares_height;
|
num_squares_height_ = param.fade.num_squares_height;
|
||||||
fade_random_squares_delay_ = param.fade.random_squares_delay;
|
random_squares_duration_ = param.fade.random_squares_duration_ms; // Usar como duración en ms
|
||||||
fade_random_squares_mult_ = param.fade.random_squares_mult;
|
square_transition_duration_ = random_squares_duration_ / 4; // 25% del tiempo total para la transición individual
|
||||||
|
random_squares_start_time_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resetea algunas variables para volver a hacer el fade sin perder ciertos parametros
|
// Resetea algunas variables para volver a hacer el fade sin perder ciertos parametros
|
||||||
void Fade::reset() {
|
void Fade::reset() {
|
||||||
state_ = FadeState::NOT_ENABLED;
|
state_ = State::NOT_ENABLED;
|
||||||
counter_ = 0;
|
counter_ = 0;
|
||||||
|
post_start_time_ = 0;
|
||||||
|
pre_start_time_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pinta una transición en pantalla
|
// Pinta una transición en pantalla
|
||||||
void Fade::render() {
|
void Fade::render() {
|
||||||
if (state_ != FadeState::NOT_ENABLED) {
|
if (state_ != State::NOT_ENABLED) {
|
||||||
|
// Para fade IN terminado, no renderizar (auto-desactivación visual)
|
||||||
|
if (state_ == State::FINISHED && mode_ == Mode::IN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_RenderTexture(renderer_, backbuffer_, nullptr, nullptr);
|
SDL_RenderTexture(renderer_, backbuffer_, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,13 +68,13 @@ void Fade::render() {
|
|||||||
// Actualiza las variables internas
|
// Actualiza las variables internas
|
||||||
void Fade::update() {
|
void Fade::update() {
|
||||||
switch (state_) {
|
switch (state_) {
|
||||||
case FadeState::PRE:
|
case State::PRE:
|
||||||
updatePreState();
|
updatePreState();
|
||||||
break;
|
break;
|
||||||
case FadeState::FADING:
|
case State::FADING:
|
||||||
updateFadingState();
|
updateFadingState();
|
||||||
break;
|
break;
|
||||||
case FadeState::POST:
|
case State::POST:
|
||||||
updatePostState();
|
updatePostState();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -75,25 +83,36 @@ void Fade::update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Fade::updatePreState() {
|
void Fade::updatePreState() {
|
||||||
if (pre_counter_ == pre_duration_) {
|
// Sistema basado en tiempo únicamente
|
||||||
state_ = FadeState::FADING;
|
Uint32 elapsed_time = SDL_GetTicks() - pre_start_time_;
|
||||||
} else {
|
|
||||||
pre_counter_++;
|
if (elapsed_time >= static_cast<Uint32>(pre_duration_)) {
|
||||||
|
state_ = State::FADING;
|
||||||
|
// CRÍTICO: Reinicializar tiempo de inicio para tipos que usan random_squares_start_time_
|
||||||
|
if (type_ == Type::RANDOM_SQUARE2 || type_ == Type::DIAGONAL) {
|
||||||
|
random_squares_start_time_ = SDL_GetTicks();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fade::updateFadingState() {
|
void Fade::updateFadingState() {
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case FadeType::FULLSCREEN:
|
case Type::FULLSCREEN:
|
||||||
updateFullscreenFade();
|
updateFullscreenFade();
|
||||||
break;
|
break;
|
||||||
case FadeType::CENTER:
|
case Type::CENTER:
|
||||||
updateCenterFade();
|
updateCenterFade();
|
||||||
break;
|
break;
|
||||||
case FadeType::RANDOM_SQUARE:
|
case Type::RANDOM_SQUARE:
|
||||||
updateRandomSquareFade();
|
updateRandomSquareFade();
|
||||||
break;
|
break;
|
||||||
case FadeType::VENETIAN:
|
case Type::RANDOM_SQUARE2:
|
||||||
|
updateRandomSquare2Fade();
|
||||||
|
break;
|
||||||
|
case Type::DIAGONAL:
|
||||||
|
updateDiagonalFade();
|
||||||
|
break;
|
||||||
|
case Type::VENETIAN:
|
||||||
updateVenetianFade();
|
updateVenetianFade();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -102,23 +121,36 @@ void Fade::updateFadingState() {
|
|||||||
counter_++;
|
counter_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Fade::changeToPostState() {
|
||||||
|
state_ = State::POST;
|
||||||
|
post_start_time_ = SDL_GetTicks();
|
||||||
|
}
|
||||||
|
|
||||||
void Fade::updatePostState() {
|
void Fade::updatePostState() {
|
||||||
if (post_counter_ == post_duration_) {
|
// Sistema basado en tiempo únicamente
|
||||||
state_ = FadeState::FINISHED;
|
Uint32 elapsed_time = SDL_GetTicks() - post_start_time_;
|
||||||
} else {
|
|
||||||
post_counter_++;
|
if (elapsed_time >= static_cast<Uint32>(post_duration_)) {
|
||||||
|
state_ = State::FINISHED;
|
||||||
}
|
}
|
||||||
cleanBackbuffer(r_, g_, b_, a_);
|
|
||||||
|
// Mantener el alpha final correcto para cada tipo de fade
|
||||||
|
Uint8 post_alpha = a_;
|
||||||
|
if (type_ == Type::RANDOM_SQUARE2 || type_ == Type::DIAGONAL) {
|
||||||
|
post_alpha = (mode_ == Mode::OUT) ? 255 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanBackbuffer(r_, g_, b_, post_alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fade::updateFullscreenFade() {
|
void Fade::updateFullscreenFade() {
|
||||||
// Modifica la transparencia
|
// Modifica la transparencia
|
||||||
a_ = mode_ == FadeMode::OUT ? std::min(counter_ * 4, 255) : 255 - std::min(counter_ * 4, 255);
|
a_ = mode_ == Mode::OUT ? std::min(counter_ * 4, 255) : 255 - std::min(counter_ * 4, 255);
|
||||||
SDL_SetTextureAlphaMod(backbuffer_, a_);
|
SDL_SetTextureAlphaMod(backbuffer_, a_);
|
||||||
|
|
||||||
// Comprueba si ha terminado
|
// Comprueba si ha terminado
|
||||||
if (counter_ >= 255 / 4) {
|
if (counter_ >= 255 / 4) {
|
||||||
state_ = FadeState::POST;
|
changeToPostState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,8 +159,8 @@ void Fade::updateCenterFade() {
|
|||||||
|
|
||||||
// Comprueba si ha terminado
|
// Comprueba si ha terminado
|
||||||
if ((counter_ * 4) > param.game.height) {
|
if ((counter_ * 4) > param.game.height) {
|
||||||
state_ = FadeState::POST;
|
|
||||||
a_ = 255;
|
a_ = 255;
|
||||||
|
changeToPostState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,20 +183,243 @@ void Fade::drawCenterFadeRectangles() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Fade::updateRandomSquareFade() {
|
void Fade::updateRandomSquareFade() {
|
||||||
if (counter_ % fade_random_squares_delay_ == 0) {
|
Uint32 elapsed_time = SDL_GetTicks() - random_squares_start_time_;
|
||||||
drawRandomSquares();
|
float progress = static_cast<float>(elapsed_time) / random_squares_duration_;
|
||||||
}
|
|
||||||
|
|
||||||
value_ = calculateValue(0, (num_squares_width_ * num_squares_height_), (counter_ * fade_random_squares_mult_ / fade_random_squares_delay_));
|
// Calcula cuántos cuadrados deberían estar activos
|
||||||
|
int total_squares = num_squares_width_ * num_squares_height_;
|
||||||
|
int active_squares = static_cast<int>(progress * total_squares);
|
||||||
|
active_squares = std::min(active_squares, total_squares);
|
||||||
|
|
||||||
|
// Dibuja los cuadrados activos
|
||||||
|
drawRandomSquares(active_squares);
|
||||||
|
|
||||||
|
value_ = calculateValue(0, total_squares, active_squares);
|
||||||
|
|
||||||
// Comprueba si ha terminado
|
// Comprueba si ha terminado
|
||||||
if (counter_ * fade_random_squares_mult_ / fade_random_squares_delay_ >=
|
if (elapsed_time >= static_cast<Uint32>(random_squares_duration_)) {
|
||||||
num_squares_width_ * num_squares_height_) {
|
changeToPostState();
|
||||||
state_ = FadeState::POST;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fade::drawRandomSquares() {
|
void Fade::updateRandomSquare2Fade() {
|
||||||
|
Uint32 elapsed_time = SDL_GetTicks() - random_squares_start_time_;
|
||||||
|
|
||||||
|
int total_squares = num_squares_width_ * num_squares_height_;
|
||||||
|
|
||||||
|
// Calcula el tiempo de activación: total - tiempo que necesitan los últimos cuadrados
|
||||||
|
int activation_time = random_squares_duration_ - square_transition_duration_;
|
||||||
|
activation_time = std::max(activation_time, square_transition_duration_); // Mínimo igual a la duración de transición
|
||||||
|
|
||||||
|
// Lógica diferente según el modo
|
||||||
|
int squares_to_activate = 0;
|
||||||
|
|
||||||
|
if (mode_ == Mode::OUT) {
|
||||||
|
// OUT: Activa cuadrados gradualmente
|
||||||
|
if (elapsed_time < static_cast<Uint32>(activation_time)) {
|
||||||
|
float activation_progress = static_cast<float>(elapsed_time) / activation_time;
|
||||||
|
squares_to_activate = static_cast<int>(activation_progress * total_squares);
|
||||||
|
} else {
|
||||||
|
squares_to_activate = total_squares; // Activar todos
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activa nuevos cuadrados y guarda su tiempo de activación
|
||||||
|
for (int i = 0; i < squares_to_activate && i < total_squares; ++i) {
|
||||||
|
if (square_age_[i] == -1) {
|
||||||
|
square_age_[i] = elapsed_time; // Guarda el tiempo de activación
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// IN: Todos los cuadrados empiezan activos desde el inicio
|
||||||
|
squares_to_activate = total_squares;
|
||||||
|
|
||||||
|
// Activa cuadrados gradualmente con tiempo de inicio escalonado
|
||||||
|
float activation_progress = static_cast<float>(elapsed_time) / activation_time;
|
||||||
|
int squares_starting_transition = static_cast<int>(activation_progress * total_squares);
|
||||||
|
|
||||||
|
// Asegurar que al menos 1 cuadrado se active desde el primer frame
|
||||||
|
squares_starting_transition = std::max(squares_starting_transition, 1);
|
||||||
|
squares_starting_transition = std::min(squares_starting_transition, total_squares);
|
||||||
|
|
||||||
|
for (int i = 0; i < squares_starting_transition; ++i) {
|
||||||
|
if (square_age_[i] == -1) {
|
||||||
|
square_age_[i] = elapsed_time; // Empieza la transición a transparente
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawRandomSquares2();
|
||||||
|
|
||||||
|
value_ = calculateValue(0, total_squares, squares_to_activate);
|
||||||
|
|
||||||
|
// Comprueba si ha terminado - todos los cuadrados han completado su transición
|
||||||
|
bool all_completed = (squares_to_activate >= total_squares);
|
||||||
|
if (all_completed) {
|
||||||
|
// Verificar que todos han completado su transición individual
|
||||||
|
for (int i = 0; i < total_squares; ++i) {
|
||||||
|
if (square_age_[i] >= 0) { // Cuadrado activado
|
||||||
|
Uint32 square_elapsed = elapsed_time - square_age_[i];
|
||||||
|
if (square_elapsed < static_cast<Uint32>(square_transition_duration_)) {
|
||||||
|
all_completed = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (all_completed) {
|
||||||
|
// Pintar textura final: OUT opaca, IN transparente
|
||||||
|
Uint8 final_alpha = (mode_ == Mode::OUT) ? 255 : 0;
|
||||||
|
cleanBackbuffer(r_, g_, b_, final_alpha);
|
||||||
|
changeToPostState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fade::updateDiagonalFade() {
|
||||||
|
Uint32 elapsed_time = SDL_GetTicks() - random_squares_start_time_;
|
||||||
|
|
||||||
|
int total_squares = num_squares_width_ * num_squares_height_;
|
||||||
|
|
||||||
|
// Calcula el tiempo de activación: total - tiempo que necesitan los últimos cuadrados
|
||||||
|
int activation_time = random_squares_duration_ - square_transition_duration_;
|
||||||
|
activation_time = std::max(activation_time, square_transition_duration_);
|
||||||
|
|
||||||
|
// Calcula cuántas diagonales deberían estar activas
|
||||||
|
int max_diagonal = num_squares_width_ + num_squares_height_ - 1; // Número total de diagonales
|
||||||
|
int active_diagonals = 0;
|
||||||
|
|
||||||
|
if (mode_ == Mode::OUT) {
|
||||||
|
// OUT: Activa diagonales gradualmente desde esquina superior izquierda
|
||||||
|
if (elapsed_time < static_cast<Uint32>(activation_time)) {
|
||||||
|
float activation_progress = static_cast<float>(elapsed_time) / activation_time;
|
||||||
|
active_diagonals = static_cast<int>(activation_progress * max_diagonal);
|
||||||
|
} else {
|
||||||
|
active_diagonals = max_diagonal; // Activar todas
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activa cuadrados por diagonales
|
||||||
|
for (int diagonal = 0; diagonal < active_diagonals; ++diagonal) {
|
||||||
|
activateDiagonal(diagonal, elapsed_time);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// IN: Todas las diagonales empiezan activas, van desapareciendo
|
||||||
|
active_diagonals = max_diagonal;
|
||||||
|
|
||||||
|
// Activa diagonales gradualmente para transición
|
||||||
|
if (elapsed_time < static_cast<Uint32>(activation_time)) {
|
||||||
|
float activation_progress = static_cast<float>(elapsed_time) / activation_time;
|
||||||
|
int diagonals_starting_transition = static_cast<int>(activation_progress * max_diagonal);
|
||||||
|
|
||||||
|
for (int diagonal = 0; diagonal < diagonals_starting_transition; ++diagonal) {
|
||||||
|
activateDiagonal(diagonal, elapsed_time);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Activar transición en todas las diagonales restantes
|
||||||
|
for (int diagonal = 0; diagonal < max_diagonal; ++diagonal) {
|
||||||
|
activateDiagonal(diagonal, elapsed_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawDiagonal();
|
||||||
|
|
||||||
|
value_ = calculateValue(0, total_squares, active_diagonals * (total_squares / max_diagonal));
|
||||||
|
|
||||||
|
// Comprueba si ha terminado - todas las diagonales activadas y último cuadrado completó transición
|
||||||
|
bool all_completed = (active_diagonals >= max_diagonal);
|
||||||
|
if (all_completed) {
|
||||||
|
// Verificar que todos han completado su transición individual
|
||||||
|
for (int i = 0; i < total_squares; ++i) {
|
||||||
|
if (square_age_[i] >= 0) { // Cuadrado activado
|
||||||
|
Uint32 square_elapsed = elapsed_time - square_age_[i];
|
||||||
|
if (square_elapsed < static_cast<Uint32>(square_transition_duration_)) {
|
||||||
|
all_completed = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (all_completed) {
|
||||||
|
// Pintar textura final: OUT opaca, IN transparente
|
||||||
|
Uint8 final_alpha = (mode_ == Mode::OUT) ? 255 : 0;
|
||||||
|
cleanBackbuffer(r_, g_, b_, final_alpha);
|
||||||
|
changeToPostState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fade::activateDiagonal(int diagonal_index, Uint32 current_time) {
|
||||||
|
// Para cada diagonal, activamos los cuadrados que pertenecen a esa diagonal
|
||||||
|
// Diagonal 0: (0,0)
|
||||||
|
// Diagonal 1: (1,0), (0,1)
|
||||||
|
// Diagonal 2: (2,0), (1,1), (0,2)
|
||||||
|
// etc.
|
||||||
|
|
||||||
|
for (int x = 0; x < num_squares_width_; ++x) {
|
||||||
|
int y = diagonal_index - x;
|
||||||
|
|
||||||
|
// Verificar que y está dentro de los límites
|
||||||
|
if (y >= 0 && y < num_squares_height_) {
|
||||||
|
// Convertir coordenadas (x,y) a índice en el vector
|
||||||
|
int index = y * num_squares_width_ + x;
|
||||||
|
|
||||||
|
if (index >= 0 && index < static_cast<int>(square_age_.size())) {
|
||||||
|
if (square_age_[index] == -1) {
|
||||||
|
square_age_[index] = current_time; // Guarda el tiempo de activación
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fade::drawDiagonal() {
|
||||||
|
auto *temp = SDL_GetRenderTarget(renderer_);
|
||||||
|
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||||
|
|
||||||
|
// CRÍTICO: Limpiar la textura antes de dibujar
|
||||||
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
||||||
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
|
SDL_BlendMode blend_mode;
|
||||||
|
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
|
||||||
|
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); // Usar BLEND para alpha
|
||||||
|
|
||||||
|
Uint32 current_time = SDL_GetTicks() - random_squares_start_time_;
|
||||||
|
|
||||||
|
// Lógica unificada: sobre textura transparente, pintar cuadrados según su estado
|
||||||
|
for (size_t i = 0; i < square_.size(); ++i) {
|
||||||
|
Uint8 current_alpha = 0;
|
||||||
|
|
||||||
|
if (square_age_[i] == -1) {
|
||||||
|
// Cuadrado no activado
|
||||||
|
if (mode_ == Mode::OUT) {
|
||||||
|
current_alpha = 0; // OUT: transparente si no activado
|
||||||
|
} else {
|
||||||
|
current_alpha = a_; // IN: opaco si no activado
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Cuadrado activado - calculamos progreso
|
||||||
|
Uint32 square_elapsed = current_time - square_age_[i];
|
||||||
|
float progress = std::min(static_cast<float>(square_elapsed) / square_transition_duration_, 1.0f);
|
||||||
|
|
||||||
|
if (mode_ == Mode::OUT) {
|
||||||
|
current_alpha = static_cast<Uint8>(progress * a_); // 0 → 255
|
||||||
|
} else {
|
||||||
|
current_alpha = static_cast<Uint8>((1.0f - progress) * a_); // 255 → 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_alpha > 0) {
|
||||||
|
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, current_alpha);
|
||||||
|
SDL_RenderFillRect(renderer_, &square_[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
|
||||||
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fade::drawRandomSquares(int active_count) {
|
||||||
auto *temp = SDL_GetRenderTarget(renderer_);
|
auto *temp = SDL_GetRenderTarget(renderer_);
|
||||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||||
|
|
||||||
@@ -173,13 +428,56 @@ void Fade::drawRandomSquares() {
|
|||||||
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
|
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
|
||||||
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
||||||
|
|
||||||
const int INDEX = std::min(counter_ / fade_random_squares_delay_,
|
// Dibuja solo los cuadrados activos
|
||||||
(num_squares_width_ * num_squares_height_) - 1);
|
for (int i = 0; i < active_count && i < static_cast<int>(square_.size()); ++i) {
|
||||||
|
SDL_RenderFillRect(renderer_, &square_[i]);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < fade_random_squares_mult_; ++i) {
|
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
|
||||||
const int INDEX2 = std::min(INDEX * fade_random_squares_mult_ + i,
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
static_cast<int>(square_.size()) - 1);
|
}
|
||||||
SDL_RenderFillRect(renderer_, &square_[INDEX2]);
|
|
||||||
|
void Fade::drawRandomSquares2() {
|
||||||
|
auto *temp = SDL_GetRenderTarget(renderer_);
|
||||||
|
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||||
|
|
||||||
|
// CRÍTICO: Limpiar la textura antes de dibujar
|
||||||
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
||||||
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
|
SDL_BlendMode blend_mode;
|
||||||
|
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
|
||||||
|
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); // Usar BLEND para alpha
|
||||||
|
|
||||||
|
Uint32 current_time = SDL_GetTicks() - random_squares_start_time_;
|
||||||
|
|
||||||
|
// Lógica unificada: sobre textura transparente, pintar cuadrados según su estado
|
||||||
|
for (size_t i = 0; i < square_.size(); ++i) {
|
||||||
|
Uint8 current_alpha = 0;
|
||||||
|
|
||||||
|
if (square_age_[i] == -1) {
|
||||||
|
// Cuadrado no activado
|
||||||
|
if (mode_ == Mode::OUT) {
|
||||||
|
current_alpha = 0; // OUT: transparente si no activado
|
||||||
|
} else {
|
||||||
|
current_alpha = a_; // IN: opaco si no activado
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Cuadrado activado - calculamos progreso
|
||||||
|
Uint32 square_elapsed = current_time - square_age_[i];
|
||||||
|
float progress = std::min(static_cast<float>(square_elapsed) / square_transition_duration_, 1.0f);
|
||||||
|
|
||||||
|
if (mode_ == Mode::OUT) {
|
||||||
|
current_alpha = static_cast<Uint8>(progress * a_); // 0 → 255
|
||||||
|
} else {
|
||||||
|
current_alpha = static_cast<Uint8>((1.0f - progress) * a_); // 255 → 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_alpha > 0) {
|
||||||
|
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, current_alpha);
|
||||||
|
SDL_RenderFillRect(renderer_, &square_[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
|
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
|
||||||
@@ -192,7 +490,7 @@ void Fade::updateVenetianFade() {
|
|||||||
updateVenetianRectangles();
|
updateVenetianRectangles();
|
||||||
calculateVenetianProgress();
|
calculateVenetianProgress();
|
||||||
} else {
|
} else {
|
||||||
state_ = FadeState::POST;
|
changeToPostState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,31 +531,30 @@ void Fade::calculateVenetianProgress() {
|
|||||||
// Activa el fade
|
// Activa el fade
|
||||||
void Fade::activate() {
|
void Fade::activate() {
|
||||||
// Si ya está habilitado, no hay que volverlo a activar
|
// Si ya está habilitado, no hay que volverlo a activar
|
||||||
if (state_ != FadeState::NOT_ENABLED) {
|
if (state_ != State::NOT_ENABLED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state_ = FadeState::PRE;
|
state_ = State::PRE;
|
||||||
counter_ = 0;
|
counter_ = 0;
|
||||||
post_counter_ = 0;
|
pre_start_time_ = SDL_GetTicks();
|
||||||
pre_counter_ = 0;
|
|
||||||
|
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case FadeType::FULLSCREEN: {
|
case Type::FULLSCREEN: {
|
||||||
// Pinta el backbuffer_ de color sólido
|
// Pinta el backbuffer_ de color sólido
|
||||||
cleanBackbuffer(r_, g_, b_, 255);
|
cleanBackbuffer(r_, g_, b_, 255);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FadeType::CENTER: {
|
case Type::CENTER: {
|
||||||
rect1_ = {0, 0, param.game.width, 0};
|
rect1_ = {.x = 0, .y = 0, .w = param.game.width, .h = 0};
|
||||||
rect2_ = {0, 0, param.game.width, 0};
|
rect2_ = {.x = 0, .y = 0, .w = param.game.width, .h = 0};
|
||||||
a_ = 64;
|
a_ = 64;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FadeType::RANDOM_SQUARE: {
|
case Type::RANDOM_SQUARE: {
|
||||||
rect1_ = {0, 0, static_cast<float>(param.game.width / num_squares_width_), static_cast<float>(param.game.height / num_squares_height_)};
|
rect1_ = {.x = 0, .y = 0, .w = static_cast<float>(param.game.width / num_squares_width_), .h = static_cast<float>(param.game.height / num_squares_height_)};
|
||||||
square_.clear();
|
square_.clear();
|
||||||
|
|
||||||
// Añade los cuadrados al vector
|
// Añade los cuadrados al vector
|
||||||
@@ -278,26 +575,96 @@ void Fade::activate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Limpia la textura
|
// Limpia la textura
|
||||||
a_ = mode_ == FadeMode::OUT ? 0 : 255;
|
a_ = mode_ == Mode::OUT ? 0 : 255;
|
||||||
cleanBackbuffer(r_, g_, b_, a_);
|
cleanBackbuffer(r_, g_, b_, a_);
|
||||||
|
|
||||||
// Deja el color listo para usar
|
// Deja el color listo para usar
|
||||||
a_ = mode_ == FadeMode::OUT ? 255 : 0;
|
a_ = mode_ == Mode::OUT ? 255 : 0;
|
||||||
|
|
||||||
|
// Inicializa el tiempo de inicio
|
||||||
|
random_squares_start_time_ = SDL_GetTicks();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FadeType::VENETIAN: {
|
case Type::RANDOM_SQUARE2: {
|
||||||
|
rect1_ = {.x = 0, .y = 0, .w = static_cast<float>(param.game.width / num_squares_width_), .h = static_cast<float>(param.game.height / num_squares_height_)};
|
||||||
|
square_.clear();
|
||||||
|
square_age_.clear();
|
||||||
|
|
||||||
|
// Añade los cuadrados al vector
|
||||||
|
for (int i = 0; i < num_squares_width_ * num_squares_height_; ++i) {
|
||||||
|
rect1_.x = (i % num_squares_width_) * rect1_.w;
|
||||||
|
rect1_.y = (i / num_squares_width_) * rect1_.h;
|
||||||
|
square_.push_back(rect1_);
|
||||||
|
square_age_.push_back(-1); // -1 indica cuadrado no activado aún
|
||||||
|
}
|
||||||
|
|
||||||
|
// Desordena el vector de cuadrados y edades
|
||||||
|
auto num = num_squares_width_ * num_squares_height_;
|
||||||
|
while (num > 1) {
|
||||||
|
auto num_arreu = rand() % num;
|
||||||
|
SDL_FRect temp_rect = square_[num_arreu];
|
||||||
|
int temp_age = square_age_[num_arreu];
|
||||||
|
square_[num_arreu] = square_[num - 1];
|
||||||
|
square_age_[num_arreu] = square_age_[num - 1];
|
||||||
|
square_[num - 1] = temp_rect;
|
||||||
|
square_age_[num - 1] = temp_age;
|
||||||
|
num--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Textura inicial: OUT transparente, IN opaca
|
||||||
|
Uint8 initial_alpha = (mode_ == Mode::OUT) ? 0 : 255;
|
||||||
|
cleanBackbuffer(r_, g_, b_, initial_alpha);
|
||||||
|
|
||||||
|
// Deja el color listo para usar (alpha target para los cuadrados)
|
||||||
|
a_ = 255; // Siempre usar 255 como alpha target
|
||||||
|
|
||||||
|
// Inicializa el tiempo de inicio y recalcula la duración de transición
|
||||||
|
random_squares_start_time_ = SDL_GetTicks();
|
||||||
|
square_transition_duration_ = std::max(random_squares_duration_ / 4, 100); // Mínimo 100ms
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::DIAGONAL: {
|
||||||
|
rect1_ = {.x = 0, .y = 0, .w = static_cast<float>(param.game.width / num_squares_width_), .h = static_cast<float>(param.game.height / num_squares_height_)};
|
||||||
|
square_.clear();
|
||||||
|
square_age_.clear();
|
||||||
|
|
||||||
|
// Añade los cuadrados al vector en orden (sin desordenar)
|
||||||
|
for (int i = 0; i < num_squares_width_ * num_squares_height_; ++i) {
|
||||||
|
rect1_.x = (i % num_squares_width_) * rect1_.w;
|
||||||
|
rect1_.y = (i / num_squares_width_) * rect1_.h;
|
||||||
|
square_.push_back(rect1_);
|
||||||
|
square_age_.push_back(-1); // -1 indica cuadrado no activado aún
|
||||||
|
}
|
||||||
|
|
||||||
|
// Textura inicial: OUT transparente, IN opaca
|
||||||
|
Uint8 initial_alpha = (mode_ == Mode::OUT) ? 0 : 255;
|
||||||
|
cleanBackbuffer(r_, g_, b_, initial_alpha);
|
||||||
|
|
||||||
|
// Deja el color listo para usar (alpha target para los cuadrados)
|
||||||
|
a_ = 255; // Siempre usar 255 como alpha target
|
||||||
|
|
||||||
|
// Inicializa el tiempo de inicio y recalcula la duración de transición
|
||||||
|
random_squares_start_time_ = SDL_GetTicks();
|
||||||
|
square_transition_duration_ = std::max(random_squares_duration_ / 4, 100); // Mínimo 100ms
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::VENETIAN: {
|
||||||
// Limpia la textura
|
// Limpia la textura
|
||||||
a_ = mode_ == FadeMode::OUT ? 0 : 255;
|
a_ = mode_ == Mode::OUT ? 0 : 255;
|
||||||
cleanBackbuffer(r_, g_, b_, a_);
|
cleanBackbuffer(r_, g_, b_, a_);
|
||||||
|
|
||||||
// Deja el color listo para usar
|
// Deja el color listo para usar
|
||||||
a_ = mode_ == FadeMode::OUT ? 255 : 0;
|
a_ = mode_ == Mode::OUT ? 255 : 0;
|
||||||
|
|
||||||
// Añade los cuadrados al vector
|
// Añade los cuadrados al vector
|
||||||
square_.clear();
|
square_.clear();
|
||||||
rect1_ = {0, 0, param.game.width, 0};
|
rect1_ = {.x = 0, .y = 0, .w = param.game.width, .h = 0};
|
||||||
const int MAX = param.game.height / param.fade.venetian_size;
|
const int MAX = param.game.height / param.fade.venetian_size;
|
||||||
|
|
||||||
for (int i = 0; i < MAX; ++i) {
|
for (int i = 0; i < MAX; ++i) {
|
||||||
|
|||||||
111
source/fade.h
111
source/fade.h
@@ -6,31 +6,32 @@
|
|||||||
|
|
||||||
struct Color;
|
struct Color;
|
||||||
|
|
||||||
// Tipos de fundido
|
// --- Clase Fade: gestor de transiciones de fundido ---
|
||||||
enum class FadeType : Uint8 {
|
|
||||||
FULLSCREEN = 0,
|
|
||||||
CENTER = 1,
|
|
||||||
RANDOM_SQUARE = 2,
|
|
||||||
VENETIAN = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Modos de fundido
|
|
||||||
enum class FadeMode : Uint8 {
|
|
||||||
IN = 0,
|
|
||||||
OUT = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estados del objeto
|
|
||||||
enum class FadeState : Uint8 {
|
|
||||||
NOT_ENABLED = 0,
|
|
||||||
PRE = 1,
|
|
||||||
FADING = 2,
|
|
||||||
POST = 3,
|
|
||||||
FINISHED = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
class Fade {
|
class Fade {
|
||||||
public:
|
public:
|
||||||
|
// --- Enums ---
|
||||||
|
enum class Type : Uint8 {
|
||||||
|
FULLSCREEN = 0, // Fundido de pantalla completa
|
||||||
|
CENTER = 1, // Fundido desde el centro
|
||||||
|
RANDOM_SQUARE = 2, // Fundido con cuadrados aleatorios
|
||||||
|
RANDOM_SQUARE2 = 3, // Fundido con cuadrados aleatorios (variante 2)
|
||||||
|
DIAGONAL = 4, // Fundido diagonal desde esquina superior izquierda
|
||||||
|
VENETIAN = 5, // Fundido tipo persiana veneciana
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Mode : Uint8 {
|
||||||
|
IN = 0, // Fundido de entrada
|
||||||
|
OUT = 1, // Fundido de salida
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class State : Uint8 {
|
||||||
|
NOT_ENABLED = 0, // No activado
|
||||||
|
PRE = 1, // Estado previo
|
||||||
|
FADING = 2, // Fundiendo
|
||||||
|
POST = 3, // Estado posterior
|
||||||
|
FINISHED = 4, // Finalizado
|
||||||
|
};
|
||||||
|
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
Fade();
|
Fade();
|
||||||
~Fade();
|
~Fade();
|
||||||
@@ -42,17 +43,17 @@ class Fade {
|
|||||||
void activate(); // Activa el fade
|
void activate(); // Activa el fade
|
||||||
|
|
||||||
// --- Configuración ---
|
// --- Configuración ---
|
||||||
void setColor(Uint8 r, Uint8 g, Uint8 b);
|
void setColor(Uint8 r, Uint8 g, Uint8 b); // Establece el color RGB del fade
|
||||||
void setColor(Color color);
|
void setColor(Color color); // Establece el color del fade
|
||||||
void setType(FadeType type) { type_ = type; }
|
void setType(Type type) { type_ = type; } // Establece el tipo de fade
|
||||||
void setMode(FadeMode mode) { mode_ = mode; }
|
void setMode(Mode mode) { mode_ = mode; } // Establece el modo de fade
|
||||||
void setPostDuration(int value) { post_duration_ = value; }
|
void setPostDuration(int value) { post_duration_ = value; } // Duración posterior al fade en milisegundos
|
||||||
void setPreDuration(int value) { pre_duration_ = value; }
|
void setPreDuration(int value) { pre_duration_ = value; } // Duración previa al fade en milisegundos
|
||||||
|
|
||||||
// --- Getters ---
|
// --- Getters ---
|
||||||
[[nodiscard]] auto getValue() const -> int { return value_; }
|
[[nodiscard]] auto getValue() const -> int { return value_; }
|
||||||
[[nodiscard]] auto isEnabled() const -> bool { return state_ != FadeState::NOT_ENABLED; }
|
[[nodiscard]] auto isEnabled() const -> bool { return state_ != State::NOT_ENABLED; }
|
||||||
[[nodiscard]] auto hasEnded() const -> bool { return state_ == FadeState::FINISHED; }
|
[[nodiscard]] auto hasEnded() const -> bool { return state_ == State::FINISHED; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
@@ -60,28 +61,24 @@ class Fade {
|
|||||||
SDL_Texture *backbuffer_; // Backbuffer para efectos
|
SDL_Texture *backbuffer_; // Backbuffer para efectos
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
FadeType type_; // Tipo de fade
|
std::vector<SDL_FRect> square_; // Vector de cuadrados
|
||||||
FadeMode mode_; // Modo de fade
|
std::vector<int> square_age_; // Edad de cada cuadrado (para RANDOM_SQUARE2)
|
||||||
FadeState state_ = FadeState::NOT_ENABLED; // Estado actual
|
SDL_FRect rect1_, rect2_; // Rectángulos para efectos
|
||||||
Uint16 counter_; // Contador interno
|
Type type_; // Tipo de fade
|
||||||
|
Mode mode_; // Modo de fade
|
||||||
// --- Parámetros de color y geometría ---
|
State state_ = State::NOT_ENABLED; // Estado actual
|
||||||
Uint8 r_, g_, b_, a_; // Color del fade
|
Uint16 counter_; // Contador interno
|
||||||
SDL_FRect rect1_, rect2_; // Rectángulos para efectos
|
Uint8 r_, g_, b_, a_; // Color del fade (RGBA)
|
||||||
|
int num_squares_width_; // Cuadrados en horizontal
|
||||||
// --- Parámetros para RANDOM_SQUARE ---
|
int num_squares_height_; // Cuadrados en vertical
|
||||||
int num_squares_width_; // Cuadrados en horizontal
|
Uint32 random_squares_start_time_; // Tiempo de inicio del fade de cuadrados
|
||||||
int num_squares_height_; // Cuadrados en vertical
|
int random_squares_duration_; // Duración total en milisegundos
|
||||||
std::vector<SDL_FRect> square_; // Vector de cuadrados
|
int square_transition_duration_; // Duración de transición de cada cuadrado en ms
|
||||||
int fade_random_squares_delay_; // Delay entre cuadrados
|
int post_duration_ = 0; // Duración posterior en milisegundos
|
||||||
int fade_random_squares_mult_; // Cuadrados por paso
|
Uint32 post_start_time_ = 0; // Tiempo de inicio del estado POST
|
||||||
|
int pre_duration_ = 0; // Duración previa en milisegundos
|
||||||
// --- Temporizadores ---
|
Uint32 pre_start_time_ = 0; // Tiempo de inicio del estado PRE
|
||||||
int post_duration_ = 0, post_counter_ = 0;
|
int value_ = 0; // Estado del fade (0-100)
|
||||||
int pre_duration_ = 0, pre_counter_ = 0;
|
|
||||||
|
|
||||||
// --- Valor de progreso ---
|
|
||||||
int value_ = 0; // Estado del fade (0-100)
|
|
||||||
|
|
||||||
// --- Inicialización y limpieza ---
|
// --- Inicialización y limpieza ---
|
||||||
void init(); // Inicializa variables
|
void init(); // Inicializa variables
|
||||||
@@ -94,17 +91,23 @@ class Fade {
|
|||||||
void updatePreState(); // Actualiza el estado previo al fade
|
void updatePreState(); // Actualiza el estado previo al fade
|
||||||
void updateFadingState(); // Actualiza el estado durante el fade
|
void updateFadingState(); // Actualiza el estado durante el fade
|
||||||
void updatePostState(); // Actualiza el estado posterior al fade
|
void updatePostState(); // Actualiza el estado posterior al fade
|
||||||
|
void changeToPostState(); // Cambia al estado POST e inicializa el tiempo
|
||||||
|
|
||||||
// --- Efectos de fundido (fade) ---
|
// --- Efectos de fundido (fade) ---
|
||||||
void updateFullscreenFade(); // Actualiza el fundido de pantalla completa
|
void updateFullscreenFade(); // Actualiza el fundido de pantalla completa
|
||||||
void updateCenterFade(); // Actualiza el fundido desde el centro
|
void updateCenterFade(); // Actualiza el fundido desde el centro
|
||||||
void updateRandomSquareFade(); // Actualiza el fundido con cuadrados aleatorios
|
void updateRandomSquareFade(); // Actualiza el fundido con cuadrados aleatorios
|
||||||
|
void updateRandomSquare2Fade(); // Actualiza el fundido con cuadrados aleatorios (variante 2)
|
||||||
|
void updateDiagonalFade(); // Actualiza el fundido diagonal
|
||||||
void updateVenetianFade(); // Actualiza el fundido tipo persiana veneciana
|
void updateVenetianFade(); // Actualiza el fundido tipo persiana veneciana
|
||||||
void updateVenetianRectangles(); // Actualiza los rectángulos del efecto veneciano
|
void updateVenetianRectangles(); // Actualiza los rectángulos del efecto veneciano
|
||||||
void calculateVenetianProgress(); // Calcula el progreso del efecto veneciano
|
void calculateVenetianProgress(); // Calcula el progreso del efecto veneciano
|
||||||
|
|
||||||
// --- Dibujo de efectos visuales ---
|
// --- Dibujo de efectos visuales ---
|
||||||
void drawCenterFadeRectangles(); // Dibuja los rectángulos del fundido central
|
void drawCenterFadeRectangles(); // Dibuja los rectángulos del fundido central
|
||||||
void drawRandomSquares(); // Dibuja los cuadrados aleatorios del fundido
|
void drawRandomSquares(int active_count = -1); // Dibuja los cuadrados aleatorios del fundido
|
||||||
|
void drawRandomSquares2(); // Dibuja los cuadrados con transición de color (RANDOM_SQUARE2)
|
||||||
|
void drawDiagonal(); // Dibuja los cuadrados con patrón diagonal
|
||||||
|
void activateDiagonal(int diagonal_index, Uint32 current_time); // Activa una diagonal específica
|
||||||
void drawVenetianBlinds(); // Dibuja las persianas venecianas del fundido
|
void drawVenetianBlinds(); // Dibuja las persianas venecianas del fundido
|
||||||
};
|
};
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
constexpr int ZOOM_FACTOR = 5;
|
constexpr int ZOOM_FACTOR = 5;
|
||||||
constexpr int FLASH_DELAY = 3;
|
constexpr int FLASH_DELAY = 3;
|
||||||
constexpr int FLASH_LENGHT = FLASH_DELAY + 3;
|
constexpr int FLASH_LENGTH = FLASH_DELAY + 3;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
GameLogo::GameLogo(int x, int y)
|
GameLogo::GameLogo(int x, int y)
|
||||||
@@ -34,7 +34,7 @@ GameLogo::GameLogo(int x, int y)
|
|||||||
|
|
||||||
// Inicializa las variables
|
// Inicializa las variables
|
||||||
void GameLogo::init() {
|
void GameLogo::init() {
|
||||||
const auto XP = x_ - coffee_texture_->getWidth() / 2;
|
const auto XP = x_ - (coffee_texture_->getWidth() / 2);
|
||||||
const auto DESP = getInitialVerticalDesp();
|
const auto DESP = getInitialVerticalDesp();
|
||||||
|
|
||||||
// Configura texturas
|
// Configura texturas
|
||||||
@@ -236,7 +236,7 @@ void GameLogo::finishArcadeEditionMoving() {
|
|||||||
|
|
||||||
void GameLogo::playTitleEffects() {
|
void GameLogo::playTitleEffects() {
|
||||||
Audio::get()->playSound("title.wav");
|
Audio::get()->playSound("title.wav");
|
||||||
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
|
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGTH, FLASH_DELAY);
|
||||||
Screen::get()->shake();
|
Screen::get()->shake();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Clase GameLogo
|
// --- Clase GameLogo: gestor del logo del juego ---
|
||||||
class GameLogo {
|
class GameLogo {
|
||||||
public:
|
public:
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
@@ -24,30 +24,31 @@ class GameLogo {
|
|||||||
[[nodiscard]] auto hasFinished() const -> bool; // Indica si ha terminado la animación
|
[[nodiscard]] auto hasFinished() const -> bool; // Indica si ha terminado la animación
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Tipos internos ---
|
// --- Enums ---
|
||||||
enum class Status {
|
enum class Status {
|
||||||
DISABLED,
|
DISABLED, // Deshabilitado
|
||||||
MOVING,
|
MOVING, // En movimiento
|
||||||
SHAKING,
|
SHAKING, // Temblando
|
||||||
FINISHED,
|
FINISHED, // Terminado
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- Estructuras privadas ---
|
||||||
struct Shake {
|
struct Shake {
|
||||||
int desp = 1; // Pixels de desplazamiento para agitar la pantalla en el eje x
|
int desp = 1; // Pixels de desplazamiento para agitar la pantalla en el eje x
|
||||||
int delay = 2; // Retraso entre cada desplazamiento de la pantalla al agitarse
|
int delay = 2; // Retraso entre cada desplazamiento de la pantalla al agitarse
|
||||||
int lenght = 8; // Cantidad de desplazamientos a realizar
|
int length = 8; // Cantidad de desplazamientos a realizar
|
||||||
int remaining = lenght; // Cantidad de desplazamientos pendientes a realizar
|
int remaining = length; // Cantidad de desplazamientos pendientes a realizar
|
||||||
int counter = delay; // Contador para el retraso
|
int counter = delay; // Contador para el retraso
|
||||||
int origin = 0; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
|
int origin = 0; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
|
||||||
|
|
||||||
Shake() = default;
|
Shake() = default;
|
||||||
Shake(int d, int de, int l, int o)
|
Shake(int d, int de, int l, int o)
|
||||||
: desp(d), delay(de), lenght(l), remaining(l), counter(de), origin(o) {}
|
: desp(d), delay(de), length(l), remaining(l), counter(de), origin(o) {}
|
||||||
|
|
||||||
void init(int d, int de, int l, int o) {
|
void init(int d, int de, int l, int o) {
|
||||||
desp = d;
|
desp = d;
|
||||||
delay = de;
|
delay = de;
|
||||||
lenght = l;
|
length = l;
|
||||||
remaining = l;
|
remaining = l;
|
||||||
counter = de;
|
counter = de;
|
||||||
origin = o;
|
origin = o;
|
||||||
@@ -67,14 +68,13 @@ class GameLogo {
|
|||||||
std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite de "Arcade Edition"
|
std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite de "Arcade Edition"
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
float x_; // Posición X del logo
|
Shake shake_; // Efecto de agitación
|
||||||
float y_; // Posición Y del logo
|
|
||||||
float zoom_ = 1.0F; // Zoom aplicado al texto "ARCADE EDITION"
|
|
||||||
int post_finished_counter_ = 1; // Contador final tras animaciones
|
|
||||||
|
|
||||||
Status coffee_crisis_status_ = Status::DISABLED; // Estado de "COFFEE CRISIS"
|
Status coffee_crisis_status_ = Status::DISABLED; // Estado de "COFFEE CRISIS"
|
||||||
Status arcade_edition_status_ = Status::DISABLED; // Estado de "ARCADE EDITION"
|
Status arcade_edition_status_ = Status::DISABLED; // Estado de "ARCADE EDITION"
|
||||||
Shake shake_; // Efecto de agitación
|
float x_; // Posición X del logo
|
||||||
|
float y_; // Posición Y del logo
|
||||||
|
float zoom_ = 1.0F; // Zoom aplicado al texto "ARCADE EDITION"
|
||||||
|
int post_finished_counter_ = 1; // Contador final tras animaciones
|
||||||
|
|
||||||
// --- Inicialización ---
|
// --- Inicialización ---
|
||||||
void init(); // Inicializa las variables
|
void init(); // Inicializa las variables
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "external/json.hpp"
|
#include "external/json.hpp"
|
||||||
#include "input_types.h" // Solo incluimos los tipos compartidos
|
#include "input_types.h" // Solo incluimos los tipos compartidos
|
||||||
|
|
||||||
|
// --- Estructuras ---
|
||||||
struct GamepadConfig {
|
struct GamepadConfig {
|
||||||
std::string name; // Nombre del dispositivo
|
std::string name; // Nombre del dispositivo
|
||||||
std::string path; // Ruta física del dispositivo
|
std::string path; // Ruta física del dispositivo
|
||||||
@@ -29,12 +30,14 @@ struct GamepadConfig {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using GamepadConfigs = std::vector<GamepadConfig>;
|
// --- Tipos ---
|
||||||
|
using GamepadConfigs = std::vector<GamepadConfig>; // Vector de configuraciones de gamepad
|
||||||
|
|
||||||
|
// --- Clase GamepadConfigManager: gestor de configuraciones de gamepad ---
|
||||||
class GamepadConfigManager {
|
class GamepadConfigManager {
|
||||||
public:
|
public:
|
||||||
// Escribir vector de GamepadConfig a archivo JSON
|
// --- Métodos estáticos ---
|
||||||
static auto writeToJson(const GamepadConfigs& configs, const std::string& filename) -> bool {
|
static auto writeToJson(const GamepadConfigs& configs, const std::string& filename) -> bool { // Escribir configuraciones a JSON
|
||||||
try {
|
try {
|
||||||
nlohmann::json j;
|
nlohmann::json j;
|
||||||
j["gamepads"] = nlohmann::json::array();
|
j["gamepads"] = nlohmann::json::array();
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
// --- Namespace GlobalEvents: maneja eventos globales del juego ---
|
||||||
namespace GlobalEvents {
|
namespace GlobalEvents {
|
||||||
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
// --- Funciones ---
|
||||||
void handle(const SDL_Event &event);
|
void handle(const SDL_Event &event); // Comprueba los eventos que se pueden producir en cualquier sección del juego
|
||||||
} // namespace GlobalEvents
|
} // namespace GlobalEvents
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "global_inputs.h"
|
#include "global_inputs.h"
|
||||||
|
|
||||||
|
#include <algorithm> // Para std::ranges::any_of
|
||||||
#include <functional> // Para function
|
#include <functional> // Para function
|
||||||
#include <memory> // Para allocator, shared_ptr
|
#include <memory> // Para allocator, shared_ptr
|
||||||
#include <string> // Para operator+, char_traits, string, to_string
|
#include <string> // Para operator+, char_traits, string, to_string
|
||||||
@@ -145,11 +146,11 @@ auto checkServiceButton() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mandos
|
// Mandos
|
||||||
for (auto gamepad : Input::get()->getGamepads()) {
|
if (std::ranges::any_of(Input::get()->getGamepads(), [](const auto& gamepad) {
|
||||||
if (Input::get()->checkAction(Input::Action::SERVICE, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad)) {
|
return Input::get()->checkAction(Input::Action::SERVICE, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad);
|
||||||
toggleServiceMenu();
|
})) {
|
||||||
return true;
|
toggleServiceMenu();
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -176,14 +177,13 @@ auto checkSystemInputs() -> bool {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto& [action, func] : ACTIONS) {
|
return std::ranges::any_of(ACTIONS, [](const auto& pair) {
|
||||||
if (Input::get()->checkAction(action, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) {
|
if (Input::get()->checkAction(pair.first, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) {
|
||||||
func();
|
pair.second();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
|
});
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba el resto de entradas
|
// Comprueba el resto de entradas
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// --- Namespace GlobalInputs: gestiona inputs globales del juego ---
|
||||||
namespace GlobalInputs {
|
namespace GlobalInputs {
|
||||||
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
// --- Funciones ---
|
||||||
auto check() -> bool;
|
auto check() -> bool; // Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
||||||
} // namespace GlobalInputs
|
} // namespace GlobalInputs
|
||||||
65
source/hit.h
65
source/hit.h
@@ -7,55 +7,44 @@
|
|||||||
#include "sprite.h" // Para Sprite
|
#include "sprite.h" // Para Sprite
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
|
|
||||||
// Estructura que representa una colisión o impacto visual
|
// --- Estructura Hit: representa una colisión o impacto visual ---
|
||||||
struct Hit {
|
struct Hit {
|
||||||
private:
|
|
||||||
// Indica si el Hit está activo o no
|
|
||||||
bool enabled_{false};
|
|
||||||
|
|
||||||
// Sprite asociado al Hit, gestionado con un puntero único
|
|
||||||
std::unique_ptr<Sprite> sprite_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Elimina el constructor por defecto para obligar a pasar una textura
|
// --- Constructor ---
|
||||||
Hit() = delete;
|
Hit() = delete; // Elimina el constructor por defecto para obligar a pasar una textura
|
||||||
|
explicit Hit(const std::shared_ptr<Texture>& texture) // Constructor con textura obligatoria
|
||||||
// Constructor que obliga a pasar una textura compartida para crear el Sprite
|
|
||||||
// Esto evita que se pueda crear un Hit sin recursos gráficos válidos
|
|
||||||
explicit Hit(std::shared_ptr<Texture> texture)
|
|
||||||
: sprite_(std::make_unique<Sprite>(texture)) {}
|
: sprite_(std::make_unique<Sprite>(texture)) {}
|
||||||
|
|
||||||
// Establece la posición del Sprite en el espacio
|
// --- Métodos principales ---
|
||||||
void setPos(SDL_FPoint position) {
|
void create(SDL_FPoint position) { // Crea un "Hit" en la posición especificada
|
||||||
SDL_FPoint centered_position = {position.x - (sprite_->getWidth() / 2), position.y - (sprite_->getHeight() / 2)};
|
|
||||||
sprite_->setPosition(centered_position);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Activa o desactiva el Hit
|
|
||||||
void enable(bool value) {
|
|
||||||
enabled_ = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consulta si el Hit está activo
|
|
||||||
[[nodiscard]] auto isEnabled() const -> bool {
|
|
||||||
return enabled_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crea un "Hit" en la posición especificada
|
|
||||||
void create(SDL_FPoint position) {
|
|
||||||
setPos(position);
|
setPos(position);
|
||||||
enable(true);
|
enable(true);
|
||||||
}
|
}
|
||||||
|
void render() { // Dibuja el hit
|
||||||
// Dibuja el hit
|
|
||||||
void render() {
|
|
||||||
if (enabled_) {
|
if (enabled_) {
|
||||||
sprite_->render();
|
sprite_->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void disable() { // Deshabilita el hit
|
||||||
// Deshabilita el hit
|
|
||||||
void disable() {
|
|
||||||
enabled_ = false;
|
enabled_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Configuración ---
|
||||||
|
void setPos(SDL_FPoint position) { // Establece la posición del Sprite en el espacio
|
||||||
|
SDL_FPoint centered_position = {position.x - (sprite_->getWidth() / 2), position.y - (sprite_->getHeight() / 2)};
|
||||||
|
sprite_->setPosition(centered_position);
|
||||||
|
}
|
||||||
|
void enable(bool value) { // Activa o desactiva el Hit
|
||||||
|
enabled_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Getters ---
|
||||||
|
[[nodiscard]] auto isEnabled() const -> bool { // Consulta si el Hit está activo
|
||||||
|
return enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// --- Variables de estado ---
|
||||||
|
std::unique_ptr<Sprite> sprite_; // Sprite asociado al Hit
|
||||||
|
bool enabled_{false}; // Indica si el Hit está activo
|
||||||
};
|
};
|
||||||
|
|||||||
105
source/input.cpp
105
source/input.cpp
@@ -36,21 +36,21 @@ void Input::bindKey(Action action, SDL_Scancode code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Asigna inputs a botones del mando
|
// Asigna inputs a botones del mando
|
||||||
void Input::bindGameControllerButton(std::shared_ptr<Gamepad> gamepad, Action action, SDL_GamepadButton button) {
|
void Input::bindGameControllerButton(const std::shared_ptr<Gamepad> &gamepad, Action action, SDL_GamepadButton button) {
|
||||||
if (gamepad != nullptr) {
|
if (gamepad != nullptr) {
|
||||||
gamepad->bindings[action].button = button;
|
gamepad->bindings[action].button = button;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Asigna inputs a botones del mando
|
// Asigna inputs a botones del mando
|
||||||
void Input::bindGameControllerButton(std::shared_ptr<Gamepad> gamepad, Action action_target, Action action_source) {
|
void Input::bindGameControllerButton(const std::shared_ptr<Gamepad> &gamepad, Action action_target, Action action_source) {
|
||||||
if (gamepad != nullptr) {
|
if (gamepad != nullptr) {
|
||||||
gamepad->bindings[action_target].button = gamepad->bindings[action_source].button;
|
gamepad->bindings[action_target].button = gamepad->bindings[action_source].button;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba si alguna acción está activa
|
// Comprueba si alguna acción está activa
|
||||||
auto Input::checkAction(Action action, bool repeat, bool check_keyboard, std::shared_ptr<Gamepad> gamepad) -> bool {
|
auto Input::checkAction(Action action, bool repeat, bool check_keyboard, const std::shared_ptr<Gamepad> &gamepad) -> bool {
|
||||||
bool success_keyboard = false;
|
bool success_keyboard = false;
|
||||||
bool success_controller = false;
|
bool success_controller = false;
|
||||||
|
|
||||||
@@ -65,6 +65,10 @@ auto Input::checkAction(Action action, bool repeat, bool check_keyboard, std::sh
|
|||||||
if (gamepad != nullptr) {
|
if (gamepad != nullptr) {
|
||||||
success_controller = checkAxisInput(action, gamepad, repeat);
|
success_controller = checkAxisInput(action, gamepad, repeat);
|
||||||
|
|
||||||
|
if (!success_controller) {
|
||||||
|
success_controller = checkTriggerInput(action, gamepad, repeat);
|
||||||
|
}
|
||||||
|
|
||||||
if (!success_controller) {
|
if (!success_controller) {
|
||||||
if (repeat) { // El usuario quiere saber si está pulsada (estado mantenido)
|
if (repeat) { // El usuario quiere saber si está pulsada (estado mantenido)
|
||||||
success_controller = gamepad->bindings[action].is_held;
|
success_controller = gamepad->bindings[action].is_held;
|
||||||
@@ -78,7 +82,7 @@ auto Input::checkAction(Action action, bool repeat, bool check_keyboard, std::sh
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba si hay almenos una acción activa
|
// Comprueba si hay almenos una acción activa
|
||||||
auto Input::checkAnyInput(bool check_keyboard, std::shared_ptr<Gamepad> gamepad) -> bool {
|
auto Input::checkAnyInput(bool check_keyboard, const std::shared_ptr<Gamepad> &gamepad) -> bool {
|
||||||
// Obtenemos el número total de acciones posibles para iterar sobre ellas.
|
// Obtenemos el número total de acciones posibles para iterar sobre ellas.
|
||||||
|
|
||||||
// --- Comprobación del Teclado ---
|
// --- Comprobación del Teclado ---
|
||||||
@@ -118,7 +122,7 @@ auto Input::checkAnyButton(bool repeat) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba los mandos
|
// Comprueba los mandos
|
||||||
for (auto gamepad : gamepads_) {
|
for (const auto &gamepad : gamepads_) {
|
||||||
if (checkAction(bi, repeat, DO_NOT_CHECK_KEYBOARD, gamepad)) {
|
if (checkAction(bi, repeat, DO_NOT_CHECK_KEYBOARD, gamepad)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -132,7 +136,9 @@ auto Input::checkAnyButton(bool repeat) -> bool {
|
|||||||
auto Input::gameControllerFound() const -> bool { return !gamepads_.empty(); }
|
auto Input::gameControllerFound() const -> bool { return !gamepads_.empty(); }
|
||||||
|
|
||||||
// Obten el nombre de un mando de juego
|
// Obten el nombre de un mando de juego
|
||||||
auto Input::getControllerName(std::shared_ptr<Gamepad> gamepad) -> std::string { return gamepad == nullptr ? std::string() : gamepad->name; }
|
auto Input::getControllerName(const std::shared_ptr<Gamepad> &gamepad) -> std::string {
|
||||||
|
return gamepad == nullptr ? std::string() : gamepad->name;
|
||||||
|
}
|
||||||
|
|
||||||
// Obtiene la lista de nombres de mandos
|
// Obtiene la lista de nombres de mandos
|
||||||
auto Input::getControllerNames() const -> std::vector<std::string> {
|
auto Input::getControllerNames() const -> std::vector<std::string> {
|
||||||
@@ -166,8 +172,8 @@ auto Input::getGamepadByName(const std::string &name) const -> std::shared_ptr<I
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el SDL_GamepadButton asignado a un action
|
// Obtiene el SDL_GamepadButton asignado a un action
|
||||||
auto Input::getControllerBinding(std::shared_ptr<Gamepad> gamepad, Action action) -> SDL_GamepadButton {
|
auto Input::getControllerBinding(const std::shared_ptr<Gamepad> &gamepad, Action action) -> SDL_GamepadButton {
|
||||||
return gamepad->bindings[action].button;
|
return static_cast<SDL_GamepadButton>(gamepad->bindings[action].button);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convierte un InputAction a std::string
|
// Convierte un InputAction a std::string
|
||||||
@@ -202,7 +208,7 @@ auto Input::stringToInput(const std::string &name) -> Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba el eje del mando
|
// Comprueba el eje del mando
|
||||||
auto Input::checkAxisInput(Action action, std::shared_ptr<Gamepad> gamepad, bool repeat) -> bool {
|
auto Input::checkAxisInput(Action action, const std::shared_ptr<Gamepad> &gamepad, bool repeat) -> bool {
|
||||||
// Umbral para considerar el eje como activo
|
// Umbral para considerar el eje como activo
|
||||||
bool axis_active_now = false;
|
bool axis_active_now = false;
|
||||||
|
|
||||||
@@ -243,9 +249,57 @@ auto Input::checkAxisInput(Action action, std::shared_ptr<Gamepad> gamepad, bool
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Comprueba los triggers del mando como botones digitales
|
||||||
|
auto Input::checkTriggerInput(Action action, const std::shared_ptr<Gamepad> &gamepad, bool repeat) -> bool {
|
||||||
|
// Solo manejamos botones específicos que pueden ser triggers
|
||||||
|
if (gamepad->bindings[action].button != static_cast<int>(SDL_GAMEPAD_BUTTON_INVALID)) {
|
||||||
|
// Solo procesamos L2 y R2 como triggers
|
||||||
|
int button = gamepad->bindings[action].button;
|
||||||
|
|
||||||
|
// Verificar si el botón mapeado corresponde a un trigger virtual
|
||||||
|
// (Para esto necesitamos valores especiales que representen L2/R2 como botones)
|
||||||
|
bool trigger_active_now = false;
|
||||||
|
|
||||||
|
// Usamos constantes especiales para L2 y R2 como botones
|
||||||
|
if (button == TRIGGER_L2_AS_BUTTON) { // L2 como botón
|
||||||
|
Sint16 trigger_value = SDL_GetGamepadAxis(gamepad->pad, SDL_GAMEPAD_AXIS_LEFT_TRIGGER);
|
||||||
|
trigger_active_now = trigger_value > TRIGGER_THRESHOLD;
|
||||||
|
} else if (button == TRIGGER_R2_AS_BUTTON) { // R2 como botón
|
||||||
|
Sint16 trigger_value = SDL_GetGamepadAxis(gamepad->pad, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER);
|
||||||
|
trigger_active_now = trigger_value > TRIGGER_THRESHOLD;
|
||||||
|
} else {
|
||||||
|
return false; // No es un trigger
|
||||||
|
}
|
||||||
|
|
||||||
|
// Referencia al binding correspondiente
|
||||||
|
auto &binding = gamepad->bindings[action];
|
||||||
|
|
||||||
|
if (repeat) {
|
||||||
|
// Si se permite repetir, simplemente devolvemos el estado actual
|
||||||
|
return trigger_active_now;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si no se permite repetir, aplicamos la lógica de transición
|
||||||
|
if (trigger_active_now && !binding.trigger_active) {
|
||||||
|
// Transición de inactivo a activo
|
||||||
|
binding.trigger_active = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!trigger_active_now && binding.trigger_active) {
|
||||||
|
// Transición de activo a inactivo
|
||||||
|
binding.trigger_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mantener el estado actual
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Input::addGamepadMappingsFromFile() {
|
void Input::addGamepadMappingsFromFile() {
|
||||||
if (SDL_AddGamepadMappingsFromFile(gamepad_mappings_file_.c_str()) < 0) {
|
if (SDL_AddGamepadMappingsFromFile(gamepad_mappings_file_.c_str()) < 0) {
|
||||||
std::cout << "Error, could not load " << gamepad_mappings_file_.c_str() << " file: " << SDL_GetError() << std::endl;
|
std::cout << "Error, could not load " << gamepad_mappings_file_.c_str() << " file: " << SDL_GetError() << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,6 +334,7 @@ void Input::resetInputStates() {
|
|||||||
for (auto &binding : gamepad->bindings) {
|
for (auto &binding : gamepad->bindings) {
|
||||||
binding.second.is_held = false;
|
binding.second.is_held = false;
|
||||||
binding.second.just_pressed = false;
|
binding.second.just_pressed = false;
|
||||||
|
binding.second.trigger_active = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,9 +352,9 @@ void Input::update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- MANDOS ---
|
// --- MANDOS ---
|
||||||
for (auto gamepad : gamepads_) {
|
for (const auto &gamepad : gamepads_) {
|
||||||
for (auto &binding : gamepad->bindings) {
|
for (auto &binding : gamepad->bindings) {
|
||||||
bool button_is_down_now = static_cast<int>(SDL_GetGamepadButton(gamepad->pad, binding.second.button)) != 0;
|
bool button_is_down_now = static_cast<int>(SDL_GetGamepadButton(gamepad->pad, static_cast<SDL_GamepadButton>(binding.second.button))) != 0;
|
||||||
|
|
||||||
// El estado .is_held del fotograma anterior nos sirve para saber si es un pulso nuevo
|
// El estado .is_held del fotograma anterior nos sirve para saber si es un pulso nuevo
|
||||||
binding.second.just_pressed = button_is_down_now && !binding.second.is_held;
|
binding.second.just_pressed = button_is_down_now && !binding.second.is_held;
|
||||||
@@ -321,13 +376,13 @@ auto Input::handleEvent(const SDL_Event &event) -> std::string {
|
|||||||
auto Input::addGamepad(int device_index) -> std::string {
|
auto Input::addGamepad(int device_index) -> std::string {
|
||||||
SDL_Gamepad *pad = SDL_OpenGamepad(device_index);
|
SDL_Gamepad *pad = SDL_OpenGamepad(device_index);
|
||||||
if (pad == nullptr) {
|
if (pad == nullptr) {
|
||||||
std::cerr << "Error al abrir el gamepad: " << SDL_GetError() << std::endl;
|
std::cerr << "Error al abrir el gamepad: " << SDL_GetError() << '\n';
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto gamepad = std::make_shared<Gamepad>(pad);
|
auto gamepad = std::make_shared<Gamepad>(pad);
|
||||||
auto name = gamepad->name;
|
auto name = gamepad->name;
|
||||||
std::cout << "Gamepad connected (" << name << ")" << std::endl;
|
std::cout << "Gamepad connected (" << name << ")" << '\n';
|
||||||
applyGamepadConfig(gamepad);
|
applyGamepadConfig(gamepad);
|
||||||
saveGamepadConfigFromGamepad(gamepad);
|
saveGamepadConfigFromGamepad(gamepad);
|
||||||
gamepads_.push_back(std::move(gamepad));
|
gamepads_.push_back(std::move(gamepad));
|
||||||
@@ -335,23 +390,23 @@ auto Input::addGamepad(int device_index) -> std::string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto Input::removeGamepad(SDL_JoystickID id) -> std::string {
|
auto Input::removeGamepad(SDL_JoystickID id) -> std::string {
|
||||||
auto it = std::find_if(gamepads_.begin(), gamepads_.end(), [id](const std::shared_ptr<Gamepad> &gamepad) {
|
auto it = std::ranges::find_if(gamepads_, [id](const std::shared_ptr<Gamepad> &gamepad) {
|
||||||
return gamepad->instance_id == id;
|
return gamepad->instance_id == id;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (it != gamepads_.end()) {
|
if (it != gamepads_.end()) {
|
||||||
std::string name = (*it)->name;
|
std::string name = (*it)->name;
|
||||||
std::cout << "Gamepad disconnected (" << name << ")" << std::endl;
|
std::cout << "Gamepad disconnected (" << name << ")" << '\n';
|
||||||
gamepads_.erase(it);
|
gamepads_.erase(it);
|
||||||
return name + " DISCONNECTED";
|
return name + " DISCONNECTED";
|
||||||
}
|
}
|
||||||
std::cerr << "No se encontró el gamepad con ID " << id << std::endl;
|
std::cerr << "No se encontró el gamepad con ID " << id << '\n';
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::printConnectedGamepads() const {
|
void Input::printConnectedGamepads() const {
|
||||||
if (gamepads_.empty()) {
|
if (gamepads_.empty()) {
|
||||||
std::cout << "No hay gamepads conectados." << std::endl;
|
std::cout << "No hay gamepads conectados." << '\n';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,7 +414,7 @@ void Input::printConnectedGamepads() const {
|
|||||||
for (const auto &gamepad : gamepads_) {
|
for (const auto &gamepad : gamepads_) {
|
||||||
std::string name = gamepad->name.empty() ? "Desconocido" : gamepad->name;
|
std::string name = gamepad->name.empty() ? "Desconocido" : gamepad->name;
|
||||||
std::cout << " - ID: " << gamepad->instance_id
|
std::cout << " - ID: " << gamepad->instance_id
|
||||||
<< ", Nombre: " << name << ")" << std::endl;
|
<< ", Nombre: " << name << ")" << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,13 +434,13 @@ void Input::applyGamepadConfig(std::shared_ptr<Gamepad> gamepad) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- Buscar configuración por RUTA (path) ---
|
// --- Buscar configuración por RUTA (path) ---
|
||||||
auto config_it = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepad](const GamepadConfig &config) {
|
auto config_it = std::ranges::find_if(gamepad_configs_, [&gamepad](const GamepadConfig &config) {
|
||||||
return config.path == gamepad->path;
|
return config.path == gamepad->path;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (config_it != gamepad_configs_.end()) {
|
if (config_it != gamepad_configs_.end()) {
|
||||||
// Se encontró una configuración específica para este puerto/dispositivo. La aplicamos.
|
// Se encontró una configuración específica para este puerto/dispositivo. La aplicamos.
|
||||||
std::cout << "Applying custom config for gamepad at path: " << gamepad->path << std::endl;
|
std::cout << "Applying custom config for gamepad at path: " << gamepad->path << '\n';
|
||||||
for (const auto &[action, button] : config_it->bindings) {
|
for (const auto &[action, button] : config_it->bindings) {
|
||||||
if (gamepad->bindings.find(action) != gamepad->bindings.end()) {
|
if (gamepad->bindings.find(action) != gamepad->bindings.end()) {
|
||||||
gamepad->bindings[action].button = button;
|
gamepad->bindings[action].button = button;
|
||||||
@@ -401,7 +456,7 @@ void Input::saveGamepadConfigFromGamepad(std::shared_ptr<Gamepad> gamepad) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- CAMBIO CLAVE: Buscar si ya existe una configuración por RUTA (path) ---
|
// --- CAMBIO CLAVE: Buscar si ya existe una configuración por RUTA (path) ---
|
||||||
auto config_it = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepad](const GamepadConfig &config) {
|
auto config_it = std::ranges::find_if(gamepad_configs_, [&gamepad](const GamepadConfig &config) {
|
||||||
return config.path == gamepad->path;
|
return config.path == gamepad->path;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -411,7 +466,7 @@ void Input::saveGamepadConfigFromGamepad(std::shared_ptr<Gamepad> gamepad) {
|
|||||||
|
|
||||||
// Copiar todos los bindings actuales del gamepad
|
// Copiar todos los bindings actuales del gamepad
|
||||||
for (const auto &[action, buttonState] : gamepad->bindings) {
|
for (const auto &[action, buttonState] : gamepad->bindings) {
|
||||||
new_config.bindings[action] = buttonState.button;
|
new_config.bindings[action] = static_cast<SDL_GamepadButton>(buttonState.button);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config_it != gamepad_configs_.end()) {
|
if (config_it != gamepad_configs_.end()) {
|
||||||
@@ -434,7 +489,7 @@ void Input::setGamepadConfigsFile(const std::string &filename) {
|
|||||||
|
|
||||||
// Método para obtener configuración de un gamepad específico (opcional)
|
// Método para obtener configuración de un gamepad específico (opcional)
|
||||||
auto Input::getGamepadConfig(const std::string &gamepad_name) -> GamepadConfig * {
|
auto Input::getGamepadConfig(const std::string &gamepad_name) -> GamepadConfig * {
|
||||||
auto config_it = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepad_name](const GamepadConfig &config) {
|
auto config_it = std::ranges::find_if(gamepad_configs_, [&gamepad_name](const GamepadConfig &config) {
|
||||||
return config.name == gamepad_name;
|
return config.name == gamepad_name;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -443,7 +498,7 @@ auto Input::getGamepadConfig(const std::string &gamepad_name) -> GamepadConfig *
|
|||||||
|
|
||||||
// Método para eliminar configuración de gamepad (opcional)
|
// Método para eliminar configuración de gamepad (opcional)
|
||||||
auto Input::removeGamepadConfig(const std::string &gamepad_name) -> bool {
|
auto Input::removeGamepadConfig(const std::string &gamepad_name) -> bool {
|
||||||
auto config_it = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepad_name](const GamepadConfig &config) {
|
auto config_it = std::ranges::find_if(gamepad_configs_, [&gamepad_name](const GamepadConfig &config) {
|
||||||
return config.name == gamepad_name;
|
return config.name == gamepad_name;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,18 +11,19 @@
|
|||||||
#include "gamepad_config_manager.h" // Para GamepadConfig (ptr only), GamepadConfigs
|
#include "gamepad_config_manager.h" // Para GamepadConfig (ptr only), GamepadConfigs
|
||||||
#include "input_types.h" // Para InputAction
|
#include "input_types.h" // Para InputAction
|
||||||
|
|
||||||
// Clase Input: gestiona la entrada de teclado y mandos (singleton)
|
// --- Clase Input: gestiona la entrada de teclado y mandos (singleton) ---
|
||||||
class Input {
|
class Input {
|
||||||
public:
|
public:
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr bool ALLOW_REPEAT = true;
|
static constexpr bool ALLOW_REPEAT = true; // Permite repetición
|
||||||
static constexpr bool DO_NOT_ALLOW_REPEAT = false;
|
static constexpr bool DO_NOT_ALLOW_REPEAT = false; // No permite repetición
|
||||||
|
static constexpr bool CHECK_KEYBOARD = true; // Comprueba teclado
|
||||||
|
static constexpr bool DO_NOT_CHECK_KEYBOARD = false; // No comprueba teclado
|
||||||
|
static constexpr int TRIGGER_L2_AS_BUTTON = 100; // L2 como botón
|
||||||
|
static constexpr int TRIGGER_R2_AS_BUTTON = 101; // R2 como botón
|
||||||
|
|
||||||
static constexpr bool CHECK_KEYBOARD = true;
|
// --- Tipos ---
|
||||||
static constexpr bool DO_NOT_CHECK_KEYBOARD = false;
|
using Action = InputAction; // Alias para mantener compatibilidad
|
||||||
|
|
||||||
// Alias para mantener compatibilidad con el código existente
|
|
||||||
using Action = InputAction;
|
|
||||||
|
|
||||||
// --- Estructuras ---
|
// --- Estructuras ---
|
||||||
struct KeyState {
|
struct KeyState {
|
||||||
@@ -35,12 +36,13 @@ class Input {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ButtonState {
|
struct ButtonState {
|
||||||
SDL_GamepadButton button; // GameControllerButton asociado
|
int button; // GameControllerButton asociado
|
||||||
bool is_held; // Está pulsada ahora mismo
|
bool is_held; // Está pulsada ahora mismo
|
||||||
bool just_pressed; // Se acaba de pulsar en este fotograma
|
bool just_pressed; // Se acaba de pulsar en este fotograma
|
||||||
bool axis_active; // Estado del eje
|
bool axis_active; // Estado del eje
|
||||||
|
bool trigger_active{false}; // Estado del trigger como botón digital
|
||||||
|
|
||||||
ButtonState(SDL_GamepadButton btn = SDL_GAMEPAD_BUTTON_INVALID, bool is_held = false, bool just_pressed = false, bool axis_act = false)
|
ButtonState(int btn = static_cast<int>(SDL_GAMEPAD_BUTTON_INVALID), bool is_held = false, bool just_pressed = false, bool axis_act = false)
|
||||||
: button(btn), is_held(is_held), just_pressed(just_pressed), axis_active(axis_act) {}
|
: button(btn), is_held(is_held), just_pressed(just_pressed), axis_active(axis_act) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -102,23 +104,23 @@ class Input {
|
|||||||
path(std::string(SDL_GetGamepadPath(pad))),
|
path(std::string(SDL_GetGamepadPath(pad))),
|
||||||
bindings{
|
bindings{
|
||||||
// Movimiento del jugador
|
// Movimiento del jugador
|
||||||
{Action::UP, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_UP)},
|
{Action::UP, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_UP))},
|
||||||
{Action::DOWN, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_DOWN)},
|
{Action::DOWN, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_DOWN))},
|
||||||
{Action::LEFT, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_LEFT)},
|
{Action::LEFT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_LEFT))},
|
||||||
{Action::RIGHT, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_RIGHT)},
|
{Action::RIGHT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_RIGHT))},
|
||||||
|
|
||||||
// Disparo del jugador
|
// Disparo del jugador
|
||||||
{Action::FIRE_LEFT, ButtonState(SDL_GAMEPAD_BUTTON_WEST)},
|
{Action::FIRE_LEFT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_WEST))},
|
||||||
{Action::FIRE_CENTER, ButtonState(SDL_GAMEPAD_BUTTON_NORTH)},
|
{Action::FIRE_CENTER, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_NORTH))},
|
||||||
{Action::FIRE_RIGHT, ButtonState(SDL_GAMEPAD_BUTTON_EAST)},
|
{Action::FIRE_RIGHT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_EAST))},
|
||||||
|
|
||||||
// Interfaz
|
// Interfaz
|
||||||
{Action::START, ButtonState(SDL_GAMEPAD_BUTTON_START)},
|
{Action::START, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_START))},
|
||||||
{Action::SERVICE, ButtonState(SDL_GAMEPAD_BUTTON_BACK)},
|
{Action::SERVICE, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_BACK))},
|
||||||
|
|
||||||
// Menu de servicio
|
// Menu de servicio
|
||||||
{Action::SM_SELECT, ButtonState(SDL_GAMEPAD_BUTTON_WEST)},
|
{Action::SM_SELECT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_WEST))},
|
||||||
{Action::SM_BACK, ButtonState(SDL_GAMEPAD_BUTTON_NORTH)}} {}
|
{Action::SM_BACK, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_NORTH))}} {}
|
||||||
|
|
||||||
~Gamepad() {
|
~Gamepad() {
|
||||||
if (pad != nullptr) {
|
if (pad != nullptr) {
|
||||||
@@ -128,11 +130,12 @@ class Input {
|
|||||||
|
|
||||||
// Reasigna un botón a una acción
|
// Reasigna un botón a una acción
|
||||||
void rebindAction(Action action, SDL_GamepadButton new_button) {
|
void rebindAction(Action action, SDL_GamepadButton new_button) {
|
||||||
bindings[action] = new_button;
|
bindings[action] = static_cast<int>(new_button);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using Gamepads = std::vector<std::shared_ptr<Gamepad>>;
|
// --- Tipos ---
|
||||||
|
using Gamepads = std::vector<std::shared_ptr<Gamepad>>; // Vector de gamepads
|
||||||
|
|
||||||
// --- Métodos de singleton ---
|
// --- Métodos de singleton ---
|
||||||
static void init(const std::string &game_controller_db_path, const std::string &gamepad_configs_file);
|
static void init(const std::string &game_controller_db_path, const std::string &gamepad_configs_file);
|
||||||
@@ -141,18 +144,18 @@ class Input {
|
|||||||
|
|
||||||
// --- Métodos de configuración de controles ---
|
// --- Métodos de configuración de controles ---
|
||||||
void bindKey(Action action, SDL_Scancode code);
|
void bindKey(Action action, SDL_Scancode code);
|
||||||
static void bindGameControllerButton(std::shared_ptr<Gamepad> gamepad, Action action, SDL_GamepadButton button);
|
static void bindGameControllerButton(const std::shared_ptr<Gamepad> &gamepad, Action action, SDL_GamepadButton button);
|
||||||
static void bindGameControllerButton(std::shared_ptr<Gamepad> gamepad, Action action_target, Action action_source);
|
static void bindGameControllerButton(const std::shared_ptr<Gamepad> &gamepad, Action action_target, Action action_source);
|
||||||
|
|
||||||
// --- Métodos de consulta de entrada ---
|
// --- Métodos de consulta de entrada ---
|
||||||
void update();
|
void update();
|
||||||
auto checkAction(Action action, bool repeat = true, bool check_keyboard = true, std::shared_ptr<Gamepad> gamepad = nullptr) -> bool;
|
auto checkAction(Action action, bool repeat = true, bool check_keyboard = true, const std::shared_ptr<Gamepad> &gamepad = nullptr) -> bool;
|
||||||
auto checkAnyInput(bool check_keyboard = true, std::shared_ptr<Gamepad> gamepad = nullptr) -> bool;
|
auto checkAnyInput(bool check_keyboard = true, const std::shared_ptr<Gamepad> &gamepad = nullptr) -> bool;
|
||||||
auto checkAnyButton(bool repeat = DO_NOT_ALLOW_REPEAT) -> bool;
|
auto checkAnyButton(bool repeat = DO_NOT_ALLOW_REPEAT) -> bool;
|
||||||
|
|
||||||
// --- Métodos de gestión de mandos ---
|
// --- Métodos de gestión de mandos ---
|
||||||
[[nodiscard]] auto gameControllerFound() const -> bool;
|
[[nodiscard]] auto gameControllerFound() const -> bool;
|
||||||
static auto getControllerName(std::shared_ptr<Gamepad> gamepad) -> std::string;
|
static auto getControllerName(const std::shared_ptr<Gamepad> &gamepad) -> std::string;
|
||||||
auto getControllerNames() const -> std::vector<std::string>;
|
auto getControllerNames() const -> std::vector<std::string>;
|
||||||
[[nodiscard]] auto getNumGamepads() const -> int;
|
[[nodiscard]] auto getNumGamepads() const -> int;
|
||||||
auto getGamepad(SDL_JoystickID id) const -> std::shared_ptr<Gamepad>;
|
auto getGamepad(SDL_JoystickID id) const -> std::shared_ptr<Gamepad>;
|
||||||
@@ -160,7 +163,7 @@ class Input {
|
|||||||
auto getGamepads() const -> const Gamepads & { return gamepads_; }
|
auto getGamepads() const -> const Gamepads & { return gamepads_; }
|
||||||
|
|
||||||
// --- Métodos de consulta y utilidades ---
|
// --- Métodos de consulta y utilidades ---
|
||||||
[[nodiscard]] static auto getControllerBinding(std::shared_ptr<Gamepad> gamepad, Action action) -> SDL_GamepadButton;
|
[[nodiscard]] static auto getControllerBinding(const std::shared_ptr<Gamepad> &gamepad, Action action) -> SDL_GamepadButton;
|
||||||
[[nodiscard]] static auto inputToString(Action action) -> std::string;
|
[[nodiscard]] static auto inputToString(Action action) -> std::string;
|
||||||
[[nodiscard]] static auto stringToInput(const std::string &name) -> Action;
|
[[nodiscard]] static auto stringToInput(const std::string &name) -> Action;
|
||||||
|
|
||||||
@@ -178,6 +181,7 @@ class Input {
|
|||||||
private:
|
private:
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr Sint16 AXIS_THRESHOLD = 30000;
|
static constexpr Sint16 AXIS_THRESHOLD = 30000;
|
||||||
|
static constexpr Sint16 TRIGGER_THRESHOLD = 16384; // Umbral para triggers (aproximadamente 50% del rango)
|
||||||
static constexpr std::array<Action, 4> BUTTON_INPUTS = {Action::FIRE_LEFT, Action::FIRE_CENTER, Action::FIRE_RIGHT, Action::START}; // Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
|
static constexpr std::array<Action, 4> BUTTON_INPUTS = {Action::FIRE_LEFT, Action::FIRE_CENTER, Action::FIRE_RIGHT, Action::START}; // Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
|
||||||
|
|
||||||
// --- Variables internas ---
|
// --- Variables internas ---
|
||||||
@@ -189,7 +193,8 @@ class Input {
|
|||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void initSDLGamePad();
|
void initSDLGamePad();
|
||||||
static auto checkAxisInput(Action action, std::shared_ptr<Gamepad> gamepad, bool repeat) -> bool;
|
static auto checkAxisInput(Action action, const std::shared_ptr<Gamepad> &gamepad, bool repeat) -> bool;
|
||||||
|
static auto checkTriggerInput(Action action, const std::shared_ptr<Gamepad> &gamepad, bool repeat) -> bool;
|
||||||
auto addGamepad(int device_index) -> std::string;
|
auto addGamepad(int device_index) -> std::string;
|
||||||
auto removeGamepad(SDL_JoystickID id) -> std::string;
|
auto removeGamepad(SDL_JoystickID id) -> std::string;
|
||||||
void addGamepadMappingsFromFile();
|
void addGamepadMappingsFromFile();
|
||||||
|
|||||||
@@ -73,7 +73,9 @@ const std::unordered_map<SDL_GamepadButton, std::string> BUTTON_TO_STRING = {
|
|||||||
{SDL_GAMEPAD_BUTTON_DPAD_UP, "DPAD_UP"},
|
{SDL_GAMEPAD_BUTTON_DPAD_UP, "DPAD_UP"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_DOWN, "DPAD_DOWN"},
|
{SDL_GAMEPAD_BUTTON_DPAD_DOWN, "DPAD_DOWN"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_LEFT, "DPAD_LEFT"},
|
{SDL_GAMEPAD_BUTTON_DPAD_LEFT, "DPAD_LEFT"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"}};
|
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"},
|
||||||
|
{static_cast<SDL_GamepadButton>(100), "L2_AS_BUTTON"},
|
||||||
|
{static_cast<SDL_GamepadButton>(101), "R2_AS_BUTTON"}};
|
||||||
|
|
||||||
const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON = {
|
const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON = {
|
||||||
{"WEST", SDL_GAMEPAD_BUTTON_WEST},
|
{"WEST", SDL_GAMEPAD_BUTTON_WEST},
|
||||||
@@ -87,7 +89,9 @@ const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON = {
|
|||||||
{"DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP},
|
{"DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP},
|
||||||
{"DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN},
|
{"DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN},
|
||||||
{"DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT},
|
{"DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT},
|
||||||
{"DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT}};
|
{"DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT},
|
||||||
|
{"L2_AS_BUTTON", static_cast<SDL_GamepadButton>(100)},
|
||||||
|
{"R2_AS_BUTTON", static_cast<SDL_GamepadButton>(101)}};
|
||||||
|
|
||||||
const std::unordered_map<InputAction, InputAction> ACTION_TO_ACTION = {
|
const std::unordered_map<InputAction, InputAction> ACTION_TO_ACTION = {
|
||||||
{InputAction::SM_SELECT, InputAction::FIRE_LEFT},
|
{InputAction::SM_SELECT, InputAction::FIRE_LEFT},
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
// Acciones de entrada posibles en el juego
|
// --- Enums ---
|
||||||
enum class InputAction : int {
|
enum class InputAction : int { // Acciones de entrada posibles en el juego
|
||||||
// Inputs de movimiento
|
// Inputs de movimiento
|
||||||
UP,
|
UP,
|
||||||
DOWN,
|
DOWN,
|
||||||
@@ -47,9 +47,9 @@ enum class InputAction : int {
|
|||||||
SIZE,
|
SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mapas para convertir entre enums y strings
|
// --- Variables ---
|
||||||
extern const std::unordered_map<InputAction, std::string> ACTION_TO_STRING;
|
extern const std::unordered_map<InputAction, std::string> ACTION_TO_STRING; // Mapeo de acción a string
|
||||||
extern const std::unordered_map<std::string, InputAction> STRING_TO_ACTION;
|
extern const std::unordered_map<std::string, InputAction> STRING_TO_ACTION; // Mapeo de string a acción
|
||||||
extern const std::unordered_map<SDL_GamepadButton, std::string> BUTTON_TO_STRING;
|
extern const std::unordered_map<SDL_GamepadButton, std::string> BUTTON_TO_STRING; // Mapeo de botón a string
|
||||||
extern const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON;
|
extern const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON; // Mapeo de string a botón
|
||||||
extern const std::unordered_map<InputAction, InputAction> ACTION_TO_ACTION;
|
extern const std::unordered_map<InputAction, InputAction> ACTION_TO_ACTION; // Mapeo de acción a acción
|
||||||
@@ -8,10 +8,8 @@
|
|||||||
|
|
||||||
class Texture; // lines 6-6
|
class Texture; // lines 6-6
|
||||||
|
|
||||||
Item::Item(ItemType type, float x, float y, SDL_FRect &play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
|
Item::Item(ItemType type, float x, float y, SDL_FRect &play_area, const std::shared_ptr<Texture> &texture, const std::vector<std::string> &animation)
|
||||||
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
|
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)), play_area_(play_area), type_(type) {
|
||||||
type_(type),
|
|
||||||
play_area_(play_area) {
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ItemType::COFFEE_MACHINE: {
|
case ItemType::COFFEE_MACHINE: {
|
||||||
width_ = COFFEE_MACHINE_WIDTH;
|
width_ = COFFEE_MACHINE_WIDTH;
|
||||||
@@ -29,7 +27,15 @@ Item::Item(ItemType type, float x, float y, SDL_FRect &play_area, std::shared_pt
|
|||||||
height_ = param.game.item_size;
|
height_ = param.game.item_size;
|
||||||
pos_x_ = x;
|
pos_x_ = x;
|
||||||
pos_y_ = y;
|
pos_y_ = y;
|
||||||
vel_x_ = -1.0F + ((rand() % 5) * 0.5F);
|
// 6 velocidades: 3 negativas (-1.0, -0.66, -0.33) y 3 positivas (0.33, 0.66, 1.0)
|
||||||
|
const int direction = rand() % 6;
|
||||||
|
if (direction < 3) {
|
||||||
|
// Velocidades negativas: -1.0, -0.66, -0.33
|
||||||
|
vel_x_ = -1.0F + (direction * 0.33F);
|
||||||
|
} else {
|
||||||
|
// Velocidades positivas: 0.33, 0.66, 1.0
|
||||||
|
vel_x_ = 0.33F + ((direction - 3) * 0.33F);
|
||||||
|
}
|
||||||
vel_y_ = -4.0F;
|
vel_y_ = -4.0F;
|
||||||
accel_y_ = 0.2F;
|
accel_y_ = 0.2F;
|
||||||
collider_.r = width_ / 2;
|
collider_.r = width_ / 2;
|
||||||
@@ -82,9 +88,9 @@ void Item::move() {
|
|||||||
const float MAX_X = play_area_.w - width_;
|
const float MAX_X = play_area_.w - width_;
|
||||||
pos_x_ = std::clamp(pos_x_, MIN_X, MAX_X);
|
pos_x_ = std::clamp(pos_x_, MIN_X, MAX_X);
|
||||||
|
|
||||||
// Si toca el borde lateral, invierte la velocidad horizontal
|
// Si toca el borde lateral
|
||||||
if (pos_x_ == MIN_X || pos_x_ == MAX_X) {
|
if (pos_x_ == MIN_X || pos_x_ == MAX_X) {
|
||||||
vel_x_ = -vel_x_;
|
vel_x_ = -vel_x_; // Invierte la velocidad horizontal
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si colisiona por arriba, rebota (excepto la máquina de café)
|
// Si colisiona por arriba, rebota (excepto la máquina de café)
|
||||||
@@ -92,8 +98,8 @@ void Item::move() {
|
|||||||
// Corrige
|
// Corrige
|
||||||
pos_y_ = param.game.play_area.rect.y;
|
pos_y_ = param.game.play_area.rect.y;
|
||||||
|
|
||||||
// Invierte la velocidad
|
// Fuerza la velocidad hacia abajo para evitar oscilaciones
|
||||||
vel_y_ = -vel_y_;
|
vel_y_ = std::abs(vel_y_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si colisiona con la parte inferior
|
// Si colisiona con la parte inferior
|
||||||
@@ -181,17 +187,17 @@ auto Item::getCoffeeMachineSpawn(int player_x, int item_width, int area_width, i
|
|||||||
// Ambos lados disponibles, elegir aleatoriamente
|
// Ambos lados disponibles, elegir aleatoriamente
|
||||||
if (rand() % 2 == 0) {
|
if (rand() % 2 == 0) {
|
||||||
// Lado izquierdo
|
// Lado izquierdo
|
||||||
return rand() % (exclude_left - LEFT_BOUND) + LEFT_BOUND;
|
return (rand() % (exclude_left - LEFT_BOUND)) + LEFT_BOUND;
|
||||||
} // Lado derecho
|
} // Lado derecho
|
||||||
return rand() % (RIGHT_BOUND - exclude_right) + exclude_right;
|
return (rand() % (RIGHT_BOUND - exclude_right)) + exclude_right;
|
||||||
}
|
}
|
||||||
if (can_spawn_left) {
|
if (can_spawn_left) {
|
||||||
// Solo lado izquierdo disponible
|
// Solo lado izquierdo disponible
|
||||||
return rand() % (exclude_left - LEFT_BOUND) + LEFT_BOUND;
|
return (rand() % (exclude_left - LEFT_BOUND)) + LEFT_BOUND;
|
||||||
}
|
}
|
||||||
if (can_spawn_right) {
|
if (can_spawn_right) {
|
||||||
// Solo lado derecho disponible
|
// Solo lado derecho disponible
|
||||||
return rand() % (RIGHT_BOUND - exclude_right) + exclude_right;
|
return (rand() % (RIGHT_BOUND - exclude_right)) + exclude_right;
|
||||||
} // No hay espacio suficiente lejos del jugador
|
} // No hay espacio suficiente lejos del jugador
|
||||||
// Por ahora, intentar spawn en el extremo más lejano posible
|
// Por ahora, intentar spawn en el extremo más lejano posible
|
||||||
int distance_to_left = abs(player_x - LEFT_BOUND);
|
int distance_to_left = abs(player_x - LEFT_BOUND);
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Tipos de objetos disponibles en el juego.
|
// --- Enums ---
|
||||||
// Define los diferentes tipos de objetos que pueden existir en el juego.
|
|
||||||
enum class ItemType : int {
|
enum class ItemType : int {
|
||||||
DISK = 1, // Disco
|
DISK = 1, // Disco
|
||||||
GAVINA = 2, // Gavina
|
GAVINA = 2, // Gavina
|
||||||
@@ -24,81 +23,57 @@ enum class ItemType : int {
|
|||||||
NONE = 8, // Ninguno
|
NONE = 8, // Ninguno
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clase Item.
|
// --- Clase Item: representa un objeto en el juego ---
|
||||||
// Representa un objeto en el juego, con sus propiedades y métodos para gestionar su comportamiento.
|
|
||||||
class Item {
|
class Item {
|
||||||
public:
|
public:
|
||||||
// Constantes
|
// --- Constantes ---
|
||||||
static constexpr int COFFEE_MACHINE_WIDTH = 30;
|
static constexpr int COFFEE_MACHINE_WIDTH = 30; // Anchura de la máquina de café
|
||||||
static constexpr int COFFEE_MACHINE_HEIGHT = 39;
|
static constexpr int COFFEE_MACHINE_HEIGHT = 39; // Altura de la máquina de café
|
||||||
|
|
||||||
// Constructor. Inicializa un objeto Item con el tipo, posición, área de juego, textura y animación.
|
// --- Constructor y destructor ---
|
||||||
Item(ItemType type, float x, float y, SDL_FRect &play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation);
|
Item(ItemType type, float x, float y, SDL_FRect &play_area, const std::shared_ptr<Texture> &texture, const std::vector<std::string> &animation); // Constructor principal
|
||||||
|
~Item() = default; // Destructor
|
||||||
|
|
||||||
// Destructor.
|
// --- Métodos principales ---
|
||||||
~Item() = default;
|
void alignTo(int x); // Centra el objeto en la posición X indicada
|
||||||
|
void render(); // Renderiza el objeto en pantalla
|
||||||
|
void disable(); // Desactiva el objeto
|
||||||
|
void update(); // Actualiza la posición, animación y contadores
|
||||||
|
|
||||||
// Centra el objeto en la posición X indicada, asegurando que no se salga del área de juego.
|
// --- Getters ---
|
||||||
void alignTo(int x);
|
[[nodiscard]] auto getPosX() const -> float { return pos_x_; } // Obtiene la posición X
|
||||||
|
[[nodiscard]] auto getPosY() const -> float { return pos_y_; } // Obtiene la posición Y
|
||||||
// Renderiza el objeto en pantalla si está habilitado.
|
[[nodiscard]] auto getWidth() const -> int { return width_; } // Obtiene la anchura
|
||||||
// Si el tiempo de vida es mayor que 200, renderiza el sprite.
|
[[nodiscard]] auto getHeight() const -> int { return height_; } // Obtiene la altura
|
||||||
// Si es menor o igual a 200, renderiza el sprite de forma intermitente.
|
[[nodiscard]] auto getType() const -> ItemType { return type_; } // Obtiene el tipo
|
||||||
void render();
|
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; } // Verifica si está habilitado
|
||||||
|
[[nodiscard]] auto isOnFloor() const -> bool { return floor_collision_; } // Verifica si está en el suelo
|
||||||
// Desactiva el objeto estableciendo su estado enabled_ a false.
|
auto getCollider() -> Circle & { return collider_; } // Obtiene el colisionador
|
||||||
void disable();
|
|
||||||
|
|
||||||
// Actualiza la posición, animación y contadores del objeto.
|
|
||||||
// Llama a move(), sprite_->update() y updateTimeToLive().
|
|
||||||
void update();
|
|
||||||
|
|
||||||
// Getters
|
|
||||||
[[nodiscard]] auto getPosX() const -> float { return pos_x_; }
|
|
||||||
[[nodiscard]] auto getPosY() const -> float { return pos_y_; }
|
|
||||||
[[nodiscard]] auto getWidth() const -> int { return width_; }
|
|
||||||
[[nodiscard]] auto getHeight() const -> int { return height_; }
|
|
||||||
[[nodiscard]] auto getType() const -> ItemType { return type_; }
|
|
||||||
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
|
|
||||||
[[nodiscard]] auto isOnFloor() const -> bool { return floor_collision_; }
|
|
||||||
auto getCollider() -> Circle & { return collider_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Objetos y punteros
|
// --- Objetos y punteros ---
|
||||||
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos del objeto
|
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos del objeto
|
||||||
|
|
||||||
// Variables de estado y físicas
|
// --- Variables de estado ---
|
||||||
|
SDL_FRect play_area_; // Rectángulo con la zona de juego
|
||||||
|
Circle collider_; // Círculo de colisión del objeto
|
||||||
|
ItemType type_; // Tipo de objeto
|
||||||
float pos_x_; // Posición X del objeto
|
float pos_x_; // Posición X del objeto
|
||||||
float pos_y_; // Posición Y del objeto
|
float pos_y_; // Posición Y del objeto
|
||||||
int width_; // Ancho del objeto
|
|
||||||
int height_; // Alto del objeto
|
|
||||||
float vel_x_; // Velocidad en el eje X
|
float vel_x_; // Velocidad en el eje X
|
||||||
float vel_y_; // Velocidad en el eje Y
|
float vel_y_; // Velocidad en el eje Y
|
||||||
float accel_x_ = 0.0F; // Aceleración en el eje X
|
float accel_x_ = 0.0F; // Aceleración en el eje X
|
||||||
float accel_y_; // Aceleración en el eje Y
|
float accel_y_; // Aceleración en el eje Y
|
||||||
bool floor_collision_ = false; // Indica si el objeto colisiona con el suelo
|
int width_; // Ancho del objeto
|
||||||
ItemType type_; // Tipo de objeto
|
int height_; // Alto del objeto
|
||||||
bool enabled_ = true; // Indica si el objeto está habilitado
|
|
||||||
Circle collider_; // Círculo de colisión del objeto
|
|
||||||
SDL_FRect play_area_; // Rectángulo con la zona de juego
|
|
||||||
Uint16 time_to_live_ = 600; // Tiempo que el objeto está presente
|
Uint16 time_to_live_ = 600; // Tiempo que el objeto está presente
|
||||||
|
bool floor_collision_ = false; // Indica si el objeto colisiona con el suelo
|
||||||
|
bool enabled_ = true; // Indica si el objeto está habilitado
|
||||||
|
|
||||||
// Alinea el círculo de colisión con la posición del objeto.
|
// --- Métodos internos ---
|
||||||
// Actualiza las coordenadas X e Y del colisionador.
|
void shiftColliders(); // Alinea el círculo de colisión con la posición del objeto
|
||||||
void shiftColliders();
|
void shiftSprite(); // Coloca el sprite en la posición del objeto
|
||||||
|
void move(); // Actualiza la posición y estados del objeto
|
||||||
// Coloca el sprite en la posición del objeto.
|
void updateTimeToLive(); // Actualiza el contador de tiempo de vida
|
||||||
// Actualiza las coordenadas X e Y del sprite.
|
static auto getCoffeeMachineSpawn(int player_x, int item_width, int area_width, int margin = 2) -> int; // Calcula la zona de aparición de la máquina de café
|
||||||
void shiftSprite();
|
|
||||||
|
|
||||||
// Actualiza la posición y estados del objeto.
|
|
||||||
// Controla las colisiones con los límites del área de juego y actualiza sprite y colisionador.
|
|
||||||
void move();
|
|
||||||
|
|
||||||
// Actualiza el contador de tiempo de vida del objeto.
|
|
||||||
// Si el tiempo de vida es mayor a 0, lo decrementa. Si llega a 0, desactiva el objeto.
|
|
||||||
void updateTimeToLive();
|
|
||||||
|
|
||||||
// Calcula la zona de aparición de la máquina de café
|
|
||||||
static auto getCoffeeMachineSpawn(int player_x, int item_width, int area_width, int margin = 2) -> int;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string> // Para string, basic_string
|
#include <string> // Para string, basic_string
|
||||||
#include <utility>
|
#include <utility> // Para move
|
||||||
|
|
||||||
|
// --- Namespace Lang: gestión de idiomas y textos ---
|
||||||
namespace Lang {
|
namespace Lang {
|
||||||
// --- Códigos de idioma soportados ---
|
// --- Enums ---
|
||||||
enum class Code : int {
|
enum class Code : int {
|
||||||
SPANISH = 0,
|
SPANISH = 0, // Español
|
||||||
VALENCIAN = 1,
|
VALENCIAN = 1, // Valenciano
|
||||||
ENGLISH = 2
|
ENGLISH = 2 // Inglés
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estructura que representa un idioma ---
|
// --- Estructuras ---
|
||||||
struct Language {
|
struct Language {
|
||||||
Code code; // Código que identifica al idioma
|
Code code; // Código que identifica al idioma
|
||||||
std::string name; // Nombre que identifica el idioma
|
std::string name; // Nombre que identifica el idioma
|
||||||
@@ -21,7 +22,7 @@ struct Language {
|
|||||||
: code(c), name(std::move(n)), file_name(std::move(fn)) {}
|
: code(c), name(std::move(n)), file_name(std::move(fn)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Métodos ---
|
// --- Funciones ---
|
||||||
auto loadFromFile(const std::string &file_path) -> bool; // Carga los textos desde el fichero JSON especificado
|
auto loadFromFile(const std::string &file_path) -> bool; // Carga los textos desde el fichero JSON especificado
|
||||||
auto getText(const std::string &key) -> std::string; // Obtiene el texto por clave
|
auto getText(const std::string &key) -> std::string; // Obtiene el texto por clave
|
||||||
auto getNextLangCode(Code current_lang) -> Code; // Obtiene el código del siguiente idioma (circular)
|
auto getNextLangCode(Code current_lang) -> Code; // Obtiene el código del siguiente idioma (circular)
|
||||||
|
|||||||
@@ -17,5 +17,5 @@ auto main(int argc, char* argv[]) -> int {
|
|||||||
auto director = std::make_unique<Director>(argc, std::span<char*>(argv, argc));
|
auto director = std::make_unique<Director>(argc, std::span<char*>(argv, argc));
|
||||||
|
|
||||||
// Bucle principal
|
// Bucle principal
|
||||||
return director->run();
|
return Director::run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ auto ManageHiScoreTable::add(const HiScoreEntry &entry) -> int {
|
|||||||
sort();
|
sort();
|
||||||
|
|
||||||
// Encontrar la posición del nuevo elemento
|
// Encontrar la posición del nuevo elemento
|
||||||
auto it = std::find_if(table_.begin(), table_.end(), [&](const HiScoreEntry &e) { return e.name == entry.name &&
|
auto it = std::ranges::find_if(table_, [&](const HiScoreEntry &e) {
|
||||||
e.score == entry.score &&
|
return e.name == entry.name && e.score == entry.score && e.one_credit_complete == entry.one_credit_complete;
|
||||||
e.one_credit_complete == entry.one_credit_complete; });
|
});
|
||||||
|
|
||||||
int position = -1;
|
int position = -1;
|
||||||
if (it != table_.end()) {
|
if (it != table_.end()) {
|
||||||
@@ -66,7 +66,7 @@ void ManageHiScoreTable::sort() {
|
|||||||
auto operator()(const HiScoreEntry &a, const HiScoreEntry &b) const -> bool { return a.score > b.score; }
|
auto operator()(const HiScoreEntry &a, const HiScoreEntry &b) const -> bool { return a.score > b.score; }
|
||||||
} score_descending_comparator;
|
} score_descending_comparator;
|
||||||
|
|
||||||
std::sort(table_.begin(), table_.end(), score_descending_comparator);
|
std::ranges::sort(table_, score_descending_comparator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carga la tabla desde un fichero
|
// Carga la tabla desde un fichero
|
||||||
|
|||||||
@@ -3,15 +3,7 @@
|
|||||||
#include <string> // Para std::string
|
#include <string> // Para std::string
|
||||||
#include <vector> // Para std::vector
|
#include <vector> // Para std::vector
|
||||||
|
|
||||||
/*
|
// --- Estructuras ---
|
||||||
Esta clase sirve para añadir elementos HiScoreEntry a un vector (tabla), de manera
|
|
||||||
que la tabla siempre está ordenada.
|
|
||||||
|
|
||||||
Además tiene un método para dejar la tabla con sus valores iniciales y métodos para
|
|
||||||
leer y escribir la tabla a un fichero.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// --- Estructura para las entradas de la tabla de records ---
|
|
||||||
struct HiScoreEntry {
|
struct HiScoreEntry {
|
||||||
std::string name; // Nombre
|
std::string name; // Nombre
|
||||||
int score; // Puntuación
|
int score; // Puntuación
|
||||||
@@ -22,7 +14,8 @@ struct HiScoreEntry {
|
|||||||
: name(n.substr(0, 6)), score(s), one_credit_complete(occ) {}
|
: name(n.substr(0, 6)), score(s), one_credit_complete(occ) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
using Table = std::vector<HiScoreEntry>;
|
// --- Tipos ---
|
||||||
|
using Table = std::vector<HiScoreEntry>; // Tabla de puntuaciones
|
||||||
|
|
||||||
// --- Clase ManageHiScoreTable ---
|
// --- Clase ManageHiScoreTable ---
|
||||||
class ManageHiScoreTable {
|
class ManageHiScoreTable {
|
||||||
@@ -30,10 +23,10 @@ class ManageHiScoreTable {
|
|||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr int NO_ENTRY = -1;
|
static constexpr int NO_ENTRY = -1;
|
||||||
|
|
||||||
// Constructor y destructor
|
// --- Constructor y destructor ---
|
||||||
explicit ManageHiScoreTable(Table &table)
|
explicit ManageHiScoreTable(Table &table) // Constructor con referencia a tabla
|
||||||
: table_(table) {}
|
: table_(table) {}
|
||||||
~ManageHiScoreTable() = default;
|
~ManageHiScoreTable() = default; // Destructor
|
||||||
|
|
||||||
// --- Métodos públicos ---
|
// --- Métodos públicos ---
|
||||||
void clear(); // Resetea la tabla a los valores por defecto
|
void clear(); // Resetea la tabla a los valores por defecto
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint32, SDL_Event
|
#include <SDL3/SDL.h> // Para Uint32, SDL_Event
|
||||||
|
|
||||||
|
// --- Namespace Mouse: gestión del ratón ---
|
||||||
namespace Mouse {
|
namespace Mouse {
|
||||||
// --- Variables de estado del cursor ---
|
// --- Variables de estado del cursor ---
|
||||||
extern Uint32 cursor_hide_time; // Tiempo en milisegundos para ocultar el cursor tras inactividad
|
extern Uint32 cursor_hide_time; // Tiempo en milisegundos para ocultar el cursor tras inactividad
|
||||||
extern Uint32 last_mouse_move_time; // Última vez (en ms) que el ratón se movió
|
extern Uint32 last_mouse_move_time; // Última vez (en ms) que el ratón se movió
|
||||||
extern bool cursor_visible; // Indica si el cursor está visible
|
extern bool cursor_visible; // Indica si el cursor está visible
|
||||||
|
|
||||||
// --- Gestión de eventos y visibilidad ---
|
// --- Funciones ---
|
||||||
void handleEvent(const SDL_Event &event); // Procesa eventos de ratón (movimiento, clic, etc.)
|
void handleEvent(const SDL_Event &event); // Procesa eventos de ratón (movimiento, clic, etc.)
|
||||||
void updateCursorVisibility(); // Actualiza la visibilidad del cursor según la inactividad
|
void updateCursorVisibility(); // Actualiza la visibilidad del cursor según la inactividad
|
||||||
} // namespace Mouse
|
} // namespace Mouse
|
||||||
@@ -1,32 +1,32 @@
|
|||||||
#include "moving_sprite.h"
|
#include "moving_sprite.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos, Rotate rotate, float zoom_w, float zoom_h, SDL_FlipMode flip)
|
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos, Rotate rotate, float horizontal_zoom, float vertical_zoom, SDL_FlipMode flip)
|
||||||
: Sprite(texture, pos),
|
: Sprite(std::move(texture), pos),
|
||||||
|
rotate_(rotate),
|
||||||
|
flip_(flip),
|
||||||
x_(pos.x),
|
x_(pos.x),
|
||||||
y_(pos.y),
|
y_(pos.y),
|
||||||
rotate_(rotate),
|
horizontal_zoom_(horizontal_zoom),
|
||||||
horizontal_zoom_(zoom_w),
|
vertical_zoom_(vertical_zoom) {}
|
||||||
vertical_zoom_(zoom_h),
|
|
||||||
flip_(flip) {}
|
|
||||||
|
|
||||||
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos)
|
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos)
|
||||||
: Sprite(texture, pos),
|
: Sprite(std::move(texture), pos),
|
||||||
|
flip_(SDL_FLIP_NONE),
|
||||||
x_(pos.x),
|
x_(pos.x),
|
||||||
y_(pos.y),
|
y_(pos.y),
|
||||||
|
|
||||||
horizontal_zoom_(1.0F),
|
horizontal_zoom_(1.0F),
|
||||||
vertical_zoom_(1.0F),
|
vertical_zoom_(1.0F) {}
|
||||||
flip_(SDL_FLIP_NONE) {}
|
|
||||||
|
|
||||||
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture)
|
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture)
|
||||||
: Sprite(texture),
|
: Sprite(std::move(texture)),
|
||||||
|
flip_(SDL_FLIP_NONE),
|
||||||
horizontal_zoom_(1.0F),
|
horizontal_zoom_(1.0F),
|
||||||
vertical_zoom_(1.0F),
|
vertical_zoom_(1.0F) { Sprite::clear(); }
|
||||||
flip_(SDL_FLIP_NONE) { Sprite::clear(); }
|
|
||||||
|
|
||||||
// Reinicia todas las variables
|
// Reinicia todas las variables
|
||||||
void MovingSprite::clear() {
|
void MovingSprite::clear() {
|
||||||
|
|||||||
@@ -9,23 +9,21 @@
|
|||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Clase MovingSprite. Añade movimiento y efectos de rotación, zoom y flip al sprite
|
// --- Clase MovingSprite: añade movimiento y efectos de rotación, zoom y flip al sprite ---
|
||||||
class MovingSprite : public Sprite {
|
class MovingSprite : public Sprite {
|
||||||
public:
|
public:
|
||||||
// --- Estructura para la rotación ---
|
// --- Estructuras ---
|
||||||
struct Rotate {
|
struct Rotate {
|
||||||
bool enabled{false}; // Indica si ha de rotar
|
bool enabled{false}; // Indica si ha de rotar
|
||||||
int counter{0}; // Contador
|
int counter{0}; // Contador
|
||||||
int speed{1}; // Velocidad de giro
|
int speed{1}; // Velocidad de giro
|
||||||
double angle{0.0}; // Ángulo para dibujarlo
|
double angle{0.0}; // Ángulo para dibujarlo
|
||||||
float amount{0.0F}; // Cantidad de grados a girar en cada iteración
|
float amount{0.0F}; // Cantidad de grados a girar en cada iteración
|
||||||
SDL_FPoint center; // Centro de rotación
|
SDL_FPoint center{.x = 0.0F, .y = 0.0F}; // Centro de rotación
|
||||||
|
|
||||||
Rotate() : center({0.0F, 0.0F}) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos, MovingSprite::Rotate rotate, float zoom_w, float zoom_h, SDL_FlipMode flip);
|
MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos, MovingSprite::Rotate rotate, float horizontal_zoom, float vertical_zoom, SDL_FlipMode flip);
|
||||||
MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos);
|
MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos);
|
||||||
explicit MovingSprite(std::shared_ptr<Texture> texture);
|
explicit MovingSprite(std::shared_ptr<Texture> texture);
|
||||||
~MovingSprite() override = default;
|
~MovingSprite() override = default;
|
||||||
@@ -36,58 +34,48 @@ class MovingSprite : public Sprite {
|
|||||||
void stop(); // Elimina el movimiento del sprite
|
void stop(); // Elimina el movimiento del sprite
|
||||||
void render() override; // Muestra el sprite por pantalla
|
void render() override; // Muestra el sprite por pantalla
|
||||||
|
|
||||||
// --- Getters de posición y movimiento ---
|
// --- Configuración ---
|
||||||
[[nodiscard]] auto getPosX() const -> float { return x_; }
|
void setPos(SDL_FRect rect); // Establece la posición y el tamaño del objeto
|
||||||
[[nodiscard]] auto getPosY() const -> float { return y_; }
|
void setPos(float pos_x, float pos_y); // Establece la posición del objeto
|
||||||
[[nodiscard]] auto getVelX() const -> float { return vx_; }
|
void setPosX(float pos_x); // Establece la posición X
|
||||||
[[nodiscard]] auto getVelY() const -> float { return vy_; }
|
void setPosY(float pos_y); // Establece la posición Y
|
||||||
[[nodiscard]] auto getAccelX() const -> float { return ax_; }
|
void setVelX(float value) { vx_ = value; } // Establece la velocidad X
|
||||||
[[nodiscard]] auto getAccelY() const -> float { return ay_; }
|
void setVelY(float value) { vy_ = value; } // Establece la velocidad Y
|
||||||
|
void setAccelX(float value) { ax_ = value; } // Establece la aceleración X
|
||||||
|
void setAccelY(float value) { ay_ = value; } // Establece la aceleración Y
|
||||||
|
void setHorizontalZoom(float value) { horizontal_zoom_ = value; } // Establece el zoom horizontal
|
||||||
|
void setVerticalZoom(float value) { vertical_zoom_ = value; } // Establece el zoom vertical
|
||||||
|
void setAngle(double value) { rotate_.angle = value; } // Establece el ángulo
|
||||||
|
void setRotatingCenter(SDL_FPoint point) { rotate_.center = point; } // Establece el centro de rotación
|
||||||
|
void setRotate(bool enable); // Activa o desactiva el efecto de rotación
|
||||||
|
void setRotateSpeed(int value) { rotate_.speed = std::max(1, value); } // Establece la velocidad de rotación
|
||||||
|
void setRotateAmount(double value) { rotate_.amount = value; } // Establece la cantidad de rotación
|
||||||
|
void switchRotate() { rotate_.amount *= -1; } // Cambia el sentido de la rotación
|
||||||
|
void setFlip(SDL_FlipMode flip) { flip_ = flip; } // Establece el flip
|
||||||
|
void flip() { flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL; } // Cambia el flip
|
||||||
|
|
||||||
// --- Setters de movimiento ---
|
// --- Getters ---
|
||||||
void setVelX(float value) { vx_ = value; }
|
[[nodiscard]] auto getPosX() const -> float { return x_; } // Obtiene la posición X
|
||||||
void setVelY(float value) { vy_ = value; }
|
[[nodiscard]] auto getPosY() const -> float { return y_; } // Obtiene la posición Y
|
||||||
void setAccelX(float value) { ax_ = value; }
|
[[nodiscard]] auto getVelX() const -> float { return vx_; } // Obtiene la velocidad X
|
||||||
void setAccelY(float value) { ay_ = value; }
|
[[nodiscard]] auto getVelY() const -> float { return vy_; } // Obtiene la velocidad Y
|
||||||
|
[[nodiscard]] auto getAccelX() const -> float { return ax_; } // Obtiene la aceleración X
|
||||||
// --- Rotación ---
|
[[nodiscard]] auto getAccelY() const -> float { return ay_; } // Obtiene la aceleración Y
|
||||||
[[nodiscard]] auto isRotating() const -> bool { return rotate_.enabled; }
|
[[nodiscard]] auto isRotating() const -> bool { return rotate_.enabled; } // Verifica si está rotando
|
||||||
void setHorizontalZoom(float value) { horizontal_zoom_ = value; }
|
auto getFlip() -> SDL_FlipMode { return flip_; } // Obtiene el flip
|
||||||
void setVerticalZoom(float value) { vertical_zoom_ = value; }
|
|
||||||
void setAngle(double value) { rotate_.angle = value; }
|
|
||||||
void setRotatingCenter(SDL_FPoint point) { rotate_.center = point; }
|
|
||||||
void setRotate(bool enable); // Activa o desactiva el efecto de rotación
|
|
||||||
void setRotateSpeed(int value) { rotate_.speed = std::max(1, value); }
|
|
||||||
void setRotateAmount(double value) { rotate_.amount = value; }
|
|
||||||
void switchRotate() { rotate_.amount *= -1; } // Cambia el sentido de la rotación
|
|
||||||
|
|
||||||
// --- Flip ---
|
|
||||||
void setFlip(SDL_FlipMode flip) { flip_ = flip; }
|
|
||||||
void flip() { flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL; }
|
|
||||||
auto getFlip() -> SDL_FlipMode { return flip_; }
|
|
||||||
|
|
||||||
// --- Posición y tamaño ---
|
|
||||||
void setPos(SDL_FRect rect); // Establece la posición y el tamaño del objeto
|
|
||||||
void setPos(float pos_x, float pos_y); // Establece la posición del objeto
|
|
||||||
void setPosX(float pos_x); // Establece la posición X
|
|
||||||
void setPosY(float pos_y); // Establece la posición Y
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// --- Variables de posición y movimiento ---
|
// --- Variables de estado ---
|
||||||
float x_ = 0.0F; // Posición en el eje X
|
|
||||||
float y_ = 0.0F; // Posición en el eje Y
|
|
||||||
|
|
||||||
float vx_ = 0.0F; // Velocidad en el eje X. Cantidad de píxeles a desplazarse
|
|
||||||
float vy_ = 0.0F; // Velocidad en el eje Y. Cantidad de píxeles a desplazarse
|
|
||||||
|
|
||||||
float ax_ = 0.0F; // Aceleración en el eje X. Variación de la velocidad
|
|
||||||
float ay_ = 0.0F; // Aceleración en el eje Y. Variación de la velocidad
|
|
||||||
|
|
||||||
// --- Efectos visuales ---
|
|
||||||
Rotate rotate_; // Variables usadas para controlar la rotación del sprite
|
Rotate rotate_; // Variables usadas para controlar la rotación del sprite
|
||||||
|
SDL_FlipMode flip_; // Indica cómo se voltea el sprite
|
||||||
|
float x_ = 0.0F; // Posición en el eje X
|
||||||
|
float y_ = 0.0F; // Posición en el eje Y
|
||||||
|
float vx_ = 0.0F; // Velocidad en el eje X
|
||||||
|
float vy_ = 0.0F; // Velocidad en el eje Y
|
||||||
|
float ax_ = 0.0F; // Aceleración en el eje X
|
||||||
|
float ay_ = 0.0F; // Aceleración en el eje Y
|
||||||
float horizontal_zoom_; // Zoom aplicado a la anchura
|
float horizontal_zoom_; // Zoom aplicado a la anchura
|
||||||
float vertical_zoom_; // Zoom aplicado a la altura
|
float vertical_zoom_; // Zoom aplicado a la altura
|
||||||
SDL_FlipMode flip_; // Indica cómo se voltea el sprite
|
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void updateAngle() { rotate_.angle += rotate_.amount; } // Incrementa el valor del ángulo
|
void updateAngle() { rotate_.angle += rotate_.amount; } // Incrementa el valor del ángulo
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <fstream> // Para basic_ostream, operator<<, basic_ostream::operator<<, basic_ofstream, basic_istream, basic_ifstream, ifstream, ofstream
|
#include <fstream> // Para basic_ostream, operator<<, basic_ostream::operator<<, basic_ofstream, basic_istream, basic_ifstream, ifstream, ofstream
|
||||||
#include <functional> // Para function
|
#include <functional> // Para function
|
||||||
#include <map> // Para map, operator==, _Rb_tree_const_iterator
|
#include <map> // Para map, operator==, _Rb_tree_const_iterator
|
||||||
|
#include <ranges> // Para std::ranges::any_of
|
||||||
#include <stdexcept> // Para invalid_argument, out_of_range
|
#include <stdexcept> // Para invalid_argument, out_of_range
|
||||||
#include <string> // Para char_traits, stoi, operator==, operator<<, allocator, string, basic_string, operator<=>, getline
|
#include <string> // Para char_traits, stoi, operator==, operator<<, allocator, string, basic_string, operator<=>, getline
|
||||||
#include <utility> // Para swap, pair
|
#include <utility> // Para swap, pair
|
||||||
@@ -65,7 +66,7 @@ auto loadFromFile() -> bool {
|
|||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(file, line)) {
|
while (std::getline(file, line)) {
|
||||||
if (line.substr(0, 1) != "#") {
|
if (line.substr(0, 1) != "#") {
|
||||||
int pos = line.find("=");
|
int pos = line.find('=');
|
||||||
if (!set(line.substr(0, pos), line.substr(pos + 1, line.length()))) {
|
if (!set(line.substr(0, pos), line.substr(pos + 1, line.length()))) {
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Unknown parameter: %s", line.substr(0, pos).c_str());
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Unknown parameter: %s", line.substr(0, pos).c_str());
|
||||||
}
|
}
|
||||||
@@ -133,6 +134,7 @@ auto saveToFile() -> bool {
|
|||||||
file << "game.difficulty=" << static_cast<int>(settings.difficulty) << "\n";
|
file << "game.difficulty=" << static_cast<int>(settings.difficulty) << "\n";
|
||||||
file << "game.autofire=" << boolToString(settings.autofire) << "\n";
|
file << "game.autofire=" << boolToString(settings.autofire) << "\n";
|
||||||
file << "game.shutdown_enabled=" << boolToString(settings.shutdown_enabled) << "\n";
|
file << "game.shutdown_enabled=" << boolToString(settings.shutdown_enabled) << "\n";
|
||||||
|
file << "game.params_file=" << settings.params_file << "\n";
|
||||||
|
|
||||||
// Opciones de mandos
|
// Opciones de mandos
|
||||||
file << "\n## CONTROLLERS\n";
|
file << "\n## CONTROLLERS\n";
|
||||||
@@ -207,6 +209,7 @@ auto set(const std::string& var, const std::string& value) -> bool {
|
|||||||
}},
|
}},
|
||||||
{"game.autofire", [](const auto& val) { settings.autofire = stringToBool(val); }},
|
{"game.autofire", [](const auto& val) { settings.autofire = stringToBool(val); }},
|
||||||
{"game.shutdown_enabled", [](const auto& val) { settings.shutdown_enabled = stringToBool(val); }},
|
{"game.shutdown_enabled", [](const auto& val) { settings.shutdown_enabled = stringToBool(val); }},
|
||||||
|
{"game.params_file", [](const auto& val) { settings.params_file = val; }},
|
||||||
// Teclado
|
// Teclado
|
||||||
{"keyboard.player", [](const auto& val) { keyboard.player_id = static_cast<Player::Id>(stoi(val)); }}};
|
{"keyboard.player", [](const auto& val) { keyboard.player_id = static_cast<Player::Id>(stoi(val)); }}};
|
||||||
|
|
||||||
@@ -392,12 +395,10 @@ void GamepadManager::clearUnassignedGamepadSlots() {
|
|||||||
auto GamepadManager::isGamepadAssigned(
|
auto GamepadManager::isGamepadAssigned(
|
||||||
const std::shared_ptr<Input::Gamepad>& physical_gamepad,
|
const std::shared_ptr<Input::Gamepad>& physical_gamepad,
|
||||||
const std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) -> bool {
|
const std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) -> bool {
|
||||||
for (const auto& assigned : assigned_instances) {
|
return std::ranges::any_of(assigned_instances,
|
||||||
if (assigned == physical_gamepad) {
|
[&physical_gamepad](const auto& assigned) {
|
||||||
return true; // Encontrado, por lo tanto, ya está asignado.
|
return assigned == physical_gamepad;
|
||||||
}
|
});
|
||||||
}
|
|
||||||
return false; // No se encontró en la lista.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convierte un player id a texto segun Lang
|
// Convierte un player id a texto segun Lang
|
||||||
@@ -413,7 +414,7 @@ auto playerIdToString(Player::Id player_id) -> std::string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convierte un texto a player id segun Lang
|
// Convierte un texto a player id segun Lang
|
||||||
auto stringToPlayerId(std::string name) -> Player::Id {
|
auto stringToPlayerId(const std::string& name) -> Player::Id {
|
||||||
if (name == Lang::getText("[SERVICE_MENU] PLAYER1")) {
|
if (name == Lang::getText("[SERVICE_MENU] PLAYER1")) {
|
||||||
return Player::Id::PLAYER1;
|
return Player::Id::PLAYER1;
|
||||||
}
|
}
|
||||||
|
|||||||
114
source/options.h
114
source/options.h
@@ -11,83 +11,62 @@
|
|||||||
#include <stdexcept> // Para out_of_range, invalid_argument
|
#include <stdexcept> // Para out_of_range, invalid_argument
|
||||||
#include <string> // Para char_traits, string, allocator, operator==, swap, operator<<, basic_string, stoi
|
#include <string> // Para char_traits, string, allocator, operator==, swap, operator<<, basic_string, stoi
|
||||||
#include <string_view> // Para string_view
|
#include <string_view> // Para string_view
|
||||||
|
#include <utility> // Para swap
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
|
#include "defaults.h" // Para GameDefaults
|
||||||
#include "difficulty.h" // Para Code
|
#include "difficulty.h" // Para Code
|
||||||
#include "input.h" // Para Input
|
#include "input.h" // Para Input
|
||||||
#include "lang.h" // Para Code
|
#include "lang.h" // Para Code
|
||||||
#include "manage_hiscore_table.h" // Para ManageHiScoreTable, Table
|
#include "manage_hiscore_table.h" // Para ManageHiScoreTable, Table
|
||||||
#include "player.h" // Para Player
|
#include "player.h" // Para Player
|
||||||
|
|
||||||
|
// --- Namespace Options: gestión de configuración y opciones del juego ---
|
||||||
namespace Options {
|
namespace Options {
|
||||||
|
|
||||||
// --- Opciones de ventana ---
|
// --- Estructuras ---
|
||||||
struct Window {
|
struct Window {
|
||||||
std::string caption; // Texto que aparece en la barra de título de la ventana
|
std::string caption = GameDefaults::Options::WINDOW_CAPTION; // Texto que aparece en la barra de título de la ventana
|
||||||
int zoom{2}; // Valor por el que se multiplica el tamaño de la ventana
|
int zoom = GameDefaults::Options::WINDOW_ZOOM; // Valor por el que se multiplica el tamaño de la ventana
|
||||||
int max_zoom{2}; // Tamaño máximo para que la ventana no sea mayor que la pantalla
|
int max_zoom = GameDefaults::Options::WINDOW_MAX_ZOOM; // Tamaño máximo para que la ventana no sea mayor que la pantalla
|
||||||
|
|
||||||
// Constructor por defecto con valores iniciales
|
|
||||||
Window()
|
|
||||||
: caption("Coffee Crisis Arcade Edition") {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones de vídeo ---
|
|
||||||
struct Video {
|
struct Video {
|
||||||
SDL_ScaleMode scale_mode{SDL_ScaleMode::SDL_SCALEMODE_NEAREST}; // Filtro usado para el escalado de la imagen
|
SDL_ScaleMode scale_mode = GameDefaults::Options::VIDEO_SCALE_MODE; // Filtro usado para el escalado de la imagen
|
||||||
bool fullscreen{false}; // Indica si se usa pantalla completa
|
bool fullscreen = GameDefaults::Options::VIDEO_FULLSCREEN; // Indica si se usa pantalla completa
|
||||||
bool vsync{true}; // Indica si se usa vsync
|
bool vsync = GameDefaults::Options::VIDEO_VSYNC; // Indica si se usa vsync
|
||||||
bool integer_scale{true}; // Indica si se usa escalado entero
|
bool integer_scale = GameDefaults::Options::VIDEO_INTEGER_SCALE; // Indica si se usa escalado entero
|
||||||
bool shaders{false}; // Indica si se usan shaders para los filtros de vídeo
|
bool shaders = GameDefaults::Options::VIDEO_SHADERS; // Indica si se usan shaders para los filtros de vídeo
|
||||||
std::string info; // Información sobre el modo de vídeo
|
std::string info; // Información sobre el modo de vídeo
|
||||||
|
|
||||||
// Constructor por defecto con valores iniciales
|
|
||||||
Video() = default;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones de música ---
|
|
||||||
struct Music {
|
struct Music {
|
||||||
bool enabled{true}; // Indica si la música suena o no
|
bool enabled = GameDefaults::Options::MUSIC_ENABLED; // Indica si la música suena o no
|
||||||
int volume{100}; // Volumen de la música
|
int volume = GameDefaults::Options::MUSIC_VOLUME; // Volumen de la música
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
Music() = default;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones de sonido ---
|
|
||||||
struct Sound {
|
struct Sound {
|
||||||
bool enabled{true}; // Indica si los sonidos suenan o no
|
bool enabled = GameDefaults::Options::SOUND_ENABLED; // Indica si los sonidos suenan o no
|
||||||
int volume{100}; // Volumen de los sonidos
|
int volume = GameDefaults::Options::SOUND_VOLUME; // Volumen de los sonidos
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
Sound() = default;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones de audio ---
|
|
||||||
struct Audio {
|
struct Audio {
|
||||||
Music music; // Opciones para la música
|
Music music; // Opciones para la música
|
||||||
Sound sound; // Opciones para los efectos de sonido
|
Sound sound; // Opciones para los efectos de sonido
|
||||||
bool enabled{true}; // Indica si el audio está activo o no
|
bool enabled = GameDefaults::Options::AUDIO_ENABLED; // Indica si el audio está activo o no
|
||||||
int volume{100}; // Volumen general del audio
|
int volume = GameDefaults::Options::AUDIO_VOLUME; // Volumen general del audio
|
||||||
|
|
||||||
// Constructor por defecto
|
|
||||||
Audio() = default;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones de configuración ---
|
|
||||||
struct Settings {
|
struct Settings {
|
||||||
Difficulty::Code difficulty{Difficulty::Code::NORMAL}; // Dificultad del juego
|
Difficulty::Code difficulty = Difficulty::Code::NORMAL; // Dificultad del juego
|
||||||
Lang::Code language{Lang::Code::VALENCIAN}; // Idioma usado en el juego
|
Lang::Code language = Lang::Code::VALENCIAN; // Idioma usado en el juego
|
||||||
bool autofire{true}; // Indicador de autofire
|
bool autofire = GameDefaults::Options::SETTINGS_AUTOFIRE; // Indicador de autofire
|
||||||
bool shutdown_enabled{false}; // Especifica si se puede apagar el sistema
|
bool shutdown_enabled = GameDefaults::Options::SETTINGS_SHUTDOWN_ENABLED; // Especifica si se puede apagar el sistema
|
||||||
Table hi_score_table; // Tabla de mejores puntuaciones
|
Table hi_score_table; // Tabla de mejores puntuaciones
|
||||||
std::vector<int> glowing_entries; // Últimas posiciones de entrada en la tabla
|
std::vector<int> glowing_entries = {ManageHiScoreTable::NO_ENTRY, ManageHiScoreTable::NO_ENTRY}; // Últimas posiciones de entrada en la tabla
|
||||||
std::string config_file; // Ruta al fichero donde guardar la configuración y las opciones del juego
|
std::string config_file; // Ruta al fichero donde guardar la configuración y las opciones del juego
|
||||||
std::string controllers_file; // Ruta al fichero con las configuraciones de los mandos
|
std::string controllers_file; // Ruta al fichero con las configuraciones de los mandos
|
||||||
|
std::string params_file = GameDefaults::Options::PARAMS_FILE; // Ruta al fichero de parámetros del juego
|
||||||
// Constructor por defecto con valores iniciales
|
|
||||||
Settings()
|
|
||||||
: glowing_entries({ManageHiScoreTable::NO_ENTRY, ManageHiScoreTable::NO_ENTRY}) {}
|
|
||||||
|
|
||||||
// Reinicia las últimas entradas de puntuación
|
// Reinicia las últimas entradas de puntuación
|
||||||
void clearLastHiScoreEntries() {
|
void clearLastHiScoreEntries() {
|
||||||
@@ -96,7 +75,6 @@ struct Settings {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estructura para gamepad individual ---
|
|
||||||
struct Gamepad {
|
struct Gamepad {
|
||||||
std::shared_ptr<Input::Gamepad> instance = nullptr; // Referencia al mando
|
std::shared_ptr<Input::Gamepad> instance = nullptr; // Referencia al mando
|
||||||
std::string name; // Nombre del mando
|
std::string name; // Nombre del mando
|
||||||
@@ -107,7 +85,7 @@ struct Gamepad {
|
|||||||
: player_id(custom_player_id) {}
|
: player_id(custom_player_id) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Manager para los gamepads ---
|
// --- Clases ---
|
||||||
class GamepadManager {
|
class GamepadManager {
|
||||||
public:
|
public:
|
||||||
void init() {
|
void init() {
|
||||||
@@ -144,7 +122,7 @@ class GamepadManager {
|
|||||||
const std::string& name) -> bool {
|
const std::string& name) -> bool {
|
||||||
try {
|
try {
|
||||||
auto& gamepad = getGamepad(player_id);
|
auto& gamepad = getGamepad(player_id);
|
||||||
gamepad.instance = instance;
|
gamepad.instance = std::move(instance);
|
||||||
gamepad.name = name;
|
gamepad.name = name;
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
@@ -161,7 +139,7 @@ class GamepadManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void resyncGamepadsWithPlayers() {
|
void resyncGamepadsWithPlayers() {
|
||||||
for (auto player : players_) {
|
for (const auto& player : players_) {
|
||||||
switch (player->getId()) {
|
switch (player->getId()) {
|
||||||
case Player::Id::PLAYER1:
|
case Player::Id::PLAYER1:
|
||||||
player->setGamepad(gamepads_[0].instance);
|
player->setGamepad(gamepads_[0].instance);
|
||||||
@@ -226,11 +204,11 @@ class GamepadManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPlayer(std::shared_ptr<Player> player) { players_.push_back(player); } // Añade un jugador a la lista
|
void addPlayer(const std::shared_ptr<Player>& player) { players_.push_back(player); } // Añade un jugador a la lista
|
||||||
void clearPlayers() { players_.clear(); } // Limpia la lista de jugadores
|
void clearPlayers() { players_.clear(); } // Limpia la lista de jugadores
|
||||||
|
|
||||||
// Asigna el mando a un jugador
|
// Asigna el mando a un jugador
|
||||||
void assignTo(Input::Gamepad gamepad, Player::Id player_id) {
|
void assignTo(const Input::Gamepad& gamepad, Player::Id player_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Asigna los mandos físicos basándose en la configuración actual de nombres.
|
// Asigna los mandos físicos basándose en la configuración actual de nombres.
|
||||||
@@ -279,8 +257,8 @@ struct Keyboard {
|
|||||||
Player::Id player_id = Player::Id::PLAYER1; // Jugador asociado al teclado
|
Player::Id player_id = Player::Id::PLAYER1; // Jugador asociado al teclado
|
||||||
std::vector<std::shared_ptr<Player>> players; // Punteros a los jugadores
|
std::vector<std::shared_ptr<Player>> players; // Punteros a los jugadores
|
||||||
|
|
||||||
void addPlayer(std::shared_ptr<Player> player) { players.push_back(player); } // Añade un jugador a la lista
|
void addPlayer(const std::shared_ptr<Player>& player) { players.push_back(player); } // Añade un jugador a la lista
|
||||||
void clearPlayers() { players.clear(); } // Limpia la lista de jugadores
|
void clearPlayers() { players.clear(); } // Limpia la lista de jugadores
|
||||||
|
|
||||||
// Asigna el teclado a un jugador
|
// Asigna el teclado a un jugador
|
||||||
void assignTo(Player::Id player_id) {
|
void assignTo(Player::Id player_id) {
|
||||||
@@ -291,17 +269,13 @@ struct Keyboard {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones pendientes de aplicar ---
|
|
||||||
struct PendingChanges {
|
struct PendingChanges {
|
||||||
Lang::Code new_language{Lang::Code::VALENCIAN}; // Idioma en espera de aplicar
|
Lang::Code new_language = Lang::Code::VALENCIAN; // Idioma en espera de aplicar
|
||||||
Difficulty::Code new_difficulty{Difficulty::Code::NORMAL}; // Dificultad en espera de aplicar
|
Difficulty::Code new_difficulty = Difficulty::Code::NORMAL; // Dificultad en espera de aplicar
|
||||||
bool has_pending_changes{false}; // Indica si hay cambios pendientes
|
bool has_pending_changes = false; // Indica si hay cambios pendientes
|
||||||
|
|
||||||
// Constructor por defecto con valores iniciales
|
|
||||||
PendingChanges() = default;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Variables globales ---
|
// --- Variables ---
|
||||||
extern Window window; // Opciones de la ventana
|
extern Window window; // Opciones de la ventana
|
||||||
extern Settings settings; // Opciones del juego
|
extern Settings settings; // Opciones del juego
|
||||||
extern Video video; // Opciones de vídeo
|
extern Video video; // Opciones de vídeo
|
||||||
@@ -310,7 +284,7 @@ extern GamepadManager gamepad_manager; // Manager de mandos para cada jugador
|
|||||||
extern Keyboard keyboard; // Opciones para el teclado
|
extern Keyboard keyboard; // Opciones para el teclado
|
||||||
extern PendingChanges pending_changes; // Opciones que se aplican al cerrar
|
extern PendingChanges pending_changes; // Opciones que se aplican al cerrar
|
||||||
|
|
||||||
// --- Funciones de configuración ---
|
// --- Funciones ---
|
||||||
void init(); // Inicializa las opciones del programa
|
void init(); // Inicializa las opciones del programa
|
||||||
void setConfigFile(const std::string& file_path); // Establece el fichero de configuración
|
void setConfigFile(const std::string& file_path); // Establece el fichero de configuración
|
||||||
void setControllersFile(const std::string& file_path); // Establece el fichero de configuración de mandos
|
void setControllersFile(const std::string& file_path); // Establece el fichero de configuración de mandos
|
||||||
@@ -321,7 +295,7 @@ void swapKeyboard();
|
|||||||
void swapControllers(); // Intercambia los jugadores asignados a los dos primeros mandos
|
void swapControllers(); // Intercambia los jugadores asignados a los dos primeros mandos
|
||||||
auto getPlayerWhoUsesKeyboard() -> Player::Id; // Averigua quién está usando el teclado
|
auto getPlayerWhoUsesKeyboard() -> Player::Id; // Averigua quién está usando el teclado
|
||||||
auto playerIdToString(Player::Id player_id) -> std::string; // Convierte un player id a texto segun Lang
|
auto playerIdToString(Player::Id player_id) -> std::string; // Convierte un player id a texto segun Lang
|
||||||
auto stringToPlayerId(std::string name) -> Player::Id; // Convierte un texto a player id segun Lang
|
auto stringToPlayerId(const std::string& name) -> Player::Id; // Convierte un texto a player id segun Lang
|
||||||
void applyPendingChanges(); // Aplica los cambios pendientes copiando los valores a sus variables
|
void applyPendingChanges(); // Aplica los cambios pendientes copiando los valores a sus variables
|
||||||
void checkPendingChanges(); // Verifica si hay cambios pendientes
|
void checkPendingChanges(); // Verifica si hay cambios pendientes
|
||||||
auto assignGamepadByName(const std::string& gamepad_name, Player::Id player_id) -> bool; // Buscar y asignar un mando disponible por nombre
|
auto assignGamepadByName(const std::string& gamepad_name, Player::Id player_id) -> bool; // Buscar y asignar un mando disponible por nombre
|
||||||
|
|||||||
335
source/param.cpp
335
source/param.cpp
@@ -2,23 +2,23 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogCategory, SDL_LogError, SDL_LogInfo
|
#include <SDL3/SDL.h> // Para SDL_LogCategory, SDL_LogError, SDL_LogInfo
|
||||||
|
|
||||||
#include <fstream> // Para basic_istream, basic_ifstream, ifstream
|
#include <fstream> // Para basic_istream, basic_ifstream, ifstream
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <sstream> // Para basic_istringstream
|
#include <sstream> // Para basic_istringstream
|
||||||
#include <stdexcept> // Para runtime_error
|
#include <stdexcept> // Para runtime_error
|
||||||
#include <string> // Para operator==, stoi, char_traits, string, ope...
|
#include <string> // Para operator==, stoi, char_traits, string, ope...
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "utils.h"
|
|
||||||
#include "ui/notifier.h" // Para Notifier::Position
|
#include "ui/notifier.h" // Para Notifier::Position
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
// Variable global - ahora se inicializa automáticamente con valores por defecto
|
// Variable global - ahora se inicializa automáticamente con valores por defecto
|
||||||
Param param;
|
Param param;
|
||||||
|
|
||||||
// Declaraciones de funciones privadas
|
// Declaraciones de funciones privadas
|
||||||
namespace {
|
namespace {
|
||||||
auto setParams(const std::string& var, const std::string& value) -> bool;
|
auto setParams(const std::string& var, const std::string& value) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementación del método privado de Param
|
// Implementación del método privado de Param
|
||||||
@@ -32,7 +32,7 @@ void Param::precalculateZones() {
|
|||||||
game.play_area.third_quarter_y = game.play_area.rect.h / 4 * 3;
|
game.play_area.third_quarter_y = game.play_area.rect.h / 4 * 3;
|
||||||
|
|
||||||
// gameArea - cálculos basados en width y height actuales
|
// gameArea - cálculos basados en width y height actuales
|
||||||
game.game_area.rect = {0, 0, game.width, game.height};
|
game.game_area.rect = {.x = 0, .y = 0, .w = game.width, .h = game.height};
|
||||||
game.game_area.center_x = game.game_area.rect.w / 2;
|
game.game_area.center_x = game.game_area.rect.w / 2;
|
||||||
game.game_area.first_quarter_x = game.game_area.rect.w / 4;
|
game.game_area.first_quarter_x = game.game_area.rect.w / 4;
|
||||||
game.game_area.third_quarter_x = game.game_area.rect.w / 4 * 3;
|
game.game_area.third_quarter_x = game.game_area.rect.w / 4 * 3;
|
||||||
@@ -45,7 +45,7 @@ void Param::precalculateZones() {
|
|||||||
void loadParamsFromFile(const std::string& file_path) {
|
void loadParamsFromFile(const std::string& file_path) {
|
||||||
// Los parámetros ya están inicializados con valores por defecto
|
// Los parámetros ya están inicializados con valores por defecto
|
||||||
// Solo necesitamos abrir el archivo y sobrescribir los valores que aparezcan
|
// Solo necesitamos abrir el archivo y sobrescribir los valores que aparezcan
|
||||||
|
|
||||||
std::ifstream file(file_path);
|
std::ifstream file(file_path);
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo abrir el archivo %s", file_path.c_str());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo abrir el archivo %s", file_path.c_str());
|
||||||
@@ -57,7 +57,7 @@ void loadParamsFromFile(const std::string& file_path) {
|
|||||||
std::string line;
|
std::string line;
|
||||||
std::string param_name;
|
std::string param_name;
|
||||||
std::string param_value;
|
std::string param_value;
|
||||||
|
|
||||||
while (std::getline(file, line)) {
|
while (std::getline(file, line)) {
|
||||||
// Elimina comentarios
|
// Elimina comentarios
|
||||||
auto comment_pos = line.find('#');
|
auto comment_pos = line.find('#');
|
||||||
@@ -82,153 +82,194 @@ void loadParamsFromFile(const std::string& file_path) {
|
|||||||
|
|
||||||
// Implementación local de setParams
|
// Implementación local de setParams
|
||||||
namespace {
|
namespace {
|
||||||
auto setParams(const std::string& var, const std::string& value) -> bool {
|
auto setParams(const std::string& var, const std::string& value) -> bool {
|
||||||
// Mapas estáticos para diferentes tipos de parámetros
|
// Mapas estáticos para diferentes tipos de parámetros
|
||||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> INT_PARAMS = {
|
static const std::unordered_map<std::string, std::function<void(const std::string&)>> INT_PARAMS = {
|
||||||
{"game.width", [](const std::string& v) { param.game.width = std::stoi(v); }},
|
{"game.width", [](const std::string& v) { param.game.width = std::stoi(v); }},
|
||||||
{"game.height", [](const std::string& v) { param.game.height = std::stoi(v); }},
|
{"game.height", [](const std::string& v) { param.game.height = std::stoi(v); }},
|
||||||
{"game.item_size", [](const std::string& v) { param.game.item_size = std::stoi(v); }},
|
{"game.item_size", [](const std::string& v) { param.game.item_size = std::stoi(v); }},
|
||||||
{"game.play_area.rect.x", [](const std::string& v) { param.game.play_area.rect.x = std::stoi(v); }},
|
{"game.play_area.rect.x", [](const std::string& v) { param.game.play_area.rect.x = std::stoi(v); }},
|
||||||
{"game.play_area.rect.y", [](const std::string& v) { param.game.play_area.rect.y = std::stoi(v); }},
|
{"game.play_area.rect.y", [](const std::string& v) { param.game.play_area.rect.y = std::stoi(v); }},
|
||||||
{"game.play_area.rect.w", [](const std::string& v) { param.game.play_area.rect.w = std::stoi(v); }},
|
{"game.play_area.rect.w", [](const std::string& v) { param.game.play_area.rect.w = std::stoi(v); }},
|
||||||
{"game.play_area.rect.h", [](const std::string& v) { param.game.play_area.rect.h = std::stoi(v); }},
|
{"game.play_area.rect.h", [](const std::string& v) { param.game.play_area.rect.h = std::stoi(v); }},
|
||||||
{"game.name_entry_idle_time", [](const std::string& v) { param.game.name_entry_idle_time = std::stoi(v); }},
|
{"game.name_entry_idle_time", [](const std::string& v) { param.game.name_entry_idle_time = std::stoi(v); }},
|
||||||
{"game.name_entry_total_time", [](const std::string& v) { param.game.name_entry_total_time = std::stoi(v); }},
|
{"game.name_entry_total_time", [](const std::string& v) { param.game.name_entry_total_time = std::stoi(v); }},
|
||||||
{"game.hit_stop_ms", [](const std::string& v) { param.game.hit_stop_ms = std::stoi(v); }},
|
{"game.hit_stop_ms", [](const std::string& v) { param.game.hit_stop_ms = std::stoi(v); }},
|
||||||
{"fade.num_squares_width", [](const std::string& v) { param.fade.num_squares_width = std::stoi(v); }},
|
{"fade.num_squares_width", [](const std::string& v) { param.fade.num_squares_width = std::stoi(v); }},
|
||||||
{"fade.num_squares_height", [](const std::string& v) { param.fade.num_squares_height = std::stoi(v); }},
|
{"fade.num_squares_height", [](const std::string& v) { param.fade.num_squares_height = std::stoi(v); }},
|
||||||
{"fade.random_squares_delay", [](const std::string& v) { param.fade.random_squares_delay = std::stoi(v); }},
|
{"fade.random_squares_duration_ms", [](const std::string& v) { param.fade.random_squares_duration_ms = std::stoi(v); }},
|
||||||
{"fade.random_squares_mult", [](const std::string& v) { param.fade.random_squares_mult = std::stoi(v); }},
|
{"fade.post_duration_ms", [](const std::string& v) { param.fade.post_duration_ms = std::stoi(v); }},
|
||||||
{"fade.post_duration", [](const std::string& v) { param.fade.post_duration = std::stoi(v); }},
|
{"fade.venetian_size", [](const std::string& v) { param.fade.venetian_size = std::stoi(v); }},
|
||||||
{"fade.venetian_size", [](const std::string& v) { param.fade.venetian_size = std::stoi(v); }},
|
{"scoreboard.rect.x", [](const std::string& v) { param.scoreboard.rect.x = std::stoi(v); }},
|
||||||
{"scoreboard.rect.x", [](const std::string& v) { param.scoreboard.rect.x = std::stoi(v); }},
|
{"scoreboard.rect.y", [](const std::string& v) { param.scoreboard.rect.y = std::stoi(v); }},
|
||||||
{"scoreboard.rect.y", [](const std::string& v) { param.scoreboard.rect.y = std::stoi(v); }},
|
{"scoreboard.rect.w", [](const std::string& v) { param.scoreboard.rect.w = std::stoi(v); }},
|
||||||
{"scoreboard.rect.w", [](const std::string& v) { param.scoreboard.rect.w = std::stoi(v); }},
|
{"scoreboard.rect.h", [](const std::string& v) { param.scoreboard.rect.h = std::stoi(v); }},
|
||||||
{"scoreboard.rect.h", [](const std::string& v) { param.scoreboard.rect.h = std::stoi(v); }},
|
{"scoreboard.skip_countdown_value", [](const std::string& v) { param.scoreboard.skip_countdown_value = std::stoi(v); }},
|
||||||
{"scoreboard.skip_countdown_value", [](const std::string& v) { param.scoreboard.skip_countdown_value = std::stoi(v); }},
|
{"title.press_start_position", [](const std::string& v) { param.title.press_start_position = std::stoi(v); }},
|
||||||
{"title.press_start_position", [](const std::string& v) { param.title.press_start_position = std::stoi(v); }},
|
{"title.title_duration", [](const std::string& v) { param.title.title_duration = std::stoi(v); }},
|
||||||
{"title.title_duration", [](const std::string& v) { param.title.title_duration = std::stoi(v); }},
|
{"title.arcade_edition_position", [](const std::string& v) { param.title.arcade_edition_position = std::stoi(v); }},
|
||||||
{"title.arcade_edition_position", [](const std::string& v) { param.title.arcade_edition_position = std::stoi(v); }},
|
{"title.title_c_c_position", [](const std::string& v) { param.title.title_c_c_position = std::stoi(v); }},
|
||||||
{"title.title_c_c_position", [](const std::string& v) { param.title.title_c_c_position = std::stoi(v); }},
|
{"intro.text_distance_from_bottom", [](const std::string& v) { param.intro.text_distance_from_bottom = std::stoi(v); }}};
|
||||||
{"intro.text_distance_from_bottom", [](const std::string& v) { param.intro.text_distance_from_bottom = std::stoi(v); }}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> COLOR_PARAMS = {
|
static const std::unordered_map<std::string, std::function<void(const std::string&)>> COLOR_PARAMS = {
|
||||||
{"fade.color", [](const std::string& v) { param.fade.color = Color::fromHex(v); }},
|
{"fade.color", [](const std::string& v) { param.fade.color = Color::fromHex(v); }},
|
||||||
{"scoreboard.separator_color", [](const std::string& v) { param.scoreboard.separator_color = Color::fromHex(v); }},
|
{"scoreboard.separator_color", [](const std::string& v) { param.scoreboard.separator_color = Color::fromHex(v); }},
|
||||||
{"scoreboard.easy_color", [](const std::string& v) { param.scoreboard.easy_color = Color::fromHex(v); }},
|
{"scoreboard.easy_color", [](const std::string& v) { param.scoreboard.easy_color = Color::fromHex(v); }},
|
||||||
{"scoreboard.normal_color", [](const std::string& v) { param.scoreboard.normal_color = Color::fromHex(v); }},
|
{"scoreboard.normal_color", [](const std::string& v) { param.scoreboard.normal_color = Color::fromHex(v); }},
|
||||||
{"scoreboard.hard_color", [](const std::string& v) { param.scoreboard.hard_color = Color::fromHex(v); }},
|
{"scoreboard.hard_color", [](const std::string& v) { param.scoreboard.hard_color = Color::fromHex(v); }},
|
||||||
{"scoreboard.text_color1", [](const std::string& v) { param.scoreboard.text_color1 = Color::fromHex(v); }},
|
{"scoreboard.text_color1", [](const std::string& v) { param.scoreboard.text_color1 = Color::fromHex(v); }},
|
||||||
{"scoreboard.text_color2", [](const std::string& v) { param.scoreboard.text_color2 = Color::fromHex(v); }},
|
{"scoreboard.text_color2", [](const std::string& v) { param.scoreboard.text_color2 = Color::fromHex(v); }},
|
||||||
{"title.bg_color", [](const std::string& v) { param.title.bg_color = Color::fromHex(v); }},
|
{"title.bg_color", [](const std::string& v) { param.title.bg_color = Color::fromHex(v); }},
|
||||||
{"background.attenuate_color", [](const std::string& v) { param.background.attenuate_color = Color::fromHex(v); }},
|
{"background.attenuate_color", [](const std::string& v) { param.background.attenuate_color = Color::fromHex(v); }},
|
||||||
{"notification.color", [](const std::string& v) { param.notification.color = Color::fromHex(v); }},
|
{"notification.color", [](const std::string& v) { param.notification.color = Color::fromHex(v); }},
|
||||||
{"service_menu.title_color", [](const std::string& v) { param.service_menu.title_color = Color::fromHex(v); }},
|
{"service_menu.title_color", [](const std::string& v) { param.service_menu.title_color = Color::fromHex(v); }},
|
||||||
{"service_menu.text_color", [](const std::string& v) { param.service_menu.text_color = Color::fromHex(v); }},
|
{"service_menu.text_color", [](const std::string& v) { param.service_menu.text_color = Color::fromHex(v); }},
|
||||||
{"service_menu.selected_color", [](const std::string& v) { param.service_menu.selected_color = Color::fromHex(v); }},
|
{"service_menu.selected_color", [](const std::string& v) { param.service_menu.selected_color = Color::fromHex(v); }},
|
||||||
{"service_menu.bg_color", [](const std::string& v) { param.service_menu.bg_color = Color::fromHex(v); }},
|
{"service_menu.bg_color", [](const std::string& v) { param.service_menu.bg_color = Color::fromHex(v); }},
|
||||||
{"service_menu.window_message.bg_color", [](const std::string& v) { param.service_menu.window_message.bg_color = Color::fromHex(v); }},
|
{"service_menu.window_message.bg_color", [](const std::string& v) { param.service_menu.window_message.bg_color = Color::fromHex(v); }},
|
||||||
{"service_menu.window_message.border_color", [](const std::string& v) { param.service_menu.window_message.border_color = Color::fromHex(v); }},
|
{"service_menu.window_message.border_color", [](const std::string& v) { param.service_menu.window_message.border_color = Color::fromHex(v); }},
|
||||||
{"service_menu.window_message.title_color", [](const std::string& v) { param.service_menu.window_message.title_color = Color::fromHex(v); }},
|
{"service_menu.window_message.title_color", [](const std::string& v) { param.service_menu.window_message.title_color = Color::fromHex(v); }},
|
||||||
{"service_menu.window_message.text_color", [](const std::string& v) { param.service_menu.window_message.text_color = Color::fromHex(v); }},
|
{"service_menu.window_message.text_color", [](const std::string& v) { param.service_menu.window_message.text_color = Color::fromHex(v); }},
|
||||||
{"intro.bg_color", [](const std::string& v) { param.intro.bg_color = Color::fromHex(v); }},
|
{"intro.bg_color", [](const std::string& v) { param.intro.bg_color = Color::fromHex(v); }},
|
||||||
{"intro.card_color", [](const std::string& v) { param.intro.card_color = Color::fromHex(v); }},
|
{"intro.card_color", [](const std::string& v) { param.intro.card_color = Color::fromHex(v); }},
|
||||||
{"intro.shadow_color", [](const std::string& v) { param.intro.shadow_color = Color::fromHex(v); }},
|
{"intro.shadow_color", [](const std::string& v) { param.intro.shadow_color = Color::fromHex(v); }},
|
||||||
{"debug.color", [](const std::string& v) { param.debug.color = Color::fromHex(v); }},
|
{"debug.color", [](const std::string& v) { param.debug.color = Color::fromHex(v); }},
|
||||||
{"resource.color", [](const std::string& v) { param.resource.color = Color::fromHex(v); }},
|
{"resource.color", [](const std::string& v) { param.resource.color = Color::fromHex(v); }},
|
||||||
{"player.one_coffee_shirt[0].darkest", [](const std::string& v) { param.player.one_coffee_shirt[0].darkest = Color::fromHex(v); }},
|
{"game.item_text_outline_color", [](const std::string& v) { param.game.item_text_outline_color = Color::fromHex(v); }},
|
||||||
{"player.one_coffee_shirt[0].dark", [](const std::string& v) { param.player.one_coffee_shirt[0].dark = Color::fromHex(v); }},
|
{"player.default_shirt[0].darkest", [](const std::string& v) { param.player.default_shirt[0].darkest = Color::fromHex(v); }},
|
||||||
{"player.one_coffee_shirt[0].base", [](const std::string& v) { param.player.one_coffee_shirt[0].base = Color::fromHex(v); }},
|
{"player.default_shirt[0].dark", [](const std::string& v) { param.player.default_shirt[0].dark = Color::fromHex(v); }},
|
||||||
{"player.one_coffee_shirt[0].light", [](const std::string& v) { param.player.one_coffee_shirt[0].light = Color::fromHex(v); }},
|
{"player.default_shirt[0].base", [](const std::string& v) { param.player.default_shirt[0].base = Color::fromHex(v); }},
|
||||||
{"player.one_coffee_shirt[1].darkest", [](const std::string& v) { param.player.one_coffee_shirt[1].darkest = Color::fromHex(v); }},
|
{"player.default_shirt[0].light", [](const std::string& v) { param.player.default_shirt[0].light = Color::fromHex(v); }},
|
||||||
{"player.one_coffee_shirt[1].dark", [](const std::string& v) { param.player.one_coffee_shirt[1].dark = Color::fromHex(v); }},
|
{"player.default_shirt[1].darkest", [](const std::string& v) { param.player.default_shirt[1].darkest = Color::fromHex(v); }},
|
||||||
{"player.one_coffee_shirt[1].base", [](const std::string& v) { param.player.one_coffee_shirt[1].base = Color::fromHex(v); }},
|
{"player.default_shirt[1].dark", [](const std::string& v) { param.player.default_shirt[1].dark = Color::fromHex(v); }},
|
||||||
{"player.one_coffee_shirt[1].light", [](const std::string& v) { param.player.one_coffee_shirt[1].light = Color::fromHex(v); }},
|
{"player.default_shirt[1].base", [](const std::string& v) { param.player.default_shirt[1].base = Color::fromHex(v); }},
|
||||||
{"player.two_coffee_shirt[0].darkest", [](const std::string& v) { param.player.two_coffee_shirt[0].darkest = Color::fromHex(v); }},
|
{"player.default_shirt[1].light", [](const std::string& v) { param.player.default_shirt[1].light = Color::fromHex(v); }},
|
||||||
{"player.two_coffee_shirt[0].dark", [](const std::string& v) { param.player.two_coffee_shirt[0].dark = Color::fromHex(v); }},
|
{"player.one_coffee_shirt[0].darkest", [](const std::string& v) { param.player.one_coffee_shirt[0].darkest = Color::fromHex(v); }},
|
||||||
{"player.two_coffee_shirt[0].base", [](const std::string& v) { param.player.two_coffee_shirt[0].base = Color::fromHex(v); }},
|
{"player.one_coffee_shirt[0].dark", [](const std::string& v) { param.player.one_coffee_shirt[0].dark = Color::fromHex(v); }},
|
||||||
{"player.two_coffee_shirt[0].light", [](const std::string& v) { param.player.two_coffee_shirt[0].light = Color::fromHex(v); }},
|
{"player.one_coffee_shirt[0].base", [](const std::string& v) { param.player.one_coffee_shirt[0].base = Color::fromHex(v); }},
|
||||||
{"player.two_coffee_shirt[1].darkest", [](const std::string& v) { param.player.two_coffee_shirt[1].darkest = Color::fromHex(v); }},
|
{"player.one_coffee_shirt[0].light", [](const std::string& v) { param.player.one_coffee_shirt[0].light = Color::fromHex(v); }},
|
||||||
{"player.two_coffee_shirt[1].dark", [](const std::string& v) { param.player.two_coffee_shirt[1].dark = Color::fromHex(v); }},
|
{"player.one_coffee_shirt[1].darkest", [](const std::string& v) { param.player.one_coffee_shirt[1].darkest = Color::fromHex(v); }},
|
||||||
{"player.two_coffee_shirt[1].base", [](const std::string& v) { param.player.two_coffee_shirt[1].base = Color::fromHex(v); }},
|
{"player.one_coffee_shirt[1].dark", [](const std::string& v) { param.player.one_coffee_shirt[1].dark = Color::fromHex(v); }},
|
||||||
{"player.two_coffee_shirt[1].light", [](const std::string& v) { param.player.two_coffee_shirt[1].light = Color::fromHex(v); }}
|
{"player.one_coffee_shirt[1].base", [](const std::string& v) { param.player.one_coffee_shirt[1].base = Color::fromHex(v); }},
|
||||||
};
|
{"player.one_coffee_shirt[1].light", [](const std::string& v) { param.player.one_coffee_shirt[1].light = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[0].darkest", [](const std::string& v) { param.player.two_coffee_shirt[0].darkest = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[0].dark", [](const std::string& v) { param.player.two_coffee_shirt[0].dark = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[0].base", [](const std::string& v) { param.player.two_coffee_shirt[0].base = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[0].light", [](const std::string& v) { param.player.two_coffee_shirt[0].light = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[1].darkest", [](const std::string& v) { param.player.two_coffee_shirt[1].darkest = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[1].dark", [](const std::string& v) { param.player.two_coffee_shirt[1].dark = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[1].base", [](const std::string& v) { param.player.two_coffee_shirt[1].base = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[1].light", [](const std::string& v) { param.player.two_coffee_shirt[1].light = Color::fromHex(v); }},
|
||||||
|
{"player.outline_color[0]", [](const std::string& v) { param.player.outline_color[0] = Color::fromHex(v); }},
|
||||||
|
{"player.outline_color[1]", [](const std::string& v) { param.player.outline_color[1] = Color::fromHex(v); }}};
|
||||||
|
|
||||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> BOOL_PARAMS = {
|
static const std::unordered_map<std::string, std::function<void(const std::string&)>> BOOL_PARAMS = {
|
||||||
{"game.hit_stop", [](const std::string& v) { param.game.hit_stop = stringToBool(v); }},
|
{"game.hit_stop", [](const std::string& v) { param.game.hit_stop = stringToBool(v); }},
|
||||||
{"scoreboard.separator_autocolor", [](const std::string& v) { param.scoreboard.separator_autocolor = stringToBool(v); }},
|
{"scoreboard.separator_autocolor", [](const std::string& v) { param.scoreboard.separator_autocolor = stringToBool(v); }},
|
||||||
{"scoreboard.text_autocolor", [](const std::string& v) { param.scoreboard.text_autocolor = stringToBool(v); }},
|
{"scoreboard.text_autocolor", [](const std::string& v) { param.scoreboard.text_autocolor = stringToBool(v); }},
|
||||||
{"balloon.bouncing_sound", [](const std::string& v) { param.balloon.bouncing_sound = stringToBool(v); }},
|
{"balloon.bouncing_sound", [](const std::string& v) { param.balloon.bouncing_sound = stringToBool(v); }},
|
||||||
{"notification.sound", [](const std::string& v) { param.notification.sound = stringToBool(v); }},
|
{"notification.sound", [](const std::string& v) { param.notification.sound = stringToBool(v); }},
|
||||||
{"service_menu.drop_shadow", [](const std::string& v) { param.service_menu.drop_shadow = stringToBool(v); }}
|
{"service_menu.drop_shadow", [](const std::string& v) { param.service_menu.drop_shadow = stringToBool(v); }}};
|
||||||
};
|
|
||||||
|
|
||||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> FLOAT_PARAMS = {
|
static const std::unordered_map<std::string, std::function<void(const std::string&)>> FLOAT_PARAMS = {
|
||||||
{"balloon.settings[0].vel", [](const std::string& v) { param.balloon.settings.at(0).vel = std::stof(v); }},
|
{"balloon.settings[0].vel", [](const std::string& v) { param.balloon.settings.at(0).vel = std::stof(v); }},
|
||||||
{"balloon.settings[0].grav", [](const std::string& v) { param.balloon.settings.at(0).grav = std::stof(v); }},
|
{"balloon.settings[0].grav", [](const std::string& v) { param.balloon.settings.at(0).grav = std::stof(v); }},
|
||||||
{"balloon.settings[1].vel", [](const std::string& v) { param.balloon.settings.at(1).vel = std::stof(v); }},
|
{"balloon.settings[1].vel", [](const std::string& v) { param.balloon.settings.at(1).vel = std::stof(v); }},
|
||||||
{"balloon.settings[1].grav", [](const std::string& v) { param.balloon.settings.at(1).grav = std::stof(v); }},
|
{"balloon.settings[1].grav", [](const std::string& v) { param.balloon.settings.at(1).grav = std::stof(v); }},
|
||||||
{"balloon.settings[2].vel", [](const std::string& v) { param.balloon.settings.at(2).vel = std::stof(v); }},
|
{"balloon.settings[2].vel", [](const std::string& v) { param.balloon.settings.at(2).vel = std::stof(v); }},
|
||||||
{"balloon.settings[2].grav", [](const std::string& v) { param.balloon.settings.at(2).grav = std::stof(v); }},
|
{"balloon.settings[2].grav", [](const std::string& v) { param.balloon.settings.at(2).grav = std::stof(v); }},
|
||||||
{"balloon.settings[3].vel", [](const std::string& v) { param.balloon.settings.at(3).vel = std::stof(v); }},
|
{"balloon.settings[3].vel", [](const std::string& v) { param.balloon.settings.at(3).vel = std::stof(v); }},
|
||||||
{"balloon.settings[3].grav", [](const std::string& v) { param.balloon.settings.at(3).grav = std::stof(v); }},
|
{"balloon.settings[3].grav", [](const std::string& v) { param.balloon.settings.at(3).grav = std::stof(v); }},
|
||||||
{"tabe.min_spawn_time", [](const std::string& v) { param.tabe.min_spawn_time = std::stof(v); }},
|
{"tabe.min_spawn_time", [](const std::string& v) { param.tabe.min_spawn_time = std::stof(v); }},
|
||||||
{"tabe.max_spawn_time", [](const std::string& v) { param.tabe.max_spawn_time = std::stof(v); }},
|
{"tabe.max_spawn_time", [](const std::string& v) { param.tabe.max_spawn_time = std::stof(v); }},
|
||||||
{"service_menu.window_message.padding", [](const std::string& v) { param.service_menu.window_message.padding = std::stof(v); }},
|
{"service_menu.window_message.padding", [](const std::string& v) { param.service_menu.window_message.padding = std::stof(v); }},
|
||||||
{"service_menu.window_message.line_spacing", [](const std::string& v) { param.service_menu.window_message.line_spacing = std::stof(v); }},
|
{"service_menu.window_message.line_spacing", [](const std::string& v) { param.service_menu.window_message.line_spacing = std::stof(v); }},
|
||||||
{"service_menu.window_message.title_separator_spacing", [](const std::string& v) { param.service_menu.window_message.title_separator_spacing = std::stof(v); }},
|
{"service_menu.window_message.title_separator_spacing", [](const std::string& v) { param.service_menu.window_message.title_separator_spacing = std::stof(v); }},
|
||||||
{"service_menu.window_message.min_width", [](const std::string& v) { param.service_menu.window_message.min_width = std::stof(v); }},
|
{"service_menu.window_message.min_width", [](const std::string& v) { param.service_menu.window_message.min_width = std::stof(v); }},
|
||||||
{"service_menu.window_message.min_height", [](const std::string& v) { param.service_menu.window_message.min_height = std::stof(v); }},
|
{"service_menu.window_message.min_height", [](const std::string& v) { param.service_menu.window_message.min_height = std::stof(v); }},
|
||||||
{"service_menu.window_message.max_width_ratio", [](const std::string& v) { param.service_menu.window_message.max_width_ratio = std::stof(v); }},
|
{"service_menu.window_message.max_width_ratio", [](const std::string& v) { param.service_menu.window_message.max_width_ratio = std::stof(v); }},
|
||||||
{"service_menu.window_message.max_height_ratio", [](const std::string& v) { param.service_menu.window_message.max_height_ratio = std::stof(v); }},
|
{"service_menu.window_message.max_height_ratio", [](const std::string& v) { param.service_menu.window_message.max_height_ratio = std::stof(v); }},
|
||||||
{"service_menu.window_message.text_safety_margin", [](const std::string& v) { param.service_menu.window_message.text_safety_margin = std::stof(v); }},
|
{"service_menu.window_message.text_safety_margin", [](const std::string& v) { param.service_menu.window_message.text_safety_margin = std::stof(v); }},
|
||||||
{"service_menu.window_message.animation_duration", [](const std::string& v) { param.service_menu.window_message.animation_duration = std::stof(v); }}
|
{"service_menu.window_message.animation_duration", [](const std::string& v) { param.service_menu.window_message.animation_duration = std::stof(v); }}};
|
||||||
};
|
|
||||||
|
|
||||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> INT_PARAMS_EXTRA = {
|
static const std::unordered_map<std::string, std::function<void(const std::string&)>> INT_PARAMS_EXTRA = {};
|
||||||
};
|
|
||||||
|
|
||||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> STRING_PARAMS = {
|
// Colores válidos para globos
|
||||||
{"balloon.color[0]", [](const std::string& v) { param.balloon.color.at(0) = v; }},
|
static const std::unordered_map<std::string, bool> VALID_BALLOON_COLORS = {
|
||||||
{"balloon.color[1]", [](const std::string& v) { param.balloon.color.at(1) = v; }},
|
{"blue", true}, {"orange", true}, {"red", true}, {"green", true}
|
||||||
{"balloon.color[2]", [](const std::string& v) { param.balloon.color.at(2) = v; }},
|
};
|
||||||
{"balloon.color[3]", [](const std::string& v) { param.balloon.color.at(3) = v; }}
|
|
||||||
};
|
auto validateBalloonColor = [](const std::string& color) -> bool {
|
||||||
|
return VALID_BALLOON_COLORS.find(color) != VALID_BALLOON_COLORS.end();
|
||||||
|
};
|
||||||
|
|
||||||
// Lambda para intentar cada mapa de parámetros
|
static const std::unordered_map<std::string, std::function<void(const std::string&)>> STRING_PARAMS = {
|
||||||
auto try_map = [&](const auto& param_map) -> bool {
|
{"balloon.color[0]", [validateBalloonColor](const std::string& v) {
|
||||||
auto it = param_map.find(var);
|
if (!validateBalloonColor(v)) {
|
||||||
if (it != param_map.end()) {
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'blue' por defecto.", v.c_str());
|
||||||
it->second(value);
|
param.balloon.color.at(0) = "blue";
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Intentar con todos los mapas
|
|
||||||
if (try_map(INT_PARAMS) || try_map(COLOR_PARAMS) || try_map(BOOL_PARAMS) ||
|
|
||||||
try_map(FLOAT_PARAMS) || try_map(STRING_PARAMS)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Casos especiales que necesitan lógica personalizada
|
|
||||||
if (var == "notification.pos_h") {
|
|
||||||
if (value == "LEFT") {
|
|
||||||
param.notification.pos_h = Notifier::Position::LEFT;
|
|
||||||
} else if (value == "MIDDLE") {
|
|
||||||
param.notification.pos_h = Notifier::Position::MIDDLE;
|
|
||||||
} else {
|
} else {
|
||||||
param.notification.pos_h = Notifier::Position::RIGHT;
|
param.balloon.color.at(0) = v;
|
||||||
}
|
}
|
||||||
|
}},
|
||||||
|
{"balloon.color[1]", [validateBalloonColor](const std::string& v) {
|
||||||
|
if (!validateBalloonColor(v)) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'orange' por defecto.", v.c_str());
|
||||||
|
param.balloon.color.at(1) = "orange";
|
||||||
|
} else {
|
||||||
|
param.balloon.color.at(1) = v;
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
{"balloon.color[2]", [validateBalloonColor](const std::string& v) {
|
||||||
|
if (!validateBalloonColor(v)) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'red' por defecto.", v.c_str());
|
||||||
|
param.balloon.color.at(2) = "red";
|
||||||
|
} else {
|
||||||
|
param.balloon.color.at(2) = v;
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
{"balloon.color[3]", [validateBalloonColor](const std::string& v) {
|
||||||
|
if (!validateBalloonColor(v)) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'green' por defecto.", v.c_str());
|
||||||
|
param.balloon.color.at(3) = "green";
|
||||||
|
} else {
|
||||||
|
param.balloon.color.at(3) = v;
|
||||||
|
}
|
||||||
|
}}};
|
||||||
|
|
||||||
|
// Lambda para intentar cada mapa de parámetros
|
||||||
|
auto try_map = [&](const auto& param_map) -> bool {
|
||||||
|
auto it = param_map.find(var);
|
||||||
|
if (it != param_map.end()) {
|
||||||
|
it->second(value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
if (var == "notification.pos_v") {
|
// Intentar con todos los mapas
|
||||||
param.notification.pos_v = value == "TOP" ? Notifier::Position::TOP : Notifier::Position::BOTTOM;
|
if (try_map(INT_PARAMS) || try_map(COLOR_PARAMS) || try_map(BOOL_PARAMS) ||
|
||||||
return true;
|
try_map(FLOAT_PARAMS) || try_map(STRING_PARAMS)) {
|
||||||
}
|
return true;
|
||||||
|
|
||||||
return false; // Parámetro no encontrado
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// Casos especiales que necesitan lógica personalizada
|
||||||
|
if (var == "notification.pos_h") {
|
||||||
|
if (value == "LEFT") {
|
||||||
|
param.notification.pos_h = Notifier::Position::LEFT;
|
||||||
|
} else if (value == "MIDDLE") {
|
||||||
|
param.notification.pos_h = Notifier::Position::MIDDLE;
|
||||||
|
} else {
|
||||||
|
param.notification.pos_h = Notifier::Position::RIGHT;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var == "notification.pos_v") {
|
||||||
|
param.notification.pos_v = value == "TOP" ? Notifier::Position::TOP : Notifier::Position::BOTTOM;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // Parámetro no encontrado
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
@@ -22,6 +22,7 @@ struct ParamGame {
|
|||||||
Uint32 speed = 15; // Este valor no estaba en el archivo de configuración
|
Uint32 speed = 15; // Este valor no estaba en el archivo de configuración
|
||||||
bool hit_stop = GameDefaults::Game::HIT_STOP;
|
bool hit_stop = GameDefaults::Game::HIT_STOP;
|
||||||
Uint32 hit_stop_ms = GameDefaults::Game::HIT_STOP_MS;
|
Uint32 hit_stop_ms = GameDefaults::Game::HIT_STOP_MS;
|
||||||
|
Color item_text_outline_color;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros del fade ---
|
// --- Parámetros del fade ---
|
||||||
@@ -29,9 +30,8 @@ struct ParamFade {
|
|||||||
Color color = Color::fromHex(GameDefaults::Fade::COLOR);
|
Color color = Color::fromHex(GameDefaults::Fade::COLOR);
|
||||||
float num_squares_width = GameDefaults::Fade::NUM_SQUARES_WIDTH;
|
float num_squares_width = GameDefaults::Fade::NUM_SQUARES_WIDTH;
|
||||||
float num_squares_height = GameDefaults::Fade::NUM_SQUARES_HEIGHT;
|
float num_squares_height = GameDefaults::Fade::NUM_SQUARES_HEIGHT;
|
||||||
int random_squares_delay = GameDefaults::Fade::RANDOM_SQUARES_DELAY;
|
int random_squares_duration_ms = GameDefaults::Fade::RANDOM_SQUARES_DURATION_MS;
|
||||||
int random_squares_mult = GameDefaults::Fade::RANDOM_SQUARES_MULT;
|
int post_duration_ms = GameDefaults::Fade::POST_DURATION_MS;
|
||||||
int post_duration = GameDefaults::Fade::POST_DURATION;
|
|
||||||
float venetian_size = GameDefaults::Fade::VENETIAN_SIZE;
|
float venetian_size = GameDefaults::Fade::VENETIAN_SIZE;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ struct ParamBalloon {
|
|||||||
float vel;
|
float vel;
|
||||||
|
|
||||||
// Constructor por defecto
|
// Constructor por defecto
|
||||||
constexpr Settings(float grav_val = 0.0f, float vel_val = 0.0f)
|
constexpr Settings(float grav_val = 0.0F, float vel_val = 0.0F)
|
||||||
: grav(grav_val), vel(vel_val) {}
|
: grav(grav_val), vel(vel_val) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -168,26 +168,54 @@ struct ParamPlayer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Inicialización con valores por defecto
|
// Inicialización con valores por defecto
|
||||||
std::array<Shirt, 2> one_coffee_shirt = {{Shirt(Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_DARKEST),
|
const Shirt default_player0_shirt = Shirt(
|
||||||
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_DARK),
|
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER0_DARKEST),
|
||||||
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_BASE),
|
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER0_DARK),
|
||||||
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_LIGHT)),
|
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER0_BASE),
|
||||||
Shirt(Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_DARKEST),
|
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER0_LIGHT));
|
||||||
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_DARK),
|
|
||||||
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_BASE),
|
|
||||||
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_LIGHT))}};
|
|
||||||
|
|
||||||
std::array<Shirt, 2> two_coffee_shirt = {{Shirt(Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_DARKEST),
|
const Shirt default_player1_shirt = Shirt(
|
||||||
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_DARK),
|
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER1_DARKEST),
|
||||||
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_BASE),
|
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER1_DARK),
|
||||||
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_LIGHT)),
|
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER1_BASE),
|
||||||
Shirt(Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_DARKEST),
|
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER1_LIGHT));
|
||||||
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_DARK),
|
|
||||||
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_BASE),
|
std::array<Shirt, 2> default_shirt = {default_player0_shirt, default_player1_shirt};
|
||||||
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_LIGHT))}};
|
|
||||||
|
const Shirt one_coffee_player0_shirt = Shirt(
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_DARKEST),
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_DARK),
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_BASE),
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_LIGHT));
|
||||||
|
|
||||||
|
const Shirt one_coffee_player1_shirt = Shirt(
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_DARKEST),
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_DARK),
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_BASE),
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_LIGHT));
|
||||||
|
|
||||||
|
std::array<Shirt, 2> one_coffee_shirt = {one_coffee_player0_shirt, one_coffee_player1_shirt};
|
||||||
|
|
||||||
|
const Shirt two_coffee_player0_shirt = Shirt(
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_DARKEST),
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_DARK),
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_BASE),
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_LIGHT));
|
||||||
|
|
||||||
|
const Shirt two_coffee_player1_shirt = Shirt(
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_DARKEST),
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_DARK),
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_BASE),
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_LIGHT));
|
||||||
|
|
||||||
|
std::array<Shirt, 2> two_coffee_shirt = {two_coffee_player0_shirt, two_coffee_player1_shirt};
|
||||||
|
|
||||||
|
const Color outline_player0_color = Color::fromHex(GameDefaults::Player::OutlineColor::PLAYER0);
|
||||||
|
const Color outline_player1_color = Color::fromHex(GameDefaults::Player::OutlineColor::PLAYER1);
|
||||||
|
std::array<Color, 2> outline_color = {outline_player0_color, outline_player1_color};
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estructura principal para almacenar todos los parámetros del juego ---
|
// --- Estructura Param: almacena todos los parámetros del juego ---
|
||||||
struct Param {
|
struct Param {
|
||||||
ParamGame game;
|
ParamGame game;
|
||||||
ParamFade fade;
|
ParamFade fade;
|
||||||
@@ -207,10 +235,10 @@ struct Param {
|
|||||||
Param() {
|
Param() {
|
||||||
// Inicializar play_area usando los valores por defecto
|
// Inicializar play_area usando los valores por defecto
|
||||||
game.play_area.rect = {
|
game.play_area.rect = {
|
||||||
GameDefaults::Game::PLAY_AREA_X,
|
.x = GameDefaults::Game::PLAY_AREA_X,
|
||||||
GameDefaults::Game::PLAY_AREA_Y,
|
.y = GameDefaults::Game::PLAY_AREA_Y,
|
||||||
GameDefaults::Game::PLAY_AREA_W,
|
.w = GameDefaults::Game::PLAY_AREA_W,
|
||||||
GameDefaults::Game::PLAY_AREA_H};
|
.h = GameDefaults::Game::PLAY_AREA_H};
|
||||||
|
|
||||||
// Las zonas calculadas se inicializarán en precalculateZones()
|
// Las zonas calculadas se inicializarán en precalculateZones()
|
||||||
precalculateZones();
|
precalculateZones();
|
||||||
@@ -220,8 +248,8 @@ struct Param {
|
|||||||
void precalculateZones();
|
void precalculateZones();
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Variable global con los parámetros del juego ---
|
// --- Variables ---
|
||||||
extern Param param;
|
extern Param param; // Variable global con los parámetros del juego
|
||||||
|
|
||||||
// --- Funciones globales ---
|
// --- Funciones ---
|
||||||
void loadParamsFromFile(const std::string& file_path);
|
void loadParamsFromFile(const std::string& file_path); // Carga parámetros desde archivo
|
||||||
@@ -11,7 +11,7 @@ auto createPath(float start, float end, PathType type, float fixed_pos, int step
|
|||||||
|
|
||||||
for (int i = 0; i < steps; ++i) {
|
for (int i = 0; i < steps; ++i) {
|
||||||
double t = static_cast<double>(i) / (steps - 1);
|
double t = static_cast<double>(i) / (steps - 1);
|
||||||
double value = start + (end - start) * easing_function(t);
|
double value = start + ((end - start) * easing_function(t));
|
||||||
|
|
||||||
if ((start > 0 && end < 0) || (start < 0 && end > 0)) {
|
if ((start > 0 && end < 0) || (start < 0 && end > 0)) {
|
||||||
value = start + (end > 0 ? 1 : -1) * std::abs(end - start) * easing_function(t);
|
value = start + (end > 0 ? 1 : -1) * std::abs(end - start) * easing_function(t);
|
||||||
@@ -56,7 +56,7 @@ void PathSprite::addPath(Path path, bool centered) {
|
|||||||
|
|
||||||
switch (path_centered) {
|
switch (path_centered) {
|
||||||
case PathCentered::ON_X: {
|
case PathCentered::ON_X: {
|
||||||
const int X = path.spots.back().x - pos_.w / 2;
|
const int X = path.spots.back().x - (pos_.w / 2);
|
||||||
for (auto &spot : path.spots) {
|
for (auto &spot : path.spots) {
|
||||||
spot.x = X;
|
spot.x = X;
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ void PathSprite::addPath(Path path, bool centered) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PathCentered::ON_Y: {
|
case PathCentered::ON_Y: {
|
||||||
const int Y = path.spots.back().y - pos_.h / 2;
|
const int Y = path.spots.back().y - (pos_.h / 2);
|
||||||
for (auto &spot : path.spots) {
|
for (auto &spot : path.spots) {
|
||||||
spot.y = Y;
|
spot.y = Y;
|
||||||
}
|
}
|
||||||
@@ -83,8 +83,8 @@ void PathSprite::addPath(int start, int end, PathType type, int fixed_pos, int s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Añade un recorrido
|
// Añade un recorrido
|
||||||
void PathSprite::addPath(std::vector<SDL_FPoint> spots, int waiting_counter) {
|
void PathSprite::addPath(const std::vector<SDL_FPoint> &spots, int waiting_counter) {
|
||||||
paths_.emplace_back(std::move(spots), waiting_counter);
|
paths_.emplace_back(spots, waiting_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Habilita el objeto
|
// Habilita el objeto
|
||||||
|
|||||||
@@ -4,27 +4,27 @@
|
|||||||
|
|
||||||
#include <functional> // Para std::function
|
#include <functional> // Para std::function
|
||||||
#include <memory> // Para shared_ptr
|
#include <memory> // Para shared_ptr
|
||||||
#include <vector> // Para vector
|
#include <utility>
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "sprite.h" // Para Sprite
|
#include "sprite.h" // Para Sprite
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// --- Tipos de recorrido ---
|
// --- Enums ---
|
||||||
enum class PathType {
|
enum class PathType { // Tipos de recorrido
|
||||||
VERTICAL,
|
VERTICAL,
|
||||||
HORIZONTAL,
|
HORIZONTAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Centrado del recorrido ---
|
enum class PathCentered { // Centrado del recorrido
|
||||||
enum class PathCentered {
|
|
||||||
ON_X,
|
ON_X,
|
||||||
ON_Y,
|
ON_Y,
|
||||||
NONE,
|
NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estructura Path: define un recorrido para el sprite ---
|
// --- Estructuras ---
|
||||||
struct Path {
|
struct Path { // Define un recorrido para el sprite
|
||||||
std::vector<SDL_FPoint> spots; // Puntos por los que se desplazará el sprite
|
std::vector<SDL_FPoint> spots; // Puntos por los que se desplazará el sprite
|
||||||
int waiting_counter; // Tiempo de espera una vez en el destino
|
int waiting_counter; // Tiempo de espera una vez en el destino
|
||||||
bool on_destination = false; // Indica si ha llegado al destino
|
bool on_destination = false; // Indica si ha llegado al destino
|
||||||
@@ -36,15 +36,15 @@ struct Path {
|
|||||||
: spots(spots_init), waiting_counter(waiting_counter_init) {}
|
: spots(spots_init), waiting_counter(waiting_counter_init) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Devuelve un vector con los puntos que conforman la ruta
|
// --- Funciones ---
|
||||||
auto createPath(float start, float end, PathType type, float fixed_pos, int steps, const std::function<double(double)> &easing_function) -> std::vector<SDL_FPoint>;
|
auto createPath(float start, float end, PathType type, float fixed_pos, int steps, const std::function<double(double)> &easing_function) -> std::vector<SDL_FPoint>; // Devuelve un vector con los puntos que conforman la ruta
|
||||||
|
|
||||||
// --- Clase PathSprite: Sprite que sigue uno o varios recorridos ---
|
// --- Clase PathSprite: Sprite que sigue uno o varios recorridos ---
|
||||||
class PathSprite : public Sprite {
|
class PathSprite : public Sprite {
|
||||||
public:
|
public:
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
explicit PathSprite(std::shared_ptr<Texture> texture)
|
explicit PathSprite(std::shared_ptr<Texture> texture)
|
||||||
: Sprite(texture) {}
|
: Sprite(std::move(texture)) {}
|
||||||
~PathSprite() override = default;
|
~PathSprite() override = default;
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
@@ -53,7 +53,7 @@ class PathSprite : public Sprite {
|
|||||||
|
|
||||||
// --- Gestión de recorridos ---
|
// --- Gestión de recorridos ---
|
||||||
void addPath(Path path, bool centered = false); // Añade un recorrido (Path)
|
void addPath(Path path, bool centered = false); // Añade un recorrido (Path)
|
||||||
void addPath(std::vector<SDL_FPoint> spots, int waiting_counter = 0); // Añade un recorrido a partir de puntos
|
void addPath(const std::vector<SDL_FPoint> &spots, int waiting_counter = 0); // Añade un recorrido a partir de puntos
|
||||||
void addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easing_function, int waiting_counter = 0); // Añade un recorrido generado
|
void addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easing_function, int waiting_counter = 0); // Añade un recorrido generado
|
||||||
|
|
||||||
// --- Estado y control ---
|
// --- Estado y control ---
|
||||||
|
|||||||
@@ -5,18 +5,18 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
// Clase dedicada para manejar el sistema de pausa
|
// --- Clase PauseManager: maneja el sistema de pausa del juego ---
|
||||||
class PauseManager {
|
class PauseManager {
|
||||||
public:
|
public:
|
||||||
// Enum encapsulado dentro de la clase
|
// --- Enums ---
|
||||||
enum class Source : uint8_t {
|
enum class Source : uint8_t { // Fuentes de pausa
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
PLAYER = 1 << 0, // 0001
|
PLAYER = 1 << 0, // 0001
|
||||||
SERVICE_MENU = 1 << 1, // 0010
|
SERVICE_MENU = 1 << 1, // 0010
|
||||||
FOCUS_LOST = 1 << 2 // 0100
|
FOCUS_LOST = 1 << 2 // 0100
|
||||||
};
|
};
|
||||||
|
|
||||||
// Operadores para trabajar con las banderas (funciones friend)
|
// --- Operadores friend ---
|
||||||
friend auto operator|(Source a, Source b) -> Source {
|
friend auto operator|(Source a, Source b) -> Source {
|
||||||
return static_cast<Source>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
|
return static_cast<Source>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
|
||||||
}
|
}
|
||||||
@@ -42,27 +42,12 @@ class PauseManager {
|
|||||||
return a = a & b;
|
return a = a & b;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
// --- Constructor y destructor ---
|
||||||
Source flags_ = Source::NONE;
|
explicit PauseManager(std::function<void(bool)> callback = nullptr) // Constructor con callback opcional
|
||||||
std::function<void(bool)> on_pause_changed_callback_;
|
|
||||||
|
|
||||||
[[nodiscard]] auto hasFlag(Source flag) const -> bool {
|
|
||||||
return (flags_ & flag) != Source::NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void notifyPauseChanged() {
|
|
||||||
if (on_pause_changed_callback_) {
|
|
||||||
on_pause_changed_callback_(isPaused());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Constructor con callback opcional
|
|
||||||
explicit PauseManager(std::function<void(bool)> callback = nullptr)
|
|
||||||
: on_pause_changed_callback_(std::move(callback)) {}
|
: on_pause_changed_callback_(std::move(callback)) {}
|
||||||
|
|
||||||
// Establece/quita una fuente de pausa específica
|
// --- Métodos principales ---
|
||||||
void setFlag(Source source, bool enable) {
|
void setFlag(Source source, bool enable) { // Establece/quita una fuente de pausa específica
|
||||||
bool was_paused = isPaused();
|
bool was_paused = isPaused();
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
@@ -76,33 +61,29 @@ class PauseManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Métodos específicos para cada fuente
|
// --- Métodos específicos para cada fuente ---
|
||||||
void setPlayerPause(bool enable) { setFlag(Source::PLAYER, enable); }
|
void setPlayerPause(bool enable) { setFlag(Source::PLAYER, enable); }
|
||||||
void setServiceMenuPause(bool enable) { setFlag(Source::SERVICE_MENU, enable); }
|
void setServiceMenuPause(bool enable) { setFlag(Source::SERVICE_MENU, enable); }
|
||||||
void setFocusLossPause(bool enable) { setFlag(Source::FOCUS_LOST, enable); }
|
void setFocusLossPause(bool enable) { setFlag(Source::FOCUS_LOST, enable); }
|
||||||
|
|
||||||
// Toggle para el jugador (más común)
|
void togglePlayerPause() { setPlayerPause(!isPlayerPaused()); } // Toggle para el jugador (más común)
|
||||||
void togglePlayerPause() { setPlayerPause(!isPlayerPaused()); }
|
|
||||||
|
|
||||||
// Getters
|
// --- Getters ---
|
||||||
[[nodiscard]] auto isPaused() const -> bool { return flags_ != Source::NONE; }
|
[[nodiscard]] auto isPaused() const -> bool { return flags_ != Source::NONE; }
|
||||||
[[nodiscard]] auto isPlayerPaused() const -> bool { return hasFlag(Source::PLAYER); }
|
[[nodiscard]] auto isPlayerPaused() const -> bool { return hasFlag(Source::PLAYER); }
|
||||||
[[nodiscard]] auto isServiceMenuPaused() const -> bool { return hasFlag(Source::SERVICE_MENU); }
|
[[nodiscard]] auto isServiceMenuPaused() const -> bool { return hasFlag(Source::SERVICE_MENU); }
|
||||||
[[nodiscard]] auto isFocusLossPaused() const -> bool { return hasFlag(Source::FOCUS_LOST); }
|
[[nodiscard]] auto isFocusLossPaused() const -> bool { return hasFlag(Source::FOCUS_LOST); }
|
||||||
|
|
||||||
// Obtiene las banderas actuales
|
[[nodiscard]] auto getFlags() const -> Source { return flags_; } // Obtiene las banderas actuales
|
||||||
[[nodiscard]] auto getFlags() const -> Source { return flags_; }
|
|
||||||
|
|
||||||
// Limpia todas las pausas (útil para reset)
|
// --- Métodos de utilidad ---
|
||||||
void clearAll() {
|
void clearAll() { // Limpia todas las pausas (útil para reset)
|
||||||
if (isPaused()) {
|
if (isPaused()) {
|
||||||
flags_ = Source::NONE;
|
flags_ = Source::NONE;
|
||||||
notifyPauseChanged();
|
notifyPauseChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] auto getStatusString() const -> std::string { // Método para debug
|
||||||
// Método para debug
|
|
||||||
[[nodiscard]] auto getStatusString() const -> std::string {
|
|
||||||
if (flags_ == Source::NONE) {
|
if (flags_ == Source::NONE) {
|
||||||
return "Active";
|
return "Active";
|
||||||
}
|
}
|
||||||
@@ -133,9 +114,22 @@ class PauseManager {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
void setCallback(std::function<void(bool)> callback) { // Permite cambiar el callback en runtime
|
||||||
|
on_pause_changed_callback_ = std::move(callback);
|
||||||
|
}
|
||||||
|
|
||||||
// Permite cambiar el callback en runtime
|
private:
|
||||||
void setCallback(std::function<void(bool)> callback) {
|
// --- Variables ---
|
||||||
on_pause_changed_callback_ = callback;
|
Source flags_ = Source::NONE;
|
||||||
|
std::function<void(bool)> on_pause_changed_callback_;
|
||||||
|
|
||||||
|
// --- Métodos internos ---
|
||||||
|
[[nodiscard]] auto hasFlag(Source flag) const -> bool {
|
||||||
|
return (flags_ & flag) != Source::NONE;
|
||||||
|
}
|
||||||
|
void notifyPauseChanged() {
|
||||||
|
if (on_pause_changed_callback_) {
|
||||||
|
on_pause_changed_callback_(isPaused());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -22,17 +22,7 @@
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Player::Player(const Config &config)
|
Player::Player(const Config &config)
|
||||||
: player_sprite_(std::make_unique<AnimatedSprite>(config.texture.at(0), config.animations.at(0))),
|
: player_sprite_(std::make_unique<AnimatedSprite>(config.texture.at(0), config.animations.at(0))), power_sprite_(std::make_unique<AnimatedSprite>(config.texture.at(4), config.animations.at(1))), enter_name_(std::make_unique<EnterName>()), hi_score_table_(config.hi_score_table), glowing_entry_(config.glowing_entry), stage_info_(config.stage_info), play_area_(*config.play_area), id_(config.id), default_pos_x_(config.x), default_pos_y_(config.y), demo_(config.demo) {
|
||||||
power_sprite_(std::make_unique<AnimatedSprite>(config.texture.at(4), config.animations.at(1))),
|
|
||||||
enter_name_(std::make_unique<EnterName>()),
|
|
||||||
hi_score_table_(config.hi_score_table),
|
|
||||||
glowing_entry_(config.glowing_entry),
|
|
||||||
stage_info_(config.stage_info),
|
|
||||||
play_area_(*config.play_area),
|
|
||||||
id_(config.id),
|
|
||||||
default_pos_x_(config.x),
|
|
||||||
default_pos_y_(config.y),
|
|
||||||
demo_(config.demo) {
|
|
||||||
// Configura objetos
|
// Configura objetos
|
||||||
player_sprite_->addTexture(config.texture.at(1));
|
player_sprite_->addTexture(config.texture.at(1));
|
||||||
player_sprite_->addTexture(config.texture.at(2));
|
player_sprite_->addTexture(config.texture.at(2));
|
||||||
@@ -199,7 +189,7 @@ void Player::handlePlayingMovement() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Player::handleRecoverMovement() {
|
void Player::handleRecoverMovement() {
|
||||||
if (player_sprite_->getCurrentAnimationFrame() == 10) { playSound("voice_brbrbr.wav"); }
|
if (player_sprite_->getCurrentAnimationFrame() == 10) { playSound("voice_recover.wav"); }
|
||||||
if (player_sprite_->animationIsCompleted()) { setPlayingState(State::RESPAWNING); }
|
if (player_sprite_->animationIsCompleted()) { setPlayingState(State::RESPAWNING); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,7 +636,7 @@ void Player::setPlayingState(State state) {
|
|||||||
init();
|
init();
|
||||||
setInvulnerable(true);
|
setInvulnerable(true);
|
||||||
setScoreboardMode(Scoreboard::Mode::SCORE);
|
setScoreboardMode(Scoreboard::Mode::SCORE);
|
||||||
stage_info_->canCollectPower();
|
stage_info_->enablePowerCollection();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::CONTINUE: {
|
case State::CONTINUE: {
|
||||||
@@ -788,15 +778,30 @@ void Player::setInvulnerable(bool value) {
|
|||||||
|
|
||||||
// Monitoriza el estado
|
// Monitoriza el estado
|
||||||
void Player::updateInvulnerable() {
|
void Player::updateInvulnerable() {
|
||||||
if (playing_state_ == State::PLAYING) {
|
if (playing_state_ == State::PLAYING && invulnerable_) {
|
||||||
if (invulnerable_) {
|
if (invulnerable_counter_ > 0) {
|
||||||
if (invulnerable_counter_ > 0) {
|
--invulnerable_counter_;
|
||||||
--invulnerable_counter_;
|
|
||||||
invulnerable_counter_ % 8 > 3 ? player_sprite_->setActiveTexture(coffees_) : player_sprite_->setActiveTexture(3);
|
// Frecuencia fija de parpadeo (como el original)
|
||||||
} else {
|
constexpr int blink_speed = 8;
|
||||||
setInvulnerable(false);
|
|
||||||
player_sprite_->setActiveTexture(coffees_);
|
// Calcula proporción decreciente: menos textura blanca hacia el final
|
||||||
|
// Al inicio: 50-50, hacia el final: 70-30 (menos blanco)
|
||||||
|
float progress = 1.0f - (static_cast<float>(invulnerable_counter_) / INVULNERABLE_COUNTER);
|
||||||
|
int white_frames = static_cast<int>((0.5f - progress * 0.2f) * blink_speed);
|
||||||
|
|
||||||
|
// Alterna entre texturas con proporción variable
|
||||||
|
bool should_show_invulnerable = (invulnerable_counter_ % blink_speed) < white_frames;
|
||||||
|
size_t target_texture = should_show_invulnerable ? INVULNERABLE_TEXTURE : coffees_;
|
||||||
|
|
||||||
|
// Solo cambia textura si es diferente (optimización)
|
||||||
|
if (player_sprite_->getActiveTexture() != target_texture) {
|
||||||
|
player_sprite_->setActiveTexture(target_texture);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Fin de invulnerabilidad
|
||||||
|
setInvulnerable(false);
|
||||||
|
player_sprite_->setActiveTexture(coffees_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,15 +24,14 @@ class Player {
|
|||||||
static constexpr int WIDTH = 32; // Anchura
|
static constexpr int WIDTH = 32; // Anchura
|
||||||
static constexpr int HEIGHT = 32; // Altura
|
static constexpr int HEIGHT = 32; // Altura
|
||||||
|
|
||||||
// --- Id para los jugadores ---
|
// --- Enums ---
|
||||||
enum class Id : int {
|
enum class Id : int {
|
||||||
NO_PLAYER = -1,
|
NO_PLAYER = -1, // Sin jugador
|
||||||
BOTH_PLAYERS = 0,
|
BOTH_PLAYERS = 0, // Ambos jugadores
|
||||||
PLAYER1 = 1,
|
PLAYER1 = 1, // Jugador 1
|
||||||
PLAYER2 = 2
|
PLAYER2 = 2 // Jugador 2
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estados posibles del jugador ---
|
|
||||||
enum class State {
|
enum class State {
|
||||||
// Estados de movimiento
|
// Estados de movimiento
|
||||||
WALKING_LEFT, // Caminando hacia la izquierda
|
WALKING_LEFT, // Caminando hacia la izquierda
|
||||||
@@ -76,17 +75,18 @@ class Player {
|
|||||||
RESPAWNING, // Tras continuar y dar las gracias, otorga inmunidad y vuelve al juego
|
RESPAWNING, // Tras continuar y dar las gracias, otorga inmunidad y vuelve al juego
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- Estructuras ---
|
||||||
struct Config {
|
struct Config {
|
||||||
Id id;
|
Id id; // Identificador del jugador
|
||||||
float x;
|
float x; // Posición X inicial
|
||||||
int y;
|
int y; // Posición Y inicial
|
||||||
bool demo;
|
bool demo; // Modo demo
|
||||||
SDL_FRect *play_area; // Usamos puntero para mantener la referencia
|
SDL_FRect *play_area; // Área de juego (puntero para mantener referencia)
|
||||||
std::vector<std::shared_ptr<Texture>> texture;
|
std::vector<std::shared_ptr<Texture>> texture; // Texturas del jugador
|
||||||
std::vector<std::vector<std::string>> animations;
|
std::vector<std::vector<std::string>> animations; // Animaciones del jugador
|
||||||
Table *hi_score_table; // También como puntero para referencia
|
Table *hi_score_table; // Tabla de puntuaciones (puntero para referencia)
|
||||||
int *glowing_entry; // Puntero para mantener la referencia
|
int *glowing_entry; // Entrada brillante (puntero para mantener referencia)
|
||||||
IStageInfo *stage_info; // Puntero para el gestor de pantallas
|
IStageInfo *stage_info; // Gestor de pantallas (puntero)
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
@@ -184,21 +184,22 @@ class Player {
|
|||||||
void setScoreBoardPanel(Scoreboard::Id panel) { scoreboard_panel_ = panel; }
|
void setScoreBoardPanel(Scoreboard::Id panel) { scoreboard_panel_ = panel; }
|
||||||
void setScoreMultiplier(float value) { score_multiplier_ = value; }
|
void setScoreMultiplier(float value) { score_multiplier_ = value; }
|
||||||
void setWalkingState(State state) { walking_state_ = state; }
|
void setWalkingState(State state) { walking_state_ = state; }
|
||||||
|
|
||||||
void addCredit();
|
void addCredit();
|
||||||
void setGamepad(std::shared_ptr<Input::Gamepad> gamepad) { gamepad_ = gamepad; }
|
void setGamepad(std::shared_ptr<Input::Gamepad> gamepad) { gamepad_ = std::move(gamepad); }
|
||||||
[[nodiscard]] auto getGamepad() const -> std::shared_ptr<Input::Gamepad> { return gamepad_; }
|
[[nodiscard]] auto getGamepad() const -> std::shared_ptr<Input::Gamepad> { return gamepad_; }
|
||||||
void setUsesKeyboard(bool value) { uses_keyboard_ = value; }
|
void setUsesKeyboard(bool value) { uses_keyboard_ = value; }
|
||||||
[[nodiscard]] auto getUsesKeyboard() const -> bool { return uses_keyboard_; }
|
[[nodiscard]] auto getUsesKeyboard() const -> bool { return uses_keyboard_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr int POWERUP_COUNTER = 1500; // Duración del estado PowerUp
|
static constexpr int POWERUP_COUNTER = 1500; // Duración del estado PowerUp
|
||||||
static constexpr int INVULNERABLE_COUNTER = 200; // Duración del estado invulnerable
|
static constexpr int INVULNERABLE_COUNTER = 200; // Duración del estado invulnerable
|
||||||
static constexpr float BASE_SPEED = 1.5F; // Velocidad base del jugador
|
static constexpr size_t INVULNERABLE_TEXTURE = 3; // Textura usada durante invulnerabilidad
|
||||||
static constexpr int COOLING_DURATION = 50;
|
static constexpr float BASE_SPEED = 1.5F; // Velocidad base del jugador
|
||||||
static constexpr int COOLING_COMPLETE = 0;
|
static constexpr int COOLING_DURATION = 50; // Duración del enfriamiento tras disparar
|
||||||
static constexpr int WAITING_COUNTER = 1000;
|
static constexpr int COOLING_COMPLETE = 0; // Valor que indica enfriamiento completado
|
||||||
|
static constexpr int WAITING_COUNTER = 1000; // Tiempo de espera en estado de espera
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
std::unique_ptr<AnimatedSprite> player_sprite_; // Sprite para dibujar el jugador
|
std::unique_ptr<AnimatedSprite> player_sprite_; // Sprite para dibujar el jugador
|
||||||
@@ -208,25 +209,25 @@ class Player {
|
|||||||
Table *hi_score_table_ = nullptr; // Tabla de máximas puntuaciones
|
Table *hi_score_table_ = nullptr; // Tabla de máximas puntuaciones
|
||||||
int *glowing_entry_ = nullptr; // Entrada de la tabla de puntuaciones para hacerla brillar
|
int *glowing_entry_ = nullptr; // Entrada de la tabla de puntuaciones para hacerla brillar
|
||||||
IStageInfo *stage_info_; // Informacion de la pantalla actual
|
IStageInfo *stage_info_; // Informacion de la pantalla actual
|
||||||
std::string name_; // Nombre del jugador
|
|
||||||
std::string last_enter_name_; // Último nombre introducido en la tabla de puntuaciones
|
|
||||||
|
|
||||||
// --- Estructuras y enums ---
|
// --- Variables de estado ---
|
||||||
SDL_FRect play_area_; // Rectángulo con la zona de juego
|
SDL_FRect play_area_; // Rectángulo con la zona de juego
|
||||||
Circle collider_ = Circle(0, 0, 9); // Círculo de colisión del jugador
|
Circle collider_ = Circle(0, 0, 9); // Círculo de colisión del jugador
|
||||||
|
std::string name_; // Nombre del jugador
|
||||||
|
std::string last_enter_name_; // Último nombre introducido en la tabla de puntuaciones
|
||||||
Scoreboard::Id scoreboard_panel_ = Scoreboard::Id::LEFT; // Panel del marcador asociado al jugador
|
Scoreboard::Id scoreboard_panel_ = Scoreboard::Id::LEFT; // Panel del marcador asociado al jugador
|
||||||
Id id_; // Identificador para el jugador
|
Id id_; // Identificador para el jugador
|
||||||
State walking_state_ = State::WALKING_STOP; // Estado del jugador al moverse
|
State walking_state_ = State::WALKING_STOP; // Estado del jugador al moverse
|
||||||
State firing_state_ = State::FIRING_NONE; // Estado del jugador al disparar
|
State firing_state_ = State::FIRING_NONE; // Estado del jugador al disparar
|
||||||
State playing_state_ = State::WAITING; // Estado del jugador en el juego
|
State playing_state_ = State::WAITING; // Estado del jugador en el juego
|
||||||
|
|
||||||
// --- Variables float ---
|
Uint32 continue_ticks_ = 0; // Variable para poder cambiar el contador de continue en función del tiempo
|
||||||
float pos_x_ = 0.0F; // Posición en el eje X
|
Uint32 name_entry_ticks_ = 0; // Variable para poder cambiar el contador de poner nombre en función del tiempo
|
||||||
float default_pos_x_; // Posición inicial para el jugador
|
Uint32 showing_name_ticks_ = 0; // Tiempo en el que se entra al estado SHOWING_NAME
|
||||||
float vel_x_ = 0.0F; // Cantidad de píxeles a desplazarse en el eje X
|
float pos_x_ = 0.0F; // Posición en el eje X
|
||||||
float score_multiplier_ = 1.0F; // Multiplicador de puntos
|
float default_pos_x_; // Posición inicial para el jugador
|
||||||
|
float vel_x_ = 0.0F; // Cantidad de píxeles a desplazarse en el eje X
|
||||||
// --- Variables int ---
|
float score_multiplier_ = 1.0F; // Multiplicador de puntos
|
||||||
int pos_y_ = 0; // Posición en el eje Y
|
int pos_y_ = 0; // Posición en el eje Y
|
||||||
int default_pos_y_; // Posición inicial para el jugador
|
int default_pos_y_; // Posición inicial para el jugador
|
||||||
int vel_y_ = 0; // Cantidad de píxeles a desplazarse en el eje Y
|
int vel_y_ = 0; // Cantidad de píxeles a desplazarse en el eje Y
|
||||||
@@ -246,20 +247,13 @@ class Player {
|
|||||||
int step_counter_ = 0; // Cuenta los pasos para los estados en los que camina automáticamente
|
int step_counter_ = 0; // Cuenta los pasos para los estados en los que camina automáticamente
|
||||||
int credits_used_ = 0; // Indica el número de veces que ha continuado
|
int credits_used_ = 0; // Indica el número de veces que ha continuado
|
||||||
int waiting_counter_ = 0; // Contador para el estado de espera
|
int waiting_counter_ = 0; // Contador para el estado de espera
|
||||||
|
bool qualifies_for_high_score_ = false; // Indica si tiene una puntuación que le permite entrar en la tabla de records
|
||||||
// --- Variables Uint32 ---
|
bool invulnerable_ = true; // Indica si el jugador es invulnerable
|
||||||
Uint32 continue_ticks_ = 0; // Variable para poder cambiar el contador de continue en función del tiempo
|
bool extra_hit_ = false; // Indica si el jugador tiene un toque extra
|
||||||
Uint32 name_entry_ticks_ = 0; // Variable para poder cambiar el contador de poner nombre en función del tiempo
|
bool power_up_ = false; // Indica si el jugador tiene activo el modo PowerUp
|
||||||
Uint32 showing_name_ticks_ = 0; // Tiempo en el que se entra al estado SHOWING_NAME
|
bool demo_ = false; // Para que el jugador sepa si está en el modo demostración
|
||||||
|
bool game_completed_ = false; // Indica si ha completado el juego
|
||||||
// --- Flags booleanas ---
|
bool uses_keyboard_ = false; // Indica si usa el teclado como dispositivo de control
|
||||||
bool qualifies_for_high_score_ = false; // Indica si tiene una puntuación que le permite entrar en la tabla de records
|
|
||||||
bool invulnerable_ = true; // Indica si el jugador es invulnerable
|
|
||||||
bool extra_hit_ = false; // Indica si el jugador tiene un toque extra
|
|
||||||
bool power_up_ = false; // Indica si el jugador tiene activo el modo PowerUp
|
|
||||||
bool demo_ = false; // Para que el jugador sepa si está en el modo demostración
|
|
||||||
bool game_completed_ = false; // Indica si ha completado el juego
|
|
||||||
bool uses_keyboard_ = false; // Indica si usa el teclado como dispositivo de control
|
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void shiftColliders(); // Actualiza el círculo de colisión a la posición del jugador
|
void shiftColliders(); // Actualiza el círculo de colisión a la posición del jugador
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ void Resource::loadTextFilesQuiet() {
|
|||||||
for (const auto &l : list) {
|
for (const auto &l : list) {
|
||||||
auto name = getFileName(l);
|
auto name = getFileName(l);
|
||||||
// Buscar en nuestra lista y cargar directamente
|
// Buscar en nuestra lista y cargar directamente
|
||||||
auto it = std::find_if(text_files_.begin(), text_files_.end(), [&name](const auto &t) { return t.name == name; });
|
auto it = std::ranges::find_if(text_files_, [&name](const auto &t) { return t.name == name; });
|
||||||
if (it != text_files_.end()) {
|
if (it != text_files_.end()) {
|
||||||
it->text_file = Text::loadFile(l);
|
it->text_file = Text::loadFile(l);
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Text file loaded: %s", name.c_str());
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Text file loaded: %s", name.c_str());
|
||||||
@@ -109,9 +109,9 @@ void Resource::loadEssentialTextures() {
|
|||||||
for (const auto &file : texture_list) {
|
for (const auto &file : texture_list) {
|
||||||
auto name = getFileName(file);
|
auto name = getFileName(file);
|
||||||
// Solo cargar texturas esenciales
|
// Solo cargar texturas esenciales
|
||||||
if (std::find(ESSENTIAL_TEXTURES.begin(), ESSENTIAL_TEXTURES.end(), name) != ESSENTIAL_TEXTURES.end()) {
|
if (std::ranges::find(ESSENTIAL_TEXTURES, name) != ESSENTIAL_TEXTURES.end()) {
|
||||||
// Buscar en nuestra lista y cargar
|
// Buscar en nuestra lista y cargar
|
||||||
auto it = std::find_if(textures_.begin(), textures_.end(), [&name](const auto &t) { return t.name == name; });
|
auto it = std::ranges::find_if(textures_, [&name](const auto &t) { return t.name == name; });
|
||||||
if (it != textures_.end()) {
|
if (it != textures_.end()) {
|
||||||
it->texture = std::make_shared<Texture>(Screen::get()->getRenderer(), file);
|
it->texture = std::make_shared<Texture>(Screen::get()->getRenderer(), file);
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ void Resource::initResourceLists() {
|
|||||||
|
|
||||||
// Obtiene el sonido a partir de un nombre (con carga perezosa)
|
// Obtiene el sonido a partir de un nombre (con carga perezosa)
|
||||||
auto Resource::getSound(const std::string &name) -> JA_Sound_t * {
|
auto Resource::getSound(const std::string &name) -> JA_Sound_t * {
|
||||||
auto it = std::find_if(sounds_.begin(), sounds_.end(), [&name](const auto &s) { return s.name == name; });
|
auto it = std::ranges::find_if(sounds_, [&name](const auto &s) { return s.name == name; });
|
||||||
|
|
||||||
if (it != sounds_.end()) {
|
if (it != sounds_.end()) {
|
||||||
// Si está en modo lazy y no se ha cargado aún, lo carga ahora
|
// Si está en modo lazy y no se ha cargado aún, lo carga ahora
|
||||||
@@ -202,7 +202,7 @@ auto Resource::getSound(const std::string &name) -> JA_Sound_t * {
|
|||||||
|
|
||||||
// Obtiene la música a partir de un nombre (con carga perezosa)
|
// Obtiene la música a partir de un nombre (con carga perezosa)
|
||||||
auto Resource::getMusic(const std::string &name) -> JA_Music_t * {
|
auto Resource::getMusic(const std::string &name) -> JA_Music_t * {
|
||||||
auto it = std::find_if(musics_.begin(), musics_.end(), [&name](const auto &m) { return m.name == name; });
|
auto it = std::ranges::find_if(musics_, [&name](const auto &m) { return m.name == name; });
|
||||||
|
|
||||||
if (it != musics_.end()) {
|
if (it != musics_.end()) {
|
||||||
// Si está en modo lazy y no se ha cargado aún, lo carga ahora
|
// Si está en modo lazy y no se ha cargado aún, lo carga ahora
|
||||||
@@ -218,7 +218,7 @@ auto Resource::getMusic(const std::string &name) -> JA_Music_t * {
|
|||||||
|
|
||||||
// Obtiene la textura a partir de un nombre (con carga perezosa)
|
// Obtiene la textura a partir de un nombre (con carga perezosa)
|
||||||
auto Resource::getTexture(const std::string &name) -> std::shared_ptr<Texture> {
|
auto Resource::getTexture(const std::string &name) -> std::shared_ptr<Texture> {
|
||||||
auto it = std::find_if(textures_.begin(), textures_.end(), [&name](const auto &t) { return t.name == name; });
|
auto it = std::ranges::find_if(textures_, [&name](const auto &t) { return t.name == name; });
|
||||||
|
|
||||||
if (it != textures_.end()) {
|
if (it != textures_.end()) {
|
||||||
// Si está en modo lazy y no se ha cargado aún, lo carga ahora
|
// Si está en modo lazy y no se ha cargado aún, lo carga ahora
|
||||||
@@ -234,7 +234,7 @@ auto Resource::getTexture(const std::string &name) -> std::shared_ptr<Texture> {
|
|||||||
|
|
||||||
// Obtiene el fichero de texto a partir de un nombre (con carga perezosa)
|
// Obtiene el fichero de texto a partir de un nombre (con carga perezosa)
|
||||||
auto Resource::getTextFile(const std::string &name) -> std::shared_ptr<Text::File> {
|
auto Resource::getTextFile(const std::string &name) -> std::shared_ptr<Text::File> {
|
||||||
auto it = std::find_if(text_files_.begin(), text_files_.end(), [&name](const auto &t) { return t.name == name; });
|
auto it = std::ranges::find_if(text_files_, [&name](const auto &t) { return t.name == name; });
|
||||||
|
|
||||||
if (it != text_files_.end()) {
|
if (it != text_files_.end()) {
|
||||||
// Si está en modo lazy y no se ha cargado aún, lo carga ahora
|
// Si está en modo lazy y no se ha cargado aún, lo carga ahora
|
||||||
@@ -250,7 +250,7 @@ auto Resource::getTextFile(const std::string &name) -> std::shared_ptr<Text::Fil
|
|||||||
|
|
||||||
// Obtiene el objeto de texto a partir de un nombre (con carga perezosa)
|
// Obtiene el objeto de texto a partir de un nombre (con carga perezosa)
|
||||||
auto Resource::getText(const std::string &name) -> std::shared_ptr<Text> {
|
auto Resource::getText(const std::string &name) -> std::shared_ptr<Text> {
|
||||||
auto it = std::find_if(texts_.begin(), texts_.end(), [&name](const auto &t) { return t.name == name; });
|
auto it = std::ranges::find_if(texts_, [&name](const auto &t) { return t.name == name; });
|
||||||
|
|
||||||
if (it != texts_.end()) {
|
if (it != texts_.end()) {
|
||||||
// Si está en modo lazy y no se ha cargado aún, lo carga ahora
|
// Si está en modo lazy y no se ha cargado aún, lo carga ahora
|
||||||
@@ -266,7 +266,7 @@ auto Resource::getText(const std::string &name) -> std::shared_ptr<Text> {
|
|||||||
|
|
||||||
// Obtiene la animación a partir de un nombre (con carga perezosa)
|
// Obtiene la animación a partir de un nombre (con carga perezosa)
|
||||||
auto Resource::getAnimation(const std::string &name) -> AnimationsFileBuffer & {
|
auto Resource::getAnimation(const std::string &name) -> AnimationsFileBuffer & {
|
||||||
auto it = std::find_if(animations_.begin(), animations_.end(), [&name](const auto &a) { return a.name == name; });
|
auto it = std::ranges::find_if(animations_, [&name](const auto &a) { return a.name == name; });
|
||||||
|
|
||||||
if (it != animations_.end()) {
|
if (it != animations_.end()) {
|
||||||
// Si está en modo lazy y no se ha cargado aún (vector vacío), lo carga ahora
|
// Si está en modo lazy y no se ha cargado aún (vector vacío), lo carga ahora
|
||||||
@@ -346,18 +346,18 @@ auto Resource::loadTextLazy(const std::string &name) -> std::shared_ptr<Text> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<TextMapping> TEXT_MAPPINGS = {
|
const std::vector<TextMapping> TEXT_MAPPINGS = {
|
||||||
{"04b_25", "04b_25.png", "04b_25.txt"},
|
{.key = "04b_25", .texture_file = "04b_25.png", .text_file = "04b_25.txt"},
|
||||||
{"04b_25_2x", "04b_25_2x.png", "04b_25_2x.txt"},
|
{.key = "04b_25_2x", .texture_file = "04b_25_2x.png", .text_file = "04b_25_2x.txt"},
|
||||||
{"04b_25_metal", "04b_25_metal.png", "04b_25.txt"},
|
{.key = "04b_25_metal", .texture_file = "04b_25_metal.png", .text_file = "04b_25.txt"},
|
||||||
{"04b_25_grey", "04b_25_grey.png", "04b_25.txt"},
|
{.key = "04b_25_grey", .texture_file = "04b_25_grey.png", .text_file = "04b_25.txt"},
|
||||||
{"04b_25_flat", "04b_25_flat.png", "04b_25.txt"},
|
{.key = "04b_25_flat", .texture_file = "04b_25_flat.png", .text_file = "04b_25.txt"},
|
||||||
{"04b_25_reversed", "04b_25_reversed.png", "04b_25.txt"},
|
{.key = "04b_25_reversed", .texture_file = "04b_25_reversed.png", .text_file = "04b_25.txt"},
|
||||||
{"04b_25_flat_2x", "04b_25_flat_2x.png", "04b_25_2x.txt"},
|
{.key = "04b_25_flat_2x", .texture_file = "04b_25_flat_2x.png", .text_file = "04b_25_2x.txt"},
|
||||||
{"04b_25_reversed_2x", "04b_25_reversed_2x.png", "04b_25_2x.txt"},
|
{.key = "04b_25_reversed_2x", .texture_file = "04b_25_reversed_2x.png", .text_file = "04b_25_2x.txt"},
|
||||||
{"8bithud", "8bithud.png", "8bithud.txt"},
|
{.key = "8bithud", .texture_file = "8bithud.png", .text_file = "8bithud.txt"},
|
||||||
{"aseprite", "aseprite.png", "aseprite.txt"},
|
{.key = "aseprite", .texture_file = "aseprite.png", .text_file = "aseprite.txt"},
|
||||||
{"smb2", "smb2.png", "smb2.txt"},
|
{.key = "smb2", .texture_file = "smb2.png", .text_file = "smb2.txt"},
|
||||||
{"smb2_grad", "smb2_grad.png", "smb2.txt"}};
|
{.key = "smb2_grad", .texture_file = "smb2_grad.png", .text_file = "smb2.txt"}};
|
||||||
|
|
||||||
for (const auto &mapping : TEXT_MAPPINGS) {
|
for (const auto &mapping : TEXT_MAPPINGS) {
|
||||||
if (mapping.key == name) {
|
if (mapping.key == name) {
|
||||||
@@ -531,18 +531,18 @@ void Resource::createPlayerTextures() {
|
|||||||
|
|
||||||
// Configuración de jugadores y sus paletas
|
// Configuración de jugadores y sus paletas
|
||||||
struct PlayerConfig {
|
struct PlayerConfig {
|
||||||
std::string base_texture;
|
std::string base_texture;
|
||||||
std::vector<std::string> palette_files;
|
std::vector<std::string> palette_files;
|
||||||
std::string name_prefix;
|
std::string name_prefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<PlayerConfig> players = {
|
std::vector<PlayerConfig> players = {
|
||||||
{"player1.gif", {"player1_coffee1.pal", "player1_coffee2.pal", "player1_invencible.pal"}, "player1"},
|
{.base_texture = "player1.gif", .palette_files = {"player1_coffee1.pal", "player1_coffee2.pal", "player1_invencible.pal"}, .name_prefix = "player1"},
|
||||||
{"player2.gif", {"player2_coffee1.pal", "player2_coffee2.pal", "player2_invencible.pal"}, "player2"}};
|
{.base_texture = "player2.gif", .palette_files = {"player2_coffee1.pal", "player2_coffee2.pal", "player2_invencible.pal"}, .name_prefix = "player2"}};
|
||||||
|
|
||||||
// Bucle principal modificado para usar un índice (player_idx)
|
// Bucle principal
|
||||||
for (size_t player_idx = 0; player_idx < players.size(); ++player_idx) {
|
for (size_t player_idx = 0; player_idx < players.size(); ++player_idx) {
|
||||||
const auto &player = players[player_idx]; // Obtenemos el jugador actual
|
const auto &player = players[player_idx]; // Obtenemos el jugador actual
|
||||||
|
|
||||||
// Encontrar el archivo original de la textura
|
// Encontrar el archivo original de la textura
|
||||||
std::string texture_file_path;
|
std::string texture_file_path;
|
||||||
@@ -554,40 +554,52 @@ void Resource::createPlayerTextures() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crear variante con paleta original (pal0) - usar la textura ya cargada
|
// Crear las 4 texturas con sus respectivas paletas
|
||||||
auto base_texture = getTexture(player.base_texture);
|
for (int palette_idx = 0; palette_idx < 4; ++palette_idx) {
|
||||||
std::string pal0_name = player.name_prefix + "_pal0";
|
std::shared_ptr<Texture> texture;
|
||||||
textures_.emplace_back(pal0_name, base_texture);
|
|
||||||
printWithDots("Player Texture : ", pal0_name, "[ DONE ]");
|
|
||||||
|
|
||||||
// Crear variantes con paletas adicionales - CADA UNA DESDE EL ARCHIVO
|
if (palette_idx == 0) {
|
||||||
for (size_t i = 0; i < player.palette_files.size(); ++i) {
|
// Textura 0 - usar la ya cargada y modificar solo paleta 0 (default_shirt)
|
||||||
// Crear textura completamente nueva desde el archivo
|
texture = getTexture(player.base_texture);
|
||||||
auto texture_copy = std::make_shared<Texture>(Screen::get()->getRenderer(), texture_file_path);
|
texture->setPaletteColor(0, 16, param.player.default_shirt[player_idx].darkest.TO_UINT32());
|
||||||
|
texture->setPaletteColor(0, 17, param.player.default_shirt[player_idx].dark.TO_UINT32());
|
||||||
|
texture->setPaletteColor(0, 18, param.player.default_shirt[player_idx].base.TO_UINT32());
|
||||||
|
texture->setPaletteColor(0, 19, param.player.default_shirt[player_idx].light.TO_UINT32());
|
||||||
|
texture->setPaletteColor(0, 56, param.player.outline_color[player_idx].TO_UINT32());
|
||||||
|
} else {
|
||||||
|
// Crear textura nueva desde archivo
|
||||||
|
texture = std::make_shared<Texture>(Screen::get()->getRenderer(), texture_file_path);
|
||||||
|
|
||||||
// Añadir todas las paletas
|
// Añadir todas las paletas
|
||||||
texture_copy->addPaletteFromPalFile(Asset::get()->get(player.palette_files[0]));
|
texture->addPaletteFromPalFile(Asset::get()->get(player.palette_files[0]));
|
||||||
texture_copy->addPaletteFromPalFile(Asset::get()->get(player.palette_files[1]));
|
texture->addPaletteFromPalFile(Asset::get()->get(player.palette_files[1]));
|
||||||
texture_copy->addPaletteFromPalFile(Asset::get()->get(player.palette_files[2]));
|
texture->addPaletteFromPalFile(Asset::get()->get(player.palette_files[2]));
|
||||||
|
|
||||||
// Añade los colores establecidos en param.player usando el índice del jugador (player_idx)
|
if (palette_idx == 1) {
|
||||||
texture_copy->setPaletteColor(1, 16, param.player.one_coffee_shirt[player_idx].darkest.toUint32());
|
// Textura 1 - modificar solo paleta 1 (one_coffee_shirt)
|
||||||
texture_copy->setPaletteColor(1, 17, param.player.one_coffee_shirt[player_idx].dark.toUint32());
|
texture->setPaletteColor(1, 16, param.player.one_coffee_shirt[player_idx].darkest.TO_UINT32());
|
||||||
texture_copy->setPaletteColor(1, 18, param.player.one_coffee_shirt[player_idx].base.toUint32());
|
texture->setPaletteColor(1, 17, param.player.one_coffee_shirt[player_idx].dark.TO_UINT32());
|
||||||
texture_copy->setPaletteColor(1, 19, param.player.one_coffee_shirt[player_idx].light.toUint32());
|
texture->setPaletteColor(1, 18, param.player.one_coffee_shirt[player_idx].base.TO_UINT32());
|
||||||
|
texture->setPaletteColor(1, 19, param.player.one_coffee_shirt[player_idx].light.TO_UINT32());
|
||||||
|
texture->setPaletteColor(1, 56, param.player.outline_color[player_idx].TO_UINT32());
|
||||||
|
} else if (palette_idx == 2) {
|
||||||
|
// Textura 2 - modificar solo paleta 2 (two_coffee_shirt)
|
||||||
|
texture->setPaletteColor(2, 16, param.player.two_coffee_shirt[player_idx].darkest.TO_UINT32());
|
||||||
|
texture->setPaletteColor(2, 17, param.player.two_coffee_shirt[player_idx].dark.TO_UINT32());
|
||||||
|
texture->setPaletteColor(2, 18, param.player.two_coffee_shirt[player_idx].base.TO_UINT32());
|
||||||
|
texture->setPaletteColor(2, 19, param.player.two_coffee_shirt[player_idx].light.TO_UINT32());
|
||||||
|
texture->setPaletteColor(2, 56, param.player.outline_color[player_idx].TO_UINT32());
|
||||||
|
}
|
||||||
|
// Textura 3 (palette_idx == 3) - no modificar nada, usar colores originales
|
||||||
|
}
|
||||||
|
|
||||||
texture_copy->setPaletteColor(2, 16, param.player.two_coffee_shirt[player_idx].darkest.toUint32());
|
// Asignar la paleta correspondiente
|
||||||
texture_copy->setPaletteColor(2, 17, param.player.two_coffee_shirt[player_idx].dark.toUint32());
|
texture->setPalette(palette_idx);
|
||||||
texture_copy->setPaletteColor(2, 18, param.player.two_coffee_shirt[player_idx].base.toUint32());
|
|
||||||
texture_copy->setPaletteColor(2, 19, param.player.two_coffee_shirt[player_idx].light.toUint32());
|
|
||||||
|
|
||||||
// Cambiar a la paleta específica (índice i+1 porque 0 es la original)
|
|
||||||
texture_copy->setPalette(i + 1);
|
|
||||||
|
|
||||||
// Guardar con nombre específico
|
// Guardar con nombre específico
|
||||||
std::string variant_name = player.name_prefix + "_pal" + std::to_string(i + 1);
|
std::string texture_name = player.name_prefix + "_pal" + std::to_string(palette_idx);
|
||||||
textures_.emplace_back(variant_name, texture_copy);
|
textures_.emplace_back(texture_name, texture);
|
||||||
printWithDots("Player Texture : ", variant_name, "[ DONE ]");
|
printWithDots("Player Texture : ", texture_name, "[ DONE ]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -604,33 +616,42 @@ void Resource::createTextTextures() {
|
|||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> CREATING TEXTURES");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> CREATING TEXTURES");
|
||||||
|
|
||||||
// Texturas de tamaño normal
|
// Texturas de tamaño normal con outline
|
||||||
std::vector<NameAndText> strings = {
|
std::vector<NameAndText> strings1 = {
|
||||||
{"game_text_1000_points", "1.000"},
|
{"game_text_1000_points", "1.000"},
|
||||||
{"game_text_2500_points", "2.500"},
|
{"game_text_2500_points", "2.500"},
|
||||||
{"game_text_5000_points", "5.000"},
|
{"game_text_5000_points", "5.000"},
|
||||||
{"game_text_powerup", Lang::getText("[GAME_TEXT] 4")},
|
{"game_text_powerup", Lang::getText("[GAME_TEXT] 4")},
|
||||||
{"game_text_one_hit", Lang::getText("[GAME_TEXT] 5")},
|
{"game_text_one_hit", Lang::getText("[GAME_TEXT] 5")},
|
||||||
{"game_text_stop", Lang::getText("[GAME_TEXT] 6")},
|
{"game_text_stop", Lang::getText("[GAME_TEXT] 6")}};
|
||||||
|
|
||||||
|
auto text1 = getText("04b_25_enhanced");
|
||||||
|
for (const auto &s : strings1) {
|
||||||
|
textures_.emplace_back(s.name, text1->writeDXToTexture(Text::STROKE, s.text, -2, Colors::NO_COLOR_MOD, 1, param.game.item_text_outline_color));
|
||||||
|
printWithDots("Texture : ", s.name, "[ DONE ]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Texturas de tamaño normal
|
||||||
|
std::vector<NameAndText> strings2 = {
|
||||||
{"game_text_1000000_points", Lang::getText("[GAME_TEXT] 8")}};
|
{"game_text_1000000_points", Lang::getText("[GAME_TEXT] 8")}};
|
||||||
|
|
||||||
auto text = getText("04b_25");
|
auto text2 = getText("04b_25");
|
||||||
for (const auto &s : strings) {
|
for (const auto &s : strings2) {
|
||||||
textures_.emplace_back(s.name, text->writeToTexture(s.text, 1, -2));
|
textures_.emplace_back(s.name, text2->writeDXToTexture(Text::STROKE, s.text, -2, Colors::NO_COLOR_MOD, 1, param.game.item_text_outline_color));
|
||||||
printWithDots("Texture : ", s.name, "[ DONE ]");
|
printWithDots("Texture : ", s.name, "[ DONE ]");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Texturas de tamaño doble
|
// Texturas de tamaño doble
|
||||||
std::vector<NameAndText> strings2_x = {
|
std::vector<NameAndText> strings3 = {
|
||||||
{"game_text_100000_points", "100.000"},
|
{"game_text_100000_points", "100.000"},
|
||||||
{"game_text_get_ready", Lang::getText("[GAME_TEXT] 7")},
|
{"game_text_get_ready", Lang::getText("[GAME_TEXT] 7")},
|
||||||
{"game_text_last_stage", Lang::getText("[GAME_TEXT] 3")},
|
{"game_text_last_stage", Lang::getText("[GAME_TEXT] 3")},
|
||||||
{"game_text_congratulations", Lang::getText("[GAME_TEXT] 1")},
|
{"game_text_congratulations", Lang::getText("[GAME_TEXT] 1")},
|
||||||
{"game_text_game_over", "Game Over"}};
|
{"game_text_game_over", "Game Over"}};
|
||||||
|
|
||||||
auto text2 = getText("04b_25_2x");
|
auto text3 = getText("04b_25_2x");
|
||||||
for (const auto &s : strings2_x) {
|
for (const auto &s : strings3) {
|
||||||
textures_.emplace_back(s.name, text2->writeToTexture(s.text, 1, -4));
|
textures_.emplace_back(s.name, text3->writeToTexture(s.text, 1, -4));
|
||||||
printWithDots("Texture : ", s.name, "[ DONE ]");
|
printWithDots("Texture : ", s.name, "[ DONE ]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -641,15 +662,18 @@ void Resource::createText() {
|
|||||||
std::string key;
|
std::string key;
|
||||||
std::string texture_file;
|
std::string texture_file;
|
||||||
std::string text_file;
|
std::string text_file;
|
||||||
|
std::string white_texture_file; // Textura blanca opcional
|
||||||
|
|
||||||
ResourceInfo(std::string k, std::string t_file, std::string txt_file)
|
ResourceInfo(std::string k, std::string t_file, std::string txt_file, std::string w_file = "")
|
||||||
: key(std::move(k)), texture_file(std::move(t_file)), text_file(std::move(txt_file)) {}
|
: key(std::move(k)), texture_file(std::move(t_file)), text_file(std::move(txt_file)), white_texture_file(std::move(w_file)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> CREATING TEXT OBJECTS");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> CREATING TEXT OBJECTS");
|
||||||
|
|
||||||
std::vector<ResourceInfo> resources = {
|
std::vector<ResourceInfo> resources = {
|
||||||
{"04b_25", "04b_25.png", "04b_25.txt"},
|
{"04b_25", "04b_25.png", "04b_25.txt"},
|
||||||
|
{"04b_25_enhanced", "04b_25.png", "04b_25.txt", "04b_25_white.png"}, // Nueva fuente con textura blanca
|
||||||
|
{"04b_25_white", "04b_25_white.png", "04b_25.txt"},
|
||||||
{"04b_25_2x", "04b_25_2x.png", "04b_25_2x.txt"},
|
{"04b_25_2x", "04b_25_2x.png", "04b_25_2x.txt"},
|
||||||
{"04b_25_metal", "04b_25_metal.png", "04b_25.txt"},
|
{"04b_25_metal", "04b_25_metal.png", "04b_25.txt"},
|
||||||
{"04b_25_grey", "04b_25_grey.png", "04b_25.txt"},
|
{"04b_25_grey", "04b_25_grey.png", "04b_25.txt"},
|
||||||
@@ -663,7 +687,13 @@ void Resource::createText() {
|
|||||||
{"smb2_grad", "smb2_grad.png", "smb2.txt"}};
|
{"smb2_grad", "smb2_grad.png", "smb2.txt"}};
|
||||||
|
|
||||||
for (const auto &resource : resources) {
|
for (const auto &resource : resources) {
|
||||||
texts_.emplace_back(resource.key, std::make_shared<Text>(getTexture(resource.texture_file), getTextFile(resource.text_file)));
|
if (!resource.white_texture_file.empty()) {
|
||||||
|
// Crear texto con textura blanca
|
||||||
|
texts_.emplace_back(resource.key, std::make_shared<Text>(getTexture(resource.texture_file), getTexture(resource.white_texture_file), getTextFile(resource.text_file)));
|
||||||
|
} else {
|
||||||
|
// Crear texto normal
|
||||||
|
texts_.emplace_back(resource.key, std::make_shared<Text>(getTexture(resource.texture_file), getTextFile(resource.text_file)));
|
||||||
|
}
|
||||||
printWithDots("Text : ", resource.key, "[ DONE ]");
|
printWithDots("Text : ", resource.key, "[ DONE ]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -784,15 +814,15 @@ void Resource::initProgressBar() {
|
|||||||
const float BAR_Y_POSITION = param.game.height - BAR_HEIGHT - Y_PADDING;
|
const float BAR_Y_POSITION = param.game.height - BAR_HEIGHT - Y_PADDING;
|
||||||
|
|
||||||
const float WIRED_BAR_WIDTH = param.game.width - (X_PADDING * 2);
|
const float WIRED_BAR_WIDTH = param.game.width - (X_PADDING * 2);
|
||||||
loading_wired_rect_ = {X_PADDING, BAR_Y_POSITION, WIRED_BAR_WIDTH, BAR_HEIGHT};
|
loading_wired_rect_ = {.x = X_PADDING, .y = BAR_Y_POSITION, .w = WIRED_BAR_WIDTH, .h = BAR_HEIGHT};
|
||||||
|
|
||||||
const float FULL_BAR_WIDTH = WIRED_BAR_WIDTH * loading_count_.getPercentage();
|
const float FULL_BAR_WIDTH = WIRED_BAR_WIDTH * loading_count_.getPercentage();
|
||||||
loading_full_rect_ = {X_PADDING, BAR_Y_POSITION, FULL_BAR_WIDTH, BAR_HEIGHT};
|
loading_full_rect_ = {.x = X_PADDING, .y = BAR_Y_POSITION, .w = FULL_BAR_WIDTH, .h = BAR_HEIGHT};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el progreso de carga, muestra la barra y procesa eventos
|
// Actualiza el progreso de carga, muestra la barra y procesa eventos
|
||||||
void Resource::updateLoadingProgress(std::string name) {
|
void Resource::updateLoadingProgress(std::string name) {
|
||||||
loading_resource_name_ = name;
|
loading_resource_name_ = std::move(name);
|
||||||
loading_count_.increase();
|
loading_count_.increase();
|
||||||
updateProgressBar();
|
updateProgressBar();
|
||||||
renderProgress();
|
renderProgress();
|
||||||
|
|||||||
@@ -140,13 +140,13 @@ class Resource {
|
|||||||
void loadEssentialResources(); // Carga recursos esenciales en modo lazy
|
void loadEssentialResources(); // Carga recursos esenciales en modo lazy
|
||||||
void loadEssentialTextures(); // Carga solo las texturas esenciales (fuentes)
|
void loadEssentialTextures(); // Carga solo las texturas esenciales (fuentes)
|
||||||
void loadTextFilesQuiet(); // Carga ficheros de texto sin mostrar progreso (para modo lazy)
|
void loadTextFilesQuiet(); // Carga ficheros de texto sin mostrar progreso (para modo lazy)
|
||||||
void createPlayerTextures(); // Crea las texturas de jugadores con todas sus variantes de paleta
|
void createPlayerTextures(); // Crea las texturas de jugadores con todas sus variantes de paleta
|
||||||
void createTextTextures(); // Crea las texturas a partir de los datos cargados
|
void createTextTextures(); // Crea las texturas a partir de los datos cargados
|
||||||
void createText(); // Crea los objetos de texto
|
void createText(); // Crea los objetos de texto
|
||||||
void clear(); // Vacía todos los vectores de recursos
|
void clear(); // Vacía todos los vectores de recursos
|
||||||
void load(); // Carga todos los recursos
|
void load(); // Carga todos los recursos
|
||||||
void clearSounds(); // Vacía el vector de sonidos
|
void clearSounds(); // Vacía el vector de sonidos
|
||||||
void clearMusics(); // Vacía el vector de músicas
|
void clearMusics(); // Vacía el vector de músicas
|
||||||
|
|
||||||
// --- Métodos para carga perezosa ---
|
// --- Métodos para carga perezosa ---
|
||||||
void initResourceLists(); // Inicializa las listas de recursos sin cargar el contenido
|
void initResourceLists(); // Inicializa las listas de recursos sin cargar el contenido
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ void Scoreboard::renderShowNameMode(size_t panel_index) {
|
|||||||
text_scoreboard_->writeDX(Text::CENTER | Text::COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
|
text_scoreboard_->writeDX(Text::CENTER | Text::COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
|
||||||
|
|
||||||
/* TEXTO CENTRADO */
|
/* TEXTO CENTRADO */
|
||||||
text_scoreboard_->writeDX(Text::CENTER | Text::COLOR, slot4_4_.x, slot4_4_.y, record_name_.at(panel_index), 1, getColorLikeKnightRider(name_colors_, loop_counter_ / 5));
|
text_scoreboard_->writeDX(Text::CENTER | Text::COLOR, slot4_4_.x, slot4_4_.y, record_name_.at(panel_index), 1, Colors::getColorLikeKnightRider(name_colors_, loop_counter_ / 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scoreboard::renderGameCompletedMode(size_t panel_index) {
|
void Scoreboard::renderGameCompletedMode(size_t panel_index) {
|
||||||
@@ -373,14 +373,14 @@ void Scoreboard::recalculateAnchors() {
|
|||||||
const float COL = PANEL_WIDTH / 2;
|
const float COL = PANEL_WIDTH / 2;
|
||||||
|
|
||||||
// Slots de 4
|
// Slots de 4
|
||||||
slot4_1_ = {COL, ROW1};
|
slot4_1_ = {.x = COL, .y = ROW1};
|
||||||
slot4_2_ = {COL, ROW2};
|
slot4_2_ = {.x = COL, .y = ROW2};
|
||||||
slot4_3_ = {COL, ROW3};
|
slot4_3_ = {.x = COL, .y = ROW3};
|
||||||
slot4_4_ = {COL, ROW4};
|
slot4_4_ = {.x = COL, .y = ROW4};
|
||||||
|
|
||||||
// Primer cuadrado para poner el nombre de record
|
// Primer cuadrado para poner el nombre de record
|
||||||
const int ENTER_NAME_LENGHT = text_scoreboard_->length(std::string(NAME_SIZE, 'A'));
|
const int ENTER_NAME_LENGTH = text_scoreboard_->length(std::string(NAME_SIZE, 'A'));
|
||||||
enter_name_pos_.x = COL - (ENTER_NAME_LENGHT / 2);
|
enter_name_pos_.x = COL - (ENTER_NAME_LENGTH / 2);
|
||||||
enter_name_pos_.y = ROW4;
|
enter_name_pos_.y = ROW4;
|
||||||
|
|
||||||
// Recoloca los sprites
|
// Recoloca los sprites
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class Scoreboard {
|
|||||||
NUM_MODES,
|
NUM_MODES,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Structs ---
|
// --- Estructuras ---
|
||||||
struct Panel {
|
struct Panel {
|
||||||
Mode mode; // Modo en el que se encuentra el panel
|
Mode mode; // Modo en el que se encuentra el panel
|
||||||
SDL_FRect pos; // Posición donde dibujar el panel dentro del marcador
|
SDL_FRect pos; // Posición donde dibujar el panel dentro del marcador
|
||||||
@@ -80,22 +80,21 @@ class Scoreboard {
|
|||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
std::array<std::string, static_cast<int>(Id::SIZE)> name_ = {}; // Nombre de cada jugador
|
std::array<std::string, static_cast<int>(Id::SIZE)> name_ = {}; // Nombre de cada jugador
|
||||||
std::array<std::string, static_cast<int>(Id::SIZE)> record_name_ = {}; // Nombre introducido para la tabla de records
|
std::array<std::string, static_cast<int>(Id::SIZE)> record_name_ = {}; // Nombre introducido para la tabla de records
|
||||||
|
std::array<Panel, static_cast<int>(Id::SIZE)> panel_ = {}; // Lista con todos los paneles del marcador
|
||||||
|
std::vector<Color> name_colors_; // Colores para destacar el nombre una vez introducido
|
||||||
|
std::string hi_score_name_; // Nombre del jugador con la máxima puntuación
|
||||||
|
SDL_FRect rect_ = {0, 0, 320, 40}; // Posición y dimensiones del marcador
|
||||||
|
Color color_; // Color del marcador
|
||||||
std::array<size_t, static_cast<int>(Id::SIZE)> selector_pos_ = {}; // Posición del selector de letra para introducir el nombre
|
std::array<size_t, static_cast<int>(Id::SIZE)> selector_pos_ = {}; // Posición del selector de letra para introducir el nombre
|
||||||
std::array<int, static_cast<int>(Id::SIZE)> score_ = {}; // Puntuación de los jugadores
|
std::array<int, static_cast<int>(Id::SIZE)> score_ = {}; // Puntuación de los jugadores
|
||||||
std::array<float, static_cast<int>(Id::SIZE)> mult_ = {}; // Multiplicador de los jugadores
|
|
||||||
std::array<int, static_cast<int>(Id::SIZE)> continue_counter_ = {}; // Tiempo para continuar de los jugadores
|
std::array<int, static_cast<int>(Id::SIZE)> continue_counter_ = {}; // Tiempo para continuar de los jugadores
|
||||||
std::array<Panel, static_cast<int>(Id::SIZE)> panel_ = {}; // Lista con todos los paneles del marcador
|
std::array<float, static_cast<int>(Id::SIZE)> mult_ = {}; // Multiplicador de los jugadores
|
||||||
|
Uint64 ticks_ = SDL_GetTicks(); // Variable donde almacenar el valor de SDL_GetTicks()
|
||||||
int stage_ = 1; // Número de fase actual
|
int stage_ = 1; // Número de fase actual
|
||||||
int hi_score_ = 0; // Máxima puntuación
|
int hi_score_ = 0; // Máxima puntuación
|
||||||
float power_ = 0; // Poder actual de la fase
|
int time_counter_ = 0; // Contador de segundos
|
||||||
std::string hi_score_name_; // Nombre del jugador con la máxima puntuación
|
int loop_counter_ = 0; // Contador de bucle
|
||||||
Color color_; // Color del marcador
|
float power_ = 0; // Poder actual de la fase
|
||||||
SDL_FRect rect_ = {0, 0, 320, 40}; // Posición y dimensiones del marcador
|
|
||||||
Uint64 ticks_ = SDL_GetTicks(); // Variable donde almacenar el valor de SDL_GetTicks()
|
|
||||||
int time_counter_ = 0; // Contador de segundos
|
|
||||||
int loop_counter_ = 0; // Contador de bucle
|
|
||||||
std::vector<Color> name_colors_; // Colores para destacar el nombre una vez introducido
|
|
||||||
|
|
||||||
// --- Variables de aspecto ---
|
// --- Variables de aspecto ---
|
||||||
Color text_color1_, text_color2_; // Colores para los marcadores del texto;
|
Color text_color1_, text_color2_; // Colores para los marcadores del texto;
|
||||||
@@ -126,10 +125,10 @@ class Scoreboard {
|
|||||||
void renderShowNameMode(size_t panel_index);
|
void renderShowNameMode(size_t panel_index);
|
||||||
void renderGameCompletedMode(size_t panel_index);
|
void renderGameCompletedMode(size_t panel_index);
|
||||||
|
|
||||||
// --- Constructor y destructor privados (singleton) ---
|
// --- Constructores y destructor privados (singleton) ---
|
||||||
Scoreboard();
|
Scoreboard(); // Constructor privado
|
||||||
~Scoreboard();
|
~Scoreboard(); // Destructor privado
|
||||||
|
|
||||||
// --- Singleton ---
|
// --- Instancia singleton ---
|
||||||
static Scoreboard *instance;
|
static Scoreboard *instance; // Instancia única de Scoreboard
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class Notifier;
|
|||||||
class ServiceMenu;
|
class ServiceMenu;
|
||||||
class Text;
|
class Text;
|
||||||
|
|
||||||
// Clase Screen: gestiona la ventana, el renderizador y los efectos visuales globales
|
// --- Clase Screen: gestiona la ventana, el renderizador y los efectos visuales globales (singleton) ---
|
||||||
class Screen {
|
class Screen {
|
||||||
public:
|
public:
|
||||||
// --- Métodos de singleton ---
|
// --- Métodos de singleton ---
|
||||||
@@ -38,8 +38,8 @@ class Screen {
|
|||||||
void initShaders(); // Inicializa los shaders
|
void initShaders(); // Inicializa los shaders
|
||||||
|
|
||||||
// --- Efectos visuales ---
|
// --- Efectos visuales ---
|
||||||
void shake(int desp = 2, int delay = 3, int lenght = 8) { shake_effect_.enable(src_rect_, dst_rect_, desp, delay, lenght); } // Agita la pantalla
|
void shake(int desp = 2, int delay = 3, int length = 8) { shake_effect_.enable(src_rect_, dst_rect_, desp, delay, length); } // Agita la pantalla
|
||||||
void flash(Color color, int lenght = 10, int delay = 0) { flash_effect_ = FlashEffect(true, lenght, delay, color); } // Pone la pantalla de color
|
void flash(Color color, int length = 10, int delay = 0) { flash_effect_ = FlashEffect(true, length, delay, color); } // Pone la pantalla de color
|
||||||
void toggleShaders(); // Alterna entre activar y desactivar los shaders
|
void toggleShaders(); // Alterna entre activar y desactivar los shaders
|
||||||
void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero
|
void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero
|
||||||
void toggleVSync(); // Alterna entre activar y desactivar el V-Sync
|
void toggleVSync(); // Alterna entre activar y desactivar el V-Sync
|
||||||
@@ -62,9 +62,9 @@ class Screen {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr int WINDOWS_DECORATIONS = 35;
|
static constexpr int WINDOWS_DECORATIONS = 35; // Decoraciones de la ventana
|
||||||
|
|
||||||
// --- Estructuras internas ---
|
// --- Estructuras privadas ---
|
||||||
struct FPS {
|
struct FPS {
|
||||||
Uint32 ticks{0}; // Tiempo en milisegundos desde que se comenzó a contar.
|
Uint32 ticks{0}; // Tiempo en milisegundos desde que se comenzó a contar.
|
||||||
int frame_count{0}; // Número acumulado de frames en el intervalo.
|
int frame_count{0}; // Número acumulado de frames en el intervalo.
|
||||||
@@ -85,16 +85,16 @@ class Screen {
|
|||||||
// Efecto de flash en pantalla: pinta la pantalla de un color durante unos frames
|
// Efecto de flash en pantalla: pinta la pantalla de un color durante unos frames
|
||||||
struct FlashEffect {
|
struct FlashEffect {
|
||||||
bool enabled; // Indica si el efecto está activo
|
bool enabled; // Indica si el efecto está activo
|
||||||
int lenght; // Duración total del efecto en frames
|
int length; // Duración total del efecto en frames
|
||||||
int delay; // Retraso antes de mostrar el flash
|
int delay; // Retraso antes de mostrar el flash
|
||||||
int counter; // Contador de frames restantes
|
int counter; // Contador de frames restantes
|
||||||
Color color; // Color del flash
|
Color color; // Color del flash
|
||||||
|
|
||||||
explicit FlashEffect(bool enabled = false, int lenght = 0, int delay = 0, Color color = Color(0xFF, 0xFF, 0xFF))
|
explicit FlashEffect(bool enabled = false, int length = 0, int delay = 0, Color color = Color(0xFF, 0xFF, 0xFF))
|
||||||
: enabled(enabled), lenght(lenght), delay(delay), counter(lenght), color(color) {}
|
: enabled(enabled), length(length), delay(delay), counter(length), color(color) {}
|
||||||
|
|
||||||
void update() { (enabled && counter > 0) ? counter-- : static_cast<int>(enabled = false); }
|
void update() { (enabled && counter > 0) ? counter-- : static_cast<int>(enabled = false); }
|
||||||
[[nodiscard]] auto isRendarable() const -> bool { return enabled && counter < lenght - delay; }
|
[[nodiscard]] auto isRendarable() const -> bool { return enabled && counter < length - delay; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Efecto de sacudida/agitación de pantalla: mueve la imagen para simular un temblor
|
// Efecto de sacudida/agitación de pantalla: mueve la imagen para simular un temblor
|
||||||
@@ -102,17 +102,17 @@ class Screen {
|
|||||||
int desp; // Desplazamiento máximo de la sacudida (en píxeles)
|
int desp; // Desplazamiento máximo de la sacudida (en píxeles)
|
||||||
int delay; // Frames entre cada movimiento de sacudida
|
int delay; // Frames entre cada movimiento de sacudida
|
||||||
int counter; // Contador de frames para el siguiente movimiento
|
int counter; // Contador de frames para el siguiente movimiento
|
||||||
int lenght; // Duración total del efecto en frames
|
int length; // Duración total del efecto en frames
|
||||||
int remaining; // Frames restantes de sacudida
|
int remaining; // Frames restantes de sacudida
|
||||||
int original_pos; // Posición original de la imagen (x)
|
int original_pos; // Posición original de la imagen (x)
|
||||||
int original_width; // Ancho original de la imagen
|
int original_width; // Ancho original de la imagen
|
||||||
bool enabled; // Indica si el efecto está activo
|
bool enabled; // Indica si el efecto está activo
|
||||||
|
|
||||||
explicit ShakeEffect(bool en = false, int dp = 2, int dl = 3, int cnt = 0, int len = 8, int rem = 0, int orig_pos = 0, int orig_width = 800)
|
explicit ShakeEffect(bool en = false, int dp = 2, int dl = 3, int cnt = 0, int len = 8, int rem = 0, int orig_pos = 0, int orig_width = 800)
|
||||||
: desp(dp), delay(dl), counter(cnt), lenght(len), remaining(rem), original_pos(orig_pos), original_width(orig_width), enabled(en) {}
|
: desp(dp), delay(dl), counter(cnt), length(len), remaining(rem), original_pos(orig_pos), original_width(orig_width), enabled(en) {}
|
||||||
|
|
||||||
// Activa el efecto de sacudida y guarda la posición y tamaño originales
|
// Activa el efecto de sacudida y guarda la posición y tamaño originales
|
||||||
void enable(SDL_FRect &src_rect, SDL_FRect &dst_rect, int new_desp = -1, int new_delay = -1, int new_lenght = -1) {
|
void enable(SDL_FRect &src_rect, SDL_FRect &dst_rect, int new_desp = -1, int new_delay = -1, int new_length = -1) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
original_pos = src_rect.x;
|
original_pos = src_rect.x;
|
||||||
@@ -125,14 +125,14 @@ class Screen {
|
|||||||
if (new_delay != -1) {
|
if (new_delay != -1) {
|
||||||
delay = new_delay;
|
delay = new_delay;
|
||||||
}
|
}
|
||||||
if (new_lenght != -1) {
|
if (new_length != -1) {
|
||||||
lenght = new_lenght;
|
length = new_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
src_rect.w -= desp;
|
src_rect.w -= desp;
|
||||||
dst_rect.w = src_rect.w;
|
dst_rect.w = src_rect.w;
|
||||||
}
|
}
|
||||||
remaining = lenght;
|
remaining = length;
|
||||||
counter = delay;
|
counter = delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,21 +170,19 @@ class Screen {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --- Singleton ---
|
|
||||||
static Screen *instance;
|
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
SDL_Window *window_; // Ventana de la aplicación
|
SDL_Window *window_; // Ventana de la aplicación
|
||||||
SDL_Renderer *renderer_; // El renderizador de la ventana
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
SDL_Texture *game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador
|
SDL_Texture *game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador
|
||||||
ServiceMenu *service_menu_; // Objeto para mostrar el menú de servicio
|
ServiceMenu *service_menu_; // Objeto para mostrar el menú de servicio
|
||||||
Notifier *notifier_; // Objeto para mostrar las notificaciones por pantalla
|
Notifier *notifier_; // Objeto para mostrar las notificaciones por pantalla
|
||||||
|
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
SDL_FRect src_rect_; // Coordenadas de origen para dibujar la textura del juego
|
SDL_FRect src_rect_; // Coordenadas de origen para dibujar la textura del juego
|
||||||
SDL_FRect dst_rect_; // Coordenadas destino para dibujar la textura del juego
|
SDL_FRect dst_rect_; // Coordenadas destino para dibujar la textura del juego
|
||||||
FPS fps_; // Gestión de frames por segundo
|
|
||||||
std::string shader_source_; // Almacena el contenido del archivo GLSL
|
std::string shader_source_; // Almacena el contenido del archivo GLSL
|
||||||
|
FPS fps_; // Gestión de frames por segundo
|
||||||
FlashEffect flash_effect_; // Efecto de flash en pantalla
|
FlashEffect flash_effect_; // Efecto de flash en pantalla
|
||||||
ShakeEffect shake_effect_; // Efecto de agitar la pantalla
|
ShakeEffect shake_effect_; // Efecto de agitar la pantalla
|
||||||
bool attenuate_effect_ = false; // Indica si la pantalla ha de estar atenuada
|
bool attenuate_effect_ = false; // Indica si la pantalla ha de estar atenuada
|
||||||
@@ -192,9 +190,6 @@ class Screen {
|
|||||||
Debug debug_info_; // Información de debug
|
Debug debug_info_; // Información de debug
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --- Texto ---
|
|
||||||
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
|
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana
|
auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana
|
||||||
void renderFlash(); // Dibuja el efecto de flash en la pantalla
|
void renderFlash(); // Dibuja el efecto de flash en la pantalla
|
||||||
@@ -208,7 +203,10 @@ class Screen {
|
|||||||
void renderAttenuate(); // Atenúa la pantalla
|
void renderAttenuate(); // Atenúa la pantalla
|
||||||
void createText(); // Crea el objeto de texto
|
void createText(); // Crea el objeto de texto
|
||||||
|
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor privados (singleton) ---
|
||||||
Screen();
|
Screen(); // Constructor privado
|
||||||
~Screen();
|
~Screen(); // Destructor privado
|
||||||
|
|
||||||
|
// --- Instancia singleton ---
|
||||||
|
static Screen *instance; // Instancia única de Screen
|
||||||
};
|
};
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#include "audio.h" // Para Audio
|
#include "audio.h" // Para Audio
|
||||||
#include "balloon_manager.h" // Para BalloonManager
|
#include "balloon_manager.h" // Para BalloonManager
|
||||||
#include "color.h" // Para Zone, SHADOW_TEXT_COLOR, NO_TEXT_COLOR, Color
|
#include "color.h" // Para Zone, Colors::SHADOW_TEXT, Colors::NO_COLOR_MOD, Color
|
||||||
#include "fade.h" // Para Fade, FadeType, FadeMode
|
#include "fade.h" // Para Fade, FadeType, FadeMode
|
||||||
#include "global_events.h" // Para check
|
#include "global_events.h" // Para check
|
||||||
#include "global_inputs.h" // Para check
|
#include "global_inputs.h" // Para check
|
||||||
@@ -35,12 +35,7 @@ constexpr std::string_view TEXT_COPYRIGHT = "@2020,2025 JailDesigner";
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Credits::Credits()
|
Credits::Credits()
|
||||||
: balloon_manager_(std::make_unique<BalloonManager>(nullptr)),
|
: balloon_manager_(std::make_unique<BalloonManager>(nullptr)), tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::DIAGONAL)), fade_in_(std::make_unique<Fade>()), fade_out_(std::make_unique<Fade>()), text_texture_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, static_cast<int>(param.game.width), static_cast<int>(param.game.height))), canvas_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, static_cast<int>(param.game.width), static_cast<int>(param.game.height))) {
|
||||||
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::DIAGONAL)),
|
|
||||||
fade_in_(std::make_unique<Fade>()),
|
|
||||||
fade_out_(std::make_unique<Fade>()),
|
|
||||||
text_texture_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
|
||||||
canvas_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)) {
|
|
||||||
if (text_texture_ == nullptr) {
|
if (text_texture_ == nullptr) {
|
||||||
throw std::runtime_error("Failed to create SDL texture for text.");
|
throw std::runtime_error("Failed to create SDL texture for text.");
|
||||||
}
|
}
|
||||||
@@ -48,13 +43,13 @@ Credits::Credits()
|
|||||||
balloon_manager_->setPlayArea(play_area_);
|
balloon_manager_->setPlayArea(play_area_);
|
||||||
|
|
||||||
fade_in_->setColor(param.fade.color);
|
fade_in_->setColor(param.fade.color);
|
||||||
fade_in_->setType(FadeType::FULLSCREEN);
|
fade_in_->setType(Fade::Type::FULLSCREEN);
|
||||||
fade_in_->setPostDuration(50);
|
fade_in_->setPostDuration(50);
|
||||||
fade_in_->setMode(FadeMode::IN);
|
fade_in_->setMode(Fade::Mode::IN);
|
||||||
fade_in_->activate();
|
fade_in_->activate();
|
||||||
|
|
||||||
fade_out_->setColor(0, 0, 0);
|
fade_out_->setColor(0, 0, 0);
|
||||||
fade_out_->setType(FadeType::FULLSCREEN);
|
fade_out_->setType(Fade::Type::FULLSCREEN);
|
||||||
fade_out_->setPostDuration(400);
|
fade_out_->setPostDuration(400);
|
||||||
|
|
||||||
updateRedRect();
|
updateRedRect();
|
||||||
@@ -63,7 +58,7 @@ Credits::Credits()
|
|||||||
initPlayers();
|
initPlayers();
|
||||||
SDL_SetTextureBlendMode(text_texture_, SDL_BLENDMODE_BLEND);
|
SDL_SetTextureBlendMode(text_texture_, SDL_BLENDMODE_BLEND);
|
||||||
fillTextTexture();
|
fillTextTexture();
|
||||||
steps_ = std::abs((top_black_rect_.h - param.game.game_area.center_y - 1) + ((left_black_rect_.w - param.game.game_area.center_x) / 4));
|
steps_ = static_cast<int>(std::abs((top_black_rect_.h - param.game.game_area.center_y - 1) + ((left_black_rect_.w - param.game.game_area.center_x) / 4)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
@@ -170,58 +165,60 @@ void Credits::fillTextTexture() {
|
|||||||
|
|
||||||
const int SPACE_POST_TITLE = 3 + text->getCharacterSize();
|
const int SPACE_POST_TITLE = 3 + text->getCharacterSize();
|
||||||
const int SPACE_PRE_TITLE = text->getCharacterSize() * 4;
|
const int SPACE_PRE_TITLE = text->getCharacterSize() * 4;
|
||||||
const int TEXTS_HEIGHT = 1 * text->getCharacterSize() + 8 * SPACE_POST_TITLE + 3 * SPACE_PRE_TITLE;
|
const int TEXTS_HEIGHT = (1 * text->getCharacterSize()) + (8 * SPACE_POST_TITLE) + (3 * SPACE_PRE_TITLE);
|
||||||
credits_rect_dst_.h = credits_rect_src_.h = TEXTS_HEIGHT;
|
const int POS_X = static_cast<int>(param.game.game_area.center_x);
|
||||||
|
credits_rect_dst_.h = credits_rect_src_.h = static_cast<float>(TEXTS_HEIGHT);
|
||||||
|
auto text_style = Text::Style(Text::CENTER | Text::SHADOW, Colors::NO_COLOR_MOD, Colors::SHADOW_TEXT);
|
||||||
|
|
||||||
// PROGRAMMED_AND_DESIGNED_BY
|
// PROGRAMMED_AND_DESIGNED_BY
|
||||||
int y = 0;
|
int y = 0;
|
||||||
text_grad->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, TEXTS.at(0), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text_grad->writeStyle(POS_X, y, TEXTS.at(0), text_style);
|
||||||
|
|
||||||
y += SPACE_POST_TITLE;
|
y += SPACE_POST_TITLE;
|
||||||
text->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, TEXTS.at(4), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text->writeStyle(POS_X, y, TEXTS.at(4), text_style);
|
||||||
|
|
||||||
// PIXELART_DRAWN_BY
|
// PIXELART_DRAWN_BY
|
||||||
y += SPACE_PRE_TITLE;
|
y += SPACE_PRE_TITLE;
|
||||||
text_grad->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, TEXTS.at(1), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text_grad->writeStyle(POS_X, y, TEXTS.at(1), text_style);
|
||||||
y += SPACE_POST_TITLE;
|
y += SPACE_POST_TITLE;
|
||||||
text->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, TEXTS.at(4), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text->writeStyle(POS_X, y, TEXTS.at(4), text_style);
|
||||||
|
|
||||||
// MUSIC_COMPOSED_BY
|
// MUSIC_COMPOSED_BY
|
||||||
y += SPACE_PRE_TITLE;
|
y += SPACE_PRE_TITLE;
|
||||||
text_grad->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, TEXTS.at(2), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text_grad->writeStyle(POS_X, y, TEXTS.at(2), text_style);
|
||||||
|
|
||||||
y += SPACE_POST_TITLE;
|
y += SPACE_POST_TITLE;
|
||||||
text->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, TEXTS.at(5), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text->writeStyle(POS_X, y, TEXTS.at(5), text_style);
|
||||||
y += SPACE_POST_TITLE;
|
y += SPACE_POST_TITLE;
|
||||||
text->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, TEXTS.at(6), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text->writeStyle(POS_X, y, TEXTS.at(6), text_style);
|
||||||
|
|
||||||
// SOUND_EFFECTS
|
// SOUND_EFFECTS
|
||||||
y += SPACE_PRE_TITLE;
|
y += SPACE_PRE_TITLE;
|
||||||
text_grad->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, TEXTS.at(3), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text_grad->writeStyle(POS_X, y, TEXTS.at(3), text_style);
|
||||||
y += SPACE_POST_TITLE;
|
y += SPACE_POST_TITLE;
|
||||||
text->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, TEXTS.at(7), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text->writeStyle(POS_X, y, TEXTS.at(7), text_style);
|
||||||
y += SPACE_POST_TITLE;
|
y += SPACE_POST_TITLE;
|
||||||
text->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, TEXTS.at(8), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text->writeStyle(POS_X, y, TEXTS.at(8), text_style);
|
||||||
y += SPACE_POST_TITLE;
|
y += SPACE_POST_TITLE;
|
||||||
text->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, TEXTS.at(9), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text->writeStyle(POS_X, y, TEXTS.at(9), text_style);
|
||||||
y += SPACE_POST_TITLE;
|
y += SPACE_POST_TITLE;
|
||||||
text->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, TEXTS.at(10), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text->writeStyle(POS_X, y, TEXTS.at(10), text_style);
|
||||||
|
|
||||||
// Mini logo
|
// Mini logo
|
||||||
y += SPACE_PRE_TITLE;
|
y += SPACE_PRE_TITLE;
|
||||||
mini_logo_rect_src_.y = y;
|
mini_logo_rect_src_.y = static_cast<float>(y);
|
||||||
auto mini_logo_sprite = std::make_unique<Sprite>(Resource::get()->getTexture("logo_jailgames_mini.png"));
|
auto mini_logo_sprite = std::make_unique<Sprite>(Resource::get()->getTexture("logo_jailgames_mini.png"));
|
||||||
mini_logo_sprite->setPosition(1 + param.game.game_area.center_x - mini_logo_sprite->getWidth() / 2, 1 + y);
|
mini_logo_sprite->setPosition(1 + POS_X - (mini_logo_sprite->getWidth() / 2), 1 + y);
|
||||||
Resource::get()->getTexture("logo_jailgames_mini.png")->setColor(SHADOW_TEXT_COLOR.r, SHADOW_TEXT_COLOR.g, SHADOW_TEXT_COLOR.b);
|
Resource::get()->getTexture("logo_jailgames_mini.png")->setColor(Colors::SHADOW_TEXT.r, Colors::SHADOW_TEXT.g, Colors::SHADOW_TEXT.b);
|
||||||
mini_logo_sprite->render();
|
mini_logo_sprite->render();
|
||||||
|
|
||||||
mini_logo_sprite->setPosition(param.game.game_area.center_x - mini_logo_sprite->getWidth() / 2, y);
|
mini_logo_sprite->setPosition(POS_X - (mini_logo_sprite->getWidth() / 2), y);
|
||||||
Resource::get()->getTexture("logo_jailgames_mini.png")->setColor(255, 255, 255);
|
Resource::get()->getTexture("logo_jailgames_mini.png")->setColor(255, 255, 255);
|
||||||
mini_logo_sprite->render();
|
mini_logo_sprite->render();
|
||||||
|
|
||||||
// Texto con el copyright
|
// Texto con el copyright
|
||||||
y += mini_logo_sprite->getHeight() + 3;
|
y += mini_logo_sprite->getHeight() + 3;
|
||||||
text->writeDX(Text::CENTER | Text::SHADOW, param.game.game_area.center_x, y, std::string(TEXT_COPYRIGHT), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text->writeDX(Text::CENTER | Text::SHADOW, POS_X, y, std::string(TEXT_COPYRIGHT), 1, Colors::NO_COLOR_MOD, 1, Colors::SHADOW_TEXT);
|
||||||
|
|
||||||
// Resetea el renderizador
|
// Resetea el renderizador
|
||||||
SDL_SetRenderTarget(Screen::get()->getRenderer(), nullptr);
|
SDL_SetRenderTarget(Screen::get()->getRenderer(), nullptr);
|
||||||
@@ -384,7 +381,7 @@ void Credits::initPlayers() {
|
|||||||
players_.back()->setPlayingState(Player::State::CREDITS);
|
players_.back()->setPlayingState(Player::State::CREDITS);
|
||||||
|
|
||||||
// Registra los jugadores en Options
|
// Registra los jugadores en Options
|
||||||
for (auto player : players_) {
|
for (const auto &player : players_) {
|
||||||
Options::keyboard.addPlayer(player);
|
Options::keyboard.addPlayer(player);
|
||||||
Options::gamepad_manager.addPlayer(player);
|
Options::gamepad_manager.addPlayer(player);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
#include "balloon.h" // Para Balloon
|
#include "balloon.h" // Para Balloon
|
||||||
#include "balloon_manager.h" // Para BalloonManager
|
#include "balloon_manager.h" // Para BalloonManager
|
||||||
#include "bullet.h" // Para Bullet, BulletType, BulletMoveStatus
|
#include "bullet.h" // Para Bullet, BulletType, BulletMoveStatus
|
||||||
#include "color.h" // Para Color, FLASH_COLOR
|
#include "color.h" // Para Color, Colors::FLASH
|
||||||
#include "difficulty.h" // Para Code
|
#include "difficulty.h" // Para Code
|
||||||
#include "fade.h" // Para Fade, FadeType, FadeMode
|
#include "fade.h" // Para Fade, FadeType, FadeMode
|
||||||
#include "global_events.h" // Para check
|
#include "global_events.h" // Para check
|
||||||
@@ -49,18 +49,7 @@
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Game::Game(Player::Id player_id, int current_stage, bool demo)
|
Game::Game(Player::Id player_id, int current_stage, bool demo)
|
||||||
: renderer_(Screen::get()->getRenderer()),
|
: renderer_(Screen::get()->getRenderer()), screen_(Screen::get()), input_(Input::get()), canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.play_area.rect.w, param.game.play_area.rect.h)), pause_manager_(std::make_unique<PauseManager>([this](bool is_paused) { onPauseStateChanged(is_paused); })), stage_manager_(std::make_unique<StageManager>()), balloon_manager_(std::make_unique<BalloonManager>(stage_manager_.get())), background_(std::make_unique<Background>(stage_manager_->getPowerNeededToReachStage(stage_manager_->getTotalStages() - 1))), fade_in_(std::make_unique<Fade>()), fade_out_(std::make_unique<Fade>()), tabe_(std::make_unique<Tabe>()), hit_(Hit(Resource::get()->getTexture("hit.png"))) {
|
||||||
screen_(Screen::get()),
|
|
||||||
input_(Input::get()),
|
|
||||||
canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.play_area.rect.w, param.game.play_area.rect.h)),
|
|
||||||
pause_manager_(std::make_unique<PauseManager>([this](bool is_paused) { onPauseStateChanged(is_paused); })),
|
|
||||||
stage_manager_(std::make_unique<StageManager>()),
|
|
||||||
balloon_manager_(std::make_unique<BalloonManager>(stage_manager_.get())),
|
|
||||||
background_(std::make_unique<Background>(stage_manager_->getTotalPowerNeededToCompleteGame())),
|
|
||||||
fade_in_(std::make_unique<Fade>()),
|
|
||||||
fade_out_(std::make_unique<Fade>()),
|
|
||||||
tabe_(std::make_unique<Tabe>()),
|
|
||||||
hit_(Hit(Resource::get()->getTexture("hit.png"))) {
|
|
||||||
// Pasa variables
|
// Pasa variables
|
||||||
demo_.enabled = demo;
|
demo_.enabled = demo;
|
||||||
|
|
||||||
@@ -79,15 +68,15 @@ Game::Game(Player::Id player_id, int current_stage, bool demo)
|
|||||||
scoreboard_ = Scoreboard::get();
|
scoreboard_ = Scoreboard::get();
|
||||||
|
|
||||||
fade_in_->setColor(param.fade.color);
|
fade_in_->setColor(param.fade.color);
|
||||||
fade_in_->setPreDuration(demo_.enabled ? 80 : 0);
|
fade_in_->setPreDuration(demo_.enabled ? 500 : 0);
|
||||||
fade_in_->setPostDuration(0);
|
fade_in_->setPostDuration(0);
|
||||||
fade_in_->setType(FadeType::RANDOM_SQUARE);
|
fade_in_->setType(Fade::Type::RANDOM_SQUARE2);
|
||||||
fade_in_->setMode(FadeMode::IN);
|
fade_in_->setMode(Fade::Mode::IN);
|
||||||
fade_in_->activate();
|
fade_in_->activate();
|
||||||
|
|
||||||
fade_out_->setColor(param.fade.color);
|
fade_out_->setColor(param.fade.color);
|
||||||
fade_out_->setPostDuration(param.fade.post_duration);
|
fade_out_->setPostDuration(param.fade.post_duration_ms);
|
||||||
fade_out_->setType(FadeType::VENETIAN);
|
fade_out_->setType(Fade::Type::VENETIAN);
|
||||||
|
|
||||||
background_->setPos(param.game.play_area.rect);
|
background_->setPos(param.game.play_area.rect);
|
||||||
|
|
||||||
@@ -230,7 +219,8 @@ void Game::updatePlayers() {
|
|||||||
handlePlayerCollision(player, balloon);
|
handlePlayerCollision(player, balloon);
|
||||||
|
|
||||||
if (demo_.enabled && allPlayersAreNotPlaying()) {
|
if (demo_.enabled && allPlayersAreNotPlaying()) {
|
||||||
fade_out_->setType(FadeType::RANDOM_SQUARE);
|
fade_out_->setType(Fade::Type::RANDOM_SQUARE2);
|
||||||
|
fade_out_->setPostDuration(500);
|
||||||
fade_out_->activate();
|
fade_out_->activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,7 +271,7 @@ void Game::updateStage() {
|
|||||||
// Efectos de cambio de fase
|
// Efectos de cambio de fase
|
||||||
playSound("stage_change.wav");
|
playSound("stage_change.wav");
|
||||||
balloon_manager_->resetBalloonSpeed();
|
balloon_manager_->resetBalloonSpeed();
|
||||||
screen_->flash(FLASH_COLOR, 3);
|
screen_->flash(Colors::FLASH, 3);
|
||||||
screen_->shake();
|
screen_->shake();
|
||||||
|
|
||||||
// Obtener datos de la nueva fase
|
// Obtener datos de la nueva fase
|
||||||
@@ -466,35 +456,35 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player) {
|
|||||||
switch (item->getType()) {
|
switch (item->getType()) {
|
||||||
case ItemType::DISK: {
|
case ItemType::DISK: {
|
||||||
player->addScore(1000, Options::settings.hi_score_table.back().score);
|
player->addScore(1000, Options::settings.hi_score_table.back().score);
|
||||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(0)->getWidth()) / 2;
|
const auto X = item->getPosX() + ((item->getWidth() - game_text_textures_.at(0)->getWidth()) / 2);
|
||||||
createItemText(X, game_text_textures_.at(0));
|
createItemText(X, game_text_textures_.at(0));
|
||||||
playSound("item_pickup.wav");
|
playSound("item_pickup.wav");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ItemType::GAVINA: {
|
case ItemType::GAVINA: {
|
||||||
player->addScore(2500, Options::settings.hi_score_table.back().score);
|
player->addScore(2500, Options::settings.hi_score_table.back().score);
|
||||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(1)->getWidth()) / 2;
|
const auto X = item->getPosX() + ((item->getWidth() - game_text_textures_.at(1)->getWidth()) / 2);
|
||||||
createItemText(X, game_text_textures_.at(1));
|
createItemText(X, game_text_textures_.at(1));
|
||||||
playSound("item_pickup.wav");
|
playSound("item_pickup.wav");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ItemType::PACMAR: {
|
case ItemType::PACMAR: {
|
||||||
player->addScore(5000, Options::settings.hi_score_table.back().score);
|
player->addScore(5000, Options::settings.hi_score_table.back().score);
|
||||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(2)->getWidth()) / 2;
|
const auto X = item->getPosX() + ((item->getWidth() - game_text_textures_.at(2)->getWidth()) / 2);
|
||||||
createItemText(X, game_text_textures_.at(2));
|
createItemText(X, game_text_textures_.at(2));
|
||||||
playSound("item_pickup.wav");
|
playSound("item_pickup.wav");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ItemType::DEBIAN: {
|
case ItemType::DEBIAN: {
|
||||||
player->addScore(100000, Options::settings.hi_score_table.back().score);
|
player->addScore(100000, Options::settings.hi_score_table.back().score);
|
||||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(6)->getWidth()) / 2;
|
const auto X = item->getPosX() + ((item->getWidth() - game_text_textures_.at(6)->getWidth()) / 2);
|
||||||
createItemText(X, game_text_textures_.at(6));
|
createItemText(X, game_text_textures_.at(6));
|
||||||
playSound("debian_pickup.wav");
|
playSound("debian_pickup.wav");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ItemType::CLOCK: {
|
case ItemType::CLOCK: {
|
||||||
enableTimeStopItem();
|
enableTimeStopItem();
|
||||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(5)->getWidth()) / 2;
|
const auto X = item->getPosX() + ((item->getWidth() - game_text_textures_.at(5)->getWidth()) / 2);
|
||||||
createItemText(X, game_text_textures_.at(5));
|
createItemText(X, game_text_textures_.at(5));
|
||||||
playSound("item_pickup.wav");
|
playSound("item_pickup.wav");
|
||||||
break;
|
break;
|
||||||
@@ -502,11 +492,11 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player) {
|
|||||||
case ItemType::COFFEE: {
|
case ItemType::COFFEE: {
|
||||||
if (player->getCoffees() == 2) {
|
if (player->getCoffees() == 2) {
|
||||||
player->addScore(5000, Options::settings.hi_score_table.back().score);
|
player->addScore(5000, Options::settings.hi_score_table.back().score);
|
||||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(2)->getWidth()) / 2;
|
const auto X = item->getPosX() + ((item->getWidth() - game_text_textures_.at(2)->getWidth()) / 2);
|
||||||
createItemText(X, game_text_textures_.at(2));
|
createItemText(X, game_text_textures_.at(2));
|
||||||
} else {
|
} else {
|
||||||
player->giveExtraHit();
|
player->giveExtraHit();
|
||||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(4)->getWidth()) / 2;
|
const auto X = item->getPosX() + ((item->getWidth() - game_text_textures_.at(4)->getWidth()) / 2);
|
||||||
createItemText(X, game_text_textures_.at(4));
|
createItemText(X, game_text_textures_.at(4));
|
||||||
}
|
}
|
||||||
playSound("voice_coffee.wav");
|
playSound("voice_coffee.wav");
|
||||||
@@ -515,7 +505,7 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player) {
|
|||||||
case ItemType::COFFEE_MACHINE: {
|
case ItemType::COFFEE_MACHINE: {
|
||||||
player->setPowerUp();
|
player->setPowerUp();
|
||||||
coffee_machine_enabled_ = false;
|
coffee_machine_enabled_ = false;
|
||||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(3)->getWidth()) / 2;
|
const auto X = item->getPosX() + ((item->getWidth() - game_text_textures_.at(3)->getWidth()) / 2);
|
||||||
createItemText(X, game_text_textures_.at(3));
|
createItemText(X, game_text_textures_.at(3));
|
||||||
playSound("voice_power_up.wav");
|
playSound("voice_power_up.wav");
|
||||||
break;
|
break;
|
||||||
@@ -549,7 +539,7 @@ void Game::checkBulletCollision() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Maneja la colisión entre bala y Tabe
|
// Maneja la colisión entre bala y Tabe
|
||||||
auto Game::checkBulletTabeCollision(std::shared_ptr<Bullet> bullet) -> bool {
|
auto Game::checkBulletTabeCollision(const std::shared_ptr<Bullet> &bullet) -> bool {
|
||||||
if (!tabe_->isEnabled()) {
|
if (!tabe_->isEnabled()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -581,7 +571,7 @@ void Game::handleTabeHitEffects() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Maneja la colisión entre bala y globos
|
// Maneja la colisión entre bala y globos
|
||||||
auto Game::checkBulletBalloonCollision(std::shared_ptr<Bullet> bullet) -> bool {
|
auto Game::checkBulletBalloonCollision(const std::shared_ptr<Bullet> &bullet) -> bool {
|
||||||
for (auto &balloon : balloon_manager_->getBalloons()) {
|
for (auto &balloon : balloon_manager_->getBalloons()) {
|
||||||
if (!balloon->isEnabled() || balloon->isInvulnerable()) {
|
if (!balloon->isEnabled() || balloon->isInvulnerable()) {
|
||||||
continue;
|
continue;
|
||||||
@@ -598,7 +588,7 @@ auto Game::checkBulletBalloonCollision(std::shared_ptr<Bullet> bullet) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Procesa el impacto en un globo
|
// Procesa el impacto en un globo
|
||||||
void Game::processBalloonHit(std::shared_ptr<Bullet> bullet, std::shared_ptr<Balloon> balloon) {
|
void Game::processBalloonHit(const std::shared_ptr<Bullet> &bullet, const std::shared_ptr<Balloon> &balloon) {
|
||||||
auto player = getPlayer(bullet->getOwner());
|
auto player = getPlayer(bullet->getOwner());
|
||||||
|
|
||||||
handleItemDrop(balloon, player);
|
handleItemDrop(balloon, player);
|
||||||
@@ -608,7 +598,7 @@ void Game::processBalloonHit(std::shared_ptr<Bullet> bullet, std::shared_ptr<Bal
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Maneja la caída de items cuando se destruye un globo
|
// Maneja la caída de items cuando se destruye un globo
|
||||||
void Game::handleItemDrop(std::shared_ptr<Balloon> balloon, std::shared_ptr<Player> player) {
|
void Game::handleItemDrop(const std::shared_ptr<Balloon> &balloon, const std::shared_ptr<Player> &player) {
|
||||||
const auto DROPPED_ITEM = dropItem();
|
const auto DROPPED_ITEM = dropItem();
|
||||||
if (DROPPED_ITEM == ItemType::NONE || demo_.recording) {
|
if (DROPPED_ITEM == ItemType::NONE || demo_.recording) {
|
||||||
return;
|
return;
|
||||||
@@ -623,9 +613,9 @@ void Game::handleItemDrop(std::shared_ptr<Balloon> balloon, std::shared_ptr<Play
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Maneja la destrucción del globo y puntuación
|
// Maneja la destrucción del globo y puntuación
|
||||||
void Game::handleBalloonDestruction(std::shared_ptr<Balloon> balloon, std::shared_ptr<Player> player) {
|
void Game::handleBalloonDestruction(std::shared_ptr<Balloon> balloon, const std::shared_ptr<Player> &player) {
|
||||||
if (player->isPlaying()) {
|
if (player->isPlaying()) {
|
||||||
auto const SCORE = balloon_manager_->popBalloon(balloon) * player->getScoreMultiplier() * difficulty_score_multiplier_;
|
auto const SCORE = balloon_manager_->popBalloon(std::move(balloon)) * player->getScoreMultiplier() * difficulty_score_multiplier_;
|
||||||
player->addScore(SCORE, Options::settings.hi_score_table.back().score);
|
player->addScore(SCORE, Options::settings.hi_score_table.back().score);
|
||||||
player->incScoreMultiplier();
|
player->incScoreMultiplier();
|
||||||
}
|
}
|
||||||
@@ -758,7 +748,7 @@ void Game::freeItems() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Crea un objeto PathSprite
|
// Crea un objeto PathSprite
|
||||||
void Game::createItemText(int x, std::shared_ptr<Texture> texture) {
|
void Game::createItemText(int x, const std::shared_ptr<Texture> &texture) {
|
||||||
path_sprites_.emplace_back(std::make_unique<PathSprite>(texture));
|
path_sprites_.emplace_back(std::make_unique<PathSprite>(texture));
|
||||||
|
|
||||||
const auto W = texture->getWidth();
|
const auto W = texture->getWidth();
|
||||||
@@ -781,7 +771,7 @@ void Game::createItemText(int x, std::shared_ptr<Texture> texture) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Crea un objeto PathSprite
|
// Crea un objeto PathSprite
|
||||||
void Game::createMessage(const std::vector<Path> &paths, std::shared_ptr<Texture> texture) {
|
void Game::createMessage(const std::vector<Path> &paths, const std::shared_ptr<Texture> &texture) {
|
||||||
path_sprites_.emplace_back(std::make_unique<PathSprite>(texture));
|
path_sprites_.emplace_back(std::make_unique<PathSprite>(texture));
|
||||||
|
|
||||||
// Inicializa
|
// Inicializa
|
||||||
@@ -874,7 +864,7 @@ void Game::handlePlayerCollision(std::shared_ptr<Player> &player, std::shared_pt
|
|||||||
if (player->hasExtraHit()) {
|
if (player->hasExtraHit()) {
|
||||||
// Lo pierde
|
// Lo pierde
|
||||||
player->removeExtraHit();
|
player->removeExtraHit();
|
||||||
throwCoffee(player->getPosX() + (player->getWidth() / 2), player->getPosY() + (player->getHeight() / 2));
|
throwCoffee(player->getPosX() + (Player::WIDTH / 2), player->getPosY() + (Player::HEIGHT / 2));
|
||||||
playSound("coffee_out.wav");
|
playSound("coffee_out.wav");
|
||||||
screen_->shake();
|
screen_->shake();
|
||||||
} else {
|
} else {
|
||||||
@@ -986,12 +976,14 @@ void Game::fillCanvas() {
|
|||||||
|
|
||||||
// Dibuja los objetos
|
// Dibuja los objetos
|
||||||
background_->render();
|
background_->render();
|
||||||
renderPlayers();
|
|
||||||
renderSmartSprites();
|
|
||||||
renderItems();
|
|
||||||
balloon_manager_->render();
|
balloon_manager_->render();
|
||||||
|
renderSmartSprites(); // El cafe que sale cuando te golpean
|
||||||
|
renderItems();
|
||||||
tabe_->render();
|
tabe_->render();
|
||||||
renderBullets();
|
renderBullets();
|
||||||
|
renderPlayers();
|
||||||
|
|
||||||
renderPathSprites();
|
renderPathSprites();
|
||||||
|
|
||||||
// Deja el renderizador apuntando donde estaba
|
// Deja el renderizador apuntando donde estaba
|
||||||
@@ -1031,7 +1023,7 @@ void Game::initPaths() {
|
|||||||
const auto &texture = Resource::get()->getTexture("game_text_get_ready");
|
const auto &texture = Resource::get()->getTexture("game_text_get_ready");
|
||||||
const auto W = texture->getWidth();
|
const auto W = texture->getWidth();
|
||||||
const int X0 = -W;
|
const int X0 = -W;
|
||||||
const int X1 = param.game.play_area.center_x - W / 2;
|
const int X1 = param.game.play_area.center_x - (W / 2);
|
||||||
const int X2 = param.game.play_area.rect.w;
|
const int X2 = param.game.play_area.rect.w;
|
||||||
const int Y = param.game.play_area.center_y;
|
const int Y = param.game.play_area.center_y;
|
||||||
paths_.emplace_back(createPath(X0, X1, PathType::HORIZONTAL, Y, 80, easeOutQuint), 20);
|
paths_.emplace_back(createPath(X0, X1, PathType::HORIZONTAL, Y, 80, easeOutQuint), 20);
|
||||||
@@ -1043,7 +1035,7 @@ void Game::initPaths() {
|
|||||||
const auto &texture = Resource::get()->getTexture("game_text_last_stage");
|
const auto &texture = Resource::get()->getTexture("game_text_last_stage");
|
||||||
const auto H = texture->getHeight();
|
const auto H = texture->getHeight();
|
||||||
const int Y0 = param.game.play_area.rect.h - H;
|
const int Y0 = param.game.play_area.rect.h - H;
|
||||||
const int Y1 = param.game.play_area.center_y - H / 2;
|
const int Y1 = param.game.play_area.center_y - (H / 2);
|
||||||
const int Y2 = -H;
|
const int Y2 = -H;
|
||||||
const int X = param.game.play_area.center_x;
|
const int X = param.game.play_area.center_x;
|
||||||
paths_.emplace_back(createPath(Y0, Y1, PathType::VERTICAL, X, 80, easeOutQuint), 20);
|
paths_.emplace_back(createPath(Y0, Y1, PathType::VERTICAL, X, 80, easeOutQuint), 20);
|
||||||
@@ -1056,9 +1048,9 @@ void Game::initPaths() {
|
|||||||
const auto W = texture->getWidth();
|
const auto W = texture->getWidth();
|
||||||
const auto H = texture->getHeight();
|
const auto H = texture->getHeight();
|
||||||
const int X0 = -W;
|
const int X0 = -W;
|
||||||
const int X1 = param.game.play_area.center_x - W / 2;
|
const int X1 = param.game.play_area.center_x - (W / 2);
|
||||||
const int X2 = param.game.play_area.rect.w;
|
const int X2 = param.game.play_area.rect.w;
|
||||||
const int Y = param.game.play_area.center_y - H / 2 - 20;
|
const int Y = param.game.play_area.center_y - (H / 2) - 20;
|
||||||
paths_.emplace_back(createPath(X0, X1, PathType::HORIZONTAL, Y, 80, easeOutQuint), 400);
|
paths_.emplace_back(createPath(X0, X1, PathType::HORIZONTAL, Y, 80, easeOutQuint), 400);
|
||||||
paths_.emplace_back(createPath(X1, X2, PathType::HORIZONTAL, Y, 80, easeInQuint), 0);
|
paths_.emplace_back(createPath(X1, X2, PathType::HORIZONTAL, Y, 80, easeInQuint), 0);
|
||||||
}
|
}
|
||||||
@@ -1069,9 +1061,9 @@ void Game::initPaths() {
|
|||||||
const auto W = texture->getWidth();
|
const auto W = texture->getWidth();
|
||||||
const auto H = texture->getHeight();
|
const auto H = texture->getHeight();
|
||||||
const int X0 = param.game.play_area.rect.w;
|
const int X0 = param.game.play_area.rect.w;
|
||||||
const int X1 = param.game.play_area.center_x - W / 2;
|
const int X1 = param.game.play_area.center_x - (W / 2);
|
||||||
const int X2 = -W;
|
const int X2 = -W;
|
||||||
const int Y = param.game.play_area.center_y + H / 2 - 20;
|
const int Y = param.game.play_area.center_y + (H / 2) - 20;
|
||||||
paths_.emplace_back(createPath(X0, X1, PathType::HORIZONTAL, Y, 80, easeOutQuint), 400);
|
paths_.emplace_back(createPath(X0, X1, PathType::HORIZONTAL, Y, 80, easeOutQuint), 400);
|
||||||
paths_.emplace_back(createPath(X1, X2, PathType::HORIZONTAL, Y, 80, easeInQuint), 0);
|
paths_.emplace_back(createPath(X1, X2, PathType::HORIZONTAL, Y, 80, easeInQuint), 0);
|
||||||
}
|
}
|
||||||
@@ -1239,7 +1231,7 @@ void Game::checkInput() {
|
|||||||
// Verifica si alguno de los controladores ha solicitado una pausa y actualiza el estado de pausa del juego.
|
// Verifica si alguno de los controladores ha solicitado una pausa y actualiza el estado de pausa del juego.
|
||||||
void Game::checkPauseInput() {
|
void Game::checkPauseInput() {
|
||||||
// Comprueba los mandos
|
// Comprueba los mandos
|
||||||
for (auto gamepad : input_->getGamepads()) {
|
for (const auto &gamepad : input_->getGamepads()) {
|
||||||
if (input_->checkAction(Input::Action::PAUSE, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad)) {
|
if (input_->checkAction(Input::Action::PAUSE, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad)) {
|
||||||
pause_manager_->togglePlayerPause();
|
pause_manager_->togglePlayerPause();
|
||||||
return;
|
return;
|
||||||
@@ -1302,7 +1294,7 @@ void Game::handleFireInput(const std::shared_ptr<Player> &player, BulletType bul
|
|||||||
switch (bullet_type) {
|
switch (bullet_type) {
|
||||||
case BulletType::UP:
|
case BulletType::UP:
|
||||||
player->setInput(Input::Action::FIRE_CENTER);
|
player->setInput(Input::Action::FIRE_CENTER);
|
||||||
bullet.x = 2 + player->getPosX() + (player->getWidth() - Bullet::WIDTH) / 2;
|
bullet.x = 2 + player->getPosX() + (Player::WIDTH - Bullet::WIDTH) / 2;
|
||||||
bullet.y = player->getPosY() - (Bullet::HEIGHT / 2);
|
bullet.y = player->getPosY() - (Bullet::HEIGHT / 2);
|
||||||
break;
|
break;
|
||||||
case BulletType::LEFT:
|
case BulletType::LEFT:
|
||||||
@@ -1312,7 +1304,7 @@ void Game::handleFireInput(const std::shared_ptr<Player> &player, BulletType bul
|
|||||||
break;
|
break;
|
||||||
case BulletType::RIGHT:
|
case BulletType::RIGHT:
|
||||||
player->setInput(Input::Action::FIRE_RIGHT);
|
player->setInput(Input::Action::FIRE_RIGHT);
|
||||||
bullet.x = player->getPosX() + player->getWidth() - (Bullet::WIDTH / 2);
|
bullet.x = player->getPosX() + Player::WIDTH - (Bullet::WIDTH / 2);
|
||||||
bullet.y = player->getPosY();
|
bullet.y = player->getPosY();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1489,8 +1481,10 @@ void Game::initDemo(Player::Id player_id) {
|
|||||||
|
|
||||||
// Asigna cafes a los jugadores
|
// Asigna cafes a los jugadores
|
||||||
for (auto &player : players_) {
|
for (auto &player : players_) {
|
||||||
for (int i = 0; i < rand() % 3; ++i) {
|
if (player->isPlaying()) {
|
||||||
player->giveExtraHit();
|
for (int i = 0; i < rand() % 3; ++i) {
|
||||||
|
player->giveExtraHit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player->setInvulnerable(true);
|
player->setInvulnerable(true);
|
||||||
@@ -1616,7 +1610,7 @@ void Game::initPlayers(Player::Id player_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Registra los jugadores en Options
|
// Registra los jugadores en Options
|
||||||
for (auto player : players_) {
|
for (const auto &player : players_) {
|
||||||
Options::keyboard.addPlayer(player);
|
Options::keyboard.addPlayer(player);
|
||||||
Options::gamepad_manager.addPlayer(player);
|
Options::gamepad_manager.addPlayer(player);
|
||||||
}
|
}
|
||||||
@@ -1660,7 +1654,8 @@ void Game::updateDemo() {
|
|||||||
|
|
||||||
// Activa el fundido antes de acabar con los datos de la demo
|
// Activa el fundido antes de acabar con los datos de la demo
|
||||||
if (demo_.counter == TOTAL_DEMO_DATA - 200) {
|
if (demo_.counter == TOTAL_DEMO_DATA - 200) {
|
||||||
fade_out_->setType(FadeType::RANDOM_SQUARE);
|
fade_out_->setType(Fade::Type::RANDOM_SQUARE2);
|
||||||
|
fade_out_->setPostDuration(param.fade.post_duration_ms);
|
||||||
fade_out_->activate();
|
fade_out_->activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1777,11 +1772,11 @@ void Game::updateMenace() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto &stage = current_stage.value();
|
const auto &stage = current_stage.value();
|
||||||
const double fraction = stage_manager_->getCurrentStageProgressFraction();
|
const double FRACTION = stage_manager_->getCurrentStageProgressFraction();
|
||||||
const int difference = stage.getMaxMenace() - stage.getMinMenace();
|
const int DIFFERENCE = stage.getMaxMenace() - stage.getMinMenace();
|
||||||
|
|
||||||
// Aumenta el nivel de amenaza en función del progreso de la fase
|
// Aumenta el nivel de amenaza en función del progreso de la fase
|
||||||
menace_threshold_ = stage.getMinMenace() + (difference * fraction);
|
menace_threshold_ = stage.getMinMenace() + (DIFFERENCE * FRACTION);
|
||||||
|
|
||||||
if (menace_ < menace_threshold_) {
|
if (menace_ < menace_threshold_) {
|
||||||
balloon_manager_->deployRandomFormation(stage_manager_->getCurrentStageIndex());
|
balloon_manager_->deployRandomFormation(stage_manager_->getCurrentStageIndex());
|
||||||
@@ -1908,7 +1903,7 @@ void Game::handleDebugEvents(const SDL_Event &event) {
|
|||||||
}
|
}
|
||||||
case SDLK_5: // 5.000
|
case SDLK_5: // 5.000
|
||||||
{
|
{
|
||||||
const int X = players_.at(0)->getPosX() + (players_.at(0)->getWidth() - game_text_textures_[3]->getWidth()) / 2;
|
const int X = players_.at(0)->getPosX() + ((Player::WIDTH - game_text_textures_[3]->getWidth()) / 2);
|
||||||
createItemText(X, game_text_textures_.at(2));
|
createItemText(X, game_text_textures_.at(2));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1919,7 +1914,7 @@ void Game::handleDebugEvents(const SDL_Event &event) {
|
|||||||
}
|
}
|
||||||
case SDLK_7: // 100.000
|
case SDLK_7: // 100.000
|
||||||
{
|
{
|
||||||
const int X = players_.at(0)->getPosX() + (players_.at(0)->getWidth() - game_text_textures_[3]->getWidth()) / 2;
|
const int X = players_.at(0)->getPosX() + ((Player::WIDTH - game_text_textures_[3]->getWidth()) / 2);
|
||||||
createItemText(X, game_text_textures_.at(6));
|
createItemText(X, game_text_textures_.at(6));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1940,14 +1935,14 @@ void Game::handleDebugEvents(const SDL_Event &event) {
|
|||||||
++formation_id_;
|
++formation_id_;
|
||||||
balloon_manager_->destroyAllBalloons();
|
balloon_manager_->destroyAllBalloons();
|
||||||
balloon_manager_->deployFormation(formation_id_);
|
balloon_manager_->deployFormation(formation_id_);
|
||||||
std::cout << formation_id_ << std::endl;
|
std::cout << formation_id_ << '\n';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SDLK_KP_MINUS: {
|
case SDLK_KP_MINUS: {
|
||||||
--formation_id_;
|
--formation_id_;
|
||||||
balloon_manager_->destroyAllBalloons();
|
balloon_manager_->destroyAllBalloons();
|
||||||
balloon_manager_->deployFormation(formation_id_);
|
balloon_manager_->deployFormation(formation_id_);
|
||||||
std::cout << formation_id_ << std::endl;
|
std::cout << formation_id_ << '\n';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -33,29 +33,29 @@ namespace Difficulty {
|
|||||||
enum class Code;
|
enum class Code;
|
||||||
} // namespace Difficulty
|
} // namespace Difficulty
|
||||||
|
|
||||||
// Clase Game
|
// --- Clase Game: gestor principal del juego ---
|
||||||
class Game {
|
class Game {
|
||||||
public:
|
public:
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr bool DEMO_OFF = false;
|
static constexpr bool DEMO_OFF = false; // Modo demo desactivado
|
||||||
static constexpr bool DEMO_ON = true;
|
static constexpr bool DEMO_ON = true; // Modo demo activado
|
||||||
|
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
Game(Player::Id player_id, int current_stage, bool demo);
|
Game(Player::Id player_id, int current_stage, bool demo); // Constructor principal
|
||||||
~Game();
|
~Game(); // Destructor
|
||||||
|
|
||||||
// --- Bucle principal ---
|
// --- Bucle principal ---
|
||||||
void run();
|
void run(); // Ejecuta el bucle principal del juego
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Tipos internos ---
|
// --- Enums ---
|
||||||
enum class State {
|
enum class State {
|
||||||
FADE_IN,
|
FADE_IN, // Transición de entrada
|
||||||
ENTERING_PLAYER,
|
ENTERING_PLAYER, // Jugador entrando
|
||||||
SHOWING_GET_READY_MESSAGE,
|
SHOWING_GET_READY_MESSAGE, // Mostrando mensaje de preparado
|
||||||
PLAYING,
|
PLAYING, // Jugando
|
||||||
COMPLETED,
|
COMPLETED, // Juego completado
|
||||||
GAME_OVER,
|
GAME_OVER, // Fin del juego
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Constantes internas ---
|
// --- Constantes internas ---
|
||||||
@@ -216,9 +216,9 @@ class Game {
|
|||||||
void freeBullets(); // Libera memoria del vector de balas
|
void freeBullets(); // Libera memoria del vector de balas
|
||||||
|
|
||||||
// --- Colisiones específicas de balas ---
|
// --- Colisiones específicas de balas ---
|
||||||
auto checkBulletTabeCollision(std::shared_ptr<Bullet> bullet) -> bool; // Detecta colisión bala-Tabe
|
auto checkBulletTabeCollision(const std::shared_ptr<Bullet> &bullet) -> bool; // Detecta colisión bala-Tabe
|
||||||
auto checkBulletBalloonCollision(std::shared_ptr<Bullet> bullet) -> bool; // Detecta colisión bala-globo
|
auto checkBulletBalloonCollision(const std::shared_ptr<Bullet> &bullet) -> bool; // Detecta colisión bala-globo
|
||||||
void processBalloonHit(std::shared_ptr<Bullet> bullet, std::shared_ptr<Balloon> balloon); // Procesa impacto en globo
|
void processBalloonHit(const std::shared_ptr<Bullet> &bullet, const std::shared_ptr<Balloon> &balloon); // Procesa impacto en globo
|
||||||
|
|
||||||
// --- Sistema de ítems y power-ups ---
|
// --- Sistema de ítems y power-ups ---
|
||||||
void updateItems(); // Actualiza posición y estado de todos los ítems
|
void updateItems(); // Actualiza posición y estado de todos los ítems
|
||||||
@@ -235,7 +235,7 @@ class Game {
|
|||||||
void throwCoffee(int x, int y); // Crea efecto de café arrojado al ser golpeado
|
void throwCoffee(int x, int y); // Crea efecto de café arrojado al ser golpeado
|
||||||
|
|
||||||
// --- Gestión de caída de ítems ---
|
// --- Gestión de caída de ítems ---
|
||||||
void handleItemDrop(std::shared_ptr<Balloon> balloon, std::shared_ptr<Player> player); // Gestiona caída de ítem desde globo
|
void handleItemDrop(const std::shared_ptr<Balloon> &balloon, const std::shared_ptr<Player> &player); // Gestiona caída de ítem desde globo
|
||||||
|
|
||||||
// --- Sprites inteligentes (smartsprites) ---
|
// --- Sprites inteligentes (smartsprites) ---
|
||||||
void updateSmartSprites(); // Actualiza todos los sprites con lógica propia
|
void updateSmartSprites(); // Actualiza todos los sprites con lógica propia
|
||||||
@@ -249,17 +249,16 @@ class Game {
|
|||||||
void initPaths(); // Inicializa rutas predefinidas para animaciones
|
void initPaths(); // Inicializa rutas predefinidas para animaciones
|
||||||
|
|
||||||
// --- Creación de sprites especiales ---
|
// --- Creación de sprites especiales ---
|
||||||
void createItemText(int x, std::shared_ptr<Texture> texture); // Crea texto animado para ítems
|
void createItemText(int x, const std::shared_ptr<Texture> &texture); // Crea texto animado para ítems
|
||||||
void createMessage(const std::vector<Path> &paths, std::shared_ptr<Texture> texture); // Crea mensaje con animación por ruta
|
void createMessage(const std::vector<Path> &paths, const std::shared_ptr<Texture> &texture); // Crea mensaje con animación por ruta
|
||||||
|
|
||||||
// --- Sistema de globos y enemigos ---
|
// --- Sistema de globos y enemigos ---
|
||||||
void handleBalloonDestruction(std::shared_ptr<Balloon> balloon, std::shared_ptr<Player> player); // Procesa destrucción de globo
|
void handleBalloonDestruction(std::shared_ptr<Balloon> balloon, const std::shared_ptr<Player> &player); // Procesa destrucción de globo
|
||||||
void handleTabeHitEffects(); // Gestiona efectos al golpear a Tabe
|
void handleTabeHitEffects(); // Gestiona efectos al golpear a Tabe
|
||||||
void checkAndUpdateBalloonSpeed(); // Ajusta velocidad de globos según progreso
|
void checkAndUpdateBalloonSpeed(); // Ajusta velocidad de globos según progreso
|
||||||
|
|
||||||
// --- Gestión de fases y progresión ---
|
// --- Gestión de fases y progresión ---
|
||||||
void updateStage(); // Verifica y actualiza cambio de fase
|
void updateStage(); // Verifica y actualiza cambio de fase
|
||||||
void setTotalPower(); // Calcula poder total necesario para completar el juego
|
|
||||||
void initDifficultyVars(); // Inicializa variables de dificultad
|
void initDifficultyVars(); // Inicializa variables de dificultad
|
||||||
|
|
||||||
// --- Sistema de amenaza ---
|
// --- Sistema de amenaza ---
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "audio.h" // Para Audio
|
#include "audio.h" // Para Audio
|
||||||
#include "background.h" // Para Background
|
#include "background.h" // Para Background
|
||||||
#include "color.h" // Para Color, easeOutQuint, NO_TEXT_COLOR
|
#include "color.h" // Para Color, easeOutQuint, Colors::NO_COLOR_MOD
|
||||||
#include "fade.h" // Para Fade, FadeMode, FadeType
|
#include "fade.h" // Para Fade, FadeMode, FadeType
|
||||||
#include "global_events.h" // Para check
|
#include "global_events.h" // Para check
|
||||||
#include "global_inputs.h" // Para check
|
#include "global_inputs.h" // Para check
|
||||||
@@ -29,15 +29,7 @@
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
HiScoreTable::HiScoreTable()
|
HiScoreTable::HiScoreTable()
|
||||||
: renderer_(Screen::get()->getRenderer()),
|
: renderer_(Screen::get()->getRenderer()), backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), fade_(std::make_unique<Fade>()), background_(std::make_unique<Background>()), ticks_(0), view_area_(SDL_FRect{0, 0, param.game.width, param.game.height}), fade_mode_(Fade::Mode::IN), background_fade_color_(Color(0, 0, 0)) {
|
||||||
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
|
||||||
fade_(std::make_unique<Fade>()),
|
|
||||||
background_(std::make_unique<Background>()),
|
|
||||||
|
|
||||||
ticks_(0),
|
|
||||||
view_area_(SDL_FRect{0, 0, param.game.width, param.game.height}),
|
|
||||||
fade_mode_(FadeMode::IN),
|
|
||||||
background_fade_color_(Color(0, 0, 0)) {
|
|
||||||
// Inicializa el resto
|
// Inicializa el resto
|
||||||
Section::name = Section::Name::HI_SCORE_TABLE;
|
Section::name = Section::Name::HI_SCORE_TABLE;
|
||||||
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
|
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
|
||||||
@@ -133,13 +125,13 @@ void HiScoreTable::run() {
|
|||||||
void HiScoreTable::updateFade() {
|
void HiScoreTable::updateFade() {
|
||||||
fade_->update();
|
fade_->update();
|
||||||
|
|
||||||
if (fade_->hasEnded() && fade_mode_ == FadeMode::IN) {
|
if (fade_->hasEnded() && fade_mode_ == Fade::Mode::IN) {
|
||||||
fade_->reset();
|
fade_->reset();
|
||||||
fade_mode_ = FadeMode::OUT;
|
fade_mode_ = Fade::Mode::OUT;
|
||||||
fade_->setMode(fade_mode_);
|
fade_->setMode(fade_mode_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fade_->hasEnded() && fade_mode_ == FadeMode::OUT) {
|
if (fade_->hasEnded() && fade_mode_ == Fade::Mode::OUT) {
|
||||||
Section::name = (Section::options == Section::Options::HI_SCORE_AFTER_PLAYING)
|
Section::name = (Section::options == Section::Options::HI_SCORE_AFTER_PLAYING)
|
||||||
? Section::Name::TITLE
|
? Section::Name::TITLE
|
||||||
: Section::Name::INSTRUCTIONS;
|
: Section::Name::INSTRUCTIONS;
|
||||||
@@ -178,11 +170,11 @@ void HiScoreTable::createSprites() {
|
|||||||
float backbuffer_height;
|
float backbuffer_height;
|
||||||
SDL_GetTextureSize(backbuffer_, &backbuffer_width, &backbuffer_height);
|
SDL_GetTextureSize(backbuffer_, &backbuffer_width, &backbuffer_height);
|
||||||
|
|
||||||
constexpr int ENTRY_LENGHT = 22;
|
constexpr int ENTRY_LENGTH = 22;
|
||||||
constexpr int MAX_NAMES = 10;
|
constexpr int MAX_NAMES = 10;
|
||||||
const int SPACE_BETWEEN_HEADER = entry_text->getCharacterSize() * 4;
|
const int SPACE_BETWEEN_HEADER = entry_text->getCharacterSize() * 4;
|
||||||
const int SPACE_BETWEEN_LINES = entry_text->getCharacterSize() * 2;
|
const int SPACE_BETWEEN_LINES = entry_text->getCharacterSize() * 2;
|
||||||
const int SIZE = SPACE_BETWEEN_HEADER + SPACE_BETWEEN_LINES * (MAX_NAMES - 1) + entry_text->getCharacterSize();
|
const int SIZE = SPACE_BETWEEN_HEADER + (SPACE_BETWEEN_LINES * (MAX_NAMES - 1)) + entry_text->getCharacterSize();
|
||||||
const int FIRST_LINE = (param.game.height - SIZE) / 2;
|
const int FIRST_LINE = (param.game.height - SIZE) / 2;
|
||||||
|
|
||||||
// Crea el sprite para el texto de cabecera
|
// Crea el sprite para el texto de cabecera
|
||||||
@@ -191,13 +183,13 @@ void HiScoreTable::createSprites() {
|
|||||||
|
|
||||||
// Crea los sprites para las entradas en la tabla de puntuaciones
|
// Crea los sprites para las entradas en la tabla de puntuaciones
|
||||||
const int ANIMATION = rand() % 4;
|
const int ANIMATION = rand() % 4;
|
||||||
const std::string SAMPLE_LINE(ENTRY_LENGHT + 3, ' ');
|
const std::string SAMPLE_LINE(ENTRY_LENGTH + 3, ' ');
|
||||||
auto sample_entry = std::make_unique<Sprite>(entry_text->writeDXToTexture(Text::SHADOW, SAMPLE_LINE, 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR));
|
auto sample_entry = std::make_unique<Sprite>(entry_text->writeDXToTexture(Text::SHADOW, SAMPLE_LINE, 1, Colors::NO_COLOR_MOD, 1, Colors::SHADOW_TEXT));
|
||||||
const auto ENTRY_WIDTH = sample_entry->getWidth();
|
const auto ENTRY_WIDTH = sample_entry->getWidth();
|
||||||
for (int i = 0; i < MAX_NAMES; ++i) {
|
for (int i = 0; i < MAX_NAMES; ++i) {
|
||||||
const auto TABLE_POSITION = format(i + 1) + ". ";
|
const auto TABLE_POSITION = format(i + 1) + ". ";
|
||||||
const auto SCORE = format(Options::settings.hi_score_table.at(i).score);
|
const auto SCORE = format(Options::settings.hi_score_table.at(i).score);
|
||||||
const auto NUM_DOTS = ENTRY_LENGHT - Options::settings.hi_score_table.at(i).name.size() - SCORE.size();
|
const auto NUM_DOTS = ENTRY_LENGTH - Options::settings.hi_score_table.at(i).name.size() - SCORE.size();
|
||||||
const auto *const ONE_CC = Options::settings.hi_score_table.at(i).one_credit_complete ? " }" : "";
|
const auto *const ONE_CC = Options::settings.hi_score_table.at(i).one_credit_complete ? " }" : "";
|
||||||
std::string dots;
|
std::string dots;
|
||||||
for (int j = 0; j < (int)NUM_DOTS; ++j) {
|
for (int j = 0; j < (int)NUM_DOTS; ++j) {
|
||||||
@@ -205,7 +197,7 @@ void HiScoreTable::createSprites() {
|
|||||||
}
|
}
|
||||||
const auto LINE = TABLE_POSITION + Options::settings.hi_score_table.at(i).name + dots + SCORE + ONE_CC;
|
const auto LINE = TABLE_POSITION + Options::settings.hi_score_table.at(i).name + dots + SCORE + ONE_CC;
|
||||||
|
|
||||||
entry_names_.emplace_back(std::make_shared<PathSprite>(entry_text->writeDXToTexture(Text::SHADOW, LINE, 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR)));
|
entry_names_.emplace_back(std::make_shared<PathSprite>(entry_text->writeDXToTexture(Text::SHADOW, LINE, 1, Colors::NO_COLOR_MOD, 1, Colors::SHADOW_TEXT)));
|
||||||
const int DEFAULT_POS_X = (backbuffer_width - ENTRY_WIDTH) / 2;
|
const int DEFAULT_POS_X = (backbuffer_width - ENTRY_WIDTH) / 2;
|
||||||
const int POS_X = (i < 9) ? DEFAULT_POS_X : DEFAULT_POS_X - entry_text->getCharacterSize();
|
const int POS_X = (i < 9) ? DEFAULT_POS_X : DEFAULT_POS_X - entry_text->getCharacterSize();
|
||||||
const int POS_Y = (i * SPACE_BETWEEN_LINES) + FIRST_LINE + SPACE_BETWEEN_HEADER;
|
const int POS_Y = (i * SPACE_BETWEEN_LINES) + FIRST_LINE + SPACE_BETWEEN_HEADER;
|
||||||
@@ -272,14 +264,15 @@ void HiScoreTable::updateSprites() {
|
|||||||
// Inicializa el fade
|
// Inicializa el fade
|
||||||
void HiScoreTable::initFade() {
|
void HiScoreTable::initFade() {
|
||||||
fade_->setColor(param.fade.color);
|
fade_->setColor(param.fade.color);
|
||||||
fade_->setType(FadeType::RANDOM_SQUARE);
|
fade_->setType(Fade::Type::RANDOM_SQUARE2);
|
||||||
fade_->setPostDuration(param.fade.post_duration);
|
fade_->setPostDuration(param.fade.post_duration_ms);
|
||||||
fade_->setMode(fade_mode_);
|
fade_->setMode(fade_mode_);
|
||||||
fade_->activate();
|
fade_->activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa el fondo
|
// Inicializa el fondo
|
||||||
void HiScoreTable::initBackground() {
|
void HiScoreTable::initBackground() {
|
||||||
|
background_->setManualMode(true);
|
||||||
background_->setPos(param.game.game_area.rect);
|
background_->setPos(param.game.game_area.rect);
|
||||||
background_->setCloudsSpeed(-0.1F);
|
background_->setCloudsSpeed(-0.1F);
|
||||||
|
|
||||||
@@ -291,7 +284,7 @@ void HiScoreTable::initBackground() {
|
|||||||
background_->setTransition(0.0F);
|
background_->setTransition(0.0F);
|
||||||
background_->setSunProgression(1.0F);
|
background_->setSunProgression(1.0F);
|
||||||
background_->setMoonProgression(0.0F);
|
background_->setMoonProgression(0.0F);
|
||||||
background_fade_color_ = GREEN_SKY_COLOR;
|
background_fade_color_ = Colors::GREEN_SKY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +294,7 @@ void HiScoreTable::initBackground() {
|
|||||||
background_->setTransition(0.0F);
|
background_->setTransition(0.0F);
|
||||||
background_->setSunProgression(0.65F);
|
background_->setSunProgression(0.65F);
|
||||||
background_->setMoonProgression(0.0F);
|
background_->setMoonProgression(0.0F);
|
||||||
background_fade_color_ = PINK_SKY_COLOR;
|
background_fade_color_ = Colors::PINK_SKY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +304,7 @@ void HiScoreTable::initBackground() {
|
|||||||
background_->setTransition(0.0F);
|
background_->setTransition(0.0F);
|
||||||
background_->setSunProgression(0.0F);
|
background_->setSunProgression(0.0F);
|
||||||
background_->setMoonProgression(0.0F);
|
background_->setMoonProgression(0.0F);
|
||||||
background_fade_color_ = BLUE_SKY_COLOR;
|
background_fade_color_ = Colors::BLUE_SKY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,7 +315,7 @@ void HiScoreTable::initBackground() {
|
|||||||
|
|
||||||
// Obtiene un color del vector de colores de entradas
|
// Obtiene un color del vector de colores de entradas
|
||||||
auto HiScoreTable::getEntryColor(int counter) -> Color {
|
auto HiScoreTable::getEntryColor(int counter) -> Color {
|
||||||
int cycle_length = entry_colors_.size() * 2 - 2;
|
int cycle_length = (entry_colors_.size() * 2) - 2;
|
||||||
size_t n = counter % cycle_length;
|
size_t n = counter % cycle_length;
|
||||||
|
|
||||||
size_t index;
|
size_t index;
|
||||||
|
|||||||
@@ -7,24 +7,19 @@
|
|||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "color.h" // Para Color
|
#include "color.h" // Para Color
|
||||||
|
#include "fade.h" // Para Fade
|
||||||
#include "path_sprite.h" // Para Path, PathSprite (ptr only)
|
#include "path_sprite.h" // Para Path, PathSprite (ptr only)
|
||||||
|
|
||||||
class Background;
|
class Background;
|
||||||
class Fade;
|
|
||||||
class Sprite;
|
class Sprite;
|
||||||
enum class FadeMode : Uint8;
|
|
||||||
|
|
||||||
/*
|
// --- Clase HiScoreTable: muestra la tabla de puntuaciones más altas ---
|
||||||
Esta clase gestiona un estado del programa. Se encarga de mostrar la tabla con las puntuaciones
|
// Esta clase gestiona un estado del programa. Se encarga de mostrar la tabla con las puntuaciones
|
||||||
más altas. Para ello utiliza un objeto que se encarga de pintar el fondo y una textura
|
// más altas. Para ello utiliza un objeto que se encarga de pintar el fondo y una textura
|
||||||
sobre la que escribe las puntuaciones. Esta textura se recorre modificando la ventana de vista
|
// sobre la que escribe las puntuaciones. Esta textura se recorre modificando la ventana de vista
|
||||||
para dar el efecto de que la textura se mueve sobre la pantalla.
|
// para dar el efecto de que la textura se mueve sobre la pantalla.
|
||||||
|
// Para mejorar la legibilidad de los textos, el objeto que dibuja el fondo es capaz de modificar
|
||||||
Para mejorar la legibilidad de los textos, el objeto que dibuja el fondo es capaz de modificar
|
// su atenuación.
|
||||||
su atenuación.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Clase HiScoreTable
|
|
||||||
class HiScoreTable {
|
class HiScoreTable {
|
||||||
public:
|
public:
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
@@ -52,7 +47,7 @@ class HiScoreTable {
|
|||||||
Uint16 counter_ = 0; // Contador
|
Uint16 counter_ = 0; // Contador
|
||||||
Uint64 ticks_; // Contador de ticks para ajustar la velocidad del programa
|
Uint64 ticks_; // Contador de ticks para ajustar la velocidad del programa
|
||||||
SDL_FRect view_area_; // Parte de la textura que se muestra en pantalla
|
SDL_FRect view_area_; // Parte de la textura que se muestra en pantalla
|
||||||
FadeMode fade_mode_; // Modo de fade a utilizar
|
Fade::Mode fade_mode_; // Modo de fade a utilizar
|
||||||
Color background_fade_color_; // Color de atenuación del fondo
|
Color background_fade_color_; // Color de atenuación del fondo
|
||||||
std::vector<Color> entry_colors_; // Colores para destacar las entradas en la tabla
|
std::vector<Color> entry_colors_; // Colores para destacar las entradas en la tabla
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "audio.h" // Para Audio
|
#include "audio.h" // Para Audio
|
||||||
#include "color.h" // Para Color, SHADOW_TEXT_COLOR, Zone, NO_TEXT_C...
|
#include "color.h" // Para Color, Colors::SHADOW_TEXT, Zone, NO_TEXT_C...
|
||||||
#include "fade.h" // Para Fade, FadeMode, FadeType
|
#include "fade.h" // Para Fade, FadeMode, FadeType
|
||||||
#include "global_events.h" // Para check
|
#include "global_events.h" // Para check
|
||||||
#include "global_inputs.h" // Para check
|
#include "global_inputs.h" // Para check
|
||||||
@@ -26,12 +26,7 @@
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Instructions::Instructions()
|
Instructions::Instructions()
|
||||||
: renderer_(Screen::get()->getRenderer()),
|
: renderer_(Screen::get()->getRenderer()), texture_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), text_(Resource::get()->getText("smb2")), tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::STATIC)), fade_(std::make_unique<Fade>()) {
|
||||||
texture_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
|
||||||
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
|
||||||
text_(Resource::get()->getText("smb2")),
|
|
||||||
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::STATIC)),
|
|
||||||
fade_(std::make_unique<Fade>()) {
|
|
||||||
// Configura las texturas
|
// Configura las texturas
|
||||||
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
|
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
|
||||||
SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
|
SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
|
||||||
@@ -43,9 +38,9 @@ Instructions::Instructions()
|
|||||||
// Inicializa objetos
|
// Inicializa objetos
|
||||||
tiled_bg_->setColor(param.title.bg_color);
|
tiled_bg_->setColor(param.title.bg_color);
|
||||||
fade_->setColor(param.fade.color);
|
fade_->setColor(param.fade.color);
|
||||||
fade_->setType(FadeType::FULLSCREEN);
|
fade_->setType(Fade::Type::FULLSCREEN);
|
||||||
fade_->setPostDuration(param.fade.post_duration);
|
fade_->setPostDuration(param.fade.post_duration_ms);
|
||||||
fade_->setMode(FadeMode::IN);
|
fade_->setMode(Fade::Mode::IN);
|
||||||
fade_->activate();
|
fade_->activate();
|
||||||
|
|
||||||
// Inicializa las líneas con un retraso progresivo de 50 ms
|
// Inicializa las líneas con un retraso progresivo de 50 ms
|
||||||
@@ -137,7 +132,7 @@ void Instructions::fillTexture() {
|
|||||||
const int FIRST_LINE = (param.game.height - SIZE) / 2;
|
const int FIRST_LINE = (param.game.height - SIZE) / 2;
|
||||||
|
|
||||||
// Calcula cual es el texto más largo de las descripciones de los items
|
// Calcula cual es el texto más largo de las descripciones de los items
|
||||||
int lenght = 0;
|
int length = 0;
|
||||||
const std::array<std::string, 5> ITEM_DESCRIPTIONS = {
|
const std::array<std::string, 5> ITEM_DESCRIPTIONS = {
|
||||||
Lang::getText("[INSTRUCTIONS] 07"),
|
Lang::getText("[INSTRUCTIONS] 07"),
|
||||||
Lang::getText("[INSTRUCTIONS] 08"),
|
Lang::getText("[INSTRUCTIONS] 08"),
|
||||||
@@ -146,32 +141,32 @@ void Instructions::fillTexture() {
|
|||||||
Lang::getText("[INSTRUCTIONS] 11")};
|
Lang::getText("[INSTRUCTIONS] 11")};
|
||||||
for (const auto &desc : ITEM_DESCRIPTIONS) {
|
for (const auto &desc : ITEM_DESCRIPTIONS) {
|
||||||
const int L = text_->length(desc);
|
const int L = text_->length(desc);
|
||||||
lenght = L > lenght ? L : lenght;
|
length = L > length ? L : length;
|
||||||
}
|
}
|
||||||
const int ANCHOR_ITEM = (param.game.width - (lenght + X_OFFSET)) / 2;
|
const int ANCHOR_ITEM = (param.game.width - (length + X_OFFSET)) / 2;
|
||||||
|
|
||||||
auto caption_style = Text::Style(Text::CENTER | Text::COLOR | Text::SHADOW, ORANGE_TEXT_COLOR, SHADOW_TEXT_COLOR);
|
auto caption_style = Text::Style(Text::CENTER | Text::COLOR | Text::SHADOW, Colors::ORANGE_TEXT, Colors::SHADOW_TEXT);
|
||||||
auto text_style = Text::Style(Text::CENTER | Text::COLOR | Text::SHADOW, NO_TEXT_COLOR, SHADOW_TEXT_COLOR);
|
auto text_style = Text::Style(Text::CENTER | Text::COLOR | Text::SHADOW, Colors::NO_COLOR_MOD, Colors::SHADOW_TEXT);
|
||||||
|
|
||||||
// Escribe el texto de las instrucciones
|
// Escribe el texto de las instrucciones
|
||||||
text_->writeStyle(param.game.game_area.center_x, FIRST_LINE, Lang::getText("[INSTRUCTIONS] 01"), caption_style);
|
text_->writeStyle(param.game.game_area.center_x, FIRST_LINE, Lang::getText("[INSTRUCTIONS] 01"), caption_style);
|
||||||
|
|
||||||
const int ANCHOR1 = FIRST_LINE + SPACE_POST_HEADER;
|
const int ANCHOR1 = FIRST_LINE + SPACE_POST_HEADER;
|
||||||
text_->writeStyle(param.game.game_area.center_x, ANCHOR1 + SPACE_BETWEEN_LINES * 0, Lang::getText("[INSTRUCTIONS] 02"), text_style);
|
text_->writeStyle(param.game.game_area.center_x, ANCHOR1 + (SPACE_BETWEEN_LINES * 0), Lang::getText("[INSTRUCTIONS] 02"), text_style);
|
||||||
text_->writeStyle(param.game.game_area.center_x, ANCHOR1 + SPACE_BETWEEN_LINES * 1, Lang::getText("[INSTRUCTIONS] 03"), text_style);
|
text_->writeStyle(param.game.game_area.center_x, ANCHOR1 + (SPACE_BETWEEN_LINES * 1), Lang::getText("[INSTRUCTIONS] 03"), text_style);
|
||||||
text_->writeStyle(param.game.game_area.center_x, ANCHOR1 + SPACE_NEW_PARAGRAPH + SPACE_BETWEEN_LINES * 2, Lang::getText("[INSTRUCTIONS] 04"), text_style);
|
text_->writeStyle(param.game.game_area.center_x, ANCHOR1 + SPACE_NEW_PARAGRAPH + (SPACE_BETWEEN_LINES * 2), Lang::getText("[INSTRUCTIONS] 04"), text_style);
|
||||||
text_->writeStyle(param.game.game_area.center_x, ANCHOR1 + SPACE_NEW_PARAGRAPH + SPACE_BETWEEN_LINES * 3, Lang::getText("[INSTRUCTIONS] 05"), text_style);
|
text_->writeStyle(param.game.game_area.center_x, ANCHOR1 + SPACE_NEW_PARAGRAPH + (SPACE_BETWEEN_LINES * 3), Lang::getText("[INSTRUCTIONS] 05"), text_style);
|
||||||
|
|
||||||
// Escribe el texto de los objetos y sus puntos
|
// Escribe el texto de los objetos y sus puntos
|
||||||
const int ANCHOR2 = ANCHOR1 + SPACE_PRE_HEADER + SPACE_NEW_PARAGRAPH + SPACE_BETWEEN_LINES * 3;
|
const int ANCHOR2 = ANCHOR1 + SPACE_PRE_HEADER + SPACE_NEW_PARAGRAPH + (SPACE_BETWEEN_LINES * 3);
|
||||||
text_->writeStyle(param.game.game_area.center_x, ANCHOR2, Lang::getText("[INSTRUCTIONS] 06"), caption_style);
|
text_->writeStyle(param.game.game_area.center_x, ANCHOR2, Lang::getText("[INSTRUCTIONS] 06"), caption_style);
|
||||||
|
|
||||||
const int ANCHOR3 = ANCHOR2 + SPACE_POST_HEADER;
|
const int ANCHOR3 = ANCHOR2 + SPACE_POST_HEADER;
|
||||||
text_->writeShadowed(ANCHOR_ITEM + X_OFFSET, ANCHOR3 + SPACE_BETWEEN_ITEM_LINES * 0, Lang::getText("[INSTRUCTIONS] 07"), SHADOW_TEXT_COLOR);
|
text_->writeShadowed(ANCHOR_ITEM + X_OFFSET, ANCHOR3 + (SPACE_BETWEEN_ITEM_LINES * 0), Lang::getText("[INSTRUCTIONS] 07"), Colors::SHADOW_TEXT);
|
||||||
text_->writeShadowed(ANCHOR_ITEM + X_OFFSET, ANCHOR3 + SPACE_BETWEEN_ITEM_LINES * 1, Lang::getText("[INSTRUCTIONS] 08"), SHADOW_TEXT_COLOR);
|
text_->writeShadowed(ANCHOR_ITEM + X_OFFSET, ANCHOR3 + (SPACE_BETWEEN_ITEM_LINES * 1), Lang::getText("[INSTRUCTIONS] 08"), Colors::SHADOW_TEXT);
|
||||||
text_->writeShadowed(ANCHOR_ITEM + X_OFFSET, ANCHOR3 + SPACE_BETWEEN_ITEM_LINES * 2, Lang::getText("[INSTRUCTIONS] 09"), SHADOW_TEXT_COLOR);
|
text_->writeShadowed(ANCHOR_ITEM + X_OFFSET, ANCHOR3 + (SPACE_BETWEEN_ITEM_LINES * 2), Lang::getText("[INSTRUCTIONS] 09"), Colors::SHADOW_TEXT);
|
||||||
text_->writeShadowed(ANCHOR_ITEM + X_OFFSET, ANCHOR3 + SPACE_BETWEEN_ITEM_LINES * 3, Lang::getText("[INSTRUCTIONS] 10"), SHADOW_TEXT_COLOR);
|
text_->writeShadowed(ANCHOR_ITEM + X_OFFSET, ANCHOR3 + (SPACE_BETWEEN_ITEM_LINES * 3), Lang::getText("[INSTRUCTIONS] 10"), Colors::SHADOW_TEXT);
|
||||||
text_->writeShadowed(ANCHOR_ITEM + X_OFFSET, ANCHOR3 + SPACE_BETWEEN_ITEM_LINES * 4, Lang::getText("[INSTRUCTIONS] 11"), SHADOW_TEXT_COLOR);
|
text_->writeShadowed(ANCHOR_ITEM + X_OFFSET, ANCHOR3 + (SPACE_BETWEEN_ITEM_LINES * 4), Lang::getText("[INSTRUCTIONS] 11"), Colors::SHADOW_TEXT);
|
||||||
|
|
||||||
// Deja el renderizador como estaba
|
// Deja el renderizador como estaba
|
||||||
SDL_SetRenderTarget(renderer_, temp);
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ class TiledBG;
|
|||||||
por la pantalla sobre el mosaico de fondo (gestionado por el correspondiente objeto).
|
por la pantalla sobre el mosaico de fondo (gestionado por el correspondiente objeto).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Estructura para almacenar información de línea animada
|
// --- Estructuras ---
|
||||||
struct Line {
|
struct Line { // Almacena información de línea animada
|
||||||
int y; // Coordenada Y de la línea
|
int y; // Coordenada Y de la línea
|
||||||
float x; // Coordenada X inicial (usamos float para mayor precisión en el suavizado)
|
float x; // Coordenada X inicial (usamos float para mayor precisión en el suavizado)
|
||||||
int direction; // Dirección de movimiento: -1 para izquierda, 1 para derecha
|
int direction; // Dirección de movimiento: -1 para izquierda, 1 para derecha
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ void Intro::initSprites() {
|
|||||||
card_sprites_.push_back(std::move(sprite));
|
card_sprites_.push_back(std::move(sprite));
|
||||||
}
|
}
|
||||||
|
|
||||||
const float X_DEST = param.game.game_area.center_x - CARD_WIDTH / 2;
|
const float X_DEST = param.game.game_area.center_x - (CARD_WIDTH / 2);
|
||||||
const float Y_DEST = param.game.game_area.first_quarter_y - (CARD_HEIGHT / 4);
|
const float Y_DEST = param.game.game_area.first_quarter_y - (CARD_HEIGHT / 4);
|
||||||
|
|
||||||
card_sprites_.at(0)->addPath(-CARD_WIDTH - 10, X_DEST, PathType::HORIZONTAL, Y_DEST, 100, easeInOutExpo, 0);
|
card_sprites_.at(0)->addPath(-CARD_WIDTH - 10, X_DEST, PathType::HORIZONTAL, Y_DEST, 100, easeInOutExpo, 0);
|
||||||
|
|||||||
@@ -11,12 +11,9 @@
|
|||||||
#include "tiled_bg.h" // Para TiledBG
|
#include "tiled_bg.h" // Para TiledBG
|
||||||
#include "writer.h" // Para Writer
|
#include "writer.h" // Para Writer
|
||||||
|
|
||||||
/*
|
// --- Clase Intro: muestra la secuencia de introducción ---
|
||||||
Esta clase gestiona un estado del programa. Se encarga de mostrar la secuencia
|
// Esta clase gestiona un estado del programa. Se encarga de mostrar la secuencia
|
||||||
de introducción.
|
// de introducción.
|
||||||
*/
|
|
||||||
|
|
||||||
// Clase Intro
|
|
||||||
class Intro {
|
class Intro {
|
||||||
public:
|
public:
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
|
|||||||
@@ -10,15 +10,12 @@
|
|||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
/*
|
// --- Clase Logo: dibuja el logo de JAILGAMES con efectos visuales ---
|
||||||
Esta clase gestiona un estado del programa. Se encarga de dibujar por pantalla el
|
// Esta clase gestiona un estado del programa. Se encarga de dibujar por pantalla el
|
||||||
logo de "JAILGAMES" utilizando un sencillo efecto consistente en generar un sprite por
|
// logo de "JAILGAMES" utilizando un sencillo efecto consistente en generar un sprite por
|
||||||
cada línea del bitmap que forma la palabra "JAILGAMES". Posteriormente realiza una
|
// cada línea del bitmap que forma la palabra "JAILGAMES". Posteriormente realiza una
|
||||||
modulación de color sobre la textura para simular un fade to black al estilo
|
// modulación de color sobre la textura para simular un fade to black al estilo
|
||||||
ZX Spectrum.
|
// ZX Spectrum.
|
||||||
*/
|
|
||||||
|
|
||||||
// --- Clase Logo ---
|
|
||||||
class Logo {
|
class Logo {
|
||||||
public:
|
public:
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "audio.h" // Para Audio
|
#include "audio.h" // Para Audio
|
||||||
#include "color.h" // Para NO_TEXT_COLOR, TITLE_SHADOW_TEXT_COLOR
|
#include "color.h" // Para Colors::NO_COLOR_MOD, Colors::TITLE_SHADOW_TEXT
|
||||||
#include "fade.h" // Para Fade, FadeType
|
#include "fade.h" // Para Fade, FadeType
|
||||||
#include "game_logo.h" // Para GameLogo
|
#include "game_logo.h" // Para GameLogo
|
||||||
#include "global_events.h" // Para check
|
#include "global_events.h" // Para check
|
||||||
@@ -37,20 +37,14 @@ class Texture;
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Title::Title()
|
Title::Title()
|
||||||
: text_(Resource::get()->getText("smb2_grad")),
|
: text_(Resource::get()->getText("smb2_grad")), fade_(std::make_unique<Fade>()), tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::RANDOM)), game_logo_(std::make_unique<GameLogo>(param.game.game_area.center_x, param.title.title_c_c_position)), mini_logo_sprite_(std::make_unique<Sprite>(Resource::get()->getTexture("logo_jailgames_mini.png"))), state_(TitleState::LOGO_ANIMATING), num_controllers_(Input::get()->getNumGamepads()) {
|
||||||
fade_(std::make_unique<Fade>()),
|
|
||||||
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::RANDOM)),
|
|
||||||
game_logo_(std::make_unique<GameLogo>(param.game.game_area.center_x, param.title.title_c_c_position)),
|
|
||||||
mini_logo_sprite_(std::make_unique<Sprite>(Resource::get()->getTexture("logo_jailgames_mini.png"))),
|
|
||||||
num_controllers_(Input::get()->getNumGamepads()),
|
|
||||||
state_(TitleState::LOGO_ANIMATING) {
|
|
||||||
// Configura objetos
|
// Configura objetos
|
||||||
tiled_bg_->setColor(param.title.bg_color);
|
tiled_bg_->setColor(param.title.bg_color);
|
||||||
game_logo_->enable();
|
game_logo_->enable();
|
||||||
mini_logo_sprite_->setX(param.game.game_area.center_x - mini_logo_sprite_->getWidth() / 2);
|
mini_logo_sprite_->setX(param.game.game_area.center_x - (mini_logo_sprite_->getWidth() / 2));
|
||||||
fade_->setColor(param.fade.color);
|
fade_->setColor(param.fade.color);
|
||||||
fade_->setType(FadeType::RANDOM_SQUARE);
|
fade_->setType(Fade::Type::RANDOM_SQUARE2);
|
||||||
fade_->setPostDuration(param.fade.post_duration);
|
fade_->setPostDuration(param.fade.post_duration_ms);
|
||||||
initPlayers();
|
initPlayers();
|
||||||
|
|
||||||
// Asigna valores a otras variables
|
// Asigna valores a otras variables
|
||||||
@@ -201,7 +195,7 @@ void Title::printColorValue(const Color& color) {
|
|||||||
<< std::hex << std::setw(2) << std::setfill('0') << (int)color.r
|
<< std::hex << std::setw(2) << std::setfill('0') << (int)color.r
|
||||||
<< std::setw(2) << std::setfill('0') << (int)color.g
|
<< std::setw(2) << std::setfill('0') << (int)color.g
|
||||||
<< std::setw(2) << std::setfill('0') << (int)color.b
|
<< std::setw(2) << std::setfill('0') << (int)color.b
|
||||||
<< std::endl;
|
<< '\n';
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -438,9 +432,9 @@ void Title::renderStartPrompt() {
|
|||||||
param.title.press_start_position,
|
param.title.press_start_position,
|
||||||
Lang::getText("[TITLE] PRESS_BUTTON_TO_PLAY"),
|
Lang::getText("[TITLE] PRESS_BUTTON_TO_PLAY"),
|
||||||
1,
|
1,
|
||||||
NO_TEXT_COLOR,
|
Colors::NO_COLOR_MOD,
|
||||||
1,
|
1,
|
||||||
TITLE_SHADOW_TEXT_COLOR);
|
Colors::TITLE_SHADOW_TEXT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,9 +449,9 @@ void Title::renderCopyright() {
|
|||||||
anchor_.copyright_text,
|
anchor_.copyright_text,
|
||||||
std::string(TEXT_COPYRIGHT),
|
std::string(TEXT_COPYRIGHT),
|
||||||
1,
|
1,
|
||||||
NO_TEXT_COLOR,
|
Colors::NO_COLOR_MOD,
|
||||||
1,
|
1,
|
||||||
TITLE_SHADOW_TEXT_COLOR);
|
Colors::TITLE_SHADOW_TEXT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,7 +532,7 @@ void Title::initPlayers() {
|
|||||||
players_.back()->setPlayingState(Player::State::TITLE_HIDDEN);
|
players_.back()->setPlayingState(Player::State::TITLE_HIDDEN);
|
||||||
|
|
||||||
// Registra los jugadores en Options
|
// Registra los jugadores en Options
|
||||||
for (auto player : players_) {
|
for (const auto& player : players_) {
|
||||||
Options::keyboard.addPlayer(player);
|
Options::keyboard.addPlayer(player);
|
||||||
Options::gamepad_manager.addPlayer(player);
|
Options::gamepad_manager.addPlayer(player);
|
||||||
}
|
}
|
||||||
@@ -560,7 +554,7 @@ void Title::renderPlayers() {
|
|||||||
|
|
||||||
// Obtiene un jugador a partir de su "id"
|
// Obtiene un jugador a partir de su "id"
|
||||||
auto Title::getPlayer(Player::Id id) -> std::shared_ptr<Player> {
|
auto Title::getPlayer(Player::Id id) -> std::shared_ptr<Player> {
|
||||||
auto it = std::find_if(players_.begin(), players_.end(), [id](const auto& player) { return player->getId() == id; });
|
auto it = std::ranges::find_if(players_, [id](const auto& player) { return player->getId() == id; });
|
||||||
|
|
||||||
if (it != players_.end()) {
|
if (it != players_.end()) {
|
||||||
return *it;
|
return *it;
|
||||||
|
|||||||
@@ -19,19 +19,11 @@ namespace Options {
|
|||||||
struct Gamepad;
|
struct Gamepad;
|
||||||
} // namespace Options
|
} // namespace Options
|
||||||
|
|
||||||
// Textos
|
// --- Constantes ---
|
||||||
constexpr std::string_view TEXT_COPYRIGHT = "@2020,2025 JailDesigner";
|
constexpr std::string_view TEXT_COPYRIGHT = "@2020,2025 JailDesigner"; // Texto de copyright
|
||||||
|
constexpr bool ALLOW_TITLE_ANIMATION_SKIP = false; // Permite saltar la animación del título
|
||||||
|
|
||||||
// Parámetros
|
// --- Clase Title: gestiona el estado de título/menú principal del juego ---
|
||||||
constexpr bool ALLOW_TITLE_ANIMATION_SKIP = false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Clase que gestiona el estado de título/menú principal del juego.
|
|
||||||
Responsable de mostrar el logo, el fondo animado y gestionar la entrada para comenzar la partida.
|
|
||||||
No permite saltar la animación del título salvo que se cambie el define.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Clase Title
|
|
||||||
class Title {
|
class Title {
|
||||||
public:
|
public:
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
@@ -42,17 +34,17 @@ class Title {
|
|||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Enumeraciones ---
|
// --- Enums ---
|
||||||
enum class TitleState {
|
enum class TitleState {
|
||||||
LOGO_ANIMATING, // El logo está animándose
|
LOGO_ANIMATING, // El logo está animándose
|
||||||
LOGO_FINISHED, // El logo ha terminado de animarse
|
LOGO_FINISHED, // El logo ha terminado de animarse
|
||||||
START_HAS_BEEN_PRESSED, // Se ha pulsado el botón de start
|
START_HAS_BEEN_PRESSED, // Se ha pulsado el botón de start
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estructura para definir anclas ---
|
// --- Estructuras privadas ---
|
||||||
struct Anchor {
|
struct Anchor {
|
||||||
int mini_logo;
|
int mini_logo; // Ancla del logo mini
|
||||||
int copyright_text;
|
int copyright_text; // Ancla del texto de copyright
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
@@ -64,18 +56,16 @@ class Title {
|
|||||||
std::vector<std::shared_ptr<Player>> players_; // Vector de jugadores
|
std::vector<std::shared_ptr<Player>> players_; // Vector de jugadores
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
int counter_ = 0; // Temporizador para la pantalla de título
|
Anchor anchor_; // Anclas para definir la posición de los elementos del título
|
||||||
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad
|
|
||||||
Section::Name next_section_; // Siguiente sección a cargar
|
Section::Name next_section_; // Siguiente sección a cargar
|
||||||
Section::Options selection_ = Section::Options::TITLE_TIME_OUT; // Opción elegida en el título
|
Section::Options selection_ = Section::Options::TITLE_TIME_OUT; // Opción elegida en el título
|
||||||
int num_controllers_; // Número de mandos conectados
|
|
||||||
TitleState state_; // Estado actual de la sección
|
TitleState state_; // Estado actual de la sección
|
||||||
bool should_render_start_prompt_ = false; // Indica si se muestra o no el texto de PRESS START BUTTON TO PLAY
|
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad
|
||||||
bool player1_start_pressed_ = false; // Indica si se ha pulsdo el boton de empezar a jugar para el jugador 1
|
int counter_ = 0; // Temporizador para la pantalla de título
|
||||||
bool player2_start_pressed_ = false; // Indica si se ha pulsdo el boton de empezar a jugar para el jugador 2
|
int num_controllers_; // Número de mandos conectados
|
||||||
|
bool should_render_start_prompt_ = false; // Indica si se muestra el texto de PRESS START BUTTON TO PLAY
|
||||||
// -- Variables de diseño ---
|
bool player1_start_pressed_ = false; // Indica si se ha pulsado el botón de empezar para el jugador 1
|
||||||
Anchor anchor_; // Anclas para definir la posición de los elementos del titulo
|
bool player2_start_pressed_ = false; // Indica si se ha pulsado el botón de empezar para el jugador 2
|
||||||
|
|
||||||
// --- Ciclo de vida del título ---
|
// --- Ciclo de vida del título ---
|
||||||
void update(); // Actualiza las variables del objeto
|
void update(); // Actualiza las variables del objeto
|
||||||
|
|||||||
@@ -1,155 +1,157 @@
|
|||||||
#include "shutdown.h"
|
#include "shutdown.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/wait.h>
|
#include <unistd.h>
|
||||||
#include <string>
|
|
||||||
|
#include <string>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace SystemShutdown {
|
namespace SystemShutdown {
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
// Función auxiliar para sistemas Unix-like
|
// Función auxiliar para sistemas Unix-like
|
||||||
ShutdownResult executeUnixShutdown(const char* command, char* const args[]) {
|
auto executeUnixShutdown(const char* command, const std::vector<char*>& args) -> ShutdownResult {
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
// Proceso hijo
|
// Proceso hijo
|
||||||
execvp(command, args);
|
execvp(command, args.data());
|
||||||
// Si llegamos aquí, execvp falló
|
// Si llegamos aquí, execvp falló
|
||||||
std::cerr << "Error: No se pudo ejecutar " << command << std::endl;
|
std::cerr << "Error: No se pudo ejecutar " << command << '\n';
|
||||||
_exit(1);
|
_exit(1);
|
||||||
} else if (pid > 0) {
|
} else if (pid > 0) {
|
||||||
// Proceso padre
|
// Proceso padre
|
||||||
int status;
|
int status;
|
||||||
waitpid(pid, &status, 0);
|
waitpid(pid, &status, 0);
|
||||||
return (WEXITSTATUS(status) == 0) ? ShutdownResult::SUCCESS : ShutdownResult::ERROR_SYSTEM_CALL;
|
return (WEXITSTATUS(status) == 0) ? ShutdownResult::SUCCESS : ShutdownResult::ERROR_SYSTEM_CALL;
|
||||||
} else {
|
} else {
|
||||||
return ShutdownResult::ERROR_FORK_FAILED;
|
return ShutdownResult::ERROR_FORK_FAILED;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Implementación de las funciones públicas
|
// Implementación de las funciones públicas
|
||||||
ShutdownResult shutdownSystem() {
|
auto shutdownSystem() -> ShutdownResult {
|
||||||
ShutdownConfig config;
|
ShutdownConfig config;
|
||||||
return shutdownSystem(config);
|
return shutdownSystem(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShutdownResult shutdownSystem(int delay_seconds, bool force_apps) {
|
auto shutdownSystem(int delay_seconds, bool force_apps) -> ShutdownResult {
|
||||||
ShutdownConfig config;
|
ShutdownConfig config;
|
||||||
config.delay_seconds = delay_seconds;
|
config.delay_seconds = delay_seconds;
|
||||||
config.force_close_apps = force_apps;
|
config.force_close_apps = force_apps;
|
||||||
return shutdownSystem(config);
|
return shutdownSystem(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShutdownResult shutdownSystem(const ShutdownConfig& config) {
|
auto shutdownSystem(const ShutdownConfig& config) -> ShutdownResult {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Windows: Usar CreateProcess
|
// Windows: Usar CreateProcess
|
||||||
STARTUPINFOA si = {0};
|
STARTUPINFOA si = {0};
|
||||||
PROCESS_INFORMATION pi = {0};
|
PROCESS_INFORMATION pi = {0};
|
||||||
si.cb = sizeof(si);
|
si.cb = sizeof(si);
|
||||||
|
|
||||||
// Crear comando con el delay especificado
|
// Crear comando con el delay especificado
|
||||||
std::string command = "shutdown.exe /s /t " + std::to_string(config.delay_seconds);
|
std::string command = "shutdown.exe /s /t " + std::to_string(config.delay_seconds);
|
||||||
if (config.force_close_apps) {
|
if (config.force_close_apps) {
|
||||||
command += " /f";
|
command += " /f";
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateProcess necesita un array de char modificable
|
// CreateProcess necesita un array de char modificable
|
||||||
char* cmd_buffer = new char[command.length() + 1];
|
char* cmd_buffer = new char[command.length() + 1];
|
||||||
strcpy(cmd_buffer, command.c_str());
|
strcpy(cmd_buffer, command.c_str());
|
||||||
|
|
||||||
bool success = CreateProcessA(
|
bool success = CreateProcessA(
|
||||||
NULL, // lpApplicationName
|
NULL, // lpApplicationName
|
||||||
cmd_buffer, // lpCommandLine
|
cmd_buffer, // lpCommandLine
|
||||||
NULL, // lpProcessAttributes
|
NULL, // lpProcessAttributes
|
||||||
NULL, // lpThreadAttributes
|
NULL, // lpThreadAttributes
|
||||||
FALSE, // bInheritHandles
|
FALSE, // bInheritHandles
|
||||||
0, // dwCreationFlags
|
0, // dwCreationFlags
|
||||||
NULL, // lpEnvironment
|
NULL, // lpEnvironment
|
||||||
NULL, // lpCurrentDirectory
|
NULL, // lpCurrentDirectory
|
||||||
&si, // lpStartupInfo
|
&si, // lpStartupInfo
|
||||||
&pi // lpProcessInformation
|
&pi // lpProcessInformation
|
||||||
);
|
);
|
||||||
|
|
||||||
delete[] cmd_buffer;
|
delete[] cmd_buffer;
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
return ShutdownResult::SUCCESS;
|
return ShutdownResult::SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
if (error == ERROR_ACCESS_DENIED) {
|
if (error == ERROR_ACCESS_DENIED) {
|
||||||
return ShutdownResult::ERROR_PERMISSION;
|
return ShutdownResult::ERROR_PERMISSION;
|
||||||
}
|
|
||||||
return ShutdownResult::ERROR_SYSTEM_CALL;
|
|
||||||
}
|
}
|
||||||
|
return ShutdownResult::ERROR_SYSTEM_CALL;
|
||||||
|
}
|
||||||
|
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
// macOS - apagado inmediato
|
// macOS - apagado inmediato
|
||||||
char* args[] = {
|
std::vector<char*> args = {
|
||||||
const_cast<char*>("shutdown"),
|
const_cast<char*>("shutdown"),
|
||||||
const_cast<char*>("-h"),
|
const_cast<char*>("-h"),
|
||||||
const_cast<char*>("now"),
|
const_cast<char*>("now"),
|
||||||
NULL
|
nullptr};
|
||||||
};
|
|
||||||
|
return executeUnixShutdown("shutdown", args);
|
||||||
return executeUnixShutdown("shutdown", args);
|
|
||||||
|
|
||||||
#elif __linux__
|
#elif __linux__
|
||||||
// Linux - apagado inmediato
|
// Linux - apagado inmediato
|
||||||
char* args[] = {
|
std::vector<char*> args = {
|
||||||
const_cast<char*>("shutdown"),
|
const_cast<char*>("shutdown"),
|
||||||
const_cast<char*>("-h"),
|
const_cast<char*>("-h"),
|
||||||
const_cast<char*>("now"),
|
const_cast<char*>("now"),
|
||||||
NULL
|
nullptr};
|
||||||
};
|
|
||||||
|
return executeUnixShutdown("shutdown", args);
|
||||||
return executeUnixShutdown("shutdown", args);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
return ShutdownResult::ERROR_UNSUPPORTED;
|
return ShutdownResult::ERROR_UNSUPPORTED;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* resultToString(ShutdownResult result) {
|
auto resultToString(ShutdownResult result) -> const char* {
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case ShutdownResult::SUCCESS:
|
case ShutdownResult::SUCCESS:
|
||||||
return "Apagado iniciado exitosamente";
|
return "Apagado iniciado exitosamente";
|
||||||
case ShutdownResult::ERROR_PERMISSION:
|
case ShutdownResult::ERROR_PERMISSION:
|
||||||
return "Error: Permisos insuficientes";
|
return "Error: Permisos insuficientes";
|
||||||
case ShutdownResult::ERROR_SYSTEM_CALL:
|
case ShutdownResult::ERROR_SYSTEM_CALL:
|
||||||
return "Error: Fallo en la llamada al sistema";
|
return "Error: Fallo en la llamada al sistema";
|
||||||
case ShutdownResult::ERROR_FORK_FAILED:
|
case ShutdownResult::ERROR_FORK_FAILED:
|
||||||
return "Error: No se pudo crear proceso hijo";
|
return "Error: No se pudo crear proceso hijo";
|
||||||
case ShutdownResult::ERROR_UNSUPPORTED:
|
case ShutdownResult::ERROR_UNSUPPORTED:
|
||||||
return "Error: Sistema operativo no soportado";
|
return "Error: Sistema operativo no soportado";
|
||||||
default:
|
default:
|
||||||
return "Error desconocido";
|
return "Error desconocido";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool isShutdownSupported() {
|
auto isShutdownSupported() -> bool {
|
||||||
#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__)
|
#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__)
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* getRequiredPermissions() {
|
auto getRequiredPermissions() -> const char* {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return "Requiere permisos de Administrador en Windows";
|
return "Requiere permisos de Administrador en Windows";
|
||||||
#elif defined(__APPLE__) || defined(__linux__)
|
#elif defined(__APPLE__) || defined(__linux__)
|
||||||
return "Requiere permisos de root/sudo en Unix";
|
return "Requiere permisos de root/sudo en Unix";
|
||||||
#else
|
#else
|
||||||
return "Sistema no soportado";
|
return "Sistema no soportado";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace SystemShutdown
|
} // namespace SystemShutdown
|
||||||
@@ -1,47 +1,33 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Utilidad multiplataforma para apagar el sistema de forma segura
|
// --- Namespace SystemShutdown: utilidad multiplataforma para apagar el sistema de forma segura ---
|
||||||
namespace SystemShutdown {
|
namespace SystemShutdown {
|
||||||
|
|
||||||
// Códigos de resultado para las operaciones de apagado
|
// --- Enums ---
|
||||||
enum class ShutdownResult {
|
enum class ShutdownResult {
|
||||||
SUCCESS = 0,
|
SUCCESS = 0, // Éxito
|
||||||
ERROR_PERMISSION, // Error de permisos insuficientes
|
ERROR_PERMISSION, // Error de permisos insuficientes
|
||||||
ERROR_SYSTEM_CALL, // Error en la llamada al sistema
|
ERROR_SYSTEM_CALL, // Error en la llamada al sistema
|
||||||
ERROR_FORK_FAILED, // Error al crear proceso hijo (Unix)
|
ERROR_FORK_FAILED, // Error al crear proceso hijo (Unix)
|
||||||
ERROR_UNSUPPORTED // Sistema operativo no soportado
|
ERROR_UNSUPPORTED // Sistema operativo no soportado
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- Estructuras ---
|
||||||
|
struct ShutdownConfig {
|
||||||
|
int delay_seconds{5}; // Segundos de retraso antes del apagado
|
||||||
|
bool force_close_apps{true}; // Forzar cierre de aplicaciones
|
||||||
|
const char* shutdown_message{"El sistema se apagará..."}; // Mensaje mostrado durante el apagado
|
||||||
|
|
||||||
// Configuración para el apagado del sistema
|
|
||||||
struct ShutdownConfig {
|
|
||||||
int delay_seconds;
|
|
||||||
bool force_close_apps;
|
|
||||||
const char* shutdown_message;
|
|
||||||
|
|
||||||
// Constructor con valores por defecto
|
// Constructor con valores por defecto
|
||||||
ShutdownConfig()
|
ShutdownConfig() = default;
|
||||||
: delay_seconds(5)
|
};
|
||||||
, force_close_apps(true)
|
|
||||||
, shutdown_message("El sistema se apagará...")
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Apaga el sistema con configuración por defecto
|
// --- Funciones ---
|
||||||
ShutdownResult shutdownSystem();
|
auto shutdownSystem() -> ShutdownResult; // Apaga el sistema con configuración por defecto
|
||||||
|
auto shutdownSystem(const ShutdownConfig& config) -> ShutdownResult; // Apaga el sistema con configuración personalizada
|
||||||
|
auto shutdownSystem(int delay_seconds, bool force_apps = true) -> ShutdownResult; // Apaga el sistema con parámetros simples
|
||||||
|
auto resultToString(ShutdownResult result) -> const char*; // Convierte un código de resultado a string descriptivo
|
||||||
|
auto isShutdownSupported() -> bool; // Verifica si el sistema actual soporta apagado programático
|
||||||
|
auto getRequiredPermissions() -> const char*; // Obtiene información sobre los permisos necesarios
|
||||||
|
|
||||||
// Apaga el sistema con configuración personalizada
|
} // namespace SystemShutdown
|
||||||
ShutdownResult shutdownSystem(const ShutdownConfig& config);
|
|
||||||
|
|
||||||
// Apaga el sistema con parámetros simples
|
|
||||||
ShutdownResult shutdownSystem(int delay_seconds, bool force_apps = true);
|
|
||||||
|
|
||||||
// Convierte un código de resultado a string descriptivo
|
|
||||||
const char* resultToString(ShutdownResult result);
|
|
||||||
|
|
||||||
// Verifica si el sistema actual soporta apagado programático
|
|
||||||
bool isShutdownSupported();
|
|
||||||
|
|
||||||
// Obtiene información sobre los permisos necesarios en la plataforma actual
|
|
||||||
const char* getRequiredPermissions();
|
|
||||||
|
|
||||||
} // namespace SystemShutdown
|
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory> // Para shared_ptr
|
#include <memory> // Para shared_ptr
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Clase SmartSprite: Sprite animado que se mueve hacia un destino y puede deshabilitarse automáticamente
|
// --- Clase SmartSprite: sprite animado que se mueve hacia un destino y puede deshabilitarse automáticamente ---
|
||||||
class SmartSprite : public AnimatedSprite {
|
class SmartSprite : public AnimatedSprite {
|
||||||
public:
|
public:
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
explicit SmartSprite(std::shared_ptr<Texture> texture)
|
explicit SmartSprite(std::shared_ptr<Texture> texture)
|
||||||
: AnimatedSprite(texture) {}
|
: AnimatedSprite(std::move(texture)) {}
|
||||||
~SmartSprite() override = default;
|
~SmartSprite() override = default;
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
@@ -31,11 +32,11 @@ class SmartSprite : public AnimatedSprite {
|
|||||||
void setEnabled(bool value) { enabled_ = value; } // Habilita o deshabilita el objeto
|
void setEnabled(bool value) { enabled_ = value; } // Habilita o deshabilita el objeto
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Variables internas ---
|
// --- Variables de estado ---
|
||||||
bool on_destination_ = false; // Indica si está en el destino
|
|
||||||
int dest_x_ = 0; // Posición de destino en el eje X
|
int dest_x_ = 0; // Posición de destino en el eje X
|
||||||
int dest_y_ = 0; // Posición de destino en el eje Y
|
int dest_y_ = 0; // Posición de destino en el eje Y
|
||||||
int finished_counter_ = 0; // Contador para deshabilitarlo
|
int finished_counter_ = 0; // Contador para deshabilitarlo
|
||||||
|
bool on_destination_ = false; // Indica si está en el destino
|
||||||
bool finished_ = false; // Indica si ya ha terminado
|
bool finished_ = false; // Indica si ya ha terminado
|
||||||
bool enabled_ = false; // Indica si el objeto está habilitado
|
bool enabled_ = false; // Indica si el objeto está habilitado
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Sprite::Sprite(std::shared_ptr<Texture> texture, float pos_x, float pos_y, float width, float height)
|
Sprite::Sprite(std::shared_ptr<Texture> texture, float pos_x, float pos_y, float width, float height)
|
||||||
: textures_{texture},
|
: textures_{std::move(texture)},
|
||||||
pos_((SDL_FRect){pos_x, pos_y, width, height}),
|
pos_((SDL_FRect){pos_x, pos_y, width, height}),
|
||||||
sprite_clip_((SDL_FRect){0, 0, pos_.w, pos_.h}) {}
|
sprite_clip_((SDL_FRect){0, 0, pos_.w, pos_.h}) {}
|
||||||
|
|
||||||
Sprite::Sprite(std::shared_ptr<Texture> texture, SDL_FRect rect)
|
Sprite::Sprite(std::shared_ptr<Texture> texture, SDL_FRect rect)
|
||||||
: textures_{texture},
|
: textures_{std::move(texture)},
|
||||||
pos_(rect),
|
pos_(rect),
|
||||||
sprite_clip_((SDL_FRect){0, 0, pos_.w, pos_.h}) {}
|
sprite_clip_((SDL_FRect){0, 0, pos_.w, pos_.h}) {}
|
||||||
|
|
||||||
Sprite::Sprite(std::shared_ptr<Texture> texture)
|
Sprite::Sprite(std::shared_ptr<Texture> texture)
|
||||||
: textures_{texture},
|
: textures_{std::move(texture)},
|
||||||
|
|
||||||
pos_(SDL_FRect{0, 0, static_cast<float>(textures_.at(texture_index_)->getWidth()), static_cast<float>(textures_.at(texture_index_)->getHeight())}),
|
pos_(SDL_FRect{0, 0, static_cast<float>(textures_.at(texture_index_)->getWidth()), static_cast<float>(textures_.at(texture_index_)->getHeight())}),
|
||||||
sprite_clip_(pos_) {}
|
sprite_clip_(pos_) {}
|
||||||
|
|
||||||
@@ -39,8 +41,8 @@ void Sprite::setPosition(SDL_FPoint point) {
|
|||||||
|
|
||||||
// Reinicia las variables a cero
|
// Reinicia las variables a cero
|
||||||
void Sprite::clear() {
|
void Sprite::clear() {
|
||||||
pos_ = {0, 0, 0, 0};
|
pos_ = {.x = 0, .y = 0, .w = 0, .h = 0};
|
||||||
sprite_clip_ = {0, 0, 0, 0};
|
sprite_clip_ = {.x = 0, .y = 0, .w = 0, .h = 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cambia la textura activa por índice
|
// Cambia la textura activa por índice
|
||||||
|
|||||||
@@ -4,11 +4,12 @@
|
|||||||
|
|
||||||
#include <cstddef> // Para size_t
|
#include <cstddef> // Para size_t
|
||||||
#include <memory> // Para shared_ptr
|
#include <memory> // Para shared_ptr
|
||||||
#include <vector> // Para vector
|
#include <utility>
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Clase Sprite: representa un objeto gráfico básico con posición, tamaño y textura
|
// --- Clase Sprite: representa un objeto gráfico básico con posición, tamaño y textura ---
|
||||||
class Sprite {
|
class Sprite {
|
||||||
public:
|
public:
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
@@ -52,20 +53,19 @@ class Sprite {
|
|||||||
|
|
||||||
// --- Textura ---
|
// --- Textura ---
|
||||||
[[nodiscard]] auto getTexture() const -> std::shared_ptr<Texture> { return textures_.at(texture_index_); }
|
[[nodiscard]] auto getTexture() const -> std::shared_ptr<Texture> { return textures_.at(texture_index_); }
|
||||||
void setTexture(std::shared_ptr<Texture> texture) { textures_.at(texture_index_) = texture; }
|
void setTexture(std::shared_ptr<Texture> texture) { textures_.at(texture_index_) = std::move(texture); }
|
||||||
void addTexture(std::shared_ptr<Texture> texture) { textures_.push_back(texture); }
|
void addTexture(const std::shared_ptr<Texture>& texture) { textures_.push_back(texture); }
|
||||||
auto setActiveTexture(size_t index) -> bool; // Cambia la textura activa por índice
|
auto setActiveTexture(size_t index) -> bool; // Cambia la textura activa por índice
|
||||||
[[nodiscard]] auto getActiveTextureIndex() const -> size_t { return texture_index_; } // Obtiene el índice de la textura activa
|
[[nodiscard]] auto getActiveTexture() const -> size_t { return texture_index_; } // Alias para getActiveTextureIndex
|
||||||
[[nodiscard]] auto getTextureCount() const -> size_t { return textures_.size(); } // Obtiene el número total de texturas
|
[[nodiscard]] auto getTextureCount() const -> size_t { return textures_.size(); } // Obtiene el número total de texturas
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
auto getTextureRef() -> std::shared_ptr<Texture>& {
|
// --- Métodos internos ---
|
||||||
return textures_.at(texture_index_);
|
auto getTextureRef() -> std::shared_ptr<Texture>& { return textures_.at(texture_index_); } // Obtiene referencia a la textura activa
|
||||||
}
|
|
||||||
|
|
||||||
// --- Variables internas ---
|
// --- Variables internas ---
|
||||||
size_t texture_index_ = 0;
|
|
||||||
std::vector<std::shared_ptr<Texture>> textures_; // Lista de texturas
|
std::vector<std::shared_ptr<Texture>> textures_; // Lista de texturas
|
||||||
|
size_t texture_index_ = 0; // Índice de la textura activa
|
||||||
SDL_FRect pos_; // Posición y tamaño donde dibujar el sprite
|
SDL_FRect pos_; // Posición y tamaño donde dibujar el sprite
|
||||||
SDL_FRect sprite_clip_; // Rectángulo de origen de la textura que se dibujará en pantalla
|
SDL_FRect sprite_clip_; // Rectángulo de origen de la textura que se dibujará en pantalla
|
||||||
double zoom_ = 1.0F; // Zoom aplicado a la textura
|
double zoom_ = 1.0F; // Zoom aplicado a la textura
|
||||||
|
|||||||
137
source/stage.cpp
137
source/stage.cpp
@@ -1,20 +1,25 @@
|
|||||||
#include "stage.h"
|
#include "stage.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
// Implementación de StageData
|
// Implementación de StageData
|
||||||
StageData::StageData(int power_to_complete, int min_menace, int max_menace, const std::string& name)
|
StageData::StageData(int power_to_complete, int min_menace, int max_menace, std::string name)
|
||||||
: power_to_complete_(power_to_complete), min_menace_(min_menace),
|
: status_(StageStatus::LOCKED),
|
||||||
max_menace_(max_menace), name_(name), status_(StageStatus::LOCKED) {}
|
name_(std::move(name)),
|
||||||
|
power_to_complete_(power_to_complete),
|
||||||
|
min_menace_(min_menace),
|
||||||
|
max_menace_(max_menace) {}
|
||||||
|
|
||||||
// Implementación de StageManager
|
// Implementación de StageManager
|
||||||
StageManager::StageManager()
|
StageManager::StageManager()
|
||||||
: current_power_(0), total_power_(0), current_stage_index_(0),
|
: power_change_callback_(nullptr),
|
||||||
power_collection_state_(PowerCollectionState::ENABLED),
|
power_collection_state_(PowerCollectionState::ENABLED),
|
||||||
power_change_callback_(nullptr) {
|
current_stage_index_(0),
|
||||||
initialize();
|
current_power_(0),
|
||||||
}
|
total_power_(0) { initialize(); }
|
||||||
|
|
||||||
void StageManager::initialize() {
|
void StageManager::initialize() {
|
||||||
stages_.clear();
|
stages_.clear();
|
||||||
@@ -24,12 +29,12 @@ void StageManager::initialize() {
|
|||||||
|
|
||||||
void StageManager::initialize(const std::string& stages_file) {
|
void StageManager::initialize(const std::string& stages_file) {
|
||||||
stages_.clear();
|
stages_.clear();
|
||||||
|
|
||||||
// Intentar cargar desde archivo, si falla usar valores predeterminados
|
// Intentar cargar desde archivo, si falla usar valores predeterminados
|
||||||
if (!loadStagesFromFile(stages_file)) {
|
if (!loadStagesFromFile(stages_file)) {
|
||||||
createDefaultStages();
|
createDefaultStages();
|
||||||
}
|
}
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,25 +60,25 @@ void StageManager::createDefaultStages() {
|
|||||||
stages_.emplace_back(950, 7 + (4 * 7), 7 + (4 * 10), "Maestría");
|
stages_.emplace_back(950, 7 + (4 * 7), 7 + (4 * 10), "Maestría");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StageManager::loadStagesFromFile(const std::string& filename) {
|
auto StageManager::loadStagesFromFile(const std::string& filename) -> bool {
|
||||||
std::ifstream file(filename);
|
std::ifstream file(filename);
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
return false; // No se pudo abrir el archivo
|
return false; // No se pudo abrir el archivo
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
while (std::getline(file, line)) {
|
while (std::getline(file, line)) {
|
||||||
// Ignorar líneas vacías y comentarios (líneas que empiezan con #)
|
// Ignorar líneas vacías y comentarios (líneas que empiezan con #)
|
||||||
if (line.empty() || line[0] == '#') {
|
if (line.empty() || line[0] == '#') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parsear línea: power_to_complete,min_menace,max_menace,name
|
// Parsear línea: power_to_complete,min_menace,max_menace,name
|
||||||
std::stringstream ss(line);
|
std::stringstream ss(line);
|
||||||
std::string token;
|
std::string token;
|
||||||
std::vector<std::string> tokens;
|
std::vector<std::string> tokens;
|
||||||
|
|
||||||
// Dividir por comas
|
// Dividir por comas
|
||||||
while (std::getline(ss, token, ',')) {
|
while (std::getline(ss, token, ',')) {
|
||||||
// Eliminar espacios en blanco al inicio y final
|
// Eliminar espacios en blanco al inicio y final
|
||||||
@@ -81,76 +86,76 @@ bool StageManager::loadStagesFromFile(const std::string& filename) {
|
|||||||
token.erase(token.find_last_not_of(" \t") + 1);
|
token.erase(token.find_last_not_of(" \t") + 1);
|
||||||
tokens.push_back(token);
|
tokens.push_back(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verificar que tenemos exactamente 4 campos
|
// Verificar que tenemos exactamente 4 campos
|
||||||
if (tokens.size() != 4) {
|
if (tokens.size() != 4) {
|
||||||
// Error de formato, continuar con la siguiente línea
|
// Error de formato, continuar con la siguiente línea
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Convertir a enteros los primeros tres campos
|
// Convertir a enteros los primeros tres campos
|
||||||
int power_to_complete = std::stoi(tokens[0]);
|
int power_to_complete = std::stoi(tokens[0]);
|
||||||
int min_menace = std::stoi(tokens[1]);
|
int min_menace = std::stoi(tokens[1]);
|
||||||
int max_menace = std::stoi(tokens[2]);
|
int max_menace = std::stoi(tokens[2]);
|
||||||
std::string name = tokens[3];
|
std::string name = tokens[3];
|
||||||
|
|
||||||
// Validar valores
|
// Validar valores
|
||||||
if (power_to_complete <= 0 || min_menace < 0 || max_menace < min_menace) {
|
if (power_to_complete <= 0 || min_menace < 0 || max_menace < min_menace) {
|
||||||
continue; // Valores inválidos, saltar línea
|
continue; // Valores inválidos, saltar línea
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crear y añadir la fase
|
// Crear y añadir la fase
|
||||||
stages_.emplace_back(power_to_complete, min_menace, max_menace, name);
|
stages_.emplace_back(power_to_complete, min_menace, max_menace, name);
|
||||||
|
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
// Error de conversión, continuar con la siguiente línea
|
// Error de conversión, continuar con la siguiente línea
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
// Verificar que se cargó al menos una fase
|
// Verificar que se cargó al menos una fase
|
||||||
return !stages_.empty();
|
return !stages_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StageManager::advanceToNextStage() {
|
auto StageManager::advanceToNextStage() -> bool {
|
||||||
if (!isCurrentStageCompleted() || current_stage_index_ >= stages_.size() - 1) {
|
if (!isCurrentStageCompleted() || current_stage_index_ >= stages_.size() - 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_stage_index_++;
|
current_stage_index_++;
|
||||||
current_power_ = 0; // Reiniciar poder para la nueva fase
|
current_power_ = 0; // Reiniciar poder para la nueva fase
|
||||||
updateStageStatuses();
|
updateStageStatuses();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StageManager::jumpToStage(size_t target_stage_index) {
|
auto StageManager::jumpToStage(size_t target_stage_index) -> bool {
|
||||||
if (!validateStageIndex(target_stage_index)) {
|
if (!validateStageIndex(target_stage_index)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calcular el poder acumulado hasta la fase objetivo
|
// Calcular el poder acumulado hasta la fase objetivo
|
||||||
int accumulated_power = 0;
|
int accumulated_power = 0;
|
||||||
for (size_t i = 0; i < target_stage_index; ++i) {
|
for (size_t i = 0; i < target_stage_index; ++i) {
|
||||||
accumulated_power += stages_[i].getPowerToComplete();
|
accumulated_power += stages_[i].getPowerToComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualizar estado
|
// Actualizar estado
|
||||||
current_stage_index_ = target_stage_index;
|
current_stage_index_ = target_stage_index;
|
||||||
current_power_ = 0; // Comenzar la fase objetivo sin poder
|
current_power_ = 0; // Comenzar la fase objetivo sin poder
|
||||||
total_power_ = accumulated_power; // Poder total como si se hubieran completado las anteriores
|
total_power_ = accumulated_power; // Poder total como si se hubieran completado las anteriores
|
||||||
|
|
||||||
updateStageStatuses();
|
updateStageStatuses();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StageManager::subtractPower(int amount) {
|
auto StageManager::subtractPower(int amount) -> bool {
|
||||||
if (amount <= 0 || current_power_ < amount) {
|
if (amount <= 0 || current_power_ < amount) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_power_ -= amount;
|
current_power_ -= amount;
|
||||||
updateStageStatuses();
|
updateStageStatuses();
|
||||||
return true;
|
return true;
|
||||||
@@ -164,69 +169,73 @@ void StageManager::disablePowerCollection() {
|
|||||||
power_collection_state_ = PowerCollectionState::DISABLED;
|
power_collection_state_ = PowerCollectionState::DISABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<StageData> StageManager::getCurrentStage() const {
|
auto StageManager::getCurrentStage() const -> std::optional<StageData> {
|
||||||
return getStage(current_stage_index_);
|
return getStage(current_stage_index_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<StageData> StageManager::getStage(size_t index) const {
|
auto StageManager::getStage(size_t index) const -> std::optional<StageData> {
|
||||||
if (!validateStageIndex(index)) {
|
if (!validateStageIndex(index)) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return stages_[index];
|
return stages_[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StageManager::isCurrentStageCompleted() const {
|
auto StageManager::isCurrentStageCompleted() const -> bool {
|
||||||
auto current_stage = getCurrentStage();
|
auto current_stage = getCurrentStage();
|
||||||
if (!current_stage.has_value()) {
|
if (!current_stage.has_value()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return current_power_ >= current_stage->getPowerToComplete();
|
return current_power_ >= current_stage->getPowerToComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StageManager::isGameCompleted() const {
|
auto StageManager::isGameCompleted() const -> bool {
|
||||||
return current_stage_index_ >= stages_.size() - 1 && isCurrentStageCompleted();
|
return current_stage_index_ >= stages_.size() - 1 && isCurrentStageCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
double StageManager::getProgressPercentage() const {
|
auto StageManager::getProgressPercentage() const -> double {
|
||||||
if (stages_.empty()) return 0.0;
|
if (stages_.empty()) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
int total_power_needed = getTotalPowerNeededToCompleteGame();
|
int total_power_needed = getTotalPowerNeededToCompleteGame();
|
||||||
if (total_power_needed == 0) return 100.0;
|
if (total_power_needed == 0) {
|
||||||
|
return 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
return (static_cast<double>(total_power_) / total_power_needed) * 100.0;
|
return (static_cast<double>(total_power_) / total_power_needed) * 100.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double StageManager::getCurrentStageProgressPercentage() const {
|
auto StageManager::getCurrentStageProgressPercentage() const -> double {
|
||||||
return getCurrentStageProgressFraction() * 100.0;
|
return getCurrentStageProgressFraction() * 100.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double StageManager::getCurrentStageProgressFraction() const {
|
auto StageManager::getCurrentStageProgressFraction() const -> double {
|
||||||
auto current_stage = getCurrentStage();
|
auto current_stage = getCurrentStage();
|
||||||
if (!current_stage.has_value()) {
|
if (!current_stage.has_value()) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int power_needed = current_stage->getPowerToComplete();
|
int power_needed = current_stage->getPowerToComplete();
|
||||||
if (power_needed == 0) {
|
if (power_needed == 0) {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Devuelve una fracción entre 0.0 y 1.0
|
// Devuelve una fracción entre 0.0 y 1.0
|
||||||
double fraction = static_cast<double>(current_power_) / power_needed;
|
double fraction = static_cast<double>(current_power_) / power_needed;
|
||||||
return std::min(fraction, 1.0);
|
return std::min(fraction, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int StageManager::getPowerNeededForCurrentStage() const {
|
auto StageManager::getPowerNeededForCurrentStage() const -> int {
|
||||||
auto current_stage = getCurrentStage();
|
auto current_stage = getCurrentStage();
|
||||||
if (!current_stage.has_value()) {
|
if (!current_stage.has_value()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::max(0, current_stage->getPowerToComplete() - current_power_);
|
return std::max(0, current_stage->getPowerToComplete() - current_power_);
|
||||||
}
|
}
|
||||||
|
|
||||||
int StageManager::getTotalPowerNeededToCompleteGame() const {
|
auto StageManager::getTotalPowerNeededToCompleteGame() const -> int {
|
||||||
int total_power_needed = 0;
|
int total_power_needed = 0;
|
||||||
for (const auto& stage : stages_) {
|
for (const auto& stage : stages_) {
|
||||||
total_power_needed += stage.getPowerToComplete();
|
total_power_needed += stage.getPowerToComplete();
|
||||||
@@ -234,8 +243,20 @@ int StageManager::getTotalPowerNeededToCompleteGame() const {
|
|||||||
return total_power_needed;
|
return total_power_needed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto StageManager::getPowerNeededToReachStage(size_t target_stage_index) const -> int {
|
||||||
|
if (!validateStageIndex(target_stage_index)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int power_needed = 0;
|
||||||
|
for (size_t i = 0; i < target_stage_index; ++i) {
|
||||||
|
power_needed += stages_[i].getPowerToComplete();
|
||||||
|
}
|
||||||
|
return power_needed;
|
||||||
|
}
|
||||||
|
|
||||||
// Implementación de la interfaz IStageInfo
|
// Implementación de la interfaz IStageInfo
|
||||||
bool StageManager::canCollectPower() const {
|
auto StageManager::canCollectPower() const -> bool {
|
||||||
return power_collection_state_ == PowerCollectionState::ENABLED;
|
return power_collection_state_ == PowerCollectionState::ENABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +264,7 @@ void StageManager::addPower(int amount) {
|
|||||||
if (amount <= 0 || !canCollectPower()) {
|
if (amount <= 0 || !canCollectPower()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_power_ += amount;
|
current_power_ += amount;
|
||||||
total_power_ += amount;
|
total_power_ += amount;
|
||||||
|
|
||||||
@@ -251,7 +272,7 @@ void StageManager::addPower(int amount) {
|
|||||||
if (power_change_callback_) {
|
if (power_change_callback_) {
|
||||||
power_change_callback_(amount);
|
power_change_callback_(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verificar si se completó la fase actual
|
// Verificar si se completó la fase actual
|
||||||
if (isCurrentStageCompleted()) {
|
if (isCurrentStageCompleted()) {
|
||||||
auto current_stage = getCurrentStage();
|
auto current_stage = getCurrentStage();
|
||||||
@@ -259,22 +280,22 @@ void StageManager::addPower(int amount) {
|
|||||||
stages_[current_stage_index_].setStatus(StageStatus::COMPLETED);
|
stages_[current_stage_index_].setStatus(StageStatus::COMPLETED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStageStatuses();
|
updateStageStatuses();
|
||||||
}
|
}
|
||||||
|
|
||||||
int StageManager::getCurrentMenaceLevel() const {
|
auto StageManager::getCurrentMenaceLevel() const -> int {
|
||||||
auto current_stage = getCurrentStage();
|
auto current_stage = getCurrentStage();
|
||||||
if (!current_stage.has_value()) {
|
if (!current_stage.has_value()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return current_stage->getMinMenace();
|
return current_stage->getMinMenace();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gestión de callbacks
|
// Gestión de callbacks
|
||||||
void StageManager::setPowerChangeCallback(PowerChangeCallback callback) {
|
void StageManager::setPowerChangeCallback(PowerChangeCallback callback) {
|
||||||
power_change_callback_ = callback;
|
power_change_callback_ = std::move(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StageManager::removePowerChangeCallback() {
|
void StageManager::removePowerChangeCallback() {
|
||||||
@@ -282,7 +303,7 @@ void StageManager::removePowerChangeCallback() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Métodos privados
|
// Métodos privados
|
||||||
bool StageManager::validateStageIndex(size_t index) const {
|
auto StageManager::validateStageIndex(size_t index) const -> bool {
|
||||||
return index < stages_.size();
|
return index < stages_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
179
source/stage.h
179
source/stage.h
@@ -1,111 +1,112 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "stage_interface.h"
|
#include <functional> // Para function
|
||||||
#include <vector>
|
#include <optional> // Para optional
|
||||||
#include <optional>
|
#include <string> // Para string
|
||||||
#include <string>
|
#include <vector> // Para vector
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
// --- Estados posibles para la recolección de poder ---
|
#include "stage_interface.h" // Para IStageInfo
|
||||||
|
|
||||||
|
// --- Enums ---
|
||||||
enum class PowerCollectionState {
|
enum class PowerCollectionState {
|
||||||
ENABLED, // Recolección habilitada
|
ENABLED, // Recolección habilitada
|
||||||
DISABLED // Recolección deshabilitada
|
DISABLED // Recolección deshabilitada
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estados posibles para una fase del juego ---
|
|
||||||
enum class StageStatus {
|
enum class StageStatus {
|
||||||
LOCKED, // Fase bloqueada
|
LOCKED, // Fase bloqueada
|
||||||
IN_PROGRESS, // Fase en progreso
|
IN_PROGRESS, // Fase en progreso
|
||||||
COMPLETED // Fase completada
|
COMPLETED // Fase completada
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Representa los datos de una fase del juego ---
|
// --- Clase StageData: representa los datos de una fase del juego ---
|
||||||
class StageData {
|
class StageData {
|
||||||
private:
|
public:
|
||||||
int power_to_complete_; // Poder necesario para completar la fase
|
// --- Constructor ---
|
||||||
int min_menace_; // Nivel mínimo de amenaza
|
StageData(int power_to_complete, int min_menace, int max_menace, std::string name = ""); // Constructor de una fase
|
||||||
int max_menace_; // Nivel máximo de amenaza
|
|
||||||
std::string name_; // Nombre de la fase
|
|
||||||
StageStatus status_; // Estado actual de la fase
|
|
||||||
|
|
||||||
public:
|
// --- Getters ---
|
||||||
// Constructor de una fase
|
[[nodiscard]] auto getPowerToComplete() const -> int { return power_to_complete_; } // Obtiene el poder necesario para completar
|
||||||
StageData(int power_to_complete, int min_menace, int max_menace, const std::string& name = "");
|
[[nodiscard]] auto getMinMenace() const -> int { return min_menace_; } // Obtiene el nivel mínimo de amenaza
|
||||||
|
[[nodiscard]] auto getMaxMenace() const -> int { return max_menace_; } // Obtiene el nivel máximo de amenaza
|
||||||
|
[[nodiscard]] auto getName() const -> const std::string& { return name_; } // Obtiene el nombre de la fase
|
||||||
|
[[nodiscard]] auto getStatus() const -> StageStatus { return status_; } // Obtiene el estado actual
|
||||||
|
[[nodiscard]] auto isCompleted() const -> bool { return status_ == StageStatus::COMPLETED; } // Verifica si está completada
|
||||||
|
|
||||||
// --- Getters ---
|
// --- Setters ---
|
||||||
int getPowerToComplete() const { return power_to_complete_; }
|
void setStatus(StageStatus status) { status_ = status; } // Establece el estado de la fase
|
||||||
int getMinMenace() const { return min_menace_; }
|
|
||||||
int getMaxMenace() const { return max_menace_; }
|
|
||||||
const std::string& getName() const { return name_; }
|
|
||||||
StageStatus getStatus() const { return status_; }
|
|
||||||
|
|
||||||
// --- Setters ---
|
private:
|
||||||
void setStatus(StageStatus status) { status_ = status; }
|
// --- Variables de estado ---
|
||||||
|
StageStatus status_; // Estado actual de la fase
|
||||||
// --- Utilidades ---
|
std::string name_; // Nombre de la fase
|
||||||
bool isCompleted() const { return status_ == StageStatus::COMPLETED; }
|
int power_to_complete_; // Poder necesario para completar la fase
|
||||||
|
int min_menace_; // Nivel mínimo de amenaza
|
||||||
|
int max_menace_; // Nivel máximo de amenaza
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Gestor principal del sistema de fases del juego ---
|
// --- Clase StageManager: gestor principal del sistema de fases del juego ---
|
||||||
class StageManager : public IStageInfo {
|
class StageManager : public IStageInfo {
|
||||||
private:
|
public:
|
||||||
std::vector<StageData> stages_; // Lista de todas las fases
|
// --- Tipos ---
|
||||||
int current_power_; // Poder actual en la fase activa
|
using PowerChangeCallback = std::function<void(int)>; // Callback para cambios de poder
|
||||||
int total_power_; // Poder total acumulado en todo el juego
|
|
||||||
size_t current_stage_index_; // Índice de la fase actual
|
|
||||||
PowerCollectionState power_collection_state_; // Estado de recolección de poder
|
|
||||||
|
|
||||||
public:
|
// --- Constructor ---
|
||||||
using PowerChangeCallback = std::function<void(int)>;
|
StageManager(); // Constructor principal
|
||||||
|
|
||||||
StageManager();
|
// --- Métodos principales del juego ---
|
||||||
|
void initialize(); // Inicializa el gestor de fases
|
||||||
// --- Métodos principales del juego ---
|
void initialize(const std::string& stages_file); // Inicializa con archivo personalizado
|
||||||
void initialize(); // Inicializa el gestor de fases
|
void reset(); // Reinicia el progreso del juego
|
||||||
void initialize(const std::string& stages_file); // Inicializa con archivo personalizado
|
auto advanceToNextStage() -> bool; // Avanza a la siguiente fase
|
||||||
void reset(); // Reinicia el progreso del juego
|
|
||||||
bool advanceToNextStage(); // Avanza a la siguiente fase
|
|
||||||
|
|
||||||
// --- Gestión de poder ---
|
|
||||||
bool subtractPower(int amount); // Resta poder de la fase actual
|
|
||||||
void enablePowerCollection(); // Habilita la recolección de poder
|
|
||||||
void disablePowerCollection(); // Deshabilita la recolección de poder
|
|
||||||
|
|
||||||
// --- Navegación ---
|
|
||||||
bool jumpToStage(size_t target_stage_index); // Salta a una fase específica
|
|
||||||
|
|
||||||
// --- Consultas de estado ---
|
|
||||||
std::optional<StageData> getCurrentStage() const; // Obtiene la fase actual
|
|
||||||
std::optional<StageData> getStage(size_t index) const; // Obtiene una fase específica
|
|
||||||
size_t getCurrentStageIndex() const { return current_stage_index_; }
|
|
||||||
int getCurrentPower() const { return current_power_; }
|
|
||||||
int getTotalPower() const { return total_power_; }
|
|
||||||
int getTotalPowerNeededToCompleteGame() const; // Poder total necesario para completar el juego
|
|
||||||
size_t getTotalStages() const { return stages_.size(); }
|
|
||||||
|
|
||||||
// --- Seguimiento de progreso ---
|
|
||||||
bool isCurrentStageCompleted() const; // Verifica si la fase actual está completada
|
|
||||||
bool isGameCompleted() const; // Verifica si el juego está completado
|
|
||||||
double getProgressPercentage() const; // Progreso total del juego (0-100%)
|
|
||||||
double getCurrentStageProgressPercentage() const; // Progreso de la fase actual (0-100%)
|
|
||||||
double getCurrentStageProgressFraction() const; // Progreso de la fase actual (0.0-1.0)
|
|
||||||
int getPowerNeededForCurrentStage() const; // Poder restante para completar la fase actual
|
|
||||||
|
|
||||||
// --- Gestión de callbacks ---
|
|
||||||
void setPowerChangeCallback(PowerChangeCallback callback); // Establece callback para cambios de poder
|
|
||||||
void removePowerChangeCallback(); // Elimina callback de cambios de poder
|
|
||||||
|
|
||||||
// --- Implementación de la interfaz IStageInfo ---
|
// --- Gestión de poder ---
|
||||||
bool canCollectPower() const override;
|
auto subtractPower(int amount) -> bool; // Resta poder de la fase actual
|
||||||
void addPower(int amount) override;
|
void enablePowerCollection() override; // Habilita la recolección de poder
|
||||||
int getCurrentMenaceLevel() const override;
|
void disablePowerCollection(); // Deshabilita la recolección de poder
|
||||||
|
|
||||||
private:
|
// --- Navegación ---
|
||||||
PowerChangeCallback power_change_callback_; // Callback para notificar cambios de poder
|
auto jumpToStage(size_t target_stage_index) -> bool; // Salta a una fase específica
|
||||||
|
|
||||||
// --- Métodos privados ---
|
// --- Consultas de estado ---
|
||||||
void createDefaultStages(); // Crea las fases predeterminadas del juego
|
[[nodiscard]] auto getCurrentStage() const -> std::optional<StageData>; // Obtiene la fase actual
|
||||||
bool loadStagesFromFile(const std::string& filename); // Carga fases desde archivo
|
[[nodiscard]] auto getStage(size_t index) const -> std::optional<StageData>; // Obtiene una fase específica
|
||||||
bool validateStageIndex(size_t index) const; // Valida que un índice de fase sea válido
|
[[nodiscard]] auto getCurrentStageIndex() const -> size_t { return current_stage_index_; } // Obtiene el índice de la fase actual
|
||||||
void updateStageStatuses(); // Actualiza los estados de todas las fases
|
[[nodiscard]] auto getCurrentPower() const -> int { return current_power_; } // Obtiene el poder actual
|
||||||
|
[[nodiscard]] auto getTotalPower() const -> int { return total_power_; } // Obtiene el poder total acumulado
|
||||||
|
[[nodiscard]] auto getTotalPowerNeededToCompleteGame() const -> int; // Poder total necesario para completar el juego
|
||||||
|
[[nodiscard]] auto getPowerNeededToReachStage(size_t target_stage_index) const -> int; // Poder necesario para llegar a la fase X
|
||||||
|
[[nodiscard]] auto getTotalStages() const -> size_t { return stages_.size(); } // Obtiene el número total de fases
|
||||||
|
|
||||||
|
// --- Seguimiento de progreso ---
|
||||||
|
[[nodiscard]] auto isCurrentStageCompleted() const -> bool; // Verifica si la fase actual está completada
|
||||||
|
[[nodiscard]] auto isGameCompleted() const -> bool; // Verifica si el juego está completado
|
||||||
|
[[nodiscard]] auto getProgressPercentage() const -> double; // Progreso total del juego (0-100%)
|
||||||
|
[[nodiscard]] auto getCurrentStageProgressPercentage() const -> double; // Progreso de la fase actual (0-100%)
|
||||||
|
[[nodiscard]] auto getCurrentStageProgressFraction() const -> double; // Progreso de la fase actual (0.0-1.0)
|
||||||
|
[[nodiscard]] auto getPowerNeededForCurrentStage() const -> int; // Poder restante para completar la fase actual
|
||||||
|
|
||||||
|
// --- Gestión de callbacks ---
|
||||||
|
void setPowerChangeCallback(PowerChangeCallback callback); // Establece callback para cambios de poder
|
||||||
|
void removePowerChangeCallback(); // Elimina callback de cambios de poder
|
||||||
|
|
||||||
|
// --- Implementación de la interfaz IStageInfo ---
|
||||||
|
[[nodiscard]] auto canCollectPower() const -> bool override; // Verifica si se puede recolectar poder
|
||||||
|
void addPower(int amount) override; // Añade poder a la fase actual
|
||||||
|
[[nodiscard]] auto getCurrentMenaceLevel() const -> int override; // Obtiene el nivel de amenaza actual
|
||||||
|
|
||||||
|
private:
|
||||||
|
// --- Variables de estado ---
|
||||||
|
std::vector<StageData> stages_; // Lista de todas las fases
|
||||||
|
PowerChangeCallback power_change_callback_; // Callback para notificar cambios de poder
|
||||||
|
PowerCollectionState power_collection_state_; // Estado de recolección de poder
|
||||||
|
size_t current_stage_index_; // Índice de la fase actual
|
||||||
|
int current_power_; // Poder actual en la fase activa
|
||||||
|
int total_power_; // Poder total acumulado en todo el juego
|
||||||
|
|
||||||
|
// --- Métodos internos ---
|
||||||
|
void createDefaultStages(); // Crea las fases predeterminadas del juego
|
||||||
|
auto loadStagesFromFile(const std::string& filename) -> bool; // Carga fases desde archivo
|
||||||
|
[[nodiscard]] auto validateStageIndex(size_t index) const -> bool; // Valida que un índice de fase sea válido
|
||||||
|
void updateStageStatuses(); // Actualiza los estados de todas las fases
|
||||||
};
|
};
|
||||||
@@ -6,13 +6,14 @@
|
|||||||
* sin requerir acceso a toda la funcionalidad de StageManager.
|
* sin requerir acceso a toda la funcionalidad de StageManager.
|
||||||
*/
|
*/
|
||||||
class IStageInfo {
|
class IStageInfo {
|
||||||
public:
|
public:
|
||||||
virtual ~IStageInfo() = default;
|
virtual ~IStageInfo() = default;
|
||||||
|
|
||||||
// Interfaz de recolección de poder
|
// Interfaz de recolección de poder
|
||||||
virtual bool canCollectPower() const = 0;
|
[[nodiscard]] virtual auto canCollectPower() const -> bool = 0;
|
||||||
virtual void addPower(int amount) = 0;
|
virtual void enablePowerCollection() = 0;
|
||||||
|
virtual void addPower(int amount) = 0;
|
||||||
// Ajuste de comportamiento del gameplay
|
|
||||||
virtual int getCurrentMenaceLevel() const = 0;
|
// Ajuste de comportamiento del gameplay
|
||||||
|
[[nodiscard]] virtual auto getCurrentMenaceLevel() const -> int = 0;
|
||||||
};
|
};
|
||||||
@@ -1,190 +1,192 @@
|
|||||||
#include "system_utils.h"
|
#include "system_utils.h"
|
||||||
#include <iostream>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <direct.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <direct.h>
|
#include <windows.h>
|
||||||
// Evitar conflictos con macros de Windows
|
// Evitar conflictos con macros de Windows
|
||||||
#ifdef ERROR_ALREADY_EXISTS
|
#ifdef ERROR_ALREADY_EXISTS
|
||||||
#undef ERROR_ALREADY_EXISTS
|
#undef ERROR_ALREADY_EXISTS
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace SystemUtils {
|
namespace SystemUtils {
|
||||||
|
|
||||||
// Función auxiliar para crear una carpeta individual
|
// Función auxiliar para crear una carpeta individual
|
||||||
Result createSingleFolder(const std::string& path, int permissions) {
|
auto createSingleFolder(const std::string& path, int permissions) -> Result {
|
||||||
struct stat st = {0};
|
struct stat st = {.st_dev = 0};
|
||||||
|
|
||||||
// Verificar si ya existe
|
|
||||||
if (stat(path.c_str(), &st) == 0) {
|
|
||||||
return Result::SUCCESS; // Ya existe, no es error por defecto
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intentar crear la carpeta
|
// Verificar si ya existe
|
||||||
int result;
|
if (stat(path.c_str(), &st) == 0) {
|
||||||
|
return Result::SUCCESS; // Ya existe, no es error por defecto
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intentar crear la carpeta
|
||||||
|
int result;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
result = _mkdir(path.c_str());
|
result = _mkdir(path.c_str());
|
||||||
#else
|
#else
|
||||||
result = mkdir(path.c_str(), permissions);
|
result = mkdir(path.c_str(), permissions);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EACCES:
|
case EACCES:
|
||||||
return Result::PERMISSION_DENIED;
|
return Result::PERMISSION_DENIED;
|
||||||
case EEXIST:
|
case EEXIST:
|
||||||
return Result::ALREADY_EXISTS;
|
return Result::ALREADY_EXISTS;
|
||||||
case ENAMETOOLONG:
|
case ENAMETOOLONG:
|
||||||
return Result::PATH_TOO_LONG;
|
return Result::PATH_TOO_LONG;
|
||||||
default:
|
default:
|
||||||
return Result::UNKNOWN_ERROR;
|
return Result::UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función auxiliar para crear carpetas padre recursivamente
|
||||||
|
auto createParentFolders(const std::string& path, int permissions) -> Result {
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
while ((pos = path.find('/', pos + 1)) != std::string::npos) {
|
||||||
|
std::string parent = path.substr(0, pos);
|
||||||
|
if (!parent.empty() && !folderExists(parent)) {
|
||||||
|
Result result = createSingleFolder(parent, permissions);
|
||||||
|
if (result != Result::SUCCESS && result != Result::ALREADY_EXISTS) {
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result::SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Función auxiliar para crear carpetas padre recursivamente
|
return Result::SUCCESS;
|
||||||
Result createParentFolders(const std::string& path, int permissions) {
|
}
|
||||||
size_t pos = 0;
|
|
||||||
|
auto createApplicationFolder(const std::string& app_name, std::string& out_path) -> Result {
|
||||||
while ((pos = path.find('/', pos + 1)) != std::string::npos) {
|
FolderConfig config;
|
||||||
std::string parent = path.substr(0, pos);
|
return createApplicationFolder(app_name, out_path, config);
|
||||||
if (!parent.empty() && !folderExists(parent)) {
|
}
|
||||||
Result result = createSingleFolder(parent, permissions);
|
|
||||||
if (result != Result::SUCCESS && result != Result::ALREADY_EXISTS) {
|
auto createApplicationFolder(const std::string& app_name, std::string& out_path, const FolderConfig& config) -> Result {
|
||||||
return result;
|
out_path = getApplicationDataPath(app_name);
|
||||||
}
|
return createFolder(out_path, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto createFolder(const std::string& path) -> Result {
|
||||||
|
FolderConfig config;
|
||||||
|
return createFolder(path, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto createFolder(const std::string& path, const FolderConfig& config) -> Result {
|
||||||
|
if (path.empty()) {
|
||||||
|
return Result::INVALID_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar si ya existe y si eso es un error
|
||||||
|
if (folderExists(path) && config.fail_if_exists) {
|
||||||
|
return Result::ALREADY_EXISTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear carpetas padre si es necesario
|
||||||
|
if (config.create_parents) {
|
||||||
|
Result parent_result = createParentFolders(path, config.permissions);
|
||||||
|
if (parent_result != Result::SUCCESS) {
|
||||||
|
return parent_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result::SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result createApplicationFolder(const std::string& app_name, std::string& out_path) {
|
// Crear la carpeta final
|
||||||
FolderConfig config;
|
return createSingleFolder(path, config.permissions);
|
||||||
return createApplicationFolder(app_name, out_path, config);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Result createApplicationFolder(const std::string& app_name, std::string& out_path, const FolderConfig& config) {
|
auto getApplicationDataPath(const std::string& app_name) -> std::string {
|
||||||
out_path = getApplicationDataPath(app_name);
|
|
||||||
return createFolder(out_path, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result createFolder(const std::string& path) {
|
|
||||||
FolderConfig config;
|
|
||||||
return createFolder(path, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result createFolder(const std::string& path, const FolderConfig& config) {
|
|
||||||
if (path.empty()) {
|
|
||||||
return Result::INVALID_PATH;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verificar si ya existe y si eso es un error
|
|
||||||
if (folderExists(path) && config.fail_if_exists) {
|
|
||||||
return Result::ALREADY_EXISTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crear carpetas padre si es necesario
|
|
||||||
if (config.create_parents) {
|
|
||||||
Result parent_result = createParentFolders(path, config.permissions);
|
|
||||||
if (parent_result != Result::SUCCESS) {
|
|
||||||
return parent_result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crear la carpeta final
|
|
||||||
return createSingleFolder(path, config.permissions);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getApplicationDataPath(const std::string& app_name) {
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char* appdata = getenv("APPDATA");
|
char* appdata = getenv("APPDATA");
|
||||||
if (appdata) {
|
if (appdata) {
|
||||||
return std::string(appdata) + "/" + app_name;
|
return std::string(appdata) + "/" + app_name;
|
||||||
}
|
}
|
||||||
return "C:/Users/Default/AppData/Roaming/" + app_name;
|
return "C:/Users/Default/AppData/Roaming/" + app_name;
|
||||||
|
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
std::string home = getHomeDirectory();
|
std::string home = getHomeDirectory();
|
||||||
return home + "/Library/Application Support/" + app_name;
|
return home + "/Library/Application Support/" + app_name;
|
||||||
|
|
||||||
#elif __linux__
|
#elif __linux__
|
||||||
std::string home = getHomeDirectory();
|
std::string home = getHomeDirectory();
|
||||||
return home + "/.config/" + app_name;
|
return home + "/.config/" + app_name;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// Fallback genérico
|
// Fallback genérico
|
||||||
std::string home = getHomeDirectory();
|
std::string home = getHomeDirectory();
|
||||||
return home + "/." + app_name;
|
return home + "/." + app_name;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool folderExists(const std::string& path) {
|
auto folderExists(const std::string& path) -> bool {
|
||||||
struct stat st = {0};
|
struct stat st = {.st_dev = 0};
|
||||||
return (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode));
|
return (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* resultToString(Result result) {
|
auto resultToString(Result result) -> const char* {
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case Result::SUCCESS:
|
case Result::SUCCESS:
|
||||||
return "Operación exitosa";
|
return "Operación exitosa";
|
||||||
case Result::PERMISSION_DENIED:
|
case Result::PERMISSION_DENIED:
|
||||||
return "Error: Permisos insuficientes";
|
return "Error: Permisos insuficientes";
|
||||||
case Result::PATH_TOO_LONG:
|
case Result::PATH_TOO_LONG:
|
||||||
return "Error: Ruta demasiado larga";
|
return "Error: Ruta demasiado larga";
|
||||||
case Result::ALREADY_EXISTS:
|
case Result::ALREADY_EXISTS:
|
||||||
return "Error: La carpeta ya existe";
|
return "Error: La carpeta ya existe";
|
||||||
case Result::INVALID_PATH:
|
case Result::INVALID_PATH:
|
||||||
return "Error: Ruta inválida";
|
return "Error: Ruta inválida";
|
||||||
case Result::UNKNOWN_ERROR:
|
case Result::UNKNOWN_ERROR:
|
||||||
return "Error desconocido";
|
return "Error desconocido";
|
||||||
default:
|
default:
|
||||||
return "Error no identificado";
|
return "Error no identificado";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string getHomeDirectory() {
|
auto getHomeDirectory() -> std::string {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char* userprofile = getenv("USERPROFILE");
|
char* userprofile = getenv("USERPROFILE");
|
||||||
if (userprofile) {
|
if (userprofile) {
|
||||||
return std::string(userprofile);
|
return std::string(userprofile);
|
||||||
}
|
}
|
||||||
return "C:/Users/Default";
|
return "C:/Users/Default";
|
||||||
#else
|
#else
|
||||||
struct passwd *pw = getpwuid(getuid());
|
struct passwd* pw = getpwuid(getuid());
|
||||||
if (pw && pw->pw_dir) {
|
if ((pw != nullptr) && (pw->pw_dir != nullptr)) {
|
||||||
return std::string(pw->pw_dir);
|
return {pw->pw_dir};
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback
|
|
||||||
char* home = getenv("HOME");
|
|
||||||
if (home) {
|
|
||||||
return std::string(home);
|
|
||||||
}
|
|
||||||
return "/tmp";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getTempDirectory() {
|
// Fallback
|
||||||
|
char* home = getenv("HOME");
|
||||||
|
if (home != nullptr) {
|
||||||
|
return {home};
|
||||||
|
}
|
||||||
|
return "/tmp";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
auto getTempDirectory() -> std::string {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char* temp = getenv("TEMP");
|
char* temp = getenv("TEMP");
|
||||||
if (temp) {
|
if (temp) {
|
||||||
return std::string(temp);
|
return std::string(temp);
|
||||||
}
|
|
||||||
return "C:/Windows/Temp";
|
|
||||||
#else
|
|
||||||
return "/tmp";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
return "C:/Windows/Temp";
|
||||||
|
#else
|
||||||
|
return "/tmp";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace SystemUtils
|
} // namespace SystemUtils
|
||||||
@@ -2,58 +2,37 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// Utilidades multiplataforma para operaciones del sistema
|
// --- Namespace SystemUtils: utilidades multiplataforma para operaciones del sistema ---
|
||||||
namespace SystemUtils {
|
namespace SystemUtils {
|
||||||
|
// --- Enums ---
|
||||||
|
enum class Result { // Códigos de resultado para operaciones del sistema
|
||||||
|
SUCCESS = 0,
|
||||||
|
PERMISSION_DENIED, // Sin permisos para crear la carpeta
|
||||||
|
PATH_TOO_LONG, // Ruta demasiado larga
|
||||||
|
ALREADY_EXISTS, // Ya existe (solo si se considera error)
|
||||||
|
INVALID_PATH, // Ruta inválida
|
||||||
|
UNKNOWN_ERROR // Error desconocido
|
||||||
|
};
|
||||||
|
|
||||||
// Códigos de resultado para operaciones del sistema
|
// --- Estructuras ---
|
||||||
enum class Result {
|
struct FolderConfig { // Configuración para creación de carpetas
|
||||||
SUCCESS = 0,
|
bool create_parents{true}; // Crear carpetas padre si no existen
|
||||||
PERMISSION_DENIED, // Sin permisos para crear la carpeta
|
bool fail_if_exists{false}; // Fallar si la carpeta ya existe
|
||||||
PATH_TOO_LONG, // Ruta demasiado larga
|
int permissions{0755}; // Permisos Unix (ignorado en Windows)
|
||||||
ALREADY_EXISTS, // Ya existe (solo si se considera error)
|
|
||||||
INVALID_PATH, // Ruta inválida
|
|
||||||
UNKNOWN_ERROR // Error desconocido
|
|
||||||
};
|
|
||||||
|
|
||||||
// Configuración para creación de carpetas
|
|
||||||
struct FolderConfig {
|
|
||||||
bool create_parents; // Crear carpetas padre si no existen
|
|
||||||
bool fail_if_exists; // Fallar si la carpeta ya existe
|
|
||||||
int permissions; // Permisos Unix (ignorado en Windows)
|
|
||||||
|
|
||||||
// Constructor con valores por defecto
|
// Constructor con valores por defecto
|
||||||
FolderConfig()
|
FolderConfig() = default;
|
||||||
: create_parents(true)
|
};
|
||||||
, fail_if_exists(false)
|
|
||||||
, permissions(0755) // rwxr-xr-x
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Crea la carpeta del sistema donde guardar datos de la aplicación
|
// --- Funciones ---
|
||||||
Result createApplicationFolder(const std::string& app_name, std::string& out_path);
|
auto createApplicationFolder(const std::string& app_name, std::string& out_path) -> Result; // Crea la carpeta del sistema donde guardar datos de la aplicación
|
||||||
|
auto createApplicationFolder(const std::string& app_name, std::string& out_path, const FolderConfig& config) -> Result; // Crea la carpeta del sistema con configuración personalizada
|
||||||
|
auto createFolder(const std::string& path) -> Result; // Crea una carpeta en la ruta especificada
|
||||||
|
auto createFolder(const std::string& path, const FolderConfig& config) -> Result; // Crea una carpeta con configuración personalizada
|
||||||
|
auto getApplicationDataPath(const std::string& app_name) -> std::string; // Obtiene la ruta de datos de la aplicación (sin crearla)
|
||||||
|
auto folderExists(const std::string& path) -> bool; // Verifica si una carpeta existe
|
||||||
|
auto resultToString(Result result) -> const char*; // Convierte un código de resultado a string descriptivo
|
||||||
|
auto getHomeDirectory() -> std::string; // Obtiene el directorio home del usuario
|
||||||
|
auto getTempDirectory() -> std::string; // Obtiene el directorio temporal del sistema
|
||||||
|
|
||||||
// Crea la carpeta del sistema con configuración personalizada
|
} // namespace SystemUtils
|
||||||
Result createApplicationFolder(const std::string& app_name, std::string& out_path, const FolderConfig& config);
|
|
||||||
|
|
||||||
// Crea una carpeta en la ruta especificada
|
|
||||||
Result createFolder(const std::string& path);
|
|
||||||
|
|
||||||
// Crea una carpeta con configuración personalizada
|
|
||||||
Result createFolder(const std::string& path, const FolderConfig& config);
|
|
||||||
|
|
||||||
// Obtiene la ruta de datos de la aplicación (sin crearla)
|
|
||||||
std::string getApplicationDataPath(const std::string& app_name);
|
|
||||||
|
|
||||||
// Verifica si una carpeta existe
|
|
||||||
bool folderExists(const std::string& path);
|
|
||||||
|
|
||||||
// Convierte un código de resultado a string descriptivo
|
|
||||||
const char* resultToString(Result result);
|
|
||||||
|
|
||||||
// Obtiene el directorio home del usuario
|
|
||||||
std::string getHomeDirectory();
|
|
||||||
|
|
||||||
// Obtiene el directorio temporal del sistema
|
|
||||||
std::string getTempDirectory();
|
|
||||||
|
|
||||||
} // namespace SystemUtils
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ void Tabe::move() {
|
|||||||
? LEFT[rand() % CHOICES]
|
? LEFT[rand() % CHOICES]
|
||||||
: RIGHT[rand() % CHOICES];
|
: RIGHT[rand() % CHOICES];
|
||||||
|
|
||||||
setRandomFlyPath(DIRECTION, 20 + rand() % 40);
|
setRandomFlyPath(DIRECTION, 20 + (rand() % 40));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,9 +125,9 @@ void Tabe::enable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Establece un vuelo aleatorio
|
// Establece un vuelo aleatorio
|
||||||
void Tabe::setRandomFlyPath(Direction direction, int lenght) {
|
void Tabe::setRandomFlyPath(Direction direction, int length) {
|
||||||
direction_ = direction;
|
direction_ = direction;
|
||||||
fly_distance_ = lenght;
|
fly_distance_ = length;
|
||||||
waiting_counter_ = 5 + rand() % 15;
|
waiting_counter_ = 5 + rand() % 15;
|
||||||
Audio::get()->playSound("tabe.wav");
|
Audio::get()->playSound("tabe.wav");
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ class Tabe {
|
|||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void move(); // Mueve el objeto
|
void move(); // Mueve el objeto
|
||||||
void shiftSprite() { sprite_->setPos(x_, y_); } // Actualiza la posición del sprite
|
void shiftSprite() { sprite_->setPos(x_, y_); } // Actualiza la posición del sprite
|
||||||
void setRandomFlyPath(Direction direction, int lenght); // Establece un vuelo aleatorio
|
void setRandomFlyPath(Direction direction, int length); // Establece un vuelo aleatorio
|
||||||
void updateState(); // Actualiza el estado
|
void updateState(); // Actualiza el estado
|
||||||
void updateTimer(); // Actualiza el temporizador
|
void updateTimer(); // Actualiza el temporizador
|
||||||
void disable(); // Deshabilita el objeto
|
void disable(); // Deshabilita el objeto
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user