InputBag in a working state and getting used.

This commit is contained in:
King_DuckZ 2014-02-24 21:16:00 +01:00
parent d9ccbede66
commit 597607366e
7 changed files with 112 additions and 9 deletions

View file

@ -1,18 +1,30 @@
#include "gamebase.hpp" #include "gamebase.hpp"
#include "texture.hpp" #include "texture.hpp"
#include "sdlmain.hpp" #include "sdlmain.hpp"
#include "inputbag.hpp"
#include "key.hpp"
#include <sstream> #include <sstream>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <ciso646> #include <ciso646>
#include <cassert>
namespace cloonel { namespace cloonel {
namespace { namespace {
///--------------------------------------------------------------------- ///---------------------------------------------------------------------
///--------------------------------------------------------------------- ///---------------------------------------------------------------------
bool DoEvents() { bool DoEvents (InputBag& parInput) {
SDL_Event eve; SDL_Event eve;
while (SDL_PollEvent(&eve)) { while (SDL_PollEvent(&eve)) {
switch (eve.type) { switch (eve.type) {
case SDL_KEYDOWN:
//eve.key.keysym.sym
parInput.NotifyKeyAction(InputDevice_Keyboard, eve.key.keysym.scancode, true);
break;
case SDL_KEYUP:
parInput.NotifyKeyAction(InputDevice_Keyboard, eve.key.keysym.scancode, false);
break;
case SDL_QUIT: case SDL_QUIT:
return true; return true;
} }
@ -24,6 +36,7 @@ namespace cloonel {
///------------------------------------------------------------------------ ///------------------------------------------------------------------------
///------------------------------------------------------------------------ ///------------------------------------------------------------------------
GameBase::GameBase (SDLMain* parSdlMain) : GameBase::GameBase (SDLMain* parSdlMain) :
m_input(new InputBag()),
m_sdlmain(parSdlMain), m_sdlmain(parSdlMain),
m_time0(SDL_GetTicks()), m_time0(SDL_GetTicks()),
m_wantsToQuit(false) m_wantsToQuit(false)
@ -49,7 +62,8 @@ namespace cloonel {
OnRender(); OnRender();
SDL_RenderPresent(ren); SDL_RenderPresent(ren);
m_wantsToQuit = DoEvents(); m_wantsToQuit = DoEvents(*m_input);
m_input->KeyStateUpdateFinished();
return delta; return delta;
} }

View file

@ -6,6 +6,7 @@
namespace cloonel { namespace cloonel {
class SDLMain; class SDLMain;
class Texture; class Texture;
class InputBag;
class GameBase { class GameBase {
public: public:
@ -20,12 +21,14 @@ namespace cloonel {
virtual void Destroy ( void ) noexcept = 0; virtual void Destroy ( void ) noexcept = 0;
SDLMain* SDLObject ( void ) { return m_sdlmain; } SDLMain* SDLObject ( void ) { return m_sdlmain; }
InputBag* InputBagObject ( void ) { return m_input.get(); }
private: private:
virtual void OnRender ( void ) = 0; virtual void OnRender ( void ) = 0;
virtual void OnUpdate ( float parDelta ) = 0; virtual void OnUpdate ( float parDelta ) = 0;
virtual bool ShouldQuit ( void ) const; virtual bool ShouldQuit ( void ) const;
const std::unique_ptr<InputBag> m_input;
SDLMain* const m_sdlmain; SDLMain* const m_sdlmain;
unsigned int m_time0; unsigned int m_time0;
bool m_wantsToQuit; bool m_wantsToQuit;

View file

@ -2,9 +2,19 @@
#include "character.hpp" #include "character.hpp"
#include "moversine.hpp" #include "moversine.hpp"
#include "sdlmain.hpp" #include "sdlmain.hpp"
#include "inputbag.hpp"
#include "key.hpp"
#include <algorithm> #include <algorithm>
#include <SDL2/SDL_scancode.h>
namespace cloonel { namespace cloonel {
namespace {
enum GameActionType {
GameAction_Left,
GameAction_Right
};
} //unnamed namespace
struct GameplaySceneClassic::LocalData { struct GameplaySceneClassic::LocalData {
}; };
@ -14,6 +24,10 @@ namespace cloonel {
GameplayScene(parSdlMain), GameplayScene(parSdlMain),
m_local(new LocalData) m_local(new LocalData)
{ {
//TODO: replace the hardcoded bindings with something more customizable.
InputBag& input = *InputBagObject();
input.AddAction(GameAction_Left, Key(InputDevice_Keyboard, SDL_SCANCODE_LEFT), "Move left");
input.AddAction(GameAction_Left, Key(InputDevice_Keyboard, SDL_SCANCODE_RIGHT), "Move right");
} }
///-------------------------------------------------------------------------- ///--------------------------------------------------------------------------

View file

@ -3,12 +3,17 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <cassert> #include <cassert>
#include <algorithm>
#include <ciso646>
namespace cloonel { namespace cloonel {
struct Action { struct Action {
Key key; Key key;
const std::string name; const std::string name;
InputBag::ActionStateType state; InputBag::ActionStateType state;
bool newStatePressed;
bool operator== ( const Key& parKey ) const { return key == parKey; }
}; };
struct InputBag::LocalData { struct InputBag::LocalData {
@ -17,6 +22,23 @@ namespace cloonel {
}; };
namespace { namespace {
// | rl | pr
// -----------------
// rel | rel | jpr
// prs | jrl | prs
// jrl | rel | jpr
// jpr | jrl | prs
const InputBag::ActionStateType g_stateTruthTable[] = {
InputBag::ActionState_Released,
InputBag::ActionState_JustReleased,
InputBag::ActionState_Released,
InputBag::ActionState_JustReleased,
InputBag::ActionState_JustPressed,
InputBag::ActionState_Pressed,
InputBag::ActionState_JustPressed,
InputBag::ActionState_Pressed
};
///---------------------------------------------------------------------- ///----------------------------------------------------------------------
///When actions vector is reallocated, update pointers in mappings. ///When actions vector is reallocated, update pointers in mappings.
///---------------------------------------------------------------------- ///----------------------------------------------------------------------
@ -45,7 +67,7 @@ namespace cloonel {
///-------------------------------------------------------------------------- ///--------------------------------------------------------------------------
void InputBag::AddAction (int parAction, const Key& parKey, std::string&& parName) { void InputBag::AddAction (int parAction, const Key& parKey, std::string&& parName) {
Action* const oldBuff = m_localdata->actions.data(); Action* const oldBuff = m_localdata->actions.data();
m_localdata->actions.push_back(Action({parKey, parName, ActionState_Released})); m_localdata->actions.push_back(Action({parKey, parName, ActionState_Released, false}));
Action* const newBuff = m_localdata->actions.data(); Action* const newBuff = m_localdata->actions.data();
if (oldBuff != newBuff) { if (oldBuff != newBuff) {
UpdatePointers(oldBuff, newBuff, m_localdata->mappings, 0); UpdatePointers(oldBuff, newBuff, m_localdata->mappings, 0);
@ -66,4 +88,37 @@ namespace cloonel {
m_localdata->actions.clear(); m_localdata->actions.clear();
m_localdata->mappings.clear(); m_localdata->mappings.clear();
} }
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
void InputBag::NotifyKeyAction (InputDeviceType parDev, int parScancode, bool parPressed) {
const Key searchKey(parDev, parScancode);
auto itFound = std::find(m_localdata->actions.begin(), m_localdata->actions.end(), searchKey);
//This method gets called every time a keypress or keyrelease is
//produced, but if the key is of any use is decided here. So it possible
//that a keystroke is not bound to any action and therefore no
//corresponding element is present in the actions list.
if (m_localdata->actions.end() != itFound)
itFound->newStatePressed = parPressed;
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
void InputBag::KeyStateUpdateFinished() noexcept {
for (auto& currAction : m_localdata->actions) {
const int numericState = static_cast<int>(currAction.state);
assert(numericState < 4);
const int index = (currAction.newStatePressed ? 4 : 0) + numericState;
currAction.state = g_stateTruthTable[index];
}
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
void InputBag::ClearState() {
for (auto& currAction : m_localdata->actions) {
currAction.newStatePressed = false;
currAction.state = ActionState_Released;
}
}
} //namespace cloonel } //namespace cloonel

View file

@ -1,6 +1,7 @@
#ifndef idF4E67FC292A5480DA4305B806170F520 #ifndef idF4E67FC292A5480DA4305B806170F520
#define idF4E67FC292A5480DA4305B806170F520 #define idF4E67FC292A5480DA4305B806170F520
#include "inputdevicetype.hpp"
#include <memory> #include <memory>
namespace cloonel { namespace cloonel {
@ -21,6 +22,9 @@ namespace cloonel {
void AddAction ( int parAction, const Key& parKey, std::string&& parName ); void AddAction ( int parAction, const Key& parKey, std::string&& parName );
ActionStateType ActionState ( int parAction ) const; ActionStateType ActionState ( int parAction ) const;
void Clear ( void ); void Clear ( void );
void NotifyKeyAction ( InputDeviceType parDev, int parScancode, bool parPressed );
void KeyStateUpdateFinished ( void ) noexcept;
void ClearState ( void );
private: private:
struct LocalData; struct LocalData;

10
src/inputdevicetype.hpp Normal file
View file

@ -0,0 +1,10 @@
#ifndef idED0C5C9767B64910A2998ACDAE14A509
#define idED0C5C9767B64910A2998ACDAE14A509
namespace cloonel {
enum InputDeviceType {
InputDevice_Keyboard
};
} //namespace cloonel
#endif

View file

@ -1,16 +1,13 @@
#ifndef id8F6145D6CFBA40338C5804DEC032CE16 #ifndef id8F6145D6CFBA40338C5804DEC032CE16
#define id8F6145D6CFBA40338C5804DEC032CE16 #define id8F6145D6CFBA40338C5804DEC032CE16
#include "inputdevicetype.hpp"
#include <ciso646> #include <ciso646>
namespace cloonel { namespace cloonel {
struct Key { struct Key {
enum KeyDevice {
KeyDevice_Keyboard
};
Key ( void ) = default; Key ( void ) = default;
Key ( KeyDevice parDev, int parScancode, const char parLabel[4] ) : Key ( InputDeviceType parDev, int parScancode, const char parLabel[4] ) :
srcdevice(parDev), srcdevice(parDev),
scancode(parScancode) scancode(parScancode)
{ {
@ -19,6 +16,12 @@ namespace cloonel {
label[2] = parLabel[2]; label[2] = parLabel[2];
label[3] = parLabel[3]; label[3] = parLabel[3];
} }
Key ( InputDeviceType parDev, int parScancode ) :
srcdevice(parDev),
scancode(parScancode),
label {0, 0, 0, 0}
{
}
~Key ( void ) noexcept = default; ~Key ( void ) noexcept = default;
bool operator== ( const Key& parOther ) const { bool operator== ( const Key& parOther ) const {
@ -31,7 +34,7 @@ namespace cloonel {
return (srcdevice == parOther.srcdevice and scancode < parOther.scancode) or (srcdevice < parOther.srcdevice); return (srcdevice == parOther.srcdevice and scancode < parOther.scancode) or (srcdevice < parOther.srcdevice);
} }
KeyDevice srcdevice; InputDeviceType srcdevice;
int scancode; int scancode;
char label[4]; char label[4];
}; };