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 "texture.hpp"
#include "sdlmain.hpp"
#include "inputbag.hpp"
#include "key.hpp"
#include <sstream>
#include <SDL2/SDL.h>
#include <ciso646>
#include <cassert>
namespace cloonel {
namespace {
///---------------------------------------------------------------------
///---------------------------------------------------------------------
bool DoEvents() {
bool DoEvents (InputBag& parInput) {
SDL_Event eve;
while (SDL_PollEvent(&eve)) {
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:
return true;
}
@ -24,6 +36,7 @@ namespace cloonel {
///------------------------------------------------------------------------
///------------------------------------------------------------------------
GameBase::GameBase (SDLMain* parSdlMain) :
m_input(new InputBag()),
m_sdlmain(parSdlMain),
m_time0(SDL_GetTicks()),
m_wantsToQuit(false)
@ -49,7 +62,8 @@ namespace cloonel {
OnRender();
SDL_RenderPresent(ren);
m_wantsToQuit = DoEvents();
m_wantsToQuit = DoEvents(*m_input);
m_input->KeyStateUpdateFinished();
return delta;
}

View file

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

View file

@ -2,9 +2,19 @@
#include "character.hpp"
#include "moversine.hpp"
#include "sdlmain.hpp"
#include "inputbag.hpp"
#include "key.hpp"
#include <algorithm>
#include <SDL2/SDL_scancode.h>
namespace cloonel {
namespace {
enum GameActionType {
GameAction_Left,
GameAction_Right
};
} //unnamed namespace
struct GameplaySceneClassic::LocalData {
};
@ -14,6 +24,10 @@ namespace cloonel {
GameplayScene(parSdlMain),
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 <map>
#include <cassert>
#include <algorithm>
#include <ciso646>
namespace cloonel {
struct Action {
Key key;
const std::string name;
InputBag::ActionStateType state;
bool newStatePressed;
bool operator== ( const Key& parKey ) const { return key == parKey; }
};
struct InputBag::LocalData {
@ -17,6 +22,23 @@ namespace cloonel {
};
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.
///----------------------------------------------------------------------
@ -45,7 +67,7 @@ namespace cloonel {
///--------------------------------------------------------------------------
void InputBag::AddAction (int parAction, const Key& parKey, std::string&& parName) {
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();
if (oldBuff != newBuff) {
UpdatePointers(oldBuff, newBuff, m_localdata->mappings, 0);
@ -66,4 +88,37 @@ namespace cloonel {
m_localdata->actions.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

View file

@ -1,6 +1,7 @@
#ifndef idF4E67FC292A5480DA4305B806170F520
#define idF4E67FC292A5480DA4305B806170F520
#include "inputdevicetype.hpp"
#include <memory>
namespace cloonel {
@ -21,6 +22,9 @@ namespace cloonel {
void AddAction ( int parAction, const Key& parKey, std::string&& parName );
ActionStateType ActionState ( int parAction ) const;
void Clear ( void );
void NotifyKeyAction ( InputDeviceType parDev, int parScancode, bool parPressed );
void KeyStateUpdateFinished ( void ) noexcept;
void ClearState ( void );
private:
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
#define id8F6145D6CFBA40338C5804DEC032CE16
#include "inputdevicetype.hpp"
#include <ciso646>
namespace cloonel {
struct Key {
enum KeyDevice {
KeyDevice_Keyboard
};
Key ( void ) = default;
Key ( KeyDevice parDev, int parScancode, const char parLabel[4] ) :
Key ( InputDeviceType parDev, int parScancode, const char parLabel[4] ) :
srcdevice(parDev),
scancode(parScancode)
{
@ -19,6 +16,12 @@ namespace cloonel {
label[2] = parLabel[2];
label[3] = parLabel[3];
}
Key ( InputDeviceType parDev, int parScancode ) :
srcdevice(parDev),
scancode(parScancode),
label {0, 0, 0, 0}
{
}
~Key ( void ) noexcept = default;
bool operator== ( const Key& parOther ) const {
@ -31,7 +34,7 @@ namespace cloonel {
return (srcdevice == parOther.srcdevice and scancode < parOther.scancode) or (srcdevice < parOther.srcdevice);
}
KeyDevice srcdevice;
InputDeviceType srcdevice;
int scancode;
char label[4];
};