Compare commits

..

2 Commits

Author SHA1 Message Date
40766ad122 fix: en console faltava SCENE DEMO 2026-04-13 18:02:04 +02:00
e67aeb10fe fix: controls en el mando 2026-04-13 17:57:13 +02:00
9 changed files with 53 additions and 18 deletions

View File

@@ -201,7 +201,7 @@ categories:
DEBUG: [MODE, START]
DEBUG MODE: [ON, OFF]
DEBUG START: [HERE, ROOM, POS, SCENE]
DEBUG START SCENE: [LOGO, LOADING, TITLE, CREDITS, GAME, ENDING, ENDING2]
DEBUG START SCENE: [LOGO, LOADING, TITLE, CREDITS, GAME, DEMO, ENDING, ENDING2]
- keyword: ITEMS
handler: cmd_items
@@ -220,9 +220,9 @@ categories:
- keyword: SCENE
handler: cmd_scene
description: Change scene
usage: "SCENE [LOGO|LOADING|TITLE|CREDITS|GAME|ENDING|ENDING2|RESTART]"
usage: "SCENE [LOGO|LOADING|TITLE|CREDITS|GAME|DEMO|ENDING|ENDING2|RESTART]"
completions:
SCENE: [LOGO, LOADING, TITLE, CREDITS, GAME, ENDING, ENDING2, RESTART]
SCENE: [LOGO, LOADING, TITLE, CREDITS, GAME, DEMO, ENDING, ENDING2, RESTART]
- keyword: EDIT
handler: cmd_edit

View File

@@ -154,8 +154,9 @@ namespace GlobalInputs {
// Detecta qué acción global ha sido presionada (si alguna)
auto getPressedAction() -> InputAction { // NOLINT(readability-function-cognitive-complexity)
// Qualsevol botó del comandament actua com a ACCEPT (saltar escenes
// d'attract mode: logo, loading, credits, demo, ending...). Es prioritza
// sobre EXIT perquè s'envia com a flag d'event, no com a check d'acció.
// d'attract mode: logo, loading, credits, demo, ending...). El botó
// BACK queda filtrat prèviament a GlobalEvents per no colidir amb EXIT
// (excepte en emscripten, on BACK no pot sortir i sí pot saltar).
if (GlobalEvents::consumeGamepadButtonPressed()) {
return InputAction::ACCEPT;
}

View File

@@ -390,12 +390,21 @@ void Input::update() { // NOLINT(readability-convert-member-functions-to-static
// --- MANDOS ---
for (const auto& gamepad : gamepads_) {
for (auto& binding : gamepad->bindings) {
bool button_is_down_now = static_cast<int>(SDL_GetGamepadButton(gamepad->pad, static_cast<SDL_GamepadButton>(binding.second.button))) != 0;
for (auto& [action, state] : gamepad->bindings) {
bool is_down_now = static_cast<int>(SDL_GetGamepadButton(gamepad->pad, static_cast<SDL_GamepadButton>(state.button))) != 0;
// JUMP accepta qualsevol dels 4 botons frontals (South/East/North/West)
if (action == Action::JUMP) {
is_down_now = is_down_now ||
(SDL_GetGamepadButton(gamepad->pad, SDL_GAMEPAD_BUTTON_SOUTH) != 0) ||
(SDL_GetGamepadButton(gamepad->pad, SDL_GAMEPAD_BUTTON_EAST) != 0) ||
(SDL_GetGamepadButton(gamepad->pad, SDL_GAMEPAD_BUTTON_NORTH) != 0) ||
(SDL_GetGamepadButton(gamepad->pad, SDL_GAMEPAD_BUTTON_WEST) != 0);
}
// 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.is_held = button_is_down_now;
state.just_pressed = is_down_now && !state.is_held;
state.is_held = is_down_now;
}
}
}

View File

@@ -60,7 +60,12 @@ class Input {
// Movimiento del jugador
{Action::LEFT, ButtonState{.button = static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_LEFT)}},
{Action::RIGHT, ButtonState{.button = static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_RIGHT)}},
{Action::JUMP, ButtonState{.button = static_cast<int>(SDL_GAMEPAD_BUTTON_WEST)}}} {}
{Action::JUMP, ButtonState{.button = static_cast<int>(SDL_GAMEPAD_BUTTON_WEST)}},
// Botó BACK del mando → sortir escena / tancar joc
{Action::EXIT, ButtonState{.button = static_cast<int>(SDL_GAMEPAD_BUTTON_BACK)}},
{Action::CANCEL, ButtonState{.button = static_cast<int>(SDL_GAMEPAD_BUTTON_BACK)}},
// Botó START del mando → pausa
{Action::PAUSE, ButtonState{.button = static_cast<int>(SDL_GAMEPAD_BUTTON_START)}}} {}
~Gamepad() {
if (pad != nullptr) {

View File

@@ -151,6 +151,7 @@ Director::Director() {
// perquè la textura 256x192 no es vegi minúscula al canvas HTML,
// i desactivem el borde per aprofitar al màxim l'espai del canvas.
Options::video.fullscreen = false;
Options::video.integer_scale = false;
Options::window.zoom = 4;
Options::video.border.enabled = true;
Options::video.border.height = 8;

View File

@@ -39,9 +39,18 @@ namespace GlobalEvents {
}
}
// Marcar polsació de qualsevol botó del comandament (els consumirà GlobalInputs).
// Marcar polsació de qualsevol botó del comandament (els consumirà GlobalInputs
// per saltar escenes d'attract mode). El botó BACK queda exclòs perquè es
// reserva per a l'acció EXIT — excepte a emscripten, on no es pot sortir del
// joc i el BACK pot actuar com a botó genèric per saltar escenes.
if (event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) {
#ifdef __EMSCRIPTEN__
gamepad_button_pressed_ = true;
#else
if (event.gbutton.button != SDL_GAMEPAD_BUTTON_BACK) {
gamepad_button_pressed_ = true;
}
#endif
}
// Enrutar eventos de texto a la consola cuando está activa

View File

@@ -93,10 +93,16 @@ void Title::handleEvent(const SDL_Event& event) {
}
// Qualsevol botó del comandament al menú principal inicia partida directament
// (els bindings ja estan definits, no cal "pulsar 1" amb el teclat).
// (els bindings ja estan definits, no cal "pulsar 1" amb el teclat). El botó
// BACK queda exclòs perquè es reserva per a EXIT — excepte a emscripten, on
// no es pot sortir del joc i BACK pot actuar com a botó genèric d'inici.
if (event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN &&
state_ == State::MAIN_MENU &&
!is_remapping_keyboard_ && !is_remapping_joystick_) {
!is_remapping_keyboard_ && !is_remapping_joystick_
#ifndef __EMSCRIPTEN__
&& event.gbutton.button != SDL_GAMEPAD_BUTTON_BACK
#endif
) {
handleMainMenuKeyPress(SDLK_1); // PLAY
return;
}

View File

@@ -491,6 +491,9 @@ static auto cmdDebug(const std::vector<std::string>& args) -> std::string { //
if (args[2] == "GAME") {
target = SceneManager::Scene::GAME;
name = "game";
} else if (args[2] == "DEMO") {
target = SceneManager::Scene::DEMO;
name = "demo";
} else if (args[2] == "LOGO") {
target = SceneManager::Scene::LOGO;
name = "logo";
@@ -651,10 +654,10 @@ static auto cmdItems(const std::vector<std::string>& args) -> std::string {
return "Items: " + std::to_string(count);
}
// SCENE [LOGO|LOADING|TITLE|CREDITS|GAME|ENDING|ENDING2|RESTART]
// SCENE [LOGO|LOADING|TITLE|CREDITS|GAME|DEMO|ENDING|ENDING2|RESTART]
static auto cmdScene(const std::vector<std::string>& args) -> std::string {
if (Options::kiosk.enabled) { return "Not allowed in kiosk mode"; }
if (args.empty()) { return "usage: scene [logo|loading|title|credits|game|ending|ending2|restart]"; }
if (args.empty()) { return "usage: scene [logo|loading|title|credits|game|demo|ending|ending2|restart]"; }
if (args[0] == "RESTART") {
SceneManager::scene_before_restart = SceneManager::current;
@@ -677,6 +680,7 @@ static auto cmdScene(const std::vector<std::string>& args) -> std::string {
if (args[0] == "TITLE") { return GO_TO(SceneManager::Scene::TITLE, "Title"); }
if (args[0] == "CREDITS") { return GO_TO(SceneManager::Scene::CREDITS, "Credits"); }
if (args[0] == "GAME") { return GO_TO(SceneManager::Scene::GAME, "Game"); }
if (args[0] == "DEMO") { return GO_TO(SceneManager::Scene::DEMO, "Demo"); }
if (args[0] == "ENDING") { return GO_TO(SceneManager::Scene::ENDING, "Ending"); }
if (args[0] == "ENDING2") { return GO_TO(SceneManager::Scene::ENDING2, "Ending 2"); }
return "Unknown scene: " + args[0];