From 1744e25efe65d0f6370a3bc58ea189766429651b Mon Sep 17 00:00:00 2001 From: Nomango <569629550@qq.com> Date: Sat, 28 Oct 2017 18:48:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=A2=B0=E6=92=9E=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E7=9B=91=E5=90=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Easy2D/Base/EApp.cpp | 1 + Easy2D/Base/EScene.cpp | 12 +- Easy2D/Common/EKeyboardMsg.cpp | 15 +- Easy2D/Common/EMouseMsg.cpp | 29 ++-- Easy2D/Easy2D.vcxproj | 2 + Easy2D/Easy2D.vcxproj.filters | 6 + Easy2D/Geometry/ECircle.cpp | 2 + Easy2D/Geometry/EEllipse.cpp | 2 + Easy2D/Geometry/EGeometry.cpp | 39 +++-- Easy2D/Geometry/EPhysicsMsg.cpp | 20 +++ Easy2D/Geometry/ERectangle.cpp | 6 +- Easy2D/Listener/ECollisionListener.cpp | 37 +++++ Easy2D/Listener/EKeyboardListener.cpp | 6 +- Easy2D/Listener/EMouseListener.cpp | 6 +- Easy2D/Listener/EPhysicsListener.cpp | 59 +++++++ Easy2D/Manager/EMsgManager.cpp | 12 +- Easy2D/Manager/EPhysicsManager.cpp | 218 ++++++++++++++++++++++++- Easy2D/Manager/ETimerManager.cpp | 2 +- Easy2D/Node/ENode.cpp | 24 ++- Easy2D/ebase.h | 6 - Easy2D/ecommon.h | 68 ++++---- Easy2D/egeometry.h | 45 ++++- Easy2D/elisteners.h | 85 +++++++++- Easy2D/emanagers.h | 84 +++++++++- Easy2D/enodes.h | 1 + 25 files changed, 661 insertions(+), 126 deletions(-) create mode 100644 Easy2D/Geometry/EPhysicsMsg.cpp create mode 100644 Easy2D/Listener/EPhysicsListener.cpp diff --git a/Easy2D/Base/EApp.cpp b/Easy2D/Base/EApp.cpp index e15455e6..8b16f58d 100644 --- a/Easy2D/Base/EApp.cpp +++ b/Easy2D/Base/EApp.cpp @@ -348,6 +348,7 @@ void e2d::EApp::_onControl() ETimerManager::TimerProc(); // 定时器管理器执行程序 EActionManager::ActionProc(); // 动作管理器执行程序 + EPhysicsManager::PhysicsProc(); // 物理引擎执行程序 EObjectManager::__flush(); // 刷新内存池 } diff --git a/Easy2D/Base/EScene.cpp b/Easy2D/Base/EScene.cpp index 2ab3c1ed..0dd21ab8 100644 --- a/Easy2D/Base/EScene.cpp +++ b/Easy2D/Base/EScene.cpp @@ -92,14 +92,4 @@ void e2d::EScene::clearAllChildren() void e2d::EScene::runAction(EAction * action) { this->m_pRoot->runAction(action); -} - -void e2d::EScene::bindListener(EMouseListener * listener) -{ - EMsgManager::bindListener(listener, this); -} - -void e2d::EScene::bindListener(EKeyboardListener * listener) -{ - EMsgManager::bindListener(listener, this); -} +} \ No newline at end of file diff --git a/Easy2D/Common/EKeyboardMsg.cpp b/Easy2D/Common/EKeyboardMsg.cpp index 64f54c1b..ceb6393a 100644 --- a/Easy2D/Common/EKeyboardMsg.cpp +++ b/Easy2D/Common/EKeyboardMsg.cpp @@ -1,20 +1,22 @@ #include "..\ecommon.h" -static e2d::EKeyboardMsg s_KeyboardMsg; +UINT e2d::EKeyboardMsg::s_nMsg = 0; +WPARAM e2d::EKeyboardMsg::s_wParam = 0; +LPARAM e2d::EKeyboardMsg::s_lParam = 0; e2d::EKeyboardMsg::KEYBOARD_MSG e2d::EKeyboardMsg::getMsg() { - return KEYBOARD_MSG(s_KeyboardMsg.m_nMsg); + return KEYBOARD_MSG(EKeyboardMsg::s_nMsg); } e2d::EKeyboardMsg::KEY e2d::EKeyboardMsg::getVal() { - return KEY(s_KeyboardMsg.m_wParam); + return KEY(EKeyboardMsg::s_wParam); } DWORD e2d::EKeyboardMsg::getCount() { - return (((DWORD)s_KeyboardMsg.m_lParam) & 0x0000FFFF); + return (((DWORD)EKeyboardMsg::s_lParam) & 0x0000FFFF); } bool e2d::EKeyboardMsg::isKeyDown(KEY key) @@ -52,8 +54,3 @@ bool e2d::EKeyboardMsg::isScrollLockOn() } return false; } - -e2d::EKeyboardMsg & e2d::EKeyboardMsg::getKeyboardMsg() -{ - return s_KeyboardMsg; -} diff --git a/Easy2D/Common/EMouseMsg.cpp b/Easy2D/Common/EMouseMsg.cpp index efe4110e..3c1ef61d 100644 --- a/Easy2D/Common/EMouseMsg.cpp +++ b/Easy2D/Common/EMouseMsg.cpp @@ -1,58 +1,55 @@ #include "..\ecommon.h" -static e2d::EMouseMsg s_MouseMsg; +UINT e2d::EMouseMsg::s_nMsg = 0; +WPARAM e2d::EMouseMsg::s_wParam = 0; +LPARAM e2d::EMouseMsg::s_lParam = 0; DWORD e2d::EMouseMsg::getPosX() { - return LOWORD(s_MouseMsg.m_lParam); + return LOWORD(EMouseMsg::s_lParam); } DWORD e2d::EMouseMsg::getPosY() { - return HIWORD(s_MouseMsg.m_lParam); + return HIWORD(EMouseMsg::s_lParam); } e2d::EPoint e2d::EMouseMsg::getPos() { - return EPoint(LOWORD(s_MouseMsg.m_lParam), HIWORD(s_MouseMsg.m_lParam)); + return EPoint(LOWORD(EMouseMsg::s_lParam), HIWORD(EMouseMsg::s_lParam)); } bool e2d::EMouseMsg::isLButtonDown() { - return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_LBUTTON; + return GET_KEYSTATE_WPARAM(EMouseMsg::s_wParam) == MK_LBUTTON; } bool e2d::EMouseMsg::isMButtonDown() { - return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_MBUTTON; + return GET_KEYSTATE_WPARAM(EMouseMsg::s_wParam) == MK_MBUTTON; } bool e2d::EMouseMsg::isRButtonDown() { - return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_RBUTTON; + return GET_KEYSTATE_WPARAM(EMouseMsg::s_wParam) == MK_RBUTTON; } bool e2d::EMouseMsg::isShiftDown() { - return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_SHIFT; + return GET_KEYSTATE_WPARAM(EMouseMsg::s_wParam) == MK_SHIFT; } bool e2d::EMouseMsg::isCtrlDown() { - return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_CONTROL; + return GET_KEYSTATE_WPARAM(EMouseMsg::s_wParam) == MK_CONTROL; } DWORD e2d::EMouseMsg::getWheelDelta() { - return GET_WHEEL_DELTA_WPARAM(s_MouseMsg.m_wParam); + return GET_WHEEL_DELTA_WPARAM(EMouseMsg::s_wParam); } e2d::EMouseMsg::MOUSE_MSG e2d::EMouseMsg::getMsg() { - return MOUSE_MSG(s_MouseMsg.m_nMsg); -} - -e2d::EMouseMsg & e2d::EMouseMsg::getMouseMsg() -{ - return s_MouseMsg; + return MOUSE_MSG(EMouseMsg::s_nMsg); } diff --git a/Easy2D/Easy2D.vcxproj b/Easy2D/Easy2D.vcxproj index 2f1a36cb..becac503 100644 --- a/Easy2D/Easy2D.vcxproj +++ b/Easy2D/Easy2D.vcxproj @@ -215,6 +215,7 @@ + @@ -225,6 +226,7 @@ + diff --git a/Easy2D/Easy2D.vcxproj.filters b/Easy2D/Easy2D.vcxproj.filters index edd343c0..8aecb84e 100644 --- a/Easy2D/Easy2D.vcxproj.filters +++ b/Easy2D/Easy2D.vcxproj.filters @@ -204,6 +204,12 @@ Manager + + Listener + + + Geometry + diff --git a/Easy2D/Geometry/ECircle.cpp b/Easy2D/Geometry/ECircle.cpp index cb8aaf55..7b82b345 100644 --- a/Easy2D/Geometry/ECircle.cpp +++ b/Easy2D/Geometry/ECircle.cpp @@ -2,11 +2,13 @@ #include "..\Win\winbase.h" e2d::ECircle::ECircle() + : m_pD2dCircle(nullptr) { this->_setCircle(EPoint(), 0); } e2d::ECircle::ECircle(EPoint center, float radius) + : ECircle() { this->_setCircle(center, radius); } diff --git a/Easy2D/Geometry/EEllipse.cpp b/Easy2D/Geometry/EEllipse.cpp index 7892102f..03cd7fd4 100644 --- a/Easy2D/Geometry/EEllipse.cpp +++ b/Easy2D/Geometry/EEllipse.cpp @@ -2,11 +2,13 @@ #include "..\Win\winbase.h" e2d::EEllipse::EEllipse() + : m_pD2dEllipse(nullptr) { this->_setEllipse(EPoint(), 0, 0); } e2d::EEllipse::EEllipse(EPoint center, float radiusX, float radiusY) + : EEllipse() { this->_setEllipse(center, radiusX, radiusY); } diff --git a/Easy2D/Geometry/EGeometry.cpp b/Easy2D/Geometry/EGeometry.cpp index 44636c8b..867b018e 100644 --- a/Easy2D/Geometry/EGeometry.cpp +++ b/Easy2D/Geometry/EGeometry.cpp @@ -1,28 +1,43 @@ #include "..\egeometry.h" #include "..\Win\winbase.h" +#include "..\enodes.h" e2d::EGeometry::EGeometry() - : m_bTransformed(true) + : m_bTransformNeeded(true) , m_pParentNode(nullptr) + , m_pTransformedGeometry(nullptr) { } -bool e2d::EGeometry::_isCollisionWith(EGeometry * pGeometry) +e2d::ENode * e2d::EGeometry::getParentNode() const +{ + return m_pParentNode; +} + +e2d::EPhysicsMsg::INTERSECT_RELATION e2d::EGeometry::_intersectWith(EGeometry * pGeometry) { D2D1_GEOMETRY_RELATION relation; - HRESULT hr = this->_getD2dGeometry()->CompareWithGeometry( - pGeometry->_getD2dGeometry(), + m_pTransformedGeometry->CompareWithGeometry( + pGeometry->m_pTransformedGeometry, D2D1::Matrix3x2F::Identity(), &relation ); - if (SUCCEEDED(hr)) - { - return (relation == D2D1_GEOMETRY_RELATION::D2D1_GEOMETRY_RELATION_OVERLAP) || - (relation == D2D1_GEOMETRY_RELATION::D2D1_GEOMETRY_RELATION_CONTAINS) || - (relation == D2D1_GEOMETRY_RELATION::D2D1_GEOMETRY_RELATION_IS_CONTAINED); - } + return EPhysicsMsg::INTERSECT_RELATION(relation); +} - return false; -} \ No newline at end of file +void e2d::EGeometry::_transform() +{ + if (m_bTransformNeeded && m_pParentNode) + { + SafeReleaseInterface(&m_pTransformedGeometry); + + GetFactory()->CreateTransformedGeometry( + _getD2dGeometry(), + m_pParentNode->m_Matri, + &m_pTransformedGeometry + ); + } + m_bTransformNeeded = false; +} diff --git a/Easy2D/Geometry/EPhysicsMsg.cpp b/Easy2D/Geometry/EPhysicsMsg.cpp new file mode 100644 index 00000000..745070a7 --- /dev/null +++ b/Easy2D/Geometry/EPhysicsMsg.cpp @@ -0,0 +1,20 @@ +#include "..\egeometry.h" + +e2d::EPhysicsMsg::INTERSECT_RELATION e2d::EPhysicsMsg::s_nRelation = e2d::EPhysicsMsg::INTERSECT_RELATION::UNKNOWN; +e2d::EGeometry * e2d::EPhysicsMsg::s_pActiveGeometry = nullptr; +e2d::EGeometry * e2d::EPhysicsMsg::s_pPassiveGeometry = nullptr; + +e2d::EPhysicsMsg::INTERSECT_RELATION e2d::EPhysicsMsg::getMsg() +{ + return EPhysicsMsg::s_nRelation; +} + +e2d::EGeometry * e2d::EPhysicsMsg::getActiveGeometry() +{ + return EPhysicsMsg::s_pActiveGeometry; +} + +e2d::EGeometry * e2d::EPhysicsMsg::getPassiveGeometry() +{ + return EPhysicsMsg::s_pPassiveGeometry; +} diff --git a/Easy2D/Geometry/ERectangle.cpp b/Easy2D/Geometry/ERectangle.cpp index 0c528a59..4d269ee2 100644 --- a/Easy2D/Geometry/ERectangle.cpp +++ b/Easy2D/Geometry/ERectangle.cpp @@ -3,11 +3,13 @@ #include "..\Win\winbase.h" e2d::ERectangle::ERectangle() + : m_pD2dRectangle(nullptr) { this->_setRect(0, 0, 0, 0); } e2d::ERectangle::ERectangle(float x, float y, float width, float height) + : ERectangle() { this->_setRect(x, y, x + width, y + height); } @@ -16,8 +18,8 @@ e2d::ERectangle::ERectangle(ENode * node) { // 计算左上角坐标 D2D1_POINT_2F upperLeftCorner = D2D1::Point2F( - node->getPosX() - node->getRealWidth() * node->getAnchorX(), - node->getPosY() - node->getRealHeight() * node->getAnchorY() + node->getRealWidth() * node->getAnchorX(), + node->getRealHeight() * node->getAnchorY() ); this->_setRect( upperLeftCorner.x, diff --git a/Easy2D/Listener/ECollisionListener.cpp b/Easy2D/Listener/ECollisionListener.cpp index e69de29b..86bc74df 100644 --- a/Easy2D/Listener/ECollisionListener.cpp +++ b/Easy2D/Listener/ECollisionListener.cpp @@ -0,0 +1,37 @@ +#include "..\elisteners.h" +#include "..\egeometry.h" + +e2d::ECollisionListener::ECollisionListener() + : EPhysicsListener() +{ +} + +e2d::ECollisionListener::ECollisionListener(const EString & name) + : EPhysicsListener(name) +{ +} + +e2d::ECollisionListener::ECollisionListener(const COLLISION_LISTENER_CALLBACK & callback) + : EPhysicsListener() +{ + this->m_Callback = callback; +} + +e2d::ECollisionListener::ECollisionListener(const EString & name, const COLLISION_LISTENER_CALLBACK & callback) + : EPhysicsListener(name) +{ + this->m_Callback = callback; +} + +void e2d::ECollisionListener::_callOn() +{ + if (EPhysicsMsg::getMsg() == EPhysicsMsg::OVERLAP || + EPhysicsMsg::getMsg() == EPhysicsMsg::CONTAINS || + EPhysicsMsg::getMsg() == EPhysicsMsg::IS_CONTAINED) + { + m_Callback( + EPhysicsMsg::getActiveGeometry()->getParentNode(), + EPhysicsMsg::getPassiveGeometry()->getParentNode() + ); + } +} diff --git a/Easy2D/Listener/EKeyboardListener.cpp b/Easy2D/Listener/EKeyboardListener.cpp index 9b4145fa..571dcf00 100644 --- a/Easy2D/Listener/EKeyboardListener.cpp +++ b/Easy2D/Listener/EKeyboardListener.cpp @@ -35,7 +35,7 @@ void e2d::EKeyboardListener::setCallback(const KEY_LISTENER_CALLBACK & callback) void e2d::EKeyboardListener::bindWith(EScene * pParentScene) { - WARN_IF(m_pParentScene != nullptr || m_pParentNode != nullptr, "EListener cannot bind with two object."); + WARN_IF(m_pParentNode != nullptr, "A listener cannot bind with two object."); if (pParentScene) { @@ -45,9 +45,9 @@ void e2d::EKeyboardListener::bindWith(EScene * pParentScene) void e2d::EKeyboardListener::bindWith(ENode * pParentNode) { - WARN_IF(m_pParentScene != nullptr || m_pParentNode != nullptr, "EListener cannot bind with two object."); + WARN_IF(m_pParentNode != nullptr, "A listener cannot bind with two object."); - if (pParentNode != nullptr && m_pParentScene == nullptr) + if (pParentNode) { EMsgManager::bindListener(this, pParentNode); } diff --git a/Easy2D/Listener/EMouseListener.cpp b/Easy2D/Listener/EMouseListener.cpp index ff4f6d72..31c675eb 100644 --- a/Easy2D/Listener/EMouseListener.cpp +++ b/Easy2D/Listener/EMouseListener.cpp @@ -35,7 +35,7 @@ void e2d::EMouseListener::setCallback(const MOUSE_LISTENER_CALLBACK & callback) void e2d::EMouseListener::bindWith(EScene * pParentScene) { - WARN_IF(m_pParentScene != nullptr || m_pParentNode != nullptr, "EListener cannot bind with two object."); + WARN_IF(m_pParentNode != nullptr, "A listener cannot bind with two object."); if (pParentScene) { @@ -45,9 +45,9 @@ void e2d::EMouseListener::bindWith(EScene * pParentScene) void e2d::EMouseListener::bindWith(ENode * pParentNode) { - WARN_IF(m_pParentScene != nullptr || m_pParentNode != nullptr, "EListener cannot bind with two object."); + WARN_IF(m_pParentNode != nullptr, "A listener cannot bind with two object."); - if (pParentNode != nullptr && m_pParentScene == nullptr) + if (pParentNode != nullptr) { EMsgManager::bindListener(this, pParentNode); } diff --git a/Easy2D/Listener/EPhysicsListener.cpp b/Easy2D/Listener/EPhysicsListener.cpp new file mode 100644 index 00000000..60300c2c --- /dev/null +++ b/Easy2D/Listener/EPhysicsListener.cpp @@ -0,0 +1,59 @@ +#include "..\elisteners.h" +#include "..\egeometry.h" +#include "..\emanagers.h" + +e2d::EPhysicsListener::EPhysicsListener() + : EListener() +{ +} + +e2d::EPhysicsListener::EPhysicsListener(const EString & name) + : EListener(name) +{ +} + +e2d::EPhysicsListener::EPhysicsListener(const PHYSICS_LISTENER_CALLBACK & callback) + : EListener() +{ + m_Callback = callback; +} + +e2d::EPhysicsListener::EPhysicsListener(const EString & name, const PHYSICS_LISTENER_CALLBACK & callback) + : EListener(name) +{ + m_Callback = callback; +} + +void e2d::EPhysicsListener::_callOn() +{ + m_Callback( + EPhysicsMsg::getActiveGeometry()->getParentNode(), + EPhysicsMsg::getPassiveGeometry()->getParentNode(), + EPhysicsMsg::getMsg() + ); +} + +void e2d::EPhysicsListener::setCallback(const PHYSICS_LISTENER_CALLBACK & callback) +{ + m_Callback = callback; +} + +void e2d::EPhysicsListener::bindWith(EScene * pParentScene) +{ + WARN_IF(m_pParentNode != nullptr, "A listener cannot bind with two object."); + + if (pParentScene) + { + EPhysicsManager::bindListener(this, pParentScene); + } +} + +void e2d::EPhysicsListener::bindWith(ENode * pParentNode) +{ + WARN_IF(m_pParentNode != nullptr, "A listener cannot bind with two object."); + + if (pParentNode != nullptr) + { + EPhysicsManager::bindListener(this, pParentNode); + } +} diff --git a/Easy2D/Manager/EMsgManager.cpp b/Easy2D/Manager/EMsgManager.cpp index d0286fa9..0ae48324 100644 --- a/Easy2D/Manager/EMsgManager.cpp +++ b/Easy2D/Manager/EMsgManager.cpp @@ -13,9 +13,9 @@ e2d::EVector s_vKeyboardListeners; void e2d::EMsgManager::MouseProc(UINT message, WPARAM wParam, LPARAM lParam) { // 保存鼠标消息 - EMouseMsg::getMouseMsg().m_nMsg = message; - EMouseMsg::getMouseMsg().m_wParam = wParam; - EMouseMsg::getMouseMsg().m_lParam = lParam; + EMouseMsg::s_nMsg = message; + EMouseMsg::s_wParam = wParam; + EMouseMsg::s_lParam = lParam; // 执行鼠标消息监听函数 for (size_t i = 0; i < s_vMouseListeners.size(); i++) { @@ -38,9 +38,9 @@ void e2d::EMsgManager::MouseProc(UINT message, WPARAM wParam, LPARAM lParam) void e2d::EMsgManager::KeyboardProc(UINT message, WPARAM wParam, LPARAM lParam) { // 保存按键消息 - EKeyboardMsg::getKeyboardMsg().m_nMsg = message; - EKeyboardMsg::getKeyboardMsg().m_wParam = wParam; - EKeyboardMsg::getKeyboardMsg().m_lParam = lParam; + EKeyboardMsg::s_nMsg = message; + EKeyboardMsg::s_wParam = wParam; + EKeyboardMsg::s_lParam = lParam; // 执行按键消息监听函数 for (size_t i = 0; i < s_vKeyboardListeners.size(); i++) { diff --git a/Easy2D/Manager/EPhysicsManager.cpp b/Easy2D/Manager/EPhysicsManager.cpp index e46a2366..7d09e2f1 100644 --- a/Easy2D/Manager/EPhysicsManager.cpp +++ b/Easy2D/Manager/EPhysicsManager.cpp @@ -1,26 +1,226 @@ #include "..\emanagers.h" +#include "..\enodes.h" +#include "..\elisteners.h" #include "..\egeometry.h" +// 监听器集合 +e2d::EVector s_vListeners; +// 形状集合 e2d::EVector s_vGeometries; -void e2d::EPhysicsManager::bindWith(EGeometry * geometry, ENode * node) -{ - WARN_IF(geometry == nullptr, "EGeometry NULL pointer exception!"); - WARN_IF(node == nullptr, "EGeometry add to a NULL ENode pointer!"); - if (geometry && node) +void e2d::EPhysicsManager::PhysicsProc() +{ + if (s_vListeners.empty() || s_vGeometries.empty() || EApp::isPaused()) + return; + + // 判断任意两形状间的交集 + for (auto &g1 : s_vGeometries) + { + // 只对进行了变化了对象进行判断 + if (g1->m_bTransformNeeded) + { + // 变化对象 + g1->_transform(); + // g1 为主动方 + EPhysicsMsg::s_pActiveGeometry = g1; + // 判断变化后的状态 + for (auto &g2 : s_vGeometries) + { + if (g1 != g2) + { + // g2 为被动方 + EPhysicsMsg::s_pPassiveGeometry = g2; + // 获取两方的关系 + EPhysicsMsg::s_nRelation = g1->_intersectWith(g2); + // 如果关系不为未知或无交集,响应监听器 + if (EPhysicsMsg::s_nRelation != EPhysicsMsg::UNKNOWN && + EPhysicsMsg::s_nRelation != EPhysicsMsg::DISJOINT) + { + PhysicsListenerProc(); + } + } + } + } + } +} + +void e2d::EPhysicsManager::PhysicsListenerProc() +{ + if (s_vListeners.empty()) return; + + // 执行鼠标消息监听函数 + for (size_t i = 0; i < s_vListeners.size(); i++) + { + auto &listener = s_vListeners[i]; + + if (listener->isRunning()) + { + if (listener->getParentNode() && + listener->getParentNode()->getParentScene() == EApp::getCurrentScene()) + { + listener->_callOn(); + } + } + } +} + +void e2d::EPhysicsManager::bindListener(EPhysicsListener * listener, EScene * pParentScene) +{ + EPhysicsManager::bindListener(listener, pParentScene->getRoot()); +} + +void e2d::EPhysicsManager::bindListener(EPhysicsListener * listener, ENode * pParentNode) +{ + WARN_IF(listener == nullptr, "EPhysicsListener NULL pointer exception!"); + WARN_IF(pParentNode == nullptr, "EPhysicsListener add to a NULL ENode pointer!"); + + if (listener && pParentNode) { ASSERT( - !geometry->m_pParentNode, - "The geometry is already added, it cannot bind again!" + !listener->m_pParentNode, + "The listener is already binded, it cannot bind again!" ); + listener->retain(); + listener->start(); + listener->m_pParentNode = pParentNode; + s_vListeners.push_back(listener); + } +} + +void e2d::EPhysicsManager::addGeometry(EGeometry * geometry) +{ + if (geometry) + { geometry->retain(); - geometry->m_pParentNode = node; s_vGeometries.push_back(geometry); } } -void e2d::EPhysicsManager::PhysicsProc() +void e2d::EPhysicsManager::delGeometry(EGeometry * geometry) { + if (geometry) + { + for (size_t i = 0; i < s_vGeometries.size(); i++) + { + if (s_vGeometries[i] == geometry) + { + SafeReleaseAndClear(&geometry); + s_vGeometries.erase(s_vGeometries.begin() + i); + return; + } + } + } +} + +void e2d::EPhysicsManager::startListeners(const EString & name) +{ + for (auto listener : s_vListeners) + { + if (listener->getName() == name) + { + listener->start(); + } + } +} + +void e2d::EPhysicsManager::stopListeners(const EString & name) +{ + for (auto listener : s_vListeners) + { + if (listener->getName() == name) + { + listener->stop(); + } + } +} + +void e2d::EPhysicsManager::delListeners(const EString & name) +{ + EVector::iterator iter; + for (iter = s_vListeners.begin(); iter != s_vListeners.end();) + { + if ((*iter)->getName() == name) + { + SafeReleaseAndClear(&(*iter)); + iter = s_vListeners.erase(iter); + } + else + { + iter++; + } + } +} + +void e2d::EPhysicsManager::startAllListenersBindedWith(EScene * pParentScene) +{ + EPhysicsManager::startAllListenersBindedWith(pParentScene->getRoot()); +} + +void e2d::EPhysicsManager::stopAllListenersBindedWith(EScene * pParentScene) +{ + EPhysicsManager::stopAllListenersBindedWith(pParentScene->getRoot()); +} + +void e2d::EPhysicsManager::startAllListenersBindedWith(ENode * pParentNode) +{ + for (auto listener : s_vListeners) + { + if (listener->getParentNode() == pParentNode) + { + listener->start(); + } + } + for (auto child : pParentNode->getChildren()) + { + EPhysicsManager::startAllListenersBindedWith(child); + } +} + +void e2d::EPhysicsManager::stopAllListenersBindedWith(ENode * pParentNode) +{ + for (auto listener : s_vListeners) + { + if (listener->getParentNode() == pParentNode) + { + listener->stop(); + } + } + for (auto child : pParentNode->getChildren()) + { + EPhysicsManager::stopAllListenersBindedWith(child); + } +} + +void e2d::EPhysicsManager::startAllListeners() +{ + EPhysicsManager::startAllListenersBindedWith(EApp::getCurrentScene()); +} + +void e2d::EPhysicsManager::stopAllListeners() +{ + EPhysicsManager::stopAllListenersBindedWith(EApp::getCurrentScene()); +} + +void e2d::EPhysicsManager::_clearManager() +{ + s_vListeners.clear(); +} + +void e2d::EPhysicsManager::_clearAllListenersBindedWith(ENode * pParentNode) +{ + for (size_t i = 0; i < s_vListeners.size();) + { + auto listener = s_vListeners[i]; + if (listener->getParentNode() == pParentNode) + { + SafeReleaseAndClear(&listener); + s_vListeners.erase(s_vListeners.begin() + i); + } + else + { + i++; + } + } } diff --git a/Easy2D/Manager/ETimerManager.cpp b/Easy2D/Manager/ETimerManager.cpp index 4c7d1670..2318ef73 100644 --- a/Easy2D/Manager/ETimerManager.cpp +++ b/Easy2D/Manager/ETimerManager.cpp @@ -127,7 +127,7 @@ void e2d::ETimerManager::stopAllTimersBindedWith(ENode * pParentNode) } for (auto child : pParentNode->getChildren()) { - ETimerManager::startAllTimersBindedWith(child); + ETimerManager::stopAllTimersBindedWith(child); } } diff --git a/Easy2D/Node/ENode.cpp b/Easy2D/Node/ENode.cpp index 67a96ec6..95bade46 100644 --- a/Easy2D/Node/ENode.cpp +++ b/Easy2D/Node/ENode.cpp @@ -41,11 +41,12 @@ e2d::ENode::~ENode() EMsgManager::_clearAllMouseListenersBindedWith(this); EMsgManager::_clearAllKeyboardListenersBindedWith(this); EActionManager::_clearAllActionsBindedWith(this); + EPhysicsManager::_clearAllListenersBindedWith(this); + EPhysicsManager::delGeometry(m_pGeometry); for (auto child : m_vChildren) { SafeReleaseAndClear(&child); } - SafeReleaseAndClear(&m_pGeometry); } void e2d::ENode::onEnter() @@ -200,10 +201,14 @@ void e2d::ENode::_updateTransform(ENode * node) { node->m_Matri = node->m_Matri * node->m_pParent->m_Matri; } - // 转换矩阵后判断 // 遍历子节点下的所有节点 node->_updateChildrenTransform(); node->m_bTransformChildrenNeeded = false; + // 绑定于自身的形状也进行相应转换 + if (node->m_pGeometry) + { + node->m_pGeometry->m_bTransformNeeded = true; + } } void e2d::ENode::_updateChildrenOpacity() @@ -474,7 +479,20 @@ void e2d::ENode::setAnchor(float anchorX, float anchorY) void e2d::ENode::setGeometry(EGeometry * geometry) { - EPhysicsManager::bindWith(geometry, this); + // 删除旧的形状 + if (m_pGeometry) + { + EPhysicsManager::delGeometry(m_pGeometry); + } + // 双向绑定 + this->m_pGeometry = geometry; + if (geometry) geometry->m_pParentNode = this; + + if (geometry) + { + m_pGeometry->_transform(); + EPhysicsManager::addGeometry(geometry); + } } void e2d::ENode::addChild(ENode * child, int order /* = 0 */) diff --git a/Easy2D/ebase.h b/Easy2D/ebase.h index 04bbabae..cbed4175 100644 --- a/Easy2D/ebase.h +++ b/Easy2D/ebase.h @@ -298,12 +298,6 @@ public: EAction * action ); - // 绑定鼠标消息监听器 - void bindListener(EMouseListener * listener); - - // 绑定按键消息监听器 - void bindListener(EKeyboardListener * listener); - protected: // 渲染场景画面 void _onRender(); diff --git a/Easy2D/ecommon.h b/Easy2D/ecommon.h index 1de5cf97..d0aa5eae 100644 --- a/Easy2D/ecommon.h +++ b/Easy2D/ecommon.h @@ -111,31 +111,6 @@ template using EVector = std::vector; -// 定时器回调函数(参数为该定时器被调用的次数,从 0 开始) -typedef std::function TIMER_CALLBACK; - -// 按钮点击回调函数 -typedef std::function BUTTON_CLICK_CALLBACK; - -// 按键消息监听回调函数 -typedef std::function KEY_LISTENER_CALLBACK; - -// 鼠标消息监听回调函数 -typedef std::function MOUSE_LISTENER_CALLBACK; - -// 鼠标点击消息监听回调函数(参数为点击位置) -typedef std::function MOUSE_CLICK_LISTENER_CALLBACK; - -// 鼠标按下消息监听回调函数(参数为按下位置) -typedef MOUSE_CLICK_LISTENER_CALLBACK MOUSE_PRESS_LISTENER_CALLBACK; - -// 鼠标双击消息监听回调函数(参数为双击位置) -typedef MOUSE_CLICK_LISTENER_CALLBACK MOUSE_DBLCLK_LISTENER_CALLBACK; - -// 鼠标拖动消息监听函数(参数为拖动前位置和拖动后位置) -typedef std::function MOUSE_DRAG_LISTENER_CALLBACK; - - class EColor { public: @@ -361,13 +336,10 @@ public: // 获取当前鼠标消息类型 static MOUSE_MSG getMsg(); - // 获取当前鼠标消息 - static EMouseMsg & getMouseMsg(); - public: - UINT m_nMsg = 0; - WPARAM m_wParam = 0; - LPARAM m_lParam = 0; + static UINT s_nMsg; + static WPARAM s_wParam; + static LPARAM s_lParam; }; @@ -433,13 +405,35 @@ public: // 获取滑动锁定状态 static bool isScrollLockOn(); - // 获取当前按键消息 - static EKeyboardMsg & getKeyboardMsg(); - public: - UINT m_nMsg = 0; - WPARAM m_wParam = 0; - LPARAM m_lParam = 0; + static UINT s_nMsg; + static WPARAM s_wParam; + static LPARAM s_lParam; }; + +// 定时器回调函数(参数为该定时器被调用的次数,从 0 开始) +typedef std::function TIMER_CALLBACK; + +// 按钮点击回调函数 +typedef std::function BUTTON_CLICK_CALLBACK; + +// 按键消息监听回调函数 +typedef std::function KEY_LISTENER_CALLBACK; + +// 鼠标消息监听回调函数 +typedef std::function MOUSE_LISTENER_CALLBACK; + +// 鼠标点击消息监听回调函数(参数为点击位置) +typedef std::function MOUSE_CLICK_LISTENER_CALLBACK; + +// 鼠标按下消息监听回调函数(参数为按下位置) +typedef MOUSE_CLICK_LISTENER_CALLBACK MOUSE_PRESS_LISTENER_CALLBACK; + +// 鼠标双击消息监听回调函数(参数为双击位置) +typedef MOUSE_CLICK_LISTENER_CALLBACK MOUSE_DBLCLK_LISTENER_CALLBACK; + +// 鼠标拖动消息监听回调函数(参数为拖动前位置和拖动后位置) +typedef std::function MOUSE_DRAG_LISTENER_CALLBACK; + } \ No newline at end of file diff --git a/Easy2D/egeometry.h b/Easy2D/egeometry.h index c5b4a76a..b9fed834 100644 --- a/Easy2D/egeometry.h +++ b/Easy2D/egeometry.h @@ -6,24 +6,65 @@ namespace e2d { class EPhysicsManager; +class ENode; +class EGeometry; + +class EPhysicsMsg +{ + friend EPhysicsManager; + +public: + enum INTERSECT_RELATION + { + UNKNOWN = 0, /* 关系不确定 */ + DISJOINT = 1, /* 没有交集 */ + IS_CONTAINED = 2, /* 完全被包含 */ + CONTAINS = 3, /* 完全包含 */ + OVERLAP = 4 /* 部分重叠 */ + }; + + // 获取当前物理碰撞消息类型 + static INTERSECT_RELATION getMsg(); + + // 获取主动方 + static EGeometry * getActiveGeometry(); + + // 获取被动方 + static EGeometry * getPassiveGeometry(); + +public: + static INTERSECT_RELATION s_nRelation; + static EGeometry * s_pActiveGeometry; + static EGeometry * s_pPassiveGeometry; +}; class EGeometry : public EObject { friend EPhysicsManager; + friend ENode; + public: EGeometry(); + // 获取父节点 + ENode * getParentNode() const; + protected: - virtual bool _isCollisionWith( + // 判断两形状的交集关系 + virtual EPhysicsMsg::INTERSECT_RELATION _intersectWith( EGeometry * pGeometry ); + // 转换形状 + virtual void _transform(); + virtual ID2D1Geometry * _getD2dGeometry() const = 0; protected: - bool m_bTransformed; + bool m_bTransformNeeded; ENode * m_pParentNode; + ID2D1TransformedGeometry * m_pTransformedGeometry; }; diff --git a/Easy2D/elisteners.h b/Easy2D/elisteners.h index 4283c062..e2e118c2 100644 --- a/Easy2D/elisteners.h +++ b/Easy2D/elisteners.h @@ -1,12 +1,13 @@ #pragma once #include "ebase.h" +#include "egeometry.h" namespace e2d { class ENode; class EMsgManager; - +class EPhysicsManager; // 监听器 class EListener : @@ -321,4 +322,86 @@ protected: virtual void _callOn() override; }; + +// 物理世界消息监听器回调函数(参数:主动方、被动方、两方关系) +typedef std::function PHYSICS_LISTENER_CALLBACK; + +// 碰撞消息监听器回调函数(参数:主动方、被动方) +typedef std::function COLLISION_LISTENER_CALLBACK; + +// 物理世界消息监听器 +class EPhysicsListener : + public EListener +{ + friend EPhysicsManager; + +public: + EPhysicsListener(); + + EPhysicsListener( + const EString &name + ); + + EPhysicsListener( + const PHYSICS_LISTENER_CALLBACK &callback + ); + + EPhysicsListener( + const EString &name, + const PHYSICS_LISTENER_CALLBACK &callback + ); + + // 设置监听器回调函数 + void setCallback( + const PHYSICS_LISTENER_CALLBACK &callback + ); + + // 将监听器与场景绑定 + virtual void bindWith( + EScene * pParentScene + ) override; + + // 将监听器与节点绑定 + virtual void bindWith( + ENode * pParentNode + ) override; + +protected: + // 执行监听器回调函数 + virtual void _callOn() override; + +protected: + PHYSICS_LISTENER_CALLBACK m_Callback; +}; + + +class ECollisionListener : + public EPhysicsListener +{ + friend EMsgManager; + +public: + ECollisionListener(); + + ECollisionListener( + const EString &name + ); + + ECollisionListener( + const COLLISION_LISTENER_CALLBACK &callback + ); + + ECollisionListener( + const EString &name, + const COLLISION_LISTENER_CALLBACK &callback + ); + +protected: + // 执行监听器回调函数 + virtual void _callOn() override; + +protected: + COLLISION_LISTENER_CALLBACK m_Callback; +}; + } \ No newline at end of file diff --git a/Easy2D/emanagers.h b/Easy2D/emanagers.h index b5016550..67966c91 100644 --- a/Easy2D/emanagers.h +++ b/Easy2D/emanagers.h @@ -13,6 +13,8 @@ class ETimer; class EAction; class EMouseListener; class EKeyboardListener; +class EGeometry; +class EPhysicsListener; // 对象管理器 class EObjectManager @@ -316,16 +318,88 @@ private: class EPhysicsManager { + friend EApp; + friend EScene; + friend ENode; + public: - // 绑定形状到节点 - static void bindWith( - EGeometry * geometry, - ENode * node + // 添加形状 + static void addGeometry( + EGeometry * geometry + ); + + // 删除已绑定的形状 + static void delGeometry( + EGeometry * geometry + ); + + // 将监听器与场景绑定 + static void bindListener( + EPhysicsListener * listener, + EScene * pParentScene + ); + + // 将监听器与节点绑定 + static void bindListener( + EPhysicsListener * listener, + ENode * pParentNode + ); + + // 启动具有相同名称的监听器 + static void startListeners( + const EString &name + ); + + // 停止具有相同名称的监听器 + static void stopListeners( + const EString &name + ); + + // 删除具有相同名称的监听器 + static void delListeners( + const EString &name + ); + + // 启动绑定在场景及其子节点上的所有监听器 + static void startAllListenersBindedWith( + EScene * pParentScene + ); + + // 停止绑定在场景及其子节点上的所有监听器 + static void stopAllListenersBindedWith( + EScene * pParentScene + ); + + // 启动绑定在节点上的所有监听器 + static void startAllListenersBindedWith( + ENode * pParentNode + ); + + // 停止绑定在节点上的所有监听器 + static void stopAllListenersBindedWith( + ENode * pParentNode + ); + + // 启动所有监听器 + static void startAllListeners(); + + // 停止所有监听器 + static void stopAllListeners(); + +private: + // 清空监听器管理器 + static void _clearManager(); + + // 清空绑定在节点上的所有监听器 + static void _clearAllListenersBindedWith( + ENode * pParentNode ); -protected: // 物理引擎执行程序 static void PhysicsProc(); + + // 物理碰撞监听器执行程序 + static void PhysicsListenerProc(); }; } \ No newline at end of file diff --git a/Easy2D/enodes.h b/Easy2D/enodes.h index a0e8588f..2adb80ba 100644 --- a/Easy2D/enodes.h +++ b/Easy2D/enodes.h @@ -15,6 +15,7 @@ class ENode : { friend EScene; friend EButton; + friend EGeometry; public: ENode();