C ++游戏导弹碰撞检测

时间:2017-04-26 16:20:56

标签: c++ collision detection

我正在重建经典游戏小行星,我在使碰撞检测正常工作方面遇到了一些问题。目前,下面的代码运行良好,但由于某种原因,它只会检测最后一枚已经发射的导弹上的碰撞。我的意思是如果我在一颗静止的小行星上直线发射3枚导弹,前两颗将穿过小行星,而只有最后一颗将与它碰撞并按预期行动。我不太清楚为什么会这样,但我认为这与迭代导弹列表有关。

这是用于检测碰撞的部分工作函数:

void checkMissileAsteroidCollision(struct particle *ast, struct particle *mis)
{
        float missileX = 0;
        float missileY = 0;

        float asteroidX = 0;
        float asteroidY = 0;
        float asteroidSize = 0;

    for( ; mis ; mis = mis->next ) 
    {
            missileX = mis->x;
            missileY = mis->y;

        for( ; ast ; ast = ast->next)
        {
            asteroidX = ast->x;
            asteroidY = ast->y;
            asteroidSize = ast->size;

            if(missileX < asteroidX + asteroidSize &&
                 missileX > asteroidX &&
                 missileY < asteroidY + asteroidSize &&
                 missileY > asteroidY && mis->draw == 1 && ast->draw == 1)
            {
                collisionCounter++;
                ast->draw = 0;
                mis->draw = 0;

            }
        }

    }
}

粒子结构;

typedef struct particle{
    float x;
        float y;
    float vx;
        float vy;
        float heading;
    float dur;
        int size;
        int draw;
    struct particle *next;
} node_t;

我已经在下面链接了两个链接,指向整个源文件及其代码来自的标题,以防需要任何其他信息来弄清楚为什么会发生这种情况。

gamestate.cpp:https://gist.github.com/Jakemangan/d286ef1f9159e6682778ec2e0daf516c

gamestate.h:https://gist.github.com/Jakemangan/6c3788a46825a86cd0e2642864fcad68

2 个答案:

答案 0 :(得分:5)

for( ; ast ; ast = ast->next)

这一行是问题所在。在此循环终止后,ast为空,但不会为外部mis循环的下一次迭代重置。这意味着只有mis循环的第一次迭代才会实际看到任何小行星。

要纠正此问题,请为此循环声明一个新变量:

for(struct particle *ast2 = ast ; ast2 ; ast2 = ast2->next)

(或选择比ast2更好的名称。)然后,显然,在循环体中将ast替换为ast2

答案 1 :(得分:1)

这是更现代的C ++版本的样子:

// drop the pointer from the struct

void checkMissileAsteroidCollision(std::vector<particle>& asteroids, std::vector<particle>& missiles)
{
    for(auto & mis : missiles) 
    {
        for(auto & ast : asteroids)
        {
            const auto missileX = mis.x;
            const auto missileY = mis.y;
            const auto asteroidX = ast.x;
            const auto asteroidY = ast.y;
            const auto asteroidSize = ast.size;

            if(missileX < asteroidX + asteroidSize &&
                 missileX > asteroidX &&
                 missileY < asteroidY + asteroidSize &&
                 missileY > asteroidY && mis.draw == 1 && ast.draw == 1)
            {
                collisionCounter++;
                ast.draw = false;
                mis.draw = false;
            }
        }
    }
}

然后创建和使用示例:

std::vector<particle> asteroids { { 0, 0, 0, 0, 0, 0, 10, true } };
std::vector<particle> missiles { { 5, 5, 0, 0, 0, 0, 10, true } };

checkMissileAsteroidCollision(asteroids, missiles);

std::cout << std::boolalpha << asteroids[0].draw;

这里有更多的改进(在类中封装,不使参数变异,不使用draw作为碰撞标志),但我相信这些属于Code Review,我鼓励你发布你的一旦你开始工作就可以解决问题。