Пишем Сапёр на Unity. Взаимодействие
4К открытий5К показов
Мы продолжаем нашу серию уроков по написанию Сапёра на Unity. В этой части мы реализуем взаимодействие между клетками, сделаем так, чтобы они подсвечивались при наведении мыши, а также добавим возможность отмечать клетки с минами, поставив на них флажки.
В прошлой части мы построили клеточное поле — основу нашей игры. А в этой мы сделаем его играбельным. Так как данная статья является продолжением серии, мы настоятельно рекомендуем вам прочитать предыдущую часть.
- Пишем Сапёр на Unity. Настройка.
- Пишем Сапёр на Unity. Взаимодействие.
- Пишем Сапёр на Unity. Обработка конца игры.
Выделение клетки при наведении мыши
Пусть выделение клетки не является обязательным пунктом для нашей игры, но эта возможность будет очень полезной. Чтобы реализовать ее, мы воспользуемся функцией OnMouseOver() — она вызывается автоматически, когда мышь находится на том объекте, где и определен метод. Давайте добавим несколько переменных в скрипт объекта Tile:
Назначьте в слот Material Idle основной материал кубика. Нам также потребуется освещенный (lightup) материал, который будет того же цвета, что и основной, но с другим шейдером.
В то время как основной материал может использовать диффузный (diffuse) шейдер,…
… освещенный должен использовать зеркальный (specular).
Во многих играх используется шейдер обводки (rim), но его пока еще нет в Unity.
Итак, компонент сценария должен выглядеть так:
И не забудем добавить непосредственно в скрипт Tile следующий код:
А теперь нажмите кнопку Play и убедитесь в том, что клетка подсвечивается по наведению мыши.
Вы наверняка заметили, что если убрать мышь с поверхности клетки, то она не возвращается в исходное состояние. Чтобы исправить этот недочет, мы добавим функцию OnMouseExit():
И вуаля! Теперь игра выглядит чуть интересней!
Назначение клеткам идентификаторов
Чтобы клетки могли взаимодействовать друг с другом (например, при вычислении количества мин вокруг), назначим каждой из них свой идентификатор. Добавим переменную ID в скрипт Tile. Также нам нужно знать количество клеток в одной строке, а потому добавим еще и переменную tilesPerRow:
Вернемся к моменту создания клетки и немного изменим код:
Идентификатором служит число от 0 до количества всех клеток. То есть первая клетка получит идентификатор 0, вторая — 1 и т. д. Вы можете проверить это, кликнув по нужному объекту и взглянув на параметр ID в компоненте сценария:
Получение соседних клеток
Нам обязательно потребуется получить доступ к соседним клеткам. Например, чтобы узнать, спрятаны под ними мины или нет. Для этого добавим несколько переменных:
В этих переменных будут храниться соседние клетки. Причем все они публичные, а потому вы можете проверить, правильно ли они инициализируются. Так как идентификаторы последовательны и все клетки хранятся в массиве Grid, то мы можем задать переменные таким образом:
Если мы будем вычислять соседей клетки с идентификатором, равным 3, а в строке находятся по 5 клеток, то получим, что верхняя имеет ID, равный 8 (номер нашей клетки плюс количество клеток в ряду), правый — 4 (номер нашей клетки плюс 1) и т. д.
Но, к сожалению, такой код не совсем корректный, ведь может получиться так, что индекс выйдет за пределы диапазона. Чтобы избежать ошибок, напишем функцию inBounds(), которая и будет проверять, находится ли данный индекс в пределах допустимых значений:
А теперь мы должны проверить индекс каждого соседа перед тем, как захотим получить его:
Приведенный код проверяет не только выход индекса за пределы массива, но и подсчет соседа, когда текущая клетка находится на краю поля. Действительно, у клетки, находящейся в левом или правом краю поля, нет соседей слева и справа соответственно.
Вот пример поиска соседей у клетки под номером 7 при условии, что поле содержит 4 клетки в строке:
Обратите внимание, что у такой клетки (которая находится на правом краю поля), нет соседей справа вообще.
Убедившись, что все работает правильно, давайте запишем всех соседей в отдельный массив, чтобы иметь к ним удобный доступ. Для этого введем новую переменную:
А затем добавим всех существующих соседей в этот массив:
Подсчет мин
После того, как все клетки созданы, все мины назначены и каждая клетка знает своих соседей, пришло время подсчитать количество мин.
Откройте скрипт Tile и добавьте новую переменную, которая и будет содержать число всех близлежащих мин:
Чтобы посчитать их, мы пробежимся по ранее созданному массиву и для каждой клетки проверим значение переменной isMine. Как вы помните, именно она и отвечает за то, скрывается ли под клеткой мина или нет. Если значение равно true, то мы увеличиваем счетчик:
Если мин нет, то строка остается пустой.
Состояния клеток
Для каждой клетки нам нужно добавить переменную, отвечающую за ее состояние. Клетка может быть отмеченной флагом, раскрытой или в состоянии ожидания. В зависимости от своего состояния, она будет по-разному реагировать на нажатие кнопок мыши.
Добавление флагов
Чтобы выиграть партию, игроку следует отметить флажками все клетки, в которых скрыты мины. Давайте добавим возможность ставить флаги.
В исходных файлах вы найдете необходимый ресурс. Поставьте сам флажок на клетку:
Для получения доступа к флажку нам потребуется новая переменная:
Добавьте флажок в слот Display Flag, а в методе start() пропишите:
Этот код отключит сам флажок и текст в начале игры.
Добавление и удаление флага
Напишем новую функцию, которая будет обрабатывать и размещение, и удаление флажка:
Не забудем изменить функцию OnMouseOver():
Примечание переводчика В данный момент в обоих условиях выполняется один и тот же код, но в следующей части эта функция претерпит некоторые изменения.
При нажатии на кнопку мыши под номером 1 (это правая кнопка) будет вызываться метод SetFlag(), который и поставит/удалит флаг в зависимости от текущего состояния клетки. Вы можете протестировать работу в этой демо-игре.
Вывод
Итак, мы дополнили нашу игру несколькими жизненно важными функциями, сделали ее визуально более интересной и дали игроку возможность ставить флажки.
В следующий раз мы реализуем «раскрытие» клетки, добавим простой интерфейс и доведем игру до ума. Оставайтесь с нами!
Перевод статьи «Build a Grid-Based Puzzle Game Like Minesweeper in Unity: Interaction»
4К открытий5К показов