Input类单例模式重做

This commit is contained in:
Nomango 2018-07-04 15:33:09 +08:00
parent 17d73916ba
commit 2eaa3814c5
6 changed files with 152 additions and 156 deletions

View File

@ -11,10 +11,12 @@ e2d::Game::Game()
, _paused(false)
, _initialized(false)
{
CoInitialize(nullptr);
}
e2d::Game::~Game()
{
CoUninitialize();
}
e2d::Game * e2d::Game::getInstance()
@ -33,41 +35,6 @@ void e2d::Game::destroyInstance()
}
}
bool e2d::Game::init()
{
if (_initialized)
{
WARN("The game has been initialized!");
return false;
}
// 初始化 COM 组件
CoInitialize(nullptr);
bool bInputInit = false;
auto DestroyResources = [&]()
{
if (bInputInit) Input::__uninit();
};
// 初始化 DirectInput
if (Input::__init())
{
bInputInit = true;
}
else
{
DestroyResources();
throw SystemException(L"初始化 DirectInput 组件失败");
}
// 初始化成功
_initialized = true;
return _initialized;
}
void e2d::Game::start(bool cleanup)
{
if (!_initialized)
@ -75,8 +42,11 @@ void e2d::Game::start(bool cleanup)
throw Exception(L"开始游戏前未进行初始化");
}
auto gc = GC::getInstance();
auto input = Input::getInstance();
auto window = Window::getInstance();
auto renderer = Renderer::getInstance();
// 初始化场景管理器
SceneManager::__init();
@ -101,7 +71,7 @@ void e2d::Game::start(bool cleanup)
// 判断是否达到了刷新状态
if (Time::__isReady())
{
Input::__update(); // 获取用户输入
input->__update(); // 获取用户输入
Timer::__update(); // 更新定时器
ActionManager::__update(); // 更新动作管理器
SceneManager::__update(); // 更新场景内容
@ -111,8 +81,8 @@ void e2d::Game::start(bool cleanup)
}
else
{
Time::__sleep(); // 挂起线程
GC::getInstance()->__update(); // 刷新内存池
Time::__sleep(); // 挂起线程
gc->__update(); // 刷新内存池
}
}
@ -160,9 +130,6 @@ void e2d::Game::quit()
void e2d::Game::cleanup()
{
if (!_initialized)
return;
// 删除所有场景
SceneManager::__uninit();
// 删除输入监听器
@ -175,12 +142,6 @@ void e2d::Game::cleanup()
Image::clearCache();
// 清空定时器
Timer::__uninit();
// 关闭输入
Input::__uninit();
// 删除所有对象
GC::getInstance()->clear();
CoUninitialize();
_initialized = false;
}

View File

@ -1,39 +1,37 @@
#include "..\e2dbase.h"
#include "..\e2dtool.h"
#include "..\e2dmanager.h"
#pragma comment(lib, "dinput8.lib")
using namespace e2d;
#define BUFFER_SIZE 256
static IDirectInput8* s_pDirectInput = nullptr; // DirectInput 接口对象
static IDirectInputDevice8* s_KeyboardDevice = nullptr; // 键盘设备接口
static char s_KeyBuffer[BUFFER_SIZE] = { 0 }; // 用于保存键盘按键信息缓冲区
static char s_KeyRecordBuffer[BUFFER_SIZE] = { 0 }; // 键盘消息二级缓冲区
static IDirectInputDevice8* s_MouseDevice = nullptr; // 鼠标设备接口
static DIMOUSESTATE s_MouseState; // 鼠标信息存储结构体
static DIMOUSESTATE s_MouseRecordState; // 鼠标信息二级缓冲
static POINT s_MousePosition; // 鼠标位置存储结构体
static std::vector<e2d::Listener*> s_vListeners; // 监听器容器
e2d::Input * e2d::Input::_instance = nullptr;
bool Input::__init()
e2d::Input::Input()
: _directInput(false)
, _keyboardDevice(false)
, _mouseDevice(false)
, _mouseState()
, _mouseStateRecord()
, _mousePos()
{
CoInitialize(nullptr);
ZeroMemory(s_KeyBuffer, sizeof(s_KeyBuffer));
ZeroMemory(s_KeyRecordBuffer, sizeof(s_KeyRecordBuffer));
ZeroMemory(&s_MouseState, sizeof(s_MouseState));
ZeroMemory(&s_MouseRecordState, sizeof(s_MouseRecordState));
ZeroMemory(&_mouseState, sizeof(_mouseState));
ZeroMemory(&_mouseStateRecord, sizeof(_mouseStateRecord));
// 初始化接口对象
HRESULT hr = DirectInput8Create(
HINST_THISCOMPONENT,
DIRECTINPUT_VERSION,
IID_IDirectInput8,
(void**)&s_pDirectInput,
(void**)&_directInput,
nullptr
);
@ -42,62 +40,76 @@ bool Input::__init()
if (SUCCEEDED(hr))
{
// 初始化键盘设备
hr = s_pDirectInput->CreateDevice(
hr = _directInput->CreateDevice(
GUID_SysKeyboard,
&s_KeyboardDevice,
&_keyboardDevice,
nullptr
);
if (SUCCEEDED(hr))
{
s_KeyboardDevice->SetCooperativeLevel(
_keyboardDevice->SetCooperativeLevel(
window->getHWnd(),
DISCL_FOREGROUND | DISCL_NONEXCLUSIVE
);
s_KeyboardDevice->SetDataFormat(
_keyboardDevice->SetDataFormat(
&c_dfDIKeyboard);
s_KeyboardDevice->Acquire();
s_KeyboardDevice->Poll();
_keyboardDevice->Acquire();
_keyboardDevice->Poll();
}
else
{
window->error(L"Keyboard not found!");
return false;
throw SystemException(L"Keyboard not found!");
}
}
if (SUCCEEDED(hr))
{
// 初始化鼠标设备
hr = s_pDirectInput->CreateDevice(GUID_SysMouse, &s_MouseDevice, nullptr);
hr = _directInput->CreateDevice(GUID_SysMouse, &_mouseDevice, nullptr);
if (SUCCEEDED(hr))
{
s_MouseDevice->SetCooperativeLevel(window->getHWnd(), DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
s_MouseDevice->SetDataFormat(&c_dfDIMouse);
s_MouseDevice->Acquire();
s_MouseDevice->Poll();
_mouseDevice->SetCooperativeLevel(window->getHWnd(), DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
_mouseDevice->SetDataFormat(&c_dfDIMouse);
_mouseDevice->Acquire();
_mouseDevice->Poll();
}
else
{
window->error(L"Mouse not found!");
return false;
throw SystemException(L"Mouse not found!");
}
}
return SUCCEEDED(hr);
}
void Input::__uninit()
e2d::Input::~Input()
{
if (s_KeyboardDevice)
s_KeyboardDevice->Unacquire();
if (s_MouseDevice)
s_MouseDevice->Unacquire();
if (_keyboardDevice)
_keyboardDevice->Unacquire();
if (_mouseDevice)
_mouseDevice->Unacquire();
SafeRelease(s_MouseDevice);
SafeRelease(s_KeyboardDevice);
SafeRelease(s_pDirectInput);
SafeRelease(_mouseDevice);
SafeRelease(_keyboardDevice);
SafeRelease(_directInput);
CoUninitialize();
}
e2d::Input * e2d::Input::getInstance()
{
if (!_instance)
_instance = new (std::nothrow) Input;
return _instance;
}
void e2d::Input::destroyInstance()
{
if (_instance)
{
delete _instance;
_instance = nullptr;
}
}
void e2d::Input::__update()
@ -106,54 +118,54 @@ void e2d::Input::__update()
Input::__updateListeners();
}
void Input::__updateDeviceState()
void e2d::Input::__updateDeviceState()
{
if (s_KeyboardDevice)
if (_keyboardDevice)
{
HRESULT hr = s_KeyboardDevice->Poll();
HRESULT hr = _keyboardDevice->Poll();
if (FAILED(hr))
{
hr = s_KeyboardDevice->Acquire();
hr = _keyboardDevice->Acquire();
while (hr == DIERR_INPUTLOST)
hr = s_KeyboardDevice->Acquire();
hr = _keyboardDevice->Acquire();
}
else
{
for (int i = 0; i < BUFFER_SIZE; ++i)
s_KeyRecordBuffer[i] = s_KeyBuffer[i];
s_KeyboardDevice->GetDeviceState(sizeof(s_KeyBuffer), (void**)&s_KeyBuffer);
_keyboardDevice->GetDeviceState(sizeof(s_KeyBuffer), (void**)&s_KeyBuffer);
}
}
if (s_MouseDevice)
if (_mouseDevice)
{
HRESULT hr = s_MouseDevice->Poll();
HRESULT hr = _mouseDevice->Poll();
if (FAILED(hr))
{
hr = s_MouseDevice->Acquire();
hr = _mouseDevice->Acquire();
while (hr == DIERR_INPUTLOST)
hr = s_MouseDevice->Acquire();
hr = _mouseDevice->Acquire();
}
else
{
s_MouseRecordState = s_MouseState;
s_MouseDevice->GetDeviceState(sizeof(s_MouseState), (void**)&s_MouseState);
_mouseStateRecord = _mouseState;
_mouseDevice->GetDeviceState(sizeof(_mouseState), (void**)&_mouseState);
}
}
GetCursorPos(&s_MousePosition);
ScreenToClient(Window::getInstance()->getHWnd(), &s_MousePosition);
GetCursorPos(&_mousePos);
ScreenToClient(Window::getInstance()->getHWnd(), &_mousePos);
}
bool Input::isDown(Key key)
bool e2d::Input::isDown(Key key)
{
if (s_KeyBuffer[static_cast<int>(key)] & 0x80)
return true;
return false;
}
bool Input::isPress(Key key)
bool e2d::Input::isPress(Key key)
{
if ((s_KeyBuffer[static_cast<int>(key)] & 0x80) &&
!(s_KeyRecordBuffer[static_cast<int>(key)] & 0x80))
@ -161,7 +173,7 @@ bool Input::isPress(Key key)
return false;
}
bool Input::isRelease(Key key)
bool e2d::Input::isRelease(Key key)
{
if (!(s_KeyBuffer[static_cast<int>(key)] & 0x80) &&
(s_KeyRecordBuffer[static_cast<int>(key)] & 0x80))
@ -171,55 +183,55 @@ bool Input::isRelease(Key key)
bool e2d::Input::isDown(Mouse code)
{
if (s_MouseState.rgbButtons[static_cast<int>(code)] & 0x80)
if (_mouseState.rgbButtons[static_cast<int>(code)] & 0x80)
return true;
return false;
}
bool e2d::Input::isPress(Mouse code)
{
if ((s_MouseState.rgbButtons[static_cast<int>(code)] & 0x80) &&
!(s_MouseRecordState.rgbButtons[static_cast<int>(code)] & 0x80))
if ((_mouseState.rgbButtons[static_cast<int>(code)] & 0x80) &&
!(_mouseStateRecord.rgbButtons[static_cast<int>(code)] & 0x80))
return true;
return false;
}
bool e2d::Input::isRelease(Mouse code)
{
if (!(s_MouseState.rgbButtons[static_cast<int>(code)] & 0x80) &&
(s_MouseRecordState.rgbButtons[static_cast<int>(code)] & 0x80))
if (!(_mouseState.rgbButtons[static_cast<int>(code)] & 0x80) &&
(_mouseStateRecord.rgbButtons[static_cast<int>(code)] & 0x80))
return true;
return false;
}
double Input::getMouseX()
double e2d::Input::getMouseX()
{
return (double)s_MousePosition.x;
return (double)_mousePos.x;
}
double Input::getMouseY()
double e2d::Input::getMouseY()
{
return (double)s_MousePosition.y;
return (double)_mousePos.y;
}
Point Input::getMousePos()
e2d::Point e2d::Input::getMousePos()
{
return Point((double)s_MousePosition.x, (double)s_MousePosition.y);
return Point((double)_mousePos.x, (double)_mousePos.y);
}
double Input::getMouseDeltaX()
double e2d::Input::getMouseDeltaX()
{
return (double)s_MouseState.lX;
return (double)_mouseState.lX;
}
double Input::getMouseDeltaY()
double e2d::Input::getMouseDeltaY()
{
return (double)s_MouseState.lY;
return (double)_mouseState.lY;
}
double Input::getMouseDeltaZ()
double e2d::Input::getMouseDeltaZ()
{
return (double)s_MouseState.lZ;
return (double)_mouseState.lZ;
}
e2d::Listener * e2d::Input::addListener(const Function& func, const String& name, bool paused)

View File

@ -45,6 +45,8 @@ e2d::Renderer::Renderer()
, _textRenderer(nullptr)
, _clearColor(D2D1::ColorF(D2D1::ColorF::Black))
{
CoInitialize(nullptr);
this->__createDeviceResources();
}
@ -53,6 +55,8 @@ e2d::Renderer::~Renderer()
SafeRelease(_renderTarget);
SafeRelease(_solidBrush);
SafeRelease(_textRenderer);
CoUninitialize();
}
bool e2d::Renderer::__createDeviceResources()

View File

@ -180,13 +180,16 @@ void e2d::Button::_fixedUpdate()
if (SceneManager::isTransitioning())
return;
auto input = Input::getInstance();
auto window = Window::getInstance();
if (_enable && _visiable && _normal)
{
if (Input::isRelease(Input::Mouse::Left))
if (input->isRelease(Input::Mouse::Left))
{
// 鼠标左键抬起时,判断鼠标坐标是否在按钮内部
if (_isSelected &&
_normal->containsPoint(Input::getMousePos()))
_normal->containsPoint(input->getMousePos()))
{
_runCallback();
}
@ -194,9 +197,9 @@ void e2d::Button::_fixedUpdate()
_isSelected = false;
}
if (Input::isPress(Input::Mouse::Left))
if (input->isPress(Input::Mouse::Left))
{
if (_normal->containsPoint(Input::getMousePos()))
if (_normal->containsPoint(input->getMousePos()))
{
// 鼠标左键按下,且位于按钮内时,标记 _isSelected 为 true
_isSelected = true;
@ -204,28 +207,28 @@ void e2d::Button::_fixedUpdate()
}
}
if (_isSelected && Input::isDown(Input::Mouse::Left))
if (_isSelected && input->isDown(Input::Mouse::Left))
{
if (_normal->containsPoint(Input::getMousePos()))
if (_normal->containsPoint(input->getMousePos()))
{
_setState(ButtonState::Selected);
Window::getInstance()->setCursor(Window::Cursor::Hand);
window->setCursor(Window::Cursor::Hand);
return;
}
}
else if (_normal->containsPoint(Input::getMousePos()))
else if (_normal->containsPoint(input->getMousePos()))
{
_setState(ButtonState::Mouseover);
Window::getInstance()->setCursor(Window::Cursor::Hand);
window->setCursor(Window::Cursor::Hand);
return;
}
_setState(ButtonState::Normal);
}
if (_visiable && !_enable && _normal && _normal->containsPoint(Input::getMousePos()))
if (_visiable && !_enable && _normal && _normal->containsPoint(input->getMousePos()))
{
Window::getInstance()->setCursor(Window::Cursor::No);
window->setCursor(Window::Cursor::No);
}
}

View File

@ -8,6 +8,7 @@ e2d::Player::Player()
, _xAudio2(nullptr)
, _masteringVoice(nullptr)
{
CoInitialize(nullptr);
}
e2d::Player::~Player()
@ -24,6 +25,8 @@ e2d::Player::~Player()
_masteringVoice->DestroyVoice();
SafeRelease(_xAudio2);
CoUninitialize();
}
e2d::Player * e2d::Player::getInstance()

View File

@ -20,12 +20,9 @@ public:
// 销毁实例
static void destroyInstance();
// 初始化游戏
bool init();
// 启动游戏
void start(
bool cleanup = true /* 自动清理资源 */
bool cleanup = true /* 自动清理资源 */
);
// 暂停游戏
@ -226,7 +223,7 @@ private:
class Listener;
// 输入控制
// 输入设备
class Input
{
friend class Game;
@ -300,53 +297,59 @@ public:
};
public:
// 获取输入设备实例
static Input * getInstance();
// 销毁输入设备实例
static void destroyInstance();
// 检测键盘某按键是否正被按下
static bool isDown(
bool isDown(
Key key
);
// 检测键盘某按键是否被点击
static bool isPress(
bool isPress(
Key key
);
// 检测键盘某按键是否正在松开
static bool isRelease(
bool isRelease(
Key key
);
// 检测鼠标按键是否正被按下
static bool isDown(
bool isDown(
Mouse code
);
// 检测鼠标按键是否被点击
static bool isPress(
bool isPress(
Mouse code
);
// 检测鼠标按键是否正在松开
static bool isRelease(
bool isRelease(
Mouse code
);
// 获得鼠标X轴坐标值
static double getMouseX();
double getMouseX();
// 获得鼠标Y轴坐标值
static double getMouseY();
double getMouseY();
// 获得鼠标坐标值
static Point getMousePos();
Point getMousePos();
// 获得鼠标X轴坐标增量
static double getMouseDeltaX();
double getMouseDeltaX();
// 获得鼠标Y轴坐标增量
static double getMouseDeltaY();
double getMouseDeltaY();
// 获得鼠标Z轴鼠标滚轮坐标增量
static double getMouseDeltaZ();
double getMouseDeltaZ();
// 添加输入监听
static Listener * addListener(
@ -390,23 +393,33 @@ public:
static void removeAllListeners();
private:
// 初始化 DirectInput 以及键盘鼠标设备
static bool __init();
Input();
~Input();
E2D_DISABLE_COPY(Input);
// 刷新输入信息
static void __update();
void __update();
// 刷新设备状态
static void __updateDeviceState();
void __updateDeviceState();
// 更新监听器
static void __updateListeners();
// 卸载 DirectInput
static void __uninit();
// 清空监听器
static void __clearListeners();
private:
IDirectInput8* _directInput;
IDirectInputDevice8* _keyboardDevice;
IDirectInputDevice8* _mouseDevice;
DIMOUSESTATE _mouseState;
DIMOUSESTATE _mouseStateRecord;
POINT _mousePos;
static Input * _instance;
};