Please use this identifier to cite or link to this item:
https://er.chdtu.edu.ua/handle/ChSTU/8846| Title: | Програмне забезпечення гри в жанрі Real-Time Strategy |
| Authors: | Немов, Руслан Григорович Татаровський, Артем Валерійович |
| Keywords: | RTS-ГРА;ГЕЙМПЛЕЙ;ІНТЕРФЕЙС;МОДУЛЬНІСТЬ;ІГРОВЕ ПРОГРАМНЕ ЗАБЕЗПЕЧЕННЯ;РОЗРОБКА ІГОР;КЕРУВАННЯ ЮНІТАМИ;ЗБІР РЕСУРСІВ;БУДІВНИЦТВО;ТРЕНУВАННЯ ЮНІТІВ;БІЙ/АТАКА;ПРОГРАМНА ІНЖЕНЕРІЯ;RTS GAME;GAMEPLAY;INTERFACE;MODULARITY;GAME SOFTWARE;GAME DEVELOPMENT;UNIT MANAGEMENT;RESOURCE GATHERING;BUILDING;UNIT TRAINING;COMBAT/ATTACK;SOFTWARE ENGINEERING |
| Issue Date: | 20-Jun-2025 |
| Abstract: | АНОТАЦІЇ
Виконавець: Татаровський Артем Валерійович.
Назва роботи: "Програмне забезпечення гри в жанрі Real-Time Strategy".
Спеціальність: 121 Інженерія програмного забезпечення.
Навчальний заклад: «Черкаський державний технологічний університет» м. Черкаси, 2025р.
Мета: Розробити програмне забезпечення гри в реальному часі (RTS) яка занурить гравців у світ, де вони зможуть продемонструвати свої тактичні навички, керуючи арміями та розбудовуючи імперії.
Цілі:
реалізація ігрових механік гри;
забезпечення оптимальної продуктивності гри, зменшуючи затримки та забезпечуючи плавний геймплей, навіть на менш потужних пристроях; розробка модульного та розширюваного коду для полегшення додавання нових функцій та вдосконалень. У розділі аналізу вимог були поставлені вимоги для програмного забезпечення. У розділі моделювання програмного забезпечення було описано архітектуру програмного забезпечення. У розділі аналіз якості були описані основні тест кейси, та стани системи після проведення тестування. У розділі впровадження та супроводу було описано процеси розгортання програмного забезпечення. ANNOTATIONS Performer:Tatarovskyi Artem Valeriiovych. The title of the work: "Real-Time Strategy game software ". Specialty: 121 Software engineering. Educational institution: Cherkasy State Technological University, Cherkasy, 2025. Goal: o develop a real-time strategy (RTS) game that immerses players in a world where they can demonstrate their tactical skills by commanding armies and building empires. Objectives: implementation of game mechanics; ensuring optimal game performance by reducing latency and providing smooth gameplay, even on less powerful devices; developing modular and extensible code to facilitate the addition of new features and improvements; in the requirements analysis section, the requirements for the software were set. The software modeling section described the software architecture. The quality analysis section described the main test cases and the system states after testing. The implementation and maintenance section describes the processes of software deployment. |
| URI: | https://er.chdtu.edu.ua/handle/ChSTU/8846 |
| Appears in Collections: | 121 Інженерія програмного забезпечення (Інженерія програмного забезпечення) |
Files in This Item:
| File | Description | Size | Format | |
|---|---|---|---|---|
| кваліфікаційна робота бакалавра Татаровський Артем Валерійович.pdf Restricted Access | 3.15 MB | Adobe PDF | View/Open Request a copy |
Items in DSpace are protected by copyright, with all rights reserved, unless otherwise indicated.
Extracted text
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
ЧЕРКАСЬКИЙ ДЕРЖАВНИЙ ТЕХНОЛОГІЧНИЙ УНІВЕРСИТЕТ
Факультет інформаційних технологій і систем
Кафедра програмного забезпечення автоматизованих систем
ПОЯСНЮВАЛЬНА ЗАПИСКА
до кваліфікаційної роботи
«бакалавра»
освітній рівень
на тему: «Програмне забезпечення гри в жанрі Real-Time Strategy»
Виконав: студент 4 курсу, групи ПЗ-2104
Спеціальності
121 «Інженерія програмного забезпечення»
(шифр і назва напряму підготовки)
Студент Татаровський А.В.
(прізвище та ініціали)
Керівник Немов Р.Г.
(прізвище та ініціали)
Рецензент Захарова М.В.
(прізвище та ініціали)
Черкаси 2025
Черкаський державний технологічний університет
повне найменування вищого навчального закладу
Факультет інформаційних технологій і систем
Кафедра програмного забезпечення автоматизованих систем
Освітній рівень бакалавр
Спеціальність 121 «Інженерія програмного забезпечення»
Освітня програма Інженерія програмного забезпечення
ЗАТВЕРДЖУЮ
Зав. кафедри ПЗАС, професор
___________ Голуб С.В.
«___» _______________ 2025 року
З А В Д А Н Н Я
НА КВАЛІФІКАЦІЙНУ РОБОТУ СТУДЕНТУ
Татаровський Артем Валерійович
(прізвище, ім’я, по батькові)
1.Тему проекту (роботи) «Програмне забезпечення гри в жанрі Real-Time Strategy»
Керівник проекту (роботи) Немов Р.Г, асистент
(прізвище, ім’я , по батькові, науковий ступінь, вчене звання)
Затверджені наказом Черкаського державного технологічного університету від «25» лютого
2025 року № 53/03-03
2. Строк подання студентом проекту (роботи) 20 червня 2025 р.
3. Вхідні дані до проекту (роботи) Технічне завдання на розробку, методичні рекомендації до
виконання бакалаврської роботи, автоматизовані системи, терміни та визначення.
4. Зміст розрахунково-пояснювальної записки (перелік питань, які потрібно розробити)
Вступ;
Розділ 1. Існуючі методи та засоби розв’язання поставлених завдань;
Розділ 2. Впровадження результатів досліджень у практику проектування програмного
забезпечення інформаційних систем;
Розділ 3. Розробка та тестування програмного забезпечення;
Висновки;
Список використаних джерел;
Додатки.
5. Перелік графічного матеріалу (з точним зазначенням обов’язкових робіт проекту;
Слайд 1; Слайд 2; Слайд 3; Слайд 4; Слайд 5; Слайд 6; Слайд 7; Слайд 8; Слайд 9; Слайд 10;
Слайд 11; Слайд 12; Слайд 13; Слайд 14; Слайд 15; Слайд 16; Слайд 16.
6. Консультанти розділів проекту (роботи)
Прізвище, ініціали та посади Підпис, дата
Розділ
консультанта Завдання видав Завдання прийняв
1
2
3
7. Дата видачі завдання 02 грудня 2024 р.
КАЛЕНДАРНИЙ ПЛАН
Строк
виконання
№
Назва етапів випускної роботи етапів Примітки
п/п
випускної
роботи
1 Постановка задачі 05.12.2024 виконано
2 Підготовка завдання 13.12.2024 виконано
3 Погодження завдання 16.12.2024 виконано
4 Затвердження завдання 25.02.2025 виконано
Основна стадія
1 Підбір матеріалів 27.02.2025 виконано
2 Аналіз шляхів вирішення поставленої задачі 04.03.2025 виконано
3 Розрахунок основних параметрів роботи 10.03.2025 виконано
4 Вибір кінцевого варіанту проектного рішення 17.03.2025 виконано
5 Оформлення первісної редакції роботи 25.03.2025 виконано
Заключна стадія
1 Узгодження прийнятих проектних рішень з 31.04.2025 виконано
керівником
2 Оформлення пояснювальної записки роботи в 13.05.2025 виконано
кінцевій редакції
3 Попередній захист роботи 15.05.2025 виконано
4 Затвердження роботи 31.05.2025 виконано
5 Рецензування роботи 31.05.2025 виконано
6 Захист роботи 20.06.2025
Студент _____________________ Татаровський А.В.
(підпис) (прізвище та ініціали)
Керівник проекту (роботи) _____________________ Немов Р.Г.
(підпис) (прізвище та ініціали)
АНОТАЦІЇ
Виконавець: Татаровський Артем Валерійович.
Назва роботи: "Програмне забезпечення гри в жанрі Real-Time Strategy".
Спеціальність: 121 Інженерія програмного забезпечення.
Навчальний заклад: «Черкаський державний технологічний університет» м.
Черкаси, 2025р.
Мета: Розробити програмне забезпечення гри в реальному часі (RTS) яка
занурить гравців у світ, де вони зможуть продемонструвати свої тактичні
навички, керуючи арміями та розбудовуючи імперії.
Цілі:
реалізація ігрових механік гри;
забезпечення оптимальної продуктивності гри, зменшуючи затримки та
забезпечуючи плавний геймплей, навіть на менш потужних пристроях;
розробка модульного та розширюваного коду для полегшення додавання
нових функцій та вдосконалень.
У розділі аналізу вимог були поставлені вимоги для програмного
забезпечення.
У розділі моделювання програмного забезпечення було описано
архітектуру програмного забезпечення.
У розділі аналіз якості були описані основні тест кейси, та стани системи
після проведення тестування.
У розділі впровадження та супроводу було описано процеси розгортання
програмного забезпечення.
Ключові слова: RTS-ГРА, ГЕЙМПЛЕЙ, ІНТЕРФЕЙС, МОДУЛЬНІСТЬ,
ІГРОВЕ ПРОГРАМНЕ ЗАБЕЗПЕЧЕННЯ, РОЗРОБКА ІГОР, КЕРУВАННЯ
ЮНІТАМИ, ЗБІР РЕСУРСІВ, БУДІВНИЦТВО, ТРЕНУВАННЯ ЮНІТІВ,
БІЙ/АТАКА, ПРОГРАМНА ІНЖЕНЕРІЯ.
ANNOTATIONS
Performer:Tatarovskyi Artem Valeriiovych.
The title of the work: "Real-Time Strategy game software ".
Specialty: 121 Software engineering.
Educational institution: Cherkasy State Technological University, Cherkasy,
2025.
Goal: o develop a real-time strategy (RTS) game that immerses players in a world
where they can demonstrate their tactical skills by commanding armies and building
empires.
Objectives:
implementation of game mechanics;
ensuring optimal game performance by reducing latency and providing smooth
gameplay, even on less powerful devices;
developing modular and extensible code to facilitate the addition of new
features and improvements;
in the requirements analysis section, the requirements for the software were set.
The software modeling section described the software architecture.
The quality analysis section described the main test cases and the system states
after testing.
The implementation and maintenance section describes the processes of software
deployment.
KEYWORDS: RTS GAME, GAMEPLAY, INTERFACE, MODULARITY,
GAME SOFTWARE, GAME DEVELOPMENT, UNIT MANAGEMENT,
RESOURCE GATHERING, BUILDING, UNIT TRAINING, COMBAT/ATTACK,
SOFTWARE ENGINEERING.
ЗМІСТ
ВСТУП ................................................................................................................ 5
РОЗДІЛ 1 ІСНУЮЧІ МЕТОДИ ТА ЗАСОБИ РОЗВ’ЯЗАННЯ
ПОСТАВЛЕНИХ ЗАВДАНЬ ....................................................................................... 8
1.1 Огляд платформ та фреймворків для розробки .... Error! Bookmark not
defined.
1.2 Методи аналізу програмного забезпечення .......... Error! Bookmark not
defined.
1.3 Порівняльний аналіз існуючих аналогів . Error! Bookmark not defined.
1.4 Постановка задачі ................................................................................... 16
ВИСНОВКИ ДО ПЕРШОГО РОЗДІЛУ ...................................................... 17
РОЗДІЛ 2 ВПРОВАДЖЕННЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ У
ПРАКТИКУ ПРОЕКТУВАННЯ ............................................................................... 18
2.1 Моделювання предметної області ......................................................... 18
2.1.1 Предметна область моделювання. Модель предметної області.
Словник предметної області .............................................................................. 19
2.1.2 Елементи моделювання предметної області .................................. 19
2.1.3 Робоча область моделювання.......................................................... 20
2.2 Формування та аналіз вимог .................... Error! Bookmark not defined.
2.2.1 Формування вимог до програмного забезпечення. Первинні і
детальні вимоги. Вимоги замовника і розробника. Функціональні та
нефункціональні вимоги ...................................... Error! Bookmark not defined.
2.2.2 Формування вимог за допомогою діаграми прецедентів .............. 29
2.3 Проектування логічної структури програмного комплексу ................. 29
2.3.1 Діаграми класів ................................................................................ 31
2.4 Архітектура проектування ..................................................................... 38
2.4.1 Діаграма компонентів ...................................................................... 39
2.4.2 Розгортання програмної системи на апаратних засобах. Діаграма
розгортання ......................................................................................................... 41
ЧДТУ. 252169-019 ПЗ
Змн. Арк. № докум. Підпис Дата
Розроб. Татаровський А.В «Програмне забезпечення гри в жанрі Літ. Лист Листів
Перевір. Немов Р.Г Real-Time Strategy» 3
Пояснювальна записка.
Н. Контр. Півень О.Б. ФІТІС, кафедра ПЗАС, ПЗ-2104
Затверд. Голуб С.В.
2.5 Моделювання поведінки системи ........ Error! Bookmark not defined.43
2.5.1 Діаграма діяльності............................ Error! Bookmark not defined.
2.5.2 Діаграма послідовності.................................................................... 45
2.5.3 Діаграма комунікації ....................................................................... 48
2.5.4 Діаграма скінченного автомату....................................................... 48
ВИСНОВКИ ДО ДРУГОГО РОЗДІЛУ ......... Error! Bookmark not defined.
РОЗДІЛ 3 РОЗРОБКА ТА ТЕСТУВАННЯ ПРОГРАМНОГО
ЗАБЕЗПЕЧЕННЯ ....................................................................................................... 51
3.1 Розробка програмного комплексу ......................................................... 51
3.1.1 Обґрунтування вибору засобів реалізації ....................................... 52
3.1.2 Опис структурної (функціональної) схеми .................................... 53
3.1.3 Опис логічної схеми ........................................................................ 55
3.1.4 Розробка бази даних .......................... Error! Bookmark not defined.
3.1.5 Розробка інтерфейсу користувача .................................................. 57
3.1.6 Опис розробки програмних компонентів ....................................... 58
3.2 Тестування системи ................................................................................ 59
3.2.1 Модульне тестування ...................................................................... 61
3.2.2 Інтеграційне тестування .................................................................. 62
3.2.3 Системне тестування ....................................................................... 63
3.2.4 Приймальне тестування ..................... Error! Bookmark not defined.
3.3 Приклади впровадженого програмного комплексу .... Error! Bookmark
not defined.
ВИСНОВКИ ДО ТРЕТЬОГО РОЗДІЛУ...................................................... 67
ВИСНОВКИ ..................................................................................................... 68
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ ......................................................... 70
Додаток А ......................................................................................................... 72
Додаток Б .......................................................................................................... 74
Додаток В ........................................................................................................ 106
Додаток Г ........................................................................................................ 111
ЧДТУ. 252169-019 ПЗ
Змн. Арк. № докум. Підпис Дата
ЧДТУ. 252169-019 ПЗ
ВСТУП
Актуальність теми –необхідність створення програмного забезпечення
гри Real-Time Strategy (RTS), який вимагає від гравців високого рівня
стратегічного мислення, тактичного планування та швидкого прийняття рішень.
Розробка якісного та функціонального програмного забезпечення для RTS-ігор є
актуальним завданням, оскільки ринок вимагає постійного впровадження
інноваційних рішень, оптимізації продуктивності та покращення взаємодії
користувача з ігровим світом. Зокрема, важливим є створення модульних та
масштабованих ігрових систем, здатних адаптуватися до різних системних
конфігурацій та забезпечувати безперервний ігровий процес у реальному часі.
Незважаючи на значну кількість вже існуючих ігор у цьому жанрі, залишається
потреба у розробці рішень, які ефективно поєднують складні ігрові механіки з
інтуїтивно зрозумілим інтерфейсом та високою стабільністю.
Мета роботи – створення повнофункціонального програмного
забезпечення гри в жанрі Real-Time Strategy (RTS). Для досягнення поставленої
мети необхідно виконати наступні завдання:
1 Розробити архітектуру програмного комплексу, що відповідає
принципам модульності та гнучкості.
2 Реалізувати ключові ігрові механіки, включаючи управління юнітами,
бойову систему, економіку гри та взаємодію з об'єктами.
3 Забезпечити оптимальну продуктивність ігрового рушія, зокрема
шляхом оптимізації алгоритмів навігації (наприклад, алгоритму A*).
4 Розробити інтуїтивно зрозумілий графічний інтерфейс користувача для
зручної взаємодії з грою.
5 Забезпечити збереження та завантаження ігрового прогресу.
6 Провести комплексне тестування програмного забезпечення для
забезпечення його надійності та стабільності.
Об'єкт розробки є програмне забезпечення та технології побудови жанрі
Real-Time Strategy.
5
ЧДТУ. 252169-019 ПЗ
Предметом розробки є програмне забезпечення, що реалізує ігрові
механіки (управління юнітами, будівництво, збір ресурсів, бойові дії, система
перемоги/поразки), графічний інтерфейс користувача та внутрішню логіку
взаємодії компонентів ігрової системи для RTS-гри.
Методи розробки – для досягнення поставленої мети використано
наступні методи:
1 Системний аналіз вимог та проєктування, що включає побудову діаграм
класів, компонентів та сценаріїв використання.
2 Об'єктно-орієнтоване програмування для створення структурованого та
легко підтримуваного коду.
3 Алгоритмізація, зокрема, застосування евристичних алгоритмів
(наприклад, A*) для оптимізації пошуку шляху.
4 Модульне проєктування та розробка для забезпечення розширюваності
функціоналу.
5 Комплексне тестування програмного забезпечення, що включає
модульне, інтеграційне, системне та приймальне тестування.
Опис отриманих результатів – у результаті виконання роботи було
розроблено за допомогою програмного забезпечення повнофункціональний
програмний комплекс RTS-гри з наступними можливостями:
1 Управління базою, включаючи будівництво та вдосконалення споруд.
2 Керування армією, тренування юнітів та їх переміщення по карті.
3 Реалізація бойової системи з розрахунком шкоди та взаємодією між
юнітами.
4 Обробка перемоги/поразки та збереження ігрового прогресу.
5 Інтуїтивно зрозумілий графічний інтерфейс користувача, що відображає
ігровий світ, міні-карту, інформаційні панелі та меню.
6 Надійне та стабільне функціонування системи, підтверджене
комплексним тестуванням.
Практичне значення отриманих результатів – розроблений програмний
комплекс є функціональною моделлю RTS-гри, яка може бути використана як
6
ЧДТУ. 252169-019 ПЗ
основа для подальшого розвитку повноцінної ігрової платформи. Практична
цінність полягає у демонстрації реалізації ключових ігрових механік, принципів
побудови масштабованої архітектури та застосування сучасних підходів до
розробки та тестування програмного забезпечення у сфері ігрової індустрії.
Особистий внесок автора – було проведено аналіз вимог до програмного
забезпечення, розроблено програмне забезпечення, архітектуру та функціональні
модулі ігрового комплексу. Були реалізовані основні ігрові механіки, такі як
управління юнітами, бойова система, економіка та навігація за допомогою
алгоритму A*. Запрограмовано графічний інтерфейс користувача та реалізація
взаємодії з ним. Також було здійснено комплексне тестування розробленого
програмного забезпечення на всіх етапах розробки, від модульних тестів до
системного та приймального тестування, та підготовлено відповідну
документацію.
7
ЧДТУ. 252169-019 ПЗ
РОЗДІЛ 1 ІСНУЮЧІ МЕТОДИ ТА ЗАСОБИ РОЗВ’ЯЗАННЯ
ПОСТАВЛЕНИХ ЗАВДАНЬ
Стратегія в реальному часі (англ. real-time strategy, RTS) є піджанром
стратегічних відеоігор, у яких гравець і противник (комп'ютер чи інший гравець)
виконують дії одночасно, а не по черзі, як у покрокових стратегіях.
Стратегії в реальному часі зазвичай відтворюють військові дії та розбудову
військових баз для здобуття перемоги над противником, мають специфічний
інтерфейс. Їм притаманні численні ігрові умовності, такі як врівноваження
можливостей протиборчих сторін, нереалістично короткі терміни проведення боїв
і будівництва.
Хоча деякі інші жанри ігровим процесом подібні до RTS та вимагають
стратегічного мислення від гравця, наприклад, симулятори містобудування, вони
не вважаються стратегіями в реальному часі.
У типовій стратегії в реальному часі екран поділяється на зону, де
відображаються ігровий світ, підрозділи та будівлі, і інтерфейс управління, що
містить кнопки команд, показники стану підконтрольних об'єктів, часто «радар»
або «міні-карту» для огляду всієї території.
Гравець зазвичай бачить ігровий світ згори, в тривимірних RTS часто є
можливість переміщувати камеру огляду. Видимість поля бою симулюється
«туманом війни», який приховує ворожі війська та споруди поза полем зору
військ, але не обов'язково ландшафт, та виглядає як темрява чи затінення. Гравці
можуть віддавати команди за допомогою миші, а також комбінацій клавіш.
Підконтрольні гравцям об'єкти називаються юнітами, хоча часто під цим
словом розуміються лише будівельники і бійці, але не споруди. Гравець зазвичай
починає гру в заздалегідь визначеному місці з кількома юнітами й невеликим
запасом ресурсів, які передбачають будівництво споруд та замовлення робітників
і бійців. Будівництво, як правило, здійснюється за ресурси, конкретні чи
абстрактні, яких може бути декілька видів. Це здійснюється за короткий час, так
зведення будівель займає від кількох секунд до кількох хвилин. Використовуючи
війська і оборонні споруди, гравець здійснює бойові дії з метою знищення
8
ЧДТУ. 252169-019 ПЗ
противника, чи виконання певної цілі, наприклад захоплення/знищення певного
об'єкта.
RTS можуть мати ліміт на створення військ, певну кількість «очок
населення», які можуть збільшуватися будівництвом спеціальних споруд. Чимало
стратегій в реальному часі мають «героїв» – сюжетних чи особливо сильних
бойових одиниць, котрі з часом розвивають свої можливості.
Напрямками розробки будуть основні особливості більшості «класичних»
стратегій в реальному часі, такі елементи як:
1 Збір ресурсів за допомогою робітників, техніки або будівель. У деяких
іграх ресурси не збираються, а генеруються автоматично спеціальними точками,
які потрібно попередньо захопити.
2 Будівництво бази (табору), в якому існують різні типи будівель, які
забезпечують отримання ресурсів, армії, та впровадження вдосконалень.
Характерною особливістю стратегій в реальному часі є умовність часу
будівництва. Цей процес займає лічені секунди або хвилини.
3 Створення армії та експансія з метою захоплення нових джерел ресурсів,
знищення противника. Як і з будівництвом, на замовлення або конструювання
бойових одиниць затрачаються секунди чи хвилини. Сам процес отримання військ
також умовний. До прикладу, військовий завод може виробляти десятки танків,
хоча не показується як до нього доставляються деталі.
4 Атака противника з метою перехоплення доступу до ресурсів та/або
знищення його армії і табору.
Крім того, існує чимало стратегічних ігор, ігровий процес яких істотно
відрізняється від класичного. Будучи успішними, такі ігри виділяються в окремі
піджанри. Наприклад, у ряді ігор не передбачено будівництво баз (Z, Myth,
Ground Control, Warhammer: Mark of Chaos, World in Conflict, ігри серії
Протистояння, Warhammer 40,000: Dawn of War II). Такі ігри здебільшого роблять
акцент на тактиці, вони вимагають від гравця дбайливіше ставитися до підлеглих
йому загонів. Інші ігри, навпаки, зосереджують увагу гравця на економічному
9
ЧДТУ. 252169-019 ПЗ
елементі, переводячи бій з противником на другий план. Прикладами таких
економічних стратегій є серія ігор The Settlers і Zeus: Master of Olympus.
Також існують стратегії зі значними домішками інших жанрів, які
поєднують елементи глобальної покрокової стратегії з тактичними битвами в
реальному режимі.
У підготовці цього розділу було використано галузі геймдеву. Роботи
Michael Moore [1], Mark J. P. [2]
1.1 Огляд платформ та фреймворків для розробки
IntelliJ IDEA [4] є однією з найпопулярніших IDE для розробки на мові Java.
Вона надає розширені можливості автоматичного кодування, відлагодження, та
підтримки множини інших мов програмування.
IntelliJ IDEA комерційне інтегроване середовище розробки для різних мов
програмування (Java, Python, Scala, PHP) від компанії JetBrains. Система
поставляється у вигляді урізаної по функціональності безкоштовної версії
«Community Edition» і повнофункціональної комерційної версії «Ultimate Edition»,
для якої активні розробники відкритих проектів мають можливість отримати
безкоштовну ліцензію.
IntelliJ IDEA відрізняється від інших IDE високою продуктивністю,
розширеним набором функцій та підтримкою різних технологій. Порівняно з
іншими IDE, такими як Eclipse, IntelliJ IDEA відома своєю швидкістю та
інтуїтивністю.
У ході розробки програмного забезпечення та алгоритмів наведених вище,
було використано декілька відповідних бібліотек.
Swing [5] – інструментарій для створення графічного інтерфейсу
користувача (GUI) мовою програмування Java. Це частина бібліотеки базових
класів Java (JFC, Java Foundation Classes).
Swing розробляли для забезпечення функціональнішого набору програмних
компонентів для створення графічного інтерфейсу користувача, ніж у ранішого
інструментарію AWT. Компоненти Swing підтримують специфічні look-and-feel
10
ЧДТУ. 252169-019 ПЗ
[en] модулі, що динамічно підключаються. Завдяки їм можлива емуляція
графічного інтерфейсу платформи (тобто до компоненту можна динамічно
підключити інші, специфічні для даної операційної системи вигляд і поведінку).
Основним недоліком таких компонентів є відносно повільна робота, хоча
останнім часом це не вдалося підтвердити через зростання потужності
персональних комп'ютерів. Позитивна сторона – універсальність інтерфейсу
створених програм на всіх платформах.
Особливостями архітектури є:
1 Незалежність від платформи: Swing – платформо-незалежна бібліотека,
що означає, що програму з використанням Swing можна запустити на всіх
платформах, які підтримують JVM.
2 Можливість для розширення: Swing – дуже розподілена архітектура, яка
дозволяє «підключати» реалізації користувача вказаної інфраструктури
інтерфейсів: користувачі можуть створити свою власну реалізацію цих
компонентів, щоб замінити компоненти без обумовлення (за замовчуванням).
Взагалі, користувачі Swing можуть розширити структуру, продовжуючи (з
допомогою extends) існуючі класи або створюючи альтернативні реалізації
основних компонентів.
3 Абстрактний віконний інтерфейс (AWT [6] – Abstract Window Toolkit) – це
оригінальний пакет класів мови програмування Java, що слугує для створення
графічного інтерфейсу користувача (GUI). AWT є частиною Java Foundation
Classes (JFC) – стандартного API для реалізації графічного інтерфейсу для Java-
програми. Пакет містить платформо-незалежні елементи графічного інтерфейсу,
щоправда їхній вигляд залежить від конкретної системи.
1.2 Методи аналізу програмного забезпечення
Розробка гри в жанрі Real-Time Strategy (RTS) вимагає всебічного аналізу
для визначення оптимальних рішень, що забезпечать високу ефективність,
ігровий баланс та залученість гравців. У цьому підрозділі розглядаються методи
11
ЧДТУ. 252169-019 ПЗ
аналізу, які використовуються для оцінки та покращення системи розробки RTS
гри.
SWOT-аналіз дозволяє оцінити сильні та слабкі сторони концепції та
механік RTS гри, а також можливості та загрози, які виникають у зовнішньому
середовищі (ринок, конкуренти, технології). Це допомагає визначити основні
конкурентні переваги проекту, а також потенційні виклики, які можуть виникнути
під час розробки та впровадження гри.
Аналіз даних включає обробку великого обсягу інформації, такої як вимоги
гравців, технічні характеристики ігрового рушія, продуктивність системи, а також
метрики ігрового процесу (наприклад, баланс юнітів, тривалість матчів,
популярність фракцій). Це дозволяє виявити тенденції, відхилення та критичні
точки, що потребують уваги під час розробки RTS гри.
Моделювання ігрових процесів передбачає використання математичних та
комп'ютерних моделей для прогнозування поведінки гри. Це включає
моделювання економічних систем, бойових зіткнень, поведінки штучного
інтелекту супротивників та оптимізацію ігрового балансу. Таке моделювання
допомагає оцінити продуктивність гри ще до її повної реалізації.
Аналіз ризиків спрямований на виявлення потенційних загроз для RTS гри
та розробку стратегій управління цими ризиками. Це включає оцінку можливих
проблем з безпекою (читерство), стабільністю мережевого коду, продуктивністю
на різних конфігураціях обладнання, а також потенційні проблеми з балансом
ігрових механік.
Аналіз потреб гравців спрямований на вивчення вимог та очікувань цільової
аудиторії гри. Це допомагає визначити найважливіші функції, бажані ігрові
механіки, вподобання щодо візуального стилю та забезпечити, що розроблена
RTS гра максимально відповідає потребам та очікуванням гравців.
Застосування вищезгаданих методів аналізу дозволяє створити ефективну,
збалансовану та привабливу RTS гру. Кожен метод забезпечує цілісне бачення
проекту з різних аспектів, що сприяє прийняттю обґрунтованих рішень та
підвищенню якості кінцевого продукту.
12
ЧДТУ. 252169-019 ПЗ
1.3 Порівняльний аналіз існуючих аналогів
Age of Empires [7](Microsoft) (рисунок 1.1) є класичною серією RTS-ігор,
яка пропонує стратегічний геймплей у різних історичних періодах. Завдяки своїй
великій популярності та визнанню серед гравців, вона служить важливим
аналогом для дослідження.
Рисунок 1.1 – Логотип серії Age of Empires
StarCraft II [8] (Blizzard Entertainment) (рисунок 1.2) є ще однією відомою
RTS-грою, яка вирізняється науково-фантастичною тематикою та складними
стратегічними аспектами. Цей аналог надає можливість аналізу глибини
геймплею в сучасних RTS.
Рисунок 1.2 – Головна обкладинка StarCraft II
Command & Conquer: Red Alert 2 (Electronic Arts) [9] (рисунок 1.3) – гра
представляє собою класичний RTS з емоційним сюжетом та розвинутою
системою управління. Її дослідження може сприяти зрозумінню та впровадженню
цікавих елементів у власну гру.
13
ЧДТУ. 252169-019 ПЗ
Рисунок 1.3 – Логотип серії ігор у «Command & Conquer 4»
Warcraft III: Reforged (Blizzard Entertainment) [10] (рисунок 1.4) поєднує
стратегічний геймплей з елементами RPG. Дослідження цієї гри може надати
інсайтів в створення унікального гібридного досвіду для гравців.
Рисунок 1.4 – Логотип гри Warcraft III
Total War: Three Kingdoms (Creative Assembly) [11] (рисунок 1.5) – це серія
гібридних стратегічних і тактичних ігор, які поєднують глобальні RTS-елементи з
батальними сценами. Дослідження такого підходу може призвести до
інноваційних елементів гри у жанрі RTS.
Рисунок 1.5 – Головна обкладинка Total War: Three Kingdoms
14
ЧДТУ. 252169-019 ПЗ
Всі вказані аналоги представляють різні підходи до стратегічного геймплею
та мають свої унікальні особливості
Кожен з аналогів має свою велику популярність та широку гравецьку фан-
базу.
Ігри охоплюють різні тематики, від історичних періодів до науково-
фантастичних світів та військових сценаріїв.
Стратегічні Аспекти: Від середньо-важких стратегічних аспектів до
складних стратегічних аспектів з багатофракційністю та глибоким геймплеєм.
Кожен аналог пропонує власні інноваційні елементи, такі як глибина
геймплею, поєднання RTS з іншими жанрами, або унікальний гібрид глобальної
стратегії та батальних елементів.
Аналіз готових програмних продуктів у жанрі RTS дозволяє отримати
інсайти та ідеї для розробки власної гри. Врахування популярності, тематики,
стратегічних аспектів та інновацій допомагає визначити ключові аспекти, які
можна вдосконалити та впровадити у власний проект.
Для порівняння програмного забезпечення з аналогами можна скористатись
таблицею 1.1.
Таблиця 1.1
Порівняння з аналогами
Star C&C: Warcraft Total War: Simple_Str
Age of
Властивість Craft Red III: Three ategy
Empires
II Alert 2 Reforged Kingdoms (Власний)
Основний жанр + + + + + +
Сучасна графіка + + + + + +
Простий гемплей - + + - + +
Мапи для модінгу + + - + + -
15
ЧДТУ. 252169-019 ПЗ
Продовження таблиці 1.1
Зрозумілий
- + + - - +
інтерфейс
Баланс гри + + + + + +
Низький
поріг
- - - + - +
системних
вимоги
Низька
- - - - - +
вартість
Підтримка
+ - - + + +
оновлення
КІЛЬКІСТЬ 5 6 5 6 6 8
Отже власний проект у жанрі RTS виявляється актуальним і вартим
розробки з кількох ключових причин, які визначають його плюси та мінуси,
порівняно з аналогами.
1.4 Постановка задачі
Розробка може бути застосована в різних сферах та мати різноманітні
варіанти використання, як-от: розважальна галузь, тренування (це може бути
корисно для розвитку когнітивних навичок у гравців). Розробка гри може
включати в себе експерименти з технічними ідеями, в наукових дослідженнях для
вивчення поведінки гравців.
Цільова аудиторія для гри у жанрі RTS включає гравців-любителів,
розробників програмного забезпечення та будь якого користувача, які хочуть
використати проект.
Також програмне забезпечення має виконувати всі поставлені
функціональні та нефункціональні вимоги.
16
ЧДТУ. 252169-019 ПЗ
ВИСНОВКИ ДО ПЕРШОГО РОЗДІЛУ
У даному відділі визначено формулювання задачі, розглянуто наявні
аналоги ігор в жанрі RTS. Представлені альтернативи вважаються достатньо
якісними, але вони мають свої недоліки.
У якості мови програмування було обрано Java, оскільки вона є мовою
високого рівня, яка має кілька переваг для розробки гри у жанрі RTS:
переносимість, багатопотоковість, безпека, екосистема та бібліотеки. Розглянуто
використання таких інструментів розробки, як IntelliJ IDEA, а також бібліотек
Swing та AWT для реалізації графічного інтерфейсу. Загальний висновок
підкреслює важливість застосування ефективних методів та засобів для
розв'язання поставлених завдань, забезпечуючи створення якісної та
конкурентоспроможної RTS-гри.
17
ЧДТУ. 252169-019 ПЗ
РОЗДІЛ 2 ВПРОВАДЖЕННЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ У ПРАКТИКУ
ПРОЕКТУВАННЯ
Програмне забезпечення виступає важливою складовою для вирішення
складних завдань та досягнення стратегічних цілей в різних галузях. Процес
розробки програмного забезпечення є складним та многозадачним, вимагаючи
глибокого розуміння вимог користувачів, ефективних методів моделювання та
конструювання.
Моделювання та конструювання програмного забезпечення становлять
ключові етапи у життєвому циклі розробки програм, де визначаються концепції,
архітектура та алгоритми, які лягають в основу майбутнього продукту. Ефективне
моделювання дозволяє визначити оптимальні рішення та забезпечити гнучкість
системи, а конструювання є процесом втілення цих концепцій у функціональний
та надійний програмний продукт.
У даній роботі детально розглядається процес моделювання та
конструювання програмного забезпечення. Аналізуються основні підходи до
створення моделей, методи та інструменти, які використовуються у цьому
процесі. Покладаючи акцент на важливість етапів моделювання та
конструювання, робота пропонує висвітлити основні концепції та вирішення, що
визначають успішну розробку програмного забезпечення.
2.1 Моделювання предметної області
Моделювання предметної області є важливим початковим етапом при
проектуванні програмного забезпечення для RTS-гри. Будуть визначені основні
сутності, їх атрибути та взаємозв'язки в досліджуваній предметній області.
Предметна область моделювання полягає в розробці RTS-гри, здатної
управляти ігровими об'єктами (юнітами, будівлями, ресурсами), реалізовувати
штучний інтелект, забезпечувати навігацію юнітів, підтримувати бойову систему
та надавати користувачеві зручний інтерфейс для взаємодії з грою.
Для побудови концептуальної моделі предметної області ми виділимо
ключові сутності, такі як гравець, юніт, будівля, ресурс, карта, ігрова сесія,
18
ЧДТУ. 252169-019 ПЗ
штучний інтелект, користувацький інтерфейс. Далі визначимо їх атрибути та
зв'язки між ними. Буде сформовано словник предметної області з поясненням
основних термінів і понять, що використовуються в цій сфері.
Результатом моделювання буде робоча область моделювання, що міститиме
опис сутностей, атрибутів, зв'язків та приклади екземплярів для кращого
розуміння предметної області.
Побудована модель предметної області забезпечить системне уявлення про
концептуальні об'єкти та взаємозв'язки в сфері розробки RTS-гри і буде
використана на подальших етапах проектування програмного забезпечення
2.1.1 Предметна область моделювання. Модель предметної області. Словник
предметної області
Предметна область моделюванн. Програмне забезпечення для гри в жанрі
Real-Time Strategy, що забезпечує управління ігровими об'єктами, штучний
інтелект, бойову систему та користувацький інтерфейс.
Модель предметної області
Сутності:
1 Гравець (Player).
2 Юніт (Unit).
3 Будівля (Building).
4 Ресурс (Resource).
5 Карта (Map).
6 Ігрова Сесія (GameSession).
7 Штучний Інтелект (AI).
8 Користувацький Інтерфейс (UI).
Атрибути сутностей:
1 Гравець: ідентифікатор, ім'я, фракція, кількість ресурсів, список юнітів,
список будівель.
2 Юніт: ідентифікатор, тип (робітник, бойовий), поточне здоров'я,
координати, швидкість, ціль, стан (рух, атака, збір).
3 Будівля: ідентифікатор, тип (штаб, казарма, шахта), координати, поточне
19
ЧДТУ. 252169-019 ПЗ
здоров'я, стан (будується, працює, зруйнована).
4 Ресурс: ідентифікатор, тип (золото, дерево, камінь), координати, кількість.
5 Карта: розмір, тайли (тип місцевості), перешкоди, початкові позиції
гравців.
6 Ігрова Сесія: ідентифікатор, список гравців, поточний час гри, стан гри
(триває, завершена).
7 Штучний Інтелект: рівень складності, стратегія, список керованих юнітів.
8 Користувацький Інтерфейс: елементи управління (кнопки, панелі),
відображення інформації (ресурси, здоров'я юнітів).
Зв'язки:
1 Гравець - володіє - Юніт (один до багатьох).
2 Гравець - володіє - Будівля (один до багатьох).
3 Юніт - взаємодіє з - Ресурс (багато до багатьох).
4 Юніт - знаходиться на - Карта (багато до одного).
5 Будівля - знаходиться на - Карта (багато до одного).
6 Ігрова Сесія - включає - Гравець (один до багатьох).
7 Штучний Інтелект - управляє - Юніт (один до багатьох).
8 Користувацький Інтерфейс - відображає - Ігрова Сесія (один до одного).
Словник предметної області
1 Гравець: Учасник ігрової сесії, що керує своєю фракцією.
2 Юніт: Окрема одиниця на ігровій карті, що виконує певні дії (збір,
будівництво, бій).
3 Будівля: Стаціонарний об'єкт на карті, що виконує функції виробництва,
збору або захисту.
4 Ресурс: Елемент, необхідний для будівництва та виробництва юнітів.
5 Карта: Ігрове поле, на якому розгортаються події.
6 Ігрова Сесія: Поточний стан гри між одним або декількома гравцями.
7 Штучний Інтелект (ШІ): Програмний компонент, що керує діями
некерованих гравцем сутностей.
8 Користувацький Інтерфейс (UI): Візуальні елементи, через які гравець
20
ЧДТУ. 252169-019 ПЗ
взаємодіє з грою.
2.1.2 Елементи моделювання предметної області
У моделюванні предметної області використовуються наступні основні
елементи:
1 Сутність: Це окремий об'єкт або концепція з унікальним набором
атрибутів у предметній області. Наприклад, "Гравець", "Юніт", "Будівля".
2 Атрибут: Це властивість або характеристика сутності. Наприклад, для
сутності "Юніт" атрибутами можуть бути "тип", "здоров'я", "координати".
3 Зв'язок: Це семантична асоціація між двома або більше сутностями.
Наприклад, зв'язок "володіє" між сутностями "Гравець" і "Юніт".
4 Множинність: Це числова характеристика зв'язку, яка визначає кількість
екземплярів однієї сутності, пов'язаних з екземпляром іншої сутності. Вона
показує обмеження на кількість об'єктів, які можуть брати участь у відносинах.
5 Атрибут зв'язку: Це атрибут, який належить зв'язку між двома або більше
сутностями та характеризує цей зв'язок.
Ці елементи використовуються для побудови концептуальної моделі
предметної області, що забезпечує загальне розуміння та опис системи без
занурення в деталі реалізації.
Таблиця 2.1
Графічні елементи UML діаграм
Графічний символ Назва елемента
Дійова особа(актор)
Варіант використання
Коментар
Пакет
21
ЧДТУ. 252169-019 ПЗ
Продовження таблиці 2.1
Клас
Об`єкт
Компонент
Вузол
Діяльність
Стан
Початковий стан
Кінцевий стан
Таблиця 2.2
Єднальні елементи UML діаграм
Графічний символ Назва елемента
Відношення асоціації
Відношення залежності
Відношення успадкування
Агрегація
Композиція
Приймач події
Джерело події
Заміна
22
ЧДТУ. 252169-019 ПЗ
Продовження таблиці 2.2
Межа
Простий потік управління
Послати
Виклик
Рекурсія
Повернути
UML діаграми - це стандартизовані графічні нотації для візуального
представлення різних аспектів системи програмного забезпечення, таких як
структура, поведінка та архітектура. Вони використовуються для документування,
проектування та комунікації в процесі розробки програмного забезпечення.
2.1.3 Робоча область моделювання
Гра реалізована з використанням графічних інтерфейсних бібліотек
awt/swing для створення ігрового середовища. Нижче наведено опис
послідовності дій користувача в грі у жанрі RTS за допомогою діаграми BPMN.
Створення армії в грі є однією з основних функцій гемплею, тому на
рисунку 2.1 загально опишемо вирішення завдання за допомогою BPMN.
Опис послідовності створення армії в грі:
користувач запускає гру та обирає режим "Створення нової гри";
гравець обирає свою фракцію та визначає основні початкові дані;
гравець розпочинає будівництво базових будівель, таких як казарми,
заводи, та ресурсні точки;
після будівництва казарм гравець може наймати різні типи військових
одиниць для своєї армії;
гравець формує армію, вибираючи військові одиниці та розподіляючи їх
до різних боєприпасів;
23
ЧДТУ. 252169-019 ПЗ
після створення армії гравець може керувати нею в реальному часі,
видаючи команди, вказуючи точки переміщення та визначаючи цілі атаки;
гра триває до досягнення одного з кінцевих умов: перемоги в великому
бою, завоювання важливих точок на карті або досягнення конкретних цілей
завдань.
Цей опис відображає послідовність подій, які гравець може виконати під
час гри у жанрі RTS, починаючи з вибору фракції та будівництва базових
структур до керування армією та завершення гри за певних умов.
Рисунок 2.1 – BPMN модель
2.2 Формування та аналіз вимог
Формування вимог до програмного забезпечення є одним із найважливіших
етапів процесу розробки, який визначає майбутню структуру, функціональність і
якість системи. Вимоги встановлюють чітке бачення того, що саме має бути
реалізовано, якими засобами та в яких умовах має функціонувати система.
24
ЧДТУ. 252169-019 ПЗ
2.2.1 Формування вимог до програмного забезпечення. Первинні і детальні
вимоги. Вимоги замовника і розробника. Функціональні та нефункціональні
вимоги
Формування вимог до програмного забезпечення
Розробка програмного забезпечення для гри жанру Real-Time Strategy (RTS)
вимагає чіткого визначення функціональних та нефункціональних вимог, які
визначають архітектуру, інтерфейс, ігрову логіку та технічні характеристики
системи
Первинні вимоги
1 Забезпечити базові механіки RTS-гри: збір ресурсів, будівництво,
виробництво юнітів, бої.
2 Реалізувати керування юнітами та будівлями гравцем.
3 Надати простий та інтуїтивний графічний інтерфейс користувача.
4 Забезпечити збереження та завантаження ігрового прогресу.
Детальні вимоги
1 Реалізація системи ресурсів (золото, дерево, камінь).
2 Можливість будівництва різних типів споруд (штаб, казарма, шахта).
3 Виробництво різних типів юнітів (робітники, воїни).
4 Штучний інтелект для базового супротивника (збір ресурсів, будівництво,
атака).
5 Навігація юнітів по карті з обходом перешкод.
6 Бойова система з розрахунком шкоди.
7 Відображення стану гри (карта, юніти, ресурси) у реальному часі.
8 Керування камерою (масштабування, переміщення).
9 Обмеження на кількість юнітів/будівель.
10 Забезпечити стійку та безперебійну роботу системи під час ігрової сесії.
11 Реалізувати логування ігрових подій для налагодження та аналізу.
12 Забезпечити масштабованість системи для додавання нових типів юнітів,
будівель, механік.
25
ЧДТУ. 252169-019 ПЗ
13 Забезпечити модульність системи для легкого розширення та підтримки.
Вимоги замовника
1 Гра повинна бути розроблена на Java.
2 Має бути можливість збирати ресурси.
3 Має бути можливість будувати базові будівлі.
4 Має бути можливість виробляти юнітів.
5 Юніти повинні пересуватися по карті та атакувати ворогів.
6 Має бути простий графічний інтерфейс.
7 Гра повинна бути стабільною.
Вимоги розробника
1 Використання об'єктно-орієнтованого підходу.
2 Розробка чіткої архітектури модулів.
3 Використання патернів проектування для покращення кодової бази.
4 Оптимізація продуктивності для плавного ігрового процесу.
5 Написання модульних та інтеграційних тестів.
6 Документування коду.
7 Використання системи контролю версій.
Розроблення функціональних вимог
Функціональні вимоги – це конкретні функції, які система чи програмне
забезпечення повинні надавати для вирішення конкретних завдань та вимог
користувачів. Ці вимоги описують очікувану функціональність та здатність
системи виконувати певні операції. Функціональні вимоги зазвичай
формулюються як конкретні задачі чи дії, які користувачі системи повинні мати
можливість виконати.
Таблиця 2.3
Функціональні вимоги
FR-1 Відкриття гри
Опис Система повинна забезпечити можливість користувача відкривати гру
через відповідний інтерфейс чи команду.
26
ЧДТУ. 252169-019 ПЗ
Продовження таблиці 2.3
FR-2 Ініціалізація початкових даних
Опис Система повинна дати можливість ініціалізувати необхідні початкові
дані для старту гри, забезпечуючи коректний початок геймплею.
FR-3 Натискання "Почати гру"
Опис Система повинна реагувати на дію користувача – натискання кнопки
"Почати гру", і запускати нову гру з визначеними параметрами.
FR-4 Вибір гравцем стратегії
Опис Система повинна дозволяти гравцеві обирати стратегію гри,
впливаючи на подальший розвиток геймплею.
FR-5 Натискання "Меню"
Опис Система повинна реагувати на дію користувача – натискання кнопки
"Меню", відкривати меню гри та надавати доступ до різних опцій.
FR-6 Поставити на паузу
Опис Система повинна реагувати на дію користувача – вибір опції
"Поставити на паузу" для тимчасового зупинення гри.
FR-7 Повернутись в основне меню (почати заново)
Опис Система повинна надавати можливість гравцеві повертатися до
основного меню для початку нової гри або вибору інших опцій.
FR-8 Вихід з гри
Опис Система повинна реагувати на дію користувача – вибір опції "Вихід з
гри" та забезпечувати коректне завершення гри та вихід з ігрового
середовища.
Таблиця трасування вимог є інструментом системного аналізу та управління
проектами, який використовується для відстеження взаємозв'язків між різними
елементами проекту. Основна мета цієї таблиці полягає в тому, щоб забезпечити
зв'язок між вихідними вимогами до системи і конкретними елементами, які
27
ЧДТУ. 252169-019 ПЗ
реалізують ці вимоги.
У контексті розробки програмного забезпечення, таблиця трасування вимог
зазвичай включає в себе список вимог або функціональних можливостей, а також
інші елементи, такі як сценарії використання (use-case'и), тестові випробування,
компоненти системи тощо. Кожен елемент таблиці поєднується з конкретними
вимогами, які він впроваджує чи тестує.
Таблиця 2.4
Матриця трасування вимог
UC\ 1 2 3 4 5 6 7 8
FR
1 X
2 X
3 X
4 X
5 X
6 X
7 X
8 X
Важливо відзначити, що таблиця трасування вимог для власного проекта
має спрощену структуру, оскільки кожен use-case повністю покривається однією
функціональною вимогою.
28
ЧДТУ. 252169-019 ПЗ
Розроблення нефункціональних вимог
Нефункціональні можливості вимоги – це характеристики системи чи
програмного забезпечення, які не стосуються конкретної функціональності, але
визначають якісні аспекти їхньої роботи та характеристики. Ці можливості
визначають "якість" системи та включають такі аспекти, як продуктивність,
надійність, безпека та інші.
Таблиця 2.5
Таблиця нефункціональних вимог
Номер Назва Опис
NFR-1 Продуктивність Система повинна забезпечувати швидку
реакцію на дії користувача, з мінімальними
затримками у виконанні операцій.
NFR-2 Надійність Система повинна мати високий рівень
надійності, запобігаючи аварійним ситуаціям та
забезпечуючи стабільну роботу протягом
тривалого періоду.
NFR-3 Сумісність Система повинна бути сумісною з різними
операційними системами та середовищами,
забезпечуючи зручність використання для
різних користувачів.
NFR-4 Безпека Система повинна забезпечувати заходи безпеки
для захисту конфіденційної інформації
користувачів та запобігання несанкціонованому
доступу до системи.
NFR-6 Зручність Користуватський інтерфейс системи повинен
інтерфейсу бути інтуїтивно зрозумілим та зручним для
використання.
29
ЧДТУ. 252169-019 ПЗ
Наведені в таблиці вимоги допомагають враховувати ключові аспекти, які
забезпечують не тільки функціональну повноту, але й задовольняють якість
програмного продукту.
2.2.2 Формування вимог за допомогою діаграми прецедентів
Головною функцією програмного забезпечення є гарантія ефективної та
захоплюючої геймплей-системи для користувачів, більше функцій можна
побачити на рисунку 2.2.
Рисунок 2.2 – Діаграма прецедентів програмного забезпечення гри
30
ЧДТУ. 252169-019 ПЗ
Ця діаграма прецедентів описує функціональні можливості ігрової системи
та взаємодію з нею двох основних типів акторів: Користувача та Опонента (Бота).
Актори (Actors)
1 Користувач: Це основний гравець, людина, яка взаємодіє з грою.
2 Опонент (Бот): Це ігровий штучний інтелект, який виступає проти
користувача.
Прецеденти (Use Cases) та їх взаємозв'язки
Основні прецеденти Користувача:
1 Відкрити гру: Користувач ініціює запуск гри.
2 Ініціювати початкові дані: Після відкриття гри, Користувач може ввести
або налаштувати початкові дані (наприклад, ім'я гравця, початкові налаштування).
3 Натиснути "Почати гру": Користувач запускає основний ігровий процес.
Основний ігровий прецедент:
4 Грати: Це центральний прецедент, що охоплює весь ігровий процес. Він
пов'язаний з Користувачем (через "Натиснути "Почати гру"") та Опонентом
(Ботом).
5 Взаємодії всередині прецеденту "Грати":
6 Брати участь в битвах: Цей прецедент є включеним (include) або
розширеним (extend) від "Грати". Він, ймовірно, охоплює бойові дії в грі.
7 Здобувати ресурси: Цей прецедент є розширенням (extend) від "Грати", що
означає, що Користувач може, але не обов'язково, здобувати ресурси під час гри.
8 Керувати базою: Цей прецедент також є розширенням (extend) від
"Грати", дозволяючи Користувачеві управляти своєю базою.
9 Формувати армію: Цей прецедент є розширенням (extend) від "Грати", що
дозволяє Користувачеві створювати та управляти своїми військами.
10 Взаємодії з Опонентом (Ботом):
11 Навчити юніта: Цей прецедент пов'язаний з Опонентом (Ботом) і
показує, що бот також може "тренувати" або "створювати" своїх юнітів. Це є
31
ЧДТУ. 252169-019 ПЗ
включеним (include) до якогось внутрішнього процесу бота. (Якщо на діаграмі
цей прецедент також пов'язаний з "Грати", це означає, що і Опонент (Бот) виконує
цю дію під час ігрового процесу).
Прецеденти управління грою:
1 Натиснути "Меню (Пауза)": Користувач може призупинити гру.
2 Вийти: Користувач може повністю покинути гру.
Загальна логіка:
Діаграма показує, що Користувач розпочинає гру, налаштовує її, а потім
вступає в основний ігровий цикл ("Грати"). Під час гри Користувач виконує різні
дії, такі як ведення битв, здобуття ресурсів, управління базою та формування
армії. Опонент (Бот) також бере участь в ігровому процесі, зокрема через
"Навчити юніта" та, ймовірно, також через бойові дії, які є частиною прецеденту
"Брати участь в битвах". Система також дозволяє Користувачеві призупиняти гру
або виходити з неї.
2.3 Проектування логічної структури програмного комплексу
Одним із ключових аспектів розробки є реалізація алгоритмів для
ефективного управління армією та стратегічними рухами гравців. Один з
найцікавіших алгоритмів є:
Використання A*(A-star) Algorithm для пошуку шляху для юнітів:
Алгоритм пошуку А* [16]– належить до евристичних алгоритмів пошуку.
Використовується для пошуку найкоротшого шляху між двома вершинами графу
з додатніми вагами ребер. Алгоритм використовує допоміжну функцію
(евристику), аби скеровувати напрям пошуку та скорочувати його тривалість.
Алгоритм повний в тому сенсі, що завжди знаходить оптимальний розв'язок, якщо
він існує.
Ідея полягає в тому, що А* спершу відвідує ті вершини, які ймовірно
ведуть до найкоротшого шляху до мети. Аби розпізнати такі вершини, кожній
відомій вершині f(x), яке дорівнює довжині найкоротшого шляху від початкової
вершини до кінцевої, який пролягає через обрану вершину. Вершини з
найменшим значенням f обираються в першу чергу. Використана евристика не
32
ЧДТУ. 252169-019 ПЗ
повинна давати завищену оцінку вартості шляху. Прикладом оцінки може
служити пряма лінія: загальний шлях не може бути коротшим за пряму лінію.
Алгоритм пошуку А* знаходить оптимальний шлях між двома вершинами в
графі. В залежності від функції вартості, яка задає кожному ребру його «вагу»,
оптимальність може означати найкоротший, найшвидший або навіть
найпростіший шлях. Теоретично, алгоритм може розв'язувати всі задачі, які
можна представити у вигляді задачі пошуку оптимального шляху на графі.
Алгоритм A* використовується як для планування шляхів, так і в
комп'ютерних іграх. Для планування шляхів, як евристична функція
використовується лінійна відстань до цілі, оскільки згідно з нерівністю
трикутника вона дає оптимальні оцінки. Також алгоритм А* використовується в
іграх, в яких необхідно досягти наперед заданий стан
Розроблені оригінальні механізми дій за допомогою логіки та математичних
бібліотек включають:
Механізм розподілу ресурсів є важливою частиною багатьох гри, особливо
стратегічних і економічних симуляцій, де гравець має можливість керувати
різними аспектами гри для досягнення своїх цілей. Оптимальне використання
ресурсів є ключовим для успішної гри, і цей механізм враховує різні фактори:
Поточні потреби гравця: аналізується поточний стан гравця, його ресурси,
потреби і стратегічні цілі. Розподіл ресурсів здійснюється таким чином, щоб
забезпечити задоволення найважливіших потреб гравця в данний момент.
Стратегічні плани: Враховуються стратегічні плани гравця на
довгострокову перспективу. Ресурси розподіляються так, щоб сприяти виконанню
стратегічних завдань та досягненню цілей гравця в майбутньому.
Економічні аспекти: Враховуються економічні обставини, такі як вартість
ресурсів, можливості для їхнього отримання чи виробництва.
Враховується динамічний характер гри, оскільки враховуються зміни як
внутрішніх, так і зовнішніх умов. Механізм може реагувати на непередбачені
події та адаптувати стратегії в режимі реального часу.
Механізм штучного інтелекту противників.
33
ЧДТУ. 252169-019 ПЗ
Цей механізм охоплює різноманітні аспекти, які роблять поведінку
противників більш реалістичною та стратегічною.
Аналіз гравця: штучний інтелект противників аналізує дії гравця,
враховуючи його стратегію та попередні рішення.
Стратегії атаки та оборони: Розробляються стратегії для ефективних атак та
оборони. Противник може використовувати різні тактики, що базуються на діях
гравця.
Ресурсообіг: штучний інтелект керує використанням ресурсів противників,
забезпечуючи їх ефективне використання в ході гри. Механізм враховує
економічні аспекти, призначаючи пріоритети для видобутку та використання
ресурсів відповідно до стратегії.
2.3.1 Діаграми класів
Для належного розуміння структури нашого програмного забезпечення (ПЗ) RTS
Game, було розроблено діаграму класів.
1 MainGui — клас, що відповідає за головне вікно гри та запуск ігрового
процесу.
2 GameDisplay — клас, що відображає графічний інтерфейс ігрового світу.
3 GameBuilder — клас, який відповідає за створення ігрової мапи та
початкових об'єктів.
4 Map — клас, що представляє ігрову карту, яка складається з клітинок
(Tile).
5 Tile — окрема клітинка карти, на якій можуть розміщуватися об'єкти.
6 Entity — базовий клас для всіх ігрових об'єктів (юніти та будівлі).
7 Unit — підклас Entity, який описує ігрових юнітів, здатних до дій.
8 Worker — клас, що представляє юнітів-збирачів ресурсів.
9 Fighter — клас, що представляє бойових юнітів.
10 Building — підклас Entity, що описує будівлі в грі.
11 Barrack — будівля, що може тренувати юнітів.
12 Ressource — клас, що описує ресурси на карті (дерево, камінь, тощо).
13 Faction — клас, що описує фракцію, до якої належать об'єкти.
34
ЧДТУ. 252169-019 ПЗ
14 FactionManager — клас, який керує всіма фракціями в грі.
15 Position — клас, що описує координати об'єктів на мапі.
Рисунок 2.3 – Діаграма класів без атрибутів
35
ЧДТУ. 252169-019 ПЗ
На діаграмі також вказано зв’язки між класами: наслідування (Entity → Unit
/ Building), композиція (Map → Tile), асоціації (Barrack → Unit, Worker →
Ressource, Entity → Faction), які показують логіку взаємодії між ігровими
сутностями.
Рисунок 2.4 – Діаграма класів з атрибутами
Опис діаграми класів:
1 MainGui — головний клас інтерфейсу гри. Містить змінні windowTitle,
isRunning та метод run(), який запускає гру.
2 GameDisplay — відповідає за рендеринг гри, має метод render().
36
ЧДТУ. 252169-019 ПЗ
3 GameBuilder — будує карту та ініціалізує об'єкти. Містить методи
buildMap() і initEntities().
4 Map — зберігає параметри карти: ширину (width), висоту (height) та
масив клітинок (tiles). Метод getTile() повертає вказану клітинку.
5 Tile — описує клітинку карти: тип поверхні (terrainType), зайнятість
(isOccupied).
6 Entity — базовий клас об'єктів. Має id, position та метод moveTo().
7 Unit — наслідує Entity, додає параметри hp, attack та метод act().
8 Worker — підтип юніта, що виконує збирання ресурсів, має carryCapacity,
метод gather().
9 Fighter — бойовий юніт, має параметр weapon, метод attack().
10 Building — клас для будівель, має constructionTime.
11 Barrack — спеціальна будівля, має метод trainUnit() для створення
юнітів.
12 Ressource — описує ресурс (type, amount) та метод decrease().
13 Faction — представляє сторону в грі (name), має метод addEntity().
14 FactionManager — керує фракціями, метод getFaction().
15 Position — містить координати x і y на мапі.
Діаграма також містить спадкування між класами Entity → Unit/Building,
Unit → Worker/Fighter, Building → Barrack. Вказано асоціації між об’єктами:
Barrack тренує Unit, Worker збирає Ressource, Entity належить до Faction. Дані
зв’язки реалізовані за допомогою композиції та агрегації.
Це є основні, але не всі описані класи для створення та відображення гри
Загальна ієрархія класів приставлена так:
java.lang.Object
engine.Animation
configuration.BotConfiguration
engine.manager.BotManager
engine.Camera
engine.math.Collision
37
ЧДТУ. 252169-019 ПЗ
java.awt.Component (implements java.awt.image.ImageObserver,
java.awt.MenuContainer, java.io.Serializable)
java.awt.Container
javax.swing.JComponent (implements java.io.Serializable)
javax.swing.JPanel (implements
javax.accessibility.Accessible)
gui.GameDisplay
java.awt.Window (implements
javax.accessibility.Accessible)
java.awt.Frame (implements java.awt.MenuContainer)
javax.swing.JFrame (implements
javax.accessibility.Accessible,
javax.swing.RootPaneContainer,
javax.swing.WindowConstants)
gui.MainGui (implements
java.lang.Runnable)
engine.manager.EntitiesManager
engine.Entity
engine.entity.building.AttackBuilding
engine.entity.building.Tower
engine.entity.building.ProductionBuilding
engine.entity.building.Archery
engine.entity.building.Barrack
engine.entity.building.Castle
engine.entity.building.Forge
engine.entity.building.Hq
engine.entity.building.Stable
engine.Ressource
engine.entity.building.SiteConstruction
38
ЧДТУ. 252169-019 ПЗ
engine.entity.building.StorageBuilding
engine.entity.unit.Unit
engine.entity.unit.Fighter
engine.entity.unit.Worker
configuration.EntityConfiguration
engine.Faction
engine.manager.FactionManager
engine.map.Fog
engine.map.FogCase
factionConfiguration.ForUpgrade
engine.manager.GameBuilder
configuration.GameConfiguration
engine.manager.GraphicsManager
engine.map.Map
configuration.MapConfiguration
engine.map.Minimap
engine.Mouse
engine.math.Node
gui.PaintStrategyGame
gui.PaintStrategyMainMenu
gui.PaintStrategyOption
gui.PaintStrategyPauseMenu
gui.PaintStrategyVictoryScreen
engine.math.Path
factionConfiguration.Patron
factionConfiguration.ForAttackBuilding
factionConfiguration.ForFighter
factionConfiguration.ForProductionBuilding
factionConfiguration.ForStorageBuilding
39
ЧДТУ. 252169-019 ПЗ
factionConfiguration.ForWorker
engine.Position
configuration.PositionConfiguration
factionConfiguration.Race
factionConfiguration.Royaume
engine.math.SelectionRect
engine.Speed
gui.StatEntityContainer
engine.map.Tile
2.4 Архітектура проектування
В розробці кожного програмного забезпечення, використання паттернів
проектування стає важливим етапом для забезпечення ефективності,
читабельності та легкості управління кодом. Один із таких паттернів – Модуль
(Module) або Компонент (Component). Патерн модуль (Module Pattern) не є
частиною стандартного об'єктно-орієнтованого програмування (ООП) або дизайн-
патернів, і ви його не знайдете в офіційних каталогах патернів проектування.
Зазвичай це термін, який використовується у контексті програмування на мовах,
які підтримують модульність.
Модульність в програмуванні означає створення програми з невеликих,
самодостатніх і замінюваних модулів. Це допомагає в підтримці, розширенні і
вдосконаленні коду.
Загальна ідея модульності полягає в тому, щоб розділити програмний код на
компоненти (модулі), які можна використовувати незалежно один від одного.
2.4.1 Діаграма компонентів
Для кращого розуміння архітектури побудуємо UML-діаграму компонентів.
UML (Unified Modeling Language) [14] – це стандартний мовний інструментарій
для моделювання об'єктно-орієнтованих систем. UML-діаграма компонентів
використовується для візуалізації, спрощення та розуміння взаємодії компонентів
40
ЧДТУ. 252169-019 ПЗ
програмної системи. Компонент в UML може представляти фізичний або
логічний модуль програми.
Рисунок 2.4 – Діаграма компонентів
Архітектура, побудована за Component(Module) паттерном, дозволяє
зберігати код чистим, легко розширювати та модифікувати, адже кожен модуль
відповідає за свою окрему функцію. Розподіл обов'язків між модулями полегшує
роботу над проектом, забезпечуючи оптимальну організацію та легкість
управління
2.4.2 Розгортання програмної системи на апаратних засобах. Діаграма
розгортання
Розгортання програмної системи RTS-гри передбачає її встановлення та
налаштування на обраних апаратних засобах, які забезпечують ефективну роботу
як під час розробки, так і під час тестування та експлуатації програмного
продукту.
Для коректного функціонування гри було обрано наступну цільову апаратну
платформу:
– операційна система: Windows 10 або новіша;
41
ЧДТУ. 252169-019 ПЗ
– процесор: Intel Core i5 (4 ядра) або еквівалентний AMD;
– оперативна пам'ять: від 8 ГБ;
– відеокарта: інтегрована або дискретна з підтримкою OpenGL 2.0;
– жорсткий диск: SSD або HDD з вільним обсягом не менше 500 МБ;
– Java Virtual Machine: Java SE Runtime Environment версії 11 або новіше.
Програмна система була розроблена у середовищі IntelliJ IDEA, що
дозволяє зручно розгортати проект на локальному комп’ютері розробника,
проводити його тестування та налагодження. Графічна складова гри реалізована з
використанням бібліотек AWT/Swing, які забезпечують незалежність інтерфейсу
від платформи, що дозволяє запускати гру на будь-якій операційній системі, що
підтримує JVM.
Процес розгортання включає наступні кроки:
1 Встановлення JDK та середовища розробки.
2 Завантаження або клонування проєкту.
3 Конфігурація запуску в IDE.
4 Збірка проєкту (build) з отриманням .jar файлу.
5 Запуск гри за допомогою JVM або подвійним кліком на зібраний .jar файл.
Діаграма розгортання (рисунок 2.5)
На діаграмі нижче наведено розгортання програмної системи на апаратних
компонентах, що взаємодіють між собою:
Рисунок 2.5 – Діаграма розгортання
42
ЧДТУ. 252169-019 ПЗ
2.5 Моделювання поведінки системи
Моделювання поведінки системи є критично важливим етапом у
проектуванні програмного забезпечення, що дозволяє візуалізувати динамічні
аспекти функціонування системи та взаємодію її компонентів у часі. Для
розробки RTS-гри це допомагає зрозуміти логіку ігрового процесу, реакції
системи на дії гравця та взаємодію ігрових об'єктів. Для цього використовуються
різні діаграми поведінки UML.
2.5.1 Діаграма діяльності
Діаграма діяльності (рисунок 2.6) відображає послідовність дій та потоки
управління у системі, або бізнес-процеси. Для RTS-гри, діаграми діяльності
можуть деталізувати ігровий цикл, процес прийняття рішень гравцем або логіку
поведінки штучного інтелекту.
Рисунок 2.6 – Діаграма діяльності
43
ЧДТУ. 252169-019 ПЗ
Ця діаграма моделює типовий життєвий цикл гри жанру RTS
1 Ініціалізація: запуск рушія, завантаження карти та ресурсів.
2 Основний цикл гри (поки гра не завершена):
– обробка вводу гравця;
– оновлення стану світу, юнітів, будівель, AI;
– проведення бойових дій.
3 Завершення гри: визначення результату, показ меню, збереження
результатів.
2.5.2 Діаграма послідовності
Діаграма послідовності відображає взаємодію між об’єктами у певній
хронологічній послідовності, показуючи, які повідомлення передаються між
об’єктами. Вона ідеально підходить для моделювання конкретних сценаріїв
використання
Ця діаграма послідовності (Рисунок 2.7) надає високорівневий огляд
типової ігрової сесії в RTS-грі, починаючи від моменту запуску програми і до її
завершення. Вона фокусується на ключових фазах взаємодії між гравцем,
користувацьким інтерфейсом (UI) та основними компонентами ігрової системи,
демонструючи їх хронологічну взаємодію.
Основні учасники діаграми та їх ролі:
гравець (Player): зовнішній актор, який взаємодіє з грою, приймає рішення
та надає команди;
користувацький інтерфейс (UI): компонент, відповідальний за
відображення ігрового світу, меню, HUD (Heads-Up Display) та обробку вхідних
даних від гравця;
менеджер стану гри (GameStateManager): відповідає за загальне
управління станом гри, переходи між основними фазами (головне меню, ігровий
процес, кінцеве меню);
ігровий цикл (GameLoop): центральний компонент, який постійно
оновлює ігровий світ, обробляє логіку, керує взаємодією між підсистемами та
підтримує синхронізацію;
44
ЧДТУ. 252169-019 ПЗ
менеджер введення (InputManager): відповідає за зчитування та
інтерпретацію вхідних даних від гравця (клавіатура, миша);
стан ігрового світу (WorldState): зберігає поточний стан усіх ігрових
об’єктів (юнітів, будівель, ресурсів, ландшафту) та їхніх властивостей.
штучний інтелект (AI): компонент, що керує діями противників (NPC),
приймаючи рішення та виконуючи стратегічні/тактичні маневри.
Послідовність взаємодій:
1 Запуск гри: Гравець ініціює запуск програми. GameStateManager бере на
себе управління, ініціалізує UI для відображення головного меню, очікуючи на
вибір гравця (наприклад, «Нова гра»).
2 Початок ігрової сесії: Після вибору «Нова гра» GameStateManager
передає управління GameLoop. GameLoop відповідає за ініціалізацію всіх
ключових підсистем: WorldState створює початкову карту та розміщує об’єкти, AI
ініціалізується для управління ворогами, а UI налаштовується для відображення
ігрового світу та HUD.
3 Основний Ігровий Цикл: Цей цикл є серцем гри і безперервно
виконується протягом усієї ігрової сесії:
gameloop постійно запитує введення від InputManager, який передає дії
гравця;
гравець взаємодіє з UI (наприклад, виділяє юнітів, віддає накази), і UI
передає ці ігрові запити до GameLoop;
gameloop оновлює WorldState на основі як дій гравця, так і рішень,
прийнятих AI (який також регулярно запитується GameLoop);
відбувається оновлення внутрішньої ігрової логіки: таймери, кулдауни,
ефекти, фізика тощо;
постійно перевіряються умови перемоги або поразки;
gameloop регулярно надсилає оновлені дані UI, який, у свою чергу,
візуалізує зміни ігрового світу для гравця.
4 Завершення гри: Коли умови перемоги або поразки виконані, GameLoop
повідомляє GameStateManager про завершення гри та її результат.
45
ЧДТУ. 252169-019 ПЗ
GameStateManager переводить гру в стан кінцевого меню, яке UI відображає
гравцеві (повідомлення «Перемога» або «Поразка»).
5 Вихід: Гравець може вибрати вихід з гри або початок нової.
GameStateManager обробляє цей запит і завершує роботу програми.
Ця діаграма підкреслює циклічний характер ігрового процесу в RTS, де
постійна взаємодія між гравцем, візуалізацією та логікою гри створює динамічний
та інтерактивний досвід
Рисунок 2.7 – Діаграма послідовності
2.5.3 Діаграма комунікації
Діаграма комунікації (рисунок 2.8) фокусується на взаємодії об'єктів та
їхніх зв'язках, показуючи, як об'єкти співпрацюють для досягнення певної мети.
Вона краще підходить для демонстрації структури взаємодії, ніж її хронологічної
46
ЧДТУ. 252169-019 ПЗ
послідовності.
Рисунок 2.8 – Діаграма комунікації
Опис діаграми комунікації для RTS гри
Діаграма комунікації вище ілюструє ключові взаємодії між основними
компонентами вашої RTS (стратегії в реальному часі) гри. Вона показує, як різні
частини системи співпрацюють для запуску гри та обробки дій гравця впродовж
ігрового циклу.
Ключові учасники комунікації:
1 Клієнт GUI (MainGui): Це головний графічний інтерфейс користувача,
який гравець бачить і з яким взаємодіє. Він відповідає за відображення гри та
ініціалізацію інших клієнтських компонентів.
2 Обробник Вводу (InputHandler): Цей компонент відповідає за отримання
вводу від гравця (наприклад, натискання клавіш, рухи миші, кліки) та
перетворення його на ігрові команди.
3 Відображення Гри (GameDisplay): Відповідає за рендеринг ігрового світу,
юнітів, будівель, карти та інших візуальних елементів на екрані гравця.
4 Будівник Гри (GameBuilder): Компонент, який відповідає за ініціалізацію
та налаштування нової ігрової сесії, завантаження початкових даних.
5 Рушій Ігрової Логіки (GameLogicEngine): Це серце гри. Він обробляє всі
ігрові правила, розраховує рух юнітів, бої, збір ресурсів, будівництво та інші
47
ЧДТУ. 252169-019 ПЗ
ігрові події.
6 Менеджер Сутностей (EntityManager): Керує всіма ігровими об'єктами
(юнітами, будівлями, ресурсами) в ігровому світі: їхнім створенням, оновленням
стану, видаленням.
7 Менеджер Фракцій (FactionManager): Відповідає за управління фракціями
гравців, їхніми характеристиками, технологіями, ресурсами та іншими даними,
пов'язаними з фракціями.
8 Сервіс Карти (MapService): Надає дані про ігрову карту, її рельєф,
перешкоди, туман війни та інші властивості.
9 Текстовий Файл Даних (TextFile): Це віртуальний компонент, що
символізує постійне сховище даних гри, реалізоване через текстові файли.
Використовується для збереження стану об'єктів та статистики фракцій.
Процес комунікації
Процес взаємодії компонентів можна розділити на два основні етапи:
1 Ініціалізація та запуск гри
Клієнт GUI (MainGui) ініціює запит до Будівника Гри (GameBuilder) на
створення нової ігрової сесії.
Після успішного створення, Будівник Гри підтверджує це MainGui.
Далі MainGui ініціалізує Відображення Гри (GameDisplay) для підготовки
до рендерингу та Обробник Вводу (InputHandler) для початку прийому дій гравця.
2 Ігровий цикл та обробка дій гравця
Обробник Вводу (InputHandler) отримує команди від гравця (наприклад,
переміщення юніта, будівництво будівлі) та передає їх до Рушія Ігрової Логіки
(GameLogicEngine).
GameLogicEngine, отримавши команду, активується для її обробки.
Для виконання команди GameLogicEngine звертається до Менеджера
Сутностей (EntityManager), щоб отримати або змінити дані ігрових об'єктів.
EntityManager у свою чергу взаємодіє з Текстовим Файлом Даних для читання або
збереження поточного стану сутностей.
Паралельно, GameLogicEngine може взаємодіяти з Менеджером Фракцій
48
ЧДТУ. 252169-019 ПЗ
(FactionManager) для оновлення характеристик фракцій (наприклад, ресурсів,
технологій). FactionManager також взаємодіє з Текстовим Файлом Даних для
збереження статистики гравця.
GameLogicEngine також звертається до Сервісу Карти (MapService), щоб
отримати актуальні дані про ігрове поле, необхідні для розрахунків (наприклад,
прохідність території).
Після всіх необхідних розрахунків та оновлень, GameLogicEngine передає
оновлений стан гри до Відображення Гри (GameDisplay) для візуалізації змін на
екрані гравця.
GameDisplay завершує оновлення, і цикл продовжується, очікуючи
наступних дій гравця або внутрішніх ігрових подій.
2.5.4 Діаграма скінченного автомату
Скінченний автомат (Finite State Machine, FSM) – це модель поведінки, яка
описує систему як набір станів, переходів між ними та подій, що викликають ці
переходи. У контексті RTS-гри FSM використовується для управління логікою
станів юнітів, зокрема – їх реакції на події (атака, переміщення, очікування,
знищення тощо).
Основні стани юніта:
очікування (idle) – початковий стан, у якому юніт не виконує активних
дій;
рух (moving) – стан, коли юніт виконує команду переміщення;
атака (attacking) – юніт здійснює бойову дію щодо супротивника;
будівництво (building) – для робітників: стан, у якому виконується
зведення будівлі;
збір ресурсів (collecting) – юніт виконує дію видобування або збору
ресурсів;
знищення (destroyed) – фінальний стан після втрати всіх очок здоров’я.
Приклади переходів:
Idle → Moving: після отримання команди на переміщення;
49
ЧДТУ. 252169-019 ПЗ
Moving → Idle: після досягнення точки призначення;
Idle/Moving → Attacking: при виявленні ворога у радіусі дії;
Attacking → Idle: після завершення бою або зникнення цілі;
Any → Destroyed: після досягнення нульового рівня здоров’я.
FSM реалізовано для кожного юніта індивідуально, що дозволяє їм
реагувати на зовнішні події незалежно одне від одного. Такий підхід забезпечує
гнучкість, масштабованість та простоту розширення логіки поведінки, зокрема
для штучного інтелекту противників.
Рисунок 2.9 – Діаграма скінченного автомату
ВИСНОВКИ ДО ДРУГОГО РОЗДІЛУ
50
ЧДТУ. 252169-019 ПЗ
У другому розділі було детально проаналізовано процес впровадження
результатів досліджень у практику проєктування програмного забезпечення.
Особливу увагу приділено моделюванню предметної області, формуванню вимог,
проектуванню логіки та архітектури гри.
Побудовані UML-діаграми – діаграми прецедентів, класів, компонентів,
розгортання, діяльності, послідовності, комунікації та скінченного автомату –
дозволили чітко структурувати систему та визначити основні функціональні
блоки. Це забезпечило можливість реалізації зрозумілої, масштабованої та
ефективної архітектури програмного продукту.
Результатом цього етапу стало створення повноцінної моделі програмної
системи RTS-гри, яка забезпечує базу для її подальшої розробки та впровадження.
Всі структурні та поведінкові аспекти системи були проаналізовані й адаптовані
до реальних потреб гравця та умов гри.
РОЗДІЛ 3 РОЗРОБКА ТА ТЕСТУВАННЯ ПРОГРАМНОГО
ЗАБЕЗПЕЧЕННЯ
51
ЧДТУ. 252169-019 ПЗ
3.1 Розробка програмного комплекс
Процес розробки програмного забезпечення гри в жанрі Real-Time Strategy
(RTS) включав комплекс заходів, спрямованих на створення ефективної,
масштабованої та зручної у використанні ігрової системи. Основні завдання на
цьому етапі полягали в реалізації ключових ігрових механік, створенні
внутрішньої архітектури, налаштуванні взаємодії компонентів та забезпеченні
працездатності системи на різних платформах.
Розробка проводилася із врахуванням попереднього аналізу вимог,
побудови моделей, діаграм класів, компонентів, сценаріїв використання, а також
діаграм поведінки. Ці матеріали стали основою для проектування функціональних
частин програми, зокрема: логіки управління юнітами, бойової системи,
економіки гри, взаємодії з користувачем та збереження даних.
У процесі розробки було враховано такі принципи:
модульність, що дозволяє розширювати функціональність без значної
перебудови проєкту;
портативність, забезпечена використанням мови програмування Java та
графічних бібліотек AWT/Swing;
продуктивність, досягнута завдяки оптимізації основних ігрових
алгоритмів (наприклад, алгоритму A* для пошуку шляху);
юзабіліті, що реалізовано через інтуїтивно зрозумілий графічний
інтерфейс;
гнучкість, яка дозволяє адаптувати гру до різних системних конфігурацій.
В основі реалізації проєкту лежить об'єктно-орієнтований підхід, що
забезпечує зручну структуру коду та спрощує процес налагодження і тестування.
Було також приділено увагу документації внутрішнього коду та використанню
шаблонів проєктування для забезпечення узгодженості архітектури.
Результатом цього етапу стала повнофункціональна програмна система, що
реалізує всі основні сценарії гри, включаючи створення бази, управління армією,
52
ЧДТУ. 252169-019 ПЗ
бойові дії, обробку перемоги/поразки, збереження прогресу та взаємодію з
інтерфейсом користувача.
3.1.1 Обґрунтування вибору засобів реалізації
Для реалізації програмного комплексу гри в жанрі Real-Time Strategy (RTS)
було обрано такі основні засоби та технології:
1 Мова програмування Java
Java була обрана як основна мова розробки з наступних причин:
1 Портативність: Програма, написана на Java, працює на будь-якій
платформі, де встановлена віртуальна машина Java (JVM). Це дозволяє
розгорнути гру на різних операційних системах без значних змін у коді.
2 Об'єктно-орієнтоване програмування (ООП): Java надає повноцінну
підтримку ООП, що дозволяє зручно організовувати структуру ігрових об'єктів.
3 Широка екосистема: Існує велика кількість бібліотек і фреймворків, які
спрощують розробку графіки, обробку подій, роботу з файлами.
2 Середовище розробки IntelliJ IDEA
Для розробки проєкту використовувалося інтегроване середовище розробки
(IDE) IntelliJ IDEA, яке забезпечує:
широкі можливості автоматичного завершення коду;
потужні засоби налагодження;
зручне управління структурою проєкту;
інтеграцію з системами контролю версій.
3 Графічні бібліотеки: AWT та Swing
Для створення інтерфейсу користувача було обрано бібліотеки AWT та
Swing, які надають засоби для реалізації:
віконного інтерфейсу з меню, кнопками, інформаційними панелями;
виведення ігрових об'єктів (юнити, будівлі, мапа);
обробки подій (миша, клавіатура).
Swing дозволяє створювати кросплатформенний інтерфейс з високим
ступенем кастомізації, а також добре інтегрується з Java.
53
ЧДТУ. 252169-019 ПЗ
4 Алгоритмічне забезпечення
У якості основного алгоритму для руху юнітів було використано A (A-star)*
– один із найефективніших евристичних алгоритмів пошуку шляху. Він дозволяє
реалізувати точне та швидке переміщення бойових одиниць у межах ігрової
карти, враховуючи перешкоди.
Таким чином, вибір засобів реалізації був зумовлений метою створити
масштабоване, кросплатформенне, функціональне та зручне у підтримці
програмне забезпечення. Обрані інструменти повністю відповідають поставленим
технічним та функціональним вимогам проєкту.
3.1.2 Опис структурної (функціональної) схеми
Функціональна схема програмного комплексу RTS-гри описує основні
компоненти системи, їхні функції та взаємодію між собою в рамках реалізації
ігрового процесу. Вона служить основою для розуміння структури програмного
забезпечення та реалізованої логіки.
Основні функціональні блоки системи:
1 Інтерфейс користувача (GUI):
забезпечує візуальну взаємодію з користувачем;
реалізовано за допомогою бібліотек AWT/Swing;
містить головне меню, ігрове вікно, інформаційні панелі, меню
паузи, меню налаштувань, екран перемоги/поразки.
2 Ігровий рушій (Engine):
відповідає за логіку гри, оновлення стану об’єктів, обробку подій
(натискання, переміщення);
містить класи для управління юнітами, спорудами, ресурсами,
фракціями та логікою бою;
виконує оновлення стану гри кожен кадр гри (game loop).
3 Модуль карт та навігації:
реалізує відображення мапи, міні-карти та механіку “туману
війни”;
54
ЧДТУ. 252169-019 ПЗ
зберігає інформацію про ігрове поле, розташування юнітів,
ресурсів і будівель;
використовує алгоритм A* для навігації юнітів по мапі.
4 Модуль управління ресурсами:
здійснює облік і розподіл ресурсів гравця;
підтримує взаємодію між ресурсами, робітниками та спорудами
для їх видобутку.
5 Модуль бойової системи:
відповідає за логіку боїв: обчислення урону, зіткнення, знищення
юнітів;
враховує різні типи атак та типи юнітів (ближній/дальній бій тощо).
6 Штучний інтелект (ШІ):
реалізує логіку поведінки опонентів: прийняття рішень, побудова
бази, управління армією;
реалізовано з урахуванням змін у стані гри та стратегії гравця.
7 Менеджер фракцій та сценаріїв:
контролює параметри кожної фракції, її ресурси, армію, логіку
розвитку;
забезпечує ініціалізацію та завершення сценаріїв гри (місії, умови
перемоги/поразки).
Загальна логіка взаємодії:
1 Користувач через інтерфейс надсилає команди (побудова, атака,
переміщення).
2 Ці команди обробляє ігровий рушій, який оновлює стан об'єктів у грі.
3 Графічний модуль відображає поточний стан гри.
4 Системи штучного інтелекту приймають рішення у відповідь на дії
гравця.
5 Ресурсна система забезпечує економіку гри, впливаючи на можливість
створення нових об’єктів.
55
ЧДТУ. 252169-019 ПЗ
Уся система працює за принципом циклічного оновлення стану (game loop),
що дозволяє реалізувати безперервний геймплей у реальному часі.
Рисунок 3.1 –Структурна (функціональна) схема
3.1.3 Опис логічної схеми
Логічна схема системи деталізує внутрішню логіку роботи ключових
алгоритмів та взаємодію об'єктів на нижчому рівні. Тут описуються конкретні
механізми, які забезпечують функціонування ігрових механік.
Приклад: Логіка пошуку шляху (Pathfinding)
Для переміщення юнітів по ігровій карті використовується алгоритм
пошуку шляху, наприклад, алгоритм A*. Цей алгоритм є одним з
найпоширеніших для пошуку найкоротшого шляху на графі, що складається з
вузлів (клітинки карти) та ребер (можливі переходи).
Вхідні дані: початкова позиція юніта, цільова позиція, карта перешкод
(непрохідні ділянки).
Ініціалізація двох списків: відкритий_список (вузли, які потрібно
розглянути) та закритий_список (вузли, які вже розглянуті).
Додавання початкової позиції до відкритого_списку.
Повторення до тих пір, поки відкритий_список не порожній або ціль не
знайдена:
Вибір вузла з відкритого_списку з найменшим значенням F = G + H, де G –
вартість шляху від старту до поточного вузла, H – евристична оцінка вартості від
поточного вузла до цілі.
Якщо обраний вузол – це ціль, шлях знайдено.
Видалення обраного вузла з відкритого_списку та додавання до
закритого_списку.
56
ЧДТУ. 252169-019 ПЗ
Розгляд сусідніх вузлів: для кожного сусіда, якщо він не в закритого_списку
та не є перешкодою, обчислити G та H. Якщо сусід вже у відкритого_списку та
новий шлях до нього кращий, оновити його значення. Інакше, додати сусіда до
відкритого_списку.
Рисунок 3.2 –Логічна схема
Вихідні дані: Послідовність вузлів, що утворюють оптимальний шлях від
початкової до цільової позиції.
Приклад: Логіка обробки бою
Бойова система реалізована за принципом покрокового розрахунку шкоди.
Коли юніт атакує іншого юніта або будівлю:
1 Визначається сила атаки атакуючого юніта.
2 Визначається рівень захисту цільового об'єкта.
3 Розраховується фактична шкода: Шкода = Сила_атаки * (1 –
Відсоток_захисту).
57
ЧДТУ. 252169-019 ПЗ
4 Від здоров'я цільового об'єкта віднімається розрахована шкода.
Якщо здоров'я цільового об'єкта падає до нуля або нижче, об'єкт
позначається як знищений/загиблий, і запускаються відповідні події (анімація
смерті, видалення з ігрового світу).
3.1.4 Розробка бази даних
У рамках розробки ігрового комплексу жанру RTS, представленого в даній
роботі, не було потреби у використанні централізованої системи управління
базами даних. Це обумовлено специфікою ігрового процесу та архітектури
Сесійний характер гри: Уся ігрова інформація (стан карти, положення
юнітів, рівень ресурсів, прогрес будівництва) є актуальною лише в межах однієї
ігрової сесії. Після її завершення (перемога/поразка або вихід гравця) ці дані не
потребують постійного збереження для подальшого використання.
Динамічна зміна стану: Ігровий світ є повністю динамічним, і його стан
постійно оновлюється в оперативній пам'яті протягом реального часу. Будь-яке
збереження стану гри (наприклад, "зберегти/завантажити гру") реалізується
шляхом серіалізації поточного стану ігрових об'єктів у файлову систему, а не
через СУБД.
Відсутність постійних облікових записів або метаданих: Проект не
передбачає ведення облікових записів користувачів, збору статистики або
зберігання глобальних налаштувань, які б вимагали постійної бази даних.
Таким чином, уся необхідна ігрова логіка та управління даними реалізовані
безпосередньо в коді програми з використанням внутрішніх структур даних, що є
оптимальним рішенням для даного типу гри.
3.1.5 Розробка інтерфейсу користувача
Інтерфейс користувача (UI) є критично важливою складовою програмного
комплексу гри в жанрі RTS, оскільки саме він забезпечує взаємодію між гравцем
та ігровим середовищем. Розробка інтерфейсу проводилась із використанням
бібліотек AWT та Swing, які забезпечують кросплатформеність, візуальну
адаптивність та широкі можливості кастомізації.
58
ЧДТУ. 252169-019 ПЗ
Основні елементи інтерфейсу:
1 Головне меню – доступ до запуску гри, параметрів, виходу.
2 Ігровий екран – основне поле гри, на якому відображаються юніти,
споруди, мапа, туман війни.
3 Мінікарта – зменшена копія мапи, яка дозволяє орієнтуватися на полі бою.
4 Інформаційна панель – відображення стану ресурсів, обраного юніта, його
характеристик.
5 Меню паузи – можливість зупинити гру, змінити параметри або вийти до
головного меню.
6 Екрани перемоги/поразки – підсумки гри, статистика.
Технічна реалізація
Інтерфейс реалізовано в окремому пакеті gui, що містить спеціалізовані
класи:
– MainGui – головний клас інтерфейсу;
– GameDisplay – візуалізація графіки гри;
– PaintStrategyGame, PaintStrategyMainMenu, PaintStrategyPauseMenu (класи
відповідальні за відображення окремих екранів гри);
– StatEntityContainer – модуль керування динамічним відображенням
інформації про сутності.
Компоненти інтерфейсу взаємодіють з ігровим рушієм через події миші та
клавіатури, а також через спеціалізовані менеджери стану гри, що дозволяє
динамічно оновлювати інформацію на екрані.
3.1.6 Опис розробки програмних компонентів
Програмні компоненти системи поділено на функціональні модулі, кожен з
яких відповідає за окрему частину логіки гри. Це дозволило реалізувати модульну
архітектуру, яка полегшує тестування, відлагодження та подальшу модернізацію
гри.
Основні компоненти:
1 Ігровий рушій (engine):
59
ЧДТУ. 252169-019 ПЗ
– Entity, Unit, Building, Worker, Fighter – класи, що описують основні об'єкти
гри;
– Animation, Camera, Mouse – реалізація візуальних ефектів та взаємодії з
мишею;
– Faction, Ressource, Speed, Position – утилітарні класи для підтримки ігрової
логіки.
2 Математичний модуль (engine.math):
– Node, Path – реалізація алгоритму A* для пошуку шляху;
– Collision, SelectionRect – логіка зіткнень та виділення елементів карти.
3 Менеджери (engine.manager):
– GameBuilder – ініціалізація нової гри;
– GraphicsManager – керування буферизованою графікою;
– BotManager, FactionManager, EntitiesManager – логіка керування ботами,
фракціями, об'єктами гри.
4 Картографічний модуль (engine.map):
– Map, Tile, Minimap, Fog, FogCase – реалізація мапи гри, динамічного
туману війни, мінікарти.
5 Конфігураційні класи (configuration):
GameConfiguration, MapConfiguration, EntityConfiguration,
PositionConfiguration – зберігання налаштувань та параметрів, які легко змінити
без модифікації коду.
Підхід до розробки:
1 Використано принцип Single Responsibility, кожен клас відповідає лише за
одну логічну функцію.
2 Дотримано інкапсуляції, зовнішній доступ до об'єктів реалізовано через
публічні методи.
3 Масштабованість досягнута через поділ на окремі пакети.
У результаті створено надійну структуру програмного забезпечення, здатну
підтримувати основний ігровий процес, масштабування контенту та розширення
функціоналу в майбутньому.
60
ЧДТУ. 252169-019 ПЗ
3.2 Тестування системи
У розділі ми детально розглянемо якість та стабільність розробленого
програмного продукту, а також проведемо процес тестування для впевненості в
його надійності та ефективності.
SonarLint [17] від Sonar – це безкоштовне розширення IDE для пошуку та
вирішення проблем кодування в режимі реального часу, позначаючи проблеми
під час кодування, подібно до перевірки орфографії. Це більше, ніж лінтер, він
також надає розширені контекстні вказівки, щоб допомогти розробникам
зрозуміти, чому виникла проблема, оцінити ризик і навчити їх виправляти її. Це
допомагає покращити їхні навички, підвищити продуктивність і взяти на себе
відповідальність за їхній код, виводячи лінтинг на інший рівень.
SonarLint – це потужний інструмент із відкритим вихідним кодом для
розробників із будь-яким досвідом і навичками, який дає їм змогу створювати
чистий код – код, придатний для розробки та виробництва. Важливий інструмент
для створення ліннів для кожного розробника.
SonarLint інтегрується з більшістю IDE JetBrains, включаючи IntelliJ IDEA,
CLion, GoLand, WebStorm, PHPStorm, PyCharm, Rider, Android Studio та
RubyMine. Підтримувані мови включають C, C++, Java, Go, JavaScript, TypeScript,
Python, C#, Kotlin, Ruby, HTML, CSS, PHP і PL/SQL.
За допомогою SonarLint було проаналізовано весь проект. При цьому аналізі
вдалося ідентифікувати різні види аномалій, такі як потенційні помилки в коді,
проблеми з безпекою та стильові конфлікти.
Однією з переваг SonarLint є можливість раннього виявлення проблем ще до
етапу компіляції чи виконання коду. Це дозволяє уникнути потенційних проблем
у подальшому розвитку проекту та поліпшити його загальну якість.
Згідно рисунку бачимо, що SonarLint виявив певні проблеми в коді, в
цілому пов’язані з стилем написання та відповідність до Java Code Conventions
[18]
61
ЧДТУ. 252169-019 ПЗ
Рисунок 3.3 – Ілюстрація звіту SonarLint
Аналіз SonarLint також виявив слабкі місця в архітектурі коду та надав
рекомендації з їх поліпшення. Це важливий аспект для забезпечення гнучкості та
розширюваності проекту у майбутньому.
Узагальнюючи, використання SonarLint було корисним етапом в розробці
проекту, допомагаючи забезпечити високу якість коду та зменшити ймовірність
виникнення проблем у процесі розробки.
3.2.1 Модульне тестування
Модульне тестування (Unit Testing) є першим етапом тестування і
фокусується на перевірці найменших, незалежних одиниць коду – модулів,
функцій або класів – в ізоляції від решти системи. Метою модульного тестування
є підтвердження того, що кожен окремий компонент системи працює коректно
відповідно до своїх специфікацій.
Мета: Перевірка коректності функціонування окремих класів та методів, які
реалізують базові ігрові механіки та логіку.
Інструменти: Для модульного тестування в проектах на Unity/C# часто
використовуються фреймворки, такі як NUnit або вбудований Unity Test
Framework. Ці інструменти дозволяють писати тестові випадки, запускати їх
автоматично та отримувати звіти про результати.
Сценарії тестування (приклади):
Тестування класу Unit:
62
ЧДТУ. 252169-019 ПЗ
1 Перевірка коректного розрахунку здоров'я після отримання шкоди
(TakeDamage(float damage)).
2 Перевірка переходу юніта в стан "Загиблий" при досягненні здоров'я
нуля.
3 Тестування методів переміщення юніта на невелику відстань.
Тестування класу ResourceManager
Перевірка коректності додавання та віднімання ресурсів
(AddResource(ResourceType type, int amount), RemoveResource(ResourceType type,
int amount)).
Тестування перевірки доступності ресурсів для будівництва/тренування
(HasEnoughResources(Cost cost)).
Тестування класу CombatSystem
Перевірка коректності розрахунку шкоди з урахуванням захисту
(CalculateDamage(float attack, float defense)).
Тестування визначення переможця в простому сценарії бою один на один.
Особливості: Модульні тести зазвичай пишуться розробником компонента.
Вони повинні бути швидкими, ізольованими та повторюваними.
Результати: На етапі модульного тестування було виявлено та усунуто
низку дрібних логічних помилок у розрахунках та управлінні станами об'єктів, що
значно покращило стабільність окремих компонентів до їх інтеграції.
Таблиця 3.1
Тест-кейси модульного тестування
№ Опис Передумови Кроки для Очікуваний результат Результат
Тест- відтворення
кейса
Продовження таблиці 3.1
1 Перевірка Клас Unit Створити Об'єкт Unit має бути Пройшов
ініціалізац завантаже екземпляр Unit з успішно створений з
ії об'єкта но. базовими правильними початковими
63
ЧДТУ. 252169-019 ПЗ
Unit Доступні параметрами. значеннями (HP, швидкість,
конфігура атака).
ції юнітів.
2 Тестуванн Клас 1. Створити два Функція повинна повернути Пройшов
я функції Collision об'єкти з true.
Collision.is завантаже відомими
Colliding() но. позиціями та
розмірами, що
перетинаються.
2. Викликати
Collision.isCollid
ing(об'єкт1,
об'єкт2).
3 Тестуванн Екземпляр 1. Створити Об'єкт Entity має бути Пройшов
я функції EntitiesMa об'єкт Entity. 2. доданий до списку
EntityMana nager Викликати керованих сутностей.
ger.addEnti створено. EntityManager.ad
ty() dEntity(об'єкт).
4 Перевірка Екземпляр 1. Отримати Кількість ресурсу має Пройшов
функції Faction початкову збільшитися на задану
Faction.add створено. кількість кількість.
Resource() ресурсу. 2.
Викликати
Faction.addResou
rce(кількість).
Продовження таблиці 3.1
5 Тестува Екземпляр 1. Встановити Позиція Unit має коректно Пройшов
ння Unit цільову позицію. змінюватися в напрямку цілі.
логіки створено з 2. Викликати
64
ЧДТУ. 252169-019 ПЗ
руху початковою Unit.updatePositi
Unit позицією та on(deltaTime).
швидкістю.
6 Перевір Екземпляр 1. Надати Функція повинна повернути Пройшов
ка Map валідні коректний тип тайла для
функцій створено та координати заданих координат.
Map.get ініціалізован тайла. 2.
TileType о. Викликати
() Map.getTileType(
x, y).
7 Тестува Екземпляр 1. Переконатися, Unit повинен отримати Пройшов
ння AttackBuildin що Unit шкоду, рівну атаці Tower.
AttackB g знаходиться в
uilding.a (наприклад, радіусі атаки
ttack() Tower) та Tower. 2.
Unit (ціль) Викликати
створено. Tower.attack(Uni
t).
8 Перевір Файл Викликати Об'єкт EntityConfiguration Пройшов
ка конфігурації метод, що має бути успішно
читання EntityConfigu відповідає за завантажений з даними з
конфігу ration.txt завантаження файлу.
рації існує і EntityConfigurati
EntityCo містить on.
nfigurati коректні
on дані.
3.2.2 Інтеграційне тестування
Інтеграційне тестування (Integration Testing) слідує за модульним і
спрямоване на перевірку взаємодії між об'єднаними модулями або підсистемами.
65
ЧДТУ. 252169-019 ПЗ
Його мета – переконатися, що компоненти, які окремо працюють коректно,
правильно взаємодіють між собою, передаючи дані та викликаючи функції.
Мета: Перевірка коректності взаємодії між різними модулями системи.
Підхід: Використовувався підхід "знизу вгору" (bottom-up), при якому
спочатку тестуються низькорівневі модулі, а потім вони об'єднуються та
тестуються з більш високорівневими.
Сценарії тестування (приклади):
Взаємодія UI System та Building Manager:
Вибір гравцем будівлі в UI, її розміщення на карті та перевірка коректного
ініціалізації об'єкта будівлі в Building Manager.
Перевірка того, як UI оновлюється після завершення будівництва.
Взаємодія Unit Manager та Combat System:
Наказ юніту атакувати ворога через Unit Manager, перевірка, як Combat
System обробляє атаку та оновлює здоров'я цільового юніта.
Перевірка коректності анімацій та звуків бою, що запускаються через
AudioManager.
Взаємодія Resource Manager та Unit Manager / Building Manager
Тестування процесу добування ресурсів робітником (WorkerUnit) та їх
зарахування до ResourceManager.
Перевірка, що ресурси правильно списуються при тренуванні юнітів або
будівництві споруд, і що операція блокується, якщо ресурсів недостатньо.
Результати: Інтеграційне тестування дозволило виявити проблеми з
передачею даних між модулями, некоректні виклики функцій та невідповідності
інтерфейсів, що було оперативно виправлено для забезпечення безшовної
взаємодії компонентів.
Таблиця 3.2
Тест-кейси ітеграційного тестування
66
ЧДТУ. 252169-019 ПЗ
Тест- Кроки для Очікуваний
Опис Передумови Результат
кейса відтворення результат
1 Перевірка Запущена гра, 1. Гравець клікає на Юніт повинен Пройшов
повного юніт існує на юніта. переміститися
циклу руху карті. 2. Гравець клікає на до цільової
юніта цільову позицію. позиції,
коректно
обходячи
перешкоди, і
його позиція має
оновитися на
GameDisplay.
2 Перевірка Запущена гра, 1. Гравець обирає Worker Пройшов
будівництв достатньо Worker. рухається до
а будівлі ресурсів, є 2. Гравець клікає на місця
Worker. кнопку будівництва будівництва,
Barrack. починається
3. Гравець обирає будівництво
місце для SiteConstruction,
будівництва. ресурси
списуються,
потім
SiteConstruction
перетворюється
на Barrack.
Продовженння таблиці 3.2
3 Перевірка Запущена гра, 1. Гравець обирає Fighter Пройшов
67
ЧДТУ. 252169-019 ПЗ
циклу Fighter та Fighter. 2. Гравець рухається до
атаки ворожий Unit клікає на ворожий ворожого Unit,
юніта існують, Unit. атакує його.
знаходяться в Ворожий Unit
зоні отримує шкоду,
видимості. його HP
оновлюється на
GameDisplay.
4 Перевірка Запущена гра, 1. Гравець обирає Worker Пройшов
збору Worker та Worker. 2. Гравець рухається до
ресурсів ресурс клікає на ресурс. ресурсу,
Worker (наприклад, починає збір,
шахта) ресурси фракції
існують. збільшуються.
5 Перевірка Запущена гра, 1. Зберегти Гра має Пройшов
збереженн є ігрові об'єкти поточний стан гри. завантажитись з
я та та прогрес. 2. Перезапустити тим самим
завантажен гру. 3. Завантажити станом об'єктів,
ня гри збережену гру. ресурсами та
позиціями, що
були на момент
збереження.
6 Перевірка Запущена гра, Спостерігати за AI бот повинен Пройшов
поведінки AI бот діями AI бота будувати базові
AI бота активний. протягом певного будівлі та
(базовий часу. тренувати
сценарій) юнітів, збирати
ресурси.
Продовженння таблиці 3.2
7 Тестування Запущена гра, 1. Перемістити Область, де Пройшов
68
ЧДТУ. 252169-019 ПЗ
логіки є FogOfWar. юніта в нерозвідану знаходиться
туману область. 2. юніт, має стати
війни Перевірити, як видимою, а
оновлюється сусідні області
видимість. можуть бути
частково
видимими.
8 Тестування Запущена гра. Виконати будь-які Minimap Пройшов
оновлення дії, що змінюють повинен
Minimap ігровий світ (рух коректно
юнітів, відображати
будівництво). зміни в
реальному часі.
3.2.3 Системне тестування
Системне тестування (System Testing) проводиться після того, як всі
компоненти інтегровані, і система функціонує як єдине ціле. На цьому етапі
перевіряється відповідність системи всім зазначеним функціональним та
нефункціональним вимогам, а також її поведінка в реальних умовах експлуатації.
Мета: Перевірка функціональності, продуктивності, надійності, безпеки
(якщо актуально) та зручності використання всієї інтегрованої системи.
Типи системного тестування
Функціональне тестування: Перевірка всіх заявлених ігрових механік
(добування ресурсів, будівництво, тренування юнітів, управління армією, бойова
система, система перемоги/поразки). Перевірка коректності роботи меню,
налаштувань, збереження/завантаження гри.
Тестування продуктивності: Оцінка FPS (кадрів за секунду) в різних ігрових
сценаріях (велика кількість юнітів, складні бої), завантаження процесора та
оперативної пам'яті. Мета – забезпечення плавного геймплею.
Тестування надійності: Перевірка здатності системи працювати без збоїв
протягом тривалого часу, стійкість до помилок вводу та непередбачених ситуацій.
69
ЧДТУ. 252169-019 ПЗ
Тестування юзабіліті (зручності використання): Оцінка інтуїтивності
інтерфейсу, зрозумілості елементів управління, зручності навігації по меню.
Регресійне тестування: Повторне виконання раніше пройдених тестів після
внесення змін або виправлень для підтвердження, що нові зміни не спричинили
появи нових дефектів або відновлення старих.
Методи: Застосовувались як ручне тестування (QA-інженерами,
тестувальниками), так і елементи автоматизованого тестування (наприклад, для
перевірки базового функціоналу після кожної значної зміни).
Сценарії тестування (приклади):
1 Повний прохід однієї ігрової сесії від початку до кінця (з перемогою та
поразкою).
2 Тестування одночасної взаємодії великої кількості юнітів на карті.
3 Перевірка роботи гри на різних конфігураціях обладнання (якщо
доступно).
Результати: Системне тестування виявило кілька проблем з продуктивністю
на певних етапах гри, а також дрібні візуальні артефакти та невідповідності в UI.
Всі виявлені критичні та значні дефекти були задокументовані, проаналізовані та
виправлені.
Таблиця 3.3
Тест-кейси системного тестування
№ Опис Передумови Кроки для Очікуваний Результа
Тест- відтворення результат т
кейса
1 Повна ігрова Запущена Грати повну Гра має коректно Пройшов
сесія до гра, обраний партію від завершитися
перемоги AI початку до перемогою одного з
(гравець противник. перемоги одного гравців, без збоїв чи
проти AI) з учасників. помилок.
Продовження таблиці 3.3
2 Стрес-тест з Запущена Створити Гра повинна Пройшов
70
ЧДТУ. 252169-019 ПЗ
великою гра, максимальну залишатися відносно
кількістю можливість кількість юнітів плавною, без
юнітів швидкого для обох фракцій значних падінь FPS,
створення та ініціювати зависань.
великої велику битву.
кількості
юнітів.
3 Тестування Запущена 1. Зберегти гру Гра повинна Пройшов
збереження/з гра, юніти в під час активних відновитися точно в
авантаження русі, будівлі ігрових процесів. тому стані, в якому
під час будуються. 2. Перезапустити була збережена, всі
активних дій гру та процеси повинні
завантажити. продовжити
коректно.
4 Перевірка AI Запущена Провести кілька AI повинен Пройшов
на різних гра, партій проти AI демонструвати
рівнях можливість на різних рівнях відповідний рівень
складності вибору складності виклику, адекватно
складності реагуючи на дії
AI. гравця.
5 Тестування Запущена Багаторазово Кількість ресурсів Пройшов
управління гра. збирати ресурси, має коректно
ресурсами будувати будівлі, оновлюватися, не
тренувати з'являються від'ємні
юнітів, щоб значення,
вичерпувати та будівництво/тренува
поповнювати ння блокуються при
запаси ресурсів. нестачі.
3.2.4 Приймальне тестування
71
ЧДТУ. 252169-019 ПЗ
Приймальне тестування (Acceptance Testing) є фінальним етапом
тестування, який проводиться для підтвердження того, що розроблена система
відповідає бізнес-вимогам або очікуванням кінцевого користувача (замовника) і
готова до розгортання.
Мета: Підтвердження відповідності системи вимогам замовника та її
готовності до релізу.
Учасники: Тестування проводилося внутрішніми тестувальниками, які
виступали в ролі потенційних користувачів. У реальних проектах це можуть бути
представники замовника або фокус-групи.
Сценарії: Використовувались реальні сценарії використання гри, що
відображають типову поведінку гравця. Оцінювалась не лише коректність роботи,
а й загальне враження від гри, її зручність та захопливість.
Критерії приймання:
1 Всі основні ігрові механіки працюють без збоїв.
2 Продуктивність відповідає встановленим вимогам (наприклад,
мінімальний FPS).
3 Інтерфейс інтуїтивно зрозумілий та зручний у використанні.
4 Відсутність критичних та блокуючих дефектів.
Зворотний зв'язок: Збирався детальний зворотний зв'язок щодо зручності,
балансу, можливих покращень.
Результати: За результатами приймального тестування було підтверджено,
що розроблена RTS-гра в цілому відповідає заявленим вимогам та готова до
подальшого впровадження/випуску. Було сформовано перелік побажань та
дрібних покращень для майбутніх оновлень.
Таблиця 3.4
Тест-кейси приймального тестування
№ Тест- Опис Передумови Кроки для Очікуваний Результат
кейса відтворення результат
Продовження таблиці 3.4
72
ЧДТУ. 252169-019 ПЗ
1 Запуск Гра 1. Запустити гру. 2. Гра повинна Пройшов
нової гри встановле Обрати "Нова гра". успішно
та перший на та 3. Обрати фракцію. запуститись, усі
бій готова до 4. Провести перший елементи
запуску. бій. інтерфейсу бути
на місці,
керування
юнітами –
інтуїтивним, а
бій –
зрозумілим.
2 Будівницт Запущена 1. Тренувати Усі будівлі Пройшов
во базових нова гра. Worker. 2. повинні успішно
споруд та Побудувати Barrack збудуватися,
збір та StorageBuilding. ресурси
ресурсів 3. Відправити коректно
Worker збирати додаватися до
ресурси. сховища, процес
збору ресурсів –
зрозумілий.
3 Тренуванн Barrack 1. Тренувати різні Юніти Пройшов
я юнітів та збудовано, типи юнітів у повинні
формуван достатньо Barrack. 2. коректно
ня армії ресурсів. Сформувати групу тренуватися,
юнітів. 3. об'єднуватися
Перемістити групу. в групи та
переміщатися
як єдине ціле.
Продовження таблиці 3.4
73
ЧДТУ. 252169-019 ПЗ
4 Перевірка Запущена 1. Спостерігати за Міні-карта Пройшов
функціона гра з міні-картою під час повинна
льності розвідани переміщення коректно
міні-карти ми та юнітів. 2. відображати
нерозвідан Спробувати ігровий світ та
ими клікнути на міні- рух юнітів, а
областями. карті для клік на ній –
переміщення переміщати
камери. камеру.
3.3 Приклади впровадженого програмного комплексу
Розглянемо покроковий процес для користувача, який хоче встановити та
виконати JAR-файл, який розташований на GitHub:
1 Завантаження JAR-файлу:
Зайдіть на сторінку репозиторію на GitHub.
Завантажте JAR-файл та src-файл, який вам потрібен.
2 Відкриття командного рядка (для Windows):
У вас має бути встановлене програмне забезпечення для роботи з
командним рядком, таке як Command Prompt / PowerShell на Windows.
Перехід до каталогу, де ви хочете зберегти JAR-файл:
3 Збережіть jar-file де ви хочете, або використовуйте команду cd для зміни
поточного каталогу.
cd шлях/до/вашого/каталогу
4 Завантаження JAR-файлу через командний рядок:
Використовуйте команду о Invoke-WebRequest (на Windows).
Invoke-WebRequest -Uri https://github.com/ваш_юзернейм/ваш_репозиторій/
/ваш_файл.jar -OutFile ваш_файл.jar
5 Запуск JAR-файлу:
Використайте команду java -jar, щоб запустити JAR-файл.
java -jar ваш_файл.jar
74
ЧДТУ. 252169-019 ПЗ
Зауважте, що для запуску Java-програми повинен бути встановлений Java
Runtime Environment (JRE) на вашому комп'ютері.
Перевірка виконання:
Переконайтеся, що гра або програма запустилася коректно і ви можете
користуватися нею.
Зазначте, що ці кроки припускають, що у користувача вже встановлено
програмне забезпечення для роботи з командним рядком (термінал чи командний
рядок) і Java Runtime Environment (JRE) для виконання JAR-файлів.
75
ЧДТУ. 252169-019 ПЗ
ВИСНОВКИ ДО ТРЕТЬОГО РОЗДІЛУ
У даному розділі було послідовно представлено повний цикл розробки
програмного комплексу RTS-гри, починаючи від архітектурних рішень до
всебічного тестування.
Обґрунтовано вибір мови Java, IDE IntelliJ IDEA та бібліотек AWT/Swing,
що забезпечило кросплатформеність, модульність та високу продуктивність
системи (включно з реалізацією алгоритму A* для навігації). Детально описано
функціональну та логічну схеми, що відображають взаємодію ключових ігрових
модулів, таких як ігровий рушій, бойова система та штучний інтелект. Відсутність
централізованої СУБД обґрунтована сесійним характером гри. Розроблений
користувацький інтерфейс забезпечує інтуїтивну взаємодію з ігровим світом.
Проведено комплексне тестування, що включало:
Аналіз якості коду (SonarLint): Виявлення та усунення потенційних проблем
на етапі розробки.
Модульне тестування: Перевірка коректності функціонування окремих
компонентів.
Інтеграційне тестування: Забезпечення коректної взаємодії між модулями.
Системне тестування: Верифікація відповідності всім функціональним та
нефункціональним вимогам.
Приймальне тестування: Підтвердження готовності продукту до
розгортання та відповідності очікуванням користувача.
Результати тестування підтвердили високу якість, стабільність та
функціональність розробленого програмного забезпечення, що забезпечує міцну
основу для його подальшого впровадження.
76
ЧДТУ. 252169-019 ПЗ
ВИСНОВКИ
У процесі роботи над проектом, вдосконалив та поглибив свої знання в
області розробки програмного забезпечення, освоїв нові інструменти та техніки,
що покращило мої навички у галузі декстопного програмування та архітектурного
проектування.
У процесі аналізу вимог до ПЗ визначено ключові функціональні та
нефункціональні вимоги. Спроектовано основні взаємодії з системою та
розглянуто основні сценарії використання.
У розділі моделювання та конструювання була розроблена архітектура.
Вона включає класи та компоненти, представлені для файлів та директорій.
Використано запозичений з іншої мови програмування паттерн проектування,
такий як Module для забезпечення в підтримці, розширенні і вдосконаленні коду.
Загальна ідея модульності полягає в тому, щоб розділити програмний код на
компоненти (модулі), які можна використовувати незалежно один від одного.
Тестування було проведено за допомогою фреймворку junit. Обрано його
через високу ефективність, гнучкість та можливість паралельного виконання
тестів. Тестування охопило різні аспекти функціональності, забезпечивши
стабільність та надійність програмного забезпечення.
Також за допомогою SonarLint було проаналізовано весь проект. При цьому
аналізі вдалося ідентифікувати різні види аномалій, такі як потенційні помилки в
коді, проблеми з безпекою та стильові конфлікти.
У розділі впровадження були детально описані кроки для розгортання ПЗ.
Це включало встановлення, зберігання та виконання JAR-file та необхідних для
нього інструментів. Документовано командні аргументи для легкості розгортання
та налаштування.
Майбутній розвиток ПЗ може включати розширення функціональності для
підтримки нових операцій та покращення ефективності роботи. Інтеграція з
іншими системами та підтримка нових типів файлів можуть стати напрямками
подальшого розвитку. Постійна оптимізація та удосконалення можуть допомогти
вдосконалюватися та відповідати зростаючим вимогам.
77
ЧДТУ. 252169-019 ПЗ
Основною ідеєю буде розширення можливостей роботи з файлами через
мережу. Це може включати в себе можливість зчитування та запису файлів на
віддалених серверах, спільний доступ до файлових ресурсів для різних
користувачів та роботу з файлами через інтернет що забезпечить
мультиплеєрність.
Створення доступу до мережі відкриває широкі перспективи для розробки
клієнтських та серверних компонентів, взаємодії між різними пристроями та
впровадження додаткових функціональних можливостей для забезпечення
ефективного та зручного користування.
78
ЧДТУ. 252169-019 ПЗ
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ
1 Michael Moore. Basics of Game Design. CRC Press, 2016. 400 p. [Література]
2 Mark J. P. Wolf. Encyclopedia of Video Games, 2012. 763 p. [Література]
3 RTS.Media [Електронний ресурс] – https://lub.fandom.com/ru/wiki/RTS.Media
4 IntelliJ IDEA [Електронний ресурс] – https://uk.wikipedia.org /wiki/IntelliJ
_IDEA
5 Swing [Електронний ресурс] https://java.fandom.com/wiki/Swing
6 AWT [Електронний ресурс] https://uk.wikipedia.org/wiki/AbstractWindow_
Toolkit
7 Age of Empires [Електронний ресурс] https://ageofempires.fandom.
com/wiki/Taunts
8 StarCraft II (Blizzard Entertainment) [Електронний ресурс]
https://starcraft2.blizzard.com/ru-ru/
9 Command & Conquer: Red Alert 2 (Electronic Arts) [Електронний ресурс]
https://ru.wikipedia.org/wiki/Command_%26_Conquer:_Red_Alert_2
10 Warcraft III: Reforged (Blizzard Entertainment) [Електронний ресурс]
https://warcraft3.blizzard.com/
11 Total War: Three Kingdoms (Creative Assembly) [Електронний ресурс]
https://en.wikipedia.org/wiki/Total_War:_Three_Kingdoms
12 Business Process Model and Notation [ Електронний ресурс] –
https://en.wikipedia.org/wiki/Business_Process_Model_and_Notation.
13 Патерн модуль (Module Pattern) [Електронний ресурс]
https://uk.wikipedia.org/wiki/Модуль_(шаблон_проєктування)
14 UML (Unified Modeling Language) [Електронний ресурс]
https://ru.wikipedia.org/wiki/UML
15 Графічний інтерфейс користувача [Електронний ресурс]
https://ru.wikipedia.org/wiki/Графический_интерфейс_пользователя
16 Алгоритм пошуку А* [Електронний ресурс] https://ru.wikipedia.org/wiki/A*
17 SonarLint [Електронний ресурс] https://docs.sonarsource.com/sonarlint/vs-
code/getting-started/requirements/
79
ЧДТУ. 252169-019 ПЗ
18 Java Code Conventions [Електронний ресурс]
https://www.oracle.com/technetwork/java/codeconventions-150003.pdf
19 JRE [Електронний ресурс] https://www.java.com/ru/download/manual.jsp
20 Junit [Електронний ресурс] https://ru.wikipedia.org/wiki/JUnit
21 Java [Електронний ресурс] https://www.java.com/
80
ДОДАТОК А
ЗАТВЕРДЖЕНО:
Зав. кафедрою ПЗАС, професор
_________________ Голуб С.В.
„____” ______________ 2025 р.
Програмне забезпечення гри в жанрі Real-Time Strategy
Специфікація
482 ЧДТУ. 252169-019
Листів 1
Розробник ________________ Татаровський А.В.
Керівник ________________ Немов Р.Г.
Черкаси 2025
81
482 ЧДТУ. 252169-019 2
Позначення Найменування Примітки
482 ЧДТУ. 252169 12 01 Текст програми
482 ЧДТУ. 252169 34 01 Інструкція користувачеві
482 ЧДТУ. 252169 90 01 Графічні матеріали
82
ДОДАТОК Б
Програмне забезпечення гри в жанрі Real-Time Strategy
Текст програми
482 ЧДТУ. 252169 12 01
Листів 31
Розробник ________________ Татаровський А.В.
Черкаси 2025
83
482 ЧДТУ. 252169 12 01 2
Файл GameDisplay.java
package gui;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.BoundedRangeModel;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.event.ChangeListener;
import configuration.EntityConfiguration;
import configuration.GameConfiguration;
import configuration.PositionConfiguration;
import engine.Camera;
import engine.Entity;
import engine.Faction;
import engine.entity.building.AttackBuilding;
import engine.entity.building.PopulationBuilding;
import engine.entity.building.ProductionBuilding;
import engine.entity.building.SiteConstruction;
import engine.entity.building.StorageBuilding;
import engine.entity.unit.Unit;
import engine.entity.unit.Fighter;
import engine.entity.unit.Worker;
import engine.manager.EntitiesManager;
import engine.manager.GameBuilder;
import engine.manager.GraphicsManager;
import engine.map.Fog;
import engine.map.Map;
import engine.map.Minimap;
import engine.math.SelectionRect;
import factionConfiguration.ForFighter;
import factionConfiguration.ForUpgrade;
import factionConfiguration.ForWorker;
import factionConfiguration.Race;
import engine.Mouse;
import engine.Position;
import engine.Ressource;
public class GameDisplay extends JPanel
{
private static final long serialVersionUID = 1L;
84
482 ЧДТУ. 252169 12 01 3
//щоб представляти всю стратегію гри, потрібно надрукувати кожен стан
private PaintStrategyGame paintStrategyGame = null;
private PaintStrategyMainMenu paintStrategyMainMenu = null;
private PaintStrategyPauseMenu paintStrategyPauseMenu = null;
private PaintStrategyVictoryScreen paintStrategyVictoryScreen = null;
private Minimap minimap;
private Map map;
private Fog fog;
private Camera camera;
private Mouse mouse;
//Вибір куди йти і де будувати
private SelectionRect selectionRectangle;
private EntitiesManager manager;
//state of the game
private int state;
private int oldState;
//for Main menuGui
private JComboBox<String> boxPlayer1;
private JComboBox<String> boxPlayer2;
private String [] races = {"Royaume"};
private JComboBox<String>boxMoney;
private JComboBox<String>boxPopulation;
private String []money = {"" + GameConfiguration.LOW_MONEY, "" +
GameConfiguration.MEDIUM_MONEY, "" + GameConfiguration.HIGH_MONEY};
private String []pop = {"" + GameConfiguration.LOW_POP, "" +
GameConfiguration.MEDIUM_POP, "" + GameConfiguration.HIGH_POP};
//for select map
private JRadioButton radioButton1;
private JRadioButton radioButton2;
private JRadioButton radioButton3;
private ButtonGroup groupButton;
//unit state
private JRadioButton agressifState;
private JRadioButton defensifState;
private JRadioButton passifState;
private ButtonGroup stateGroupButton;
//print the selected map
private JLabel labelMap;
private ImageIcon map1;
//button
private JButton constructionButton = new JButton(new
PrintConstruction("construction"));
//panel of game
private JPanel mainMenuPanel;
private JPanel gamePanel;
private JPanel pauseMenuPanel;
private JPanel loosePanel;
private JPanel winPanel = null
85
482 ЧДТУ. 252169 12 01 4
private JPanel descriptionPanel;
private JPanel ressourceInfoPanel;
private JPanel minimapPanel;
private JLabel populationLabel;
private JLabel moneyLabel;
private JLabel ageLabel;
private JTextArea currentProductionLabel = new JTextArea();
private JLabel timeLabel;
private JTextArea unitStatistiquesLabel = new JTextArea();
private JTextArea buildingStatistiquesLabel = new JTextArea();
private JTextArea ressourceStatistiquesLabel = new JTextArea();
private JTextArea workerRessourceLabel = new JTextArea();
private GraphicsManager graphicsManager;
private StatEntityContainer statEntityContainer= new StatEntityContainer();
//Для вибору мапи, але потрібно доробити ще мапи
private int selectedMap = 1;
//Для таймера
private float time;
private int startingMoney;
private int maxPopulation;
public GameDisplay(Camera camera, EntitiesManager manager, Mouse mouse,
SelectionRect selectionRectangle, GraphicsManager graphicsManager)
{
this.graphicsManager = graphicsManager;
this.camera = camera;
this.manager = manager;
this.mouse = mouse;
this.selectionRectangle = selectionRectangle;
this.state = GameConfiguration.INMENU;
this.oldState = this.state;
this.setLayout(new GridLayout(1,1));
this.setOpaque(false);
this.maxPopulation = 0;
this.startingMoney = 0;
pauseMenuPanel = createPauseMenuPanel();
pauseMenuPanel.setVisible(false);
mainMenuPanel = createMainMenuPanel();
mainMenuPanel.setVisible(true);
currentProductionLabel.setEditable(false);
unitStatistiquesLabel.setEditable(false);
buildingStatistiquesLabel.setEditable(false);
ressourceStatistiquesLabel.setEditable(false);
workerRessourceLabel.setEditable(false);
constructionButton.setOpaque(false);
currentProductionLabel.setOpaque(false);
unitStatistiquesLabel.setOpaque(false);
buildingStatistiquesLabel.setOpaque(false);
ressourceStatistiquesLabel.setOpaque(false);
workerRessourceLabel.setOpaque(false);
this.add(mainMenuPanel);
public JPanel getMainPanel()
{
return this;
86
482 ЧДТУ. 252169 12 01 5
}
private JPanel createLoosePanel() {
JPanel panel = new JPanel(new GridLayout(1, 3));
GridLayout gridLayout = new GridLayout(11,1);
JPanel panelBis = new JPanel(gridLayout);
panel.add(new JLabel());
int gridPlacement = gridLayout.getColumns() * gridLayout.getRows();
for(int i = 0; i < gridPlacement; i++) {
if(i == PositionConfiguration.LOOSE_BUTTON_PANEL) {
panelBis.add(new JButton(new BackToMenuAfterVictory("back to
Menu")));
}
else if(i == PositionConfiguration.LOOSE_TEXT_PANEL) {
JTextArea area = new JTextArea();
area.setText(" Your faction lost\n"
+ " game over\n"
+ " you are looser");
area.setEditable(false);
area.setOpaque(false);
panelBis.add(area);
}
else {
panelBis.add(new JLabel());
}
}
panel.add(panelBis);
panel.add(new JLabel());
panelBis.setOpaque(false);
panel.setOpaque(false);
return panel;
}
private JPanel createWinPanel() {
JPanel panel = new JPanel(new GridLayout(1, 3));
GridLayout gridLayout = new GridLayout(11,1);
JPanel panelBis = new JPanel(gridLayout);
panel.add(new JLabel());
int gridPlacement = gridLayout.getColumns() * gridLayout.getRows();
for(int i = 0; i < gridPlacement; i++) {
if(i == PositionConfiguration.WIN_BUTTON_PANEL) {
panelBis.add(new JButton(new BackToMenuAfterVictory("Back to
Menu")));
}
else if(i == PositionConfiguration.WIN_TEXT_PANEL) {
JTextArea area = new JTextArea();
area.setText(" Your faction wins\n"
+ " The opponent is defeated\n"
+ " you are better");
area.setEditable(false);
area.setOpaque(false);
panelBis.add(area);
}
else {
87
482 ЧДТУ. 252169 12 01 6
panelBis.add(new JLabel());
}
}
panel.add(panelBis);
panel.add(new JLabel());
panelBis.setOpaque(false);
panel.setOpaque(false);
return panel;
}
private JPanel createMainMenuPanel()
{
JPanel panel = new JPanel(new GridLayout(0,3));
panel.add(createMainMenuCenterPanel());
panel.add(createMainMenuRightPanel());
panel.setOpaque(false);
return panel;
}
private JPanel createMainMenuCenterPanel()
{
GridLayout gridLayout = new GridLayout(10,1);
JPanel panel = new JPanel(gridLayout);
int gridPlacement = gridLayout.getColumns() * gridLayout.getRows();
for(int i = 0; i < gridPlacement; i++)
{
if(i == PositionConfiguration.J1_BUTTON_PANEL)
{
JPanel panel2 = new JPanel(new GridLayout(2,0));
JLabel p1 = new JLabel("Player 1");
p1.setOpaque(false);
panel2.add(p1);
boxPlayer1 = new JComboBox<String>(races);
boxPlayer1.setOpaque(false);
panel2.setOpaque(false);
panel2.add(boxPlayer1);
panel.add(panel2);
}
else if(i == PositionConfiguration.J2_BUTTON_PANEL)
{
JPanel panel2 = new JPanel(new GridLayout(2,0));
JLabel p2 = new JLabel("Player 2");
p2.setOpaque(false);
panel2.add(p2);
boxPlayer2 = new JComboBox<String>(races);
boxPlayer2.setOpaque(false);
boxPlayer2.setSelectedIndex(0);
panel2.setOpaque(false);
panel2.add(boxPlayer2);
panel.add(panel2);
}
else if(i == PositionConfiguration.EXIT_BUTTON_PANEL)
{
JButton button = new JButton(new ExitGameButton("EXIT"));
panel.add(button);
}
else
{
JLabel label = new JLabel();
88
482 ЧДТУ. 252169 12 01 7
label.setVisible(false);
panel.add(label);
}
}
panel.setOpaque(false);
return panel;
}
private JPanel createMainMenuRightPanel(){
groupButton = new ButtonGroup();
GridLayout gridLayout = new GridLayout(2,1);
JPanel panel = new JPanel(gridLayout);
int gridPlacement = gridLayout.getColumns() * gridLayout.getRows();
GridLayout gridLayout2 = new GridLayout(6,2);
JPanel panel2 = new JPanel(gridLayout2);
int gridPlacement2 = gridLayout2.getColumns() *
gridLayout2.getRows();
for(int j = 0; j < gridPlacement2; j++){
if(j == PositionConfiguration.MONEY_COMBO_PANEL) {
JPanel panel3 = new JPanel(new GridLayout(2,0));
JLabel p2 = new JLabel("Gold");
p2.setOpaque(false);
panel3.add(p2);
boxMoney = new JComboBox<String>(money);
boxMoney.setOpaque(false);
boxMoney.setSelectedIndex(1);
panel3.setOpaque(false);
panel3.add(boxMoney);
panel2.add(panel3);
}
else if(j == PositionConfiguration.POPULATION_COMBO_PANEL) {
JPanel panel3 = new JPanel(new GridLayout(2,0));
JLabel p2 = new JLabel("Population");
p2.setOpaque(false);
panel3.add(p2);
boxPopulation = new JComboBox<String>(pop);
boxPopulation.setOpaque(false);
boxPopulation.setSelectedIndex(1);
panel3.setOpaque(false);
panel3.add(boxPopulation);
panel2.add(panel3);
}
else if(j == PositionConfiguration.START_BUTTON_PANEL){
panel2.add(new JButton(new LaunchGame("START GAME")));
}
else{
JLabel label = new JLabel();
label.setVisible(false);
panel2.add(label);
}
}
panel2.setOpaque(false);
panel.add(panel2);
panel.setOpaque(false);
return panel;
}
private JPanel createGamePanel()
{
89
482 ЧДТУ. 252169 12 01 8
GridLayout gridLayout = new GridLayout(4,3);
JPanel panel = new JPanel(gridLayout);
panel.setOpaque(false);
int gridPlacement = gridLayout.getColumns() * gridLayout.getRows();
for(int i = 0; i < gridPlacement; i++)
{
if(i == PositionConfiguration.RESSOURCE_INFO_PANEL)
{
panel.add(createRessourceInfo());
}
else if(i == PositionConfiguration.GAME_MENU_PANEL)
{
panel.add(createGameMenuPanel());
}
else if(i == PositionConfiguration.DESCRIPTION_PANEL)
{
panel.add(createDescriptionPanel());
}
else if(i == PositionConfiguration.MINIMAP_PANEL) {
panel.add(createMinimapPanel());
}
else{
JLabel label = new JLabel();
panel.add(label);
}
}
return panel;
}
private JPanel createGameMenuPanel()
{
GridLayout gridLayout = new GridLayout(6,5);
JPanel panel = new JPanel(gridLayout);
panel.setOpaque(false);
int gridPlacement = gridLayout.getColumns() * gridLayout.getRows();
for(int i = 0; i < gridPlacement; i++) {
if(i == PositionConfiguration.GAME_PAUSE_PANEL) {
panel.add(new JButton(new PauseGameMenu("MENU")));
}
else {
panel.add(new JLabel());
}
}
return panel;
}
private JPanel createDescriptionPanel()
{
descriptionPanel = new JPanel(new GridLayout(2, 2));
descriptionPanel.setOpaque(false);
setDescriptionPanelStandard();
return descriptionPanel;
}
public void setDescriptionPanelForWorker(Worker worker)
{
descriptionPanel.removeAll();
90
482 ЧДТУ. 252169 12 01 9
descriptionPanel.setLayout(new GridLayout(2, 1));
descriptionPanel.add(constructionButton);
statEntityContainer.setForWorker(worker);
unitStatistiquesLabel.setText("\nHP : " + worker.getHp() +
"\nDamage : " + worker.getDamage() +
"\nHP : " + worker.getArmor());
workerRessourceLabel.setText(" " + worker.getDescription() +
"\n Ressources : " + worker.getQuantityRessource());
JPanel panel = new JPanel(new GridLayout(1, 2));
panel.setOpaque(false);
panel.add(workerRessourceLabel);
panel.add(unitStatistiquesLabel);
descriptionPanel.add(panel);
descriptionPanel.validate();
}
//Для зданія
private void setDescriptionPanelForConstruction()
{
descriptionPanel.removeAll();
descriptionPanel.setLayout(new GridLayout(5, 2));
Faction faction =
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION);
JButton buttonForge = new JButton(new ConstructBuilding("Smithy",
EntityConfiguration.FORGE,
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getProductionBuildings().get(EntityConfiguration.FORGE).getCost()));
buttonForge.setFocusable(false);
if(faction.getAge() <= 1) {
buttonForge.setEnabled(false);
buttonForge.setToolTipText("Cost : " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.FORGE).getCost(
) + ",required age : " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.FORGE).getAge()
);
}
else {
buttonForge.setToolTipText("Cost: " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.FORGE).getCost(
));
}
JButton buttonPop = new JButton(new ConstructBuilding("House",
EntityConfiguration.HOUSE,
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getPopulationBuildings().get(EntityConfiguration.HOUSE).getCost()));
buttonPop.setFocusable(false);
buttonPop.setToolTipText(("Cost : " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.BARRACK).getCos
t()));
JButton buttonBarrack = new JButton(new ConstructBuilding("Barn",
EntityConfiguration.BARRACK,
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getProductionBuildings().get(EntityConfiguration.BARRACK).getCost()));
buttonBarrack.setFocusable(false);
buttonBarrack.setToolTipText("Cost: " +
91
482 ЧДТУ. 252169 12 01 10
faction.getRace().getProductionBuildings().get(EntityConfiguration.BARRACK).getCos
t());
JButton buttonStable = new JButton(new ConstructBuilding("Stable",
EntityConfiguration.STABLE,
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getProductionBuildings().get(EntityConfiguration.STABLE).getCost()));
buttonStable.setFocusable(false);
if(faction.getAge() <= 1) {
buttonStable.setEnabled(false);
buttonStable.setToolTipText("Cost : " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.STABLE).getCost
() + ",required age: " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.STABLE).getAge(
));
}
else {
buttonStable.setToolTipText("Cost : " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.STABLE).getCost
());
}
JButton buttonHq = new JButton(new ConstructBuilding("HeadHouse",
EntityConfiguration.HQ,
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getProductionBuildings().get(EntityConfiguration.HQ).getCost()));
buttonHq.setFocusable(false);
if(faction.getAge() <= 1) {
buttonHq.setEnabled(false);
buttonHq.setToolTipText("Cost : " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.HQ).getCost() +
",required age : " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.HQ).getAge());
}
else {
buttonHq.setToolTipText("Cost: " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.HQ).getCost());
}
JButton buttonStockage = new JButton(new ConstructBuilding("Storage",
EntityConfiguration.STORAGE,
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getStorageBuildings().get(EntityConfiguration.STORAGE).getCost()));
buttonStockage.setFocusable(false);
buttonStockage.setToolTipText("Cost : " +
faction.getRace().getStorageBuildings().get(EntityConfiguration.STORAGE).getCost()
);
JButton buttonCastle = new JButton(new ConstructBuilding("Castle",
EntityConfiguration.CASTLE,
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getProductionBuildings().get(EntityConfiguration.CASTLE).getCost()));
buttonCastle.setFocusable(false);
if(faction.getAge() <= 2) {
buttonCastle.setEnabled(false);
buttonCastle.setToolTipText("Cost : " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.CASTLE).getCost
() + ",required age : " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.CASTLE).getAge(
));
}
else {
buttonCastle.setToolTipText("Cost: " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.CASTLE).getCost
92
482 ЧДТУ. 252169 12 01 11
());
}
JButton buttonArchery = new JButton(new ConstructBuilding("Archer",
EntityConfiguration.ARCHERY,
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getProductionBuildings().get(EntityConfiguration.ARCHERY).getCost()));
buttonArchery.setFocusable(false);
if(faction.getAge() <= 1) {
buttonArchery.setEnabled(false);
buttonArchery.setToolTipText("Cost : " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.ARCHERY).getCos
t() + ",required age : " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.ARCHERY).getAge
());
}
else {
buttonArchery.setToolTipText("Cost : " +
faction.getRace().getProductionBuildings().get(EntityConfiguration.ARCHERY).getCos
t());
}
JButton buttonTower = new JButton(new ConstructBuilding("Tower",
EntityConfiguration.TOWER,
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getAttackBuildings().get(EntityConfiguration.TOWER).getCost()));
buttonTower.setFocusable(false);
buttonTower.setToolTipText("Cost : " +
faction.getRace().getAttackBuildings().get(EntityConfiguration.TOWER).getCost());
JTextArea area = new JTextArea();
area.setEditable(false);
area.setOpaque(false);
area.setText("\n list of instructions");
descriptionPanel.add(area);
descriptionPanel.add(new JLabel());
descriptionPanel.add(new JLabel());
descriptionPanel.add(buttonPop);
descriptionPanel.add(buttonHq);
descriptionPanel.add(buttonStockage);
descriptionPanel.add(buttonBarrack);
descriptionPanel.add(buttonArchery);
descriptionPanel.add(buttonStable);
descriptionPanel.add(buttonCastle);
descriptionPanel.add(buttonForge);
descriptionPanel.add(buttonTower);
descriptionPanel.validate();
}
// AGRESSIF, DEFENSIF AND PASSIF
public void setDescriptionPanelForUnit(Unit unit, List<Fighter>fighters)
{
descriptionPanel.removeAll();
descriptionPanel.setLayout(new GridLayout(1, 3));
stateGroupButton = new ButtonGroup();
agressifState = new JRadioButton(new ChangeState("AGRESSIF",
EntityConfiguration.AGRESSIF_STATE, fighters));
defensifState = new JRadioButton(new ChangeState("DEFENSIF",
EntityConfiguration.DEFENSIF_STATE, fighters));
passifState = new JRadioButton(new ChangeState("PASSIF",
EntityConfiguration.PASSIF_STATE, fighters));
93
482 ЧДТУ. 252169 12 01 12
agressifState.setOpaque(false);
defensifState.setOpaque(false);
passifState.setOpaque(false);
agressifState.setFocusable(false);
defensifState.setFocusable(false);
passifState.setFocusable(false);
stateGroupButton.add(agressifState);
stateGroupButton.add(defensifState);
stateGroupButton.add(passifState);
Fighter fighter2 = null;
if(fighters.contains(unit)) {
fighter2 = fighters.get(fighters.indexOf(unit));
}
if(fighter2 != null) {
if(fighter2.getState() == EntityConfiguration.AGRESSIF_STATE) {
agressifState.setSelected(true);
}
else if(fighter2.getState() == EntityConfiguration.DEFENSIF_STATE) {
defensifState.setSelected(true);
}
else if(fighter2.getState() == EntityConfiguration.PASSIF_STATE) {
passifState.setSelected(true);
}
}
statEntityContainer.setForUnit(unit);
unitStatistiquesLabel.setText("\nHP : " + unit.getHp() +
"\nDamage : " + unit.getDamage() +
"\nHP : " + unit.getArmor());
JPanel pForButton = new JPanel(new GridLayout(3,1));
pForButton.setOpaque(false);
pForButton.add(agressifState);
pForButton.add(defensifState);
pForButton.add(passifState);
descriptionPanel.add(pForButton);
descriptionPanel.add(new JLabel(unit.getDescription()));
descriptionPanel.add(unitStatistiquesLabel);
descriptionPanel.validate();
}
//Для тавера
public void setDescriptionPanelForBuilding(AttackBuilding building)
{
descriptionPanel.removeAll();
descriptionPanel.setLayout(new FlowLayout());
statEntityContainer.setForAttackBuilding(building);
buildingStatistiquesLabel.setText("\n\n" + building.getDescription() + ",
Attack enemy units in the vicinity\nHP : " + building.getHp());
descriptionPanel.add(buildingStatistiquesLabel);
descriptionPanel.validate();
}
public void setDescriptionPanelForBuilding(StorageBuilding building)
{
descriptionPanel.removeAll();
descriptionPanel.setLayout(new FlowLayout());
94
482 ЧДТУ. 252169 12 01 13
statEntityContainer.setForStorageBuilding(building);
buildingStatistiquesLabel.setText("\n\n" + building.getDescription() + ",
allows you to place resources\nHP : " + building.getHp());
descriptionPanel.add(buildingStatistiquesLabel);
descriptionPanel.validate();
}
public void setDescriptionPanelForBuilding(PopulationBuilding building)
{
descriptionPanel.removeAll();
descriptionPanel.setLayout(new FlowLayout());
statEntityContainer.setForPopulationBuilding(building);
buildingStatistiquesLabel.setText("\n\n" + building.getDescription() + ",
Contains population\nHP : " + building.getHp());
descriptionPanel.add(buildingStatistiquesLabel);
descriptionPanel.validate();
}
public void setDescriptionPanelForBuilding(ProductionBuilding building,
List<Integer> searchingUpgrades)
{
descriptionPanel.removeAll();
descriptionPanel.setLayout(new GridLayout(3, 1));
statEntityContainer.setForProductionBuilding(building);
if(building.getFaction() == EntityConfiguration.PLAYER_FACTION) {
for(int i = 0; i < 2; i++) {
if(i == 0) {
buildingStatistiquesLabel.setText("\n " +
building.getDescription() + "\n HP : " + building.getHp());
descriptionPanel.add(buildingStatistiquesLabel);
}
else if(i == 1) {
if(building.getIsProducing()) {
int idProduction = building.getElementCount().get(0);
Race race =
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace();
ForFighter fighter =
race.getPatronFighters().get(idProduction);
ForUpgrade forgeUpgrade =
race.getForgeUpgrades().get(idProduction);
ForUpgrade hqUpgrade = race.getHQUpgrades().get(idProduction);
ForWorker worker = race.getPatronWorkers().get(idProduction);
if(fighter != null) {
currentProductionLabel.setText("\n Prod: " +
fighter.getDescription()+ ", Time left : " + (int)building.getTimer() + ", file
d'attente : " + (building.getElementCount().size()– 1));
}
else if(forgeUpgrade != null) {
currentProductionLabel.setText("\n Prod: " +
forgeUpgrade.getDescription()+ ", Time left : " + (int)building.getTimer() + ",
file d'attente : " + (building.getElementCount().size() – 1));
}
else if(hqUpgrade != null){
95
482 ЧДТУ. 252169 12 01 14
currentProductionLabel.setText("\n Prod: " +
hqUpgrade.getDescription()+ ", Time left : " + (int)building.getTimer() + ", file
d'attente : " + (building.getElementCount().size() – 1));
}
else if(worker != null) {
currentProductionLabel.setText("\n Prod: " +
worker.getDescription()+ ", Time left : " + (int)building.getTimer() + ", file
d'attente : " + (building.getElementCount().size() – 1));
}
}
else {
currentProductionLabel.setText("\n Nothing is produced");
}
descriptionPanel.add(currentProductionLabel);
}
}
GridLayout gridLayout = new GridLayout(4,2);
JPanel panel = new JPanel(gridLayout);
panel.setOpaque(false);
int caseLayoutCount = gridLayout.getColumns() * gridLayout.getRows();
int infoEnd = 1;
JButton button1 = new JButton(new UndoProduction("Remove production",
building));
button1.setFocusable(false);
panel.add(button1);
if(building.getId() == EntityConfiguration.FORGE) {
AbstractMap<Integer, ForUpgrade> upgradesAvailable =
building.getUpgrades();
AbstractMap<Integer, ForUpgrade> upgradesUse = new HashMap<Integer,
ForUpgrade>();
for(int key : upgradesAvailable.keySet()) {
upgradesUse.put(key, upgradesAvailable.get(key));
}
for(Integer id : searchingUpgrades) {
if(upgradesAvailable.containsKey(id)) {
upgradesUse.remove(id);
}
}
for(ForUpgrade upgrade : upgradesAvailable.values()) {
if(!upgradesUse.containsValue(upgrade)) {
panel.add(new JLabel());
}
else {
JButton button = new JButton(new BuildingProduction("" +
upgrade.getDescription(), upgrade.getId(), building ));
button.setFocusable(false);
button.setToolTipText("Cost : " + upgrade.getCost());
if(upgrade.getAge() >
this.manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACT
ION).getAge()) {
button.setEnabled(false);
}
panel.add(button);
}
infoEnd++;
}
96
482 ЧДТУ. 252169 12 01 15
}
else if(building.getId() == EntityConfiguration.HQ) {
String name =
manager.getFactionManager().getFactions().get(building.getFaction()).getRace().get
PatronWorkers().get(building.getProductionId()).getDescription();
AbstractMap<Integer, ForUpgrade> upgradesAvailable =
building.getUpgrades();
AbstractMap<Integer, ForUpgrade> upgradesUse = new HashMap<Integer,
ForUpgrade>();
JButton button = new JButton(new BuildingProduction("" + name,
building.getProductionId(), building ));
button.setFocusable(false);
button.setToolTipText("Cost : " +
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getPatronWorkers().get(building.getProductionId()).getCost());
infoEnd++;
panel.add(button);
for(int key : upgradesAvailable.keySet()) {
upgradesUse.put(key, upgradesAvailable.get(key));
}
for(Integer id : searchingUpgrades) {
if(upgradesAvailable.containsKey(id)) {
upgradesUse.remove(id);
}
}
for(ForUpgrade upgrade : upgradesAvailable.values()) {
if(!upgradesUse.containsValue(upgrade)) {
panel.add(new JLabel());
}
else {
button = new JButton(new BuildingProduction("" +
upgrade.getDescription(), upgrade.getId(), building ));
button.setFocusable(false);
button.setToolTipText("Cost : " + upgrade.getCost());
if(upgrade.getId() == EntityConfiguration.AGE_UPGRADE_2 &&
this.manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACT
ION).getAge() < 2) {
button.setEnabled(false);
}
panel.add(button);
}
infoEnd++;
}
}
else {
String name =
manager.getFactionManager().getFactions().get(building.getFaction()).getRace().get
PatronFighters().get(building.getProductionId()).getDescription();
JButton button = new JButton(new BuildingProduction("" + name,
building.getProductionId(), building ));
button.setFocusable(false);
button.setToolTipText("Cost : " +
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getPatronFighters().get(building.getProductionId()).getCost());
infoEnd++;
panel.add(button);
}
97
482 ЧДТУ. 252169 12 01 16
for(int i = infoEnd; i < caseLayoutCount; i++) {
panel.add(new JLabel());
}
descriptionPanel.add(panel);
}
else {
descriptionPanel.setLayout(new FlowLayout());
buildingStatistiquesLabel.setText("\n\n" + building.getDescription() +
", adverse production building\nHP : " + building.getHp());
descriptionPanel.add(buildingStatistiquesLabel);
}
descriptionPanel.validate();
}
//дескріп Для ресурсів
public void setDescriptionPanelForRessource(Ressource ressource)
{
descriptionPanel.removeAll();
descriptionPanel.setLayout(new FlowLayout());
statEntityContainer.setForRessource(ressource);
ressourceStatistiquesLabel.setText("\nRessources left : " +
ressource.getHp());
descriptionPanel.add(ressourceStatistiquesLabel);
descriptionPanel.validate();
}
public void setDescriptionPanelForSiteConstruction(SiteConstruction
siteConstruction) {
descriptionPanel.removeAll();
descriptionPanel.setLayout(new FlowLayout());
statEntityContainer.setForSiteConstruction(siteConstruction);
buildingStatistiquesLabel.setText("\n\nIt is a construction site of : " +
siteConstruction.getDescription() +
"\nHP : " + siteConstruction.getHp());
descriptionPanel.add(buildingStatistiquesLabel);
descriptionPanel.validate();
}
//По дефолту так:
public void setDescriptionPanelStandard()
{
descriptionPanel.removeAll();
descriptionPanel.setLayout(new FlowLayout());
JTextArea area = new JTextArea();
area.setEditable(false);
area.setOpaque(false);
area.setText("\n\nYour faction is : " +
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getName());
descriptionPanel.add(area);
descriptionPanel.validate();
}
//Зліва зверху
private JPanel createRessourceInfo()
98
482 ЧДТУ. 252169 12 01 17
{
JPanel panel = new JPanel(new GridLayout(5, 1));
ressourceInfoPanel = new JPanel(new GridLayout(2,5));
this.moneyLabel = new JLabel("GOLD:" +
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getMoneyCount());
this.moneyLabel.setForeground(Color.WHITE);
this.timeLabel = new JLabel("TIME:");
this.timeLabel.setForeground(Color.WHITE);
this.populationLabel = new JLabel("POPULATION:" +
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getPopulationCount());
this.populationLabel.setForeground(Color.WHITE);
this.ageLabel = new JLabel("AGE:" +
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getAge());
this.ageLabel.setForeground(Color.WHITE);
JLabel race = new JLabel("FACTION : " +
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace().getName());
race.setForeground(Color.WHITE);
ressourceInfoPanel.add(moneyLabel);
ressourceInfoPanel.add(timeLabel);
ressourceInfoPanel.add(populationLabel);
ressourceInfoPanel.add(ageLabel);
ressourceInfoPanel.add(race);
ressourceInfoPanel.setOpaque(false);
panel.add(ressourceInfoPanel);
panel.setOpaque(false);
return panel;
}
//Меню пауза
private JPanel createPauseMenuPanel()
{
JPanel panel = new JPanel();
JPanel panelBis = new JPanel();
GridLayout gridLayaout = new GridLayout(1,3);
panelBis.setLayout(new
GridLayout(PositionConfiguration.PAUSEMENUMAXINDEX,1));
for(int i = 1; i <= PositionConfiguration.PAUSEMENUMAXINDEX; i++)
{
switch(i)
{
case PositionConfiguration.BACKTOGAMEINDEX:
panelBis.add(new JButton(new UnpauseGameButton("RETURN TO
GAME")));
break;
case PositionConfiguration.LEAVEINDEX:
panelBis.add(new JButton(new GoToMainMenuFromPauseMenu("RETURN TO
MAIN MENU")));
break;
default:
panelBis.add(new JLabel());
break;
99
482 ЧДТУ. 252169 12 01 18
}
}
panel.setLayout(gridLayaout);
panel.add(new JLabel());
panel.add(panelBis);
panel.add(new JLabel());
panelBis.setOpaque(false);
panel.setOpaque(false);
return panel;
}
//Мінімап панель
public JPanel createMinimapPanel() {
minimapPanel = new JPanel();
minimapPanel.setOpaque(false);
return minimapPanel;
}
//Побудова, або коли не те місце
public void actualiseCurrentProdLabel(ProductionBuilding building) {
if(statEntityContainer.checkChangeForProductionBuilding(building)) {
if(building.getFaction() == EntityConfiguration.PLAYER_FACTION) {
buildingStatistiquesLabel.setText("\n " +
building.getDescription() + "\n HP : " + building.getHp());
if(building.getHp() <= 0) {
this.setDescriptionPanelStandard();
}
if(building.getIsProducing()) {
int idProduction = building.getElementCount().get(0);
Race race =
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getRace();
ForFighter fighter = race.getPatronFighters().get(idProduction);
ForUpgrade forgeUpgrade =
race.getForgeUpgrades().get(idProduction);
ForUpgrade hqUpgrade = race.getHQUpgrades().get(idProduction);
ForWorker worker = race.getPatronWorkers().get(idProduction);
if(fighter != null) {
currentProductionLabel.setText("\n Prod: " +
fighter.getDescription()+ ", time left : " + (int)building.getTimer() + ", queue :
" + (building.getElementCount().size()– 1));
}
else if(forgeUpgrade != null) {
currentProductionLabel.setText("\n Prod: " +
forgeUpgrade.getDescription()+ ", time left : " + (int)building.getTimer() + ",
queue : " + (building.getElementCount().size() – 1));
}
else if(hqUpgrade != null){
currentProductionLabel.setText("\n Prod: " +
hqUpgrade.getDescription()+ ", time left : " + (int)building.getTimer() + ", queue
: " + (building.getElementCount().size() – 1));
}
else if(worker != null) {
currentProductionLabel.setText("\n Prod: " +
worker.getDescription()+ ", time left : " + (int)building.getTimer() + ", queue :
" + (building.getElementCount().size() – 1));
}
}
else {
currentProductionLabel.setText("\n Nothing is produced");
100
482 ЧДТУ. 252169 12 01 19
}
}
else {
buildingStatistiquesLabel.setText("\n\n" + building.getDescription()
+ ", Unfavorable production possibilities\nHP : " + building.getHp());
descriptionPanel.add(buildingStatistiquesLabel);
}
}
}
public void actualiseStatistiquesBuilding(AttackBuilding building) {
if(statEntityContainer.checkChangeForAttackBuilding(building)) {
buildingStatistiquesLabel.setText("\n\n" + building.getDescription() +
", Attack enemy units in the vicinity\nHP : " + building.getHp());
}
if(building.getHp() <= 0) {
this.setDescriptionPanelStandard();
}
}
public void actualiseStatistiquesBuilding(StorageBuilding building) {
if(statEntityContainer.checkChangeForStorageBuilding(building)) {
buildingStatistiquesLabel.setText("\n\n" + building.getDescription() +
", allows you to place resources\nHP : " + building.getHp());
}
if(building.getHp() <= 0) {
this.setDescriptionPanelStandard();
}
}
public void actualiseStatistiquesBuilding(PopulationBuilding building) {
if(statEntityContainer.checkChangeForPopulationBuilding(building)) {
buildingStatistiquesLabel.setText("\n\n" + building.getDescription() +
", Contains population\nHP : " + building.getHp());
}
if(building.getHp() <= 0) {
this.setDescriptionPanelStandard();
}
}
public void actualiseStatistiquesRessource(Ressource ressource) {
if(statEntityContainer.checkChangeForRessource(ressource)) {
ressourceStatistiquesLabel.setText("\nResources left : " +
ressource.getHp());
}
if(ressource.getHp() <= 0) {
this.setDescriptionPanelStandard();
}
}
public void actualiseStatistiquesWorker(Worker worker) {
if(statEntityContainer.checkChangeForWorker(worker)) {
unitStatistiquesLabel.setText("\nHP : " + worker.getHp() +
"\nDamage : " + worker.getDamage() +
"\nHP : " + worker.getArmor());
workerRessourceLabel.setText(" " + worker.getDescription() +
"\n Resources : " + worker.getQuantityRessource());
statEntityContainer.setForWorker(worker);
}
}
public void actualiseStatistiquesFighter(Fighter fighter) {
if(statEntityContainer.checkChangeForFighter(fighter)) {
101
482 ЧДТУ. 252169 12 01 20
unitStatistiquesLabel.setText("\nHP : " + fighter.getHp() +
"\nDamage : " + fighter.getDamage() +
"\nHP : " + fighter.getArmor());
}
}
public void actualiseStatistiquesSiteConstruction(SiteConstruction
siteConstruction) {
if(statEntityContainer.checkChangeForSiteConstruction(siteConstruction)) {
buildingStatistiquesLabel.setText("\n\nThis is a construction site : " +
siteConstruction.getDescription() +
"\nHP : " + siteConstruction.getHp());
}
}
//Метод буде обновляти всю інфу що зверху, голда, популятіон, час і тд
public void update() {
if(state == GameConfiguration.INGAME){
int populationCount =
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getPopulationCount();
int maxPopulation =
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getMaxPopulation();
time += 1.0 / GameConfiguration.GAME_SPEED;
this.moneyLabel.setText("GOLD:" +
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getMoneyCount());
this.timeLabel.setText("TIME:" + (int)time);
this.populationLabel.setText("POPULATION:" + populationCount + " / " +
maxPopulation);
this.ageLabel.setText("AGE:" +
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
getAge());
if(this.manager.getSelectedProdBuilding() != null) {
ProductionBuilding prod = manager.getSelectedProdBuilding();
actualiseCurrentProdLabel(prod);
}
else if(this.manager.getSelectedAttackBuilding() != null) {
AttackBuilding attack = manager.getSelectedAttackBuilding();
actualiseStatistiquesBuilding(attack);
}
else if(this.manager.getSelectedStorageBuilding() != null) {
StorageBuilding storage = manager.getSelectedStorageBuilding();
actualiseStatistiquesBuilding(storage);
}
else if(this.manager.getSelectedPopulationBuilding() != null) {
PopulationBuilding popBuilding =
manager.getSelectedPopulationBuilding();
actualiseStatistiquesBuilding(popBuilding);
}
else if(this.manager.getSelectedRessource() != null) {
Ressource ressource = manager.getSelectedRessource();
actualiseStatistiquesRessource(ressource);
}
else if(this.manager.getSelectedSiteConstruction() != null) {
SiteConstruction sc = manager.getSelectedSiteConstruction();
actualiseStatistiquesSiteConstruction(sc);
}
else if(this.manager.getSelectedUnits().isEmpty() == false) {
if(this.manager.getSelectedWorkers().isEmpty() == false) {
102
482 ЧДТУ. 252169 12 01 21
actualiseStatistiquesWorker(this.manager.getSelectedWorkers().get(0));
}
else {
actualiseStatistiquesFighter(this.manager.getSelectedFighters().get(0));
}
}
if(this.statEntityContainer.getEntity() != null) {
Entity entity = statEntityContainer.getEntity();
if(entity.getHp() <= 0) {
statEntityContainer.setEntity(null);
this.setDescriptionPanelStandard();
}
else if(entity.getId() == EntityConfiguration.SITE_CONSTRUCTION &&
entity.getHp() >= entity.getHpMax()) {
statEntityContainer.setEntity(null);
this.setDescriptionPanelStandard();
}
}
if(manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTIO
N).isUpgradeAge()) {
if(this.manager.getSelectedProdBuilding() != null) {
List<Integer> searchingUpgrades =
manager.getFactionManager().getFactions().get(this.manager.getSelectedProdBuilding
().getFaction()).getSearchingUpgrades();
setDescriptionPanelForBuilding(this.manager.getSelectedProdBuilding(),
searchingUpgrades);
}
else if(this.manager.getSelectedWorkers().isEmpty() == false &&
this.manager.getSelectedFighters().isEmpty()) {
setDescriptionPanelForConstruction();
}
manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTION).
setUpgradeAge(false);
}
if(!GameConfiguration.debug_mod) {
List<Entity> entitie = manager.getPlayerEntities();
List<Entity> entities = new ArrayList<Entity>();
for(Entity entity : entitie) {
entities.add(entity);
}
List<Entity> botEntities = manager.getBotEntities();
fog.resetDynamicFog();
for(Entity entity : entities) {
Position p = entity.getPosition();
fog.clearFog(p.getX() – entity.getSightRange() / 3, p.getY() –
entity.getSightRange() / 3, entity.getSightRange(), entity,
manager.getDrawingList(), manager.getWaitingList(), manager.getRemoveList(),
botEntities);
}
fog.checkingBotTargetInFog(manager.getDrawingList(),
manager.getWaitingList(), manager.getRemoveList());
}
else {
List<Entity> entitie = manager.getDrawingList(
103
482 ЧДТУ. 252169 12 01 22
List<Entity> entities = new ArrayList<Entity>();
for(Entity entity : entitie) {
entities.add(entity);
}
for(Entity entity : entities) {
Position p = entity.getPosition();
fog.clearFog(p.getX() – entity.getSightRange() / 3, p.getY() –
entity.getSightRange() / 3, entity.getSightRange(), entity, null, null, null,
null);
}
}
if(manager.getPlayerWin()) {
oldState = state;
state = GameConfiguration.PLAYERWIN;
winPanel = createWinPanel();
manageState();
}
else if(manager.getBotWin()) {
oldState = state;
state = GameConfiguration.BOTWIN;
loosePanel = createLoosePanel();
manageState();
}
}
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(state == GameConfiguration.INGAME)
{
if(this.paintStrategyGame == null) {
minimap = new Minimap(minimapPanel);
paintStrategyGame = new
PaintStrategyGame(GameConfiguration.WINDOW_WIDTH, GameConfiguration.WINDOW_HEIGHT,
minimapPanel, minimap);
}
this.paintStrategyGame.paint(this.map, g, this.camera, graphicsManager);
List<Entity> entitie = manager.getDrawingList();
List<Entity> entities = new ArrayList<Entity>();
for(Entity entity : entitie) {
entities.add(entity);
}
List<Unit> units = manager.getSelectedUnits();
Entity building = null;
ProductionBuilding prodBuilding = null;
Entity ressource = null;
if(manager.getSelectedAttackBuilding() != null) {
building = manager.getSelectedAttackBuilding();
}
else if(manager.getSelectedProdBuilding() != null) {
prodBuilding = manager.getSelectedProdBuilding();
}
else if(manager.getSelectedStorageBuilding() != null) {
building = manager.getSelectedStorageBuilding();
104
482 ЧДТУ. 252169 12 01 23
}
else if(manager.getSelectedSiteConstruction() != null) {
building = manager.getSelectedSiteConstruction();
}
else if(manager.getSelectedPopulationBuilding() != null) {
building = manager.getSelectedPopulationBuilding();
}
if(manager.getSelectedRessource() != null) {
ressource = manager.getSelectedRessource();
}
for(Entity entity : entities) {
this.paintStrategyGame.paint(entity, g, camera);
}
for(Unit unit : units) {
this.paintStrategyGame.paintRectSelectionUnit(unit, g, camera);
}
if(building != null) {
this.paintStrategyGame.paintSelectionRectBuilding(building, g,
camera);
}
else if(ressource != null) {
this.paintStrategyGame.paintSelectionRectRessource(ressource, g,
camera);
}
else if(prodBuilding != null) {
this.paintStrategyGame.paintSelectionRectBuilding(prodBuilding, g,
camera);
this.paintStrategyGame.paintRallyPoint(prodBuilding, g, camera);
}
this.paintStrategyGame.paint(fog, g, camera);
if(mouse.getId() > -1) {
this.paintStrategyGame.paintMouseBuilding(mouse, g, map, camera);
}
if(selectionRectangle.isActive())
{
this.paintStrategyGame.paint(selectionRectangle, g);
}
this.paintStrategyGame.paintGui(map, fog, entities, g, camera,
descriptionPanel, ressourceInfoPanel, minimapPanel, minimap, graphicsManager);
}
else if(state == GameConfiguration.INMENU)
{
if(this.paintStrategyMainMenu == null) {
paintStrategyMainMenu = new PaintStrategyMainMenu();
}
this.paintStrategyMainMenu.paint(g, graphicsManager);
}
else if(state == GameConfiguration.INPAUSEMENU)
{
if(this.paintStrategyPauseMenu == null) {
paintStrategyPauseMenu = new PaintStrategyPauseMenu();
}
this.paintStrategyPauseMenu.paint(g, graphicsManager);
}
105
482 ЧДТУ. 252169 12 01 24
else if(state == GameConfiguration.BOTWIN || state ==
GameConfiguration.PLAYERWIN) {
if(this.paintStrategyVictoryScreen == null) {
paintStrategyVictoryScreen = new PaintStrategyVictoryScreen();
}
this.paintStrategyVictoryScreen.paint(g, graphicsManager);
}
}
private class BuildingProduction extends AbstractAction
{
private static final long serialVersionUID = 1L;
private int id;
private ProductionBuilding prodBuilding;
public BuildingProduction(String name, int id, ProductionBuilding building)
{
super(name);
this.id = id;
this.prodBuilding = building;
}
@Override
public void actionPerformed(ActionEvent e) {
int money =
manager.getFactionManager().getFactions().get(prodBuilding.getFaction()).getMoneyC
ount();
int priceOfProduction = prodBuilding.startProd(id, money);
if(priceOfProduction > 0) {
manager.getFactionManager().getFactions().get(prodBuilding.getFaction()).setMoneyC
ount(money – priceOfProduction);
if(id >= EntityConfiguration.ARMOR_UPGRADE && id <=
EntityConfiguration.AGE_UPGRADE_2) {
manager.getFactionManager().getFactions().get(prodBuilding.getFaction()).getSearch
ingUpgrades().add(id);
setDescriptionPanelForBuilding(prodBuilding,
manager.getFactionManager().getFactions().get(prodBuilding.getFaction()).getSearch
ingUpgrades());
}
}
}
}
private class BackToMenuAfterVictory extends AbstractAction{
private static final long serialVersionUID = 1L;
public BackToMenuAfterVictory(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent e) {
oldState = state;
state = GameConfiguration.INMENU;
manageState();
}
}
private class UndoProduction extends AbstractAction{
106
482 ЧДТУ. 252169 12 01 25
private static final long serialVersionUID = 1L;
private ProductionBuilding prodBuilding;
public UndoProduction(String name, ProductionBuilding building) {
super(name);
this.prodBuilding = building;
}
public void actionPerformed(ActionEvent e) {
int money =
manager.getFactionManager().getFactions().get(prodBuilding.getFaction()).getMoneyC
ount();
List<Integer>searchingUpgrades =
manager.getFactionManager().getFactions().get(prodBuilding.getFaction()).getSearch
ingUpgrades();
manager.getFactionManager().getFactions().get(prodBuilding.getFaction()).setMoneyC
ount(money + prodBuilding.removeProduction(searchingUpgrades));
setDescriptionPanelForBuilding(prodBuilding, searchingUpgrades);
}
}
private class PauseGameMenu extends AbstractAction
{
private static final long serialVersionUID = 1L;
public PauseGameMenu(String name)
{
super(name);
}
@Override
public void actionPerformed(ActionEvent e)
{
oldState = state;
state = GameConfiguration.INPAUSEMENU;
manageState();
}
}
private class ConstructBuilding extends AbstractAction
{
private static final long serialVersionUID = 1L;
private int id;
private int cost;
public ConstructBuilding(String name, int id, int cost)
{
super(name);
this.id = id;
this.cost = cost;
}
@Override
public void actionPerformed(ActionEvent e) {
if(manager.getFactionManager().getFactions().get(EntityConfiguration.PLAYER_FACTIO
N).getMoneyCount() >= cost) {
mouse.setId(this.getId());
mouse.setCost(this.cost);
mouse.getEntityNoAnimationTexture(graphicsManager, id,
EntityConfiguration.PLAYER_FACTION);
107
482 ЧДТУ. 252169 12 01 26
}
}
public int getId() {
return id;
}
}
private class PrintConstruction extends AbstractAction
{
private static final long serialVersionUID = 1L;
public PrintConstruction(String name)
{
super(name);
}
@Override
public void actionPerformed(ActionEvent e)
{
setDescriptionPanelForConstruction();
}
}
private class ChangeState extends AbstractAction{
private static final long serialVersionUID = 1L;
private int type;
private List<Fighter>fighters;
public ChangeState(String name, int type, List<Fighter> fighters) {
super(name);
this.type = type;
this.fighters = fighters;
}
@Override
public void actionPerformed(ActionEvent e) {
if(type == EntityConfiguration.DEFENSIF_STATE) {
for(Fighter fighter : fighters) {
fighter.setState(EntityConfiguration.DEFENSIF_STATE);
}
}
else if(type == EntityConfiguration.AGRESSIF_STATE) {
for(Fighter fighter : fighters) {
fighter.setState(EntityConfiguration.AGRESSIF_STATE);
}
}
else if(type == EntityConfiguration.PASSIF_STATE) {
for(Fighter fighter : fighters) {
fighter.setState(EntityConfiguration.PASSIF_STATE);
}
}
}
}
//for mainMenuGui
private class RadioButton1 extends AbstractAction
{
108
482 ЧДТУ. 252169 12 01 27
private static final long serialVersionUID = 1L;
public RadioButton1(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent e)
{
labelMap.setIcon(map1);
setSelectedMap(1);
}
}
private class ExitGameButton extends AbstractAction
{
private static final long serialVersionUID = 1L;
public ExitGameButton(String name)
{
super(name);
}
@Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
private class LaunchGame extends AbstractAction
{
private static final long serialVersionUID = 1L;
public LaunchGame(String name)
{
super(name);
}
@Override
public void actionPerformed(ActionEvent e)
{
fog = new Fog(GameConfiguration.LINE_COUNT,
GameConfiguration.COLUMN_COUNT);
manager.setPlayerFog(fog);
time = 0;
map = GameBuilder.buildMap(selectedMap, graphicsManager, manager);
if(boxMoney.getSelectedIndex() == 0) {
startingMoney = GameConfiguration.LOW_MONEY;
}
else if(boxMoney.getSelectedIndex() == 1) {
startingMoney = GameConfiguration.MEDIUM_MONEY;
}
else {
startingMoney = GameConfiguration.HIGH_MONEY;
}
if(boxPopulation.getSelectedIndex() == 0) {
maxPopulation = GameConfiguration.LOW_POP;
}
else if(boxPopulation.getSelectedIndex() == 1) {
maxPopulation = GameConfiguration.MEDIUM_POP;
109
482 ЧДТУ. 252169 12 01 28
}
else {
maxPopulation = GameConfiguration.HIGH_POP;
}
GameBuilder.buildFaction(manager, boxPlayer1.getSelectedIndex() + 1,
boxPlayer2.getSelectedIndex() + 1, map, maxPopulation, startingMoney);
manager.setMap(map);
gamePanel = createGamePanel();
gamePanel.setVisible(false);
oldState = state;
state = GameConfiguration.INGAME;
manageState();
}
}
private class ScrollingModel implements BoundedRangeModel
{
public ScrollingModel()
{
super();
}
@Override
public void addChangeListener(ChangeListener arg0)
{
}
@Override
public int getExtent()
{
return 0;
}
@Override
public int getMaximum()
{
return 0;
}
@Override
public int getMinimum()
{
return 0;
}
@Override
public int getValue()
{
return 0;
}
@Override
public boolean getValueIsAdjusting()
{
return false;
}
@Override
public void removeChangeListener(ChangeListener arg0)
110
482 ЧДТУ. 252169 12 01 29
{
}
@Override
public void setExtent(int arg0)
{
}
@Override
public void setMaximum(int arg0)
{
}
@Override
public void setMinimum(int arg0)
{
}
@Override
public void setRangeProperties(int arg0, int arg1, int arg2, int arg3,
boolean arg4)
{
}
@Override
public void setValue(int arg0)
{
}
@Override
public void setValueIsAdjusting(boolean arg0)
{
}
}
private class SonModel implements BoundedRangeModel
{
private int value;
public SonModel()
{
super();
this.value = 25;
this.setValue(value);
}
@Override
public void addChangeListener(ChangeListener arg0)
{
}
@Override
public int getExtent()
{
return 0;
}
@Override
public int getMaximum()
{
return 100;
111
482 ЧДТУ. 252169 12 01 30
}
@Override
public int getMinimum()
{
return 0;
}
@Override
public int getValue()
{
return value;
}
@Override
public boolean getValueIsAdjusting()
{
return false;
}
@Override
public void removeChangeListener(ChangeListener arg0)
{
}
@Override
public void setExtent(int arg0)
{
}
@Override
public void setMaximum(int arg0)
{
}
@Override
public void setMinimum(int arg0)
{
}
@Override
public void setRangeProperties(int arg0, int arg1, int arg2, int arg3,
boolean arg4)
{
}
@Override
public void setValue(int arg0)
{
value = arg0;
}
@Override
public void setValueIsAdjusting(boolean arg0)
{
}
}
private class UnpauseGameButton extends AbstractAction
{
private static final long serialVersionUID = 1L;
public UnpauseGameButton(String name)
{
112
482 ЧДТУ. 252169 12 01 31
super(name);
}
public void actionPerformed(ActionEvent e)
{
oldState = state;
state = GameConfiguration.INGAME;
manageState();
}
}
private class GoToMainMenuFromPauseMenu extends AbstractAction
{
private static final long serialVersionUID = 1L;
public GoToMainMenuFromPauseMenu(String name)
{
super(name);
}
public void actionPerformed(ActionEvent e)
{
oldState = state;
state = GameConfiguration.INMENU;
manageState();
mouse.reset();
}
}
private void manageState()
{
switch(state)
{
case GameConfiguration.INMENU:
if(oldState == GameConfiguration.INPAUSEMENU)
{
pauseMenuPanel.setVisible(false);
getMainPanel().remove(pauseMenuPanel);
manager.clean();
camera.reset();
}
else if(oldState == GameConfiguration.BOTWIN) {
loosePanel.setVisible(false);
getMainPanel().remove(loosePanel);
manager.clean();
camera.reset();
}
else if(oldState == GameConfiguration.PLAYERWIN) {
winPanel.setVisible(false);
getMainPanel().remove(winPanel);
manager.clean();
camera.reset();
}
mainMenuPanel.setVisible(true);
getMainPanel().add(mainMenuPanel);
break;
case GameConfiguration.INGAME:
if(oldState == GameConfiguration.INPAUSEMENU)
{
pauseMenuPanel.setVisible(false);
getMainPanel().remove(pauseMenuPanel);
113
482 ЧДТУ. 252169 12 01 32
}
else if(oldState == GameConfiguration.INMENU)
{
mainMenuPanel.setVisible(false);
getMainPanel().remove(mainMenuPanel);
}
gamePanel.setVisible(true);
getMainPanel().add(gamePanel);
break;
case GameConfiguration.INPAUSEMENU:
if(oldState == GameConfiguration.INGAME)
{
gamePanel.setVisible(false);
getMainPanel().remove(gamePanel);
}
pauseMenuPanel.setVisible(true);
getMainPanel().add(pauseMenuPanel);
break;
case GameConfiguration.PLAYERWIN:
if(oldState == GameConfiguration.INGAME) {
gamePanel.setVisible(false);
getMainPanel().remove(gamePanel);
}
winPanel.setVisible(true);
getMainPanel().add(winPanel);
break;
case GameConfiguration.BOTWIN:
if(oldState == GameConfiguration.INGAME) {
gamePanel.setVisible(false);
getMainPanel().remove(gamePanel);
}
loosePanel.setVisible(true);
getMainPanel().add(loosePanel);
break;
default:
break;
}
getMainPanel().validate();
}
public Map getMap()
{
return this.map;
}
public int getState() {
return state;
public void setSelectedMap(int selectedMap) {
this.selectedMap = selectedMap;
}
public JPanel getMinimapPanel() {
return minimapPanel;
}
public Minimap getMinimap() {
return minimap;
}
public JPanel getDescriptionPanel() {
return descriptionPanel;
}
114
ДОДАТОК В
Програмне забезпечення гри в жанрі Real-Time Strategy
Інструкція користувачеві
482 ЧДТУ. 252169 34 01
Листів 4
Розробник ________________ Татаровський А.В.
Черкаси 2025
115
482 ЧДТУ. 252169 34 01 2
Після відкриття виконуваного файлу почнеться загрузка гри
При запуску програмного застосунку користувачу буде відображено
головне меню (рисунок В.1), де йому пропонується обрати свою фракцію,
кількість початкового золота та кількість максимальної популяції для фракції.
Рисунок В.1 – Головне меню додатку
Користувач має змогу обрати початкові дані та натиснути кнопку «Start
Game» або ж вийти з гри
При початку, гравцю надається можливість керування різними видами
юнітів, серед яких: працюючі та розвідник
Рисунок В.2 – Зображення вигляду внутрішнього геймплею та вигляд
підконтрольних юнітів
116
482 ЧДТУ. 252169 34 01 3
Користувач має змогу сам вирішувати що робити, а саме:
Здобувати ресурси (рисунок В.3), Будувати будівлі, Тренерувати більше
юнітів, Розвідувати територію, Нападати на противника і безліч інших
можливостей.
Рисунок В.3 – Зображення збору гравцем ресурсів
Користувач має змогу добувати ресурси, щоб вдосконалювати свої
володіння та армію
Рисунок В.4 – Зображення процесу будівництва
Користувач має змогу почати будівництво або вдосконалення існуючих
будівель для подальшого розвитку
117
482 ЧДТУ. 252169 34 01 4
Рисунок В.5 – Зображення тренерування юнітів
Користувач має змогу розвивати свою армію для подальшого її керування і
створення тактики
Рисунок В.6 – Зображення бою з противником
Користувач має змогу захищатись або ж атакувати ворожих юнітів або
ворожі будівлі
Рисунок В.7 – Зображення кінцевого меню, де повідомляється про виграш
гравця, або його програш
118
482 ЧДТУ. 252169 34 01 5
При розбитті армії супротивника та знищенні його будівель гру буде
завершено (рисунок В.7) та повідомлено гравцю про його перемогу або ж навпаки
про його невдачу
119
ДОДАТОК Г
Програмне забезпечення гри в жанрі Real-Time Strategy
Графічні матеріали
482 ЧДТУ. 252169 90 01
Листів 9
Розробник ________________ Татаровський А.В.
Черкаси 2025
120
482 ЧДТУ. 252169 90 01 2
Рисунок Г1 – Слайд 1
Рисунок Г2 – Слайд 2
121
482 ЧДТУ. 252169 90 01 3
Рисунок Г3 – Слайд 3
Рисунок Г4 – Слайд 4
122
482 ЧДТУ. 252169 90 01 4
Рисунок Г5 – Слайд 5
Рисунок Г6 – Слайд 6
123
482 ЧДТУ. 252169 90 01 5
Рисунок Г7 – Слайд 7
Рисунок Г8 – Слайд 8
124
482 ЧДТУ. 252169 90 01 6
Рисунок Г9 – Слайд 9
Рисунок Г10 – Слайд 10
125
482 ЧДТУ. 252169 90 01 7
Рисунок Г11 – Слайд 11
Рисунок Г12 – Слайд 12
126
482 ЧДТУ. 252169 90 01 8
Рисунок Г13 – Слайд 13
Рисунок Г14 – Слайд 14
127
482 ЧДТУ. 252169 90 01 9
Рисунок Г15 – Слайд 15
Рисунок Г16 – Слайд 16
128
482 ЧДТУ. 252169 90 01 10
Рисунок Г17 – Слайд 17
129