矢量下标超出范围

时间:2016-07-20 21:35:26

标签: c++ exception vector

我的游戏有点问题。当我试图检查子弹和敌人是否发生碰撞时,我随机得到一个错误“矢量下标超出范围”,我不确定这是一个问题,但我在两个地方删除我的矢量:< / p>

//Checking if enemy is crossing a bullet
        for (size_t i = 0; i < ennemies.size(); i++)
        {
            ennemies[i].update(player);

            if (player.getGlobalBounds().intersects(ennemies[i].getGlobalBounds()))
            {
                player.kill();
            }

            for (size_t j = 0; j < bullets.size(); j++)
            {
                if (ennemies[i].getGlobalBounds().intersects(bullets[j].getGlobalBounds()))
                {
                    ennemies.erase(ennemies.begin() + i);
                    bullets.erase(bullets.begin() + j);
                    ilosc--;
                }
            }
        }

这是第二名:

for (int i = 0; i < Level::LEVEL_HEIGHT; i++)
{
    for (int j = 0; j < Level::LEVEL_WIDTH; j++)
    {
        if (level.tiles[i][j].tileType != 0)
        {
            if (x.intersects(map[i][j].getGlobalBounds()))
                kolX = true;
            else if (y.intersects(map[i][j].getGlobalBounds()))
                kolY = true;

            for (int k = 0; k < bullets.size(); k++)
            {
                if (bullets[k].getGlobalBounds().intersects(map[i][j].getGlobalBounds()))
                {
                    bullets.erase(bullets.begin() + k);
                    ilosc--;
                }
            }
        }
    }
}

这是主类的整个代码:

    #include "Engine.h"

Engine::Engine()
{
    //wczytywanie bg
    bgTexture.loadFromFile("data\\textures\\bg.png");
    bgSprite.setTexture(bgTexture);

    //wczytywanie textur
    for (int i = 1; i < level.iloscTextur; i++)
    {
        tiles[i].loadFromFile("data\\textures\\tiles.png", IntRect((i-1)*level.TILE_WIDTH, 0, 32, 32));
    }

    //ustawianie kafli
    for (int i = 0; i < Level::LEVEL_HEIGHT; i++)
    {
        for (int j = 0; j < Level::LEVEL_WIDTH; j++)
        {
            if (level.tiles[i][j].tileType != 0)
            {
                map[i][j].setPosition(j * Level::TILE_WIDTH, i * Level::TILE_HEIGHT);
                map[i][j].setTexture(tiles[level.tiles[i][j].tileType]);
            }
        }
    }
}

Engine::~Engine()
{

}

//Renderowany poziom gry

void Engine::runEngine(RenderWindow & window)
{
    //Zegary do pętli stałokrokowej, pocisków i przeciwników
    Time UpdateTime = Time::Zero;
    Time czasOdPocisku = Time::Zero;
    Time czasDoSpawnu = Time::Zero;

    Clock przeciwnicy;
    Clock zegar;
    Clock czasPocisku;

    const Time StepTime = seconds(1.f / 60.f);
    const Time WaitTime = seconds(0.1);
    Time EnemySpawn = enemy.losujSpawn();

    bool menu = false;

    while (!menu)
    {
        Time czas = zegar.restart();
        UpdateTime += czas;

        //Pętla aktualizujaca logikę gry

        while (UpdateTime > StepTime)
        {
            czasOdPocisku = czasPocisku.getElapsedTime();
            czasDoSpawnu = przeciwnicy.getElapsedTime();

            UpdateTime -= StepTime;
            Event event;
            Vector2f mouse = window.mapPixelToCoords(Mouse::getPosition(window));   

            player.update(mouse);

            if (window.pollEvent(event))
            {
                if (event.type == Event::Closed)
                    menu = true;

                if ((Keyboard::isKeyPressed(Keyboard::Left) && WaitTime < czasOdPocisku) || (Keyboard::isKeyPressed(Keyboard::Right) && WaitTime < czasOdPocisku) ||
                    (Keyboard::isKeyPressed(Keyboard::Up) && WaitTime < czasOdPocisku) || (Keyboard::isKeyPressed(Keyboard::Down) && WaitTime < czasOdPocisku))
                {
                    czasPocisku.restart();

                    bullets.push_back(bullet);
                    bullets[ilosc].addBullet(player);
                    ilosc++;
                }
            }

            //Spawn przeciwników


            if (EnemySpawn < czasDoSpawnu)
            {
                czasDoSpawnu = przeciwnicy.restart();
                EnemySpawn = enemy.losujSpawn();
                for (int i = 0; i < enemy.losujPrzeciwnikow(); i++)
                    ennemies.push_back(enemy);
            }

            //aktualizacje logiki

            for (int i = 0; i < bullets.size(); i++)
            {
                bullets[i].update();
            }

            //Checking if enemy is crossing a bullet
            for (size_t i = 0; i < ennemies.size(); i++)
            {
                ennemies[i].update(player);

                if (player.getGlobalBounds().intersects(ennemies[i].getGlobalBounds()))
                {
                    player.kill();
                }

                for (size_t j = 0; j < bullets.size(); j++)
                {
                    if (ennemies[i].getGlobalBounds().intersects(bullets[j].getGlobalBounds()))
                    {
                        ennemies.erase(ennemies.begin() + i);
                        bullets.erase(bullets.begin() + j);
                        ilosc--;
                    }
                }
            }
            czyKoliduje(player.ruch(StepTime));
        }

        window.clear();
        window.draw(bgSprite);

        //Rysowanie poziomu

        for (int i = 0; i < Level::LEVEL_HEIGHT; i++)
        {
            for (int j = 0; j < Level::LEVEL_WIDTH; j++)
            {
                window.draw(map[i][j]);
            }
        }

        //Rysowanie pociskow

        for (int i = 0; i < bullets.size(); i++)
        {
            window.draw(bullets[i]);
        }   

        for (int i = 0; i < ennemies.size(); i++)
        {
            window.draw(ennemies[i]);
        }

        window.draw(player);
        window.display();
    }
}

//Kolizje

void Engine::czyKoliduje(Vector2f ruch)
{

    FloatRect x = player.getGlobalBounds();
    FloatRect y = player.getGlobalBounds();

    x.left += ruch.x;
    y.top += ruch.y;

    bool kolY = false, kolX = false;

    for (int i = 0; i < Level::LEVEL_HEIGHT; i++)
    {
        for (int j = 0; j < Level::LEVEL_WIDTH; j++)
        {
            if (level.tiles[i][j].tileType != 0)
            {
                if (x.intersects(map[i][j].getGlobalBounds()))
                    kolX = true;
                else if (y.intersects(map[i][j].getGlobalBounds()))
                    kolY = true;

                for (int k = 0; k < bullets.size(); k++)
                {
                    if (bullets[k].getGlobalBounds().intersects(map[i][j].getGlobalBounds()))
                    {
                        bullets.erase(bullets.begin() + k);
                        ilosc--;
                    }
                }
            }
        }
    }

    if (!kolX)
        player.move(Vector2f(ruch.x, 0));
    if (!kolY)
        player.move(Vector2f(0, ruch.y));
}

1 个答案:

答案 0 :(得分:3)

在容器上调用erase()的所有循环都没有考虑到当您从中删除项目时容器的大小会发生变化。要正确循环容器,而从中删除项目,您应该使用迭代器而不是索引。 erase()返回一个新的迭代器,指向被删除项目后的项目,因此您可以继续循环。

std::vector<enemy>::iterator i = ennemies.begin();
while (i != ennemies.end())
{
    i->update(player);

    if (player.getGlobalBounds().intersects(i->getGlobalBounds()))
    {
        player.kill();
    }

    bool hit = false;
    for (std::vector<bullet>::iterator j = bullets.begin(); j != bullets.end); ++j)
    {
        if (i->getGlobalBounds().intersects(j->getGlobalBounds()))
        {
            hit = true;
            i = ennemies.erase(i);
            j = bullets.erase(j);
            ilosc--;
            break;
        }
    }

    if (!hit)
        ++i;
}

for (int i = 0; i < Level::LEVEL_HEIGHT; i++)
{
    for (int j = 0; j < Level::LEVEL_WIDTH; j++)
    {
        if (level.tiles[i][j].tileType != 0)
        {
            if (x.intersects(map[i][j].getGlobalBounds()))
                kolX = true;
            else if (y.intersects(map[i][j].getGlobalBounds()))
                kolY = true;

            std::vector<bullet>::iterator k = bullets.begin();
            while (k != bullets.end())
            {
                if (k->getGlobalBounds().intersects(map[i][j].getGlobalBounds()))
                {
                    k = bullets.erase(k);
                    ilosc--;
                }
                else
                    ++k;
            }
        }
    }
}

话虽如此,您可以考虑使用std::remove_if()代替手动erase()循环:

template<typename SourceType, typename TargetType>
struct intersectsBounds
{
    TargetType &m_target;

    intersectsBounds(TargetType &target) : m_target(target) {}

    bool operator()(const SourceType &source) const
    {
        return source.getGlobalBounds().intersects(m_target.getGlobalBounds());
    }
};

std::vector<enemy>::iterator i = ennemies.begin();
while (i != ennemies.end())
{
    i->update(player);

    if (player.getGlobalBounds().intersects(i->getGlobalBounds()))
    {
        player.kill();
    }

    std::vector<bullet>::iterator j = std::remove_if(bullets.begin(), bullets.end(), intersectsBounds(*i));
    if (j != bullets.end())
    {
        i = ennemies.erase(i);

        int numErased = std::distance(j, bullets.end());
        bullets.erase(j, bullets.end());
        ilosc -= numErased;
    }
    else
        ++i;
}

for (int i = 0; i < Level::LEVEL_HEIGHT; i++)
{
    for (int j = 0; j < Level::LEVEL_WIDTH; j++)
    {
        if (level.tiles[i][j].tileType != 0)
        {
            if (x.intersects(map[i][j].getGlobalBounds()))
                kolX = true;
            else if (y.intersects(map[i][j].getGlobalBounds()))
                kolY = true;

            std::vector<bullet>::iterator k = std::remove_if(bullets.begin(), bullets.end(), intersectsBounds(map[i][j]));
            if (k != bullets.end())
            {
                int numErased = std::distance(k, bullets.end());
                bullets.erase(k, bullets.end());
                ilosc -= numErased;
            }
        }
    }
}