【问题标题】:Good way to start playing sound when two object collide in Bullet PhysicsBullet Physics 中两个物体碰撞时开始播放声音的好方法
【发布时间】:2018-02-04 07:13:16
【问题描述】:

我正在尝试在我的引擎中为碰撞实现音频功能,但我很难找到一个好的方法来做到这一点。我使用 Bullet Physics,我想在两个物体碰撞时播放声音。我通过 gContactAddedCallback 实现了一个回调机制,所以每次两个对象碰撞时我都会收到回调。我遇到的问题是回调函数可以在每个游戏循环中多次调用,我不确定如何播放音频以进行碰撞。

我正在考虑保留某种列表,其中包含某个对象的所有当前冲突,但是通过这种方式,我再次不确定何时清理列表。我尝试在每个游戏循环中清理列表,但我仍然收到多个关于两个对象碰撞的回调。

谁能解释或指出一个资源,解释使物理引擎和音频协同工作的正确方法?

【问题讨论】:

    标签: game-engine game-physics bulletphysics


    【解决方案1】:

    好的,所以我找到了一种方法来做我正在寻找的事情,但它似乎非常未经优化并且有点老套。我仍然想知道是否有一种我没有看到的简单方法来做到这一点。这是我现在所做的。我保留了一个持续冲突列表并将其与另一个当前冲突列表进行比较。如果当前冲突有一个在持久冲突列表中不存在的条目,我将其添加到持久冲突中并播放声音。之后,我遍历持久冲突列表并删除当前冲突列表中未包含的所有条目。这是代码。

    // 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++;
        }
    }
    

    【讨论】:

    • 我的方式和你的很相似。我像static_cast&lt;MyObject*&gt;(rigidBody-&gt;getUserPointer())-&gt;listOfMyObject 那样做。我不确定哪个更好。你介绍过你的技术吗?真的有那么慢吗?
    • 我在发布此内容后所做的一项更改是用 unordered_maps 替换向量以加快查找速度。我什至不确定这是否产生了重大影响。我没有进行任何分析,但我怀疑这会成为瓶颈。我唯一的问题是,我强烈地感觉到有更好的方法来做到这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多