From 61f97ef7a5a96569b57ddbdbacc8246058bab1d8 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Mon, 29 Dec 2008 15:39:39 +0000 Subject: [PATCH] Basic joystick support --- src/Game.cpp | 29 +++++----- src/Game.hpp | 1 - src/HighScores.cpp | 23 ++++---- src/Input.cpp | 131 +++++++++++++++++++++++++-------------------- src/Input.hpp | 23 ++++---- src/Menu.cpp | 23 ++++---- src/Options.cpp | 18 +++---- 7 files changed, 126 insertions(+), 122 deletions(-) diff --git a/src/Game.cpp b/src/Game.cpp index 9e31cca..30fbf12 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -21,6 +21,7 @@ #include "Menu.hpp" #include "HighScores.hpp" #include "LoadOnce.hpp" +#include "Input.hpp" /* * Constants affecting level generation. @@ -121,25 +122,25 @@ void Game::Process() OpenGL &opengl = OpenGL::GetInstance(); // Check keys - if (input.GetKeyState(SDLK_p)) { + if (input.QueryAction(Input::PAUSE)) { if (state == gsPaused) { // Unpause the game state = gsInGame; - input.ResetKey(SDLK_p); } else if (state == gsInGame) { // Pause the game state = gsPaused; - input.ResetKey(SDLK_p); ship.ThrustOff(); } + + input.ResetAction(Input::PAUSE); } - // Check for paused state + // Do no more game processing in the paused state if (state == gsPaused) return; - if ((input.GetKeyState(SDLK_UP) || input.QueryJoystickButton(1)) + if (input.QueryAction(Input::THRUST) && !fuelmeter.OutOfFuel() && state == gsInGame) { // Thrusting ship.ThrustOn(); @@ -149,32 +150,30 @@ void Game::Process() else ship.ThrustOff(); - if ((input.GetKeyState(SDLK_RIGHT) || input.QueryJoystickAxis(0) > 0) - && state == gsInGame) { + if (input.QueryAction(Input::RIGHT) && state == gsInGame) { // Turn clockwise ship.Turn(TURN_ANGLE); } - else if ((input.GetKeyState(SDLK_LEFT) || input.QueryJoystickAxis(0) < 0) - && state == gsInGame) { + else if (input.QueryAction(Input::LEFT) && state == gsInGame) { // Turn anti-clockwise ship.Turn(-TURN_ANGLE); } - if (input.GetKeyState(SDLK_SPACE) && state == gsExplode) { - // Skip explosion + if (input.QueryAction(Input::SKIP) && state == gsExplode) { + // The player got bored watching the explosion EnterDeathWait(lives == 0 ? DEATH_TIMEOUT : 1); } - if (input.GetKeyState(SDLK_ESCAPE) && state == gsInGame) { + if (input.QueryAction(Input::ABORT) && state == gsInGame) { // Quit to main menu ExplodeShip(); lives = 0; } - if (input.GetKeyState(SDLK_d)) { - // Toggle mode + if (input.QueryAction(Input::DEBUG)) { + // Toggle debug mode bDebugMode = !bDebugMode; - input.ResetKey(SDLK_d); + input.ResetAction(Input::DEBUG); } // Move only if not in game over diff --git a/src/Game.hpp b/src/Game.hpp index 3ede68c..590a269 100644 --- a/src/Game.hpp +++ b/src/Game.hpp @@ -24,7 +24,6 @@ #include "OpenGL.hpp" #include "Emitter.hpp" #include "ScreenManager.hpp" -#include "Input.hpp" #include "Font.hpp" #include "SoundEffect.hpp" #include "Fade.hpp" diff --git a/src/HighScores.cpp b/src/HighScores.cpp index d9d0a84..a79c55a 100644 --- a/src/HighScores.cpp +++ b/src/HighScores.cpp @@ -51,11 +51,9 @@ void HighScores::Process() // Check for input if (state == hssDisplay) { - if (input.GetKeyState(SDLK_SPACE) - || input.QueryJoystickButton(0) - || input.QueryJoystickButton(0) - || input.GetKeyState(SDLK_RETURN) - || input.GetKeyState(SDLK_ESCAPE)) { + if (input.QueryAction(Input::SKIP) + || input.QueryAction(Input::ABORT) + || input.QueryAction(Input::FIRE)) { // Go back to main menu fade = HS_FADE_OUT_SPEED; @@ -67,14 +65,13 @@ void HighScores::Process() fw[i].em->life = 0.5f; } - input.ResetKey(SDLK_RETURN); - input.ResetKey(SDLK_SPACE); + input.ResetAction(Input::SKIP); + input.ResetAction(Input::FIRE); + input.ResetAction(Input::ABORT); } } else if (state == hssEnterName) { - if ((input.GetKeyState(SDLK_RETURN) - || input.QueryJoystickButton(0) - || input.QueryJoystickButton(1)) + if (input.QueryAction(Input::FIRE) && strlen(input.GetInput()) > 0) { // Enter name into high score chart @@ -84,10 +81,8 @@ void HighScores::Process() state = hssDisplay; flAlpha = 0.0f; fade = HS_FADE_IN_SPEED; - - input.ResetKey(SDLK_RETURN); - input.ResetJoystickButton(0); - input.ResetJoystickButton(1); + + input.ResetAction(Input::FIRE); } } diff --git a/src/Input.cpp b/src/Input.cpp index fb637ae..b388f59 100644 --- a/src/Input.cpp +++ b/src/Input.cpp @@ -24,7 +24,8 @@ * Create a new input manager. Never call this directly: use GetInstance. */ Input::Input() - : joystick(NULL), textinput(false) + : joystick(NULL), textinput(false), joyLeft(false), joyRight(false), + joyUp(false), joyDown(false), joyButton0(false), joyButton1(false) { // Start SDL joystick handling subsystem if (SDL_Init(SDL_INIT_JOYSTICK) < 0) { @@ -42,11 +43,8 @@ Input::Input() joystick = SDL_JoystickOpen(0); } - for (int i = 0; i < NUM_KEYS; i++) - ignore[i] = 0; - - for (int i = 0; i < NUM_BUTTONS; i++) - jignore[i] = 0; + for (int i = 0; i < NUM_ACTIONS; i++) + actionIgnore[i] = 0; } @@ -77,7 +75,6 @@ Input &Input::GetInstance() void Input::Update() { SDL_Event e; - int i; while (SDL_PollEvent(&e)) { switch (e.type) { @@ -113,72 +110,108 @@ void Input::Update() case SDL_JOYAXISMOTION: // Joystick was moved - if ((e.jaxis.value < -3200) || (e.jaxis.value > 3200)) { + if ((e.jaxis.value < -3500) || (e.jaxis.value > 3500)) { if (e.jaxis.axis == 0) { // Left-right movement code goes here + if (e.jaxis.value < 0) + joyLeft = true; + else + joyRight = true; } if (e.jaxis.axis == 1) { // Up-Down movement code goes here + if (e.jaxis.value < 0) + joyUp = true; + else + joyDown = true; } } + else { + joyLeft = false; + joyRight = false; + joyUp = false; + joyDown = false; + } break; case SDL_JOYBUTTONDOWN: // Joystick button was pressed // Button is e.jbutton.button + switch (e.jbutton.button) { + case 0: + joyButton0 = true; + break; + case 1: + joyButton1 = true; + break; + } break; case SDL_JOYBUTTONUP: // Joystick button was released + switch (e.jbutton.button) { + case 0: + joyButton0 = false; + break; + case 1: + joyButton1 = false; + break; + } break; } } - for (i = 0; i < NUM_KEYS; i++) { - if (ignore[i] > 0) - ignore[i]--; + for (int i = 0; i < NUM_ACTIONS; i++) { + if (actionIgnore[i] > 0) + actionIgnore[i]--; } } - -/* - * Returns the state of one key. Result true if currently pressed. - */ -bool Input::GetKeyState(int key) +// Returns true if the action a is being perfomed. +// Either on the keyboard on the first joystick. +bool Input::QueryAction(Action a) const { int numkeys; Uint8 *keystate; - if (ignore[key]) + if (actionIgnore[a] > 0) return false; - + keystate = SDL_GetKeyState(&numkeys); - assert(key < numkeys); - - return keystate[key] != 0; + + switch (a) { + case UP: + return (keystate[SDLK_UP] != 0) || joyUp; + case DOWN: + return (keystate[SDLK_DOWN] != 0) || joyDown; + case LEFT: + return (keystate[SDLK_LEFT] != 0) || joyLeft; + case RIGHT: + return (keystate[SDLK_RIGHT] != 0) || joyRight; + case FIRE: + return (keystate[SDLK_RETURN] != 0) || joyButton0 || joyButton1; + case SKIP: + return (keystate[SDLK_SPACE] != 0) || joyButton0; + case ABORT: + return keystate[SDLK_ESCAPE] != 0; + case DEBUG: + return keystate[SDLK_d] != 0; + case PAUSE: + return keystate[SDLK_p] != 0; + case THRUST: + return (keystate[SDLK_UP] != 0) || joyButton1; + default: + assert(false); + } } - -/* - * Waits RESET_TIMEOUT frames before registering a particular keypress again. - */ -void Input::ResetKey(int key) +// Waits RESET_TIMEOUT frames before registering action a again. +void Input::ResetAction(Action a) { - assert(key < NUM_KEYS); - - ignore[key] = RESET_TIMEOUT; -} + assert(a < NUM_ACTIONS); - -/* - * Waits RESET_TIMEOUT frames before registering a particular button press again. - */ -void Input::ResetJoystickButton(int button) -{ - assert(button < NUM_BUTTONS); - - jignore[button] = RESET_TIMEOUT; + actionIgnore[a] = RESET_TIMEOUT; } @@ -215,23 +248,3 @@ const char *Input::GetInput() const return text.c_str(); } - -/* - * Returns the current value of a joystick axis. - * axis -> 0 = horizontal, 1 = vertical. - */ -int Input::QueryJoystickAxis(int axis) -{ - return 0; -} - - -/* - * Returns the current state of a joystick button. - * button -> Numbered from zero. - */ -bool Input::QueryJoystickButton(int button) -{ - return false; -} - diff --git a/src/Input.hpp b/src/Input.hpp index 45e9c55..e0c549a 100644 --- a/src/Input.hpp +++ b/src/Input.hpp @@ -27,14 +27,17 @@ */ class Input { public: + // Possible inputs + enum Action { + UP, DOWN, LEFT, RIGHT, FIRE, + SKIP, ABORT, DEBUG, PAUSE, THRUST + }; + static Input &GetInstance(); + bool QueryAction(Action a) const; + void ResetAction(Action a); void Update(); - bool GetKeyState(int key); - void ResetKey(int key); - int QueryJoystickAxis(int axis); - bool QueryJoystickButton(int button); - void ResetJoystickButton(int button); void OpenCharBuffer(int max=256); void CloseCharBuffer(); @@ -44,20 +47,20 @@ private: Input(); ~Input(); - static const int NUM_KEYS = 512; // Maximum number of input keys - static const int RESET_TIMEOUT = 5; // Frames between key presses - static const int NUM_BUTTONS = 16; // Maximum number of joystick buttons + static const int NUM_ACTIONS = 10; + static const int RESET_TIMEOUT = 10; // Frames between key presses SDL_Joystick *joystick; - int ignore[NUM_KEYS]; // Timeout for keys being ignored - int jignore[NUM_BUTTONS]; // Timeout for buttons being ignored + int actionIgnore[NUM_ACTIONS]; // Timeout for actions being ignored bool shift; bool textinput; // Is a character buffer open? string text; // Text read so far int maxchar; // Maximum number of characters to read + // Record joystick state + bool joyLeft, joyRight, joyUp, joyDown, joyButton0, joyButton1; }; #endif diff --git a/src/Menu.cpp b/src/Menu.cpp index f23998e..b881157 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -72,7 +72,7 @@ void MainMenu::Process() // Stop user doing something when they're not supposed to if (state == msInMenu) { // Look at keys - if (input.GetKeyState(SDLK_DOWN) || input.QueryJoystickAxis(1) > 0) { + if (input.QueryAction(Input::DOWN)) { // Move the selection down switch (selOption) { case optStart: @@ -87,11 +87,10 @@ void MainMenu::Process() default: break; } - - input.ResetKey(SDLK_DOWN); - //opengl.di.ResetProp(DIJ_YAXIS); + + input.ResetAction(Input::DOWN); } - else if (input.GetKeyState(SDLK_UP) /*|| opengl.di.QueryJoystick(DIJ_YAXIS) < 0*/) { + else if (input.QueryAction(Input::UP)) { // Move the selection up switch (selOption) { case optScore: @@ -106,12 +105,10 @@ void MainMenu::Process() default: break; } - - input.ResetKey(SDLK_UP); - //opengl.di.ResetProp(DIJ_YAXIS); + + input.ResetAction(Input::UP); } - else if (input.GetKeyState(SDLK_RETURN) - /*|| opengl.di.QueryJoystick(DIJ_BUTTON0) || opengl.di.QueryJoystick(DIJ_BUTTON1)*/ ) { + else if (input.QueryAction(Input::FIRE)) { // Select this option switch (selOption) { case optStart: @@ -127,10 +124,8 @@ void MainMenu::Process() state = msFadeToExit; break; } - - input.ResetKey(SDLK_RETURN); - /*opengl.di.ResetProp(DIJ_BUTTON0); - opengl.di.ResetProp(DIJ_BUTTON1);*/ + + input.ResetAction(Input::FIRE); } } diff --git a/src/Options.cpp b/src/Options.cpp index bbda0e4..aa3cef6 100644 --- a/src/Options.cpp +++ b/src/Options.cpp @@ -85,31 +85,31 @@ void Options::ProcessMain() { Input &input = Input::GetInstance(); - if (input.GetKeyState(SDLK_RETURN)) { + if (input.QueryAction(Input::FIRE)) { state = optFadeOut; } - else if (input.GetKeyState(SDLK_UP)) { + else if (input.QueryAction(Input::UP)) { if (selected > 0) selected--; - input.ResetKey(SDLK_UP); + input.ResetAction(Input::UP); } - else if (input.GetKeyState(SDLK_DOWN)) { + else if (input.QueryAction(Input::DOWN)) { if (selected + 1 < items.size()) selected++; - input.ResetKey(SDLK_DOWN); + input.ResetAction(Input::DOWN); } - else if (input.GetKeyState(SDLK_LEFT)) { + else if (input.QueryAction(Input::LEFT)) { Item &item = items[selected]; if (item.active == 0) item.active = item.values.size() - 1; else item.active = (item.active - 1) % item.values.size(); - input.ResetKey(SDLK_LEFT); + input.ResetAction(Input::LEFT); } - else if (input.GetKeyState(SDLK_RIGHT)) { + else if (input.QueryAction(Input::RIGHT)) { Item &item = items[selected]; item.active = (item.active + 1) % item.values.size(); - input.ResetKey(SDLK_RIGHT); + input.ResetAction(Input::RIGHT); } } -- 2.39.2