Убьём врага прыжком сверху, при этом он удалится из списка. Врагов можно убивать разными способами – выстрел, прыжок, какие то иные “супер действия”, которые приведут его к гибели (тому пример какие-то оригинальные битвы с боссами). Но суть одинакова – если у врага <=0 жизней, то life=false.
Видеоверсия http://www.youtube.com/watch?v=3EM5NzJaJpY
Собственно уже дальше – если life==false, то удаляем врага из списка, он пропадает. Перед этим можно забацать красивую анимацию со взрывом/кровью и подобающими звуками. Анимацию и звуки мы делать пока не будем – оставим это на следующий раз. Сейчас наша задача убить врага с прыжка, при этом герой должен слегка отскочить вверх (как в марио при убийстве врага), а враг должен пропасть и удалиться из списка.
Сейчас сделаем простое взаимодействие со спрайтами игрока и врага. Под взаимодействием будем понимать пересечение. Как вы знаете – спрайт накидан на прямоугольник и именно прямоугольники мы и будем проверять на пересечение. У нас уже достаточно инструментов для выполнения этого действия, нам в этом поможет функция getRect(), которая должна быть у вас в методах класса Entity. Все объекты будут её использовать, поскольку все они пересекаются в нашем тесном игровом мире друг с другом.
Функция getRect дословно означает get Rectangle – “получить прямоугольник”. Если ваши функции что-то возвращают, то логично их называть get+то,что они возвращают. Если ваша функция предполагает изменение\задание чего-либо, то логичнее будет её назвать set+то,что ваша функция изменяет\задаёт.
getRect() в Entity
1 2 3 |
FloatRect getRect(){ return FloatRect(x, y, w, h); } |
Теперь после вызова update игрока напишем такие строки (отвечают за удаление объекта из списка):
1 2 3 4 5 6 7 |
for (it = entities.begin(); it != entities.end();)//говорим что проходимся от начала до конца { Entity *b = *it;//для удобства, чтобы не писать (*it)-> b->update(time);//вызываем ф-цию update для всех объектов (по сути для тех, кто жив) if (b->life == false) { it = entities.erase(it); delete b; }// если этот объект мертв, то удаляем его else it++;//и идем курсором (итератором) к след объекту. так делаем со всеми объектами списка } |
Они позволят нам удалять объект из списка, если у него жизни==ложь. Учтите, что предыдущий вызов update (прошлые уроки) для элементов списка следует удалить, иначе вы вызовете две ф-ции update. Но вы это заметите, т.к объекты будут быстрее двигаться =)
Теперь после этого пишем:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
for (it = entities.begin(); it != entities.end(); it++)//проходимся по эл-там списка { if ((*it)->getRect().intersects(p.getRect()))//если прямоугольник спрайта объекта пересекается с игроком { if ((*it)->name == "EasyEnemy"){//и при этом имя объекта EasyEnemy,то.. if ((p.dy>0) && (p.onGround == false)) { (*it)->dx = 0; p.dy = -0.2; (*it)->health = 0; }//если прыгнули на врага,то даем врагу скорость 0,отпрыгиваем от него чуть вверх,даем ему здоровье 0 else { p.health -= 5; //иначе враг подошел к нам сбоку и нанес урон } } } } |
как вы заметили – intersects как раз и проверяет пересечение двух прямоугольников наших спрайтов. Аналогичным образом можно сделать и взаимодействие между двумя объектами списка, нам понадобится второй итератор. Сделаем это на одном из следующих уроков.
Как видим здоровье врага становится равно 0, а у нас в Enemy update есть такая строка:
1 |
if (health <= 0){ life = false; } |
Вот благодаря ей программа видит кто умер и кого надо удалить из игры.
Теперь при напрыгивании на врага – он умирает. Когда нибудь взорвём его к чертям :)) Ближе к середине лета)
Скриншотов нету т.к показывать тут нечего. Все так же как в прошлый раз, только можем удалять элемент из списка, в частности врага, напрыгивая ему на голову.
Хотелось бы отметить, что можно добавить условие, которое позволит убивать врага только прыгая ему на голову. То есть если попали на автомобиль – это минус здоровье. Следующий урок будет посвящен взаимодействию между прямоугольниками, а именно – разберем как работать с пересечениями этих прямоугольников.
Кстати говоря
Как выяснилось у нас много желающих делать домашнее задание, что меня порадовало Будет несколько уровней сложности/видов, выбирайте любой или делайте все. Как угодно :))
Домашка к уроку 24:
http://www.youtube.com/watch?v=Z_xli5aS2SQ
задание 1:
сделайте так, чтобы после убийства врага он появлялся в новом конкретном месте
задание 2:
наш враг не умрет если мы слетим с пола вниз на него не подпрыгивая (т.е не нажимая клавишу прыжка). необходимо реализовать его смерть и в этом случае.
задание 3:
сделайте так, чтобы после убийства врага он появлялся в новом конкретном месте и не на глазах у игрока, при этом имел большую скорость и здоровье
задание 4:
сделайте так, чтобы после убийства врага он появлялся в новом случайном месте и не на глазах у игрока
Свои решения присылаете в новый раздел на форуме, создавая тему с названием: Урок 24-1 появление врага после убийства
Где 24 это номер урока, а 1 – номер задания.
вот такая проблема:
есть список патронов, который проверяется на то жив ли патрон или мертв. если мертв, то он должен убираться из списка, но при таком коде, выскакивает ошибка: Expression: list iterator not incrementable
…..
std::list<Bullet*> projectileList;
std::list<Bullet*>::iterator pt;
…..
for ( pt = projectileList.begin(); pt != projectileList.end();)//цикл проверки каждого патрона который на то жив ли он(летит) илил мертв(тоесть уже попал в цель)
{
(*pt)->update(time);//обновляем его местоположение
if ((*pt)->life == false)//если жизнь равна false то мы его удаляем
{
pt = projectileList.erase(pt);//удаляем обьект из списка
delete *pt++;//удаляем указательна него и переходим к следующему
}
else
pt++;// если обьект не мертв, то переходим к следующему
}
проблему решил )