InputBag in a working state and getting used.
This commit is contained in:
parent
d9ccbede66
commit
597607366e
7 changed files with 112 additions and 9 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
10
src/inputdevicetype.hpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef idED0C5C9767B64910A2998ACDAE14A509
|
||||||
|
#define idED0C5C9767B64910A2998ACDAE14A509
|
||||||
|
|
||||||
|
namespace cloonel {
|
||||||
|
enum InputDeviceType {
|
||||||
|
InputDevice_Keyboard
|
||||||
|
};
|
||||||
|
} //namespace cloonel
|
||||||
|
|
||||||
|
#endif
|
15
src/key.hpp
15
src/key.hpp
|
@ -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];
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue