Вы находитесь на странице: 1из 61

МИНИСТЕРСТВО ОБРАЗОВАНИЯ РЕСПУБЛИКИ БАШКОРТОСТАН

ГОСУДАРСТВЕННОЕ АВТОНОМНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ


СРЕДНЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ
ТУЙМАЗИНСКИЙ ГОСУДАРСТВЕННЫЙ ЮРИДИЧЕСКИЙ КОЛЛЕДЖ

КАФЕДРА КОМПЬЮТЕРНЫХ ТЕХНОЛОГИЙ

РАЗРАБОТКА КОМПЬЮТЕРНОЙ ИГРЫ "2048"

КУРСОВАЯ РАБОТА

РАШИТОВА АЛСУ ДАМИРОВНА


ПКС-407
09.02.03 ПРОГРАММИРОВАНИЕ В КОМПЬЮТЕРНЫХ СИСТЕМАХ
ВЫПОЛНИЛ СТУДЕНТ
ГРУППЫ ПКС-407
РАШИТОВА А. Д.

РУКОВОДИТЕЛЬ:
КУЗНЕЦОВА В.Э.
ДАТА ЗАЩИТЫ:
______________________
ОЦЕНКА: _____________
ПОДПИСЬ___________

ТУЙМАЗЫ 2021

Содержание
Введение..................................................................................................................3
Глава 1. Теоретическая часть.............................................................................5
1.1. Движок Unreal Engine...................................................................................5
1.2. История развития игры...............................................................................10
1.3. Исследование понятия и классификация компьютерных игр................14
Глава 2. Практическая часть............................................................................30
2.1. Алгоритм реализации проекта...................................................................30
2.2. Функционал проекта...................................................................................33
2.3. Разработка компьютерной игры «Ферма»................................................36
Заключение...........................................................................................................40
Список источников и литературы...................................................................42
Приложение..........................................................................................................44

2
Введение

Unity - межплатформенная среда разработки компьютерных игр,


разработанная американской компанией Unity Technologies. Unity позволяет
создавать приложения, работающие на более чем двадцати пяти различных
платформах, включающих персональные компьютеры, игровые консоли,
мобильные устройства, интернет-приложения и другие. Выпуск Unity
состоялся в 2005 году и с того времени идёт постоянное развитие.
Основными преимуществами Unity являются наличие визуальной
среды разработки, межплатформенной поддержки и модульной системы
компонентов. К недостаткам относят появление сложностей при работе с
многокомпонентными схемами и затруднения при подключении внешних
библиотек.
Игровой движок Unity очень популярен среди разработчиков видеоигр,
особенно среди начинающих, из-за простоты освоения и бесплатности.
Несмотря на то, что движок ориентирован на трехмерные приложения, он
поддерживает работу с двухмерной графикой. Однако не все компоненты
редактора одинаково хорошо работают в 3D и 2D. В частности, встроенная
система освещения не позволяет двухмерным объектам служить
полноценным препятствием для света и отбрасывать тени на другие объекты.
Ко всем объектам прикреплен одинаковый материал с одинаковым
шейдером. Если куб является полноценным препятствием для света, то
четырехугольник отбрасывает тень только от тех источников, которые не
лежат в одной плоскости с ним, а спрайт и вовсе игнорируется системой
расчета теней. В трехмерном пространстве это обусловлено физическим
расчетом освещаемых областей, так как четырехугольник, в отличие от куба,
не имеет толщины, однако в двухмерном пространстве объемные фигуры
представлены плоскими 2D объектами, поэтому необходимо обеспечить

3
возможность взаимодействия со светом двухмерных объектов, идентичную
взаимодействию трехмерных в 3D пространстве
На Unity написаны тысячи игр, приложений, визуализации
математических моделей, которые охватывают множество платформ и
жанров. При этом Unity используется как крупными разработчиками, так и
независимыми студиями.
Целью данной курсовой работы является изучение и реализация в
программном продукте компьютерной игры «2048». Данная работа состоит
из двух разделов, заключения и приложения. Первый раздел - теоретический
и содержит общие сведения. Второй - это практическая часть. Здесь
описывается метод, разобранный на конкретных примерах. В заключении
представлен вывод о проделанной работе.
Задачи:
1. Изучить игровой движок Project Anarchy и расписать изученную
информацию.
2. Изучить информацию о Unity.
3. Разработать игру на игровом движке Unity.

4
Глава 1. Теоретическая часть
1.1. Движок Project Anarchy

Project Anarchy (рис. 1) - мощный инструмент, который включает в


себя широкие возможности по созданию графики, физики и AI. Он позволяет
создавать игры для платформ Android, iOS и Tizen. Project Anarchy составит
серьёзную конкуренцию другому популярному в среде независимых
разработчиков движку Unity.
Кроме того, Havok предлагает разработчикам другой вариант движка -
Project Anarchy Pro. Он предназначен для тех, кто собирается выпускать игры
для PS, Xbox или Windows Phone. Project Anarchy Pro бесплатным не будет,
однако цену Havok пока не сообщает.

Рис. 1 Логотип Project Anarchy.


Несколько слов о самой компании. Havok была основана сотрудниками
дублинского Тринити-колледжа, что в Ирландии, в 1998 году. Дела пошли в
гору после того, как 2 года спустя Havok приобрела немецкого разработчика
игровой физики Ipion Virtual Physics. Объединенные наработки двух
компаний и легли в основу знаменитого физического движка Havok Physics,
находящегося внутри почти двух сотен игр, многие из которых, как
перечисленные выше, стали настоящими хитами. Другой важной вехой в
истории компании стало приобретение ее корпорацией Intel в 2007 году; с тех
пор, оставшись отдельной структурной единицей, Havok имеет статус An
Intel Company.
5
Помимо физического движка, Havok имеет разработки и в других
областях игровой индустрии, таких как реализация искусственного
интеллекта Havok AI, моделирование поведения персонажей Havok
Animation Studio, а также собственный игровой движок Havok Vision Engine.
Эти перечисленные ключевые продукты Havok, объединенные общим
WYSIWYG редактором и оснащенные средствами экспорта, учебным
материалом и примерами, как раз и составляют пакет Project Anarchy. С
помощью бесплатных средств разработки Project Anarchy вы можете
создавать игры под платформы Android и Tizen. Расширенные возможности,
такие как профессиональная техподдержка, дополнительные исходники и
целевые платформы, включая ПК, доступны за отдельную плату.
Чаще всего 3D движки или системы рендеринга в игровых движках
построены на графическом API, таком как Direct3D или OpenGL, который
обеспечивает программную абстракцию GPU или видеокарты.
Низкоуровневые библиотеки, например, DirectX, SDL и OpenAL, также
используются в играх, так как обеспечивают аппаратно-независимый доступ
к другому аппаратному обеспечению компьютера, такому как устройства
ввода (мышь, клавиатура и джойстик), сетевые и звуковые карты. До
появления аппаратно-ускоряемой 3D графики использовались программные
визуализаторы. Программный рендеринг всё ещё используется в некоторых
инструментах моделирования для рендеринга изображений, для которых
визуальная достоверность важнее производительности (количество кадров в
секунду) или когда аппаратное обеспечение компьютера не удовлетворяет
требованиям, например, не поддерживает шейдеры.
В дополнение к многократно используемым программным
компонентам, игровые движки предоставляют набор визуальных
инструментов для разработки. Эти инструменты обычно составляют
интегрированную среду разработки для упрощённой, быстрой разработки игр
на манер поточного производства. Эти игровые движки иногда называют
«игровым подпрограммным обеспечением» (сокр. ППО; англ. middleware),
6
так как, с точки зрения бизнеса, они предоставляют гибкую и многократно
используемую программную платформу со всей необходимой
функциональностью для разработки игрового приложения, сокращая
затраты, сложность и время разработки - все критические факторы в
сильноконкурирующей индустрии видеоигр.
Как и другие ППО решения, игровые движки обычно платформо-
независимы и позволяют некоторой игре запускаться на различных
платформах, включая игровые консоли и персональные компьютеры, с
некоторыми внесёнными в исходный код изменениями (или вообще без них).
Часто игровое ППО имеет компонентную архитектуру, позволяющую
заменять или расширять некоторые системы движка более
специализированными (и часто более дорогими) ППО компонентами,
например, Havok - для физики, FMOD - для звука или SpeedTree - для
рендеринга. Некоторые игровые движки, такие как RenderWare,
проектируются как набор слабосвязанных ППО компонентов, которые могут
выборочно комбинироваться для создания собственного движка, вместо
более традиционного подхода расширения или настройки гибкого
интегрируемого решения. Тем не менее расширяемость достигнута и
остаётся высокоприоритетной в игровых движках из-за широких
возможностей их применения. Несмотря на специфичность названия,
игровые движки часто используются в других типах интерактивных
приложений, требующих графику в реальном времени, таких как рекламные
демо-ролики, архитектурные визуализации, обучающие симуляторы и среды
моделирования.
Некоторые игровые движки предоставляют только возможности 3D
рендеринга в реальном времени вместо всей функциональности,
необходимой играм. Эти движки доверяют разработчику игры реализацию
остальной функциональности или её сбор на основе других игровых ППО
компонентов. Такие типы движков обычно относят к «графическим
движкам», «движкам рендеринга» или «3D движкам» вместо более
7
содержательного термина «игровой движок». Однако эта терминология
используется противоречиво: так, многие полнофункциональные игровые 3D
движки упомянуты просто как «3D движки». Некоторые примеры
графических движков: RealmForge, Ogre 3D, Power Render, Crystal Space и
Genesis3D. Современные игровые или графические движки обычно
предоставляют графические сцены - объектно-ориентированное
представление 3D мира игры, которое часто упрощает игровой дизайн и
может использоваться для более эффективного рендеринга огромных
виртуальных миров.
Игровой движок - это центральный программный компонент
компьютерных и видео игр или других интерактивных приложений с
графикой, обрабатываемой в реальном времени. Он обеспечивает основные
технологии, упрощает разработку и часто даёт игре возможность запускаться
на нескольких платформах, таких как игровые консоли и настольные
операционные системы, например, GNU/Linux, Mac OS X и Microsoft
Windows.
Основную функциональность обычно обеспечивает игровой движок,
включающий движок рендеринга («визуализатор»), физический движок,
звук, систему скриптов, анимацию, искусственный интеллект, сетевой код,
управление памятью и многопоточность. Часто на процессе разработки
можно сэкономить за счет повторного использования одного игрового
движка для создания множества различных игр.
Первое время из-за невысокой скорости и отсутствия какой-либо
стандартизации аппаратной части даже порты одной игры серьёзно
переписывались - а из одной игры в другую вообще переносили минимум
кода. Впрочем, в играх жанра квест существовали Infocom'овская Z-Machine
и SCI компании Sierra - именно их можно считать первыми законченными
игровыми движками.
Сам же термин «игровой движок» появился в середине 1990-х годов,
главным образом в связи с 3D-играми, такими как шутеры от первого лица.
8
Игры Doom и Quake от id Software оказались настолько популярными, что
другие разработчики вместо того, чтобы работать с чистого листа,
лицензировали основные части программного обеспечения и создавали свою
собственную графику, персонажей, оружие и уровни - «игровой контент» или
«игровые ресурсы». Движок Quake был использован в более чем десяти
проектах и дал серьёзный толчок развитию middleware-индустрии.
Более поздние игры, такие как: Unreal 1998 года (движок Unreal Engine)
и Quake III Arena (на движке id Tech 3) 1999 года, были спроектированы с
применением данного подхода, с отдельно разработанными движком и
наполнением. Практика лицензирования такой технологии оказалась
полезным вспомогательным доходом для некоторых разработчиков игр. Так,
стоимость одной лицензии на коммерческий игровой движок класса high-end
может варьироваться от 10 тыс. до 3,75 млн $ (в случае Warcraft III), а число
лицензиатов может достигать несколько десятков компаний (как для Unreal
Engine). По крайней мере, многократно используемые движки ускоряют и
упрощают разработку игры, что является ценным преимуществом в
конкурирующей индустрии компьютерных игр.
Дальнейшее усовершенствование игровых движков привело к
сильному разделению между рендерингом, скриптингом, художественным
дизайном и дизайном уровней. Сейчас для типичной команды разработчиков
игр является вполне обычным иметь в составе столько же художников,
сколько и программистов.
Шутеры от первого лица остаются преобладающими пользователями
сторонних игровых движков, но сейчас такие движки также используются в
других жанрах. Например, RPG Morrowind и MMORPG Dark Age of Camelot
основаны на движке NetImmerse, в то время, как Oblivion и Fallout 3
используют новую версию данной технологии - Gamebryo. Известная
MMORPG Lineage II построена на движке Unreal Engine 2 (несмотря на то,
что данный движок изначально предназначался для использования в
шутерах).
9
Игровые движки также используются в играх, первоначально
разработанных для игровых консолей; например, движок RenderWare
используется во франчайзах Grand Theft Auto и Burnout.
Современные игровые движки - одни из самых сложных в написании
приложений, зачастую состоящие из десятков различных компонентов,
каждый из которых можно настраивать по отдельности под нужды игры. На
сайте Future Game Coders есть различные темы о подсистемах современных
игр.

1.2. История развития игры

Игра как одно из удивительных явлений человеческой жизни


привлекала к себе внимание философов и исследователей всех эпох. Уже
Платон считал игру одним из полезнейших занятий, а Аристотель видел в
игре источник душевного равновесия, гармонии души и тела. Определенные
этапы развития обусловили негативное отношение к игре и сделали почти
невозможной направленность теоретической мысли на исследование этой
деятельности. Но с последней трети XIX века интерес к игровой
деятельности появляется вновь, появляются первые научные теории игры.
Игра начинает рассматриваться как важное средство формирования и
тренировки навыков, необходимых для психофизического и личностного
развития, как первичная форма приобщения человека к социуму, а так же как
один из способов формирования способности к обучению и воспитания
чувства ответственности за свои поступки и за свою группу. Одним из
первых исследователей, высказавшим подобные взгляды на игру, был
К.Гросс.С начала XX века интерес к изучению игры возникает с новой силой.
Ряд исследователей (У. Макдауголл, Г. Мерфи, Ф.Я. Бентендейх) выдвинули
тезис, что игра - это "некий социальный инстинкт", присущий каждому
человеку. Большой популярностью до сих пор пользуется теория инра как
10
самовыражение (Ж.Пиаже). Представители культуроведческого подхода к
игре считают, что игра украшает жизнь, дополняет ее и является жизненно
необходимой каждому человеку. Известный советский психолог
А.Н.Леонтьев считал игру ведущей деятельностью дошкольного периода,
благодаря овладению и выполнению которой формируются центральные
психологические новообразования и происходит подготовка к другим видам
деятельности. [10 – 135 с.]
Один из ведущих современных психологов России Р.С.Немов
определил игру как "вид деятельности, выполняющий две функции:
психологическое развитие человека и его отдыха" [16 – 143 с.]. Многие
выдающиеся педагоги обращали внимание на эффективность использования
игр в процессе обучения. А.С. Макаренко считал, что игра обеспечивает
высокую эффективность любой деятельности и способствует гармоничному
развитию личности, так как "хорошая игра" обязательно содержит в себе
усилие (физическое, эмоциональное, интеллектуальное или творческое),
доставляет радость (радость творчества, победы) и налагает ответственность
на участников. В игре особенно проявляются способности ребенка.
Крупнейший знаток этой проблемы Д.Б. Эльконин наделяет игру
четырьмя важными функциями: средство развития мотивационно -
потребностной сферы, средство развития умственных действий, средство
познания и средство развития произвольного поведения.
В публичной практике последних лет в науке понятие игры
осмысливается по-новому, игра распространяется на многие сферы жизни,
игра применяется, как общенаучная, серьезная категория. Может быть,
поэтому игры начинают входить в дидактику более активно.
Большая роль в развитии и воспитании дитя принадлежит игре -
важнейшему виду детской деятельности. Она является эффективным
средством формирования личности школьника, его морально-волевых
свойств, в игре реализуется потребность действия на мир. Игра дает свободу,

11
так как она не задачка, не долг, не закон. По приказу играться нельзя, лишь
добровольно.
А что игра даёт детям? Перерыв в повседневности, с её утилитаризмом,
с её монотонностью, с её твердой детерминацией вида жизни. Игра это
неординарность. Выход в другое состояние души. Подчиняясь только
правилам игры, человек свободен от всяческих сословных, меркантильных и
иных условностей. Игра снимает то твердое напряжение, в котором
пребывает ребенок в собственной настоящей жизни, и заменяет его
добровольной и удовлетворённой мобилизацией духовных и физических сил.
Порядок: система правил в игре абсолютна и несомненна. Нереально
нарушать правила и быть в игре. Это качество порядок, совсем ценно сейчас
в нашем нестабильном, беспорядочном мире. Создает гармонию.
Сформировывает рвение к совершенству. Игра имеет тенденцию становиться
прелестной. Хотя в игре существует элемент неопределенности,
противоречия в игре стремятся к разрешению. Увлеченность: в игре нет
частичной выгоды. Она интенсивно вовлекает всего человека, активизирует
его способности. Возможность сделать и сплотить коллектив.
Привлекательность игры столь велика и игровой контакт людей друг с
другом столь полон и глубок, что игровые содружества обнаруживают
способность сохраняться и после окончания игры, вне её рамок. Элемент
неопределенности, который возбуждает, активизирует разум, настраивает на
поиск хороших решений. Понятие о чести. Она противоборствует корыстным
и узкогрупповым интересам. Для нее не значительно, кто конкретно победит,
но принципиально, чтоб победа была одержана по всем правилам, и чтоб в
борьбе были проявлены с наибольшей полнотой мужество, разум, честность
и благородство. Игра дает понятие о самоограничении и самопожертвовании
в пользу коллектива, поскольку лишь "сыгранный" коллектив добьется
совершенства в игре. Компенсацию, нейтрализацию недостатков реальности.
Противопоставляет твердому миру действительности иллюзорный
гармоничный мир - антипод. Игра дает романтизм. Физическое улучшение,
12
поскольку в активных собственных формах она предполагает обучение и
применение в деле игрового фехтования, умения ориентироваться и
двигаться по пересеченной местности, причем в доспехах и с игровым
орудием. Возможность проявить либо совершенствовать свои творческие
навыки в разработке нужной игровой атрибутики. Это орудие, доспехи,
одежда, разные амулеты, идолы и прочее. Развитие воображения, поскольку
оно нужно для сотворения новейших миров, легенд, ситуаций, правил игры.
Стойкий энтузиазм к хорошей литературе, поскольку ролевая игра создается
способом литературного моделирования. Чтоб сделать свой мир необходимо
прочесть предварительно о остальных. Возможность развить свой разум,
поскольку нужно выстроить интригу и воплотить её. Развитие остроумия,
поскольку процесс и пространство игры непременно предполагают
возникновение комичных ситуаций, хохм и анекдотов. Развитие
психологической пластичности. Игра далеко не одно лишь состязание, но и
театральное искусство, способность вживаться в образ и довести его до
конца. Удовлетворенность общения с единомышленниками. Умение
ориентироваться в настоящих жизненных ситуациях, проигрывая их не один
раз и как бы понарошку в собственном вымышленном мире. Дает
психологическую устойчивость. Снимает уровень тревожности, который так
высок сейчас у родителей и передается детям. Производит активное
отношение к жизни и целеустремленность в выполнении поставленной цели.
Воспитательное значение игры во многом зависит от
профессионального мастерства педагога, от знания им психологии дитя,
учета его возрастных и личных особенностей, от правильного методического
управления взаимоотношениями детей, от четкой организации и проведения
всевозможных игр.
Игровое творчество проявляется и в поисках средств, для изображения
загаданного. Дети реализуют свой план с помощью речи, жестов, мимики,
употребляя различные предметы, сооружения, постройки.

13
Игровое творчество развивается под влиянием воспитания и обучения,
уровень его зависит от обретенных знаний и привитых умений, от
сформированных интересов дитя. Не считая того, в игре с особой силой
появляются личные особенности детей, также влияющие на развитие
творческого плана.
Через игру равномерно готовится сознание дитя к грядущим
изменениям условий жизни, отношений со сверстниками и со взрослыми,
формируются свойства личности, нужные школьнику. В игре формируются
такие свойства, как самостоятельность, инициативность, организованность,
развиваются творческие способности, умение работать коллективно.
Игровым приемом при обучении иностранным языкам пользовались
издавна. Известные педагоги эпохи Возрождения (Рабле, Эразм
Роттердамский) уделяли большое внимание играм на занятиях иностранным
языком. Игры широко использовались при обучении в домашних условиях.
На возможность использования игр при обучении иностранным языкам
обратил внимание еще величайший педагог прошлого Я.А. Каменский, а в
дальнейшем Н.К. Крупская писала: "Чрезвычайно важны и полезны игры на
иностранном языке. Они помогают естественному изучению языка".

1.3. Классификация компьютерных игр

Четкая классификация затруднена из-за того, что подчас трудно


отнести игру к какому-нибудь конкретному жанру. Игра может представлять
собой как смешение существующих жанров, так и не относиться ни к одному
из них. Несмотря на это, в ходе развития компьютерных игр сложилась
следующая классификация:
1) 3D Shooter (3D-шутеры, "бродилки") (рис. 2)
Название произошло от понятия 3D - 3 dimensions (три измерения) и
shooter (англ. «стрелок»). Основной принцип состоит в изображении
14
виртуального пространства и предметов посредством игровой программы,
исполняемой на компьютере. При этом игрок может воздействовать на
виртуальную игровую среду. Применяется для обозначения всех видов
компьютерных игр, содержащих элементы боя в виртуальном трехмерном
пространстве. В основном используется техника «шутер от первого лица» -
при этом изображение на экране монитора компьютера имитирует вид из
глаз игрока. С точки зрения организации игры различаются Singleplayer и
Multiplayer - игра в одиночку против компьютера и игра с другими игроками.
Примеры: Doom, Quake, Counter-strike, Half-life, Unreal, Tomb Raider

Рис. 2 3D Shooter
2) Arcade (аркада) (рис. 3)
Игры, в которых игроку приходится действовать быстро, полагаясь в
первую очередь на свои рефлексы и реакцию. Аркады характеризуются
развитой системой бонусов: начисление очков, постепенно открываемые
элементы игры и т.д. Термин «аркада» по отношению к компьютерным играм
возник во времена игровых автоматов, которые устанавливались в торговых
галереях (arcades). Игры на них были простыми в освоении (чтобы привлечь
побольше играющих). В последствии эти игры перекочевали в игровые
приставки и до сих являются основным жанром на них.
15
Рис. 3 Arcade
3) Arcade Racing (Аркадные гонки)(рис. 4)
Аркадные гонки характеризуются легким, отдаленным от реальности
управлением.
Примеры: серия Trackmania, Go for ride

Рис. 4 Arcade Racing

16
4) Classic Arcade (Классические аркады) (рис. 5)
Суть классических аркад объяснить довольно сложно. Обычно главной
целью является прохождение уровня за максимально короткий промежуток
времени или сбор всех бонусов на уровне. Сюда же можно отнести
разнообразные арканоиды и пинболлы.
Примеры: Pacman, Digger, Battle City

Рис. 5 Classic Arcade


5) Fighting (Драки) (рис. 6)
В драках два персонажа дерутся на арене, применяя различные удары,
броски и комбинации. Характеризуется большим количеством персонажей
(бойцов) и ударов (иногда больше ста для каждого персонажа). Жанр
малопопулярен на PC из-за ориентации на совместную игру, а на клавиатуре
довольно проблематично одновременно играть вдвоем. Однако хорошо
развит на игровых приставках. По некоторым играм этого жанра даже
проводятся мировые чемпионаты.
Примеры: Mortal Combat, Street Fighter, Tekken

17
Рис. 6 Fighting
6) Platformer (Платформеры) (рис.7)
Понятие платформеров пришло с игровых приставок. Именно там этот
жанр наиболее популярен. Основной задачей игрока является преодоление
препятствий (ям, шипов, врагов и т.д.) с помощью прыжков. Зачастую
приходится прыгать по абстрактно расставленным в воздухе "палочкам" (т.н.
платформам), отсюда и пошло название жанра.
Примеры: Mario, Aladdin

Рис. 7 Platformer
18
7) Scrollers (Скроллеры) (рис. 8)
В скроллерах экран непрерывно движется в одну из сторон, а игроку
предлагается уничтожать появляющихся врагов и собирать появляющиеся
бонусы. По направлению движения различают вертикальные и
горизонтальные скроллеры. Жанр был очень популярен в середине 90-х
годов, сейчас скроллеры практически не выпускаются.
Примеры: Jets'n'Guns, AirStrike, DemonStar, KaiJin

Рис. 8 Scrollers
8) Virtual Shooting (Виртуальный тир) (рис. 9)
Впервые зародился на игровых автоматах, впоследствии перешел на
многие игровые платформы, включая PC. Игровой процесс представляет
собой отстрел неожиданно появляющихся врагов, но в отличии от экшенов
мы не можем управлять движением игрока или камерой, всю игру мы как
едем по "рельсам". В связи с этим иногда делают видеотиры, т.е. всю игру
снимают на видеокамеру, в определенных местах подставляя разные
варианты видеоотрывков.
Примеры: Mad Dog McGee, серия House of the Dead

19
Рис. 9 Scrollers
9) Simulation (симуляторы) (рис. 10)
Игра-симуляция. При помощи компьютера, как можно более полно,
имитируется управление каким-либо сложным технической системы
(например: боевым истребителем, автомобилем и т.д.).
Примеры: серия Need for Speed, Descent III, Aviator

Рис. 10 Simulation

20
10) Экономические симуляции (рис. 11)
В экономических симуляциях представлены различные экономические
процессы и взаимодействия различных величин.
Примеры: Sims, Civilization

Рис. 11 Экономические симуляции


11) Strategy (стратегии) (рис. 12)
Игра требующая выработки стратегии, например для победы в военной
операции. Игрок управляет не одним персонажем, а целым подразделением,
предприятием или даже вселенной. Различают:
- походовые или пошаговые стратегические игры (Turn-Based Strategy,
TBS). Игроки поочерёдно делают ходы, и каждому игроку отводится
неограниченное или ограниченное (в зависимости от типа и сложности игры)
время на свой ход.
- стратегические игры в реальном времени (Real Time Strategy, RTS).
Все игроки выполняют свои действия одновременно, и ход времени не
прерывается.
Примеры: WarCraft, StarCraft, Dune

21
Рис. 12 Strategy
12) Sport (спортивные) (рис. 13)
Как и следует из названия - имитация какой-либо спортивной игры,
например футбола.
Примеры: FIFA, NBA, Tennis

Рис. 13 Sport

22
13) Adventure (приключения), или Quest (рис. 14)
Игра-повествование, в которой управляемый игроком герой
продвигается по сюжету и взаимодействует с игровым миром посредством
применения предметов, общения с другими персонажами и решения
логических задач.
Примеры: Space Quest; Myst, Мор. Утопия

Рис. 14 Adventure
14) Role-Playing Games (RPG) (ролевые игры) (рис. 15)
Правильное название этого жанра Computer RPG (CRPG), так как эти
игры являются адаптированными для компьютера традиционными ролевыми
играми.

23
Рис. 15 Role-Playing Games
15) Puzzle (головоломки, логические) (рис. 16)
В некомпьютерной головоломке роль арбитра, следящего за
соблюдением правил, играет или сам игрок (пасьянс), или некоторое
механическое устройство (кубик Рубика). С появлением компьютеров
возможности головоломок расширились, так как написать компьютерную
программу проще, чем сконструировать механическое устройство.
Головоломки, как правило, не требуют реакции от игрока (однако многие
ведут счёт времени, потраченного на решение).
Примеры: Сапёр (Minesweeper); Sokoban.

24
Рис. 16 Puzzle
16) Traditional (традиционные) и board (настольные) (рис. 17)
Компьютерная реализация настольных игр, например шахмат.
Примеры: CGoban

Рис. 17 Вoard
17) Текстовые (рис. 18)
Новое веяние в игровой культуре. Чаще всего, жанр являет собой
текстовый квест, количество участников в котором не ограничено. Иногда
такая игра может длиться годами.
Классификация игр по количеству игроков.
25
Рис. 18 Текстовые
18) Одиночные (single player) (рис. 19)
Рассчитаны на игру в одиночку, против компьютера.

Рис. 19 Одиночные

19) Многопользовательские (multiplayer) (рис. 20)


26
Рассчитаны на игру нескольких человек, обычно до 32, по локальной
сети, модему или Интернету.

Рис. 20 Многопользовательские
20) Многопользовательские на одном компьютере (hot seat и splitscreen)
(рис. 21)
На современных персональных компьютерах бывают редко, однако
часто встречаются на старых ПК и приставках. Hot seat - игра по очереди на
одном компьютере. В режиме splitscreen экран делится на две части, каждый
из игроков играет на своей части.

27
Рис. 21 Многопользовательские на одном компьютере
21) Многопользовательские через электронную почту (PBEM) (рис. 22)
В основном встречается в пошаговых стратегиях. Результаты хода
записываются в специальный файл и отсылаются другому игроку через
электронную почту.

Рис. 22 Многопользовательские через электронную почту

28
22) Массовые (MMO, Massively Multiplayer Onine) (рис. 23)
Массовые игры по Интернету. Наиболее часто встречающиеся жанры -
настольные и ролевые игры (т.н. MMORPG, или Massively Multiplayer Online
RPG). Среди них различают также браузерные игры (игры, не требующие
установки какого-либо клиента), а также текстовые онлайновые игры - жанр
MUD.

Рис. 23 Массовые

29
Глава 2. Практическая часть
2.1. Игровой движок Unity

Unity - межплатформенная среда разработки компьютерных игр,


разработанная американской компанией Unity Technologies. Unity позволяет
создавать приложения, работающие на более чем 25 различных платформах,
включающих персональные компьютеры, игровые консоли, мобильные
устройства, интернет-приложения и другие. Выпуск Unity состоялся в 2005
году и с того времени идёт постоянное развитие.
Основными преимуществами Unity являются наличие визуальной
среды разработки, межплатформенной поддержки и модульной системы
компонентов. К недостаткам относят появление сложностей при работе с
многокомпонентными схемами и затруднения при подключении внешних.
На Unity написаны тысячи игр, приложений, визуализации
математических моделей, которые охватывают множество платформ и
жанров. При этом Unity используется как крупными разработчиками, так и
независимыми студиями.
Редактор Unity имеет простой Drag&Drop нтерфейс, который легко
настраивать, состоящий из различных окон, благодаря чему можно
производить отладку игры прямо в редакторе. Движок использует для
написания скриптов C#. Ранее поддерживались также Boo (диалект Python,
поддержку убрали в 5-й версии) и модификация JavaScript, известная как
UnityScript (поддержка прекращена в версии 2017.1). Расчёты физики
производит физический движок PhysX от NVIDIA. Графический API -
DirectX (на данный момент DX 11, поддерживается DX 12)
Проект в Unity делится на сцены (уровни) - отдельные файлы,
содержащие свои игровые миры со своим набором объектов, сценариев, и
настроек. Сцены могут содержать в себе как, собственно, объекты (модели),
так и пустые игровые объекты - объекты, которые не имеют модели
30
(«пустышки»). Объекты, в свою очередь содержат наборы компонентов, с
которыми и взаимодействуют скрипты. Также у объектов есть название (в
Unity допускается наличие двух и более объектов с одинаковыми
названиями), может быть тег (метка) и слой, на котором он должен
отображаться. Так, у любого объекта на сцене обязательно присутствует
компонент Transform - он хранит в себе координаты местоположения,
поворота и размеров объекта по всем трём осям. У объектов с видимой
геометрией также по умолчанию присутствует компонент Mesh Renderer,
делающий модель объекта видимой.
К объектам можно применять коллизии (в Unity т. н. коллайдеры -
collider), которых существует несколько типов.
Также Unity поддерживает физику твёрдых тел и ткани, а также физику
типа Ragdoll (тряпичная кукла). В редакторе имеется система наследования
объектов; дочерние объекты будут повторять все изменения позиции,
поворота и масштаба родительского объекта. Скрипты в редакторе
прикрепляются к объектам в виде отдельных компонентов.
При импорте текстуры в Unity можно сгенерировать alpha-канал, mip-
уровни, normal-map, light-map, карту отражений, однако непосредственно на
модель текстуру прикрепить нельзя - будет создан материал, которому будет
назначен шейдер, и затем материал прикрепится к модели. Редактор Unity
поддерживает написание и редактирование шейдеров. Редактор Unity имеет
компонент для создания анимации, но также анимацию можно создать
предварительно в 3D-редакторе и импортировать вместе с моделью, а затем
разбить на файлы.
Unity 3D поддерживает систему Level Of Detail (сокр. LOD), суть
которой заключается в том, что на дальнем расстоянии от игрока
высокодетализированные модели заменяются на менее детализированные, и
наоборот, а также систему Occlusion culling, суть которой в том, что у
объектов, не попадающих в поле зрения камеры не визуализируется
геометрия и коллизия, что снижает нагрузку на центральный процессор и
31
позволяет оптимизировать проект. При компиляции проекта создается
исполняемый (.exe) файл игры (для Windows), а в отдельной папке - данные
игры (включая все игровые уровни и динамически подключаемые
библиотеки).
Движок поддерживает множество популярных форматов. Модели,
звуки, текстуры, материалы, скрипты можно запаковывать в формат
.unitypackage и передавать другим разработчикам, или выкладывать в
свободный доступ. Этот же формат используется во внутреннем магазине
Unity Asset Store, в котором разработчики могут бесплатно и за деньги
выкладывать в общий доступ различные элементы, нужные при создании
игр. Чтобы использовать Unity Asset Store, необходимо иметь аккаунт
разработчика Unity. Unity имеет все нужные компоненты для создания
мультиплеера. UNet был удалён, начиная с версии 2018.4; решение «из
коробки» для мультиплеера отсутствует. Также можно использовать
подходящий пользователю способ контроля версий. К примеру, Tortoise
SVN, Git или Source Gear.
В Unity входит Unity Asset Server - инструментарий для совместной
разработки на базе Unity, являющийся дополнением, добавляющим контроль
версий и ряд других серверных решений.

32
2.2. Функционал проекта

Проект представляет собой компьютерную игру жанра головоломка,


основная цель которой заключается в развлечении и предоставлении
средства для отдыха и приятного времяпрепровождения.
Прежде всего, проект должен отвечать следующим требованиям:
1. Игра должна обладать простым и понятным геймплеем.
2. Основная механика игры заключается в передвижении плиток с
цифрами.
3. Не должно быть слишком усложнённое восприятие игры.
4. В игре присутствует счет, который увеличивается при соединении
двух плиток с одинаковыми цифрами.
5. При выигрыше или проигрыше игрока, должно выводиться
небольшое меню, предлагающее повторить уровень.
Данные требования к функциональной части являются основными,
должны быть выполнены в первую очередь.
Почти все действия в игре осуществляются посредством нажатием
клавиш клавиатуры. Плитки передвигаются вправо, влево, вверх и вниз. Для
управления плитками используются клавиши стрелка вправо, стрелка влево,
стрелка вверх, стрелка вниз.
Необходимо следить за игровым полем, если поле заполнится
плитками, то игра будет окончена. Чтобы одержать победу, необходимо
набрать максимальное число 2048.
Правила игры:
1. В каждом раунде появляется плитка номинала «2» (с
вероятностью 90 %) или «4» (с вероятностью 10 %).
2. Нажатием стрелки игрок может скинуть все плитки игрового
поля в одну из 4 сторон. Если при сбрасывании две плитки одного номинала
«налетают» одна на другую, то они превращаются в одну, номинал которой
равен сумме соединившихся плиток. После каждого хода на свободной
33
секции поля появляется новая плитка номиналом «2» или «4». Если при
нажатии кнопки местоположение плиток или их номинал не изменится, то
ход не совершается.
3. Если в одной строчке или в одном столбце находится более двух
плиток одного номинала, то при сбрасывании они начинают соединяться с
той стороны, в которую были направлены. Например, находящиеся в одной
строке плитки (4, 4, 4) после хода влево превратятся в (8, 4), а после хода
вправо - в (4, 8). Данная обработка неоднозначности позволяет более точно
формировать стратегию игры.
4. За каждое соединение игровые очки увеличиваются на номинал
получившейся плитки.
5. Игра заканчивается поражением, если после очередного хода
невозможно совершить действие.
Стоит отметить, что данная игра - для людей, которые любят ребусы и
головоломки, а также имеют аналитический склад ума. Вот несколько
советов, с которыми вам будет легче пройти всю игру до конца.
1. Изучите основное правило игры. Что имеется в виду? Сыграйте в
"2048" много раз, пока не поймете до конца, как перемещаются ячейки с
цифрами, как они складываются, пока не начнете продумывать действия на
несколько ходов вперед.
2. Не спешите. В данной игре важно продумывать каждый ход,
прежде чем его совершать, не стоит передвигать ячейки в беспорядке туда-
сюда.
3. Просчитывайте ходы. Этот момент нужно обязательно занести в
правила игры "2048", поскольку, если его не соблюдать, вероятность
выигрыша ничтожно мала.
4. В одно движение необходимо соединять как можно больше
ячеек. Интересно то, что в одно движение вы можете соединить даже три
цифры. Это позволит вам быстро расчистить поле и собрать больше крупных
цифр.
34
5. Обращайте больше внимания на маленькие цифры. Вы допустите
большую ошибку, если будете собирать много крупных цифр, при этом не
следя за маленькими.
Чтобы не теряться на поле и всегда знать, куда вести свои большие
цифры, старайтесь играть в одном углу. Что это значит? Собирайте свои
большие числа вместе. Так они будут рядом, и вам легче будет соединять их
между собой. Те, кто играл в "2048", знает, что не всегда получает держаться
одного угла. И случаются ситуации, когда нет другого выхода, и приходится
выводить свою самую большую ячейку на середину поля. Если это случилось
и с вами, сделайте что нужно, но следующим же ходом возвращайтесь в свой
угол.
Игра "2048" - это увлекательное приложение, которое поможет вам
скоротать время и развить свою логику. Игра имеет несколько основных
несложных правил, приятное оформление. Несмотря на то, что это просто
игра-головоломка, она имеет определенную пользу. Не стоит сразу унывать,
как только вы проиграете, без проигрыша не бывает побед. Теперь вы не
только знаете, как играть в "2048", но и обладаете ценными знаниями,
которые помогут вам почувствовать вкус победы.
Конечная цель игры - плитка с цифрами 2048. Добиться таких
результатов, можно лишь одним способом, а именно просчитывая все ходы
наперед. Разберём подробно, как играть 2048, начнем с простых правил.
Игра заканчивается тогда, когда все пустые ячейки заполнены, и вы
больше не можете передвигать клеточки ни в одну из сторон. Ну, или когда
на одном из кубов, наконец, появилась заветная цифра 2048.

35
2.3. Разработка компьютерной игры «2048»

Запускаем UnityHub. Далее в нем создаем новый проект. Здесь мы


должны выбрать модель игрового проекта (2D, 3D и т.д.), задать имя и
выбрать местоположение на локальном устройстве (рис. 24).

Рис. 24 Создание проекта


Создаем на главной сцене все нужные компоненты, которые
пригодятся нам далее в проекте. Кликаем правой кнопкой мыши в
инспекторе объектов, кликаем по “UI” и далее выбираем “Text”. Создается
текстовое поле, которое мы будем использовать для приветствия игрока.
Сразу же меняем его название на подходящее по смыслу, например,
“GameOverPanel”. По аналогии создаем ScorePanel для вывода количества
очков.

Для удобной навигации в папке Assets нужно создать такие папки как:
Scripts, Prefabs, Spawners. Далее в папке Prefabs создадим наши плитки с
цифрами (рис. 25). Даем им имена.

36
Рис. 25 Игровые плитки
Кликаем левой кнопкой мыши на плитку. Справа появится инспектор,
где мы можем поменять позицию, повернуть его, уменьшить или увеличить в
размерах.
Сами по себе плитки двигаться не будут. Для этого им нужно
прописать скрипт, который при нажатии определенной кнопки будет
двигаться в ту или иную сторону. Нажимаем на кнопку Add Component и в
поиске пишем название скрипта с заглавной буквы. Кликаем по кнопке New
Script и нажимаем Create and Add (рис. 26).

Рис. 26 Добавление скрипта


Открываем скрипт и пропишем код небольшой кусочек скрипта. После
создания скрипта есть только две изначально заложенные функции Update и
Start. Объявляем переменные в самом начале скрипта, но после объявления
класса. Далее в функции Update пишем часть кода для движения плиток.
После пишем сам код движения (рис. 27).

37
Рис. 27 Скрипт движения
При запуске игры нас встречает игровое поле. В правом верхнем углу
наши очки, после каждого соединения плиток с одинаковыми цифрами очки
суммируются (рис. 28).

Рис. 28 Игровое поле

38
Чем дольше вы играете, тем больше очков вы набираете. После
проигрыша появятся окошко с предложением переиграть (рис. 29).

Рис. 29 Окошко с предложением перееиграть

39
Заключение

В данной курсовой работе по разработке компьютерной игры, были


осуществлены все предъявляемые требования, а также описан сам процесс
разработки. Платформа Unity 3D является современным инструментом для
разработки игр, простой и гибкий интерфейс не требующий установки
дополнительного программного обеспечения (для разработки игры
использовался только Unity), при этом значительных недостатков при работе
с платформой замечено не было. Unity постоянно развивается и довольно
часто выходят обновления, в которых появляются новые возможности. Игра
является законченным продуктом, но существует очень много идей, которые
можно реализовать, тем самым дополнив проект. По такому же правилу
можно создать и другие виды игр, концепция создания остается такой же.
В процессе выполнения работы были поняты базовые принципы
работы приложений, созданных с использованием инструментария Unity и
изучены некоторые разделы предоставляемых платформой библиотек. Цели,
поставленные в начале работ, выполнены в полной мере.
Полученные знания и навыки дают базу для более глубокого изучения,
а итоговая программа будет полезна в дальнейшем как основа для более
сложного в техническом плане приложения.
Во время анализа доступных источников было проведено исследование
понятия компьютерная игра, во время которого была проведена
классификация компьютерных игр по 4 критериям, но из-за сравнительной
молодости игровой индустрии, а так же того, что классификация
компьютерных игр не была систематизирована, составить подробную
классификацию не удалось. Дополнительно был составлен алгоритм
разработки видеоигр.
Освоение среды разработки Unity несет не маловажный характер, так
как в современном мире индустрия разработки игр все сильнее
распространяется в нашем обществе.
40
Игры перестали быть лишь предметом для развлечений, и теперь
используются и в других областях, например, в науке или в обучении
пользователей. Поэтому развитие в данном направлении можно считать
одним из самых важных в современном обществе.
Unity постоянно развивается и довольно часто выходят обновления, в
которых появляются новые возможности. Игра является законченным
продуктом, но существует очень много идей, которые можно реализовать,
тем самым дополнив проект. По такому же правилу можно создать и другие
виды игр, концепция создания остается такой же.
Для того чтобы разобраться какие технологии использовать,
необходимо определиться с требованиями к программному обеспечению.
Создаваемые средства должны предоставлять пользователю большое
количество возможностей по настройке будущей игрыжанра шутер от
первого и третьего лица, должен быть простой и понятный интерфейс,
работающий быстро и поддерживающий вывод изображения как можно
лучшего качества, мы должны использовать программное обеспечение для
ОС windows, видеокарты поддерживающей directX.

41
Список источников и литературы

1. Creighton, R.-H.Unity 3D Game Development by Example Beginner's


Guide. - Packt Publishing, 2018. - 384 c..
2. Goldstone, W. Unity Game Development Essentials. - Packt Publishing,
2019. -316 с.
3. Sue Blackman. Beginning 3D Game Development with Unity: All-in-one,
Multi-platform Game Development. - Apress, 2018. - 992 с.
4. Степчева З.В. Основы геометрического моделирования в Unity 3D.
Учебное электронное издание. УлГТУ - Ульяновск, 2019 – 312 с.
5. Nicolas Alejandro Borromeo Hands-On Unity 2020 Game Development,
2020 – 581 с.
6. Компьютерные игры как искусство [Электронный ресурс]. — Режим
доступа: http://gamesisart.ru (дата обращения: 09.02.2020).
7. Game Maker: Studio [Электронный ресурс]. — Режим па:
https://www.yoyogames.com/gamemakerhttps://unity3d.com/ru (Дата обращения:
09.02.2020).
8. Mark of the Ninja [Электронный ресурс]. — Режим па:
https://www.kleientertainment.com/games/mark-ninjahttps://unity3d.com/ru (Дата
обращения: 09.02.2020).
9. Unity Game Engine [Электронный ресурс]. — Режим па:
https://unity3d.com/ru (Дата обращения: 09.02.2020).
10.Unity Manual, Unity Documentation [Электронный ресурс]: справочник.
— Режим доступа: https://docs.unity3d.com/Manual/ (дата обращения:
09.02.2020).
11.Varcure, Unity Game Development for students. - Publishing, 2020. -345 с.
12.Хорхе Паласиос Unity 5.х. Программирование искусственного
интеллекта в играх, 2020 – 272 с.
13.Джон Мэннинг, Пэрис Батфилд-Эддисон Unity для разработчика.
Мобильные мультиплатформенные игры , 2020 – 304 с.
42
14.Nicolas Alejandro Borromeo Hands-On Unity 2020 Game Development,
2020 – 581 с.
15.Sue Blackman. Beginning 3D Game Development with Unity: All-in-one,
Multi-platform Game Development. - Apress, 2018. - 992 с.
16.Хокинг Джозеф Unity в действии. Мультиплатформенная разработка на
C#, 2019 – 352 с.
17.Степчева З.В. Основы геометрического моделирования в Unity 3D.
18.Goldstone, W. Unity Game Development Essentials. - Packt Publishing,
2019. -316 с.
19.Creighton, R.-H.Unity 3D Game Development by Example Beginner's
Guide. - Packt Publishing, 2018. - 384 c.
20.C# Programming Guide. [Электронный ресурс] URL:
https://msdn.microsoft.com/en-us/library/67ef8sbd.aspx (дата обращения:
09.02.2020).
21.Официальный сайт Visual Studio. [Электронный ресурс] URL:
https://www.visualstudio.com/ru/vs/ (дата обращения: 09.02.2020).
22.Официальный сайт игры Pacman. [Электронный ресурс] URL:
http://pacman.com/en/ (дата обращения: 09.02.2020).

43
Приложение

using UnityEngine;

using UnityEngine.UI;

using System.Collections;

using System.Collections.Generic;

public class GridManager : MonoBehaviour {

private static int rows = 4;

private static int cols = 4;

private static int lowestNewTileValue = 2;

private static int highestNewTileValue = 4;

private static float borderOffset = 0.05f;

private static float horizontalSpacingOffset = -1.65f;

private static float verticalSpacingOffset = 1.65f;

private static float borderSpacing = 0.1f;

private static float halfTileWidth = 0.55f;

private static float spaceBetweenTiles = 1.1f;

private int points;

private List<GameObject> tiles;

private Rect resetButton;

private Rect gameOverButton;

private Vector2 touchStartPosition = Vector2.zero;

public int maxValue = 2048;

public GameObject gameOverPanel;

public GameObject noTile;

public Text scoreText;

public GameObject[] tilePrefabs;

public LayerMask backgroundLayer;

public float minSwipeDistance = 10.0f;

private enum State {

Loaded,

44
WaitingForInput,

CheckingMatches,

GameOver

private State state;

#region monodevelop

void Awake() {

tiles = new List<GameObject>();

state = State.Loaded;

void Update() {

if (state == State.GameOver) {

gameOverPanel.SetActive(true);

} else if (state == State.Loaded) {

state = State.WaitingForInput;

GenerateRandomTile();

GenerateRandomTile();

} else if (state == State.WaitingForInput) {

#if UNITY_STANDALONE

if (Input.GetButtonDown("Left")) {

if (MoveTilesLeft()) {

state = State.CheckingMatches;

} else if (Input.GetButtonDown("Right")) {

if (MoveTilesRight()) {

state = State.CheckingMatches;

} else if (Input.GetButtonDown("Up")) {

if (MoveTilesUp()) {

state = State.CheckingMatches;

} else if (Input.GetButtonDown("Down")) {

45
if (MoveTilesDown()) {

state = State.CheckingMatches;

} else if (Input.GetButtonDown("Reset")) {

Reset();

} else if (Input.GetButtonDown("Quit")) {

Application.Quit();

#endif

#if UNITY_ANDROID || UNITY_IOS || UNITY_WP8 || UNITY_WP8_1

if(Input.touchCount > 0 && Input.GetTouch(0).phase ==


TouchPhase.Began) {

touchStartPosition = Input.GetTouch(0).position;

if(Input.GetTouch(0).phase == TouchPhase.Ended) {

Vector2 swipeDelta = (Input.GetTouch(0).position -


touchStartPosition);

if(swipeDelta.magnitude < minSwipeDistance) {

return;

swipeDelta.Normalize();

if(swipeDelta.y > 0.0f && swipeDelta.x > -0.5f &&


swipeDelta.x < 0.5f) {

if(MoveTilesUp()) {

state = State.CheckingMatches;

} else if(swipeDelta.y < 0.0f && swipeDelta.x > -0.5f &&


swipeDelta.x < 0.5f) {

if(MoveTilesDown()) {

state = State.CheckingMatches;

} else if(swipeDelta.x > 0.0f && swipeDelta.y > -0.5f &&


swipeDelta.y < 0.5f) {

if(MoveTilesRight()) {

state = State.CheckingMatches;

46
} else if(swipeDelta.x < 0.0f && swipeDelta.y > -0.5f &&
swipeDelta.y < 0.5f) {

if(MoveTilesLeft()) {

state = State.CheckingMatches;

#endif

} else if (state == State.CheckingMatches) {

GenerateRandomTile();

if (CheckForMovesLeft()) {

ReadyTilesForUpgrading();

state = State.WaitingForInput;

} else {

state = State.GameOver;

#endregion

#region class methods

private static Vector2 GridToWorldPoint(int x, int y) {

return new Vector2(x + horizontalSpacingOffset + borderSpacing * x,

-y + verticalSpacingOffset - borderSpacing * y);

private static Vector2 WorldToGridPoint(float x, float y) {

return new Vector2((x - horizontalSpacingOffset) / (1 + borderSpacing),

(y - verticalSpacingOffset) / -(1 + borderSpacing));

#endregion

#region private methods

private bool CheckForMovesLeft() {

if (tiles.Count < rows * cols) {

47
return true;

for (int x = 0; x < cols; x++) {

for (int y = 0; y < rows; y++) {

Tile currentTile = GetObjectAtGridPosition(x, y).GetComponent<Tile>();

Tile rightTile = GetObjectAtGridPosition(x + 1, y).GetComponent<Tile>();

Tile downTile = GetObjectAtGridPosition(x, y + 1).GetComponent<Tile>();

if (x != cols - 1 && currentTile.value == rightTile.value) {

return true;

} else if (y != rows - 1 && currentTile.value == downTile.value) {

return true;

return false;

public void GenerateRandomTile() {

if (tiles.Count >= rows * cols) {

throw new UnityException("Unable to create new tile - grid is already full");

int value;

// find out if we are generating a tile with the lowest or highest value

float highOrLowChance = Random.Range(0f, 0.99f);

if (highOrLowChance >= 0.9f) {

value = highestNewTileValue;

} else {

value = lowestNewTileValue;

// attempt to get the starting position

int x = Random.Range(0, cols);


48
int y = Random.Range(0, rows);

// starting from the random starting position, loop through

// each cell in the grid until we find an empty positio

bool found = false;

while (!found) {

if (GetObjectAtGridPosition(x, y) == noTile) {

found = true;

Vector2 worldPosition = GridToWorldPoint(x, y);

GameObject obj;

if (value == lowestNewTileValue) {

obj = SimplePool.Spawn(tilePrefabs[0],
worldPosition, transform.rotation);

} else {

obj = SimplePool.Spawn(tilePrefabs[1],
worldPosition, transform.rotation);

tiles.Add(obj);

TileAnimationHandler tileAnimManager =
obj.GetComponent<TileAnimationHandler>();

tileAnimManager.AnimateEntry();

x++;

if (x >= cols) {

y++;

x = 0;

if (y >= rows) {

y = 0;

49
private GameObject GetObjectAtGridPosition(int x, int y) {

RaycastHit2D hit = Physics2D.Raycast(GridToWorldPoint(x, y), Vector2.right,


borderSpacing);

if (hit && hit.collider.gameObject.GetComponent<Tile>() != null) {

return hit.collider.gameObject;

} else {

return noTile;

private bool MoveTilesDown() {

bool hasMoved = false;

for (int y = rows - 1; y >= 0; y--) {

for (int x = 0; x < cols; x++) {

GameObject obj = GetObjectAtGridPosition(x, y);

if (obj == noTile) {

continue;

Vector2 raycastOrigin = obj.transform.position;

raycastOrigin.y -= halfTileWidth;

RaycastHit2D hit = Physics2D.Raycast(raycastOrigin, -Vector2.up,


Mathf.Infinity);

if (hit.collider != null) {

GameObject hitObject = hit.collider.gameObject;

if (hitObject != obj) {

if (hitObject.tag == "Tile") {

Tile thatTile = hitObject.GetComponent<Tile>();

Tile thisTile = obj.GetComponent<Tile>();

if (CanUpgrade(thisTile, thatTile)) {

UpgradeTile(obj, thisTile, hitObject, thatTile);

hasMoved = true;

} else {

Vector3 newPosition = hitObject.transform.position;


50
newPosition.y += spaceBetweenTiles;

if (!Mathf.Approximately(obj.transform.position.y, newPosition.y)) {

obj.transform.position = newPosition;

hasMoved = true;

} else if (hitObject.tag == "Border") {

Vector3 newPosition = obj.transform.position;

newPosition.y = hit.point.y + halfTileWidth + borderOffset;

if (!Mathf.Approximately(obj.transform.position.y, newPosition.y)) {

obj.transform.position = newPosition;

hasMoved = true;

return hasMoved;

private bool MoveTilesLeft() {

bool hasMoved = false;

for (int x = 1; x < cols; x++) {

for (int y = 0; y < rows; y++) {

GameObject obj = GetObjectAtGridPosition(x, y);

if (obj == noTile) {

continue;

Vector2 raycastOrigin = obj.transform.position;

raycastOrigin.x -= halfTileWidth;

51
RaycastHit2D hit = Physics2D.Raycast(raycastOrigin, -Vector2.right,
Mathf.Infinity);

if (hit.collider != null) {

GameObject hitObject = hit.collider.gameObject;

if (hitObject != obj) {

if (hitObject.tag == "Tile") {

Tile thatTile = hitObject.GetComponent<Tile>();

Tile thisTile = obj.GetComponent<Tile>();

if (CanUpgrade(thisTile, thatTile)) {

UpgradeTile(obj, thisTile, hitObject, thatTile);

hasMoved = true;

} else {

Vector3 newPosition = hitObject.transform.position;

newPosition.x += spaceBetweenTiles;

if (!Mathf.Approximately(obj.transform.position.x, newPosition.x)) {

obj.transform.position = newPosition;

hasMoved = true;

} else if (hitObject.tag == "Border") {

Vector3 newPosition = obj.transform.position;

newPosition.x = hit.point.x + halfTileWidth + borderOffset;

if (!Mathf.Approximately(obj.transform.position.x, newPosition.x)) {

obj.transform.position = newPosition;

hasMoved = true;

return hasMoved;

52
private bool MoveTilesRight() {

bool hasMoved = false;

for (int x = cols - 1; x >= 0; x--) {

for (int y = 0; y < rows; y++) {

GameObject obj = GetObjectAtGridPosition(x, y);

if (obj == noTile) {

continue;

Vector2 raycastOrigin = obj.transform.position;

raycastOrigin.x += halfTileWidth;

RaycastHit2D hit = Physics2D.Raycast(raycastOrigin, Vector2.right,


Mathf.Infinity);

if (hit.collider != null) {

GameObject hitObject = hit.collider.gameObject;

if (hitObject != obj) {

if (hitObject.tag == "Tile") {

Tile thatTile = hitObject.GetComponent<Tile>();

Tile thisTile = obj.GetComponent<Tile>();

if (CanUpgrade(thisTile, thatTile)) {

UpgradeTile(obj, thisTile, hitObject, thatTile);

hasMoved = true;

} else {

Vector3 newPosition = hitObject.transform.position;

newPosition.x -= spaceBetweenTiles;

if (!Mathf.Approximately(obj.transform.position.x, newPosition.x)) {

obj.transform.position = newPosition;

hasMoved = true;

} else if (hitObject.tag == "Border") {

Vector3 newPosition = obj.transform.position;

newPosition.x = hit.point.x - halfTileWidth - borderOffset;

if (!Mathf.Approximately(obj.transform.position.x, newPosition.x)) {

53
obj.transform.position = newPosition;

hasMoved = true;

return hasMoved;

private bool MoveTilesUp() {

bool hasMoved = false;

for (int y = 1; y < rows; y++) {

for (int x = 0; x < cols; x++) {

GameObject obj = GetObjectAtGridPosition(x, y);

if (obj == noTile) {

continue;

Vector2 raycastOrigin = obj.transform.position;

raycastOrigin.y += halfTileWidth;

RaycastHit2D hit = Physics2D.Raycast(raycastOrigin, Vector2.up,


Mathf.Infinity);

if (hit.collider != null) {

GameObject hitObject = hit.collider.gameObject;

if (hitObject != obj) {

if (hitObject.tag == "Tile") {

Tile thatTile = hitObject.GetComponent<Tile>();

Tile thisTile = obj.GetComponent<Tile>();

if (CanUpgrade(thisTile, thatTile)) {

UpgradeTile(obj, thisTile, hitObject, thatTile);

hasMoved = true;

54
} else {

Vector3 newPosition = hitObject.transform.position;

newPosition.y -= spaceBetweenTiles;

if (!Mathf.Approximately(obj.transform.position.y, newPosition.y)) {

obj.transform.position = newPosition;

hasMoved = true;

} else if (hitObject.tag == "Border") {

Vector3 newPosition = obj.transform.position;

newPosition.y = hit.point.y - halfTileWidth - borderOffset;

if (!Mathf.Approximately(obj.transform.position.y, newPosition.y)) {

obj.transform.position = newPosition;

hasMoved = true;

return hasMoved;

private bool CanUpgrade(Tile thisTile, Tile thatTile) {

return (thisTile.value != maxValue && thisTile.power == thatTile.power && !


thisTile.upgradedThisTurn && !thatTile.upgradedThisTurn);

private void ReadyTilesForUpgrading() {

foreach (var obj in tiles) {

Tile tile = obj.GetComponent<Tile>();

tile.upgradedThisTurn = false;

55
public void Reset() {

gameOverPanel.SetActive(false);

foreach (var tile in tiles) {

SimplePool.Despawn(tile);

tiles.Clear();

points = 0;

scoreText.text = "0";

state = State.Loaded;

private void UpgradeTile(GameObject toDestroy, Tile destroyTile, GameObject


toUpgrade, Tile upgradeTile) {

Vector3 toUpgradePosition = toUpgrade.transform.position;

tiles.Remove(toDestroy);

tiles.Remove(toUpgrade);

SimplePool.Despawn(toDestroy);

SimplePool.Despawn(toUpgrade);

// create the upgraded tile

GameObject newTile = SimplePool.Spawn(tilePrefabs[upgradeTile.power],


toUpgradePosition, transform.rotation);

tiles.Add(newTile);

Tile tile = newTile.GetComponent<Tile>();

tile.upgradedThisTurn = true;

points += upgradeTile.value * 2;

scoreText.text = points.ToString();

TileAnimationHandler tileAnim = newTile.GetComponent<TileAnimationHandler>();

tileAnim.AnimateUpgrade();

}
56
#endregion

using UnityEngine;
using System.Collections.Generic;

public static class SimplePool


{

// Вы можете избежать изменения размера внутреннего массива стека, установив


его на число, равное или большее того, что вы хотите.
// ожидайте, что большинство ваших размеров бассейна будут такими.
// Примечание, вы также можете использовать Preload() для установки начального
размера
// of a pool-это может быть удобно, если только некоторые из ваших пулов
// будут исключительно большими (например, ваши пули.)
const int DEFAULT_POOL_SIZE = 3;

/// <summary>
/// Класс Pool представляет пул для конкретного сборного модуля.
/// </summary>
class Pool {
// Мы добавляем идентификатор к имени всего, что мы создаем.
// Это чисто косметическое средство.
int nextId =1;

// Структура, содержащая наши неактивные объекты.


// Почему Стек, а не список? Потому что нам это никогда не понадобится
// выдерните объект из начала или середины массива.
// Мы всегда будем просто хватать последний, что исключает
// любая необходимость перетасовывать объекты в памяти.
Stack<GameObject> inactive;

// Сборный дом, который мы объединяем


GameObject prefab;

// Constructor
public Pool(GameObject prefab, int initialQty) {
this.prefab = prefab;

// Если Стек использует связанный список внутренне, то это


// // все это изначально-это плацебо, которое мы могли бы
// strip out для более минимального кода.
inactive = new Stack<GameObject>(initialQty);
}

// Порождение объекта из нашего пула


public GameObject Spawn(Vector3 pos, Quaternion rot) {
GameObject obj;
if(inactive.Count==0) {
// У нас нет объекта в нашем бассейне, поэтому мы
// создать экземпляр совершенно нового объекта.
obj = (GameObject)GameObject.Instantiate(prefab, pos, rot);
obj.name = prefab.name + " ("+(nextId++)+")";

// Добавьте компонент-член пула, чтобы мы знали, какой пул


// мы принадлежим.
obj.AddComponent<PoolMember>().myPool = this;
}
else {

57
// Захватите последний объект в неактивном массиве
obj = inactive.Pop();

if(obj == null) {
// Неактивный объект, который мы ожидали найти,
больше не существует.
// Наиболее вероятными причинами являются:
// - Кто-то вызывает Destroy() на нашем объекте
// - Смена сцены (которая уничтожит все наши объекты).
// ПРИМЕЧАНИЕ: Это можно было бы предотвратить с помощью
DontDestroyOnLoad
// -если ты действительно этого не хочешь.
// Не беспокойтесь-мы просто попробуем следующий в нашей
последовательности.

return Spawn(pos, rot);


}
}

obj.transform.position = pos;
obj.transform.rotation = rot;
obj.SetActive(true);
return obj;

// Возврат объекта в неактивный пул.


public void Despawn(GameObject obj) {
obj.SetActive(false);

// Поскольку у стека нет члена Емкости, мы не можем его


контролировать
// фактор роста, если ему действительно нужно расширить
внутренний массив.
// С другой стороны, он может просто использовать связанный
список
// внутренне. Но тогда почему он позволяет нам определить размер
// в конструкторе? Стек-это странно.
inactive.Push(obj);
}

/// <summary>
/// Добавлено к недавно созданным объектам, чтобы мы могли связать их обратно
/// к правильному пулу на despawn.
/// </summary>
class PoolMember : MonoBehaviour {
public Pool myPool;
}

// Все наши бассейны


static Dictionary< GameObject, Pool > pools;

/// <summary>
/// Init our dictionary.
/// </summary>
static void Init (GameObject prefab=null, int qty = DEFAULT_POOL_SIZE) {
if(pools == null) {
pools = new Dictionary<GameObject, Pool>();
58
}
if(prefab!=null && pools.ContainsKey(prefab) == false) {
pools[prefab] = new Pool(prefab, qty);
}
}

/// <summary>
/// Если вы хотите предварительно загрузить несколько копий объекта в начале
/// сцены, вы можете использовать это. Действительно не нужен, если только вы
не
/// собирается перейти от нулевых экземпляров к 10+ очень быстро.
/// Технически можно было бы оптимизировать больше, но на практике
// Последовательность / Spawn/Despawn будет чертовски быстрой, и
/// это позволит избежать дублирования кода.
/// </summary>
static public void Preload(GameObject prefab, int qty = 1) {
Init(prefab, qty);

// Создайте массив, чтобы захватить объекты, которые мы собираемся


предварительно породить.
GameObject[] obs = new GameObject[qty];
for (int i = 0; i < qty; i++) {
obs[i] = Spawn (prefab, Vector3.zero, Quaternion.identity);
}

// Now despawn them all.


for (int i = 0; i < qty; i++) {
Despawn( obs[i] );
}
}

/// <summary>
/// Создает копию указанного префаба (при необходимости создает экземпляр).
/// ПРИМЕЧАНИЕ: Помните, что Awake() или Start() будут запускаться только в
самом первом случае.
/// spawn и что переменные-члены не будут сброшены. OnEnable будет работать
/// /// после нереста-но помните, что переключение Активно будет также
/// вызовите эту функцию.
/// </summary>
static public GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot)
{
Init(prefab);

return pools[prefab].Spawn(pos, rot);


}

/// <summary>
/// Отбросьте указанный gameobject обратно в свой пул.
/// </summary>
static public void Despawn(GameObject obj) {
PoolMember pm = obj.GetComponent<PoolMember>();
if(pm == null) {
Debug.Log ("Object '"+obj.name+"' wasn't spawned from a pool.
Destroying it instead.");
GameObject.Destroy(obj);
}
else {
pm.myPool.Despawn(obj);
}
}

59
}

using UnityEngine;
using System.Collections;

public class Tile : MonoBehaviour {

public int value;


public int power;
public bool upgradedThisTurn;

}
using UnityEngine;
using System.Collections;

public class Tile : MonoBehaviour


{

public int value;


public int power;
public bool upgradedThisTurn;

}
using UnityEngine;
using System.Collections;

public class TileAnimationHandler : MonoBehaviour {


public float scaleSpeed;
public float growSize;
private Transform _transform;
private Vector3 growVector;

public void AnimateEntry() {


StartCoroutine("AnimationEntry");
}

public void AnimateUpgrade() {


StartCoroutine("AnimationUpgrade");
}

private IEnumerator AnimationEntry() {


while (_transform == null) {
yield return null;
}

_transform.localScale = new Vector3(0.25f, 0.25f, 1f);


while (_transform.localScale.x < 1f) {
_transform.localScale = Vector3.MoveTowards(_transform.localScale, Vector3.one,
scaleSpeed * Time.deltaTime);
yield return null;
}
}

private IEnumerator AnimationUpgrade() {


while (_transform == null) {
yield return null;
}

while (_transform.localScale.x < 1f + growSize) {


_transform.localScale = Vector3.MoveTowards(_transform.localScale, Vector3.one
+ growVector, scaleSpeed * Time.deltaTime);

60
yield return null;
}

while (_transform.localScale.x > 1f) {


_transform.localScale = Vector3.MoveTowards(_transform.localScale, Vector3.one,
scaleSpeed * Time.deltaTime);
yield return null;
}
}

void Start() {
_transform = transform;
growVector = new Vector3(growSize, growSize, 0f);
}
}

61

Вам также может понравиться