我正在尝试在我的引擎中实现碰撞的音频功能,我努力找到一个好的方法来做到这一点。我用的是Bullet物理,我想在两个物体碰撞时播放声音。我通过gContactAddedCallback实现了一个回调机制,所以每次两个对象发生冲突时我都会得到回调。我遇到的问题是,回调函数可能会在每个游戏循环中被多次调用,而我不确定如何播放冲突的音频。
我在考虑保留某种类型的列表,其中包含某个对象的所有当前碰撞,但通过这种方式,我再次不确定何时清理列表。我试图在每个游戏循环中清理列表,但我仍然收到两个对象碰撞的多个回调。
谁能解释一下或者指出一个资源,它解释了一种让物理引擎和音频协同工作的正确方法?
发布于 2018-02-04 23:25:15
好了,我找到了一种方法来做我想做的事情,但它似乎非常未经优化,有点老生常谈。我仍然在想,是否有一种简单的方法可以做到这一点,我没有看到。这是我现在所做的。我保存了一个持久冲突列表,并将其与当前冲突的另一个列表进行比较。如果当前冲突有一个条目不存在于持久冲突列表中,我将其添加到持久冲突列表中,然后播放声音。在此之后,我遍历持久冲突列表并删除当前冲突列表中未包含的所有条目。下面是代码。
// persistentCollisions map.
std::map<int, std::vector<int>> persistentCollisions;
// Main game loop
while (!glfwWindowShouldClose(window.getWindow()))
{
//.
//.
//.
physicsEngine->getDynamicsWorld()->stepSimulation(1.0f / 60.0f);
// New collision map
std::map<int, std::vector<int>> newCollisions;
// Go over the collision manifold and extract all existing collisions
int numManifolds = physicsEngine->getDynamicsWorld()->getDispatcher()->getNumManifolds();
for (int i = 0; i < numManifolds; i++)
{
btPersistentManifold* contactManifold = physicsEngine->getDynamicsWorld()->getDispatcher()->getManifoldByIndexInternal(i);
const btCollisionObject* obA = contactManifold->getBody0();
const btCollisionObject* obB = contactManifold->getBody1();
int numContacts = contactManifold->getNumContacts();
for (int j = 0; j < numContacts; j++)
{
btManifoldPoint& pt = contactManifold->getContactPoint(j);
if (pt.getDistance() < 0.f)
{
// If it is a new collision, add to the newCollision list
if (std::find(newCollisions[obA->getUserIndex()].begin(), newCollisions[obA->getUserIndex()].end(), obB->getUserIndex()) == newCollisions[obA->getUserIndex()].end())
{
newCollisions[obA->getUserIndex()].emplace_back(obB->getUserIndex());
}
}
}
}
// Iterate over new collisions and add new collision to persistent collisions if it does not exist
std::map<int, std::vector<int>>::iterator newCollisionIterator = newCollisions.begin();
while (newCollisionIterator != newCollisions.end())
{
for (auto item : newCollisionIterator->second)
{
if (std::find(persistentCollisions[newCollisionIterator->first].begin(), persistentCollisions[newCollisionIterator->first].end(), item) == persistentCollisions[newCollisionIterator->first].end())
{
std::cout << "New collision between " << newCollisionIterator->first << " And " << item << std::endl;
// We can play our collision audio here
persistentCollisions[newCollisionIterator->first].emplace_back(item);
}
}
newCollisionIterator++;
}
// Iterate over persistent collisions and remove all collisions that did not exist in new collision
std::map<int, std::vector<int>>::iterator persistentCollisionIterator = persistentCollisions.begin();
while (persistentCollisionIterator != persistentCollisions.end())
{
std::vector<int>::iterator iter;
for (iter = persistentCollisionIterator->second.begin(); iter != persistentCollisionIterator->second.end(); )
{
if (std::find(newCollisions[persistentCollisionIterator->first].begin(), newCollisions[persistentCollisionIterator->first].end(), *iter) != newCollisions[persistentCollisionIterator->first].end())
{
++iter;
}
else
{
iter = persistentCollisionIterator->second.erase(iter);
}
}
persistentCollisionIterator++;
}
}
https://stackoverflow.com/questions/48605701
复制相似问题