Предупреждение: вопрос от неискушенного :)
Привет,
Я делаю макет космических захватчиков для домашнего задания и работаю над пулями, которые корабль и инопланетяне будут выпускать/сбрасывать. У меня есть абстрактный базовый класс для обработки всех пуль с двумя производными классами — ракетой и бомбой.
Первоначально я использовал вектор, но где-то читал, что список будет более эффективным, поскольку они будут добавляться и удаляться так быстро (?). Тем не менее, я новичок в списках, и у меня есть некоторые проблемы с этим. Честно говоря, я не совсем уверен, как и могу ли я вообще использовать список с абстрактным классом.
Я еще не реализовал класс бомбы, потому что хочу сначала заставить работать класс ракеты.
Вот, например, заголовок базового класса (выстрел) + ракета:
enum attackType { BOMB, MISSILE };
class shot
{
private:
float xPos,
yPos;
attackType bombOrMissile;
public:
shot(Vector2f pos, attackType b_OR_m); // passed ship pos + who fired shot
virtual void draw(RenderWindow & win) = 0; // draws bullet on screen
virtual Sprite & getSprite() = 0; // gives sprite information
};
class missile : public shot
{
private:
Sprite missileSprite;
public:
missile(Vector2f pos, Texture & t);
void draw(RenderWindow & win);
Sprite & getSprite();
};
У меня есть класс «Менеджер выстрелов», который управляет списком пуль. Он увеличивает/уменьшает список и изменяет положение спрайта.
Заголовок:
class shotMgr
{
private:
list<shot*> shotsFired;
Texture missileTexture;
public:
shotMgr(); // loads texture
void shoot(attackType b_OR_m, Vector2f pos);
void disappear();
void move();
void draw(RenderWindow& win);
int getAmountFilled() { return shotsFired.size(); }
};
мой главный вопрос: как я могу здесь разобраться с синтаксисом? Я запутался, пытаясь обойти ptrs. Является ли вектор в конечном итоге лучшим вариантом в этом случае, или я просто что-то делаю неправильно?
Вот одна из моих функций shotMgr, чтобы продемонстрировать, что я сейчас делаю (она не компилируется); другие функции аналогичны синтаксически:
void shotMgr::disappear()
{
list<shot>::iterator iter;
for (iter = shotsFired.begin(); iter != shotsFired.end();)
{
if (iter->getSprite().getPosition().y < 0)
{
iter = shotsFired.erase(iter);
}
else
iter++;
}
}
Мы будем очень признательны за любые советы. Спасибо!
@супер Спасибо! Это отличный совет. Теперь это работает.
Возможно, вы захотите прочитать онлайн-книгу gameprogrammingpatterns и, в частности, gameprogrammingpatterns.com/update-method.html
@Ian4264 Спасибо за рекомендацию! Я обязательно посмотрю на это.





std::vector наиболее эффективен при добавлении и удалении в конце коллекции. Когда код вставляет или удаляет где-либо еще в векторе, все элементы с индексом, большим, чем элемент, к которому осуществляется доступ, подвергаются "перемещению". То есть, когда вы вставляете, все, что находится справа от этого элемента в массиве, должно «перемещаться на единицу». Точно так же, когда вы удаляете, все, что находится справа от удаляемого элемента, должно скользить влево. Не отличается от того, если бы вы использовали обычный массив в качестве коллекции.
std::list больше похож на связанный список. Может использовать немного больше памяти на элемент, но определенно лучше для случайных вставок и удалений. Но использование list vs vector не является корнем вашей проблемы.
Что касается вашей ошибки компиляции. Скорее всего из-за этого:
list<shot>::iterator iter;
Вы объявляете итератор для list<shot>::iterator, но ваша коллекция имеет тип list<shot*>. Так что вы, вероятно, хотите list<shot*>::iterator. Давайте исправим вашу функцию. auto на помощь, чтобы вам не пришлось слишком много думать об этом.
void shotMgr::disappear()
{
for (auto iter = shotsFired.begin(); iter != shotsFired.end();)
{
shot* ptrShot = *iter;
if (ptrShot->getSprite().getPosition().y < 0)
{
iter = shotsFired.erase(iter);
}
else
{
iter++;
}
}
}
Большое спасибо! Это было отличное объяснение, и оно отлично работает. Очень признателен.
Вероятно, вам стоит остаться с
std::vector. Список может вставлять и удалять элементы из любой позиции быстрее, но почти во всем остальном он будет медленнее, чем вектор. Вы пытаетесь использоватьlist<shot>::iteratorвместоlist<shot*>::iterator. Может быть, что-то еще не так, просто бегло посмотрел. Использованиеauto iter = shotsFired.begin()— хорошая идея в тех случаях, когда очевидно, к какому типу данных относитсяauto.