Урок 23 SFML Создание нескольких врагов

Когда мы создаем врага – мы создаем один экземпляр класса Enemy. Что если нам нужно 50 врагов? Нам что создавать разные экземпляры врагов ещё и задавать им разное имя?

Видеоверсия ( http://www.youtube.com/watch?v=AlwrUT_U_A4 )

Получается вот такие строки будут повторяться 50 раз?

И тд…

А если мы захотим удалить объект, ведь врага можно убить. В общем, нам нужно как-то это обойти и сделать всё проще и удобнее.

Будем использовать список – занесем в него объекты, а именно врагов.

Давайте расставим на карте с помощью tiled map editor ещё несколько объектов врагов с именем EasyEnemy.

lesson 23 sfml
lesson 23 sfml

Проверьте, чтобы были подключены в main.cpp:

В функции int main() создадим список ( хорошо про список здесь – https://youtu.be/KNVPFVG49Oc?t=10m25s ) entities типа данных Entity (потому что класс – пользовательский тип данных), в него будем помещать потом практически всех, кого бывает много.. (пули, ездящие платформы, враги). ну кроме игрока соответственно)

Далее забираем  врагов

Теперь закинем в наш ранее созданный список всех врагов из карты tmx:

Таким образом мы поместим столько врагов в нашу игру, сколько их на карте .tmx , причем у каждого элемента вектора (то есть объекта врага с карты) своя координата “нахождения” этого врага на карте. Эти координаты и передаются:

А создание одного врага надо удалить:

Осталось только вызвать функцию update для всех элементов списка.
Но у нас сейчас не получится – этой функции вообще нет в Entity, а список у нас типа Entity. Поэтому – в классе Entity добавим:

Виртуальная функция — это функция, объявленная с ключевым словом virtual в базовом классе и переопределенная в одном или в нескольких производных классах.




Всё, теперь можем юзать ф-цию update для элементов списка entities , и врубаться будет именно update класса Enemy, поскольку именно объекты Enemy хранятся в списке типа Entity.

Таким образом можно будет вызывать ф-цию update и для платформ и для пуль и тд.

Вызываем ф-цию update:

Осталось нарисовать наши объекты из списка:

враги в sfml урок 23
враги в sfml урок 23

В списке в каждом элементы есть данные и указатель на следующий элемент списка. Давайте предположим, что у нас есть список из трёх врагов (на картинке ниже односвязный список. в уроке двусвязный, но пока его используем как односвязный, так что смысл тот же):

список врагов sfml
список врагов sfml

При удалении элемента посередине указатель первого элемента будет указывать на третий и всё.

Вобще элементы списка разбросаны по памяти, в отличие от вектора – там они идут последовательно и для них выделяется память целыми блоками.

Вектор , например, последовательно хранит блоками данные в памяти, поэтому в векторе можно очень быстро получать произвольный доступ к элементу вектора, зато удаление из середины происходит дольше, поскольку все ячейки должны будут сдвинуться влево. Зато в векторе быстро удаляются элементы из конца, например. Кстати , при удалении элемента из вектора память может не освободиться, это потому, что вектор хавает блоки памяти.

Вобще вот тут написано, вкладка “за и против”:
https://ru.wikipedia.org/wiki/Vector_(C%2B%2B)

Вобщем для разных задач нужны разные контейнеры. Вектор хорошо лепится к полоске здоровья персонажа-последний элемент добавляем или удаляем в зависимости от урона по персонажу или пополнению здоровья.

Буду благодарен, если поделитесь:
SFML вопросы, прошу, задавайте на форуме.
  1. У меня 5 методов инициализации моего объекта (LoadMassAnim(SkeletAnim); setAnimPropers(seconds(0.2), true, false); SetSpeed(5); SetPos(900, 750, 100); LoadObjectMass(ZombieMass, i, 10);)// последние это передача силки на массив элементу массива.

    Как это сделать через список ?

  2. Ради справедливости хотелось бы отметить, что std::list является двунаправленным списком (иначе как бы мы могли использовать обратные итераторы rbegin и rback?). Пруф (второй абзац). Но это никак не влияет на качество урока, ибо как всегда пять с плюсом! :-)

    Единственное, что хотелось бы уточнить, почему автор избегает использования “нового” for’a для обхода контейнеров? На это есть конкретные причины или это просто такой олд скул? :-)

      1. В общем, да. Но foreach в шарпе :-) Я говорил об этом:

        Вот на Вики. И по-моему с итераторами менее наглядно, хотя более полезно :-) В любом случае, это не так уж и важно, я из любопытства. Некоторые избегают этой записи, чтобы с C++ 11 не связываться.

  3. Есть ли смысл для однотипных врагов каждый раз загружать картинку, создавать текстуру ( про спрайт фз, может быть потом будет проблемой проверить столкновение для враг / враг … хотя можно написать свою проверку на столкновение учитывая ток координаты).
    Не экономичнее хранить только координаты для однотипных врагов.

    Но пока не решил вопрос: где и как.

    1. мы не загружаем картинку каждый раз для однотипных врагов. мы загрузили картинку один раз и передали по ссылке. если бы передали по значению – создавалась бы копия этой картинки для каждого врага и нерационально раздувалась бы память

Добавить комментарий