Show window and allow user to close it to quit.
This commit is contained in:
parent
6afa1a4cd4
commit
92a1069324
10 changed files with 375 additions and 11 deletions
|
@ -55,6 +55,7 @@ add_executable(${PROJECT_NAME}
|
|||
src/sizenotifiable.cpp
|
||||
src/sizeratio.cpp
|
||||
src/gamescenebase.cpp
|
||||
src/inputbag.cpp
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} SYSTEM
|
||||
|
|
|
@ -1,11 +1,55 @@
|
|||
#include "gamescenebase.hpp"
|
||||
#include "inputbag.hpp"
|
||||
#include "sdlmain.hpp"
|
||||
#include <cassert>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
namespace curry {
|
||||
GameSceneBase::GameSceneBase() :
|
||||
namespace {
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
bool DoEvents (cloonel::InputBag& parInput, cloonel::SDLMain* parSdlMain) {
|
||||
using cloonel::InputDevice_Keyboard;
|
||||
|
||||
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;
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
if (SDL_WINDOWEVENT_RESIZED == eve.window.event) {
|
||||
parSdlMain->SetResolution(vec2us(static_cast<uint16_t>(eve.window.data1), static_cast<uint16_t>(eve.window.data2)));
|
||||
}
|
||||
else if (SDL_WINDOWEVENT_CLOSE == eve.window.event) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} //unnamed namespace
|
||||
|
||||
GameSceneBase::GameSceneBase (cloonel::SDLMain* parSdlMain) :
|
||||
m_input(std::make_unique<cloonel::InputBag>()),
|
||||
m_sdlmain(parSdlMain),
|
||||
m_wants_to_quit(false)
|
||||
{
|
||||
assert(m_sdlmain);
|
||||
}
|
||||
|
||||
GameSceneBase::~GameSceneBase() noexcept = default;
|
||||
|
||||
void GameSceneBase::prepare() {
|
||||
m_wants_to_quit = false;
|
||||
this->on_prepare();
|
||||
|
@ -23,4 +67,15 @@ namespace curry {
|
|||
void GameSceneBase::set_wants_to_quit() {
|
||||
m_wants_to_quit = true;
|
||||
}
|
||||
|
||||
void GameSceneBase::exec() {
|
||||
if (DoEvents(*m_input, m_sdlmain))
|
||||
set_wants_to_quit();
|
||||
|
||||
this->on_update();
|
||||
}
|
||||
|
||||
cloonel::SDLMain* GameSceneBase::sdl_main() {
|
||||
return m_sdlmain;
|
||||
}
|
||||
} //namespace curry
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace cloonel {
|
||||
class InputBag;
|
||||
class SDLMain;
|
||||
} //namespace cloonel
|
||||
|
||||
namespace curry {
|
||||
class GameSceneBase {
|
||||
public:
|
||||
GameSceneBase();
|
||||
virtual ~GameSceneBase() noexcept = default;
|
||||
explicit GameSceneBase (cloonel::SDLMain* parSdlMain);
|
||||
virtual ~GameSceneBase() noexcept;
|
||||
|
||||
void prepare();
|
||||
void destroy() noexcept;
|
||||
|
||||
virtual void exec() = 0;
|
||||
void exec();
|
||||
|
||||
bool wants_to_quit() const;
|
||||
void set_wants_to_quit();
|
||||
|
@ -17,8 +24,12 @@ namespace curry {
|
|||
protected:
|
||||
virtual void on_prepare() = 0;
|
||||
virtual void on_destroy() noexcept = 0;
|
||||
virtual void on_update() = 0;
|
||||
cloonel::SDLMain* sdl_main();
|
||||
|
||||
private:
|
||||
std::unique_ptr<cloonel::InputBag> m_input;
|
||||
cloonel::SDLMain* m_sdlmain;
|
||||
bool m_wants_to_quit;
|
||||
};
|
||||
} //namespace curry
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
namespace curry {
|
||||
IngameScene::IngameScene (cloonel::SDLMain* parSDLMain) :
|
||||
m_sdlmain(parSDLMain)
|
||||
GameSceneBase(parSDLMain)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ namespace curry {
|
|||
std::cout << "game prepare\n";
|
||||
}
|
||||
|
||||
void IngameScene::exec() {
|
||||
void IngameScene::on_update() {
|
||||
std::cout << "game exec\n";
|
||||
}
|
||||
|
||||
|
|
|
@ -12,13 +12,9 @@ namespace curry {
|
|||
explicit IngameScene (cloonel::SDLMain* parSDLMain);
|
||||
virtual ~IngameScene() noexcept;
|
||||
|
||||
virtual void exec() override;
|
||||
|
||||
protected:
|
||||
virtual void on_prepare() override;
|
||||
virtual void on_destroy() noexcept override;
|
||||
|
||||
private:
|
||||
cloonel::SDLMain* m_sdlmain;
|
||||
virtual void on_update() override;
|
||||
};
|
||||
} //namespace curry
|
||||
|
|
150
src/inputbag.cpp
Normal file
150
src/inputbag.cpp
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
Copyright 2014 Michele "King_DuckZ" Santullo
|
||||
|
||||
This file is part of CloonelJump.
|
||||
|
||||
CloonelJump is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CloonelJump is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "inputbag.hpp"
|
||||
#include "key.hpp"
|
||||
#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 {
|
||||
std::vector<Action> actions;
|
||||
std::map<int, Action*> mappings;
|
||||
};
|
||||
|
||||
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.
|
||||
///----------------------------------------------------------------------
|
||||
void UpdatePointers (Action* parOldAddrStart, Action* parNewAddress, std::map<int, Action*>& parUpdate, int parOffset) {
|
||||
for (auto& itMap : parUpdate) {
|
||||
if (itMap.second >= parOldAddrStart) {
|
||||
itMap.second = parNewAddress + (itMap.second - parOldAddrStart) + parOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
} //unnamed namespace
|
||||
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
InputBag::InputBag() :
|
||||
m_localdata(new LocalData)
|
||||
{
|
||||
}
|
||||
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
InputBag::~InputBag() noexcept {
|
||||
}
|
||||
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
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, false}));
|
||||
Action* const newBuff = m_localdata->actions.data();
|
||||
if (oldBuff != newBuff) {
|
||||
UpdatePointers(oldBuff, newBuff, m_localdata->mappings, 0);
|
||||
}
|
||||
m_localdata->mappings[parAction] = &m_localdata->actions.back();
|
||||
}
|
||||
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
InputBag::ActionStateType InputBag::ActionState (int parAction) const {
|
||||
assert(m_localdata->mappings.find(parAction) != m_localdata->mappings.end());
|
||||
return m_localdata->mappings[parAction]->state;
|
||||
}
|
||||
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
void InputBag::Clear() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
bool IsPressed (const InputBag& parInput, int parAction) {
|
||||
const InputBag::ActionStateType state = parInput.ActionState(parAction);
|
||||
return InputBag::ActionState_Pressed == state or InputBag::ActionState_JustPressed == state;
|
||||
}
|
||||
} //namespace cloonel
|
59
src/inputbag.hpp
Normal file
59
src/inputbag.hpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
Copyright 2014 Michele "King_DuckZ" Santullo
|
||||
|
||||
This file is part of CloonelJump.
|
||||
|
||||
CloonelJump is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CloonelJump is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef idF4E67FC292A5480DA4305B806170F520
|
||||
#define idF4E67FC292A5480DA4305B806170F520
|
||||
|
||||
#include "inputdevicetype.hpp"
|
||||
#include <memory>
|
||||
#include <ciso646>
|
||||
|
||||
namespace cloonel {
|
||||
struct Key;
|
||||
|
||||
class InputBag {
|
||||
public:
|
||||
enum ActionStateType {
|
||||
ActionState_Released,
|
||||
ActionState_Pressed,
|
||||
ActionState_JustReleased,
|
||||
ActionState_JustPressed
|
||||
};
|
||||
|
||||
InputBag ( void );
|
||||
~InputBag ( void ) noexcept;
|
||||
|
||||
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;
|
||||
|
||||
const std::unique_ptr<LocalData> m_localdata;
|
||||
};
|
||||
|
||||
bool IsPressed ( const InputBag& parInput, int parAction );
|
||||
inline bool IsReleased ( const InputBag& parInput, int parAction ) { return not IsPressed(parInput, parAction); }
|
||||
} //namespace cloonel
|
||||
|
||||
#endif
|
29
src/inputdevicetype.hpp
Normal file
29
src/inputdevicetype.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Copyright 2014 Michele "King_DuckZ" Santullo
|
||||
|
||||
This file is part of CloonelJump.
|
||||
|
||||
CloonelJump is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CloonelJump is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef idED0C5C9767B64910A2998ACDAE14A509
|
||||
#define idED0C5C9767B64910A2998ACDAE14A509
|
||||
|
||||
namespace cloonel {
|
||||
enum InputDeviceType {
|
||||
InputDevice_Keyboard
|
||||
};
|
||||
} //namespace cloonel
|
||||
|
||||
#endif
|
62
src/key.hpp
Normal file
62
src/key.hpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Copyright 2014 Michele "King_DuckZ" Santullo
|
||||
|
||||
This file is part of CloonelJump.
|
||||
|
||||
CloonelJump is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
CloonelJump is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef id8F6145D6CFBA40338C5804DEC032CE16
|
||||
#define id8F6145D6CFBA40338C5804DEC032CE16
|
||||
|
||||
#include "inputdevicetype.hpp"
|
||||
#include <ciso646>
|
||||
|
||||
namespace cloonel {
|
||||
struct Key {
|
||||
Key ( void ) = default;
|
||||
Key ( InputDeviceType parDev, int parScancode, const char parLabel[4] ) :
|
||||
srcdevice(parDev),
|
||||
scancode(parScancode)
|
||||
{
|
||||
label[0] = parLabel[0];
|
||||
label[1] = parLabel[1];
|
||||
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 {
|
||||
return srcdevice == parOther.srcdevice and scancode == parOther.scancode;
|
||||
}
|
||||
bool operator!= ( const Key& parOther ) const {
|
||||
return not this->operator==(parOther);
|
||||
}
|
||||
bool operator< ( const Key& parOther ) const {
|
||||
return (srcdevice == parOther.srcdevice and scancode < parOther.scancode) or (srcdevice < parOther.srcdevice);
|
||||
}
|
||||
|
||||
InputDeviceType srcdevice;
|
||||
int scancode;
|
||||
char label[4];
|
||||
};
|
||||
} //namespace cloonel
|
||||
|
||||
#endif
|
|
@ -36,6 +36,7 @@ namespace vwr {
|
|||
|
||||
namespace curry {
|
||||
using vec2f = vwr::Vec<std::array<float, 2>>;
|
||||
using vec2us = vwr::Vec<std::array<uint16_t, 2>>;
|
||||
} //namespace curry
|
||||
|
||||
//make stuff from CloonelJump compile happily
|
||||
|
|
Loading…
Add table
Reference in a new issue