#include "..\e2dmanager.h" #include "..\e2dobject.h" #include "..\e2dtool.h" #include "..\e2dmodule.h" e2d::CollisionManager * e2d::CollisionManager::GetInstance() { static CollisionManager instance; return &instance; } e2d::CollisionManager::CollisionManager() : collision_enabled_(false) { } e2d::CollisionManager::~CollisionManager() { } void e2d::CollisionManager::AddCollider(Collider * collider) { colliders_.push_back(collider); } void e2d::CollisionManager::RemoveCollider(Collider * collider) { auto iter = std::find(colliders_.begin(), colliders_.end(), collider); if (iter != colliders_.end()) { colliders_.erase(iter); } } void e2d::CollisionManager::UpdateCollider(Collider* active) { if (!collision_enabled_ || Game::GetInstance()->IsTransitioning()) return; auto currScene = Game::GetInstance()->GetCurrentScene(); if (active->GetNode()->GetParentScene() != currScene) return; std::vector currColliders; currColliders.reserve(colliders_.size()); std::copy_if( colliders_.begin(), colliders_.end(), std::back_inserter(currColliders), [this, active, currScene](Collider* passive) -> bool { return active != passive && passive->GetNode()->IsVisible() && passive->GetNode()->GetParentScene() == currScene && this->IsCollidable(active->GetNode(), passive->GetNode()); } ); for (const auto& passive : currColliders) { // 判断两碰撞体交集情况 Collider::Relation relation = active->GetRelationWith(passive); // 忽略 UNKNOWN 和 DISJOIN 情况 if (relation != Collider::Relation::Unknown && relation != Collider::Relation::Disjoin) { auto activeNode = active->GetNode(); auto passiveNode = passive->GetNode(); // 触发两次碰撞事件 Collision activeCollision(passiveNode, relation); if (dynamic_cast(activeNode)) dynamic_cast(activeNode)->Handle(activeCollision); Collision passiveCollision(activeNode, passive->GetRelationWith(active)); if (dynamic_cast(passiveNode)) dynamic_cast(passiveNode)->Handle(passiveCollision); } } } void e2d::CollisionManager::SetCollisionEnabled(bool enabled) { collision_enabled_ = enabled; } void e2d::CollisionManager::AddName(const String & name1, const String & name2) { if (!name1.IsEmpty() && !name2.IsEmpty()) { collision_list_.insert(std::make_pair(name1.GetHash(), name2.GetHash())); } } void e2d::CollisionManager::AddName(const std::vector >& names) { for (const auto& name : names) { if (!name.first.IsEmpty() && !name.second.IsEmpty()) { collision_list_.insert(std::make_pair(name.first.GetHash(), name.second.GetHash())); } } } bool e2d::CollisionManager::IsCollidable(Node * node1, Node * node2) { return CollisionManager::IsCollidable(node1->GetName(), node2->GetName()); } bool e2d::CollisionManager::IsCollidable(const String & name1, const String & name2) { size_t hashName1 = name1.GetHash(), hashName2 = name2.GetHash(); auto pair1 = std::make_pair(hashName1, hashName2), pair2 = std::make_pair(hashName2, hashName1); for (const auto& pair : collision_list_) { if (pair == pair1 || pair == pair2) { return true; } } return false; }