Refactoring...

This commit is contained in:
Nomango 2018-08-28 00:06:10 +08:00
parent a370685dd0
commit 3a8428d54e
25 changed files with 520 additions and 453 deletions

View File

@ -73,6 +73,15 @@ void e2d::GC::clear()
} }
_pool.clear(); _pool.clear();
_cleanup = false; _cleanup = false;
// 헌뇜뻠닸
Image::clearCache();
// 헌뇜데절
Game::destroyInstance();
Renderer::destroyInstance();
Input::destroyInstance();
Window::destroyInstance();
} }
e2d::GC * e2d::GC::getInstance() e2d::GC * e2d::GC::getInstance()

View File

@ -6,12 +6,27 @@
#include <thread> #include <thread>
e2d::Game * e2d::Game::_instance = nullptr;
e2d::Game * e2d::Game::getInstance()
{
if (!_instance)
_instance = new (std::nothrow) Game;
return _instance;
}
void e2d::Game::destroyInstance()
{
if (_instance)
{
delete _instance;
_instance = nullptr;
}
}
e2d::Game::Game() e2d::Game::Game()
: _quit(true) : _quit(true)
, _paused(false) , _paused(false)
, _window(nullptr)
, _input(nullptr)
, _renderer(nullptr)
, _currScene(nullptr) , _currScene(nullptr)
, _nextScene(nullptr) , _nextScene(nullptr)
, _transition(nullptr) , _transition(nullptr)
@ -19,36 +34,18 @@ e2d::Game::Game()
{ {
CoInitialize(nullptr); CoInitialize(nullptr);
_input = new (std::nothrow) Input; _window = Window::getInstance();
_renderer = new (std::nothrow) Renderer; _input = Input::getInstance();
_renderer = Renderer::getInstance();
_timer = Timer::getInstance(); _timer = Timer::getInstance();
_actionManager = ActionManager::getInstance(); _actionManager = ActionManager::getInstance();
} }
e2d::Game::~Game() e2d::Game::~Game()
{ {
if (_renderer)
delete _renderer;
if (_input)
delete _input;
CoUninitialize(); CoUninitialize();
} }
e2d::Game * e2d::Game::getInstance()
{
static Game instance;
return &instance;
}
void e2d::Game::initWithWindow(Window * window)
{
_window = window;
_renderer->initWithWindow(_window);
_input->initWithWindow(_window);
}
void e2d::Game::start() void e2d::Game::start()
{ {
_quit = false; _quit = false;
@ -274,11 +271,11 @@ void e2d::Game::drawScene()
{ {
if (_transition) if (_transition)
{ {
_transition->_render(this); _transition->_render();
} }
else if (_currScene) else if (_currScene)
{ {
_currScene->visit(this); _currScene->visit();
} }
} }
_renderer->endDraw(); _renderer->endDraw();

View File

@ -4,6 +4,24 @@
#pragma comment(lib, "dinput8.lib") #pragma comment(lib, "dinput8.lib")
e2d::Input * e2d::Input::_instance = nullptr;
e2d::Input * e2d::Input::getInstance()
{
if (!_instance)
_instance = new (std::nothrow) Input;
return _instance;
}
void e2d::Input::destroyInstance()
{
if (_instance)
{
delete _instance;
_instance = nullptr;
}
}
e2d::Input::Input() e2d::Input::Input()
: _directInput(false) : _directInput(false)
, _keyboardDevice(false) , _keyboardDevice(false)
@ -15,32 +33,17 @@ e2d::Input::Input()
ZeroMemory(&_mouseState, sizeof(_mouseState)); ZeroMemory(&_mouseState, sizeof(_mouseState));
// 初始化接口对象 // 初始化接口对象
HRESULT hr = DirectInput8Create( ThrowIfFailed(
DirectInput8Create(
HINST_THISCOMPONENT, HINST_THISCOMPONENT,
DIRECTINPUT_VERSION, DIRECTINPUT_VERSION,
IID_IDirectInput8, IID_IDirectInput8,
(void**)&_directInput, (void**)&_directInput,
nullptr nullptr
)
); );
}
e2d::Input::~Input() HWND hwnd = Window::getInstance()->getHWnd();
{
if (_keyboardDevice)
_keyboardDevice->Unacquire();
if (_mouseDevice)
_mouseDevice->Unacquire();
SafeRelease(_mouseDevice);
SafeRelease(_keyboardDevice);
SafeRelease(_directInput);
CoUninitialize();
}
void e2d::Input::initWithWindow(Window * window)
{
HWND hwnd = window->getHWnd();
// 初始化键盘设备 // 初始化键盘设备
ThrowIfFailed( ThrowIfFailed(
@ -71,6 +74,20 @@ void e2d::Input::initWithWindow(Window * window)
_mouseDevice->Poll(); _mouseDevice->Poll();
} }
e2d::Input::~Input()
{
if (_keyboardDevice)
_keyboardDevice->Unacquire();
if (_mouseDevice)
_mouseDevice->Unacquire();
SafeRelease(_mouseDevice);
SafeRelease(_keyboardDevice);
SafeRelease(_directInput);
CoUninitialize();
}
void e2d::Input::update() void e2d::Input::update()
{ {
if (_keyboardDevice) if (_keyboardDevice)
@ -130,13 +147,12 @@ float e2d::Input::getMouseY()
e2d::Point e2d::Input::getMousePos() e2d::Point e2d::Input::getMousePos()
{ {
auto window = Game::getInstance()->getWindow(); auto window = Window::getInstance();
float dpi = window->getDpi();
POINT mousePos; POINT mousePos;
::GetCursorPos(&mousePos); ::GetCursorPos(&mousePos);
::ScreenToClient(window->getHWnd(), &mousePos); ::ScreenToClient(window->getHWnd(), &mousePos);
float dpi = window->getDpi();
return Point(mousePos.x * 96.f / dpi, mousePos.y * 96.f / dpi); return Point(mousePos.x * 96.f / dpi, mousePos.y * 96.f / dpi);
} }

View File

@ -3,6 +3,39 @@
#include "..\e2dnode.h" #include "..\e2dnode.h"
e2d::Renderer* e2d::Renderer::_instance = nullptr;
ID2D1Factory* e2d::Renderer::_factory = nullptr;
IWICImagingFactory* e2d::Renderer::_imagingFactory = nullptr;
IDWriteFactory* e2d::Renderer::_writeFactory = nullptr;
ID2D1StrokeStyle* e2d::Renderer::_miterStrokeStyle = nullptr;
ID2D1StrokeStyle* e2d::Renderer::_bevelStrokeStyle = nullptr;
ID2D1StrokeStyle* e2d::Renderer::_roundStrokeStyle = nullptr;
e2d::Renderer * e2d::Renderer::getInstance()
{
if (!_instance)
{
_instance = new (std::nothrow) Renderer;
}
return _instance;
}
void e2d::Renderer::destroyInstance()
{
if (_instance)
{
delete _instance;
_instance = nullptr;
SafeRelease(_miterStrokeStyle);
SafeRelease(_bevelStrokeStyle);
SafeRelease(_roundStrokeStyle);
SafeRelease(_factory);
SafeRelease(_imagingFactory);
SafeRelease(_writeFactory);
}
}
e2d::Renderer::Renderer() e2d::Renderer::Renderer()
: _showFps(false) : _showFps(false)
, _lastRenderTime(Time::now()) , _lastRenderTime(Time::now())
@ -12,63 +45,11 @@ e2d::Renderer::Renderer()
, _renderTarget(nullptr) , _renderTarget(nullptr)
, _solidBrush(nullptr) , _solidBrush(nullptr)
, _textRenderer(nullptr) , _textRenderer(nullptr)
, _factory(nullptr)
, _imagingFactory(nullptr)
, _writeFactory(nullptr)
, _miterStrokeStyle(nullptr)
, _bevelStrokeStyle(nullptr)
, _roundStrokeStyle(nullptr)
, _clearColor(D2D1::ColorF(D2D1::ColorF::Black)) , _clearColor(D2D1::ColorF(D2D1::ColorF::Black))
{ {
CoInitialize(nullptr); CoInitialize(nullptr);
ThrowIfFailed( HWND hWnd = Window::getInstance()->getHWnd();
D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
&_factory
)
);
ThrowIfFailed(
CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
reinterpret_cast<void**>(&_imagingFactory)
)
);
ThrowIfFailed(
DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&_writeFactory)
)
);
}
e2d::Renderer::~Renderer()
{
SafeRelease(_fpsFormat);
SafeRelease(_fpsLayout);
SafeRelease(_textRenderer);
SafeRelease(_solidBrush);
SafeRelease(_renderTarget);
SafeRelease(_miterStrokeStyle);
SafeRelease(_bevelStrokeStyle);
SafeRelease(_roundStrokeStyle);
SafeRelease(_factory);
SafeRelease(_imagingFactory);
SafeRelease(_writeFactory);
CoUninitialize();
}
void e2d::Renderer::initWithWindow(Window * window)
{
HWND hWnd = window->getHWnd();
RECT rc; RECT rc;
GetClientRect(hWnd, &rc); GetClientRect(hWnd, &rc);
@ -81,7 +62,7 @@ void e2d::Renderer::initWithWindow(Window * window)
// 创建设备相关资源。这些资源应在 Direct2D 设备消失时重建 // 创建设备相关资源。这些资源应在 Direct2D 设备消失时重建
// 创建一个 Direct2D 渲染目标 // 创建一个 Direct2D 渲染目标
ThrowIfFailed( ThrowIfFailed(
_factory->CreateHwndRenderTarget( getFactory()->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(), D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties( D2D1::HwndRenderTargetProperties(
hWnd, hWnd,
@ -103,13 +84,24 @@ void e2d::Renderer::initWithWindow(Window * window)
ThrowIfFailed( ThrowIfFailed(
TextRenderer::Create( TextRenderer::Create(
&_textRenderer, &_textRenderer,
_factory, getFactory(),
_renderTarget, _renderTarget,
_solidBrush _solidBrush
) )
); );
} }
e2d::Renderer::~Renderer()
{
SafeRelease(_fpsFormat);
SafeRelease(_fpsLayout);
SafeRelease(_textRenderer);
SafeRelease(_solidBrush);
SafeRelease(_renderTarget);
CoUninitialize();
}
void e2d::Renderer::beginDraw() void e2d::Renderer::beginDraw()
{ {
// 开始渲染 // 开始渲染
@ -134,7 +126,7 @@ void e2d::Renderer::endDraw()
if (!_fpsFormat) if (!_fpsFormat)
{ {
ThrowIfFailed( ThrowIfFailed(
_writeFactory->CreateTextFormat( getWriteFactory()->CreateTextFormat(
L"", L"",
nullptr, nullptr,
DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_WEIGHT_NORMAL,
@ -154,7 +146,7 @@ void e2d::Renderer::endDraw()
SafeRelease(_fpsLayout); SafeRelease(_fpsLayout);
ThrowIfFailed( ThrowIfFailed(
_writeFactory->CreateTextLayout( getWriteFactory()->CreateTextLayout(
(const WCHAR *)fpsText, (const WCHAR *)fpsText,
(UINT32)fpsText.length(), (UINT32)fpsText.length(),
_fpsFormat, _fpsFormat,
@ -220,12 +212,58 @@ void e2d::Renderer::showFps(bool show)
_showFps = show; _showFps = show;
} }
ID2D1Factory * e2d::Renderer::getFactory()
{
if (!_factory)
{
ThrowIfFailed(
D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
&_factory
)
);
}
return _factory;
}
IWICImagingFactory * e2d::Renderer::getImagingFactory()
{
if (!_imagingFactory)
{
ThrowIfFailed(
CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
reinterpret_cast<void**>(&_imagingFactory)
)
);
}
return _imagingFactory;
}
IDWriteFactory * e2d::Renderer::getWriteFactory()
{
if (!_writeFactory)
{
ThrowIfFailed(
DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&_writeFactory)
)
);
}
return _writeFactory;
}
ID2D1StrokeStyle * e2d::Renderer::getMiterStrokeStyle() ID2D1StrokeStyle * e2d::Renderer::getMiterStrokeStyle()
{ {
if (!_miterStrokeStyle) if (!_miterStrokeStyle)
{ {
ThrowIfFailed( ThrowIfFailed(
_factory->CreateStrokeStyle( getFactory()->CreateStrokeStyle(
D2D1::StrokeStyleProperties( D2D1::StrokeStyleProperties(
D2D1_CAP_STYLE_FLAT, D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT, D2D1_CAP_STYLE_FLAT,
@ -248,7 +286,7 @@ ID2D1StrokeStyle * e2d::Renderer::getBevelStrokeStyle()
if (!_bevelStrokeStyle) if (!_bevelStrokeStyle)
{ {
ThrowIfFailed( ThrowIfFailed(
_factory->CreateStrokeStyle( getFactory()->CreateStrokeStyle(
D2D1::StrokeStyleProperties( D2D1::StrokeStyleProperties(
D2D1_CAP_STYLE_FLAT, D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT, D2D1_CAP_STYLE_FLAT,
@ -271,7 +309,7 @@ ID2D1StrokeStyle * e2d::Renderer::getRoundStrokeStyle()
if (!_roundStrokeStyle) if (!_roundStrokeStyle)
{ {
ThrowIfFailed( ThrowIfFailed(
_factory->CreateStrokeStyle( getFactory()->CreateStrokeStyle(
D2D1::StrokeStyleProperties( D2D1::StrokeStyleProperties(
D2D1_CAP_STYLE_FLAT, D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT, D2D1_CAP_STYLE_FLAT,

View File

@ -8,83 +8,36 @@
#define REGISTER_CLASS L"Easy2DApp" #define REGISTER_CLASS L"Easy2DApp"
e2d::Window::Window(const String & title, int width, int height, int iconID) e2d::Window * e2d::Window::_instance = nullptr;
e2d::Window * e2d::Window::getInstance()
{
if (!_instance)
_instance = new (std::nothrow) Window;
return _instance;
}
void e2d::Window::destroyInstance()
{
if (_instance)
{
delete _instance;
_instance = nullptr;
}
}
e2d::Window::Window()
: _hWnd(nullptr) : _hWnd(nullptr)
, _width(width) , _width(640)
, _height(height) , _height(480)
, _title(title) , _title(L"Easy2D Game")
, _iconID(iconID) , _iconID(0)
, _dpi(0.f) , _dpi(0.f)
{ {
CoInitialize(nullptr); CoInitialize(nullptr);
// 获取系统 DPI // 获取系统 DPI
_dpi = static_cast<float>(::GetDpiForSystem()); _dpi = static_cast<float>(::GetDpiForSystem());
WNDCLASSEX wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpszClassName = REGISTER_CLASS;
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = Window::WndProc;
wcex.hIcon = nullptr;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = HINST_THISCOMPONENT;
wcex.hbrBackground = nullptr;
wcex.lpszMenuName = nullptr;
wcex.hCursor = ::LoadCursor(nullptr, IDC_ARROW);
if (_iconID != 0)
{
wcex.hIcon = (HICON)::LoadImage(
HINST_THISCOMPONENT,
MAKEINTRESOURCE(_iconID),
IMAGE_ICON,
0,
0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
);
}
// 注册窗口类
RegisterClassEx(&wcex);
// 计算窗口大小
Rect clientRect = _locate(_width, _height);
// 创建窗口
_hWnd = ::CreateWindowEx(
NULL,
REGISTER_CLASS,
(LPCTSTR)_title,
WINDOW_STYLE,
int(clientRect.origin.x),
int(clientRect.origin.y),
int(clientRect.size.width),
int(clientRect.size.height),
nullptr,
nullptr,
HINST_THISCOMPONENT,
this
);
if (_hWnd)
{
// 禁用输入法
setTypewritingEnabled(false);
// 禁用控制台关闭按钮
HWND consoleHWnd = ::GetConsoleWindow();
if (consoleHWnd)
{
HMENU hmenu = ::GetSystemMenu(consoleHWnd, FALSE);
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
}
}
else
{
::UnregisterClass(REGISTER_CLASS, HINST_THISCOMPONENT);
throw SystemException("Create window failed");
}
} }
e2d::Window::~Window() e2d::Window::~Window()
@ -192,8 +145,75 @@ e2d::String e2d::Window::getTitle() const
return _title; return _title;
} }
HWND e2d::Window::getHWnd() const HWND e2d::Window::getHWnd()
{ {
if (!_hWnd)
{
WNDCLASSEX wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpszClassName = REGISTER_CLASS;
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = Window::WndProc;
wcex.hIcon = nullptr;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = HINST_THISCOMPONENT;
wcex.hbrBackground = nullptr;
wcex.lpszMenuName = nullptr;
wcex.hCursor = ::LoadCursor(nullptr, IDC_ARROW);
if (_iconID != 0)
{
wcex.hIcon = (HICON)::LoadImage(
HINST_THISCOMPONENT,
MAKEINTRESOURCE(_iconID),
IMAGE_ICON,
0,
0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
);
}
// 注册窗口类
RegisterClassEx(&wcex);
// 计算窗口大小
Rect clientRect = _locate(_width, _height);
// 创建窗口
_hWnd = ::CreateWindowEx(
NULL,
REGISTER_CLASS,
(LPCTSTR)_title,
WINDOW_STYLE,
int(clientRect.origin.x),
int(clientRect.origin.y),
int(clientRect.size.width),
int(clientRect.size.height),
nullptr,
nullptr,
HINST_THISCOMPONENT,
this
);
if (_hWnd)
{
// 禁用输入法
setTypewritingEnabled(false);
// 禁用控制台关闭按钮
HWND consoleHWnd = ::GetConsoleWindow();
if (consoleHWnd)
{
HMENU hmenu = ::GetSystemMenu(consoleHWnd, FALSE);
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
}
}
else
{
::UnregisterClass(REGISTER_CLASS, HINST_THISCOMPONENT);
throw SystemException("Create window failed");
}
}
return _hWnd; return _hWnd;
} }
@ -318,7 +338,7 @@ void e2d::Window::setTypewritingEnabled(bool enabled)
{ {
if (hImc != nullptr) if (hImc != nullptr)
{ {
::ImmAssociateContext(_hWnd, hImc); ::ImmAssociateContext(getHWnd(), hImc);
hImc = nullptr; hImc = nullptr;
} }
} }
@ -326,7 +346,7 @@ void e2d::Window::setTypewritingEnabled(bool enabled)
{ {
if (hImc == nullptr) if (hImc == nullptr)
{ {
hImc = ::ImmAssociateContext(_hWnd, nullptr); hImc = ::ImmAssociateContext(getHWnd(), nullptr);
} }
} }
} }
@ -448,8 +468,7 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染 // 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
// 目标适当。它可能会调用失败,但是这里可以忽略有可能的 // 目标适当。它可能会调用失败,但是这里可以忽略有可能的
// 错误,因为这个错误将在下一次调用 EndDraw 时产生 // 错误,因为这个错误将在下一次调用 EndDraw 时产生
auto renderer = Game::getInstance()->getRenderer(); auto pRT = Renderer::getInstance()->getRenderTarget();
auto pRT = renderer->getRenderTarget();
if (pRT) if (pRT)
{ {
pRT->Resize(D2D1::SizeU(width, height)); pRT->Resize(D2D1::SizeU(width, height));

View File

@ -80,7 +80,7 @@ void e2d::Collider::render()
{ {
if (_geometry && _enabled && _visible) if (_geometry && _enabled && _visible)
{ {
auto renderer = Game::getInstance()->getRenderer(); auto renderer = Renderer::getInstance();
// 获取纯色画刷 // 获取纯色画刷
ID2D1SolidColorBrush * brush = renderer->getSolidColorBrush(); ID2D1SolidColorBrush * brush = renderer->getSolidColorBrush();
// 设置画刷颜色和透明度 // 设置画刷颜色和透明度
@ -131,7 +131,7 @@ void e2d::Collider::recreate()
return; return;
SafeRelease(_geometry); SafeRelease(_geometry);
auto factory = Game::getInstance()->getRenderer()->getFactory(); auto factory = Renderer::getFactory();
switch (_shape) switch (_shape)
{ {

View File

@ -157,9 +157,8 @@ bool e2d::Image::preload(const Resource& res)
return true; return true;
} }
Renderer* renderer = Game::getInstance()->getRenderer(); IWICImagingFactory *pImagingFactory = Renderer::getImagingFactory();
ID2D1HwndRenderTarget* pRenderTarget = renderer->getRenderTarget(); ID2D1HwndRenderTarget* pRenderTarget = Renderer::getInstance()->getRenderTarget();
IWICImagingFactory *pImagingFactory = renderer->getImagingFactory();
IWICBitmapDecoder *pDecoder = nullptr; IWICBitmapDecoder *pDecoder = nullptr;
IWICBitmapFrameDecode *pSource = nullptr; IWICBitmapFrameDecode *pSource = nullptr;
IWICStream *pStream = nullptr; IWICStream *pStream = nullptr;
@ -287,9 +286,8 @@ bool e2d::Image::preload(const String & fileName)
if (_bitmapCache.find(hash) != _bitmapCache.end()) if (_bitmapCache.find(hash) != _bitmapCache.end())
return true; return true;
Renderer* renderer = Game::getInstance()->getRenderer(); IWICImagingFactory *pImagingFactory = Renderer::getImagingFactory();
ID2D1HwndRenderTarget* pRenderTarget = renderer->getRenderTarget(); ID2D1HwndRenderTarget* pRenderTarget = Renderer::getInstance()->getRenderTarget();
IWICImagingFactory *pImagingFactory = renderer->getImagingFactory();
IWICBitmapDecoder *pDecoder = nullptr; IWICBitmapDecoder *pDecoder = nullptr;
IWICBitmapFrameDecode *pSource = nullptr; IWICBitmapFrameDecode *pSource = nullptr;
IWICStream *pStream = nullptr; IWICStream *pStream = nullptr;

View File

@ -332,6 +332,17 @@ e2d::String::operator wchar_t*() const
return const_cast<wchar_t*>(_str.c_str()); return const_cast<wchar_t*>(_str.c_str());
} }
e2d::String::operator std::wstring() const
{
return _str;
}
e2d::String::operator std::string() const
{
std::string str = static_cast<const char *>(_bstr_t(_str.c_str()));
return std::move(str);
}
bool e2d::String::isEmpty() const bool e2d::String::isEmpty() const
{ {
return _str.empty(); return _str.empty();
@ -348,17 +359,6 @@ size_t e2d::String::hash() const
return hash(_str); return hash(_str);
} }
std::wstring e2d::String::getWString() const
{
return _str;
}
std::string e2d::String::getCString() const
{
std::string str = static_cast<const char *>(_bstr_t(_str.c_str()));
return std::move(str);
}
wchar_t e2d::String::at(int index) const wchar_t e2d::String::at(int index) const
{ {
return _str[size_t(index)]; return _str[size_t(index)];

View File

@ -59,18 +59,16 @@ STDMETHODIMP_(void) TextRenderer::SetTextStyle(
sOutlineColor_ = outlineColor; sOutlineColor_ = outlineColor;
fOutlineWidth = 2 * outlineWidth; fOutlineWidth = 2 * outlineWidth;
auto pRenderer = Game::getInstance()->getRenderer();
switch (outlineJoin) switch (outlineJoin)
{ {
case D2D1_LINE_JOIN_MITER: case D2D1_LINE_JOIN_MITER:
pCurrStrokeStyle_ = pRenderer->getMiterStrokeStyle(); pCurrStrokeStyle_ = Renderer::getMiterStrokeStyle();
break; break;
case D2D1_LINE_JOIN_BEVEL: case D2D1_LINE_JOIN_BEVEL:
pCurrStrokeStyle_ = pRenderer->getBevelStrokeStyle(); pCurrStrokeStyle_ = Renderer::getBevelStrokeStyle();
break; break;
case D2D1_LINE_JOIN_ROUND: case D2D1_LINE_JOIN_ROUND:
pCurrStrokeStyle_ = pRenderer->getRoundStrokeStyle(); pCurrStrokeStyle_ = Renderer::getRoundStrokeStyle();
break; break;
default: default:
pCurrStrokeStyle_ = nullptr; pCurrStrokeStyle_ = nullptr;

View File

@ -32,47 +32,47 @@ void e2d::CollisionManager::__removeCollider(Collider * collider)
} }
} }
void e2d::CollisionManager::__updateCollider(Collider* collider) void e2d::CollisionManager::__updateCollider(Collider* active)
{ {
if (!_collisionEnabled || if (!_collisionEnabled ||
Game::getInstance()->isTransitioning()) Game::getInstance()->isTransitioning())
return; return;
auto currScene = Game::getInstance()->getCurrentScene();
if (active->getNode()->getParentScene() != currScene)
return;
std::vector<Collider*> currColliders; std::vector<Collider*> currColliders;
currColliders.reserve(_colliders.size()); currColliders.reserve(_colliders.size());
std::copy_if( std::copy_if(
_colliders.begin(), _colliders.begin(),
_colliders.end(), _colliders.end(),
std::back_inserter(currColliders), std::back_inserter(currColliders),
[this, collider](Collider* passive) -> bool [this, active, currScene](Collider* passive) -> bool
{ {
return collider != passive && return active != passive &&
passive->getNode()->isVisible() && passive->getNode()->isVisible() &&
collider->getNode()->getParentScene() == passive->getNode()->getParentScene() && passive->getNode()->getParentScene() == currScene &&
this->isCollidable(collider->getNode(), passive->getNode()); this->isCollidable(active->getNode(), passive->getNode());
} }
); );
for (const auto& passive : currColliders) for (const auto& passive : currColliders)
{ {
// 判断两碰撞体交集情况 // 判断两碰撞体交集情况
Collider::Relation relation = collider->getRelationWith(passive); Collider::Relation relation = active->getRelationWith(passive);
// 忽略 UNKNOWN 和 DISJOIN 情况 // 忽略 UNKNOWN 和 DISJOIN 情况
if (relation != Collider::Relation::Unknown && if (relation != Collider::Relation::Unknown &&
relation != Collider::Relation::Disjoin) relation != Collider::Relation::Disjoin)
{ {
auto activeNode = collider->getNode(); auto activeNode = active->getNode();
auto passiveNode = passive->getNode(); auto passiveNode = passive->getNode();
// 触发两次碰撞事件 // 触发两次碰撞事件
Collision activeCollision(passiveNode, relation); Collision activeCollision(passiveNode, relation);
if (dynamic_cast<CollisionHandler*>(activeNode->getParentScene()))
dynamic_cast<CollisionHandler*>(activeNode->getParentScene())->handle(activeCollision);
if (dynamic_cast<CollisionHandler*>(activeNode)) if (dynamic_cast<CollisionHandler*>(activeNode))
dynamic_cast<CollisionHandler*>(activeNode)->handle(activeCollision); dynamic_cast<CollisionHandler*>(activeNode)->handle(activeCollision);
Collision passiveCollision(activeNode, passive->getRelationWith(collider)); Collision passiveCollision(activeNode, passive->getRelationWith(active));
if (dynamic_cast<CollisionHandler*>(passiveNode->getParentScene()))
dynamic_cast<CollisionHandler*>(passiveNode->getParentScene())->handle(passiveCollision);
if (dynamic_cast<CollisionHandler*>(passiveNode)) if (dynamic_cast<CollisionHandler*>(passiveNode))
dynamic_cast<CollisionHandler*>(passiveNode)->handle(passiveCollision); dynamic_cast<CollisionHandler*>(passiveNode)->handle(passiveCollision);
} }

View File

@ -189,20 +189,20 @@ bool e2d::Button::dispatch(const MouseEvent & e, bool handled)
return Node::dispatch(e, handled); return Node::dispatch(e, handled);
} }
void e2d::Button::visit(Game * game) void e2d::Button::visit()
{ {
Node::visit(game); Node::visit();
if (_visible && if (_visible &&
!_enabled && !_enabled &&
_normal && _normal &&
_normal->containsPoint(game->getInput()->getMousePos())) _normal->containsPoint(Input::getInstance()->getMousePos()))
{ {
game->getWindow()->setCursor(Window::Cursor::No); Window::getInstance()->setCursor(Window::Cursor::No);
} }
else if (_status == Status::Mouseover || _status == Status::Selected) else if (_status == Status::Mouseover || _status == Status::Selected)
{ {
game->getWindow()->setCursor(Window::Cursor::Hand); Window::getInstance()->setCursor(Window::Cursor::Hand);
} }
} }

View File

@ -1,16 +1,14 @@
#include "..\e2dnode.h" #include "..\e2dnode.h"
e2d::Canvas::Canvas(float width, float height) e2d::Canvas::Canvas(float width, float height)
: _renderer(nullptr) : _renderTarget(nullptr)
, _renderTarget(nullptr)
, _fillBrush(nullptr) , _fillBrush(nullptr)
, _lineBrush(nullptr) , _lineBrush(nullptr)
, _strokeStyle(nullptr) , _strokeStyle(nullptr)
, _strokeWidth(1.0f) , _strokeWidth(1.0f)
, _stroke(Stroke::Miter) , _stroke(Stroke::Miter)
{ {
_renderer = Game::getInstance()->getRenderer(); _renderTarget = Renderer::getInstance()->getRenderTarget();
_renderTarget = _renderer->getRenderTarget();
_renderTarget->AddRef(); _renderTarget->AddRef();
ThrowIfFailed( ThrowIfFailed(
@ -60,13 +58,13 @@ void e2d::Canvas::setStrokeStyle(Stroke strokeStyle)
switch (strokeStyle) switch (strokeStyle)
{ {
case e2d::Stroke::Miter: case e2d::Stroke::Miter:
_strokeStyle = _renderer->getMiterStrokeStyle(); _strokeStyle = Renderer::getMiterStrokeStyle();
break; break;
case e2d::Stroke::Bevel: case e2d::Stroke::Bevel:
_strokeStyle = _renderer->getBevelStrokeStyle(); _strokeStyle = Renderer::getBevelStrokeStyle();
break; break;
case e2d::Stroke::Round: case e2d::Stroke::Round:
_strokeStyle = _renderer->getRoundStrokeStyle(); _strokeStyle = Renderer::getRoundStrokeStyle();
break; break;
} }
} }

View File

@ -79,11 +79,12 @@ e2d::Node::~Node()
} }
} }
void e2d::Node::visit(Game * game) void e2d::Node::visit()
{ {
if (!_visible) if (!_visible)
return; return;
auto game = Game::getInstance();
if (!game->isPaused()) if (!game->isPaused())
{ {
auto updatableNode = dynamic_cast<Updatable*>(this); auto updatableNode = dynamic_cast<Updatable*>(this);
@ -99,8 +100,7 @@ void e2d::Node::visit(Game * game)
_extrapolate = this->getProperty(); _extrapolate = this->getProperty();
} }
auto renderer = game->getRenderer(); auto renderTarget = Renderer::getInstance()->getRenderTarget();
auto renderTarget = renderer->getRenderTarget();
if (_clipEnabled) if (_clipEnabled)
{ {
renderTarget->SetTransform(_finalMatri); renderTarget->SetTransform(_finalMatri);
@ -116,7 +116,7 @@ void e2d::Node::visit(Game * game)
if (drawableNode) if (drawableNode)
{ {
renderTarget->SetTransform(_finalMatri); renderTarget->SetTransform(_finalMatri);
drawableNode->draw(renderer); drawableNode->draw();
} }
} }
else else
@ -131,7 +131,7 @@ void e2d::Node::visit(Game * game)
// 访问 Order 小于零的节点 // 访问 Order 小于零的节点
if (child->getOrder() < 0) if (child->getOrder() < 0)
{ {
child->visit(game); child->visit();
} }
else else
{ {
@ -143,12 +143,12 @@ void e2d::Node::visit(Game * game)
if (drawableNode) if (drawableNode)
{ {
renderTarget->SetTransform(_finalMatri); renderTarget->SetTransform(_finalMatri);
drawableNode->draw(renderer); drawableNode->draw();
} }
// 访问剩余节点 // 访问剩余节点
for (; i < _children.size(); ++i) for (; i < _children.size(); ++i)
_children[i]->visit(game); _children[i]->visit();
} }
if (_clipEnabled) if (_clipEnabled)
@ -157,10 +157,11 @@ void e2d::Node::visit(Game * game)
} }
} }
void e2d::Node::drawOutline(Renderer * renderer) void e2d::Node::drawOutline()
{ {
if (_visible) if (_visible)
{ {
auto renderer = Renderer::getInstance();
renderer->getRenderTarget()->SetTransform(_finalMatri); renderer->getRenderTarget()->SetTransform(_finalMatri);
renderer->getRenderTarget()->DrawRectangle( renderer->getRenderTarget()->DrawRectangle(
D2D1::RectF(0, 0, _width, _height), D2D1::RectF(0, 0, _width, _height),
@ -171,7 +172,7 @@ void e2d::Node::drawOutline(Renderer * renderer)
// 渲染所有子节点的轮廓 // 渲染所有子节点的轮廓
for (const auto& child : _children) for (const auto& child : _children)
{ {
child->drawOutline(renderer); child->drawOutline();
} }
} }
} }
@ -842,7 +843,7 @@ bool e2d::Node::containsPoint(const Point& point)
// 为节点创建一个轮廓 // 为节点创建一个轮廓
BOOL ret = 0; BOOL ret = 0;
ID2D1RectangleGeometry * rectGeo = nullptr; ID2D1RectangleGeometry * rectGeo = nullptr;
auto factory = Game::getInstance()->getRenderer()->getFactory(); auto factory = Renderer::getFactory();
ThrowIfFailed( ThrowIfFailed(
factory->CreateRectangleGeometry( factory->CreateRectangleGeometry(
@ -874,7 +875,7 @@ bool e2d::Node::intersects(Node * node)
D2D1_GEOMETRY_RELATION relation = D2D1_GEOMETRY_RELATION_UNKNOWN; D2D1_GEOMETRY_RELATION relation = D2D1_GEOMETRY_RELATION_UNKNOWN;
ID2D1RectangleGeometry *rectGeo = nullptr, *rectGeo2 = nullptr; ID2D1RectangleGeometry *rectGeo = nullptr, *rectGeo2 = nullptr;
ID2D1TransformedGeometry *transGeo = nullptr, *transGeo2 = nullptr; ID2D1TransformedGeometry *transGeo = nullptr, *transGeo2 = nullptr;
auto factory = Game::getInstance()->getRenderer()->getFactory(); auto factory = Renderer::getFactory();
ThrowIfFailed( ThrowIfFailed(
factory->CreateRectangleGeometry( factory->CreateRectangleGeometry(

View File

@ -6,6 +6,7 @@ e2d::Scene::Scene()
: _outlineVisible(false) : _outlineVisible(false)
, _colliderVisible(false) , _colliderVisible(false)
{ {
_parentScene = this;
} }
e2d::Scene::~Scene() e2d::Scene::~Scene()
@ -22,20 +23,21 @@ void e2d::Scene::setColliderVisible(bool visible)
_colliderVisible = visible; _colliderVisible = visible;
} }
void e2d::Scene::visit(Game * game) void e2d::Scene::visit()
{ {
Node::visit(game); Node::visit();
if (_outlineVisible) if (_outlineVisible)
{ {
auto brush = game->getRenderer()->getSolidColorBrush(); auto brush = Renderer::getInstance()->getSolidColorBrush();
brush->SetColor(D2D1::ColorF(D2D1::ColorF::Red, 0.6f)); brush->SetColor(D2D1::ColorF(D2D1::ColorF::Red, 0.6f));
brush->SetOpacity(1.f); brush->SetOpacity(1.f);
this->drawOutline(game->getRenderer()); this->drawOutline();
} }
if (_colliderVisible) if (_colliderVisible)
{ {
game->getRenderer()->getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); Renderer::getInstance()->getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
this->drawCollider(); this->drawCollider();
} }
} }

View File

@ -103,7 +103,7 @@ e2d::Image * e2d::Sprite::getImage() const
return _image; return _image;
} }
void e2d::Sprite::draw(Renderer * renderer) const void e2d::Sprite::draw() const
{ {
if (_image && _image->getBitmap()) if (_image && _image->getBitmap())
{ {
@ -111,7 +111,7 @@ void e2d::Sprite::draw(Renderer * renderer) const
float fCropX = _image->getCropX(); float fCropX = _image->getCropX();
float fCropY = _image->getCropY(); float fCropY = _image->getCropY();
// äÖȾͼƬ // äÖȾͼƬ
renderer->getRenderTarget()->DrawBitmap( Renderer::getInstance()->getRenderTarget()->DrawBitmap(
_image->getBitmap(), _image->getBitmap(),
D2D1::RectF(0, 0, _width, _height), D2D1::RectF(0, 0, _width, _height),
_displayOpacity, _displayOpacity,

View File

@ -287,24 +287,25 @@ void e2d::Text::setOutlineStroke(Stroke outlineStroke)
_style.outlineStroke = outlineStroke; _style.outlineStroke = outlineStroke;
} }
void e2d::Text::draw(Renderer * renderer) const void e2d::Text::draw() const
{ {
if (_textLayout) if (_textLayout)
{ {
auto renderer = Renderer::getInstance();
// 创建文本区域 // 创建文本区域
D2D1_RECT_F textLayoutRect = D2D1::RectF(0, 0, _width, _height); D2D1_RECT_F textLayoutRect = D2D1::RectF(0, 0, _width, _height);
// 设置画刷颜色和透明度 // 设置画刷颜色和透明度
renderer->getSolidColorBrush()->SetOpacity(_displayOpacity); renderer->getSolidColorBrush()->SetOpacity(_displayOpacity);
// 获取文本渲染器 // 获取文本渲染器
auto pTextRenderer = renderer->getTextRenderer(); auto textRenderer = renderer->getTextRenderer();
pTextRenderer->SetTextStyle( textRenderer->SetTextStyle(
(D2D1_COLOR_F)_style.color, (D2D1_COLOR_F)_style.color,
_style.hasOutline, _style.hasOutline,
(D2D1_COLOR_F)_style.outlineColor, (D2D1_COLOR_F)_style.outlineColor,
_style.outlineWidth, _style.outlineWidth,
D2D1_LINE_JOIN(_style.outlineStroke) D2D1_LINE_JOIN(_style.outlineStroke)
); );
_textLayout->Draw(nullptr, pTextRenderer, 0, 0); _textLayout->Draw(nullptr, textRenderer, 0, 0);
} }
} }
@ -320,7 +321,8 @@ void e2d::Text::_createFormat()
{ {
SafeRelease(_textFormat); SafeRelease(_textFormat);
HRESULT hr = Game::getInstance()->getRenderer()->getWriteFactory()->CreateTextFormat( ThrowIfFailed(
Renderer::getWriteFactory()->CreateTextFormat(
(const WCHAR *)_font.family, (const WCHAR *)_font.family,
nullptr, nullptr,
DWRITE_FONT_WEIGHT(_font.weight), DWRITE_FONT_WEIGHT(_font.weight),
@ -329,18 +331,12 @@ void e2d::Text::_createFormat()
_font.size, _font.size,
L"", L"",
&_textFormat &_textFormat
)
); );
if (FAILED(hr))
{
WARN("Text::_createFormat error : Create IDWriteTextFormat failed!");
_textFormat = nullptr;
return;
}
else
{
// 设置文字对齐方式 // 设置文字对齐方式
_textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(_style.alignment)); _textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(_style.alignment));
// 设置行间距 // 设置行间距
if (_style.lineSpacing == 0.f) if (_style.lineSpacing == 0.f)
{ {
@ -354,6 +350,7 @@ void e2d::Text::_createFormat()
_style.lineSpacing * 0.8f _style.lineSpacing * 0.8f
); );
} }
// 打开文本自动换行时,设置换行属性 // 打开文本自动换行时,设置换行属性
if (_style.wrapping) if (_style.wrapping)
{ {
@ -364,7 +361,6 @@ void e2d::Text::_createFormat()
_textFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); _textFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
} }
} }
}
void e2d::Text::_createLayout() void e2d::Text::_createLayout()
{ {
@ -383,52 +379,60 @@ void e2d::Text::_createLayout()
return; return;
} }
HRESULT hr;
UINT32 length = (UINT32)_text.length(); UINT32 length = (UINT32)_text.length();
auto writeFactory = Game::getInstance()->getRenderer()->getWriteFactory(); auto writeFactory = Renderer::getWriteFactory();
// 对文本自动换行情况下进行处理 // 对文本自动换行情况下进行处理
if (_style.wrapping) if (_style.wrapping)
{ {
hr = writeFactory->CreateTextLayout( ThrowIfFailed(
writeFactory->CreateTextLayout(
(const WCHAR *)_text, (const WCHAR *)_text,
length, length,
_textFormat, _textFormat,
_style.wrappingWidth, _style.wrappingWidth,
0, 0,
&_textLayout &_textLayout
)
); );
if (_textLayout)
{
// 获取文本布局的宽度和高度 // 获取文本布局的宽度和高度
DWRITE_TEXT_METRICS metrics; DWRITE_TEXT_METRICS metrics;
_textLayout->GetMetrics(&metrics); _textLayout->GetMetrics(&metrics);
// 重设文本宽高 // 重设文本宽高
this->setSize(metrics.layoutWidth, metrics.height); this->setSize(metrics.layoutWidth, metrics.height);
} }
}
else else
{ {
hr = writeFactory->CreateTextLayout((const WCHAR *)_text, length, _textFormat, 0, 0, &_textLayout); // 为防止文本对齐问题,根据先创建 layout 以获取宽度
// 为防止文本对齐问题,根据刚才创建的 layout 宽度重新创建它 ThrowIfFailed(
if (_textLayout) writeFactory->CreateTextLayout(
{ (const WCHAR *)_text,
length,
_textFormat,
0,
0,
&_textLayout
)
);
// 获取文本布局的宽度和高度 // 获取文本布局的宽度和高度
DWRITE_TEXT_METRICS metrics; DWRITE_TEXT_METRICS metrics;
_textLayout->GetMetrics(&metrics); _textLayout->GetMetrics(&metrics);
// 重设文本宽高 // 重设文本宽高
this->setSize(metrics.width, metrics.height); this->setSize(metrics.width, metrics.height);
// 重新创建 layout // 重新创建 layout
SafeRelease(_textLayout); SafeRelease(_textLayout);
hr = writeFactory->CreateTextLayout((const WCHAR *)_text, length, _textFormat, _width, 0, &_textLayout); ThrowIfFailed(
} writeFactory->CreateTextLayout(
} (const WCHAR *)_text,
length,
if (FAILED(hr)) _textFormat,
{ _width,
WARN("Text::_createLayout error : Create IDWriteTextLayout failed!"); 0,
_textLayout = nullptr; &_textLayout
return; )
);
} }
// 添加下划线和删除线 // 添加下划线和删除线

View File

@ -70,7 +70,7 @@ e2d::String e2d::File::getExtension() const
{ {
String fileExtension; String fileExtension;
// 找到文件名中的最后一个 '.' 的位置 // 找到文件名中的最后一个 '.' 的位置
size_t pos = _fileName.getWString().find_last_of(L'.'); size_t pos = std::wstring(_fileName).find_last_of(L'.');
// 判断 pos 是否是有效位置 // 判断 pos 是否是有效位置
if (pos != std::wstring::npos) if (pos != std::wstring::npos)
{ {
@ -79,7 +79,7 @@ e2d::String e2d::File::getExtension() const
// 转换为小写字母 // 转换为小写字母
fileExtension = fileExtension.toLower(); fileExtension = fileExtension.toLower();
} }
return fileExtension; return std::move(fileExtension);
} }
bool e2d::File::del() bool e2d::File::del()
@ -160,8 +160,7 @@ bool e2d::File::createFolder(const String & dirPath)
e2d::String e2d::File::getSaveFilePath(const String& title, const String& defExt) e2d::String e2d::File::getSaveFilePath(const String& title, const String& defExt)
{ {
auto window = Game::getInstance()->getWindow(); HWND hwnd = Window::getInstance()->getHWnd();
HWND hwnd = window->getHWnd();
// 弹出保存对话框 // 弹出保存对话框
OPENFILENAME ofn = { 0 }; OPENFILENAME ofn = { 0 };

View File

@ -12,7 +12,7 @@ e2d::String e2d::Path::getDataPath()
{ {
// 设置数据的保存路径 // 设置数据的保存路径
String localAppDataPath = Path::getLocalAppDataPath(); String localAppDataPath = Path::getLocalAppDataPath();
String title = Game::getInstance()->getWindow()->getTitle(); String title = Window::getInstance()->getTitle();
String folderName = String::parse(title.hash()); String folderName = String::parse(title.hash());
if (!localAppDataPath.isEmpty()) if (!localAppDataPath.isEmpty())
@ -37,7 +37,7 @@ e2d::String e2d::Path::getTempPath()
{ {
// 设置临时文件保存路径 // 设置临时文件保存路径
wchar_t path[_MAX_PATH]; wchar_t path[_MAX_PATH];
String title = Game::getInstance()->getWindow()->getTitle(); String title = Window::getInstance()->getTitle();
String folderName = String::parse(title.hash()); String folderName = String::parse(title.hash());
if (0 != ::GetTempPath(_MAX_PATH, path)) if (0 != ::GetTempPath(_MAX_PATH, path))

View File

@ -20,13 +20,14 @@ void e2d::BoxTransition::_update()
{ {
Transition::_update(); Transition::_update();
auto size = Window::getInstance()->getSize();
if (_delta <= 0.5) if (_delta <= 0.5)
{ {
_outLayerParam.contentBounds = D2D1::RectF( _outLayerParam.contentBounds = D2D1::RectF(
_windowSize.width * _delta, size.width * _delta,
_windowSize.height * _delta, size.height * _delta,
_windowSize.width * (1 - _delta), size.width * (1 - _delta),
_windowSize.height * (1 - _delta) size.height * (1 - _delta)
); );
} }
else else
@ -34,10 +35,10 @@ void e2d::BoxTransition::_update()
_outLayerParam.opacity = 0; _outLayerParam.opacity = 0;
_inLayerParam.opacity = 1; _inLayerParam.opacity = 1;
_inLayerParam.contentBounds = D2D1::RectF( _inLayerParam.contentBounds = D2D1::RectF(
_windowSize.width * (1 - _delta), size.width * (1 - _delta),
_windowSize.height * (1 - _delta), size.height * (1 - _delta),
_windowSize.width * _delta, size.width * _delta,
_windowSize.height * _delta size.height * _delta
); );
if (_delta >= 1) if (_delta >= 1)
{ {

View File

@ -11,27 +11,26 @@ bool e2d::MoveTransition::_init(Game * game, Scene * prev)
{ {
if (Transition::_init(game, prev)) if (Transition::_init(game, prev))
{ {
float width = _windowSize.width; auto size = Window::getInstance()->getSize();
float height = _windowSize.height;
if (_direction == Direction::Up) if (_direction == Direction::Up)
{ {
_posDelta = Vector2(0, -height); _posDelta = Vector2(0, -size.height);
_startPos = Point(0, height); _startPos = Point(0, size.height);
} }
else if (_direction == Direction::Down) else if (_direction == Direction::Down)
{ {
_posDelta = Vector2(0, height); _posDelta = Vector2(0, size.height);
_startPos = Point(0, -height); _startPos = Point(0, -size.height);
} }
else if (_direction == Direction::Left) else if (_direction == Direction::Left)
{ {
_posDelta = Vector2(-width, 0); _posDelta = Vector2(-size.width, 0);
_startPos = Point(width, 0); _startPos = Point(size.width, 0);
} }
else if (_direction == Direction::Right) else if (_direction == Direction::Right)
{ {
_posDelta = Vector2(width, 0); _posDelta = Vector2(size.width, 0);
_startPos = Point(-width, 0); _startPos = Point(-size.width, 0);
} }
if (_outScene) _outScene->setPos(0, 0); if (_outScene) _outScene->setPos(0, 0);

View File

@ -40,7 +40,7 @@ bool e2d::Transition::_init(Game * game, Scene * prev)
_outScene->retain(); _outScene->retain();
HRESULT hr = S_OK; HRESULT hr = S_OK;
auto renderer = game->getRenderer(); auto renderer = Renderer::getInstance();
if (_inScene) if (_inScene)
{ {
hr = renderer->getRenderTarget()->CreateLayer(&_inLayer); hr = renderer->getRenderTarget()->CreateLayer(&_inLayer);
@ -56,7 +56,6 @@ bool e2d::Transition::_init(Game * game, Scene * prev)
return false; return false;
} }
_windowSize = game->getWindow()->getSize();
_outLayerParam = _inLayerParam = D2D1::LayerParameters( _outLayerParam = _inLayerParam = D2D1::LayerParameters(
D2D1::InfiniteRect(), D2D1::InfiniteRect(),
nullptr, nullptr,
@ -83,24 +82,25 @@ void e2d::Transition::_update()
} }
} }
void e2d::Transition::_render(Game * game) void e2d::Transition::_render()
{ {
auto renderTarget = game->getRenderer()->getRenderTarget(); auto renderTarget = Renderer::getInstance()->getRenderTarget();
auto size = Window::getInstance()->getSize();
if (_outScene) if (_outScene)
{ {
Point rootPos = _outScene->getPos(); auto rootPos = _outScene->getPos();
auto clipRect = D2D1::RectF( auto clipRect = D2D1::RectF(
std::max(rootPos.x, 0.f), std::max(rootPos.x, 0.f),
std::max(rootPos.y, 0.f), std::max(rootPos.y, 0.f),
std::min(rootPos.x + _windowSize.width, _windowSize.width), std::min(rootPos.x + size.width, size.width),
std::min(rootPos.y + _windowSize.height, _windowSize.height) std::min(rootPos.y + size.height, size.height)
); );
renderTarget->SetTransform(D2D1::Matrix3x2F::Identity()); renderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
renderTarget->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); renderTarget->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
renderTarget->PushLayer(_outLayerParam, _outLayer); renderTarget->PushLayer(_outLayerParam, _outLayer);
_outScene->visit(game); _outScene->visit();
renderTarget->PopLayer(); renderTarget->PopLayer();
renderTarget->PopAxisAlignedClip(); renderTarget->PopAxisAlignedClip();
@ -112,14 +112,14 @@ void e2d::Transition::_render(Game * game)
auto clipRect = D2D1::RectF( auto clipRect = D2D1::RectF(
std::max(rootPos.x, 0.f), std::max(rootPos.x, 0.f),
std::max(rootPos.y, 0.f), std::max(rootPos.y, 0.f),
std::min(rootPos.x + _windowSize.width, _windowSize.width), std::min(rootPos.x + size.width, size.width),
std::min(rootPos.y + _windowSize.height, _windowSize.height) std::min(rootPos.y + size.height, size.height)
); );
renderTarget->SetTransform(D2D1::Matrix3x2F::Identity()); renderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
renderTarget->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); renderTarget->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
renderTarget->PushLayer(_inLayerParam, _inLayer); renderTarget->PushLayer(_inLayerParam, _inLayer);
_inScene->visit(game); _inScene->visit();
renderTarget->PopLayer(); renderTarget->PopLayer();
renderTarget->PopAxisAlignedClip(); renderTarget->PopAxisAlignedClip();

View File

@ -33,14 +33,11 @@ public:
}; };
public: public:
Window( // 获取窗体实例
const String& title, /* 窗体标题 */ static Window * getInstance();
int width, /* 窗体宽度 */
int height, /* 窗体高度 */
int iconID = 0 /* 窗体图标 */
);
~Window(); // 销毁窗体实例
static void destroyInstance();
// 创建窗体互斥体 // 创建窗体互斥体
bool createMutex( bool createMutex(
@ -84,7 +81,7 @@ public:
float getDpi() const; float getDpi() const;
// 获取窗口句柄 // 获取窗口句柄
HWND getHWnd() const; HWND getHWnd();
// 打开或隐藏控制台 // 打开或隐藏控制台
void setConsoleEnabled( void setConsoleEnabled(
@ -109,6 +106,12 @@ public:
void poll(); void poll();
private: private:
Window();
~Window();
E2D_DISABLE_COPY(Window);
// 根据客户区大小定位窗口 // 根据客户区大小定位窗口
Rect _locate( Rect _locate(
int width, int width,
@ -131,6 +134,8 @@ private:
String _title; String _title;
int _iconID; int _iconID;
float _dpi; float _dpi;
static Window * _instance;
}; };
@ -138,9 +143,11 @@ private:
class Input class Input
{ {
public: public:
Input(); // 获取输入设备实例
static Input * getInstance();
~Input(); // 销毁输入设备实例
static void destroyInstance();
// 检测键盘某按键是否正被按下 // 检测键盘某按键是否正被按下
bool isDown( bool isDown(
@ -170,20 +177,24 @@ public:
// 获得鼠标Z轴鼠标滚轮坐标增量 // 获得鼠标Z轴鼠标滚轮坐标增量
float getMouseDeltaZ(); float getMouseDeltaZ();
// 初始化输入设备
void initWithWindow(
Window * window
);
// 刷新输入设备状态 // 刷新输入设备状态
void update(); void update();
private: protected:
Input();
~Input();
E2D_DISABLE_COPY(Input);
protected:
IDirectInput8W* _directInput; IDirectInput8W* _directInput;
IDirectInputDevice8W* _keyboardDevice; IDirectInputDevice8W* _keyboardDevice;
IDirectInputDevice8W* _mouseDevice; IDirectInputDevice8W* _mouseDevice;
DIMOUSESTATE _mouseState; DIMOUSESTATE _mouseState;
char _keyBuffer[256]; char _keyBuffer[256];
static Input * _instance;
}; };
@ -191,9 +202,11 @@ private:
class Renderer class Renderer
{ {
public: public:
Renderer(); // 获取渲染器实例
static Renderer * getInstance();
~Renderer(); // 销毁实例
static void destroyInstance();
// 获取背景色 // 获取背景色
Color getBackgroundColor(); Color getBackgroundColor();
@ -209,6 +222,12 @@ public:
bool show bool show
); );
// 开始渲染
void beginDraw();
// 结束渲染
void endDraw();
// 获取文字渲染器 // 获取文字渲染器
TextRenderer * getTextRenderer() const { return _textRenderer; } TextRenderer * getTextRenderer() const { return _textRenderer; }
@ -219,35 +238,31 @@ public:
ID2D1SolidColorBrush * getSolidColorBrush() const { return _solidBrush; } ID2D1SolidColorBrush * getSolidColorBrush() const { return _solidBrush; }
// 获取 ID2D1Factory 对象 // 获取 ID2D1Factory 对象
ID2D1Factory * getFactory() const { return _factory; } static ID2D1Factory * getFactory();
// 获取 IWICImagingFactory 对象 // 获取 IWICImagingFactory 对象
IWICImagingFactory * getImagingFactory() const { return _imagingFactory; } static IWICImagingFactory * getImagingFactory();
// 获取 IDWriteFactory 对象 // 获取 IDWriteFactory 对象
IDWriteFactory * getWriteFactory() const { return _writeFactory; } static IDWriteFactory * getWriteFactory();
// 获取 Miter 样式的 ID2D1StrokeStyle // 获取 Miter 样式的 ID2D1StrokeStyle
ID2D1StrokeStyle * getMiterStrokeStyle(); static ID2D1StrokeStyle * getMiterStrokeStyle();
// 获取 Bevel 样式的 ID2D1StrokeStyle // 获取 Bevel 样式的 ID2D1StrokeStyle
ID2D1StrokeStyle * getBevelStrokeStyle(); static ID2D1StrokeStyle * getBevelStrokeStyle();
// 获取 Round 样式的 ID2D1StrokeStyle // 获取 Round 样式的 ID2D1StrokeStyle
ID2D1StrokeStyle * getRoundStrokeStyle(); static ID2D1StrokeStyle * getRoundStrokeStyle();
// 初始化渲染器 protected:
void initWithWindow( Renderer();
Window * window
);
// 开始渲染 ~Renderer();
void beginDraw();
// 结束渲染 E2D_DISABLE_COPY(Renderer);
void endDraw();
private: protected:
bool _showFps; bool _showFps;
int _renderTimes; int _renderTimes;
Time _lastRenderTime; Time _lastRenderTime;
@ -257,12 +272,14 @@ private:
IDWriteTextLayout* _fpsLayout; IDWriteTextLayout* _fpsLayout;
ID2D1SolidColorBrush* _solidBrush; ID2D1SolidColorBrush* _solidBrush;
ID2D1HwndRenderTarget* _renderTarget; ID2D1HwndRenderTarget* _renderTarget;
ID2D1Factory* _factory;
IWICImagingFactory* _imagingFactory; static ID2D1Factory* _factory;
IDWriteFactory* _writeFactory; static IWICImagingFactory* _imagingFactory;
ID2D1StrokeStyle* _miterStrokeStyle; static IDWriteFactory* _writeFactory;
ID2D1StrokeStyle* _bevelStrokeStyle; static ID2D1StrokeStyle* _miterStrokeStyle;
ID2D1StrokeStyle* _roundStrokeStyle; static ID2D1StrokeStyle* _bevelStrokeStyle;
static ID2D1StrokeStyle* _roundStrokeStyle;
static Renderer * _instance;
}; };
@ -278,19 +295,8 @@ public:
// 获取 Game 实例 // 获取 Game 实例
static Game * getInstance(); static Game * getInstance();
// 初始化 // 销毁实例
void initWithWindow( static void destroyInstance();
Window * window
);
// 获取窗体
Window * getWindow() const { return _window; }
// 获取输入设备
Input * getInput() const { return _input; }
// 获取图形设备
Renderer * getRenderer() const { return _renderer; }
// 启动游戏 // 启动游戏
void start(); void start();
@ -355,15 +361,17 @@ protected:
private: private:
bool _quit; bool _quit;
bool _paused; bool _paused;
Window* _window;
Input* _input;
Renderer* _renderer;
Timer* _timer; Timer* _timer;
Scene* _currScene; Scene* _currScene;
Scene* _nextScene; Scene* _nextScene;
Transition* _transition; Transition* _transition;
Window* _window;
Input* _input;
Renderer* _renderer;
ActionManager* _actionManager; ActionManager* _actionManager;
std::stack<Scene*> _scenes; std::stack<Scene*> _scenes;
static Game * _instance;
}; };

View File

@ -144,12 +144,6 @@ public:
// 判断字符串是否为空 // 判断字符串是否为空
bool isEmpty() const; bool isEmpty() const;
// »ñÈ¡ Unicode ×Ö·û´®
std::wstring getWString() const;
// »ñÈ¡ ANSI ×Ö·û´®
std::string getCString() const;
// 获取指定位置字符 // 获取指定位置字符
wchar_t at( wchar_t at(
int index int index
@ -244,6 +238,8 @@ public:
// 类型转换操作符 // 类型转换操作符
E2D_OP_EXPLICIT operator const wchar_t* () const; E2D_OP_EXPLICIT operator const wchar_t* () const;
E2D_OP_EXPLICIT operator wchar_t* () const; E2D_OP_EXPLICIT operator wchar_t* () const;
E2D_OP_EXPLICIT operator std::wstring () const;
E2D_OP_EXPLICIT operator std::string () const;
// 比较运算符 // 比较运算符
bool operator== (const String &) const; bool operator== (const String &) const;

View File

@ -14,7 +14,7 @@ class Drawable
{ {
public: public:
// 渲染图形 // 渲染图形
virtual void draw(Renderer * renderer) const = 0; virtual void draw() const = 0;
}; };
@ -430,14 +430,10 @@ public:
); );
// 遍历节点 // 遍历节点
virtual void visit( virtual void visit();
Game * game
);
// 渲染节点轮廓 // 渲染节点轮廓
virtual void drawOutline( virtual void drawOutline();
Renderer * renderer
);
// 渲染碰撞体轮廓 // 渲染碰撞体轮廓
virtual void drawCollider(); virtual void drawCollider();
@ -523,9 +519,7 @@ public:
); );
// 遍历节点 // 遍历节点
virtual void visit( virtual void visit() override;
Game * game
) override;
protected: protected:
E2D_DISABLE_COPY(Scene); E2D_DISABLE_COPY(Scene);
@ -592,9 +586,7 @@ public:
Image * getImage() const; Image * getImage() const;
// 渲染精灵 // 渲染精灵
virtual void draw( virtual void draw() const override;
Renderer * renderer
) const override;
protected: protected:
E2D_DISABLE_COPY(Sprite); E2D_DISABLE_COPY(Sprite);
@ -799,9 +791,7 @@ public:
); );
// 渲染文字 // 渲染文字
virtual void draw( virtual void draw() const override;
Renderer * renderer
) const override;
protected: protected:
E2D_DISABLE_COPY(Text); E2D_DISABLE_COPY(Text);
@ -903,9 +893,7 @@ public:
) override; ) override;
// 遍历节点 // 遍历节点
virtual void visit( virtual void visit() override;
Game * game
) override;
protected: protected:
E2D_DISABLE_COPY(Button); E2D_DISABLE_COPY(Button);
@ -1203,7 +1191,6 @@ protected:
protected: protected:
float _strokeWidth; float _strokeWidth;
Stroke _stroke; Stroke _stroke;
Renderer * _renderer;
ID2D1RenderTarget * _renderTarget; ID2D1RenderTarget * _renderTarget;
ID2D1SolidColorBrush * _fillBrush; ID2D1SolidColorBrush * _fillBrush;
ID2D1SolidColorBrush * _lineBrush; ID2D1SolidColorBrush * _lineBrush;

View File

@ -36,9 +36,7 @@ protected:
virtual void _update(); virtual void _update();
// 渲染场景过渡动画 // 渲染场景过渡动画
virtual void _render( virtual void _render();
Game * game
);
// 停止场景过渡动画 // 停止场景过渡动画
virtual void _stop(); virtual void _stop();
@ -51,7 +49,6 @@ protected:
float _duration; float _duration;
float _delta; float _delta;
Time _started; Time _started;
Size _windowSize;
Scene* _outScene; Scene* _outScene;
Scene* _inScene; Scene* _inScene;
ID2D1Layer * _outLayer; ID2D1Layer * _outLayer;