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

Вступление.

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

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

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

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

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

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

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

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

Код функции getDirectionShip:

Обновлённый код обработчика события onmousedown:

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

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

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

За окончание редактирования положения корабля, также, как и за окончание переноса, отвечает функция onMouseUp, вызываемая обработчиком события onmouseup.

Редактируемый корабль имеет атрибут style в котором прописано смещение относительно левого верхнего угла игрового поля. Этот атрибут нужно учитывать при окончании переноса, если придётся возвращать корабль на исходную позицию. Если проигнорировать этот атрибут, то корабль установится в левый верхний угол игрового поля, независимо от первоначального местоположения.

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

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

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

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

Рассмотрим алгоритм работы функции rotationShip по шагам:

  • 1

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

  • 2

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

  • 3

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

  • 4

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

  • 5

    При помощи функции checkLocationShip проверяем валидность координат при новом направлении расположения палуб.

    Перед проверкой необходимо удалить экземпляр корабля, иначе результатом работы функции checkLocationShip всегда будет false — будет считаться, что в соседних клетках есть какой-то корабль.

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

  • 6

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

  • 7

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

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

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

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

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

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

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

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

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

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

Весь gameplay игры «Морской бой», реализован в модуле Controller. В данном случае применена наиболее распространённая реализация модуля с использованием самовызывающейся функции, которая скрывает внутренние свойства и методы.

Внутри модуля Controller есть объект battle, в котором и реализован весь функционал игры «Морской бой». В этот объект с помощью простой литеральной нотации записаны все функции определяющие алгоритм игры.
В данной статье мы рассмотрим только инициализацию игры, которая происходит при нажатии на кнопку Play. Так как первоначально мы реализуем выстрел игрока, то и JS-код инициализации пока будем писать исходя из этого. Конечно, в дальнейшем этот код будет дополнен.

У нас появилась новая функция showServiseText, которая является методом объекта battle. Её назначение — выводить текст в нижней служебной строке, под игровыми полями.

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

Комментарии

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

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

Добавить комментарий

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