移除Config中垂直同步的设置,并优化程序的延时处理

This commit is contained in:
Nomango 2018-07-29 13:44:53 +08:00
parent 62a34b9ba2
commit d1ad592df7
8 changed files with 100 additions and 132 deletions

View File

@ -4,9 +4,7 @@
e2d::Config::Config() e2d::Config::Config()
: _gameName() : _gameName()
, _soundEnabled(true) , _soundEnabled(true)
, _frameInterval(15)
, _showFps(false) , _showFps(false)
, _vSyncEnabled(true)
, _outlineVisible(false) , _outlineVisible(false)
, _collisionEnabled(false) , _collisionEnabled(false)
, _colliderVisible(false) , _colliderVisible(false)
@ -27,16 +25,6 @@ void e2d::Config::showFps(bool show)
_showFps = show; _showFps = show;
} }
void e2d::Config::setVSyncEnabled(bool enabled)
{
_vSyncEnabled = enabled;
}
void e2d::Config::setFrameInterval(int interval)
{
_frameInterval = interval;
}
void e2d::Config::setOutlineVisible(bool visible) void e2d::Config::setOutlineVisible(bool visible)
{ {
_outlineVisible = visible; _outlineVisible = visible;
@ -67,21 +55,11 @@ bool e2d::Config::isSoundEnabled() const
return _soundEnabled; return _soundEnabled;
} }
bool e2d::Config::isVSyncEnabled() const
{
return _vSyncEnabled;
}
bool e2d::Config::isFpsShow() const bool e2d::Config::isFpsShow() const
{ {
return _showFps; return _showFps;
} }
int e2d::Config::getFrameInterval() const
{
return _frameInterval;
}
bool e2d::Config::isOutlineVisible() const bool e2d::Config::isOutlineVisible() const
{ {
return _outlineVisible; return _outlineVisible;

View File

@ -10,7 +10,6 @@ e2d::Game::Game()
: _quit(true) : _quit(true)
, _paused(false) , _paused(false)
, _config() , _config()
, _frameInterval(_config.getFrameInterval())
{ {
CoInitialize(nullptr); CoInitialize(nullptr);
@ -40,27 +39,24 @@ void e2d::Game::destroyInstance()
void e2d::Game::start() void e2d::Game::start()
{ {
// ÏÔʾ´°¿Ú SceneManager::getInstance()->update();
HWND hWnd = Window::getInstance()->getHWnd(); HWND hWnd = Window::getInstance()->getHWnd();
::ShowWindow(hWnd, SW_SHOWNORMAL); ::ShowWindow(hWnd, SW_SHOWNORMAL);
::UpdateWindow(hWnd); ::UpdateWindow(hWnd);
SceneManager::getInstance()->update();
Window::getInstance()->poll(); Window::getInstance()->poll();
// ¿ªÊ¼ÓÎÏ·
int wait = 0;
Duration interval;
_quit = false; _quit = false;
_last = _now = Time::now(); _last = _now = Time::now();
const Duration minInterval(15);
while (!_quit) while (!_quit)
{ {
_now = Time::now(); _now = Time::now();
interval = _now - _last; Duration interval = _now - _last;
if (_config.isVSyncEnabled() || _frameInterval < interval) if (minInterval < interval)
{ {
_last = _now; _last = _now;
Input::getInstance()->update(); Input::getInstance()->update();
@ -73,7 +69,14 @@ void e2d::Game::start()
} }
else else
{ {
std::this_thread::yield(); // ID2D1HwndRenderTarget 在渲染时会等待显示器刷新,即开启了垂直同步,
// 它起到了非常稳定的延时作用,所以大部分时候不需要手动挂起线程进行延时。
// 下面的代码仅在一些情况下(例如窗口最小化时)挂起线程,防止占用过高 CPU 。
int wait = (minInterval - interval).milliseconds();
if (wait > 1)
{
std::this_thread::sleep_for(std::chrono::milliseconds(wait));
}
} }
} }
} }
@ -109,16 +112,6 @@ void e2d::Game::setConfig(const Config& config)
Player::getInstance()->getXAudio2()->StopEngine(); Player::getInstance()->getXAudio2()->StopEngine();
} }
if (_config.getFrameInterval() != config.getFrameInterval())
{
_frameInterval = Duration(config.getFrameInterval());
}
if (_config.isVSyncEnabled() != config.isVSyncEnabled())
{
Renderer::getInstance()->discardDeviceResources();
}
_config = config; _config = config;
} }

View File

@ -69,10 +69,10 @@ void e2d::Renderer::discardDeviceResources()
void e2d::Renderer::render() void e2d::Renderer::render()
{ {
HRESULT hr = S_OK;
// 创建设备相关资源
auto renderTarget = this->getRenderTarget(); auto renderTarget = this->getRenderTarget();
// 仅当窗口没有被遮挡时进行渲染
if (renderTarget->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED)
return;
// 开始渲染 // 开始渲染
renderTarget->BeginDraw(); renderTarget->BeginDraw();
@ -89,7 +89,7 @@ void e2d::Renderer::render()
} }
// 终止渲染 // 终止渲染
hr = renderTarget->EndDraw(); HRESULT hr = renderTarget->EndDraw();
if (hr == D2DERR_RECREATE_TARGET) if (hr == D2DERR_RECREATE_TARGET)
{ {
@ -195,15 +195,13 @@ ID2D1HwndRenderTarget * e2d::Renderer::getRenderTarget()
rc.bottom - rc.top rc.bottom - rc.top
); );
bool VSyncEnabled = Game::getInstance()->getConfig().isVSyncEnabled();
// 创建一个 Direct2D 渲染目标 // 创建一个 Direct2D 渲染目标
HRESULT hr = Renderer::getFactory()->CreateHwndRenderTarget( HRESULT hr = Renderer::getFactory()->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(), D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties( D2D1::HwndRenderTargetProperties(
hWnd, hWnd,
size, size,
VSyncEnabled ? D2D1_PRESENT_OPTIONS_NONE : D2D1_PRESENT_OPTIONS_IMMEDIATELY), D2D1_PRESENT_OPTIONS_NONE),
&_renderTarget &_renderTarget
); );

View File

@ -44,7 +44,7 @@ e2d::Color::Color(UINT rgb, float alpha)
e2d::Color::operator D2D1_COLOR_F() const e2d::Color::operator D2D1_COLOR_F() const
{ {
return D2D1::ColorF(r, g, b, a); return std::move(D2D1::ColorF(r, g, b, a));
} }
void e2d::Color::_init(UINT rgb, float alpha) void e2d::Color::_init(UINT rgb, float alpha)

View File

@ -22,7 +22,9 @@ void e2d::Scene::render()
if (Game::getInstance()->getConfig().isOutlineVisible()) if (Game::getInstance()->getConfig().isOutlineVisible())
{ {
Renderer::getInstance()->getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); auto brush = Renderer::getInstance()->getSolidColorBrush();
brush->SetColor(D2D1::ColorF(D2D1::ColorF::Red, 0.6f));
brush->SetOpacity(1.f);
_root->_renderOutline(); _root->_renderOutline();
} }

View File

@ -65,7 +65,6 @@ e2d::Node::Node()
, _needTransform(false) , _needTransform(false)
, _autoUpdate(true) , _autoUpdate(true)
, _positionFixed(false) , _positionFixed(false)
, _outline(nullptr)
, _collider(this) , _collider(this)
, _extrapolate(Property::Origin) , _extrapolate(Property::Origin)
{ {
@ -73,8 +72,6 @@ e2d::Node::Node()
e2d::Node::~Node() e2d::Node::~Node()
{ {
SafeRelease(_outline);
ActionManager::getInstance()->clearAllBindedWith(this); ActionManager::getInstance()->clearAllBindedWith(this);
for (auto child : _children) for (auto child : _children)
{ {
@ -158,7 +155,7 @@ void e2d::Node::_render()
if (_children.empty()) if (_children.empty())
{ {
// 转换渲染器的二维矩阵 // 转换渲染器的转换矩阵
pRT->SetTransform(_finalMatri); pRT->SetTransform(_finalMatri);
// 渲染自身 // 渲染自身
this->onRender(); this->onRender();
@ -183,7 +180,7 @@ void e2d::Node::_render()
} }
} }
// 转换渲染器的二维矩阵 // 转换渲染器的转换矩阵
pRT->SetTransform(_finalMatri); pRT->SetTransform(_finalMatri);
// 渲染自身 // 渲染自身
this->onRender(); this->onRender();
@ -203,17 +200,13 @@ void e2d::Node::_renderOutline()
{ {
if (_visible) if (_visible)
{ {
if (_outline) auto renderer = Renderer::getInstance();
{ renderer->getRenderTarget()->SetTransform(_finalMatri);
auto renderer = Renderer::getInstance(); renderer->getRenderTarget()->DrawRectangle(
// 获取纯色画刷 D2D1::RectF(0, 0, _width, _height),
ID2D1SolidColorBrush * brush = renderer->getSolidColorBrush(); renderer->getSolidColorBrush(),
// 设置画刷颜色和透明度 1.5f
brush->SetColor(D2D1::ColorF(D2D1::ColorF::Red, 0.6f)); );
brush->SetOpacity(1.f);
// 渲染轮廓
renderer->getRenderTarget()->DrawGeometry(_outline, brush, 1.5f);
}
// 渲染所有子节点的轮廓 // 渲染所有子节点的轮廓
for (auto child : _children) for (auto child : _children)
@ -274,29 +267,6 @@ void e2d::Node::updateTransform()
// 更新碰撞体 // 更新碰撞体
_collider.recreate(); _collider.recreate();
// 为节点创建一个轮廓
ID2D1RectangleGeometry * rectGeo = nullptr;
ID2D1TransformedGeometry * transformedGeo = nullptr;
auto factory = Renderer::getFactory();
HRESULT hr = factory->CreateRectangleGeometry(
D2D1::RectF(0, 0, _width, _height),
&rectGeo
);
if (SUCCEEDED(hr))
{
factory->CreateTransformedGeometry(
rectGeo,
_finalMatri,
&transformedGeo
);
}
SafeRelease(rectGeo);
SafeRelease(_outline);
_outline = transformedGeo;
// 通知子节点进行转换 // 通知子节点进行转换
for (auto& child : _children) for (auto& child : _children)
{ {
@ -896,43 +866,92 @@ void e2d::Node::stopAction(const String& name)
bool e2d::Node::containsPoint(const Point& point) bool e2d::Node::containsPoint(const Point& point)
{ {
// 更新转换矩阵
updateTransform(); updateTransform();
if (_outline)
// 为节点创建一个轮廓
BOOL ret = 0;
ID2D1RectangleGeometry * rectGeo = nullptr;
auto factory = Renderer::getFactory();
HRESULT hr = factory->CreateRectangleGeometry(
D2D1::RectF(0, 0, _width, _height),
&rectGeo
);
if (SUCCEEDED(hr))
{ {
BOOL ret = 0; rectGeo->FillContainsPoint(
_outline->FillContainsPoint(
D2D1::Point2F(point.x, point.y), D2D1::Point2F(point.x, point.y),
D2D1::Matrix3x2F::Identity(), _finalMatri,
&ret &ret
); );
if (ret)
{
return true;
}
} }
return false; SafeRelease(rectGeo);
return ret != 0;
} }
bool e2d::Node::intersects(Node * node) bool e2d::Node::intersects(Node * node)
{ {
// 更新转换矩阵
updateTransform(); updateTransform();
node->updateTransform(); node->updateTransform();
if (_outline)
// 为节点创建轮廓
D2D1_GEOMETRY_RELATION relation = D2D1_GEOMETRY_RELATION_UNKNOWN;
ID2D1RectangleGeometry *rectGeo = nullptr, *rectGeo2 = nullptr;
ID2D1TransformedGeometry *transGeo = nullptr, *transGeo2 = nullptr;
auto factory = Renderer::getFactory();
HRESULT hr = factory->CreateRectangleGeometry(
D2D1::RectF(0, 0, _width, _height),
&rectGeo
);
if (SUCCEEDED(hr))
{
hr = factory->CreateRectangleGeometry(
D2D1::RectF(0, 0, node->_width, node->_height),
&rectGeo2
);
}
if (SUCCEEDED(hr))
{
hr = factory->CreateTransformedGeometry(
rectGeo,
_finalMatri,
&transGeo
);
}
if (SUCCEEDED(hr))
{
hr = factory->CreateTransformedGeometry(
rectGeo2,
node->_finalMatri,
&transGeo2
);
}
if (SUCCEEDED(hr))
{ {
D2D1_GEOMETRY_RELATION relation;
// 获取相交状态 // 获取相交状态
_outline->CompareWithGeometry( transGeo->CompareWithGeometry(
node->_outline, transGeo2,
D2D1::Matrix3x2F::Identity(), D2D1::Matrix3x2F::Identity(),
&relation &relation
); );
if ((relation != D2D1_GEOMETRY_RELATION_UNKNOWN) &&
(relation != D2D1_GEOMETRY_RELATION_DISJOINT))
{
return true;
}
} }
return false;
SafeRelease(rectGeo);
SafeRelease(rectGeo2);
SafeRelease(transGeo);
SafeRelease(transGeo2);
return relation != D2D1_GEOMETRY_RELATION_UNKNOWN &&
relation != D2D1_GEOMETRY_RELATION_DISJOINT;
} }
void e2d::Node::setAutoUpdate(bool bAutoUpdate) void e2d::Node::setAutoUpdate(bool bAutoUpdate)

View File

@ -30,18 +30,6 @@ public:
bool show bool show
); );
// 打开或关闭垂直同步
// 默认:打开
void setVSyncEnabled(
bool enabled
);
// 设置帧率刷新间隔(关闭垂直同步时生效)
// 默认15
void setFrameInterval(
int interval
);
// 显示或隐藏节点轮廓 // 显示或隐藏节点轮廓
// 默认:隐藏 // 默认:隐藏
void setOutlineVisible( void setOutlineVisible(
@ -72,15 +60,9 @@ public:
// 获取声音打开状态 // 获取声音打开状态
bool isSoundEnabled() const; bool isSoundEnabled() const;
// 获取垂直同步打开状态
bool isVSyncEnabled() const;
// 获取 FPS 显示状态 // 获取 FPS 显示状态
bool isFpsShow() const; bool isFpsShow() const;
// 获取帧率刷新间隔
int getFrameInterval() const;
// 获取节点轮廓显示状态 // 获取节点轮廓显示状态
bool isOutlineVisible() const; bool isOutlineVisible() const;
@ -92,12 +74,10 @@ public:
protected: protected:
bool _showFps; bool _showFps;
bool _vSyncEnabled;
bool _soundEnabled; bool _soundEnabled;
bool _outlineVisible; bool _outlineVisible;
bool _collisionEnabled; bool _collisionEnabled;
bool _colliderVisible; bool _colliderVisible;
int _frameInterval;
String _gameName; String _gameName;
}; };
@ -155,7 +135,6 @@ private:
Time _start; Time _start;
Time _now; Time _now;
Time _last; Time _last;
Duration _frameInterval;
static Game * _instance; static Game * _instance;
}; };

View File

@ -467,7 +467,6 @@ protected:
Scene * _parentScene; Scene * _parentScene;
Node * _parent; Node * _parent;
Property _extrapolate; Property _extrapolate;
ID2D1Geometry* _outline;
D2D1::Matrix3x2F _initialMatri; D2D1::Matrix3x2F _initialMatri;
D2D1::Matrix3x2F _finalMatri; D2D1::Matrix3x2F _finalMatri;
std::vector<Node*> _children; std::vector<Node*> _children;