241 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
| #include "..\e2dcollider.h"
 | |
| #include "..\e2dnode.h"
 | |
| #include "..\e2dtool.h"
 | |
| 
 | |
| typedef std::pair<UINT, UINT> HashPair;
 | |
| 
 | |
| static std::vector<e2d::Listener*> s_vListeners;	// 监听器容器
 | |
| static bool s_bCollisionEnable = false;				// 碰撞触发状态
 | |
| static e2d::Node * s_pActiveNode = nullptr;			// 主动碰撞体
 | |
| static e2d::Node * s_pPassiveNode = nullptr;		// 被动碰撞体
 | |
| static std::set<HashPair> s_sCollisionList;			// 碰撞映射
 | |
| 
 | |
| 
 | |
| void e2d::Collision::addName(const String & name1, const String & name2)
 | |
| {
 | |
| 	if (!name1.isEmpty() && !name2.isEmpty())
 | |
| 	{
 | |
| 		s_sCollisionList.insert(HashPair(name1.getHashCode(), name2.getHashCode()));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void e2d::Collision::addName(const std::vector<std::pair<String, String> >& names)
 | |
| {
 | |
| 	for (auto& name : names)
 | |
| 	{
 | |
| 		if (!name.first.isEmpty() && !name.second.isEmpty())
 | |
| 		{
 | |
| 			s_sCollisionList.insert(HashPair(name.first.getHashCode(), name.second.getHashCode()));
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| bool e2d::Collision::isCollidable(Node * node1, Node * node2)
 | |
| {
 | |
| 	return Collision::isCollidable(node1->getName(), node2->getName());
 | |
| }
 | |
| 
 | |
| bool e2d::Collision::isCollidable(const String & name1, const String & name2)
 | |
| {
 | |
| 	UINT hashName1 = name1.getHashCode(), hashName2 = name2.getHashCode();
 | |
| 	HashPair pair1 = HashPair(hashName1, hashName2), pair2 = HashPair(hashName2, hashName1);
 | |
| 	for (auto& pair : s_sCollisionList)
 | |
| 	{
 | |
| 		if (pair == pair1 || pair == pair2)
 | |
| 		{
 | |
| 			return true;
 | |
| 		}
 | |
| 	}
 | |
| 	return false;
 | |
| }
 | |
| 
 | |
| e2d::Node * e2d::Collision::getActiveNode()
 | |
| {
 | |
| 	return s_pActiveNode;
 | |
| }
 | |
| 
 | |
| e2d::Node * e2d::Collision::getPassiveNode()
 | |
| {
 | |
| 	return s_pPassiveNode;
 | |
| }
 | |
| 
 | |
| bool e2d::Collision::isCausedBy(const String & name1, const String & name2)
 | |
| {
 | |
| 	String activeName = s_pActiveNode->getName();
 | |
| 	String passiveName = s_pPassiveNode->getName();
 | |
| 	return (activeName == name1 && passiveName == name2) ||
 | |
| 		(activeName == name2 && passiveName == name1);
 | |
| }
 | |
| 
 | |
| bool e2d::Collision::isCausedBy(Node * node1, Node * node2)
 | |
| {
 | |
| 	return (s_pActiveNode == node1 && s_pPassiveNode == node2) ||
 | |
| 		(s_pActiveNode == node2 && s_pPassiveNode == node1);
 | |
| }
 | |
| 
 | |
| e2d::Node* e2d::Collision::isCausedBy(Node * node)
 | |
| {
 | |
| 	if (s_pActiveNode == node)
 | |
| 		return s_pPassiveNode;
 | |
| 	if (s_pPassiveNode == node)
 | |
| 		return s_pActiveNode;
 | |
| 	return nullptr;
 | |
| }
 | |
| 
 | |
| e2d::Node* e2d::Collision::isCausedBy(const String& name)
 | |
| {
 | |
| 	if (s_pActiveNode->getName() == name)
 | |
| 		return s_pActiveNode;
 | |
| 	if (s_pPassiveNode->getName() == name)
 | |
| 		return s_pPassiveNode;
 | |
| 	return nullptr;
 | |
| }
 | |
| 
 | |
| 
 | |
| void e2d::Collision::setEnable(bool enable)
 | |
| {
 | |
| 	s_bCollisionEnable = enable;
 | |
| }
 | |
| 
 | |
| bool e2d::Collision::isEnable()
 | |
| {
 | |
| 	return s_bCollisionEnable;
 | |
| }
 | |
| 
 | |
| void e2d::Collision::__update(Node * active, Node * passive)
 | |
| {
 | |
| 	if (s_vListeners.empty() || Game::getInstance()->isPaused())
 | |
| 		return;
 | |
| 
 | |
| 	s_pActiveNode = active;
 | |
| 	s_pPassiveNode = passive;
 | |
| 
 | |
| 	for (size_t i = 0; i < s_vListeners.size(); ++i)
 | |
| 	{
 | |
| 		auto listener = s_vListeners[i];
 | |
| 		// 清除已停止的监听器
 | |
| 		if (listener->_stopped)
 | |
| 		{
 | |
| 			GC::release(listener);
 | |
| 			s_vListeners.erase(s_vListeners.begin() + i);
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			// 更新监听器
 | |
| 			listener->_update();
 | |
| 			++i;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	s_pActiveNode = nullptr;
 | |
| 	s_pPassiveNode = nullptr;
 | |
| }
 | |
| 
 | |
| e2d::Listener * e2d::Collision::addListener(const Function& func, const String& name, bool paused)
 | |
| {
 | |
| 	auto listener = Create<Listener>(func, name, paused);
 | |
| 	GC::retain(listener);
 | |
| 	s_vListeners.push_back(listener);
 | |
| 	return listener;
 | |
| }
 | |
| 
 | |
| void e2d::Collision::addListener(Listener * listener)
 | |
| {
 | |
| 	if (listener)
 | |
| 	{
 | |
| 		auto iter = std::find(s_vListeners.begin(), s_vListeners.end(), listener);
 | |
| 		if (iter == s_vListeners.end())
 | |
| 		{
 | |
| 			GC::retain(listener);
 | |
| 			s_vListeners.push_back(listener);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void e2d::Collision::removeListener(Listener * listener)
 | |
| {
 | |
| 	if (listener)
 | |
| 	{
 | |
| 		auto iter = std::find(s_vListeners.begin(), s_vListeners.end(), listener);
 | |
| 		if (iter != s_vListeners.end())
 | |
| 		{
 | |
| 			GC::release(listener);
 | |
| 			s_vListeners.erase(iter);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void e2d::Collision::stopListener(const String& name)
 | |
| {
 | |
| 	if (s_vListeners.empty() || name.isEmpty())
 | |
| 		return;
 | |
| 
 | |
| 	for (auto listener : s_vListeners)
 | |
| 	{
 | |
| 		if (listener->_name == name)
 | |
| 		{
 | |
| 			listener->stop();
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void e2d::Collision::startListener(const String& name)
 | |
| {
 | |
| 	if (s_vListeners.empty() || name.isEmpty())
 | |
| 		return;
 | |
| 
 | |
| 	for (auto listener : s_vListeners)
 | |
| 	{
 | |
| 		if (listener->_name == name)
 | |
| 		{
 | |
| 			listener->start();
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void e2d::Collision::removeListener(const String& name)
 | |
| {
 | |
| 	if (s_vListeners.empty() || name.isEmpty())
 | |
| 		return;
 | |
| 
 | |
| 	for (auto listener : s_vListeners)
 | |
| 	{
 | |
| 		if (listener->_name == name)
 | |
| 		{
 | |
| 			listener->_stopped = true;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void e2d::Collision::stopAllListeners()
 | |
| {
 | |
| 	for (auto listener : s_vListeners)
 | |
| 	{
 | |
| 		listener->stop();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void e2d::Collision::startAllListeners()
 | |
| {
 | |
| 	for (auto listener : s_vListeners)
 | |
| 	{
 | |
| 		listener->start();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void e2d::Collision::removeAllListeners()
 | |
| {
 | |
| 	for (auto listener : s_vListeners)
 | |
| 	{
 | |
| 		listener->_stopped = true;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void e2d::Collision::__clearListeners()
 | |
| {
 | |
| 	for (auto listener : s_vListeners)
 | |
| 	{
 | |
| 		GC::release(listener);
 | |
| 	}
 | |
| 	s_vListeners.clear();
 | |
| } |