我正在用C ++和SFML制作游戏。 我有一个奇怪的错误,每当我在屏幕上只有1个敌人和3个镜头并且子弹与敌人发生碰撞时,游戏就会崩溃。 我得到的错误是:
Expression: vector subscript out of range这就是我检查镜头和敌人之间碰撞的方法:
for (int i = 0; i < enemies.size(); i++) { for (int s = 0; s < shots.size(); s++) { if (Collision::PixelPerfectTest(enemies[i].getSprite(), shots[s].getSprite())) { enemies[i].setHealth(enemies[i].getHealth() - player.getDamage()); if (enemies[i].getHealth() <= 0) { enemies.erase(enemies.begin() + i); } shots.erase(shots.begin() + s); } } }“敌人”和“镜头”是我在主循环中每隔x秒插入的向量。 这是代码:
if (enemySpawner.getElapsedTime().asSeconds() >= 1.5f) { enemies.push_back(Enemy(spriteManager.enemySprite)); std::cout << enemies.size() << " enemies" << std::endl; enemySpawner.restart(); } if (shotSpawner.getElapsedTime().asSeconds() >= 0.3f && sf::Mouse::isButtonPressed(sf::Mouse::Left)) { shots.push_back(Shot(spriteManager.shotSprite, player.getPosition(), *window)); std::cout << shots.size() << " shots" << std::endl; shotSpawner.restart(); }正如我所说,这只发生在我有1个敌人和3个射击时,否则它似乎工作正常。
编辑:现在当第一个敌人产生时,游戏会冻结。 这是更新的代码:
//Shot vs enemy for (auto eit = enemies.begin(); eit != enemies.end();) { for (auto sit = shots.begin(); sit != shots.end();) { if (Collision::PixelPerfectTest((*eit).getSprite(), (*sit).getSprite())) { (*eit).setHealth((*eit).getHealth() - player.getDamage()); if ((*eit).getHealth() <= 0) { enemies.erase(eit); shots.erase(sit); } shots.erase(sit); eit = eit++; sit = sit++; } } }I'm making a game in C++ and SFML. I have a weird bug, whenever I have exactly 1 enemy and 3 shots on the screen and a bullet collides with the enemy, the game crashes. The error I get is:
Expression: vector subscript out of rangeThis is how I check for collision between shots and enemies:
for (int i = 0; i < enemies.size(); i++) { for (int s = 0; s < shots.size(); s++) { if (Collision::PixelPerfectTest(enemies[i].getSprite(), shots[s].getSprite())) { enemies[i].setHealth(enemies[i].getHealth() - player.getDamage()); if (enemies[i].getHealth() <= 0) { enemies.erase(enemies.begin() + i); } shots.erase(shots.begin() + s); } } }"enemies" and "shots" are vectors that I insert into every x seconds in the main loop. Here's the code for that:
if (enemySpawner.getElapsedTime().asSeconds() >= 1.5f) { enemies.push_back(Enemy(spriteManager.enemySprite)); std::cout << enemies.size() << " enemies" << std::endl; enemySpawner.restart(); } if (shotSpawner.getElapsedTime().asSeconds() >= 0.3f && sf::Mouse::isButtonPressed(sf::Mouse::Left)) { shots.push_back(Shot(spriteManager.shotSprite, player.getPosition(), *window)); std::cout << shots.size() << " shots" << std::endl; shotSpawner.restart(); }As I said, this only happens when I have 1 enemy and 3 shots, otherwise it seems to work fine.
EDIT: Now the game freezes when the first enemy spawns. Here's the updated code:
//Shot vs enemy for (auto eit = enemies.begin(); eit != enemies.end();) { for (auto sit = shots.begin(); sit != shots.end();) { if (Collision::PixelPerfectTest((*eit).getSprite(), (*sit).getSprite())) { (*eit).setHealth((*eit).getHealth() - player.getDamage()); if ((*eit).getHealth() <= 0) { enemies.erase(eit); shots.erase(sit); } shots.erase(sit); eit = eit++; sit = sit++; } } }最满意答案
@ moka的答案解释了代码的核心问题,他/她使用迭代器的代码将解决您的问题。 但是,还有另一种方法可以解决这个问题:将代码拆分为“计算通道”和“数组修改通道”。 代码看起来像:
for (int i = 0; i < enemies.size(); i++) { for (int s = 0; s < shots.size(); s++) { if (!enemies[i].alive || !shots[s].active) { continue; } if (Collision::PixelPerfectTest(enemies[i].sprite(), shots[s].sprite())) { shots[s].active = false; enemies[i].setHealth(enemies[i].getHealth() - player.getDamage()); if (enemies[i].getHealth() <= 0) { enemies[i].alive = false; } } } } enemies.erase(std::remove_if(enemies.begin(), enemies.end(), [](Enemy const &e) { return !e.alive; }), enemies.end()); shots.erase(std::remove_if(shots.begin(), shots.end(), [](Shot const &s) { return !s.active; }), shots.end());这种风格也很好,因为它将游戏逻辑与实现分开了一点。 例如,如果你想允许一个射击对一个以上的敌人造成伤害,那么无论如何你都必须使用这样的方法来射击阵列。
“优秀游戏编程模式”一书中关于双缓冲的章节更深入。
@moka's answer explains the core problem with your code, and his/her code using iterators will fix your problem. However, there is another way to deal with the problem: splitting your code into a "computation pass" and an "array modification pass." The code would look like:
for (int i = 0; i < enemies.size(); i++) { for (int s = 0; s < shots.size(); s++) { if (!enemies[i].alive || !shots[s].active) { continue; } if (Collision::PixelPerfectTest(enemies[i].sprite(), shots[s].sprite())) { shots[s].active = false; enemies[i].setHealth(enemies[i].getHealth() - player.getDamage()); if (enemies[i].getHealth() <= 0) { enemies[i].alive = false; } } } } enemies.erase(std::remove_if(enemies.begin(), enemies.end(), [](Enemy const &e) { return !e.alive; }), enemies.end()); shots.erase(std::remove_if(shots.begin(), shots.end(), [](Shot const &s) { return !s.active; }), shots.end());This style is also good because it separates the game logic from the implementation a bit more. For example, if you want to allow a shot to damage more than one enemy, you would have to use an approach like this for the shots array anyway.
Chapter on Double Buffering in the excellent Game Programming Patterns book goes into more depth.
SFML奇怪的射击bug(SFML weird shooting bug)我正在用C ++和SFML制作游戏。 我有一个奇怪的错误,每当我在屏幕上只有1个敌人和3个镜头并且子弹与敌人发生碰撞时,游戏就会崩溃。 我得到的错误是:
Expression: vector subscript out of range这就是我检查镜头和敌人之间碰撞的方法:
for (int i = 0; i < enemies.size(); i++) { for (int s = 0; s < shots.size(); s++) { if (Collision::PixelPerfectTest(enemies[i].getSprite(), shots[s].getSprite())) { enemies[i].setHealth(enemies[i].getHealth() - player.getDamage()); if (enemies[i].getHealth() <= 0) { enemies.erase(enemies.begin() + i); } shots.erase(shots.begin() + s); } } }“敌人”和“镜头”是我在主循环中每隔x秒插入的向量。 这是代码:
if (enemySpawner.getElapsedTime().asSeconds() >= 1.5f) { enemies.push_back(Enemy(spriteManager.enemySprite)); std::cout << enemies.size() << " enemies" << std::endl; enemySpawner.restart(); } if (shotSpawner.getElapsedTime().asSeconds() >= 0.3f && sf::Mouse::isButtonPressed(sf::Mouse::Left)) { shots.push_back(Shot(spriteManager.shotSprite, player.getPosition(), *window)); std::cout << shots.size() << " shots" << std::endl; shotSpawner.restart(); }正如我所说,这只发生在我有1个敌人和3个射击时,否则它似乎工作正常。
编辑:现在当第一个敌人产生时,游戏会冻结。 这是更新的代码:
//Shot vs enemy for (auto eit = enemies.begin(); eit != enemies.end();) { for (auto sit = shots.begin(); sit != shots.end();) { if (Collision::PixelPerfectTest((*eit).getSprite(), (*sit).getSprite())) { (*eit).setHealth((*eit).getHealth() - player.getDamage()); if ((*eit).getHealth() <= 0) { enemies.erase(eit); shots.erase(sit); } shots.erase(sit); eit = eit++; sit = sit++; } } }I'm making a game in C++ and SFML. I have a weird bug, whenever I have exactly 1 enemy and 3 shots on the screen and a bullet collides with the enemy, the game crashes. The error I get is:
Expression: vector subscript out of rangeThis is how I check for collision between shots and enemies:
for (int i = 0; i < enemies.size(); i++) { for (int s = 0; s < shots.size(); s++) { if (Collision::PixelPerfectTest(enemies[i].getSprite(), shots[s].getSprite())) { enemies[i].setHealth(enemies[i].getHealth() - player.getDamage()); if (enemies[i].getHealth() <= 0) { enemies.erase(enemies.begin() + i); } shots.erase(shots.begin() + s); } } }"enemies" and "shots" are vectors that I insert into every x seconds in the main loop. Here's the code for that:
if (enemySpawner.getElapsedTime().asSeconds() >= 1.5f) { enemies.push_back(Enemy(spriteManager.enemySprite)); std::cout << enemies.size() << " enemies" << std::endl; enemySpawner.restart(); } if (shotSpawner.getElapsedTime().asSeconds() >= 0.3f && sf::Mouse::isButtonPressed(sf::Mouse::Left)) { shots.push_back(Shot(spriteManager.shotSprite, player.getPosition(), *window)); std::cout << shots.size() << " shots" << std::endl; shotSpawner.restart(); }As I said, this only happens when I have 1 enemy and 3 shots, otherwise it seems to work fine.
EDIT: Now the game freezes when the first enemy spawns. Here's the updated code:
//Shot vs enemy for (auto eit = enemies.begin(); eit != enemies.end();) { for (auto sit = shots.begin(); sit != shots.end();) { if (Collision::PixelPerfectTest((*eit).getSprite(), (*sit).getSprite())) { (*eit).setHealth((*eit).getHealth() - player.getDamage()); if ((*eit).getHealth() <= 0) { enemies.erase(eit); shots.erase(sit); } shots.erase(sit); eit = eit++; sit = sit++; } } }最满意答案
@ moka的答案解释了代码的核心问题,他/她使用迭代器的代码将解决您的问题。 但是,还有另一种方法可以解决这个问题:将代码拆分为“计算通道”和“数组修改通道”。 代码看起来像:
for (int i = 0; i < enemies.size(); i++) { for (int s = 0; s < shots.size(); s++) { if (!enemies[i].alive || !shots[s].active) { continue; } if (Collision::PixelPerfectTest(enemies[i].sprite(), shots[s].sprite())) { shots[s].active = false; enemies[i].setHealth(enemies[i].getHealth() - player.getDamage()); if (enemies[i].getHealth() <= 0) { enemies[i].alive = false; } } } } enemies.erase(std::remove_if(enemies.begin(), enemies.end(), [](Enemy const &e) { return !e.alive; }), enemies.end()); shots.erase(std::remove_if(shots.begin(), shots.end(), [](Shot const &s) { return !s.active; }), shots.end());这种风格也很好,因为它将游戏逻辑与实现分开了一点。 例如,如果你想允许一个射击对一个以上的敌人造成伤害,那么无论如何你都必须使用这样的方法来射击阵列。
“优秀游戏编程模式”一书中关于双缓冲的章节更深入。
@moka's answer explains the core problem with your code, and his/her code using iterators will fix your problem. However, there is another way to deal with the problem: splitting your code into a "computation pass" and an "array modification pass." The code would look like:
for (int i = 0; i < enemies.size(); i++) { for (int s = 0; s < shots.size(); s++) { if (!enemies[i].alive || !shots[s].active) { continue; } if (Collision::PixelPerfectTest(enemies[i].sprite(), shots[s].sprite())) { shots[s].active = false; enemies[i].setHealth(enemies[i].getHealth() - player.getDamage()); if (enemies[i].getHealth() <= 0) { enemies[i].alive = false; } } } } enemies.erase(std::remove_if(enemies.begin(), enemies.end(), [](Enemy const &e) { return !e.alive; }), enemies.end()); shots.erase(std::remove_if(shots.begin(), shots.end(), [](Shot const &s) { return !s.active; }), shots.end());This style is also good because it separates the game logic from the implementation a bit more. For example, if you want to allow a shot to damage more than one enemy, you would have to use an approach like this for the shots array anyway.
Chapter on Double Buffering in the excellent Game Programming Patterns book goes into more depth.
发布评论