Создание игр » Featured, Уроки » Создание игры. Выстрелы и столкновения.
Создание игры. Выстрелы и столкновения.
В создаваемой нами игре уже есть главный герой, которым мы можем управлять, есть враги, которые летят по экрану сверху вниз, мы уже создали фон для игры и вообще всё хорошо ) Но теперь пришла пора сделать игру игрой. А в нашем случае это означает, что нам нужно, что бы мы могли стрелять, что бы враги стреляли в нас и все эти выстрелы кого-то поражали и убивали. Заодно имеет смысл сделать, что бы при столкновении корабля игрока и корабля противника так же происходил бы взрыв и оба корабля теряли жизни (либо сразу погибали). Давайте всеми этими вопросами и займёмся в этом уроке по созданию игр.
Первым делом решим, как будем проверять столкновения кораблей друг с другом и со снарядами. Давайте выберем простейший способ – будем считать корабли окружностями, а снаряды точками, так вычисления упростятся максимально…
Зададим радиус окружности для живых объектов:
// это добавим в объявление класса CLiveObject float m_fRadius; // радиус для столкновений // функция получения радиуса объекта float Radius() const; // функция для проверки столкновения с другим CLiveObject bool TestCollision(const CLiveObject& obj) const; // это добавим в конструктор CLiveObject m_fRadius(28) // чуть меньше радиуса спрайта //и сама функция проверки bool CLiveObject::TestCollision( const CLiveObject& obj ) const { // вектор от одного объекта до другого D3DXVECTOR2 dist = obj.Pos()-Pos(); // если расстояние меньше или равно сумме радиусов if (obj.Radius()+Radius()>=D3DXVec2Length(&dist)) return true; // столкновение return false; // иначе нет } |
Теперь выстрелы. Создадим класс снаряда:
class CBullet { float m_iDamage; // урон D3DXVECTOR2 m_pos; // текущая позиция D3DXVECTOR2 m_speed; // текущая скорость //! Текстура со спрайтом снаряда CTexturePtr m_pTex; public: CBullet(D3DXVECTOR2 pos=D3DXVECTOR2(0,0), D3DXVECTOR2 speed=D3DXVECTOR2(0,0)); ~CBullet(void); D3DXVECTOR2 Pos() const; void Draw() const; int Damage() const; void Update(float fDeltaTime); // апдейт снаряда bool TestCollision(const CLiveObject& obj) const; }; |
Дополним основной цикл приложения. Кстати, в прошлом примере забыл одну вещь – надо удалять корабли противника, когда они вылетают за экран, иначе будут утечки памяти и они будут впустую считаться (чем дольше играем, тем больше игра будет требовать памяти и больше тормозить). Собственно, вот код:
for (size_t i=0; i<vecEnemies.size(); i++) { vecEnemies[i].Update(.02f); // проверяем столкновение с игроком if (vecEnemies[i].TestCollision(*g_pPlayer)) vecEnemies[i].DoDamage(100); // наносим урон // проверяем столкновение со снарядами игрока for (size_t j=0; j<vecBulletPlayer.size(); j++) if (vecBulletPlayer[j].TestCollision(vecEnemies[i])) { vecEnemies[i].DoDamage(vecBulletPlayer[j].Damage()); vecBulletPlayer[j] = * vecBulletPlayer.rbegin(); vecBulletPlayer.pop_back(); } // проверяем на вышел ли за экран if (vecEnemies[i].Pos().y>400) vecEnemies[i].DoDamage(100000); // уничтожаем if (!vecEnemies[i].IsAlive()) // если объект умер { // копируем последний в текущий vecEnemies[i] = *vecEnemies.rbegin(); vecEnemies.pop_back(); // удаляем последний } } |
Осталось только создать практически идентичный код для врагов – что бы они так же могли стрелять в игрока, как он стреляет в них. Думаю, как это сделать понятно, потому код приводить не буду. В конце-концов, кому интересно – можете попробовать сделать сами и потом сравнить с тем, что получилось у меня.
Вы можете скачать демку игры или скачать проект с исходным кодом.
Раздел: Featured, Уроки · Теги: Создание игр
Классные уроки, с нетирпением жду продолжения…
игрушка такая компактная получается, я поначалу думал что кода будет куда больше.
Также хотелось бы на сайте увидеть уроки по GL в связке с SDL.
И еще непомешали бы уроки по физике. Спасибо =)…
RomU4, спасибо за отзыв, рад что Вам понравилось. Своими уроками я как раз хочу показать, что игры делать совсем не сложно – надо лишь иметь немного желания и планировать свою работу. Уроки по ОГЛ + SDL, к сожалению, обещать не могу – я достаточно давно с ними не работаю, т.к. последние годы сосредоточился именно на DirectX. А вот статьи по физике будут уже в самое ближайшее время.
Неплохо!
А разве пули противников и врагов не надо удалять?
Конечно же надо.
Вячеслав, уроки безусловно отличны! Хотелось бы узнать, есть ли способы апроксимации по проверки столкновений? Так как если в игре будет множество объектов, допустим 50 кораблей, каждый из них будет вести стрельбу, допустим 10 выстрелов за время жизни одного выстрела, то получится слишком накладно с точки зрения просчетов.
Обычно коллижены считаются сначала на уровне ААББ, а потом уже на уровне масок. Таким образом обычно можно без проблем считать сотни и иногда даже тысяч пересечений каждый кадр. При этом часто можно “выстрел” упростить до точки, либо до отрезка, что ещё больше упрощает ситуацию и ускоряет расчёты.