feat(gamepad): controls de gamepad per al player i el menú de servei
This commit is contained in:
1 parent
7c35ffaa74
commit
a230351b79
2 files changed
+67
No files matched your search
@@ -8,6 +8,7 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "core/input/gamepad_manager.hpp"
|
||||||
#include "core/input/input_state.hpp"
|
#include "core/input/input_state.hpp"
|
||||||
#include "core/resources/resource_cache.hpp"
|
#include "core/resources/resource_cache.hpp"
|
||||||
#include "core/resources/resource_helper.hpp"
|
#include "core/resources/resource_helper.hpp"
|
||||||
@@ -20,6 +21,29 @@ namespace {
|
|||||||
// Alias local per reduir soroll; la constant viu a Defaults::Player.
|
// Alias local per reduir soroll; la constant viu a Defaults::Player.
|
||||||
constexpr float SPEED_PX_PER_S = Defaults::Player::SPEED_PX_PER_S;
|
constexpr float SPEED_PX_PER_S = Defaults::Player::SPEED_PX_PER_S;
|
||||||
|
|
||||||
|
// Dead-zone del stick analògic esquerre (rang Sint16: -32768..32767).
|
||||||
|
// Converteix eix analògic en direcció digital; per sota, es considera
|
||||||
|
// repòs i no contribueix a la velocitat.
|
||||||
|
constexpr Sint16 STICK_DEADZONE = 12000;
|
||||||
|
|
||||||
|
// Acumula la contribució del primer gamepad (cruceta + stick esquerre)
|
||||||
|
// sobre els acumuladors de velocitat. Extracció d'`update()` per a
|
||||||
|
// mantenir la complexitat cognitiva sota llindar (threshold 25).
|
||||||
|
void accumulateGamepadMovement(float& vx, float& vy) {
|
||||||
|
SDL_Gamepad* pad = GamepadManager::get().getPrimary();
|
||||||
|
if (pad == nullptr) { return; }
|
||||||
|
if (InputState::getGamepadButton(pad, SDL_GAMEPAD_BUTTON_DPAD_LEFT)) { vx -= SPEED_PX_PER_S; }
|
||||||
|
if (InputState::getGamepadButton(pad, SDL_GAMEPAD_BUTTON_DPAD_RIGHT)) { vx += SPEED_PX_PER_S; }
|
||||||
|
if (InputState::getGamepadButton(pad, SDL_GAMEPAD_BUTTON_DPAD_UP)) { vy -= SPEED_PX_PER_S; }
|
||||||
|
if (InputState::getGamepadButton(pad, SDL_GAMEPAD_BUTTON_DPAD_DOWN)) { vy += SPEED_PX_PER_S; }
|
||||||
|
const Sint16 LX = InputState::getGamepadAxis(pad, SDL_GAMEPAD_AXIS_LEFTX);
|
||||||
|
const Sint16 LY = InputState::getGamepadAxis(pad, SDL_GAMEPAD_AXIS_LEFTY);
|
||||||
|
if (LX < -STICK_DEADZONE) { vx -= SPEED_PX_PER_S; }
|
||||||
|
if (LX > STICK_DEADZONE) { vx += SPEED_PX_PER_S; }
|
||||||
|
if (LY < -STICK_DEADZONE) { vy -= SPEED_PX_PER_S; }
|
||||||
|
if (LY > STICK_DEADZONE) { vy += SPEED_PX_PER_S; }
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void Player::loadFrom(const std::string& yaml_path) {
|
void Player::loadFrom(const std::string& yaml_path) {
|
||||||
@@ -70,6 +94,14 @@ void Player::update(float delta_time) {
|
|||||||
if (keys[controls_.up]) { vy -= SPEED_PX_PER_S; }
|
if (keys[controls_.up]) { vy -= SPEED_PX_PER_S; }
|
||||||
if (keys[controls_.down]) { vy += SPEED_PX_PER_S; }
|
if (keys[controls_.down]) { vy += SPEED_PX_PER_S; }
|
||||||
|
|
||||||
|
// Cruceta i stick esquerre del primer gamepad (si n'hi ha). També
|
||||||
|
// respecten el bloqueig d'`InputState`, així que amb el menú obert
|
||||||
|
// els botons tornen false/0 i no contribueixen a la velocitat.
|
||||||
|
// Direccions oposades (teclat left + d-pad right) es cancel·len de
|
||||||
|
// forma natural; premuda simultània en la mateixa direcció no duplica
|
||||||
|
// la velocitat perquè cada branca només resta/suma una vegada.
|
||||||
|
accumulateGamepadMovement(vx, vy);
|
||||||
|
|
||||||
setVelX(vx);
|
setVelX(vx);
|
||||||
setVelY(vy);
|
setVelY(vy);
|
||||||
|
|
||||||
|
|||||||
@@ -426,6 +426,41 @@ void ServiceMenu::activateCurrent(int direction) {
|
|||||||
|
|
||||||
auto ServiceMenu::handleEvent(const SDL_Event& ev) -> bool {
|
auto ServiceMenu::handleEvent(const SDL_Event& ev) -> bool {
|
||||||
if (!open_) { return false; }
|
if (!open_) { return false; }
|
||||||
|
|
||||||
|
// Botons del gamepad: cruceta per navegar, EAST/NORTH com a OK,
|
||||||
|
// WEST/SOUTH com a BACK de pàgina, BACK tanca el menú sencer. Quan
|
||||||
|
// el menú està obert consumim TOTS els BUTTON_DOWN perquè cap botó
|
||||||
|
// arribi als consumidors de gameplay. Paral·lel al consum total de
|
||||||
|
// KEY_DOWN més avall.
|
||||||
|
if (ev.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) {
|
||||||
|
switch (ev.gbutton.button) {
|
||||||
|
case SDL_GAMEPAD_BUTTON_DPAD_UP:
|
||||||
|
moveCursor(-1);
|
||||||
|
break;
|
||||||
|
case SDL_GAMEPAD_BUTTON_DPAD_DOWN:
|
||||||
|
moveCursor(+1);
|
||||||
|
break;
|
||||||
|
case SDL_GAMEPAD_BUTTON_DPAD_LEFT:
|
||||||
|
activateCurrent(-1);
|
||||||
|
break;
|
||||||
|
case SDL_GAMEPAD_BUTTON_DPAD_RIGHT:
|
||||||
|
case SDL_GAMEPAD_BUTTON_EAST:
|
||||||
|
case SDL_GAMEPAD_BUTTON_NORTH:
|
||||||
|
activateCurrent(+1);
|
||||||
|
break;
|
||||||
|
case SDL_GAMEPAD_BUTTON_WEST:
|
||||||
|
case SDL_GAMEPAD_BUTTON_SOUTH:
|
||||||
|
popPage();
|
||||||
|
break;
|
||||||
|
case SDL_GAMEPAD_BUTTON_BACK:
|
||||||
|
close();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (ev.type != SDL_EVENT_KEY_DOWN) { return false; }
|
if (ev.type != SDL_EVENT_KEY_DOWN) { return false; }
|
||||||
|
|
||||||
const auto SC = ev.key.scancode;
|
const auto SC = ev.key.scancode;
|
||||||
|
|||||||
Reference in new issue
Block a user