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();