Уроки Коммент.

Создание игр » Новости » Создание игры. Выстрелы и столкновения.

Создание игры. Выстрелы и столкновения.

Создание игры. Выстрелы.В создаваемой нами игре уже есть главный герой, которым мы можем управлять, есть враги, которые летят по экрану сверху вниз, мы уже создали фон для игры и вообще всё хорошо ) Но теперь пришла пора сделать игру игрой. А в нашем случае это означает, что нам нужно, что бы мы могли стрелять, что бы враги стреляли в нас и все эти выстрелы кого-то поражали и убивали. Заодно имеет смысл сделать, что бы при столкновении корабля игрока и корабля противника так же происходил бы взрыв и оба корабля теряли жизни (либо сразу погибали). Давайте всеми этими вопросами и займёмся в этом уроке по созданию игр.

Первым делом решим, как будем проверять столкновения кораблей друг с другом и со снарядами. Давайте выберем простейший способ – будем считать корабли окружностями, а снаряды точками, так вычисления упростятся максимально…

Зададим радиус окружности для живых объектов:

// это добавим в объявление класса 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(); // удаляем последний
	}
}

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

Вы можете скачать демку игры или скачать проект с исходным кодом.

Ещё по этой теме:




Раздел: Новости

6 комментариев на "Создание игры. Выстрелы и столкновения."
  1. RomU4 пишет:

    Классные уроки, с нетирпением жду продолжения…

    игрушка такая компактная получается, я поначалу думал что кода будет куда больше.
    Также хотелось бы на сайте увидеть уроки по GL в связке с SDL.

    И еще непомешали бы уроки по физике. Спасибо =)…

    1. Вячеслав пишет:

      RomU4, спасибо за отзыв, рад что Вам понравилось. Своими уроками я как раз хочу показать, что игры делать совсем не сложно – надо лишь иметь немного желания и планировать свою работу. Уроки по ОГЛ + SDL, к сожалению, обещать не могу – я достаточно давно с ними не работаю, т.к. последние годы сосредоточился именно на DirectX. А вот статьи по физике будут уже в самое ближайшее время.

  2. Roman пишет:

    Неплохо!
    А разве пули противников и врагов не надо удалять?

    1. Вячеслав пишет:

      Конечно же надо.

  3. Сергей пишет:

    Вячеслав, уроки безусловно отличны! Хотелось бы узнать, есть ли способы апроксимации по проверки столкновений? Так как если в игре будет множество объектов, допустим 50 кораблей, каждый из них будет вести стрельбу, допустим 10 выстрелов за время жизни одного выстрела, то получится слишком накладно с точки зрения просчетов.

    1. Вячеслав пишет:

      Обычно коллижены считаются сначала на уровне ААББ, а потом уже на уровне масок. Таким образом обычно можно без проблем считать сотни и иногда даже тысяч пересечений каждый кадр. При этом часто можно “выстрел” упростить до точки, либо до отрезка, что ещё больше упрощает ситуацию и ускоряет расчёты.

Оставить комментарий

*

Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>