Разработка мобильного игрового приложения для операционной системы android

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

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 24.06.2018
Размер файла 1,3 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

Размещено на http://www.allbest.ru/

[Введите текст]

СОДЕРЖАНИЕ

Введение

1. Постановка задачи

1.1 Основные понятия и определения

1.2 Общее описание разрабатываемого приложения

2. Анализ методов и средств решения поставленной задачи

2.1 Теоретические основы

2.2 Аналитический обзор аналогичных приложений

3. Анализ требований к игровому приложению

3.1 Требования к интерфейсу

4. Проектирование игрового приложения

4.1 Архитектура игрового приложения

4.2 Выбор инструментальных средств разработки

4.3 Проектирование структур данных и алгоритмов

4.4 Проектирование пользовательского интерфейса

5. Тестирование игрового приложения

5.1 Обоснование методики тестирования

5.2 Результаты тестирования

6. Разработка документации

Заключение

Список использованных источников

Приложения

ВВЕДЕНИЕ

Игровая индустрия зародилась в середине 1970-х годов и за несколько лет выросла из небольшого рынка в одну из крупнейших отраслей индустрии развлечений. На рынке работают крупные игроки, небольшие фирмы и стартапы, а также независимые разработчики и сообщества.

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

В настоящее время рынок мобильных приложений очень быстро растет, и в 2017 сравнялся с рынком игр на пк, лидером игровой индустрии по платформам в настоящее время являются смартфоны(1).

Целью моей ВКР является создание небольшого игрового приложения на платформу Android, которое будет исправно работать и интерфейс которого будет точно откликаться на нужные действия пользователя, например, исполнение пользователем каких-либо действий в приложение.

В задачи исследования входит:

· Изучение любых материалов, необходимых для создания приложения.

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

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

Объектом исследования является игровой движок Unity, а предметом исследования будет разработка игры в жанре Action - Platformer на данном движке, в процессе которой мы изучим те функции движка, которые помогут нам в создании своего приложения.

1. ПОСТАНОВКА ЗАДАЧИ

1.1 Основные понятия и определения

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

· Геймплей (англ.gameplay) - игровой процесс, описывает то как игрок взаимодействует с игровым миром и механиками игры.

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

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

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

· Сеттинг - (англ. setting -- с англ.?--?«помещение, установка, обстановка») время, место и обстоятельства, в которых развиваются события. Описывая сеттинг, пользователь определяет свойства реальности, моделируемой медиапродуктом.

· Фэнтези - (англ. fantasy -- «фантазия») жанр современного искусства, основанный на использование мифологических и сказочных мотивов в современном виде.

· Квест(англ. Quest) - в компьютерных ролевых играх - это задание, выполнив которое, персонаж игрока или его группа получает определенную награду(в т.ч. продвижение по сюжету).

· Сценарный язык(англ. scripting language) - высокоуровневый язык сценариев - кратких описаний действий, выполняемых системой.

· Сценарий -- это программа, имеющая дело с готовыми программными компонентам.

· Freemium(также известное как «условно-бесплатное ПО», англ. free -- бесплатный и англ. premium -- улучшенный, отличающийся более высоким качеством) - бизнес-модель заключающаяся в предложении воспользоваться приложением бесплатно, в то время как его расширенная версия, дополнительный функционал, сервисы, либо другие продукты связанные с основным предлагаются за дополнительную плату.

· Платформер(англ. Platformer) - жанр компьютерных игр, в которых основной чертой игрового процесса является прыгание по платформам, лазанье по лестницам, собирание предметов.

· Параллактическое отображение(англ. Parallax mapping) - программная техника в трёхмерной компьютерной графике, осуществляется смещением текстурных координат так, чтобы поверхность казалась объёмной.

1.2 Общее описание разрабатываемого приложения

Аналитическая компания Playliner проводила исследование по популярным жанрам и сеттингам мобильных игр во время которого были проанализировала 150 игровых приложений из списка лидеров Google play. Лидирующую позицию занял сеттинг фэнтези. Действие 31 игры из списка лидеров разворачивается именно в фэнтезийном мире. На втором месте оказались сказочный сеттинг и сеттинг казино, по 25 игр. Третью позицию занял “современный мир”. Для жанра RPG самым популярным сеттингом стал фэнтези(2). android движок алгоритм интерфейс

Следующий критерий популярности - длина игровой сессии. Согласно исследованиям GameAnalytics(3), в среднем человек проводит за мобильной игрой 6 минут. Для игр жанра Action средний показатель равняется 5 минутам.

Самым популярным жанром оказался с довольно большим отрывом Action 23.5% от всех приложений, на втором месте идет жанр Simulation 15.8%

Данное мобильное игровое приложение будет выполнено в жанре Platformer фэнтези сеттинга, написанная на движке Unity, ориентированное на пользователей, использующих мобильные устройства на базе OC Android, и предназначенное для развлечения пользователей, жанр был выбран из личных предпочтений. Визуальная составляющая будет выполнена в виде 2D графики с игровой камерой, фиксированной на персонаже. Также будет присутствовать развитие персонажа, разные типы врагов и другие геймплейные особенности.

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

2. АНАЛИЗ МЕТОДОВ И СРЕДСТВ РЕШЕНИЯ ПОСТАВЛЕННОЙ ЗАДАЧИ

2.1 Теоретические основы

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

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

В качестве инструмента для создания анимации был выбран встроенный в Unity компонент Animator. В качестве языка программирование был выбран C#.

Для работы со звуком и звуковыми эффектами были использованы стандартные возможности Unity, для более удобного контроля звуковых эффектов было принято решение написать скрипт AudioManager.

Более подробно движки будут рассмотрены в пункте 4.2

2.2 Аналитический обзор аналогичных приложений

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

· Magic Rampage

· Требования игры: Android 4.0 и выше

Жанр: Action Platformer

Метки: Экшен, Выбор редакции

Количество установок: 1.000.000+

Оценка: 4.6 на основе 206.337 отзывов

Разработчик: asanteegames

Управление: Сенсорный экран

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

· Sword Of Xolan

· Требования игры: Android 2.3 и выше

Жанр: Action Platformer

Метки: Экшен

Количество установок: 1.000.000+

Оценка: 4.5 на основе 55.571 отзыва

Разработчик: Alper Sarэkaya

Управление: Сенсорный экран

Для управления героем используются сенсорные клавиши. Путешествуем по миру игры, уничтожаем противников, собираем монетки и стараемся освободить заключенных людей. На каждом уровне таких заключенных по три штуки, плюс можно найти тайное место с сундуком, в котором спрятано много монеток. Так же на уровнях попадаются ящики и вазы, разбив которые вы сможете найти очки жизней, бутылки с маной, монеты(4).

· Ghoulboy - Dark sword of Goblin-Action platform

· Требования игры: Android 4.1 и выше

Жанр: Action platformer

Метки: Экшен

Количество установок GooglePlay: 50.000+

Оценка: 4.3 на основе 1.165 отзывов

Разработчик: Serkan Bakar

Управление: Сенсорный экран

С точки зрения геймплея Ghoulboy -- Dark Sword of Goblin даже не пытается привнести что-то новое в жанр, но при этом искусно совмещает в себе правильно подобранные и всем нам знакомые элементы. Наш герой умеет прыгать, и использовать два вида оружия - дальнего и ближнего боя, каждого из которых в игре по три разновидности. Из интересных особенностей можно отметить использование копья в качестве платформы, чтобы забраться в недоступные для обычного прыжка места. Помимо сражений, вам также предстоит проходить зачастую очень непростые ловушки, решать головоломки и драться с боссами(5).

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

3. АНАЛИЗ ТРЕБОВАНИЙ К ИГРОВОМУ ПРИЛОЖЕНИЮ

3.1 Требования к интерфейсу

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

Давайте распишем основные требования к интерфейсу, которые должны быть реализованы в нашей игре:

1) Вывод графического интерфейса игры на экран.

2) Фон генерируется в зависимости от положения персонажа.

3) Наличие разных игровых сцен.

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

5) В меню паузы должны находится кнопки продолжения игры, выхода в меню, рестарта уровня и выхода из приложения

6) На главном игровом экране должны присутствовать сенсорные кнопки взаимодействия с миром, управления персонажем и паузы.

7) На главной игровой сцене должны присутствовать панели состояний игрока, врагов и некоторых объектов.

4. ПРОЕКТИРОВАНИЕ ИГРОВОГО ПРИЛОЖЕНИЯ

4.1 Архитектура игрового приложения

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

Таблица 4.1 - Обязательные и возможные составляющие структуры Android-приложения:

Название

Описание

Необходимость

gen

Файлы, сгенерированные самой Java. Здесь находится такой важный файл как R.java

Да

AndroidManifest.xml

Файл манифеста AndroidManifest.xml предоставляет системе основную информацию о программе. Каждое приложение должно иметь свой файл манифеста

Да

src

Каталог, в котором содержится исходный код приложения

Да

assets

Произвольное собрание каталогов и файлов

Нет

res

Каталог, содержащий ресурсы приложения. В данном каталоге могут находиться подпапки drawable, anim, layout, menu, values, xml и raw (см. ниже)

Да

Структура файлов и папок в моем игровом приложении показана на рисунке 4.1

Рисунок 4.1 - Пример класса Player.

Chars - содержит файлы относящиеся к персонажам, в т.ч. анимации.

Environment - содержит спрайты фонов и объектов.

Fonts - содержит используемые шрифты.

Plugins - содержит плагин для сенсорного контролера/джойстика.

Scenes - содержит все сцены приложения.

Scripts - содержит все c# скрипты приложения, суммарное количество скриптом используемых в проекте - 31, в таблице 4.2 представлен список скриптов с их кратким описанием.

Sounds - содержит все звуковые эффекты приложения.

Таблица 4.2 - Используемые скрипты.

Название

Описание

Camera2DFollow

Содержит функции следования камеры за игроком и ограничение максимальных координат камеры.

Character

Абстрактный суперкласс, содержит основные функции персонажей и также их характеристики.

GameOverUI

Контролирует меню «конец игры».

Parallaxing

Содержит функцию параллактическое отображение

PauseMenu

Контролирует меню паузы.

Player

Singleton, содержит дополнительные функции и характеристики персонажа игрока.

ThrowWeapon

Содержит информацию о снарядах(скорость полета, удаление объекта при ударе, направление снаряда)

Tiling

Клонирует и позиционирует дополнительные фоны при контакте камеры с пустым краем.

BarScript

Отвечает за отображение статусов персонажа и врагов.

Stat

Отвечает за характеристики всех персонажей.

AttackBehaviour

Конечный автомат, отвечает за реакцию всех персонажей на определенные действия и связывает их с анимацией.

Attack - атака и нанесение урона врагу.

Damage - получение урона.

Death - смерть персонажа.

Jump - прыжок, нахождение в воздухе.

Land - приземление.

Slide - скольжение.

DamageBehaviour

DeathBehaviour

JumpBehaviour

LandBehaviour

SlideBehaviour

IgnoreCollision

Содержит функция для игнорирования столкновений между двумя объектами.

IUseable

Интерфейс для всех используемых предметов.

JumpOff

Содержит функцию для спрыгивания с платформ.

Название

Описание

Range1EnemyCollider

Содержит функцию для удаления снарядов через определенное время после попадания по цели.

Enemy

Содержит дополнительные функции и характеристики персонажей врага.

EnemySight

Контролирует область видимости врага.

IEnemyState

Интерфейс, отвечает за поведение врагов.

MeleeState

Отвечает за поведение врагов в ближнем бою.

PatrolState

Поведение врагов во время патрулирования.

IdleState

Поведение врагов во время простоя.

RangedState

Поведение врагов в дальнем бою.

AudioManager

Отвечает за все звуки в игре.

GameManager

Отвечает за выпадение предметов.

MenuManager

Отвечает за экран главного меню и экран загрузки.

SettingMenu

Меню настроек.

Далее рассмотрим примеры некоторых скриптов.

Класс Player реализуется с использованием паттерна singleton и абстрактного суперкласса Character часть кода показана на рисунке 4.2.

Рисунок 4.2 - Пример класса Player.

Класс Enemy использует абстрактный суперкласс Character и паттерн state machine. Пример кода показан на рисунке 4.3.

Рис 4.3. Пример класса Enemy.

Пример абстрактного суперкласса Character показан на рисунке 4.4.

Рисунок 4.4 - Пример класса Character.

Для реализации поведения врагов и используемых предметов используется паттерн state machine (конечный автомат) обобщенная UML диаграмма которого представлена на рисунке 4.5.

Рисунок 4.5 - UML State Machine для поведения врагов.

4.2 Выбор инструментальных средств разработки

При выборе технологий для проекта были рассмотрены три популярных движка и выбран наиболее подходящий из них.

При анализе движков были выбраны и более подробно проанализированы 3 движка: Unity, Unreal Engine, Cocos2D

1)Unity

Один из самых популярных игровых движков.

*Входной порог

Очень низкий. Имеется подробная документация и очень большое число руководств на любом языке. Огромное сообщество.

*Инструментарий

Большой набор инструментов, имеется магазин с дополнительным инструментарием, модулями и т.д..

*Удобство

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

*Языки

C#. Наличие JavaScript

*Гибкость

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

*Портируемость

Приложения легко портируется на большинство платформ

*Производительность

В целом движок очень хорошо оптимизирован, и на нем при должном усердии можно сделать производительную игру. Однако, C# довольно сильно ограничивает. Сложные диалоги, длинные списки без оптимизаций довольно сильно нагружают систему.

2)Unreal Engine

Профессиональный игровой движок, является бесплатным если суммарный доход за квартал не превышает 3000$.

*Входной порог

Довольно высок.

*Инструментарий

Огромный набор инструментов, от редактора частиц до анимирования персонажей

*Удобство

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

*Сложность разработки игровой логики

в Unreal игровая логика пишется либо на С++ с использованием Blueprints. По словам разработчиков, все работает так: С++ программисты пишут ядро и «блоки» для Blueprint'ов, а дизайнеры из этих блоков составляют игровые механики.

*Гибкость

Архитектура и С++ дают безграничные возможности в разработке, однако уклон идет в трехмерные проекты. Двумерные игры для создателей никогда не были в приоритете.

*Портируемость

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

*Производительность

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

3)Cocos2D

Полностью бесплатный и с открытым исходным кодом движок. Есть all-in-one редактор, документация и куча примеров. Игровая логика пишется на С++, либо на JavaScript. Очень много проектов на нем выпущено, отличительная особенность этих проектов -- хорошая оптимизация. Однако при более детальном рассмотрении редактор оказывается не таким удобным как кажется на первый взгляд, находится куча недочетов в исходниках и приходится много чего доделывать

*Входной порог

Довольно высок, необходимо знание С++ и довольно хорошее понимание как делаются игры.

*Инструментарий

Довольно обширный набор инструментов.

*Удобство

Очень много скопировано из других технологий. Множество консольных утилит.

*Сложность разработки игровой логики

В основном используются С++, но также есть возможность использовать JavaScript. Однако использовать их вместе несколько затруднительно.

*Гибкость

Открытый исходный код и С++ позволяют сделать все что угодно

*Портируемость

Все мобильные платформы.

*Производительность

Из-за своей простоты и гибкости позволяет достичь очень хороших результатов.

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

4.3 Проектирование структур данных и алгоритмов

Для генерации фонов используется скрипт Tiling - который дублирует фон при соприкосновении камеры с пустым краем, для придания эффекта объемности фонов при движении используется параллактическое отображение (скрипт Parallaxing). Блок-схема показана на рисунке 4.6

Рисунок 4.6 - Блок-схема скрипта Tiling.

Большая часть движений и действий персонажей реализуется в скриптах Character, Enemy и Player, все действия имею свою анимацию и при активации устанавливают триггеры для аниматора, который выполняет переходы между анимацией. Уровень Ground контроллера Player показан на рисунках 4.7-4.9. Уровень Air показан на рисунке 4.10. Также на рисунке 4.11 показана блок-схема скрипта передвижения персонажа, большая часть алгоритмов действий реализуется похожим образом.

Рисунок 4.7 - Уровень Ground - Player.

Рисунок 4.8 - ActionStates группа - Ground - Player.

Рисунок 4.9 - IdleStates группа - Ground - Player.

Рисунок 4.10 - Уровень Air - Player.

Рисунок 4.11 - Блок схема горизонтального передвижения персонажа.

4.4 Проектирование пользовательского интерфейса

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

Для движения, прыжков и скольжения используется экранный стик-контроллер, показанный на рисунке 4.12 с горизонтальной и вертикальной осями.

Рисунок 4.12 - стик-контроллер.

Для взаимодействия с миром и атак используются экранные клавиши X, A, B. X - дистанционная атака, B - атака в ближнем бою, A - спрыгивание с платформ. Данные клавиши представлены на рисунке 4.13.

Рисунок 4.13 - Клавиши взаимодействия.

Игра состоит из двух сцен:

1) Главное меню.

2) Уровень.

Сначала разберем меню, присутствующие на сцене уровня. Сенсорная кнопка “Pause” служит для вызова меню паузы, рисунок 4.14. На рисунке 4.15 показано меню паузы и на рисунке 4.16 меню «конец игры» когда у персонажа заканчиваются все жизни, все клавиши анимированные и имеют звуковой эффект при нажатии.

Рисунок 4.14 - Клавиши вызова меню паузы.

Рисунок 4.15 - Меню паузы.

Resume - снимает паузу и возобновляет игру.

Restart - полностью перезапускает текущую сцену.

To Menu - выполняет выход в главное меню.

Quit - выполняет выход из приложения.

Рисунок 4.16 - Меню «конец игры».

Retry - полностью перезапускает текущую сцену.

Quit to menu - выполняет выход в главное меню.

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

Рисунок 4.17 - Главное меню.

Play - запускает асинхронную загрузку уровня и переходит на экран загрузки представленный на рисунке 4.18.

Settings - переход на экран меню настроек - рисунок 4.19.

Quit - выполняет выход из приложения.

Рисунок 4.18 - Экран загрузки.

Рисунок 4.19 - Экран настроек.

Так как необходимо отображать здоровье, ману, количество оставшихся жизней персонажа, а также количество убитых врагов сделаны отдельные UI элементы значение и заполнения которых меняется скриптами. Индикатор здоровья врагов выполнен отдельно и появляется над каждым врагом, если его здоровье не является полным. Элементы показаны на рисунках 4.20-4.22.

Рисунок 4.20 - Панели здоровья, маны, а также индикатор оставшихся жизней персонажа.

Рисунок 4.21 - Индикатор количества убитых врагов.

Рисунок 4.22 - Индикатор здоровья врага.

За управление меню и индикаторов интерфейса отвечают скрипты GameManager, PauseMenu, BarScript, Stat, MenuManager.

5. ТЕСТИРОВАНИЕ ИГРОВОГО ПРИЛОЖЕНИЯ

5.1 Обоснование методики тестирования

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

1) Модульное тестирование.

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

2) Функциональное тестирование.

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

3) Тестирование производительности.

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

4) Тестирование инсталляции.

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

5.2 Результаты тестирования

1) Результаты модульного тестирование.

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

2) Результаты функционального тестирования.

Каждая функция тестировалась согласно функциональным требованиям, тестирование приведено в таблице 5.1.

Таблица 5.1 - функциональное тестирование.

Функция

Результат

Меню: кнопка Play

Переносит на экран загрузки уровня.

Меню: кнопка Settings

Открывает меню настроек.

Меню: кнопка Quit

Выполняет выход из приложения.

Меню настроек: ползунок Volume

Меняет общую громкость звука в приложение.

Меню настроек: кнопка Back

Возвращает назад в главное меню.

Игровая сцена: кнопки X, A, B

При нажатии на кнопку проигрывается анимация, звук и эффект действия.

Игровая сцена: стик-контроллер

Передвижение, прыжок и скольжение персонажа выполняется верно, в зависимости от положение осей контроллера.

Игровая сцена: кнопка Pause

Вызывает меню паузы, приостанавливает игру.

Меню паузы: кнопка Resume

Возобновляет игру.

Меню паузы: кнопка Restart

Перезапускает уровень.

Меню паузы: To Menu

Возвращает в главное меню.

Меню паузы: Quit

Выполняет выход из приложения.

Игровая сцена: элемент UI Count

При убийстве врагов числовое значение увеличивается на верную величину.

Функция

Результат

Игровая сцена: элемент UI HealthBar

При получение урона уровень заполнения и числовое значение снижаются, при подборе сферы здоровья уровень заполнения и числовое значение корректно увеличиваются.

Игровая сцена: элемент UI ManaBar

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

Игровая сцена: элемент UI LivesLeft

При опустошение шкалы здоровья снижается на 1.

Игровая сцена: элемент UI EnemyHealthBar

Появляется и при получение врагами урона, уровень заполнения и числовое значение корректно снижаются.

Игровая сцена: взаимодействие с противниками.

Корректно реагируют на попадание игрока в поле зрения, переходят в режим патрулирования при полной потере игрока из обзора.

Игровая сцена: выпадение сфер.

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

Меню «конец игры»: кнопка RETRY

Перезапускает уровень.

Меню «конец игры»: кнопка QUIT TO MENU

Возвращает на главное меню.

3) Результаты тестирование производительности.

Тестирование проводилось на устройстве Meizu M3 Note с android прошивкой версии. Результаты производительности оценивались инструментом Unity Profiler на рисунке 5.1 представлены результаты.

Рисунок 5.2 - тестирование производительности.

Приложение тестировалось на настройках графики показанных на рисунке 5.3.

Рисунок 5.3 - настройки графики.

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

4) Результаты тестирования инсталляцией

Приложение было успешно установлено как на личный мобильный телефон, так и на мобильные устройства нескольких друзей. Никаких проблем с производительностью, отображением, установкой либо удалением приложения замечено не было.

6. РАЗРАБОТКА ДОКУМЕНТАЦИИ

Общие данные:

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

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

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

Описание игровых сцен:

Интерфейс игровой сцены был разработан и упрощён с учетом сенсорных экранов мобильных устройств.

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

Описание игровых правил:

Игровые правила, на прохождение уровня дается 3 попытки, при снижении количества попыток до 0 уровень игры полностью перезапускается, падения характеристики здоровья до 0 воскрешает персонажа спустя 3 секунды, но убавляет число попыток на 1. Шкала здоровья снижается от получения урона, шкала маны снижается при использование специальных атак. При смерти с врагов в случайном порядке падает либо сфера, пополняющая шкалу здоровья, либо шкалу маны. Необходимо пройти уровень за 3 попытки, при переходе на следующий уровень число попыток полностью восстанавливается.

Пояснения по техническим вопросам:

Громкость звука в игре можно регулировать как через специальную функцию в меню настроек, так и аппаратными клавишами устройства.

Приложение можно в любой момент выключить как через меню паузы, так и через операционную систему.

Установка возможно на любой из накопителей устройства и требует порядка 40 мегабайт свободного места.

Приложение полностью бесплатно, при запуске приложение присутствует небольшая реклама - требование использования бесплатного движка Unity.

ЗАКЛЮЧЕНИЕ

В процессе работы над ВКР была произведена аналитика жанров, сеттингов и аудитории мобильных приложение, в результате чего было решено сделать приложение в жанре action platformer 2D с фэнтези сеттингом. Проведен анализ аналогичных приложений, выявлены некоторые их особенности, которые в последствие помогли с формированием стилистики и игровых механик моего игрового приложения. Для реализации продукта был выбран готовый движок Unity3D. Цель работы - создание игрового мобильного приложения на базе ОС Android - была достигнута.

В ходе работы были получены практические и теоретические знание о процессе разработки небольших мобильных игровых приложений. Были изучены возможности и особенности движка Unity3D и язык программирования C#.

Разработанный продукт успешно прошел все этапы тестирования, все найденные в результате баги были исправлены.

СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

1. Game Perimeter [Электронный ресурс]: Юрий Шпак / Мировой рынок компьютерных игр в 2017 году - тенденции и перспективы - Режим доступа:

2. https://gameperimeter.com/materials/analytics/the-world-market-of-computer-games-in-2017

3. habr [Электронный ресурс]: Вячеслав Уточкин / Жанры и сеттинги мобильных игр -- статистика на апрель 2017г. - Режим доступа: https://habr.com/company/miip/blog/327164/

4. GameAnalytics [Электронный ресурс]: - Режим доступа:

5. https://public-production.gameanalytics.com/assets/GameAnalytics%20Benchmarks%20Report.pdf

6. МегаОбзор [Электронный ресурс]: Влад Волошин - Режим доступа:

7. https://megaobzor.com/obzor-Magic-Rampage-platformer-dlya-dotoshnyh.html

8. https://megaobzor.com/obzor-Sword-Of-Xolan-opasnyy-pikselnyy-geroy.html

9. blast games [Электронный ресурс]: jERS / Ghoulboy -- Dark Sword of Goblin -- ретро-платформер в стиле Castlevania - Режим доступа:

10. http://blast-games.ru/obzori/ghoulboy-dark-sword-of-goblin-obzor/

11. Википедия [Электронный ресурс]:

12. Платформер - Режим доступа:

13. https://ru.wikipedia.org/wiki/Платформер

14. habr [Электронный ресурс]: Зенкович Андрей / Зачем в 2017 году писать свой движок для мобильных игр? - Режим доступа: https://habr.com/post/338214/

15. {InScopeStudios.com} [Электронный ресурс]: - Режим доступа:

16. https://inscopestudios.com/

17. BRACKEYS [Электронный ресурс]: - Режим доступа:

18. http://brackeys.com/

19. OpenGameArt.Org [Электронный ресурс]: - Режим доступа:

20. https://opengameart.org/

21. UNITY Asset Store [Электронный ресурс]: - Режим доступа:

22. https://assetstore.unity.com/

23. Itch.io [Электронный ресурс]: - Режим доступа:

24. https://itch.io/

25. Unity | Documentation [Электронный ресурс]: - Режим доступа:

26. https://docs.unity3d.com/Manual/index.html

ПРИЛОЖЕНИЕ 1

(обязательное)

Скрипты проекта

1) BarScript.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

public class BarScript : MonoBehaviour

{

private float fillAmount;

[SerializeField]

private Image content;

[SerializeField]

private float lerpSpeed;

[SerializeField]

private Text valueText;

public float MaxValue { get; set; }

public float Value

{

set

{

string[] tmp = valueText.text.Split(':');

valueText.text = tmp[0] + ": " + value;

fillAmount = Map(value, 0, MaxValue, 0, 1);

}

}

void Update ()

{

HandleBar();

}

private void HandleBar()

{

if (fillAmount != content.fillAmount)

{

content.fillAmount = Mathf.Lerp(content.fillAmount,fillAmount,Time.deltaTime*lerpSpeed);

}

}

private float Map(float value, float inMin, float inMax, float outMin, float outMax)

{

return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;

}

}

2) Stat.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

[Serializable]

public class Stat

{

[SerializeField]

private BarScript bar;

[SerializeField]

private float maxVal;

[SerializeField]

private float currentVal;

public float CurrentVal

{

get

{

return currentVal;

}

set

{

this.currentVal = Mathf.Clamp(value, 0, MaxVal);

bar.Value = currentVal;

}

}

public float MaxVal

{

get

{

return maxVal;

}

set

{

this.maxVal = value;

bar.MaxValue = maxVal;

}

}

public void Initialize()

{

this.MaxVal = maxVal;

this.CurrentVal = currentVal;

}

}

3) AttackBehaviour.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class AttackBehaviour : StateMachineBehaviour {

override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

animator.GetComponent<Character>().Attack = true;

animator.SetFloat("Speed", 0);

if (animator.tag =="Player")

{

if (Player.Instance.OnGround)

{

Player.Instance.rb2d.velocity = Vector2.zero;

}

}

}

override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

animator.GetComponent<Character>().Attack = false;

animator.GetComponent<Character>().SwordCollider.enabled = false;

animator.ResetTrigger("attack");

animator.ResetTrigger("throw");

}

}

4) DamageBehaviour.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class DamageBehaviour : StateMachineBehaviour {

override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

animator.GetComponent<Character>().TakingDamage = true;

animator.GetComponent<Rigidbody2D>().velocity = Vector2.zero;

}

override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

animator.GetComponent<Character>().TakingDamage = false;

}

}

5) DeathBehaviour.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class DeathBehaviour : StateMachineBehaviour {

private float respawnTime = 3;

private float DeathTimer;

override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

DeathTimer = 0;

}

override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

DeathTimer += Time.deltaTime;

if (DeathTimer>=respawnTime)

{

DeathTimer = 0;

animator.GetComponent<Character>().Death();

}

}

}

6) JumpBehaviour.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class JumpBehaviour : StateMachineBehaviour {

override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

Player.Instance.Jump = true;

}

override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

Player.Instance.Jump = false;

}

}

7) JumpBehaviour.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class JumpBehaviour : StateMachineBehaviour {

override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

Player.Instance.Jump = true;

}

override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

Player.Instance.Jump = false;

}

}

8) LandBehaviour.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class LandBehaviour : StateMachineBehaviour {

override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

if (Player.Instance.OnGround)

{

animator.SetBool("land", false);

animator.ResetTrigger("jump");

}

}

}

9) SlideBehaviour.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class SlideBehaviour : StateMachineBehaviour

{

private Vector2 slideOffset = new Vector2(-0.16f,-1.0f);

private Vector2 slideSize = new Vector2(1.9f, 1.52f);

private Vector2 size;

private Vector2 offset;

private BoxCollider2D PlayerCollider2D;

override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

Player.Instance.Slide = true;

if (PlayerCollider2D == null)

{

PlayerCollider2D = Player.Instance.GetComponent<BoxCollider2D>();

size = PlayerCollider2D.size;

offset = PlayerCollider2D.offset;

}

PlayerCollider2D.size = slideSize;

PlayerCollider2D.offset = slideOffset;

}

override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

{

Player.Instance.Slide = false;

animator.ResetTrigger("slide");

PlayerCollider2D.size = size;

PlayerCollider2D.offset = offset;

}

}

10) IgnoreCollision.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class IgnoreCollision : MonoBehaviour {

[SerializeField]

private Collider2D other;

void Awake ()

{

Physics2D.IgnoreCollision(GetComponent<Collider2D>(), other, true);

}

}

11) IUseable.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public interface IUseable

{

void Use();

}

12) JumpOff.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class JumpOff : MonoBehaviour, IUseable

{

[SerializeField]

private Collider2D platformCollider;

public void Use()

{

if (Player.Instance.OnPlatform)

{

UsePlatform(false);

}

else

{

UsePlatform(true);

Physics2D.IgnoreCollision(Player.Instance.GetComponent<Collider2D>(), platformCollider, true);

}

}

private void UsePlatform(bool onPlatform)

{

Player.Instance.OnPlatform = onPlatform;

}

private void OnTriggerExit2D(Collider2D other)

{

if(other.tag == "Player")

{

UsePlatform(false);

Physics2D.IgnoreCollision(Player.Instance.GetComponent<Collider2D>(), platformCollider, false);

}

}

}

13) Range1EnemyCollider.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class Range1EnemyCollider : MonoBehaviour

{

[SerializeField]

private string targetTag;

void OnTriggerEnter2D(Collider2D other)

{

if (other.tag == targetTag)

{

Destroy(gameObject, .15f);

}

}

}

14) Enemy.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class Enemy : Character

{

private IEnemyState currentState;

public GameObject Target { get; set; }

[SerializeField]

private float MeleeRange;

[SerializeField]

private float ThrowRange;

private int HPorMP;

private bool Dropped = false;

[SerializeField]

private Transform leftEdge;

[SerializeField]

private Transform rightEdge;

private Canvas healthCav;

public bool InMeleeRange

{

get

{

if (Target!=null)

{

return Vector2.Distance(transform.position, Target.transform.position) <= MeleeRange;

}

return false;

}

}

public bool InThrowRange

{

get

{

if (Target != null)

{

return Vector2.Distance(transform.position, Target.transform.position) <= ThrowRange;

}

return false;

}

}

public override bool IsDead

{

get

{

return HPStat.CurrentVal <= 0;

}

}

public override void Start ()

{

base.Start();

Player.Instance.Dead += new DeadEventHandler(RemoveTarget);

ChangeState(new IdleState());

healthCav = transform.GetComponentInChildren<Canvas>();

}

void Update ()

{

if (!IsDead)

{

if (!TakingDamage)

{

currentState.Execute();

}

LookAtTarget();

}

HPorMP = UnityEngine.Random.Range(0, 2);

}

public void RemoveTarget()

{

Target = null;

ChangeState(new PatrolState());

}

private void LookAtTarget()

{

if (Target != null)

{

float xDir = Target.transform.position.x - transform.position.x;

if (xDir < 0 && fRight || xDir > 0 && !fRight)

{

ChangeDirection();

}

}

}

private void RunSound(int i)

{

if (i == 0)

{

AudioManager.instance.PlaySound("enemyStep0");

}

if (i == 1)

{

AudioManager.instance.PlaySound("enemyStep1");

}

if (i == 2)

{

AudioManager.instance.PlaySound("enemyStep2");

}

}

private void AttackSound()

{

AudioManager.instance.PlaySound("EnemySword");

}

public void ChangeState(IEnemyState newState)

{

if (currentState != null)

{

currentState.Exit();

}

currentState = newState;

currentState.Enter(this);

}

public void Move()

{

if (!Attack)

{

if((GetDirection().x > 0 && transform.position.x < rightEdge.position.x) || (GetDirection().x < 0 && transform.position.x > leftEdge.position.x))

{

mAnimator.SetFloat("Speed", 1);

transform.Translate(GetDirection() * (mSpeed * Time.deltaTime));

}

else if (currentState is PatrolState || currentState is IdleState)

{

ChangeDirection();

}

else if (currentState is RangedState)

{

Target = null;

ChangeState(new IdleState());

}

}

}

public Vector2 GetDirection()

{

return fRight ? Vector2.right : Vector2.left;

}

public override void OnTriggerEnter2D(Collider2D other)

{

base.OnTriggerEnter2D(other);

currentState.OnTriggerEnter(other);

}

public override IEnumerator TakeDamage()

{

if(!healthCav.isActiveAndEnabled)

{

healthCav.enabled = true;

}

HPStat.CurrentVal -= 10;

if (!IsDead)

{

AudioManager.instance.PlaySound("enemyhit");

mAnimator.SetTrigger("damage");

}

else

{

if (HPorMP == 1 && Dropped == false)

{

GameObject hp =(GameObject)Instantiate(GameManager.Instance.HPPrefab, new Vector3(transform.position.x, transform.position.y + 2), Quaternion.identity);

Physics2D.IgnoreCollision(hp.GetComponent<Collider2D>(), GetComponent<Collider2D>());

Dropped = true;

}

else if (HPorMP == 0 && Dropped == false)

{

GameObject mp = (GameObject)Instantiate(GameManager.Instance.MPPrefab, new Vector3(transform.position.x, transform.position.y + 2), Quaternion.identity);

Physics2D.IgnoreCollision(mp.GetComponent<Collider2D>(), GetComponent<Collider2D>());

Dropped = true;

}

AudioManager.instance.PlaySound("enemydead");

mAnimator.SetTrigger("die");

yield return null;

}

}

public override void Death()

{

Destroy(gameObject, 3);

mAnimator.ResetTrigger("die");

healthCav.enabled = false;

}

public override void ChangeDirection()

{

Transform tmp = transform.Find("EnemyHPCanvas").transform;

Vector3 pos = tmp.position;

tmp.SetParent(null);

base.ChangeDirection();

tmp.SetParent(transform);

tmp.position = pos;

}

public void CountOnDeath()

{

GameManager.Instance.EnemyKilled++;

}

}

15) EnemySight.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class EnemySight : MonoBehaviour

{

[SerializeField]

private Enemy enemy;

void OnTriggerEnter2D(Collider2D other)

{

if (other.tag == "Player")

{

enemy.Target = other.gameObject;

}

}

void OnTriggerExit2D(Collider2D other)

{

if (other.tag == "Player")

{

enemy.Target = null;

}

}

}

16) IdleState.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class IdleState : IEnemyState

{

private Enemy enemy;

private float idleTimer;

private float idleDuration;

public void Enter(Enemy enemy)

{

idleDuration = UnityEngine.Random.Range(3, 6);

this.enemy = enemy;

}

public void Execute()

{

Idle();

if (enemy.Target != null)

{

enemy.ChangeState(new PatrolState());

}

}

public void Exit()

{

}

public void OnTriggerEnter(Collider2D other)

{

if (other.tag == "PlayerThrow" || other.tag == "SwordDMG")

{

enemy.Target = Player.Instance.gameObject;

}

}

private void Idle()

{

enemy.mAnimator.SetFloat("Speed", 0);

idleTimer += Time.deltaTime;

if (idleTimer >= idleDuration)

{

enemy.ChangeState(new PatrolState());

}

}

}

17) IEnemyState.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public interface IEnemyState

{

void Execute();

void Enter(Enemy enemy);

void Exit();

void OnTriggerEnter(Collider2D other);

}

18) MeleeState.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class MeleeState : IEnemyState

{

private Enemy enemy;

public float attackTimer;

public float attackCD=2;

public bool canAttack = true;

public void Enter(Enemy enemy)

{

this.enemy = enemy;

}

public void Execute()

{

Attack();

if (enemy.InThrowRange && !enemy.InMeleeRange)

{

enemy.ChangeState(new RangedState());

}

else if (enemy.Target == null)

{

enemy.ChangeState(new IdleState());

}

}

public void Exit()

{

}

public void OnTriggerEnter(Collider2D other)

{

}

private void Attack()

{

attackTimer += Time.deltaTime;

if (attackTimer >= attackCD)

{

canAttack = true;

attackTimer = 0;

}

if (canAttack)

{

canAttack = false;

enemy.mAnimator.SetTrigger("attack");

}

}

}

19) PatrolState.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class PatrolState : IEnemyState

{

private Enemy enemy;

private float patrolTimer;

private float patrolDuration;

public void Enter(Enemy enemy)

{

patrolDuration = UnityEngine.Random.Range(6, 12);

this.enemy = enemy;

}

public void Execute()

{

Patrol();

enemy.Move();

if (enemy.Target != null && enemy.InThrowRange)

{

enemy.ChangeState(new RangedState());

}

if (enemy.Target != null && enemy.InMeleeRange)

{

enemy.ChangeState(new MeleeState());

}

}

public void Exit()

{

}

public void OnTriggerEnter(Collider2D other)

{

if (other.tag == "PlayerThrow" || other.tag == "SwordDMG")

{

enemy.Target = Player.Instance.gameObject;

}

}

private void Patrol()

{

patrolTimer += Time.deltaTime;

if (patrolTimer >= patrolDuration)

{

enemy.ChangeState(new IdleState());

}

}

}

20) RangedState.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class RangedState : IEnemyState

{

private Enemy enemy;

public float throwTimer;

public float throwCD = 10;

public bool canThrow = true;

public void Enter(Enemy enemy)

{

throwCD = UnityEngine.Random.Range(8, 12);

this.enemy = enemy;

}

public void Execute()

{

ThrowWeapon();

if (enemy.InMeleeRange)

{

enemy.ChangeState(new MeleeState());

}

else if (enemy.Target != null)

{

enemy.Move();

}

else

{

enemy.ChangeState(new IdleState());

}

}

public void Exit()

{

}

public void OnTriggerEnter(Collider2D other)

{

}

private void ThrowWeapon()

{

throwTimer += Time.deltaTime;

if(throwTimer >= throwCD)

{

canThrow = true;

throwTimer = 0;

}

if (canThrow)

{

canThrow = false;

enemy.mAnimator.SetTrigger("throw");

}

}

}

21) AudioManager.cs

using UnityEngine;

[System.Serializable]

public class Sound

{

public string name;

public AudioClip clip;

private AudioSource source;

[Range(0f,1f)]

public float volume = 0.7f;

[Range(0.5f,1.5f)]

public float pitch = 1f;

public bool loop = false;

public void SetSource(AudioSource _source)

{

source = _source;

source.clip = clip;

source.loop = loop;

}

public void Play()

{

source.volume = volume;

source.pitch = pitch;

source.Play();

}

public void Stop()

{

source.Stop();

}

}

public class AudioManager : MonoBehaviour

{

public static AudioManager instance;

[SerializeField]

Sound[] sounds;

void Awake()

{

if (instance != null)

{

if (instance != this)

{

Destroy(this.gameObject);

}

}

else

{

instance = this;

DontDestroyOnLoad(this);

}

}

void Start()

{

for (int i = 0; i<sounds.Length; i++)

{

GameObject _go = new GameObject("Sound_" + i + "_" + sounds[i].name);

_go.transform.SetParent(this.transform);

sounds[i].SetSource (_go.AddComponent<AudioSource>());

}

PlaySound("Music");

}

public void PlaySound(string _name)

{

for (int i = 0; i < sounds.Length; i++)

{

if (sounds[i].name == _name)

{

sounds[i].Play();

return;

}

}

Debug.LogWarning("AudioManager: Sound not found in list: "+ _name);

}

public void StopSound(string _name)

{

for (int i = 0; i < sounds.Length; i++)

{

if (sounds[i].name == _name)

{

sounds[i].Stop();

return;

}

}

Debug.LogWarning("AudioManager: Sound not found in list: " + _name);

}

}

22) GameManager.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

public class GameManager : MonoBehaviour {

private static GameManager instance;

[SerializeField]

private GameObject hPPrefab;

[SerializeField]

private GameObject mPPrefab;

[SerializeField]

private Text EnemyKilledTXT;

private int enemyKilled;

[SerializeField]

private Text LivesLeftTXT;

private int livesLeft=3;

public int LivesLeft

{

get

{

return livesLeft;

}

set

{

LivesLeftTXT.text = value.ToString();

livesLeft = value;

}

}

public static GameManager Instance

{

get

{

if (instance == null)

{

instance = FindObjectOfType<GameManager>();

}

return instance;

}

}

public GameObject HPPrefab

{

get

{

return hPPrefab;

}

}

public GameObject MPPrefab

{

get

{

return mPPrefab;

}

}

public int EnemyKilled

{

get

{

return enemyKilled;

}

set

{

EnemyKilledTXT.text = value.ToString();

this.enemyKilled = value;

}

}

}

23) MenuManager.cs

using UnityEngine;

using UnityEngine.SceneManagement;

using System.Collections;

using UnityEngine.UI;

public class MenuManager : MonoBehaviour

{

public GameObject loadingScreen;

public Slider slider;

public GameObject settingMenu;

public void Start()

{

AudioManager.instance.PlaySound("Music");

}

public void StartGame()

{

AudioManager.instance.PlaySound("buttonPress");

StartCoroutine(LoadAsynchronously());

}

IEnumerator LoadAsynchronously()

{

AsyncOperation operation = SceneManager.LoadSceneAsync(SceneManager.GetActiveScene().buildIndex + 1);

loadingScreen.SetActive(true);

while (!operation.isDone)

{

float progress = Mathf.Clamp01(operation.progress / .9f);

slider.value = progress;

yield return null;

}

}

public void QuitGame()

{

AudioManager.instance.PlaySound("buttonPress");

Application.Quit();

}

public void toSettings()

{

settingMenu.SetActive(true);

}

public void BacktoMenu()

{

settingMenu.SetActive(false);

}

}

24) SettingMenu.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.Audio;

public class SettingMenu : MonoBehaviour

{

public void SetVolumeMixer(float slidevolume)

{

AudioManager.instance.PlaySound("buttonPress");

AudioListener.volume = slidevolume;

}

}

25) Camera2DFollow.cs

using System;

using UnityEngine;

namespace UnityStandardAssets._2D

{

public class Camera2DFollow : MonoBehaviour

{

public Transform target;

public float damping = 1;

public float lookAheadFactor = 3;

public float lookAheadReturnSpeed = 0.5f;

public float lookAheadMoveThreshold = 0.1f;

private float m_OffsetZ;

private Vector3 m_LastTargetPosition;

private Vector3 m_CurrentVelocity;

private Vector3 m_LookAheadPos;

public bool border;

public float minX;

public float maxX;

public float minY;

public float maxY;

private void Start()

{

m_LastTargetPosition = target.position;

m_OffsetZ = (transform.position - target.position).z;

transform.parent = null;

}

private void Update()

{

float xMoveDelta = (target.position - m_LastTargetPosition).x;

bool updateLookAheadTarget = Mathf.Abs(xMoveDelta) > lookAheadMoveThreshold;

if (updateLookAheadTarget)

{

m_LookAheadPos = lookAheadFactor * Vector3.right * Mathf.Sign(xMoveDelta);

}

else

{

m_LookAheadPos = Vector3.MoveTowards(m_LookAheadPos, Vector3.zero, Time.deltaTime * lookAheadReturnSpeed);

}

Vector3 aheadTargetPos = target.position + m_LookAheadPos + Vector3.forward * m_OffsetZ;

Vector3 newPos = Vector3.SmoothDamp(transform.position, aheadTargetPos, ref m_CurrentVelocity, damping);

transform.position = newPos;


Подобные документы

  • Преимущества операционной системы Android. Проектирование интерфейса приложений. Визуальные редакторы и средства кроссплатформенной разработки. Оптимизация игрового процесса, выбор фреймворка и библиотек. Классификация и характеристика игр по жанрам.

    дипломная работа [2,6 M], добавлен 10.07.2017

  • Обзор мобильной ОС Android. Выбор инструментов и технологий. Проектирование прототипа графического интерфейса. Характеристика и описание пользовательского интерфейса. Проектирование и разработка базы данных. Определение списка необходимых разрешений.

    курсовая работа [376,6 K], добавлен 13.09.2017

  • Архитектура и история создания операционной системы Android. Язык программирования Java. Выбор средства для реализации Android приложения. Программная реализация Android приложения. Проведение тестирования разработанного программного обеспечения.

    курсовая работа [167,8 K], добавлен 18.01.2017

  • Структура Android-приложений. Особенности игрового движка. Алгоритмизация и программирование. Список игровых состояний. Настройка, отладка и тестирование программы. Разработка руководства пользователя. Тестирование инсталляции и отображения элементов.

    дипломная работа [4,5 M], добавлен 19.01.2017

  • Современное состояние рынка мобильных приложений. Основные подходы к разработке мобильных приложений. Обоснование выбора целевой группы потребителей приложения. Этапы проектирования и разработки мобильного приложения для операционной системы Android.

    курсовая работа [987,1 K], добавлен 27.06.2019

  • Создание, изучение и разработка приложение на Android. Среда разработки приложения DelphiXE5. Установка и настройка среды программирования. Этапы разработки приложения. Инструменты для упрощения конструирования графического интерфейса пользователя.

    курсовая работа [1,6 M], добавлен 19.04.2017

  • Структура и архитектура платформы Android. Основные достоинства и недостатки операционной системы Android. Среда разработки Eclipse, платформа Java. Подготовка среды разработки. Вкладка "Погода", "Курс валют", "Новости". Просмотр полной новости.

    дипломная работа [1,0 M], добавлен 11.07.2014

  • Архитектура операционной системы Android, набор библиотек для обеспечения базового функционала приложений и виртуальная машина Dalvik. Объектно-ориентированный язык программирования Java как инструмент разработки мобильных приложений для ОС Android.

    дипломная работа [1,6 M], добавлен 08.07.2015

  • Разработка клиент-серверного игрового приложения на примере игры в шашки для мобильных устройств на базе операционной системы Android. Обзор мобильных платформ. Экраны приложения и их взаимодействие. Графический интерфейс, руководство пользователя.

    курсовая работа [2,6 M], добавлен 15.06.2013

  • Общая схема работы приложения Android. Разработка обучающего приложения для операционной системы Android, назначение которого - развитие речи посредством произнесения скороговорок. Описание компонентов разработанного приложения, его тестирование.

    дипломная работа [1,2 M], добавлен 04.02.2016

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.