From b853bb76cf724ecbb4bd4cea45ba33b1190de364 Mon Sep 17 00:00:00 2001 From: Nomango <569629550@qq.com> Date: Sun, 11 Mar 2018 23:56:40 +0800 Subject: [PATCH] New class Listener;Fixed String bugs;class File rename to Path. --- core/Base/Game.cpp | 16 +-- core/Base/Input.cpp | 155 ++++++++++++++++++++++++-- core/Common/Image.cpp | 6 - core/Common/Listener.cpp | 63 +++++++++++ core/Common/String.cpp | 34 +++++- core/Manager/ActionManager.cpp | 44 ++++---- core/Manager/MusicManager.cpp | 6 +- core/Manager/SceneManager.cpp | 6 +- core/Manager/TimerManager.cpp | 12 +- core/Node/Node.cpp | 124 +++++++++------------ core/Tool/Data.cpp | 51 ++++++--- core/Tool/File.cpp | 93 ++++++++++++---- core/ebase.h | 49 +++++++- core/ecommon.h | 116 ++++++++++++++----- core/emanagers.h | 65 +++++------ core/enodes.h | 19 ++-- core/etools.h | 45 ++++++-- project/vs2012/Easy2D.vcxproj | 1 + project/vs2012/Easy2D.vcxproj.filters | 3 + project/vs2013/Easy2D.vcxproj | 1 + project/vs2013/Easy2D.vcxproj.filters | 3 + project/vs2017/Easy2D.vcxproj | 1 + project/vs2017/Easy2D.vcxproj.filters | 3 + 23 files changed, 663 insertions(+), 253 deletions(-) create mode 100644 core/Common/Listener.cpp diff --git a/core/Base/Game.cpp b/core/Base/Game.cpp index cf65b4b8..81910dca 100644 --- a/core/Base/Game.cpp +++ b/core/Base/Game.cpp @@ -102,20 +102,20 @@ int e2d::Game::run() // 判断是否达到了刷新状态 if (Time::__isReady()) { - TimerManager::__update(); // 定时器管理器执行程序 - ActionManager::__update(); // 动作管理器执行程序 + TimerManager::__update(); // 定时器管理器执行程序 + ActionManager::__update(); // 动作管理器执行程序 while (Time::__isReady()) { - Input::__updateDeviceState(); // 获取用户输入 - SceneManager::__update(); // 更新场景内容 - Time::__updateLast(); // 刷新时间信息 + Input::__update(); // 获取用户输入 + SceneManager::__update(); // 更新场景内容 + Time::__updateLast(); // 刷新时间信息 } - Renderer::__render(); // 渲染游戏画面 + Renderer::__render(); // 渲染游戏画面 } else { - ObjectManager::__update(); // 刷新内存池 - Time::__sleep(); // 挂起线程 + ObjectManager::__update(); // 刷新内存池 + Time::__sleep(); // 挂起线程 } } diff --git a/core/Base/Input.cpp b/core/Base/Input.cpp index f653f5ba..1e1d0a48 100644 --- a/core/Base/Input.cpp +++ b/core/Base/Input.cpp @@ -15,18 +15,9 @@ static DIMOUSESTATE s_MouseState; // static DIMOUSESTATE s_MouseRecordState; // 鼠标信息二级缓冲 static POINT s_MousePosition; // 鼠标位置存储结构体 +// 监听器容器 +static std::vector s_vListeners; -void Input::__uninit() -{ - if (s_KeyboardDevice) - s_KeyboardDevice->Unacquire(); - if (s_MouseDevice) - s_MouseDevice->Unacquire(); - - SafeReleaseInterface(&s_MouseDevice); - SafeReleaseInterface(&s_KeyboardDevice); - SafeReleaseInterface(&s_pDirectInput); -} bool Input::__init() { @@ -94,6 +85,38 @@ bool Input::__init() return SUCCEEDED(hr); } +void Input::__uninit() +{ + if (s_KeyboardDevice) + s_KeyboardDevice->Unacquire(); + if (s_MouseDevice) + s_MouseDevice->Unacquire(); + + SafeReleaseInterface(&s_MouseDevice); + SafeReleaseInterface(&s_KeyboardDevice); + SafeReleaseInterface(&s_pDirectInput); +} + +void e2d::Input::__update() +{ + Input::__updateDeviceState(); + + for (size_t i = 0; i < s_vListeners.size(); i++) + { + auto pListener = s_vListeners[i]; + // 更新监听器 + if (pListener->m_bClear) + { + pListener->release(); + s_vListeners.erase(s_vListeners.begin() + i); + } + else if (pListener->isRunning()) + { + pListener->update(); + } + } +} + void Input::__updateDeviceState() { if (s_KeyboardDevice) @@ -134,6 +157,116 @@ void Input::__updateDeviceState() ScreenToClient(Window::getHWnd(), &s_MousePosition); } +void e2d::Input::__add(Listener * pListener) +{ + WARN_IF(pListener == nullptr, "Listener NULL pointer exception!"); + + if (pListener) + { + auto findListener = [](Listener * pListener) -> bool + { + for (const auto &l : s_vListeners) + { + if (pListener == l) + { + return true; + } + } + return false; + }; + + bool bHasListener = findListener(pListener); + WARN_IF(bHasListener, "The listener is already added, cannot be added again!"); + + if (!bHasListener) + { + pListener->retain(); + s_vListeners.push_back(pListener); + } + } +} + +void e2d::Input::add(VoidFunction callback, const String & name) +{ + auto pListener = new Listener(callback, name); + pListener->start(); +} + +void e2d::Input::start(const String & name) +{ + for (const auto & pListener : s_vListeners) + { + if (pListener->getName() == name) + { + pListener->start(); + } + } +} + +void e2d::Input::stop(const String & name) +{ + for (const auto & pListener : s_vListeners) + { + if (pListener->getName() == name) + { + pListener->stop(); + } + } +} + +void e2d::Input::clear(const String & name) +{ + for (const auto & pListener : s_vListeners) + { + if (pListener->getName() == name) + { + pListener->stopAndClear(); + } + } +} + +void e2d::Input::startAll() +{ + for (const auto & pListener : s_vListeners) + { + pListener->start(); + } +} + +void e2d::Input::stopAll() +{ + for (const auto & pListener : s_vListeners) + { + pListener->stop(); + } +} + +void e2d::Input::clearAll() +{ + for (const auto & pListener : s_vListeners) + { + pListener->stopAndClear(); + } +} + +std::vector e2d::Input::get(const String & name) +{ + std::vector vListeners; + for (auto pListener : s_vListeners) + { + if (pListener->getName() == name) + { + vListeners.push_back(pListener); + } + } + return std::move(vListeners); +} + +std::vector e2d::Input::getAll() +{ + return s_vListeners; +} + bool Input::isKeyDown(int nKeyCode) { if (s_KeyBuffer[nKeyCode] & 0x80) diff --git a/core/Common/Image.cpp b/core/Common/Image.cpp index 80c5949c..4ff1d456 100644 --- a/core/Common/Image.cpp +++ b/core/Common/Image.cpp @@ -47,12 +47,6 @@ void e2d::Image::open(const String & strFilePath) m_fSourceClipHeight = m_pBitmap->GetSize().height; } -void e2d::Image::open(const String & strFilePath, double x, double y, double width, double height) -{ - open(strFilePath); - clip(x, y, width, height); -} - void e2d::Image::clip(double x, double y, double width, double height) { if (m_pBitmap) diff --git a/core/Common/Listener.cpp b/core/Common/Listener.cpp new file mode 100644 index 00000000..32c55eb8 --- /dev/null +++ b/core/Common/Listener.cpp @@ -0,0 +1,63 @@ +#include "..\ecommon.h" +#include "..\ebase.h" + +e2d::Listener::Listener() + : m_bRunning(false) + , m_callback(nullptr) + , m_bClear(false) +{ + Input::__add(this); +} + +e2d::Listener::Listener(VoidFunction callback, const String & name) + : m_bRunning(false) + , m_sName(name) + , m_callback(callback) + , m_bClear(false) +{ + Input::__add(this); +} + +void e2d::Listener::start() +{ + m_bRunning = true; +} + +void e2d::Listener::stop() +{ + m_bRunning = false; +} + +void e2d::Listener::stopAndClear() +{ + m_bRunning = false; + m_bClear = true; +} + +bool e2d::Listener::isRunning() +{ + return m_bRunning; +} + +e2d::String e2d::Listener::getName() +{ + return m_sName; +} + +void e2d::Listener::setName(const String & name) +{ + m_sName = name; +} + +void e2d::Listener::setCallback(VoidFunction callback) +{ + m_callback = callback; +} + +void e2d::Listener::update() +{ + if (m_callback) + { + m_callback(); + } +} diff --git a/core/Common/String.cpp b/core/Common/String.cpp index af5c805d..45821af1 100644 --- a/core/Common/String.cpp +++ b/core/Common/String.cpp @@ -173,8 +173,8 @@ e2d::String e2d::String::operator+(const wchar_t *str) e2d::String e2d::String::operator+(const char *str) { - String temp(str); - temp.m_str += m_str; + String temp; + temp.m_str = m_str + ::ConvertAnsi2Wide(str); return std::move(temp); } @@ -201,8 +201,8 @@ e2d::String e2d::operator+(const wchar_t *str1, const e2d::String &str2) e2d::String e2d::operator+(const char *str1, const String &str2) { - String temp(str1); - temp.m_str += str2.m_str; + String temp; + temp.m_str = ::ConvertAnsi2Wide(str1) + str2.m_str; return std::move(temp); } @@ -257,6 +257,21 @@ bool e2d::String::operator<=(const String &str) const return m_str <= str.m_str; } +e2d::String & e2d::String::operator<<(const String &str) +{ + return this->append(str); +} + +e2d::String & e2d::String::operator<<(const wchar_t *str) +{ + return this->append(str); +} + +e2d::String & e2d::String::operator<<(wchar_t *str) +{ + return this->append(str); +} + e2d::String & e2d::String::operator<<(const char * value) { return this->append(value); @@ -393,12 +408,23 @@ int e2d::String::findLastOf(const wchar_t ch) const return index; } +void e2d::String::clear() +{ + m_str.clear(); +} + e2d::String & e2d::String::append(const wchar_t * str) { m_str += str; return *this; } +e2d::String & e2d::String::append(wchar_t * str) +{ + m_str += str; + return *this; +} + e2d::String & e2d::String::append(const char * str) { m_str += ::ConvertAnsi2Wide(str); diff --git a/core/Manager/ActionManager.cpp b/core/Manager/ActionManager.cpp index 87e25771..bce5df29 100644 --- a/core/Manager/ActionManager.cpp +++ b/core/Manager/ActionManager.cpp @@ -15,20 +15,20 @@ void e2d::ActionManager::__update() { auto action = s_vRunningActions[i]; // 获取动作运行状态 - if (action->isRunning()) + if (action->_isEnding()) { - if (!action->_isEnding()) + // 动作已经结束 + action->release(); + action->m_pTarget = nullptr; + s_vRunningActions.erase(s_vRunningActions.begin() + i); + } + else + { + if (action->isRunning()) { // 执行动作 action->_update(); } - else - { - // 动作已经结束 - action->release(); - action->m_pTarget = nullptr; - s_vRunningActions.erase(s_vRunningActions.begin() + i); - } } } } @@ -72,7 +72,7 @@ void e2d::ActionManager::__startAction(Action * pAction, Node * pTargetNode) } } -void e2d::ActionManager::resumeAllActionsBindedWith(Node * pTargetNode) +void e2d::ActionManager::__resumeAllBindedWith(Node * pTargetNode) { if (pTargetNode) { @@ -86,7 +86,7 @@ void e2d::ActionManager::resumeAllActionsBindedWith(Node * pTargetNode) } } -void e2d::ActionManager::pauseAllActionsBindedWith(Node * pTargetNode) +void e2d::ActionManager::__pauseAllBindedWith(Node * pTargetNode) { if (pTargetNode) { @@ -100,7 +100,7 @@ void e2d::ActionManager::pauseAllActionsBindedWith(Node * pTargetNode) } } -void e2d::ActionManager::stopAllActionsBindedWith(Node * pTargetNode) +void e2d::ActionManager::__stopAllBindedWith(Node * pTargetNode) { if (pTargetNode) { @@ -114,7 +114,7 @@ void e2d::ActionManager::stopAllActionsBindedWith(Node * pTargetNode) } } -void e2d::ActionManager::resumeAllActions(const String & strActionName) +void e2d::ActionManager::resume(const String & strActionName) { for (auto action : s_vRunningActions) { @@ -125,7 +125,7 @@ void e2d::ActionManager::resumeAllActions(const String & strActionName) } } -void e2d::ActionManager::pauseAllActions(const String & strActionName) +void e2d::ActionManager::pause(const String & strActionName) { for (auto action : s_vRunningActions) { @@ -136,7 +136,7 @@ void e2d::ActionManager::pauseAllActions(const String & strActionName) } } -void e2d::ActionManager::stopAllActions(const String & strActionName) +void e2d::ActionManager::stop(const String & strActionName) { for (auto action : s_vRunningActions) { @@ -147,7 +147,7 @@ void e2d::ActionManager::stopAllActions(const String & strActionName) } } -void e2d::ActionManager::__clearAllActionsBindedWith(Node * pTargetNode) +void e2d::ActionManager::__clearAllBindedWith(Node * pTargetNode) { if (pTargetNode) { @@ -167,27 +167,27 @@ void e2d::ActionManager::__clearAllActionsBindedWith(Node * pTargetNode) } } -void e2d::ActionManager::resumeAllActions() +void e2d::ActionManager::resumeAll() { for (auto child : SceneManager::getCurrentScene()->getRoot()->getChildren()) { - ActionManager::resumeAllActionsBindedWith(child); + ActionManager::__resumeAllBindedWith(child); } } -void e2d::ActionManager::pauseAllActions() +void e2d::ActionManager::pauseAll() { for (auto child : SceneManager::getCurrentScene()->getRoot()->getChildren()) { - ActionManager::pauseAllActionsBindedWith(child); + ActionManager::__pauseAllBindedWith(child); } } -void e2d::ActionManager::stopAllActions() +void e2d::ActionManager::stopAll() { for (auto child : SceneManager::getCurrentScene()->getRoot()->getChildren()) { - ActionManager::stopAllActionsBindedWith(child); + ActionManager::__stopAllBindedWith(child); } } diff --git a/core/Manager/MusicManager.cpp b/core/Manager/MusicManager.cpp index 9f0ef947..01a9530b 100644 --- a/core/Manager/MusicManager.cpp +++ b/core/Manager/MusicManager.cpp @@ -96,7 +96,7 @@ e2d::Music * e2d::MusicManager::get(const String & strFilePath) return nullptr; } -void e2d::MusicManager::pauseAllMusics() +void e2d::MusicManager::pauseAll() { for (auto iter : getMusicList()) { @@ -104,7 +104,7 @@ void e2d::MusicManager::pauseAllMusics() } } -void e2d::MusicManager::resumeAllMusics() +void e2d::MusicManager::resumeAll() { for (auto iter : getMusicList()) { @@ -112,7 +112,7 @@ void e2d::MusicManager::resumeAllMusics() } } -void e2d::MusicManager::stopAllMusics() +void e2d::MusicManager::stopAll() { for (auto iter : getMusicList()) { diff --git a/core/Manager/SceneManager.cpp b/core/Manager/SceneManager.cpp index 3a224e21..fc56ba52 100644 --- a/core/Manager/SceneManager.cpp +++ b/core/Manager/SceneManager.cpp @@ -1,7 +1,6 @@ #include "..\emanagers.h" #include "..\ebase.h" #include "..\etransitions.h" -#include static e2d::Scene * s_pCurrentScene = nullptr; static e2d::Scene * s_pNextScene = nullptr; @@ -77,6 +76,11 @@ e2d::Scene * e2d::SceneManager::getCurrentScene() return s_pCurrentScene; } +std::stack e2d::SceneManager::getSceneStack() +{ + return s_SceneStack; +} + bool e2d::SceneManager::isTransitioning() { return s_pTransition != nullptr; diff --git a/core/Manager/TimerManager.cpp b/core/Manager/TimerManager.cpp index 165e5553..9cc57a72 100644 --- a/core/Manager/TimerManager.cpp +++ b/core/Manager/TimerManager.cpp @@ -85,7 +85,7 @@ void e2d::TimerManager::stop(const String & name) } } -void e2d::TimerManager::stopAndClear(const String & name) +void e2d::TimerManager::clear(const String & name) { for (auto timer : s_vTimers) { @@ -96,7 +96,7 @@ void e2d::TimerManager::stopAndClear(const String & name) } } -std::vector e2d::TimerManager::getTimers(const String & name) +std::vector e2d::TimerManager::get(const String & name) { std::vector vTimers; for (auto timer : s_vTimers) @@ -109,7 +109,7 @@ std::vector e2d::TimerManager::getTimers(const String & name) return std::move(vTimers); } -void e2d::TimerManager::startAllTimers() +void e2d::TimerManager::startAll() { for (auto timer : s_vTimers) { @@ -117,7 +117,7 @@ void e2d::TimerManager::startAllTimers() } } -void e2d::TimerManager::stopAllTimers() +void e2d::TimerManager::stopAll() { for (auto timer : s_vTimers) { @@ -125,7 +125,7 @@ void e2d::TimerManager::stopAllTimers() } } -void e2d::TimerManager::stopAndClearAllTimers() +void e2d::TimerManager::stopAndClearAll() { for (auto timer : s_vTimers) { @@ -135,7 +135,7 @@ void e2d::TimerManager::stopAndClearAllTimers() s_vTimers.clear(); } -std::vector e2d::TimerManager::getAllTimers() +std::vector e2d::TimerManager::getAll() { return s_vTimers; } diff --git a/core/Node/Node.cpp b/core/Node/Node.cpp index bdc854ab..616922ee 100644 --- a/core/Node/Node.cpp +++ b/core/Node/Node.cpp @@ -46,7 +46,7 @@ e2d::Node::Node() e2d::Node::~Node() { - ActionManager::__clearAllActionsBindedWith(this); + ActionManager::__clearAllBindedWith(this); ShapeManager::__delShape(m_pShape); for (auto child : m_vChildren) { @@ -614,7 +614,23 @@ e2d::Scene * e2d::Node::getParentScene() const return m_pParentScene; } -std::vector& e2d::Node::getChildren() +std::vector e2d::Node::getChildren(const String & name) +{ + std::vector vChildren; + unsigned int hash = name.getHashCode(); + + for (auto child : m_vChildren) + { + // 不同的名称可能会有相同的 Hash 值,但是先比较 Hash 可以提升搜索速度 + if (child->m_nHashName == hash && child->m_sName == name) + { + vChildren.push_back(child); + } + } + return std::move(vChildren); +} + +std::vector e2d::Node::getChildren() { return m_vChildren; } @@ -624,33 +640,6 @@ int e2d::Node::getChildrenCount() const return static_cast(m_vChildren.size()); } -e2d::Node * e2d::Node::getChild(const String & name) -{ - WARN_IF(name.isEmpty(), "Invalid Node name."); - - unsigned int hash = name.getHashCode(); - - for (auto child : m_vChildren) - { - // 不同的名称可能会有相同的 Hash 值,但是先比较 Hash 可以提升搜索速度 - if (child->m_nHashName == hash && child->m_sName == name) - return child; - } - return nullptr; -} - -std::vector e2d::Node::getChildren(const String & name) -{ - std::vector vChildren; - unsigned int hash = name.getHashCode(); - - for (auto child : m_vChildren) - if (child->m_nHashName == hash && child->m_sName == name) - vChildren.push_back(child); - - return std::move(vChildren); -} - void e2d::Node::removeFromParent() { if (m_pParent) @@ -833,15 +822,9 @@ std::vector e2d::Node::getActions(const String & strActionName) bool e2d::Node::isPointIn(Point point) const { - // 为节点创建一个形状 - ID2D1RectangleGeometry * rect; - Renderer::getID2D1Factory()->CreateRectangleGeometry( - D2D1::RectF(0, 0, m_fWidth, m_fHeight), - &rect - ); // 判断点是否在形状内 BOOL ret = 0; - rect->FillContainsPoint( + this->m_pShape->_getD2dGeometry()->FillContainsPoint( D2D1::Point2F( static_cast(point.x), static_cast(point.y)), @@ -853,46 +836,39 @@ bool e2d::Node::isPointIn(Point point) const { return true; } - else - { - for (auto child : m_vChildren) - if (child->isPointIn(point)) - return true; - } + + // 判断点是否在子节点内 + for (auto child : m_vChildren) + if (child->isPointIn(point)) + return true; + return false; } -bool e2d::Node::isIntersectWith(Node * pNode) const +bool e2d::Node::isIntersectWith(const Node * pNode) const { - ID2D1RectangleGeometry * pRect1; - ID2D1RectangleGeometry * pRect2; - ID2D1TransformedGeometry * pShape; - D2D1_GEOMETRY_RELATION relation; + if (this->m_pShape && pNode->m_pShape) + { + int relation = this->m_pShape->getRelationWith(pNode->m_pShape); + if ((relation != Relation::UNKNOWN) && + (relation != Relation::DISJOINT)) + { + return true; + } + } - // 根据自身大小位置创建矩形 - Renderer::getID2D1Factory()->CreateRectangleGeometry( - D2D1::RectF(0, 0, m_fWidth, m_fHeight), - &pRect1 - ); - // 根据二维矩阵进行转换 - Renderer::getID2D1Factory()->CreateTransformedGeometry( - pRect1, - this->m_MatriFinal, - &pShape - ); - // 根据相比较节点的大小位置创建矩形 - Renderer::getID2D1Factory()->CreateRectangleGeometry( - D2D1::RectF(0, 0, pNode->m_fWidth, pNode->m_fHeight), - &pRect2 - ); - // 获取相交状态 - pShape->CompareWithGeometry( - pRect2, - pNode->m_MatriFinal, - &relation - ); - return (relation != D2D1_GEOMETRY_RELATION::D2D1_GEOMETRY_RELATION_UNKNOWN) && - (relation != D2D1_GEOMETRY_RELATION::D2D1_GEOMETRY_RELATION_DISJOINT); + // 判断和其子节点是否相交 + for (auto child : pNode->m_vChildren) + if (this->isIntersectWith(child)) + return true; + + // 判断子节点和其是否相交 + for (auto child : m_vChildren) + if (child->isIntersectWith(pNode)) + return true; + + // 都不相交,返回 false + return false; } void e2d::Node::setAutoUpdate(bool bAutoUpdate) @@ -913,17 +889,17 @@ void e2d::Node::setDefaultShapeEnable(bool bEnable) void e2d::Node::resumeAllActions() { - ActionManager::resumeAllActionsBindedWith(this); + ActionManager::__resumeAllBindedWith(this); } void e2d::Node::pauseAllActions() { - ActionManager::pauseAllActionsBindedWith(this); + ActionManager::__pauseAllBindedWith(this); } void e2d::Node::stopAllActions() { - ActionManager::stopAllActionsBindedWith(this); + ActionManager::__stopAllBindedWith(this); } void e2d::Node::setVisiable(bool value) diff --git a/core/Tool/Data.cpp b/core/Tool/Data.cpp index 32b5f34e..669486d8 100644 --- a/core/Tool/Data.cpp +++ b/core/Tool/Data.cpp @@ -1,49 +1,68 @@ #include "..\etools.h" +static e2d::String s_sDefaultFileName = L"DefaultData.ini"; -void e2d::Data::saveInt(const String & key, int value) +void e2d::Data::saveInt(const String & key, int value, const String & fileName) { - ::WritePrivateProfileString(L"Default", key, String::toString(value), File::getDefaultSavePath()); + ::WritePrivateProfileString(L"Default", key, String::toString(value), Data::getDataFilePath(fileName)); } -void e2d::Data::saveDouble(const String & key, double value) +void e2d::Data::saveDouble(const String & key, double value, const String & fileName) { - ::WritePrivateProfileString(L"Default", key, String::toString(value), File::getDefaultSavePath()); + ::WritePrivateProfileString(L"Default", key, String::toString(value), Data::getDataFilePath(fileName)); } -void e2d::Data::saveBool(const String & key, bool value) +void e2d::Data::saveBool(const String & key, bool value, const String & fileName) { const wchar_t* sValue = value ? L"1" : L"0"; - ::WritePrivateProfileString(L"Default", key, sValue, File::getDefaultSavePath()); + ::WritePrivateProfileString(L"Default", key, sValue, Data::getDataFilePath(fileName)); } -void e2d::Data::saveString(const String & key, const String & value) +void e2d::Data::saveString(const String & key, const String & value, const String & fileName) { - ::WritePrivateProfileString(L"Default", key, value, File::getDefaultSavePath()); + ::WritePrivateProfileString(L"Default", key, value, Data::getDataFilePath(fileName)); } -int e2d::Data::getInt(const String & key, int defaultValue) +int e2d::Data::getInt(const String & key, int defaultValue, const String & fileName) { - return ::GetPrivateProfileInt(L"Default", key, defaultValue, File::getDefaultSavePath()); + return ::GetPrivateProfileInt(L"Default", key, defaultValue, Data::getDataFilePath(fileName)); } -double e2d::Data::getDouble(const String & key, double defaultValue) +double e2d::Data::getDouble(const String & key, double defaultValue, const String & fileName) { wchar_t temp[32] = { 0 }; - ::GetPrivateProfileString(L"Default", key, String::toString(defaultValue), temp, 31, File::getDefaultSavePath()); + ::GetPrivateProfileString(L"Default", key, String::toString(defaultValue), temp, 31, Data::getDataFilePath(fileName)); return std::stof(temp); } -bool e2d::Data::getBool(const String & key, bool defaultValue) +bool e2d::Data::getBool(const String & key, bool defaultValue, const String & fileName) { int nDefaultValue = defaultValue ? 1 : 0; - int nValue = ::GetPrivateProfileInt(L"Default", key, nDefaultValue, File::getDefaultSavePath()); + int nValue = ::GetPrivateProfileInt(L"Default", key, nDefaultValue, Data::getDataFilePath(fileName)); return nValue != 0; } -e2d::String e2d::Data::getString(const String & key, const String & defaultValue) +e2d::String e2d::Data::getString(const String & key, const String & defaultValue, const String & fileName) { wchar_t temp[256] = { 0 }; - ::GetPrivateProfileString(L"Default", key, defaultValue, temp, 255, File::getDefaultSavePath()); + ::GetPrivateProfileString(L"Default", key, defaultValue, temp, 255, Data::getDataFilePath(fileName)); return temp; } + +void e2d::Data::setDefaultFileName(const String & fileName) +{ + if (!fileName.isEmpty()) + { + s_sDefaultFileName.clear(); + s_sDefaultFileName << fileName << L".ini"; + } +} + +e2d::String e2d::Data::getDataFilePath(const String & fileName) +{ + if (fileName.isEmpty()) + { + return Path::getDefaultSavePath() + s_sDefaultFileName; + } + return Path::getDefaultSavePath() + fileName + L".ini"; +} diff --git a/core/Tool/File.cpp b/core/Tool/File.cpp index 53b7650d..bb33a671 100644 --- a/core/Tool/File.cpp +++ b/core/Tool/File.cpp @@ -9,7 +9,7 @@ DEFINE_KNOWN_FOLDER(FOLDERID_LocalAppData, 0xF1B32785, 0x6FBA, 0x4FCF, 0x9D, 0x55, 0x7B, 0x8E, 0x7F, 0x15, 0x70, 0x91); -e2d::String e2d::File::getLocalAppDataPath() +e2d::String e2d::Path::getLocalAppDataPath() { typedef HRESULT(WINAPI* pFunSHGetKnownFolderPath)(const GUID& rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath); @@ -28,39 +28,74 @@ e2d::String e2d::File::getLocalAppDataPath() return L""; } -e2d::String e2d::File::getTempPath() +e2d::String e2d::Path::getTempPath() { // 获取临时文件目录 wchar_t path[_MAX_PATH]; - ::GetTempPath(_MAX_PATH, path); + if (0 == ::GetTempPath(_MAX_PATH, path)) + { + return L""; + } // 创建临时文件目录 - e2d::String tempFilePath = path + e2d::Game::getAppName(); - if (::_waccess(tempFilePath, 0) == -1) + e2d::String tempFilePath; + tempFilePath << path << L"Easy2DGameTemp"; + // 创建文件夹 + if (!Path::createFolder(tempFilePath)) { - ::_wmkdir(tempFilePath); + return path; } - return tempFilePath; + + // 获取 AppName + String sAppName = Game::getAppName(); + if (!sAppName.isEmpty()) + { + // 创建文件夹 + if (!Path::createFolder(tempFilePath + L"\\" + sAppName)) + { + return std::move(tempFilePath); + } + tempFilePath << L"\\" << sAppName; + } + tempFilePath << L"\\"; + return std::move(tempFilePath); } -e2d::String e2d::File::getDefaultSavePath() +e2d::String e2d::Path::getDefaultSavePath() { - String path = File::getLocalAppDataPath(); - WARN_IF(path.isEmpty(), "Cannot get local AppData path!"); + // 获取 AppData 路径 + String path = Path::getLocalAppDataPath(); - path += L"\\" + Game::getAppName(); - - if (::_waccess(path, 0) == -1) + if (path.isEmpty()) { - ::_wmkdir(path); + WARN_IF(true, "Cannot get local AppData path!"); + return std::move(path); } + + // 创建文件夹 + if (!Path::createFolder(path + L"\\Easy2DGameData")) + { + return std::move(path); + } + path << L"\\Easy2DGameData"; - path += L"\\DefaultData.ini"; - - return path; + // 获取 AppName + String sAppName = Game::getAppName(); + if (!sAppName.isEmpty()) + { + // 创建文件夹 + if (!Path::createFolder(path + L"\\" + sAppName)) + { + return std::move(path); + } + path << L"\\" << sAppName; + } + path << L"\\"; + + return std::move(path); } -e2d::String e2d::File::getFileExtension(const String & filePath) +e2d::String e2d::Path::getFileExtension(const String & filePath) { String fileExtension; // 找到文件名中的最后一个 '.' 的位置 @@ -77,7 +112,7 @@ e2d::String e2d::File::getFileExtension(const String & filePath) return fileExtension; } -e2d::String e2d::File::getSaveFilePath(const String & title, const String & defExt) +e2d::String e2d::Path::getSaveFilePath(const String & title, const String & defExt) { // 弹出保存对话框 OPENFILENAME ofn = { 0 }; @@ -98,4 +133,22 @@ e2d::String e2d::File::getSaveFilePath(const String & title, const String & defE return strFilename; } return L""; -} \ No newline at end of file +} + +bool e2d::Path::createFolder(const String & strDirPath) +{ + if (strDirPath.isEmpty()) + { + WARN_IF(true, "Path::createFolder Failed: Invalid directory path!"); + return false; + } + + if (-1 == ::_waccess(strDirPath, 0)) + { + if (0 != ::_wmkdir(strDirPath)) + { + return false; + } + } + return true; +} diff --git a/core/ebase.h b/core/ebase.h index c3743763..9e3fdaf7 100644 --- a/core/ebase.h +++ b/core/ebase.h @@ -148,8 +148,47 @@ private: class Input { friend Game; + friend Listener; public: + // 添加输入监听 + static void add( + VoidFunction callback, /* 回调函数 */ + const String & name = L"" /* 监听器名称 */ + ); + + // 启动输入监听 + static void start( + const String & name + ); + + // 停止输入监听 + static void stop( + const String & name + ); + + // 清除输入监听 + static void clear( + const String & name + ); + + // 启动所有监听器 + static void startAll(); + + // 停止所有监听器 + static void stopAll(); + + // 清除所有监听器 + static void clearAll(); + + // 获取监听器 + static std::vector get( + const String & name + ); + + // 获取全部监听器 + static std::vector getAll(); + // 检测键盘某按键是否正被按下 static bool isKeyDown( int nKeyCode @@ -214,9 +253,17 @@ private: // 初始化 DirectInput 以及键盘鼠标设备 static bool __init(); - // 获得输入信息 + // 刷新输入信息 + static void __update(); + + // 刷新设备状态 static void __updateDeviceState(); + // 添加输入监听 + static void __add( + Listener * pListener + ); + // 卸载 DirectInput static void __uninit(); }; diff --git a/core/ecommon.h b/core/ecommon.h index 885aa484..205a5a7f 100644 --- a/core/ecommon.h +++ b/core/ecommon.h @@ -1,5 +1,6 @@ #pragma once #include "emacros.h" +#include #include #include #include @@ -8,6 +9,37 @@ namespace e2d { +// 返回值和参数列表都为空的函数 +typedef std::function VoidFunction; + +// 定时器回调函数 +typedef VoidFunction TimerCallback; + +// 按钮点击回调函数 +typedef VoidFunction ButtonCallback; + +template +inline VoidFunction CreateCallback(Func&& func) +{ + return std::bind(func); +} + +template +inline VoidFunction CreateCallback(Object&& obj, Func&& func) +{ + return std::bind(func, obj); +} + +template +inline void SafeDelete(T** p) { if (*p) { delete *p; *p = nullptr; } } + +template +inline void SafeRelease(Object** p) { if (*p) { (*p)->release(); *p = nullptr; } } + +template +inline void SafeReleaseInterface(Interface **pp) { if (*pp != nullptr) { (*pp)->Release(); (*pp) = nullptr; } } + + struct Size; // 表示坐标的结构体 @@ -29,6 +61,9 @@ struct Point double y; // Y 坐标 }; +// 二维向量 +typedef Point Vector; + // 表示大小的结构体 struct Size { @@ -75,6 +110,11 @@ public: const wchar_t *str ); + // 后接字符串 + String& append( + wchar_t *str + ); + // 后接字符串 String& append( const String &str @@ -106,6 +146,9 @@ public: const wchar_t ch ) const; + // 清空字符串 + void clear(); + // 获取大写字符串 String toUpper() const; @@ -163,6 +206,9 @@ public: bool operator< (const String &) const; bool operator<= (const String &) const; + String& operator<< (const String &); + String& operator<< (const wchar_t *); + String& operator<< (wchar_t *); template String& operator<< (const T value) { return this->append<>(value); } @@ -516,15 +562,6 @@ public: const String & strFilePath ); - // 从本地文件中读取图片并裁剪 - void open( - const String & strFilePath,/* 图片文件路径 */ - double nClipX, /* 裁剪位置 X 坐标 */ - double nClipY, /* 裁剪位置 Y 坐标 */ - double nClipWidth, /* 裁剪宽度 */ - double nClipHeight /* 裁剪高度 */ - ); - // 裁剪图片 void clip( double nClipX, /* 裁剪位置 X 坐标 */ @@ -565,7 +602,7 @@ public: // 预加载资源 static bool preload( - const String & sFileName /* 图片文件路径 */ + const String & strFileName /* 图片文件路径 */ ); // 清空缓存 @@ -653,30 +690,55 @@ protected: }; -// 二维向量 -typedef Point Vector; +class Input; -// 返回值和参数列表都为空的函数 -typedef std::function VoidFunction; +// 监听器 +class Listener + : public Object +{ + friend Input; -// 定时器回调函数 -typedef VoidFunction TimerCallback; +public: + Listener(); -// 按钮点击回调函数 -typedef VoidFunction ButtonCallback; + Listener( + VoidFunction callback, /* 回调函数 */ + const String & name = L"" /* 监听器名称 */ + ); -#ifndef CreateCallback - #define CreateCallback(pointer, func) std::bind(&func, pointer) -#endif + // 启动 + void start(); + // 停止 + void stop(); -template -inline void SafeDelete(T** p) { if (*p) { delete *p; *p = nullptr; } } + // 停止并清除 + void stopAndClear(); -template -inline void SafeRelease(Object** p) { if (*p) { (*p)->release(); *p = nullptr; } } + // 获取运行状态 + bool isRunning(); -template -inline void SafeReleaseInterface(Interface **pp) { if (*pp != nullptr) { (*pp)->Release(); (*pp) = nullptr; } } + // 获取名称 + String getName(); + + // 修改名称 + void setName( + const String & name + ); + + // 修改回调函数 + void setCallback( + VoidFunction callback + ); + + // 更新 + void update(); + +protected: + String m_sName; + bool m_bRunning; + bool m_bClear; + VoidFunction m_callback; +}; } \ No newline at end of file diff --git a/core/emanagers.h b/core/emanagers.h index 5c1e5d9d..d7d1c5f0 100644 --- a/core/emanagers.h +++ b/core/emanagers.h @@ -64,6 +64,9 @@ public: // 获取当前场景 static Scene * getCurrentScene(); + // 获取场景栈 + static std::stack getSceneStack(); + // 是否正在进行转场动画 static bool isTransitioning(); @@ -107,26 +110,26 @@ public: ); // 删除具有相同名称的定时器 - static void stopAndClear( + static void clear( const String &name ); // 获取名称相同的定时器 - static std::vector getTimers( + static std::vector get( const String & name ); // 启动所有定时器 - static void startAllTimers(); + static void startAll(); // 停止所有定时器 - static void stopAllTimers(); + static void stopAll(); // 停止并清除所有定时器 - static void stopAndClearAllTimers(); + static void stopAndClearAll(); // 获取所有定时器 - static std::vector getAllTimers(); + static std::vector getAll(); private: // 更新定时器 @@ -154,43 +157,28 @@ class ActionManager public: // 继续名称相同的所有动作 - static void resumeAllActions( + static void resume( const String & strActionName ); // 暂停名称相同的所有动作 - static void pauseAllActions( + static void pause( const String & strActionName ); // 停止名称相同的所有动作 - static void stopAllActions( + static void stop( const String & strActionName ); - // 继续绑定在节点上的所有动作 - static void resumeAllActionsBindedWith( - Node * pTargetNode - ); - - // 暂停绑定在节点上的所有动作 - static void pauseAllActionsBindedWith( - Node * pTargetNode - ); - - // 停止绑定在节点上的所有动作 - static void stopAllActionsBindedWith( - Node * pTargetNode - ); - // 继续所有动作 - static void resumeAllActions(); + static void resumeAll(); // 暂停所有动作 - static void pauseAllActions(); + static void pauseAll(); // 停止所有动作 - static void stopAllActions(); + static void stopAll(); // 获取所有名称相同的动作 static std::vector getActions( @@ -220,8 +208,23 @@ private: Node * pTargetNode ); + // 继续绑定在节点上的所有动作 + static void __resumeAllBindedWith( + Node * pTargetNode + ); + + // 暂停绑定在节点上的所有动作 + static void __pauseAllBindedWith( + Node * pTargetNode + ); + + // 停止绑定在节点上的所有动作 + static void __stopAllBindedWith( + Node * pTargetNode + ); + // 清空绑定在节点上的所有动作 - static void __clearAllActionsBindedWith( + static void __clearAllBindedWith( Node * pTargetNode ); @@ -268,13 +271,13 @@ public: ); // 暂停所有音乐 - static void pauseAllMusics(); + static void pauseAll(); // 继续播放所有音乐 - static void resumeAllMusics(); + static void resumeAll(); // 停止所有音乐 - static void stopAllMusics(); + static void stopAll(); // 获取 IXAudio2 对象 static IXAudio2 * getIXAudio2(); diff --git a/core/enodes.h b/core/enodes.h index a933bb64..aab76fca 100644 --- a/core/enodes.h +++ b/core/enodes.h @@ -52,7 +52,7 @@ public: // 判断两节点是否相交 virtual bool isIntersectWith( - Node * pNode + const Node * pNode ) const; // 获取节点名称 @@ -121,18 +121,13 @@ public: // 获取节点所在场景 virtual Scene * getParentScene() const; - // 获取名称相同的子节点 - virtual Node * getChild( - const String & name - ); - // 获取所有名称相同的子节点 virtual std::vector getChildren( const String & name ); // 获取所有子节点 - virtual std::vector &getChildren(); + virtual std::vector getChildren(); // 获取子节点数量 virtual int getChildrenCount() const; @@ -467,16 +462,16 @@ public: ); virtual ~Sprite(); - - // 加载精灵图片 - virtual void open( - Image * texture - ); // 从本地文件加载图片 virtual void open( const String & imageFileName ); + + // 加载图片 + virtual void open( + Image * image + ); // 裁剪图片 virtual void clip( diff --git a/core/etools.h b/core/etools.h index 44712b77..f72a50e1 100644 --- a/core/etools.h +++ b/core/etools.h @@ -133,59 +133,77 @@ public: // 保存 int 类型的值 static void saveInt( const String & key, - int value + int value, + const String & fileName = L"" ); // 保存 double 类型的值 static void saveDouble( const String & key, - double value + double value, + const String & fileName = L"" ); // 保存 bool 类型的值 static void saveBool( const String & key, - bool value + bool value, + const String & fileName = L"" ); // 保存 字符串 类型的值 static void saveString( const String & key, - const String & value + const String & value, + const String & fileName = L"" ); // 获取 int 类型的值 // (若不存在则返回 defaultValue 参数的值) static int getInt( const String & key, - int defaultValue + int defaultValue, + const String & fileName = L"" ); // 获取 double 类型的值 // (若不存在则返回 defaultValue 参数的值) static double getDouble( const String & key, - double defaultValue + double defaultValue, + const String & fileName = L"" ); // 获取 bool 类型的值 // (若不存在则返回 defaultValue 参数的值) static bool getBool( const String & key, - bool defaultValue + bool defaultValue, + const String & fileName = L"" ); // 获取 字符串 类型的值 // (若不存在则返回 defaultValue 参数的值) static String getString( const String & key, - const String & defaultValue + const String & defaultValue, + const String & fileName = L"" + ); + + // 修改数据文件的默认名称 + static void setDefaultFileName( + const String & fileName + ); + + // 获取数据文件的完整路径 + static String getDataFilePath( + const String & fileName ); }; -// 文件管理工具 -class File +// 路径工具 +class Path { public: // 获取系统的 AppData Local 路径 @@ -194,7 +212,7 @@ public: // 获取临时文件目录 static String getTempPath(); - // 获取默认的保存路径 + // 获取数据的默认保存路径 static String getDefaultSavePath(); // 获取文件扩展名 @@ -207,6 +225,11 @@ public: const String & title = L"保存到", /* 对话框标题 */ const String & defExt = L"" /* 默认扩展名 */ ); + + // 创建文件夹 + static bool createFolder( + const String & strDirPath /* 文件夹路径 */ + ); }; diff --git a/project/vs2012/Easy2D.vcxproj b/project/vs2012/Easy2D.vcxproj index fd82e125..218faad9 100644 --- a/project/vs2012/Easy2D.vcxproj +++ b/project/vs2012/Easy2D.vcxproj @@ -53,6 +53,7 @@ + diff --git a/project/vs2012/Easy2D.vcxproj.filters b/project/vs2012/Easy2D.vcxproj.filters index aeb84b3b..4a916b8c 100644 --- a/project/vs2012/Easy2D.vcxproj.filters +++ b/project/vs2012/Easy2D.vcxproj.filters @@ -197,5 +197,8 @@ Common + + Common + \ No newline at end of file diff --git a/project/vs2013/Easy2D.vcxproj b/project/vs2013/Easy2D.vcxproj index 3b4c867b..0c57d807 100644 --- a/project/vs2013/Easy2D.vcxproj +++ b/project/vs2013/Easy2D.vcxproj @@ -192,6 +192,7 @@ + diff --git a/project/vs2013/Easy2D.vcxproj.filters b/project/vs2013/Easy2D.vcxproj.filters index 778a987a..dd2611c1 100644 --- a/project/vs2013/Easy2D.vcxproj.filters +++ b/project/vs2013/Easy2D.vcxproj.filters @@ -198,5 +198,8 @@ Common + + Common + \ No newline at end of file diff --git a/project/vs2017/Easy2D.vcxproj b/project/vs2017/Easy2D.vcxproj index 6d0d5d6f..15de7b6a 100644 --- a/project/vs2017/Easy2D.vcxproj +++ b/project/vs2017/Easy2D.vcxproj @@ -212,6 +212,7 @@ + diff --git a/project/vs2017/Easy2D.vcxproj.filters b/project/vs2017/Easy2D.vcxproj.filters index 8e16089b..6116fceb 100644 --- a/project/vs2017/Easy2D.vcxproj.filters +++ b/project/vs2017/Easy2D.vcxproj.filters @@ -186,6 +186,9 @@ Common + + Common +