Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Unity_в_действии_Джозеф_Хокинг_Рус.pdf
Скачиваний:
82
Добавлен:
21.06.2022
Размер:
26.33 Mб
Скачать

5.4. Совпадения и подсчет очков      129

5.4. Совпадения и подсчет очков

Для создания полнофункциональной игры Memory нам не хватает проверки совпадений. Хотя у нас есть выложенные на стол карты, открывающиеся при щелчке на них, они никак не связаны друг с другом. Нам же нужно, чтобы каждая открытая пара проверялась на совпадение.

Эта абстрактная логическая схема — проверка совпадений и соответствующая реакция — требует, чтобы карты в ответ на щелчок уведомляли сценарий SceneController. Для этого в данный сценарий следует добавить код следующего листинга.

Листинг 5.8. Сценарий SceneController, следящий за открываемыми картами

...

private MemoryCard _firstRevealed; private MemoryCard _secondRevealed;

public bool canReveal {

Функция чтения, которая возвращает значение false,

get {return _secondRevealed == null;} ¬

}

если вторая карта уже открыта.

 

...

 

public void CardRevealed(MemoryCard card) {

 

// изначально пусто

 

}

 

...

 

Метод CardRevealed() мы сейчас напишем; просто пока нам нужен вспомогательный пустой метод, на который можно будет ссылаться в сценарии MemoryCard.cs без появления ошибок компиляции. Обратите внимание, что мы снова применяем функцию чтения, на этот раз чтобы определить, открыта ли вторая карта; возможность открыть карту дается игроку только при отсутствии в сцене двух открытых карт.

Теперь нам снова нужно отредактировать сценарий MemoryCard.cs, добавив туда вызов метода (пока пустого), который будет информировать компонент SceneController о том, что игрок щелкнул на карте. Внесите в код сценария MemoryCard.cs изменения в соответствии со следующим листингом.

Листинг 5.9. Отредактированный сценарий MemoryCard.cs для открытия карт

...

public void OnMouseDown() {

 

Проверка свойства canReveal контроллера,

if (cardBack.activeSelf && controller.canReveal) {

¬ позволяющая гарантировать, что одновременно

cardBack.SetActive(false);

могут быть открыты всего две карты.

controller.CardRevealed(this); ¬ Уведомление контроллера при открытии этой карты.

}

 

 

}

Открытый метод, позволяющий компоненту

public void Unreveal() { ¬

SceneController снова скрыть карту (вернув на место

спрайт card_back).

 

cardBack.SetActive(true);

}

...

Если поместить в метод CardRevealed() инструкцию отладки для проверки взаимодействия объектов, можно увидеть, что после щелчка на любой карте появляется тестовое сообщение. Но мы сначала обработаем одну открытую карту.

130      Глава 5. Игра Memory на основе новой 2D-функциональности

5.4.1. Сохранение и сравнение открытых карт

Объект-карта был передан в метод CardRevealed(), поэтому мы начнем следить за открываемыми картами. Введите код следующего листинга.

Листинг 5.10. Слежение за открываемыми картами в сценарии SceneController

...

public void CardRevealed(MemoryCard card) {

if (_firstRevealed

== null) { ¬ Сохранение карт в одной из двух переменных

_firstRevealed =

card;

в зависимости от того, какая из них свободна.

}else {

_secondRevealed = card;

Debug.Log("Match? " + (_firstRevealed.id == _secondRevealed.id)); ¬

}

}

...

Сравнение

идентификаторов двух открытых карт.

Этот код сохраняет открытые карты в одной из двух переменных. Если первая переменная свободна, заполняется именно она; если ей уже присвоен другой объект-кар- та, заполняется вторая переменная, а затем проверяется, совпадают ли идентификаторы карт. В зависимости от результата инструкция отладки выводит на консоль значение true или false.

Пока наш код никак не реагирует на совпадения, он только проверяет их. Поэтому давайте запрограммируем ответ.

5.4.2. Скрытие несовпадающих карт

Мы снова воспользуемся сопрограммой, так как реакция на отсутствие совпадения должна включать в себя остановку выполнения, дающую игроку возможность рассмотреть открытые карты. Сопрограммы детально рассматривались в главе 3; коротко говоря, именно сопрограмма позволит нам сделать паузу в процессе проверки совпадения. Следующий листинг содержит код, который следует добавить в сценарий

SceneController.

Листинг 5.11. Сценарий SceneController, подсчитывающий очки или скрывающий карты при отсутствии совпадения

...

private int _score = 0; ¬ Еще одна переменная, добавленная в список в верхней части сценария SceneController.

...

public void CardRevealed(MemoryCard card) { if (_firstRevealed == null) {

_firstRevealed = card; } else {

_secondRevealed = card;

StartCoroutine(CheckMatch()); ¬

Единственная отредактированная строка в этой функции

}

вызывает сопрограмму после открытия двух карт.

 

}

 

private IEnumerator CheckMatch() {

if (_firstRevealed.id == _secondRevealed.id) {

_score++; ¬ Увеличиваем счет на единицу, если идентификаторы открытых карт совпадают.

5.4. Совпадения и подсчет очков      131

Debug.Log("Score: " + _score);

}

else {

yield return new WaitForSeconds(.5f);

_firstRevealed.Unreveal(); ¬ Закрытие несовпадающих карт. _secondRevealed.Unreveal();

}

_firstRevealed = null; ¬ Очистка переменных вне зависимости от того, было ли совпадение.

_secondRevealed = null;

}

...

Первым делом мы добавляем переменную _score, предназначенную для слежения; затем после открытия второй карты загружаем в метод CheckMatch() сопрограмму.

Вней есть два варианта кода — выбор варианта зависит от того, произошло ли совпадение. В случае совпадения сопрограмма не останавливает выполнение кода; команда yield просто пропускается. В противном же случае происходит остановка на полсекунды, а потом для обеих карт снова вызывается скрывающий их метод Unreveal().

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

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

5.4.3. Текстовое отображение счета

Отображение сведений для игрока является одной из причин добавления в игру пользовательского интерфейса (вторая причина состоит в необходимости предоставить игроку способ ввода информации; UI-кнопки мы обсудим в следующем разделе).

ОПРЕДЕЛЕНИЕ  Употребляя аббревиатуру UI (User Interface — пользовательский интерфейс), обычно имеют в виду графический интерфейс пользователя (Graphical User Interface, GUI), который означает визуальную часть интерфейса, то есть текст и кнопки.

В Unity существуют разные способы отображения текста. Можно, к примеру, создать

всцене трехмерный текстовый объект. Это специальный сеточный компонент, поэтому нам нужен пустой объект, к которому его можно будет присоединить. Выберите

вменю GameObject команду Create Empty. Затем щелкните на кнопке Add Component и выберите в разделе Mesh вариант Text Mesh.

ПРИМЕЧАНИЕ  Может показаться, что трехмерный текст несовместим с двухмерной игрой, но не следует забывать, что с технической точки зрения мы работаем с трехмерной сценой, которая выглядит плоской, так как демонстрируется через ортографическую камеру. Это означает, что при желании мы можем добавлять в игру трехмерные объекты — просто они будут отображаться как плоские.

Поместите этот объект в точку с координатами –4.75, 3.65, –10; то есть сдвиньте его на 475 пикселов влево и на 365 пикселов вверх, расположив в верхнем левом углу стола

132      Глава 5. Игра Memory на основе новой 2D-функциональности

и приблизив к камере, чтобы он отображался поверх других игровых объектов. Найдите в нижней части панели Inspector параметр Font; щелкните на маленьком кружке, чтобы вызвать окно выбора файлов, и щелчком выделите единственный доступный шрифт Arial. В поле Text введите слово Score:. Корректное позиционирование требует, чтобы параметр Anchor имел значение Upper Left (он контролирует, каким образом растягиваются вводимые буквы), поэтому отредактируйте его, если требуется. По умолчанию вы получите размытый текст, но это легко исправить, введя параметры, представленные на рис. 5.10.

С а а а

а а

Д

С а а€

а а :

‚ а

Text, Anchor Font

 

Рис. 5.10. Параметры текстового объекта на панели Inspector, позволяющие получить четкий и контрастный текст

Если импортировать в проект новый шрифт формата TrueType, можно будет им воспользоваться, но для наших целей вполне подойдет вариант, предлагаемый по умолчанию. Достаточно странно, что для получения четкой и контрастной надписи шрифтом, предлагаемым по умолчанию, требуется изменить его размер. Сначала мы присвоили параметру Font Size компонента Text Mesh очень большое значение (у меня это значение 80). Затем сделали масштаб этого компонента очень маленькими (например, 0.1, 0.1, 0.1). Увеличение размера шрифта добавило к отображаемому тексту множество пикселов, а масштабирование сгруппировало эти пикселы на меньшем пространстве. Для дальнейшего управления объектом нужно внести в код изменения, показанные в следующем листинге.

Листинг 5.12. Вывод счета при помощи текстового объекта

...

[SerializeField] private TextMesh scoreLabel;

...

private IEnumerator CheckMatch() {