diff --git a/core/Action/Action.cpp b/core/Action/Action.cpp index d998ca9e..a23b0974 100644 --- a/core/Action/Action.cpp +++ b/core/Action/Action.cpp @@ -24,7 +24,7 @@ bool e2d::Action::isRunning() void e2d::Action::resume() { _running = true; - _last = Time::getTotalTime(); + _last = Game::getInstance()->getTotalTime(); } void e2d::Action::pause() @@ -56,7 +56,7 @@ void e2d::Action::reset() { _initialized = false; _done = false; - _last = Time::getTotalTime(); + _last = Game::getInstance()->getTotalTime(); } bool e2d::Action::_isDone() @@ -74,7 +74,7 @@ void e2d::Action::_startWithTarget(Node* target) void e2d::Action::_init() { _initialized = true; - _last = Time::getTotalTime(); + _last = Game::getInstance()->getTotalTime(); } void e2d::Action::_update() diff --git a/core/Action/Animate.cpp b/core/Action/Animate.cpp index 69eadd0d..5ce614aa 100644 --- a/core/Action/Animate.cpp +++ b/core/Action/Animate.cpp @@ -56,7 +56,7 @@ void e2d::Animate::_update() return; } - while ((Time::getTotalTime() - _last) >= _animation->getInterval()) + while ((Game::getInstance()->getTotalTime() - _last) >= _animation->getInterval()) { auto& frames = _animation->getFrames(); auto target = dynamic_cast(_target); @@ -80,7 +80,7 @@ void e2d::Animate::_update() void e2d::Animate::_resetTime() { Action::_resetTime(); - _last = Time::getTotalTime(); + _last = Game::getInstance()->getTotalTime(); } void e2d::Animate::reset() diff --git a/core/Action/Delay.cpp b/core/Action/Delay.cpp index 76157905..007f6e08 100644 --- a/core/Action/Delay.cpp +++ b/core/Action/Delay.cpp @@ -31,7 +31,7 @@ void e2d::Delay::_update() { Action::_update(); - _delta = Time::getTotalTime() - _last; + _delta = Game::getInstance()->getTotalTime() - _last; if (_delta >= _delay) { @@ -42,5 +42,5 @@ void e2d::Delay::_update() void e2d::Delay::_resetTime() { Action::_resetTime(); - _last = Time::getTotalTime() - _delta; + _last = Game::getInstance()->getTotalTime() - _delta; } diff --git a/core/Action/FiniteTimeAction.cpp b/core/Action/FiniteTimeAction.cpp index 91e980e0..ae11a3eb 100644 --- a/core/Action/FiniteTimeAction.cpp +++ b/core/Action/FiniteTimeAction.cpp @@ -28,7 +28,7 @@ void e2d::FiniteTimeAction::_update() } else { - _delta = std::min((Time::getTotalTime() - _last) / _duration, 1.0); + _delta = std::min((Game::getInstance()->getTotalTime() - _last) / _duration, 1.0); if (_delta >= 1) { @@ -40,5 +40,5 @@ void e2d::FiniteTimeAction::_update() void e2d::FiniteTimeAction::_resetTime() { Action::_resetTime(); - _last = Time::getTotalTime() - _delta * _duration; + _last = Game::getInstance()->getTotalTime() - _delta * _duration; } diff --git a/core/Base/GC.cpp b/core/Base/GC.cpp index d459e3b5..c59ccc22 100644 --- a/core/Base/GC.cpp +++ b/core/Base/GC.cpp @@ -49,6 +49,10 @@ e2d::GC::GC() e2d::GC::~GC() { + // 删除所有对象 + GC::clear(); + // 清除图片缓存 + Image::clearCache(); // 删除所有单例 Game::destroyInstance(); Renderer::destroyInstance(); @@ -92,6 +96,11 @@ void e2d::GC::flush() void e2d::GC::clear() { _instance._cleanup = true; + + SceneManager::getInstance()->clear(); + Timer::getInstance()->clearAllTasks(); + ActionManager::getInstance()->clearAll(); + for (auto pair : _instance._pool) { if (pair.second) diff --git a/core/Base/Game.cpp b/core/Base/Game.cpp index 014cf68d..93b51baa 100644 --- a/core/Base/Game.cpp +++ b/core/Base/Game.cpp @@ -1,6 +1,9 @@ #include "..\e2dbase.h" #include "..\e2dmanager.h" #include "..\e2dtool.h" +#include + +using namespace std::chrono; e2d::Game * e2d::Game::_instance = nullptr; @@ -11,6 +14,8 @@ e2d::Game::Game() , _config(nullptr) { CoInitialize(nullptr); + + _start = _last = _now = steady_clock::now(); } e2d::Game::~Game() @@ -36,7 +41,7 @@ void e2d::Game::destroyInstance() } } -void e2d::Game::start(bool cleanup) +void e2d::Game::start() { auto input = Input::getInstance(); auto window = Window::getInstance(); @@ -45,51 +50,56 @@ void e2d::Game::start(bool cleanup) auto sceneManager = SceneManager::getInstance(); auto actionManager = ActionManager::getInstance(); - // 显示窗口 - ::ShowWindow(window->getHWnd(), SW_SHOWNORMAL); - // 刷新窗口内容 - ::UpdateWindow(window->getHWnd()); - // 处理窗口消息 - window->poll(); - // 初始化计时 - Time::__init(); + if (!input || !window || !renderer || !timer || !sceneManager || !actionManager) + { + throw SystemException(L"初始化失败"); + } + HWND hWnd = window->getHWnd(); + if (hWnd == nullptr) + { + throw SystemException(L"无法创建窗口"); + } + + // 显示窗口 + ::ShowWindow(hWnd, SW_SHOWNORMAL); + ::UpdateWindow(hWnd); + window->poll(); + + // 开始游戏 + const milliseconds frameInterval(15LL); + milliseconds wait, interval; + _ended = false; + _last = _now = steady_clock::now(); while (!_ended) { - // 处理窗口消息 - window->poll(); - // 刷新时间 - Time::__updateNow(); + _now = steady_clock::now(); + interval = duration_cast(_now - _last); - // 判断是否达到了刷新状态 - if (Time::__isReady()) + if (frameInterval < interval) { - if (_config->_unconfigured) - { - _config->_update(); - } + _last = _now; input->update(); // 获取用户输入 timer->update(); // 更新定时器 actionManager->update(); // 更新动作管理器 sceneManager->update(); // 更新场景内容 + _config->_update(); // 更新游戏配置 renderer->render(); // 渲染游戏画面 + window->poll(); // 处理窗口消息 GC::flush(); // 刷新内存池 - - Time::__updateLast(); // 刷新时间信息 } else { - Time::__sleep(); // 挂起线程 + wait = frameInterval - interval; + if (wait.count() > 1LL) + { + std::this_thread::sleep_for(wait - milliseconds(1LL)); + } } } - - if (cleanup) - { - Game::cleanup(); - } } void e2d::Game::pause() @@ -101,7 +111,9 @@ void e2d::Game::resume() { if (_paused && !_ended) { - Time::__reset(); + _last = _now = steady_clock::now(); + Timer::getInstance()->updateTime(); + ActionManager::getInstance()->updateTime(); } _paused = false; } @@ -129,6 +141,11 @@ e2d::Config* e2d::Game::getConfig() return _config; } +double e2d::Game::getTotalTime() const +{ + return duration_cast(steady_clock::now() - _start).count() / 1000.0 / 1000.0; +} + void e2d::Game::quit() { _ended = true; // 这个变量将控制游戏是否结束 @@ -136,16 +153,7 @@ void e2d::Game::quit() void e2d::Game::cleanup() { - // 删除所有场景 - SceneManager::getInstance()->clear(); - // 清空定时器 - Timer::getInstance()->clearAllTasks(); - // 清除所有动作 - ActionManager::getInstance()->clearAll(); - // 清空图片缓存 - Image::clearCache(); - // 清空音乐缓存 - Player::getInstance()->clearCache(); - // 删除所有对象 GC::clear(); + Image::clearCache(); + Player::getInstance()->clearCache(); } diff --git a/core/Base/Renderer.cpp b/core/Base/Renderer.cpp index d6395ed8..22c3b9fe 100644 --- a/core/Base/Renderer.cpp +++ b/core/Base/Renderer.cpp @@ -161,11 +161,11 @@ void e2d::Renderer::_renderFps() { ++_renderTimes; - double fDelay = Time::getTotalTime() - _lastRenderTime; + double fDelay = Game::getInstance()->getTotalTime() - _lastRenderTime; if (fDelay >= 0.1) { _fpsText = String::format(L"FPS: %.1lf", (1 / fDelay) * _renderTimes); - _lastRenderTime = Time::getTotalTime(); + _lastRenderTime = Game::getInstance()->getTotalTime(); _renderTimes = 0; } diff --git a/core/Base/Time.cpp b/core/Base/Time.cpp deleted file mode 100644 index 29ebc2fb..00000000 --- a/core/Base/Time.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "..\e2dbase.h" -#include "..\e2dtool.h" -#include "..\e2dmanager.h" -#include - -using namespace std::chrono; - - -// 游戏开始时间 -steady_clock::time_point e2d::Time::_start; -// 当前时间 -steady_clock::time_point e2d::Time::_now; -// 上一帧刷新时间 -steady_clock::time_point e2d::Time::_last; -// 固定的刷新时间 -steady_clock::time_point e2d::Time::_fixedLast; -// 每一帧间隔 -milliseconds e2d::Time::_interval; - - -double e2d::Time::getTotalTime() -{ - return duration_cast(_now - _start).count() / 1000.0 / 1000.0; -} - -double e2d::Time::getDeltaTime() -{ - return duration_cast(_now - _last).count() / 1000.0 / 1000.0; -} - -bool e2d::Time::__init() -{ - _start = _fixedLast = _last = _now = steady_clock::now(); - _interval = milliseconds(15); - return true; -} - -bool e2d::Time::__isReady() -{ - return _interval < duration_cast(_now - _fixedLast); -} - -void e2d::Time::__updateNow() -{ - _now = steady_clock::now(); -} - -void e2d::Time::__updateLast() -{ - _fixedLast += _interval; - - _last = _now; - _now = steady_clock::now(); -} - -void e2d::Time::__reset() -{ - _last = _fixedLast = _now = steady_clock::now(); - Timer::getInstance()->updateTime(); - ActionManager::getInstance()->updateTime(); -} - -void e2d::Time::__sleep() -{ - // 计算挂起时长 - int nWaitMS = 16 - static_cast(duration_cast(_now - _fixedLast).count()); - - if (nWaitMS > 1) - { - // 挂起线程,释放 CPU 占用 - std::this_thread::sleep_for(milliseconds(nWaitMS)); - } -} diff --git a/core/Common/Config.cpp b/core/Common/Config.cpp index 89512686..5354bbdb 100644 --- a/core/Common/Config.cpp +++ b/core/Common/Config.cpp @@ -107,6 +107,9 @@ bool e2d::Config::isColliderVisible() const void e2d::Config::_update() { + if (!_unconfigured) + return; + _unconfigured = false; if (_soundEnabled) diff --git a/core/Common/Duration.cpp b/core/Common/Duration.cpp new file mode 100644 index 00000000..04f210b4 --- /dev/null +++ b/core/Common/Duration.cpp @@ -0,0 +1,17 @@ +#include "..\e2dcommon.h" + +using namespace std::chrono; + +e2d::Duration::Duration() +{ +} + +e2d::Duration e2d::Duration::operator+(Duration const & size) const +{ + return Duration(); +} + +e2d::Duration e2d::Duration::operator-(Duration const & size) const +{ + return Duration(); +} diff --git a/core/Common/Image.cpp b/core/Common/Image.cpp index 559c06eb..28def6dc 100644 --- a/core/Common/Image.cpp +++ b/core/Common/Image.cpp @@ -296,9 +296,12 @@ bool e2d::Image::preload(const Resource& res) void e2d::Image::clearCache() { + if (_bitmapCache.empty()) + return; + for (auto bitmap : _bitmapCache) { - SafeRelease(bitmap.second); + bitmap.second->Release(); } _bitmapCache.clear(); } diff --git a/core/Common/Time.cpp b/core/Common/Time.cpp new file mode 100644 index 00000000..9016cab6 --- /dev/null +++ b/core/Common/Time.cpp @@ -0,0 +1,18 @@ +#include "..\e2dcommon.h" + +using namespace std::chrono; + + +e2d::Time::Time() +{ +} + +e2d::Time e2d::Time::operator+(Duration const & size) const +{ + return Time(); +} + +e2d::Duration e2d::Time::operator-(Time const & size) const +{ + return Duration(); +} diff --git a/core/Manager/ActionManager.cpp b/core/Manager/ActionManager.cpp index edfaaa7a..fb321bce 100644 --- a/core/Manager/ActionManager.cpp +++ b/core/Manager/ActionManager.cpp @@ -213,12 +213,16 @@ void e2d::ActionManager::clearAllBindedWith(Node * target) void e2d::ActionManager::clearAll() { - for (auto action : _runningActions) + if (!_runningActions.empty()) { - GC::release(action); + for (auto action : _runningActions) + { + GC::release(action); + } + _runningActions.clear(); } + _actions.clear(); - _runningActions.clear(); } std::vector e2d::ActionManager::get(const String& name) diff --git a/core/Manager/SceneManager.cpp b/core/Manager/SceneManager.cpp index bd940677..f91eac14 100644 --- a/core/Manager/SceneManager.cpp +++ b/core/Manager/SceneManager.cpp @@ -85,20 +85,19 @@ void e2d::SceneManager::pop(Transition * transition /* = nullptr */) // 设置切换场景动作 if (transition) { - _transition = transition; GC::retain(transition); transition->_init(_currScene, _nextScene); transition->_update(); + _transition = transition; } } void e2d::SceneManager::clear() { // 清空场景栈 - while (_scenes.size()) + while (!_scenes.empty()) { - auto temp = _scenes.top(); - GC::safeRelease(temp); + _scenes.top()->release(); _scenes.pop(); } } diff --git a/core/Tool/Player.cpp b/core/Tool/Player.cpp index b3409439..d3c15602 100644 --- a/core/Tool/Player.cpp +++ b/core/Tool/Player.cpp @@ -13,9 +13,13 @@ e2d::Player::Player() e2d::Player::~Player() { - for (auto pair : _musicList) - GC::release(pair.second); - _musicList.clear(); + if (!_musicList.empty()) + { + for (auto pair : _musicList) + { + delete pair.second; + } + } if (_masteringVoice) _masteringVoice->DestroyVoice(); @@ -31,9 +35,8 @@ e2d::Player * e2d::Player::getInstance() { _instance = new (std::nothrow) Player; - HRESULT hr; - if (FAILED(hr = XAudio2Create(&_instance->_xAudio2, 0)) || - FAILED(hr = _instance->_xAudio2->CreateMasteringVoice(&_instance->_masteringVoice))) + if (FAILED(XAudio2Create(&_instance->_xAudio2, 0)) || + FAILED(_instance->_xAudio2->CreateMasteringVoice(&_instance->_masteringVoice))) { throw SystemException(L"初始化 XAudio2 组件失败"); } @@ -68,11 +71,10 @@ bool e2d::Player::preload(const Resource& res) if (_musicList.end() != _musicList.find(res)) return true; - Music * music = new (e2d::autorelease) Music(); + Music * music = new Music(); if (music->open(res)) { - GC::retain(music); music->setVolume(_volume); _musicList.insert(std::make_pair(res, music)); return true; @@ -139,10 +141,6 @@ void e2d::Player::stop(const String& filePath) void e2d::Player::stop(const Resource& res) { - if (res.isResource()) - { - - } if (_musicList.end() != _musicList.find(res)) _musicList[res]->stop(); } @@ -204,7 +202,7 @@ void e2d::Player::clearCache() { for (auto pair : _musicList) { - GC::release(pair.second); + delete pair.second; } _musicList.clear(); } diff --git a/core/Tool/Task.cpp b/core/Tool/Task.cpp index 09de625b..d1d6de0c 100644 --- a/core/Tool/Task.cpp +++ b/core/Tool/Task.cpp @@ -60,7 +60,7 @@ bool e2d::Task::isReady() const { return true; } - if ((Time::getTotalTime() - _lastTime) >= _delay) + if ((Game::getInstance()->getTotalTime() - _lastTime) >= _delay) { return true; } @@ -80,5 +80,5 @@ e2d::String e2d::Task::getName() const void e2d::Task::updateTime() { - _lastTime = Time::getTotalTime(); + _lastTime = Game::getInstance()->getTotalTime(); } \ No newline at end of file diff --git a/core/Tool/Timer.cpp b/core/Tool/Timer.cpp index 8a8c4699..83462dcc 100644 --- a/core/Tool/Timer.cpp +++ b/core/Tool/Timer.cpp @@ -100,6 +100,9 @@ void e2d::Timer::removeAllTasks() void e2d::Timer::clearAllTasks() { + if (_tasks.empty()) + return; + for (auto task : _tasks) { GC::release(task); diff --git a/core/Transition/Transition.cpp b/core/Transition/Transition.cpp index 39dc1baf..f528f2e1 100644 --- a/core/Transition/Transition.cpp +++ b/core/Transition/Transition.cpp @@ -45,7 +45,7 @@ void e2d::Transition::_init(Scene * prev, Scene * next) throw SystemException(L"场景过渡动画图层创建失败"); } - _last = Time::getTotalTime(); + _last = Game::getInstance()->getTotalTime(); _outScene = prev; _inScene = next; GC::retain(_outScene); @@ -64,7 +64,7 @@ void e2d::Transition::_update() } else { - _delta = std::min((Time::getTotalTime() - _last) / _duration, 1.0); + _delta = std::min((Game::getInstance()->getTotalTime() - _last) / _duration, 1.0); } this->_updateCustom(); diff --git a/core/e2dbase.h b/core/e2dbase.h index fa250747..011b4456 100644 --- a/core/e2dbase.h +++ b/core/e2dbase.h @@ -21,9 +21,7 @@ public: static void destroyInstance(); // 启动游戏 - void start( - bool cleanup = true /* 自动清理资源 */ - ); + void start(); // 暂停游戏 void pause(); @@ -48,6 +46,8 @@ public: // 获取游戏配置 Config* getConfig(); + double getTotalTime() const; + private: Game(); @@ -59,6 +59,9 @@ private: bool _ended; bool _paused; Config* _config; + std::chrono::steady_clock::time_point _start; + std::chrono::steady_clock::time_point _now; + std::chrono::steady_clock::time_point _last; static Game * _instance; }; @@ -185,46 +188,6 @@ private: }; -// 时间控制 -class Time -{ - friend class Game; - -public: - // 获取上一帧的时间间隔(秒) - static double getDeltaTime(); - - // 获取游戏总时长(秒) - static double getTotalTime(); - -private: - // 初始化计时操作 - static bool __init(); - - // 是否达到更新时间 - static bool __isReady(); - - // 更新当前时间 - static void __updateNow(); - - // 更新时间信息 - static void __updateLast(); - - // 重置时间信息 - static void __reset(); - - // 挂起线程 - static void __sleep(); - -private: - static std::chrono::steady_clock::time_point _start; - static std::chrono::steady_clock::time_point _now; - static std::chrono::steady_clock::time_point _last; - static std::chrono::steady_clock::time_point _fixedLast; - static std::chrono::milliseconds _interval; -}; - - // 输入设备 class Input { diff --git a/core/e2dcommon.h b/core/e2dcommon.h index 98690f0b..3c182037 100644 --- a/core/e2dcommon.h +++ b/core/e2dcommon.h @@ -404,6 +404,34 @@ protected: }; +// 时间段 +class Duration +{ +public: + Duration(); + + Duration operator + (Duration const & size) const; + Duration operator - (Duration const & size) const; + +protected: + std::chrono::milliseconds _duration; +}; + + +// 时间点 +class Time +{ +public: + Time(); + + Time operator + (Duration const & size) const; + Duration operator - (Time const & size) const; + +protected: + std::chrono::steady_clock::time_point _time; +}; + + // 字体 class Font { diff --git a/project/vs2012/Easy2D.vcxproj b/project/vs2012/Easy2D.vcxproj index f6e7174c..b2092b05 100644 --- a/project/vs2012/Easy2D.vcxproj +++ b/project/vs2012/Easy2D.vcxproj @@ -55,11 +55,11 @@ - + @@ -70,6 +70,7 @@ + diff --git a/project/vs2012/Easy2D.vcxproj.filters b/project/vs2012/Easy2D.vcxproj.filters index d34ca1f8..9602e8a8 100644 --- a/project/vs2012/Easy2D.vcxproj.filters +++ b/project/vs2012/Easy2D.vcxproj.filters @@ -115,9 +115,6 @@ Base - - Base - Base diff --git a/project/vs2013/Easy2D.vcxproj b/project/vs2013/Easy2D.vcxproj index 94595c9b..f7d162fd 100644 --- a/project/vs2013/Easy2D.vcxproj +++ b/project/vs2013/Easy2D.vcxproj @@ -199,11 +199,11 @@ - + @@ -214,6 +214,7 @@ + diff --git a/project/vs2013/Easy2D.vcxproj.filters b/project/vs2013/Easy2D.vcxproj.filters index 12e5a74d..5f46b7f1 100644 --- a/project/vs2013/Easy2D.vcxproj.filters +++ b/project/vs2013/Easy2D.vcxproj.filters @@ -115,9 +115,6 @@ Base - - Base - Base diff --git a/project/vs2017/Easy2D.vcxproj b/project/vs2017/Easy2D.vcxproj index 1f305c7b..b5f050a0 100644 --- a/project/vs2017/Easy2D.vcxproj +++ b/project/vs2017/Easy2D.vcxproj @@ -219,11 +219,11 @@ - + @@ -234,6 +234,7 @@ + diff --git a/project/vs2017/Easy2D.vcxproj.filters b/project/vs2017/Easy2D.vcxproj.filters index 44d35575..4792a873 100644 --- a/project/vs2017/Easy2D.vcxproj.filters +++ b/project/vs2017/Easy2D.vcxproj.filters @@ -78,9 +78,6 @@ Manager - - Base - Base @@ -249,6 +246,12 @@ Event + + Common + + + Common +