移除Config中垂直同步的设置,并优化程序的延时处理
This commit is contained in:
parent
62a34b9ba2
commit
d1ad592df7
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue