Описание реализации программных модулей. Поскольку разработка игры велась с использованием языковых сред последнего поколения, программа является событийно-управляемой. Структура программы ветвящаяся, причём переход по каждой из ветвей инициируется событием, генерируемым системой или поступающим от пользователя. Описание модулей программы приведено в таблице 1. Таблица 1 – Файлы проекта Имя файла | Описание | Avtomobil.cs | Описывает поведение модели автомобиля (игрока) | Vrag.cs | Описывает поведение моделей игровых противников | Strelba.cs | Описывает процесс стрельбы в игре | Objects.cs | Описывает поведение дополнительных игровых объектов | SpawnObjets.cs | Описание метода появления игровых объектов на карте | Doroga.cs | Описывает выбор, загрузку, повреждение игровых уровней | VragDamage.cs | Описание модели получение урона игровых противников | Links.cs | Дополнительный связующий класс. | В Таблице 2 приведено описание методов классов программы. Таблица 2 – Методы классов программы Класс | Название метода | Описание | Avtomobil.cs | Start | Состояние машины (показатели) при старте | onGUI | Связь показателей машины с элементами интерфейса | Update | Cвязь экранных интерфейсных кнопок с поведением машины | FixedUpdate | Обработчик производных действий класса Update | OnCollisionEnter2D | Описание модели повреждения машины, взаимодействия с другими игровыми объектами | Dead | Запрос на состояние модели игрока (жив/убит) для взаимодействия в меню игры | Vrag.cs | OnTriggerEnter2D | Обработка поведения моделей противников при стрельбе игрока | | OnCollisionEnter2D | Описание модели повреждения моделей противников, взаимодействия с другими игровыми объектами | Dead | Запрос на состояние моделей противников (жив/убит) для взаимодействия с системными показателями игры | EnemyDamage | Метод, передающий данные о повреждениях противников из файла VragDamage | carMotion | Метод, передающий данные о повреждениях противников из файла Avtomobil.cs | Strelba.cs | FireProcess | Описание процесс стрельбы модели игрока и противников | AutoFire | Моделирует процесс автоматического ведения огня (специальный режим) | сarLink | Метод, связывающий параметры стрельбы с файлом Avtomobil.cs для их синхронной работы. | Object.cs | OnTriggerEnter2D | Обработка поведения дополнительных игровых объектов (в примере – бочки) при взаимодействии с моделью игрока | OnCollisionEnter2D | Описание модели повреждения дополнительных игровых объектов (в примере – бочки) при взаимодействии с моделями противников | SpawnObjects.cs | EnemyBarrelSpawner | Моделирует процесс создания моделями противников дополнительных игровых объектов в качестве препятствий | VragFixed | Метод, связывающий параметры создания дополнительных игровых объектов с файлом Vrag.cs для их синхронной работы. | TimingUpdate | Описывает временную синхронизации создания новых доп. объектов | Doroga.cs | LevelGenerator | Метод, описывающий создание игрового уровня из файлов приложения. | Start | Метод, синхронизирующий «камеру» (вид на игровую модель) с самой моделью | selectionUpdate | Выбор определенного набора игровых файлов, в зависимости от выбранного уровня и процента его прохождения | VragDamage.cs | GameObjects | Выбор модели противников, в зависимости от уровня | Start | Метод, синхронизирующий «камеру» (вид на игровую модель) с моделями противников | DamageInfo | Метод, передающий данные о повреждениях противников файл Vrag.cs | 3.4 Описание внутренних переменных. В программе присутствуют интерфейсные переменные, их перечень представлен в таблице 3. Таблица 3 – Список переменных Переменная | Тип | Назначение | Speed | int | Максимальная скорость модели игрока | currentSpeed | float | Текущая скорость модели игрока | Taran | float | Системная переменная («уровень тарана») для определения повреждения модели игрока и противников | HP | float | Значение очков здоровья модели игрока в начале уровня | currentHP | float | Текущее значение очков здоровья модели игрока | eHP | float | Текущее значение очков здоровья моделей противников | HPMAX | float | Значение очков здоровья моделей противников в начале уровня | KD | float | Максимальное количество выстрелов в минуту игровых моделей | currentKD | float | Количество выстрелов в минуту игровых моделей в текущий момент | timerBarrel | float | Время сброса нового препятствия (в примере, бочки) моделями противников | DPM | float | Время «перезарядки» при стрельбе моделей противников | rand | int | Случайное значение при выборе уровня игры | timerRoad | float | Системное значение – процент прохождения уровня, влияющий на состояние дороги | enemytimer | float | Системное значение – процент прохождения уровня, влияющий на появление определенного вида противников | 3.5. Реализация диалога с пользователем. При запуске файла Gonki.exe главное меню игры «Захватывающие гонки». Игра имеет вид оконного (в версии для Android – полноэрканного) приложения, представляющего собой гоночную «аркаду» с противниками. Пользователю предлагается на выбор четыре действия: начать игру, перейти в меню настроек, просмотреть информацию об игре, либо же нажать кнопку выхода из приложения (рис 3.1).  Рисунок 3.1 – Главное меню В меню настроек (рис 3.2) пользователю предлагается выбрать язык всех текстовых надписей в игре (на русском или английском языках), включить или выключить звуковое сопровождение в игре, а также возможность выйти из приложения. В меню «Об игре» содержится информация об авторах игры, и ссылки на автора используемой в приложении музыкального сопровождения. При нажатии на кнопку «Играть» появляется окно (рис 3.3) выбора игровой модели (машины). Изначально доступны для выбора только два типа автомобилей. После прохождения определенного количества уровней становятся доступны и другие. При нажатии на кнопку «Покраска» возможно изменение внешнего вида выбранного автомобиля. При выборе определенной машины в меню появляется крупная ее фотография, а также игровая модель, которая и будет использоваться в игре. Также в этом меню отображается количество заработанных за все время игры внутренних средств.  Рисунок 3.2 – Меню настроек игры Рисунок 3.3 – Меню выбора автомобиля При нажатии кнопки далее появляется меню выбора уровня (рис 3.4). Изначально доступен лишь первый уровень, по мере прохождения будут открываться и следующие. При нажатии на кнопку «Старт» происходит запуск уровня. Игровой процесс (рис 3.5) происходит следующим образом: модель игрока управляется экранными кнопками (вверх-вниз-вправ-влево), стрельба по противниками осуществляется автоматически. Полоса справа показывается уровень жизни модели игрока, полоса справа – количество патронов для стрельбы. Число серого цвета возле кнопки паузы показывает количество средств, заработанных на уровен, число синего цвета – расстояние дго финиша.  Рисунок 3.4 – Меню выбора уровня Рисунок 3.5 – Игровой процесс По ходу игры на игровой карте будут постоянно находиться специальные бонусы – лежащие на дороге «аптечки», пополняющие здоровье игрока, и комплект патронов для стрельбы (рис 3.6). Противники на протяжении всего уровня будут пытаться помешать игроку добраться до финиша (рис 3.7). Они могут сбрасывать дополнительные препятствия (например, бочки). Игрок может использовать специальное оружие – «огненный выхлоп» (рис 3.7). Для этого необходимо нажать на кнопку с изображением круга в левой части экрана. При прохождении уровня появляется финишный экран (рис 3.8). В нем пользователю предлагается перейти на следующий уровень, перезапустить текущий или выйти в главное меню. Функциональность последних двух пунктов также содержатся в меню паузы, и в меню конца игры.  Рисунок 3.6 – Игровые бонусы  Рисунок 3.7 – Игровые противники Рисунок 3.8 – Финишный экран «Огненный выхлоп» 3.6. Тестирование приложения. Тестирование — процесс выполнения программы с целью обнаружения ошибок. Шаги процесса задаются тестами. Другое название теста — тестовый вариант. Хорошим считают тестовый вариант с высокой вероятностью обнаружения еще не раскрытой ошибки. Успешным называют тест, который обнаруживает до сих пор не раскрытую ошибку. Целью проектирования тестовых вариантов является систематическое обнаружение различных классов ошибок при минимальных затратах времени и стоимости. Тестирование обеспечивает: 1. обнаружение ошибок; 2. демонстрацию соответствия функций программы ее назначению; 3. демонстрацию реализации требований к характеристикам программы; 4. отображение надежности как индикатора качества программы. Тестирование не может показать отсутствия дефектов (оно может показывать только присутствие дефектов). Важно помнить это (скорее печальное) утверждение при проведении тестирования. Рассмотрим информационные потоки процесса тестирования. Они показаны на рис. 1.  Рисунок 4.1 – Информационные потоки процесса тестирования Выполняются тесты, все полученные результаты оцениваются. Это значит, что реальные результаты тестов сравниваются с ожидаемыми результатами. Когда обнаруживается несовпадение, фиксируется ошибка — начинается отладка. Процесс отладки непредсказуем по времени. На поиск места дефекта и исправление может потребоваться час, день, месяц. Неопределенность в отладке приводит к большим трудностям в планировании действий. После сбора и оценивания результатов тестирования начинается отображение качества и надежности ПО. Если регулярно встречаются серьезные ошибки, требующие проектных изменений, то качество и надежность ПО подозрительны, констатируется необходимость усиления тестирования. В конечном счете, если тесты не обнаруживают ошибок, появляется сомнение в том, что тестовые варианты достаточно продуманы и что в ПО нет скрытых ошибок. Такие ошибки будут, в конечном итоге, обнаруживаться пользователями и корректироваться разработчиком на этапе сопровождения (когда стоимость исправления возрастает в 60-100 раз по сравнению с этапом разработки). Результаты, накопленные в ходе тестирования, могут оцениваться и более формальным способом. Для этого используют модели надежности ПО, выполняющие прогноз надежности по реальным данным об интенсивности ошибок. Существуют 2 принципа тестирования программы: функциональное и структурное. Понятие о структурном программировании. Структурное тестирование называют также тестированием по «маршрутам», так как в этом случае тестовые наборы формируют путем анализа маршрутов, предусмотренных алгоритмом. Под маршрутами при этом понимают последовательности операторов программы, которые выполняются при конкретном варианте исходных данных. В основе структурного тестирования лежит концепция максимально полного тестирования всех маршрутов программы. Так, если алгоритм программы включает ветвление, то при одном наборе исходных данных может быть выполнена последовательность операторов, реализующая действия, которые предусматривает одна ветвь, а при втором - другая. Соответственно, для программы будут существовать маршруты, различающиеся выбранным при ветвлении вариантом. Считают, что программа проверена полностью, если с помощью тестов удается осуществить выполнение программы по всем возможным маршрутам передач управления. Однако нетрудно видеть, что даже в программе среднего уровня сложности число неповторяющихся маршрутов может быть очень велико, и, следовательно, полное или исчерпывающее тестирование маршрутов, как правило, невозможно. Структурный подход к тестированию имеет ряд недостатков. Так тестовые наборы, построенные по данной стратегии: • не обнаруживают пропущенных маршрутов; • не обнаруживают ошибок, зависящих от обрабатываемых данных; • не дают гарантии, что функциональность программы правильна. Тестовые требования: 1) Корректная работа главного меню приложения. 2) Корректная работа меню настроек приложения. 3) Корректная работа меню выбора авто. 4) Корректная работа меню уровня. 5) Корректная работа кнопок управления. 6) Корректная работа «бонусов» на уровне. Таблица 4 – Результаты тестирования. № | Ожидаемый результат | Полученный результат | Примечания | | Запуск меню настроек при нажатии на соответствующую кнопку Запуск меню информации при нажатии на соответствующую кнопку Запуск меню выбора авто при нажатии на соответствующую кнопку | Запуск меню настроек при нажатии на соответствующую кнопку Запуск меню информации при нажатии на соответствующую кнопку Запуск меню выбора авто при нажатии на соответствующую кнопку | Корректные действия при нажатии на соответствующие кнопки | | Выключение звукового сопровождения игры при нажатии на соответствующую кнопку Изменения языка надписей игры на английский | Выключение звукового сопровождения игры при нажатии на соответствующую кнопку Изменения языка надписей игры на английский | Корректные действия при нажатии на соответствующие кнопки | | Выбор машины «Ivolga» при нажатии на соответствующую кнопку Выбор машины «HotRoad» при нажатии на соответствующую кнопку Выбор машины «Armer» при нажатии на соответствующую кнопку Выбор машины «Buggy» при нажатии на соответствующую кнопку | Выбор машины «Ivolga» при нажатии на соответствующую кнопку Выбор машины «HotRoad» при нажатии на соответствующую кнопку Выбор машины «Armer» при нажатии на соответствующую кнопку Выбор машины «Buggy» при нажатии на соответствующую кнопку | Корректные действия при нажатии на соответствующие кнопки | | Выбор первого уровня при нажатии на соответствующую кнопку Выбор второго уровня при нажатии на соответствующую кнопку Выбор третьего уровня при нажатии на соответствующую кнопку | Выбор первого уровня при нажатии на соответствующую кнопку Выбор второго уровня при нажатии на соответствующую кнопку Выбор третьего уровня при нажатии на соответствующую кнопку | Корректные действия при нажатии на соответствующие кнопки | | Машина движется влево при нажатии на соответствующую кнопку Машина движется вправо при нажатии на соответствующую кнопку Машина движется вверх при нажатии на соответствующую кнопку Машина движется вниз при нажатии на соответствующую кнопку | Машина движется влево при нажатии на соответствующую кнопку Машина движется вправо при нажатии на соответствующую кнопку Машина движется вверх при нажатии на соответствующую кнопку Машина движется вниз при нажатии на соответствующую кнопку | Корректные действия при нажатии на соответствующие кнопки | | Зачисление 100% очков здоровья при использовании «бонуса» | Зачисление 100% очков здоровья при использовании «бонуса» | Корректное зачисление бонусных единиц | ЗАКЛЮЧЕНИЕ В ходе выполнения курсовой работы был разработан программный продукт, в виде игры в жанре «гонки» для компьютеров и мобильных устройств. Закреплены понятия объектно-ориентированного программирования, объектно-ориентированного анализа и объектно-ориентированного подхода, навыки по программированию в объектно-ориентированной среде, а также в построении диаграмм и тестировании. Приложение (игра) соответствует поставленной задаче и выполняет все указанные в ней требования. Ошибок и перегрузок не обнаружено, все исключительные ситуации учтены и прописаны в коде программы. СПИСОК ЛИТЕРАТУРЫ 1.Леоненков А.В. Самоучитель UML.-СПб.: БХВ-Петербург,2001.-304с. 2.Павловская Т.А. C#. Программирование на языке высокого уровня. Учебник для вузов.-СПб.: Питер, 2007.-432с. 3.Эндрю Троелсен. Язык программирования C# 2010 и платформа .NET 4.0— 5-е изд. — М.: Вильямс, 2010. — 1392 с. 4.Герберт Шилдт C# 4.0: полное руководство. - М.: «Вильямс», 2010. — 1056 с. 5.Кристиан Нейгел, Карли Уотсон и др. Visual C# 2010: полный курс. - М.: Диалектика, 2010. 6.Трей Нэш C# 2010: ускоренный курс для профессионалов.- М.: Вильямс, 2010. — 592 с. 7.Кристиан Гросс Самоучитель по C# ; БХВ Петербург, 2009 г. 576 с. 8.http://sharp-generation.narod.ru/C_Sharp/prinzips.html - Интернет ресурс ПРИЛОЖЕНИЕ Avtomobil.cs using UnityEngine; using System.Collections; public class Car : MonoBehaviour { public static int Control=40; private int Speed=40; public static float Taran=2; private int currentControl=0; private float currentSpeed=0; public GameObject Cam; public Rigidbody2D Player; public AudioClip boom; public GameObject exp; public static float HP; хп на public static float currentHP; void Start () { currentHP = HP; } void OnGUI(){: if (GUI.Button (new Rect (Screen.width * 0.0f, Screen.height * 0.45f, Screen.width * 0.5f, Screen.height * 0.17f), "")){ Application.LoadLevel (0); } } void Update () { if (Input.anyKey) { if (Input.GetKey (KeyCode.A)) {currentControl = Control;} if (Input.GetKey (KeyCode.D)) {currentControl = -Control;} if (Input.GetKey (KeyCode.W)) {currentSpeed = Speed;} if (Input.GetKey (KeyCode.S)) {currentSpeed = -Speed*1.6f;} if (Input.GetKey (KeyCode.Escape)) {Application.LoadLevel (0);} }else{ currentControl =0; currentSpeed = 0;} } void FixedUpdate () { Player.AddForce (new Vector2 (currentSpeed, currentControl)); } void OnCollisionEnter2D(Collision2D col){ if (col.gameObject.name.Contains ("Barrel")) { Handheld.Vibrate(); Car.currentHP -= 25; Dead(); Destroy(col.gameObject); AudioSource.PlayClipAtPoint(boom,new Vector3(0, 0, 0)); звук Instantiate (exp, new Vector2 (col.transform.position.x, col.transform.position.y), Quaternion.Inverse (transform.rotation)); } if (col.gameObject.name.Contains ("Taran")) { Handheld.Vibrate(); Car.currentHP -= 25; Dead(); Destroy(col.gameObject) AudioSource.PlayClipAtPoint(boom,new Vector3(0, 0, 0)); Instantiate (exp, new Vector2 (col.transform.position.x, col.transform.position.y), Quaternion.Inverse (transform.rotation)); } } void Dead(){ if (currentHP <= 0) { Instantiate (exp, new Vector2 (transform.position.x+0.5f, transform.position.y), Quaternion.identity); AudioSource.PlayClipAtPoint(boom,new Vector3(0, 0, 0)); звук Application.LoadLevel(0); } } Vrag.cs using UnityEngine; using System.Collections; public class EnemyDamage : MonoBehaviour { public float HP; public float HPMAX; public Rigidbody2D En; public GameObject sparks; public AudioClip dzink; public GameObject trup; void FixedUpdate () { En.AddRelativeForce(new Vector2(0, 10)); } void OnTriggerEnter2D(Collider2D col){ if (col.gameObject.name.Contains ("Bullet")) { Destroy (col.gameObject); En.AddTorque (Random.Range(-2,2)); AudioSource.PlayClipAtPoint(dzink,new Vector3(0, 0, 0)); Instantiate (sparks, new Vector2 (col.transform.position.x+1, col.transform.position.y), Quaternion.Inverse(transform.rotation)); HP -= 1; Dead(); } } void OnCollisionEnter2D(Collision2D col){ if (col.gameObject.name.Contains ("Car")) { if (gameObject.name.Contains ("Taran")) HP -= 1000; else HP -= Car.Taran; Dead(); } } void Dead(){ if (HP <= 0) { Destroy(gameObject); Instantiate (trup, new Vector2 (transform.position.x, transform.position.y), transform.rotation); Instantiate (exp, new Vector2 (transform.position.x, transform.position.y), Quaternion.identity); AudioSource.PlayClipAtPoint(boom,new Vector3(0, 0, 0)); } } Strelba.cs using UnityEngine; using System.Collections; public class CarShoot : MonoBehaviour { public static float KD; public float currentKD; public GameObject bullet; public AudioClip shoot1; void Update () { currentKD-=Time.deltaTime*50; if (currentKD <= 0) { if(CarSelect.carnumber == 1){ Instantiate (bullet, new Vector2 (5, 0), Quaternion.Euler(0, 0, Random.Range(-3,3))); Instantiate (bullet, new Vector2 (-5, 0), Quaternion.Euler(0, 0, Random.Range(-3,3))); } if(CarSelect.carnumber == 2){ Instantiate (bullet, new Vector2 (0, 0), Quaternion.Euler(0, 0, Random.Range(-3,3))); } if(CarSelect.carnumber == 2){ Instantiate (bullet, new Vector2 (0, 0), Quaternion.Euler(0, 0, -2)); Instantiate (bullet, new Vector2 (0, 0), Quaternion.Euler(0, 0,-1)); Instantiate (bullet, new Vector2 (0, 0), Quaternion.Euler(0, 0, 0)); Instantiate (bullet, new Vector2 (0, 0), Quaternion.Euler(0, 0, 1)); Instantiate (bullet, new Vector2 (0, 0), Quaternion.Euler(0, 0, 2)); } AudioSource.PlayClipAtPoint(shoot1,new Vector3(0, 0, 0)); currentKD = KD; } Objects.cs (частично) using UnityEngine; using System.Collections; public class Barrel : MonoBehaviour { public float Hp = 3; public AudioClip boom; public GameObject exp; void OnTriggerEnter2D(Collider2D col){ if (col.gameObject.name.Contains ("Bullet")) { Hp--; Destroy(col.gameObject); if (Hp<=0){ AudioSource.PlayClipAtPoint(boom,new Vector3(0, 0, 0)); Instantiate (exp, new Vector2 (transform.position.x, transform.position.y), Quaternion.Inverse(transform.rotation)); Destroy(gameObject); } } SpawnObjets.cs(частично) using UnityEngine; using System.Collections; public class EnemyBarrelSpawner : MonoBehaviour { public Transform barrel; private float timerBarrel = -1 public float DPM = 100; void FixedUpdate(){ timerBarrel += 1; if (timerBarrel >= DPM) { Instantiate (barrel, new Vector2 (transform.position.x, transform.position.y), Quaternion.Inverse(Quaternion.Inverse(transform.rotation))); спавн бочки timerBarrel = 0; } } Doroga.cs using UnityEngine; using System.Collections; public class LevelGenerator : MonoBehaviour { public float timerRoad = 0; public GameObject Cam; private int rand; public Transform road1; public Transform road2; public Transform road3; public Transform road4; public Transform road5; public Transform road6; public Transform road7; public Transform road8; public Transform road9; public Transform road10; void Start () { Cam = GameObject.Find("Main Camera"); } void Update () { } void FixedUpdate(){ timerRoad += 1; if (timerRoad > 50) { timerRoad = 0; rand = Random.Range(1,11); if (rand == 1){ Transform Lev = Instantiate (road1, new Vector2 (Cam.transform.position.x + 500, 0), Quaternion.Inverse (road1.rotation))as Transform; Lev.transform.parent = transform; } if (rand == 2){ Transform Lev = Instantiate (road2, new Vector2 (Cam.transform.position.x + 500, 0), Quaternion.Inverse (road1.rotation))as Transform; Lev.transform.parent = transform; } if (rand == 3){ Transform Lev = Instantiate (road3, new Vector2 (Cam.transform.position.x + 500, 0), Quaternion.Inverse (road1.rotation))as Transform; Lev.transform.parent = transform; } if (rand == 4){ Transform Lev = Instantiate (road4, new Vector2 (Cam.transform.position.x + 500, 0), Quaternion.Inverse (road1.rotation))as Transform; Lev.transform.parent = transform; } if (rand == 5){ Transform Lev = Instantiate (road5, new Vector2 (Cam.transform.position.x + 500, 0), Quaternion.Inverse (road1.rotation))as Transform; Lev.transform.parent = transform; } if (rand == 6){ Transform Lev = Instantiate (road6, new Vector2 (Cam.transform.position.x + 500, 0), Quaternion.Inverse (road1.rotation))as Transform; Lev.transform.parent = transform; } if (rand == 7){ Transform Lev = Instantiate (road7, new Vector2 (Cam.transform.position.x + 500, 0), Quaternion.Inverse (road1.rotation))as Transform; Lev.transform.parent = transform; } if (rand == 8){ Transform Lev = Instantiate (road8, new Vector2 (Cam.transform.position.x + 500, 0), Quaternion.Inverse (road1.rotation))as Transform; Lev.transform.parent = transform; } if (rand == 9){ Transform Lev = Instantiate (road9, new Vector2 (Cam.transform.position.x + 500, 0), Quaternion.Inverse (road1.rotation))as Transform; Lev.transform.parent = transform; } if (rand == 10){ Transform Lev = Instantiate (road10, new Vector2 (Cam.transform.position.x + 500, 0), Quaternion.Inverse (road1.rotation))as Transform; Lev.transform.parent = transform; } } } } VragDamage.cs using UnityEngine; using System.Collections; public class LevelGameplay : MonoBehaviour { public int EnemyT; public float enemytimer; public GameObject Enemy1; public GameObject Enemy2; public GameObject Enemy3; public GameObject Enemy4; public GameObject Enemy5; public GameObject Enemy6; public GameObject Enemy7; public GameObject Enemy8; public GameObject Enemy9; public GameObject Enemy10; public GameObject Cam; void Start () { Cam = GameObject.Find("Main Camera"); } void FixedUpdate () { enemytimer--; bonustimer--; if (enemytimer <= 0) { if (police == 0) { switch (Random.Range(1, 11)) {//от 1 до N-1 case 1: Instantiate(Enemy1, new Vector2(Cam.transform.position.x + 6, Random.Range(-1.3f, 1.3f)), Quaternion.Inverse(Enemy1.transform.rotation)); break; case 2: Instantiate(Enemy2, new Vector2(Cam.transform.position.x + 6, Random.Range(-1.3f, 1.3f)), Quaternion.Inverse(Enemy2.transform.rotation)); break; case 3: Instantiate(Enemy3, new Vector2(Cam.transform.position.x + 6, Random.Range(-1.3f, 1.3f)), Quaternion.Inverse(Enemy3.transform.rotation)); break; case 4: Instantiate(Enemy4, new Vector2(Cam.transform.position.x + 6, Random.Range(-1.3f, 1.3f)), Quaternion.Inverse(Enemy4.transform.rotation)); break; case 5: Instantiate(Enemy5, new Vector2(Cam.transform.position.x + 6, Random.Range(-1.3f, 1.3f)), Quaternion.Inverse(Enemy5.transform.rotation)); break; case 6: Instantiate(Enemy6, new Vector2(Cam.transform.position.x + 6, Random.Range(-1.3f, 1.3f)), Quaternion.Inverse(Enemy6.transform.rotation)); break; case 7: Instantiate(Enemy7, new Vector2(Cam.transform.position.x + 6, Random.Range(-1.3f, 1.3f)), Quaternion.Inverse(Enemy7.transform.rotation)); break; case 8: Instantiate(Enemy8, new Vector2(Cam.transform.position.x + 6, Random.Range(-1.3f, 1.3f)), Quaternion.Inverse(Enemy8.transform.rotation)); break; case 9: Instantiate(Enemy9, new Vector2(Cam.transform.position.x + 6, Random.Range(-1.3f, 1.3f)), Quaternion.Inverse(Enemy9.transform.rotation)); break; case 10: Instantiate(Enemy10, new Vector2(Cam.transform.position.x + 6, Random.Range(-1.3f, 1.3f)), Quaternion.Inverse(Enemy10.transform.rotation)); break; } enemytimer = Random.Range(50, EnemyT); } } |