Игра Морской бой на JavaScript. Редактирование положения корабля и начало игры.

Вступление.

Третья статья из цикла «Игра Морской бой на чистом JavaScript». В этой статье мы рассмотрим:

  1. Редактирование положение кораблей на игровом поле.
  2. Изменения направления расположения палуб путём поворота корабля на 90°.
  3. Начало игры.
  4. Инициализацию контроллера игры.

Прежде чем читать дальше, необходимо ознакомиться со статьёй «Игра Морской бой на JavaScript. Расстановка кораблей методом перетаскивания.», иначе вам не всё будет понятно в этой статье.

Игра «Морской бой». Редактирование положения корабля.

Код редактирования положения корабля на игровом поле практически ничем не отличается от кода, реализующего его перемещения. При этом используются те же самые обработчики событий onMouseDown, onMouseMove и onMouseUp с небольшими изменениями и дополнениями.

Игра «Морской бой». Начало редактирования положения корабля.

Инициирование редактирования положения корабля так же, как и начало переноса, начинается с нажатия левой кнопки мыши на корабль. Отличие состоит в том, что в объект dragObject, в котором запоминаются свойства переносимого элемента, записывается дополнительная информация — значения left и top, прописанные в атрибуте style. Эта информация будет использоваться для возвращения корабля в исходное место при невалидных координатах его нового местоположения.

Корабль может быть расположен как горизонтально, так и вертикально. Поэтому необходимо получить направление расположения его палуб. Как вы помните, полная информация о каждом экземпляре корабля хранится в массиве squadron и, зная имя корабля, эту информацию можно получить из этого массива.

Запишем в конец функции onMouseDown следующий код:

Теперь полный код функции onMouseDown выглядит так:

Игра «Морской бой». Перемещение корабля при редактировании положения.

Перемещение корабля при редактировании его положения ничем не отличается от его первоначальной установки, поэтому используется тот же самый функционал с небольшим дополнением.
После создания клона, необходимо удалить всю информацию о сдвигаемом корабле из объекта squadron и матрицы, где отмечено расположение палуб редактируемого корабля. После окончания редактирования, туда будет записана новая информация о положении корабля. Для удаления данных создадим функцию removeShipFromSquadron и вызовем её сразу после создания клона. Теперь JS-код создания клона в функции onMouseMove будет выглядеть так:

Рассмотрим функцию removeShipFromSquadron. Её код достаточнопростой и будет достаточно комментариев внутри функции:

Игра «Морской бой». Поворот корабля на 90°.

Поворот корабля на 90° будем осуществлять кликом по нему правой кнопкой мыши, при котором возникает событие contextmenu. Чтобы не вешать обработчик события на каждый корабль, воспользуемся делегированием и с помощью метода addEventListener вешаем всего лишь один обработчик на родительский элемент — humanfield. Данный обработчик при срабатывании будет вызывать функцию rotationShip.

В код, где у нас регистрируются обработчики события, добавим ещё одну строчку:

Рассмотрим алгоритм работы функции rotationShip, являющейся методом класса Placement, по шагам:

  • 1

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

  • 2

    Получаем id корабля, по которому был сделан клик, т. к. id совпадает с именем корабля.

  • 3

    Полная информация о каждом корабле хранится в объекте human.squadron. Обходим данный объект в поисках корабля с именем равным полученному id.

  • 4

    Меняем у найденного корабля значения специальных коэффициентов kx и ky на противоположные. Если kx == 0 и ky == 1 — корабль расположен горизонтально, если kx == 1 и ky == 0, то вертикально.

  • 5

    Использую функцию removeShipFromSquadron, удаляем устаревшую информацию о расположении палуб корабля из объекта эскадры и двумерного массива matrix.

  • 6

    При помощи функции checkLocationShip проверяем валидность координат при новом направлении расположения палуб. Если координаты окажутся невалидны, то возвращаем старые значения коэффициентов kx и ky.

  • 7

    Используя конструктор Ships, создаём новый экземпляр корабля.

  • 8

    Подсветим на 0.75 сек. красным цветом контур корабля, если в результате проверки валидности было получено false — так мы визуально покажем, что поворот корабля невозможен.

Внимание.
Более подробно об объекте squadron, функции checkLocationShip, создании экземпляра корабля и конструкторе Ships изложено в статье «Игра Морской бой на JavaScript. Рандомная расстановка кораблей.»

Теперь, когда разобрались с алгоритмом поворота корабля на 90°, напишем функционал реализующий этот алгоритм. Полный код функции:

Игра «Морской бой». Запуск игры.

Игра запускается при нажатии на кнопку «Play». Изначально она не отображается, пока все десять кораблей эскадры игрока не будут расставлены на игровом поле. Соответственно, эта кнопка видна при редактировании положения кораблей эскадры.
При клике на кнопку «Play» происходит следующее:

  1. Убирается поле с инструкцией и контейнер shipsCollection.
  2. Выводится игровое поле компьютера и на нём рандомно расставляются корабли. Естественно, визуально они не отображаются.
  3. Скрывается кнопка «Play» и выводится сообщение, информирующее о начале игры.
  4. Удаляются обработчики событий привязанные к игровому полю игрока:
    — редактирование положения кораблей;
    — поворот корабля на 90°.
  5. Создаётся экземпляр класса Controller управляющего игрой.

JavaScript, реализующий данный функционал, не сложный. Особое внимание хочется обратить на расстановку кораблей компьютера. Для этой цели используются таже самая функция, что и при рандомной расстановке кораблей игрока — randomLocationShips, только перед этим создаётся экземпляр computer при помощи конструктора Field и очищается игровое поле компьютера от ранее расставленных кораблей. Это актуально при перезапуске игры.

Внимание.
Более подробно о конструкторе Field и работе функции randomLocationShips изложено в статье «Игра Морской бой на JavaScript. Рандомная расстановка кораблей.»

Полный код обработчика события запуска игры:

Флаг startGame нужен для блокировки изменения расстановки кораблей игроком во время игры.

Игра «Морской бой». Контроллер управления игрой «Морской бой».

Весь геймплей игры «Морской бой», реализован в классе Controller. Рассмотрим, какие задачи выполняет данный класс:

  • 1

    Подготовка к игре «Морской бой»: регистрация ряда массивов, для координат выстрелов компьютера для различных игровых ситуаций.

  • 2

    Инициализация игры «Морской бой»:
    — рандомно определяется, кто стреляет первым и выводится сообщение об этом;
    — генерируются координаты выстрелов компьютера, на основе оптимального порядка обстрела игрового поля противника;
    — устанавливаются обработчики событий (нажатие левой и правой кнопок мыши) для игрока;

  • 3

    Формирование выстрела и его визуальное отображение.

  • 4

    Обработка результата выстрела и установка иконки, соответствующей результату. Вывод текстовой информации о результате и о том, чей следующий выстрел.

  • 5

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

  • 6

    Управление ведением боя компьютером:
    — анализ игровой ситуации;
    — выбор оптимальных координат для выстрела;
    — обстрел «раненого» корабля с учётом предыдущих попаданий и промахов.

  • 7

    Подсчёт количества потопленных кораблей в эскадрах игрока и компьютера и определение победителя.

  • 8

    Перезапуск игры после окончания морского боя.

В этой статье мы рассмотрим подготовку к игре и её инициализацию. Хочу сразу предупредить, что все функции, которые будут разобраны ниже, являются методами класса Controller и расположены в пределах его области видимости.

Игра «Морской бой». Подготовка к игре.

Прежде всего рассмотрим конструктор класса Controller. Конструктор инициализирует ряд переменных, в которых, на момент выстрела, содержится информация о стреляющем и его противнике. Также инициализируются три массива, в которых будут храниться координаты выстрелов компьютера для различных игровых ситуаций:

coordsFixedHit
массив с заранее вычисленными координатами выстрелов для реализации оптимальной тактики игры;
coordsRandomHit
массив с координатами, оставшихся после использования всех координат массива coordsFixed;
coordsAroundHit
массив с координатами вокруг клетки с попаданием.

Кроме инициализации переменных и массивов, конструктор вызывает функцию resetTempShip. Функция очищает временный объект корабля, куда будем заносить координаты попаданий, расположение корабля, количество попаданий. Это необходимо при повторном запуске игры, когда все данные сбрасываются в исходное состояние.

JS-код конструктора:

JS-код функции resetTempShip:

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

START_POINTS
массив базовых координат для формирования массива coordsFixedHit;
SERVICE_TEXT
блок, в который выводятся информационные сообщения в процессе игры;
showServiceText
вывод информационных сообщений под игровыми полями;
getCoordsIcon
преобразование абсолютных координат иконок в координаты матрицы;
removeElementArray
удаление ненужных координат из массива.

JS-код класса Controller на данном этапе:

Игра «Морской бой». Инициализация игры.

Инициализация игры происходит в функции init, являющейся методом класса Controller. Так как функция вызывается из обработчика события запуска игры, т. е. за пределами области видимости класса, для её вызова используется созданный экземпляр класса control.

Что делает функция init:

  1. Рандомно определяет, кто стреляет первым. Исходя из этого задаёт значения свойствам player и opponent.
  2. Устанавливает для игрока обработчики событий:
    — нажатие на левую кнопку мыши (выстрел);
    — нажатие на правую кнопку мыши (маркирование пустой клетки).
  3. Выводит под игровыми полями сообщение о том, кто стреляет первым.

JS-код функции init:

На данном этапе подготовка к игре закончена полностью. В следующей статье мы рассмотрим выстрел игрока.

Комментарии

Всего: 2 комментария
Требования при посте комментариев:
  1. Комментарии должны содержать вопросы и дополнения по статье, ответы на вопросы других пользователей.
    Комментарии содержащие обсуждение политики, будут безжалостно удаляться.
  2. Для удобства чтения Вашего кода, не забываейте его форматировать. Вы его можете подсветить код с помощью тега <pre>:
    <pre class="lang:xhtml"> - HTML;
    <pre class="lang:css"> - CSS;
    <pre class="lang:javascript"> - JavaScript.
  3. Если что-то не понятно в статье, постарайтесь указать более конкретно, что именно не понятно.
  • Хотел узнать, когда сможете выложить следующую четвертую статью «Морской бой»? Очень интересный ход работы над игрой.

  • В данный момент пишу статью. Надеюсь, через неделю будет готова.

Добавить комментарий для Азамат

Ваш адрес email не будет опубликован. Обязательные поля помечены *