每帧开始时清空上一帧的碰撞记录collision_pairs_.clear();//
(auto*
PhysicsEngine::checkObjectCollisions(){//
--->
obj_a->getComponent<engine::component::ColliderComponent>();if(!cc_a
continue;
obj_b->getComponent<engine::component::ColliderComponent>();if(!cc_b
continue;
检查碰撞if(collision::checkCollision(*cc_a,
*cc_b))
记录碰撞对collision_pairs_.emplace_back(std::make_pair(obj_a,
obj_b));}}}
collision_pairs_.clear(),每帧开始时清空上一帧的碰撞记录
---
遍历所有PhysicsComponent,应用物理规则更新位置
---
checkObjectCollisions(),执行碰撞检测
id="checkobjectcollisions优化">checkObjectCollisions优化
class="language-cpp">for(size_t
<
性能考虑:对于对象层物体不多的情况,O(n$^2$)暴力求解是可以接受的。
class="language-cpp">collision_pairs_.emplace_back(obj_a,obj_b);
如果collision::checkCollision返回true,就将这对发生碰撞的GameObject指针存入collision_pairs_。
我们在GameScene中创建两个物体:一个受重力影响的箱子(AABB碰撞体)和一个静止的箱子(圆形碰撞体),并给其加上ColliderComponent。
id="gamescenegame_scenecpp">game/scene/game_scene.cpp
{std::unique_ptr<engine::object::GameObject>
gameobj
std::make_unique<engine::object::GameObject>("test1");//
添加组件进行测试gameobj->addComponent<engine::component::TransformComponent>(glm::vec2(200.0f,100.0f));gameobj->addComponent<engine::component::SpriteComponent>("assets/textures/Props/big-crate.png",context_.getResourceManager(),engine::utils::Alignment::CENTER);gameobj->addComponent<engine::component::PhysicsComponent>(&context_.getPhysicsEngine(),1.0f);gameobj->addComponent<engine::component::ColliderComponent>(std::make_unique<engine::physics::AABBCollider>((glm::vec2(32))));addGameObject(std::move(gameobj));auto
gameobj1
std::make_unique<engine::object::GameObject>("test2");gameobj1->addComponent<engine::component::TransformComponent>(glm::vec2(200.0f,200.0f));gameobj1->addComponent<engine::component::SpriteComponent>("assets/textures/Props/big-crate.png",context_.getResourceManager(),engine::utils::Alignment::CENTER);gameobj1->addComponent<engine::component::PhysicsComponent>(&context_.getPhysicsEngine(),1.0f,false);gameobj1->addComponent<engine::component::ColliderComponent>(std::make_unique<engine::physics::AABBCollider>((glm::vec2(32))));addGameObject(std::move(gameobj1));
}void
{Scene::update(delta_time);TestCollisionPairs();
每帧检查并打印碰撞对
context_.getPhysicsEngine().getCollisionPairs()){spdlog::info("{}和{}发生碰撞",pair.first->getName(),pair.second->getName());}
data-src="https://img2024.cnblogs.com/blog/2727651/202602/2727651-20260218211059417-1569890633.png"
可以看到两个箱子发生了碰撞,这证明我们的碰撞检测系统已经成功运行了
collision::checkCollision()(检测算法)
---调用--->
PhysicsEngine::checkObjectCollisions()
--->
创建碰撞组件:ColliderComponent管理碰撞器集成到物理引擎PhysicsEngine统一管理碰撞检测,限定返回的引用是只读的,调用方不能通过这个引用修改force_;
函数后的const,限定这个成员函数是只读的,函数内部不能修改类的任何非mutable成员,(force_不能改),这会让force_变成const属性。
在const成员函数中,类的成员变量(比如force_)会被编译器视为const类型
即force_的实际类型是const
glm::vec2
,这是后续所有写法是否合法的核心前提。