Танчики 1990. Играем в проектирование.

Условия задачи.

Разработать игру “танчики” на языке С++.

  • Игра состоит из игрового поля. На поле располагаются танки и препятствия.
  • Танки делятся на два вида: игровые и танки противника.
  • Игровые танки управляются игроком при помощи клавиатуры. Их может быть не более двух.
  • Танки противника передвигаются по полю в произвольном порядке и открывают огонь с различным интервалом времени.
  • Танки могут быть трех видов: легкий,средний, тяжелый. Скорость и броня обратно пропорциональна классу танка, т.е. легкий движется быстрее всех, но при первом попадании разрушается, тяжелый разрушается от трех попаданий но его скорость самая низкая.
  • Игровые препятствия могут быть двух видов. Разрушаемые и не разрушаемые ( например,стена кирпичная и из сверхпрочного материала). Попадание по разрушаемому препятствию приводит к его частичному уничтожению.
    В игре один уровень.
  • При уничтожении всех танков игрока- поражение. При уничтожении всех танков противника - победа.

Дополнительно:

У игрока имеется охраняемый объект, окруженный со всех сторон кирпичной стеной. При одном попадании по объекту ( после разрушения охраняющей его стены) игра завершается - игрок проиграл. Если все танки противника уничтожены, то засчитывается победа игрока. Переход следующий уровень.

А что вообще происходит?

По заветам Кренга Лармана выделим волеизъявителей (акторы) и сценарии, которые они запускают (use case). И так, в игре в первую очередь изменяются танки (двигаются, стреляют). Танки управляются пользователем и компьютером-противником. Танки компьютера можно наделить волей (собственный контекст исполнения), но боюсь закопаться в многопоточности, поэтому пусть они управляются из единого центра.

Компьютеры у нас дискретные, поэтому общий случай действия противника будет шаг игры, какой конкретно будет вычисляться по ходу (random). Реализовывать будем сценарий выстрела.

Чем оперируем.

Читаем условия задачки и выделяем существительные. Это будут объекты между которыми происходит взаимодействия. И так, у нас есть:

  • Поле битвы
  • Танки
  • Летящие снаряды (они могут быть или не быть, они обладают направлением)

Для упрощения о стенах и орлах (охраняемый объект) забудем.

Движуха.

Как уже говорилось выше, действия у нас дискретные. Шаг запускается либо нажатием кнопки (игроком), либо сигналом таймера (ход/действие компьютера). Танк может стоять (Idle), двигаться (Move) и стрелять (Fire). Движение пока не будем проектировать вглубь, разработаем происходящее при выстреле. Когда танк открывает огонь инстанционируется снаряд, вычисляется есть ли на траектории снаряда цель, и если она есть, то отмечаем попадание.

Распределяем состояние игры.

Начнем с простого - со снаряда. У него есть точка запуска, у него есть направление, по этим данным строим луч и проверяем пересекает ли этот луч какую-нибудь цель. Для упрощения у него будет бесконечная скорость (чтобы не рассчитывать его позицию).  Танк знает свою позицию (для точки запуска снаряда), у танка есть флажок жив/убит (этот флажок в дальнейшем можно расширить до поля HP). Игровое поле я планирую использовать как точку входа и маршрутизатор эвентов, соответственно в нем должны быть танки. По игровому полю вычисляется попадание/промах выстрела. Можно конечно перебирать все (противника) танки в поле и смотреть попадает ли положение танка на луч снаряда, но это такое себе. Так что в игровом поле должны быть еще и позиции всех танков. Дублировать позицию в танке и в поле плохая идея - обновлять нужно в двух местах, возможен разъезд данных. Поэтому вынесем позицию в отдельную сущность, а в игровое поле и танк вставим ссылку на позицию.

Целься, пли!

При приходе эвента выстрела находим в игровом поле стреляющий танк (ключ - поле Id танка в эвенте). Дальше танк на основе своей позиции и направления выстрела  (содержится в эвенте) создает снаряд. Игровое поле проверяет есть ли на пути снаряда цель, если есть, то цель помечается  убитой (метод kill танка-цели).


Заглавная картинка взята отсюда.