Please use this identifier to cite or link to this item: https://er.chdtu.edu.ua/handle/ChSTU/5439
Title: Гра "Racing online" під ОС Android та веб-платформи для її ком'юніті
Authors: Тарасенко, Ярослав Володимирович
Бакуменко, Роман Вікторович
Keywords: мобільна гра;веб-платформа;ком'юніті гри;Android;розробка гри;соціальна взаємодія
Issue Date: 14-Jun-2023
Abstract: В кваліфікаційній роботі бакалавра розглянуто дослідження в області створення ігор для платформи Android. Мета роботи – створити гру для користувачів, а також сайт для ком’юніті гри «Racing online» Предметом дослідження є розробка мобільних ігор і сайтів для них. Розробка гри включає в себе такі дослідження як вибір і налаштування технологій та інструментів, розробка бекенду для мультиплеєра. А також розробка сайту включає в себе такі аспекти, як інтеграцію БД, розробку бекенд-функцій. В першому розділі розглянуто аналоги які на сьогодні створенні, проведено аналіз їх і визначення чітких цілей які повинна виконати моя дипломна робота. В другому розділі розписане технічне завдання, де описано який дизайн повинен мати продукт, а також який розписано більш детально який саме функціонал повинен мати продукт. В третьому розділі розповідається про реалізацію продукту, а також про тестування його і які були виявлені баги під час тестування, а в кінці розділу іде зрівняння наскільки мій продукт краще за аналоги.
URI: https://er.chdtu.edu.ua/handle/ChSTU/5439
Appears in Collections:126 Інформаційні системи та технології (Web-технології, web-дизайн)

Files in This Item:
File Description SizeFormat 
РЕП_БАК_Бакуменко_WEBC-2111.pdf
  Restricted Access
«Гра "Racing online" під ОС Android та веб-платформи для її ком'юніті5.92 MBAdobe PDFView/Open Request a copy


Items in DSpace are protected by copyright, with all rights reserved, unless otherwise indicated.

Extracted text
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ 
ЧЕРКАСЬКИЙ ДЕРЖАВНИЙ ТЕХНОЛОГІЧНИЙ УНІЕРСИТЕТ 
 
ФАКУЛЬТЕТ ІНФОРМАЦІЙНИХ ТЕХНОЛОГІЙ І СИСТЕМ 
 
 
Кафедра інформаційних технологій проектування 
 
 
 
 
Пояснювальна записка 
до кваліфікаційної роботи 
 
 
_______________________________бакалавра_____________________________ 
  (освітньо-кваліфікаційний рівень) 
 
 
на тему: «Гра "Racing online" під ОС Android та веб-платформи для її 
ком'юніті» 
 
 
 
 
 
                                                Виконав: студент 4 курсу, групи WebC-2111 
                                Спеціальність 126 “Інформаційні 
              системи та технології” 
                                  ОП “Web-технології, Web-дизайн” 
Бакуменко Роман Вікторович 
      (прізвище та ініціали) 
 
Керівник: к.т.н., доцент кафедри ІТП 
Тарасенко Ярослав Володимирович 
 
Рецензент: Директор ТОВ Андерсенлаб 
Олег Вікторович Алесін 
 
 
 
 
 
 
Черкаси 2023 року  
АНОТАЦІЯ 
 
В кваліфікаційній роботі бакалавра розглянуто дослідження в області 
створення ігор для платформи Android. Мета роботи – створити гру для 
користувачів, а також сайт для ком’юніті гри «Racing online» 
Предметом дослідження є розробка мобільних ігор і сайтів для них. 
Розробка гри включає в себе такі дослідження як вибір і налаштування 
технологій та інструментів, розробка бекенду для мультиплеєра. А також 
розробка сайту включає в себе такі аспекти, як інтеграцію БД, розробку 
бекенд-функцій.  
В першому розділі розглянуто аналоги які на сьогодні створенні, 
проведено аналіз їх і визначення чітких цілей які повинна виконати моя 
дипломна робота. 
В другому розділі розписане технічне завдання, де описано який 
дизайн повинен мати продукт, а також який розписано більш детально який 
саме функціонал повинен мати продукт. 
В третьому розділі розповідається про реалізацію продукту, а також 
про тестування його і які були виявлені баги під час тестування, а в кінці 
розділу іде зрівняння наскільки мій продукт краще за аналоги. 
Кваліфікаційна робота складається з 48 сторінок, 2 таблиць, 45 
рисунків, 25 джерел використаної літератури, 3 додатків. Включає в себе такі 
частини: огляд існуючих аналогів, розробка технічного завдання, розробка 
продукту, висновки та список використаних джерел, додаток А, додаток В, 
додаток Б. 
Ключові слова бакалаврської роботи є такі: мобільна гра, ком'юніті 
гри, Android, розробка гри, соціальна взаємодія, веб-платформа. 
  
ANNOTATION 
In the bachelor's qualification work, research in the field of creating games 
for the Android platform is considered. The goal of the work is to create a game for 
users, as well as a site for the community of the game "Racing online" 
The subject of research is the development of mobile games and sites for 
them. The development of the game includes such research as the selection and 
adjustment of technologies and tools, the development of the backend for 
multiplayer. Also, site development includes such aspects as database integration, 
development of backend functions. 
In the first chapter, analogues that are created today are considered, their 
analysis is carried out and the clear goals that my thesis must fulfill are defined. 
The second section describes the technical task, which describes what 
design the product should have, and which describes in more detail what 
functionality the product should have. 
The third chapter tells about the implementation of the product, as well as 
about its testing and what bugs were discovered during testing, and at the end of 
the chapter there is a comparison of how much better my product is than its 
counterparts. 
The qualification work consists of 48 pages, 2 tables, 45 figures, 25 sources 
of used literature, 3 appendices. Includes the following parts: review of existing 
analogues, development of technical terms of reference, product development, 
conclusions and list of sources used, appendix A, appendix B, appendix B. 
The keywords of the bachelor thesis are as follows: mobile game, game 
communities, Android, game development, social interaction, web platform. 
 
ЗМІСТ 
ПЕРЕЛІК УМОВНИХ ПОЗНАЧЕНЬ І СКОРОЧЕНЬ………………………….....4 
ВСТУП ……………………………………………………………………………….5 
    РОЗДІЛ 1. ОГЛЯД ІСНУЮЧИХ АНАЛОГІВ …………………………………….7 
1.1. Гра «Rally Fury» як прототип майбутньої гри………………………….….…7 
1.2. Гра «Drag racing:Уличні перегони» ……………………………………..…..11 
1.3. Сайт гри «Forza horizon»…………………………………………………..….14 
1.4. Які завдання потрібно вирішити………………………………………..……17 
РОЗДІЛ 2.  РОЗРОБКА ТЕХНІЧНОГО ЗАВДАННЯ………..…………….…….18 
2.1.  Технічне завдання для сайту……………………………………...…...……18 
2.1.1.  Призначення розроблювального продукту…………………..…………..18 
2.1.2.  Вимоги до дизайну……………………………………………..………….18 
2.1.3.  Структура серверу та сторінок…………………………………..……… 18 
2.1.4.  Навігація продукту……………………………………………..………… 20 
2.1.5.  Вимоги до наповнення сторінок………………………………..……….. 21 
2.1.6.  Адміністрування сайту:……………………………………….…………. 22 
2.2.  Технічне завдання для гри………………………………………..…………24 
2.2.1.  Призначення розроблювального продукту…………………..…………..24 
2.2.2.  Технічні вимоги …………………………………………………..……….24 
2.2.3.  Вимоги до дизайну ………………………………………………..………25 
2.2.4.  Структура гри……………………………………………………..……… 25 
2.2.5.  Навігація продукту. ……………………………………………..………...25 
2.2.6.  Вимоги до наповнення гри……………………………………..………....26 
2.2.7.  Тестування………………………………………………………..………...27 
2.3.  Економічна вигода………………………………………………..………….27 
РОЗДІЛ 3. РОЗРОБКА ПРОДУКТУ…..………...……………………...…………29 
3.1.  Засоби для реалізації сайту та гри.……………………………..…………..29 
 
ЧДТУ 232227.001 ПЗ 
Зм. Лист № докумемента Підпис Дата 
Розроб. Бакуменко Р.В.  
 Літ. Лист Листів 
Перев. Тарасенко Я.В. Гра "Racing online" під ОС Android та веб- Н 2  
Алесін О.В, платформи для її ком'юніті 
Реценз   ФІТІС, 
Н. .контр. Тарасенко Я.В Пояснювальна записка 
Затв. Прокопенко Т.О. кафедра ІТП, WEBC-2111 
  
 
3.2.  Реалізація продукту...………………………………………..………………29 
3.2.1.  Створення таблиць в БД…………………………………..………………29 
3.2.2.  Розробка сайту……………………………………………..………………30 
3.2.3.  Розробка гри………………………………………………..………………38 
3.3.  Тестування продукту……………………………………….……………… 42 
3.4.  Порівняння з аналогами …………………………………..………………...46 
ВИСНОВКИ………………………………………………………………………...49 
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ…...……………………………………..50 
ДОДАТОК А…………...…………………………………………………………...52 
ДОДАТОК Б………………………………………………………………………...54 
ДОДАТОК В……………………...………………………………………………...75 
 
 
ЧДТУ 232227.001 ПЗ 
Зм. Лист № докумемента Підпис Дата 
Розроб. Бакуменко Р.В.  
 Літ. Лист Листів 
Перев. Тарасенко Я.В. Гра "Racing online" під ОС Android та веб- Н 3  
Алесін О.В, платформи для її ком'юніті 
Реценз   ФІТІС, 
Н. .контр. Тарасенко Я.В. Пояснювальна записка 
Затв. Прокопенко Т.О. кафедра ІТП, WEBC-2111 
  
 
 
 
ПЕРЕЛІК УМОВНИХ ПОЗНАЧЕНЬ І СКОРОЧЕНЬ  
HTML - HyperText Markup Language: мова розмітки, що використовується для 
створення структури та відображення вмісту веб-сторінок 
CSS - Cascading Style Sheets: мова стилізації, що використовується для 
оформлення та вигляду веб-сторінок. 
JS - JavaScript: мова програмування, що використовується для додавання 
динамічної функціональності до веб-сайту. 
UI - User Interface: інтерфейс користувача, тобто взаємодія між користувачем та 
веб-сайтом. 
UX  - User Experience: враження та задоволення користувача від взаємодії з веб-
сайтом. 
SEO - Search Engine Optimization: оптимізація для пошукових систем, що 
дозволяє покращити видимість веб-сайту в пошукових результатах. 
Photon - мережева бібліотека для синхронізації стану для Unity. 
Unity - багатоплатформовий інструмент для розроблення відеоігор і застосунків 
  
Арк . 
ЧДТУ 232227.001 ПЗ 
 4 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
ВСТУП  
На сьогоднішній день потреби в мобільних іграх набагато більше ніж 
розробники можуть запропонувати і в найближчі 5 років ці потреби навряд чи 
будуть  повністю задовільні, також одна з причин чому більшість розробляє саме 
легкі мобільні ігри, а не великі проекти для ПК або телефонів це можливість 
створити портфоліо програмісту і показати, що він розбирається в цій ніші, і має 
певні навички для цього. Також однією з причин це гроші які приносять мобільні 
ігри, через те що популярність мобільних ігор тільки зростає і для розробників є 
великий спектор можливостей монетезувати свою гру і заробити на цьому, то 
вони стимулюють людей зробити донат задля отримання переваги над гравцями 
або отримання унікального скіна персонажа.  
Тема дипломної роботи яку я вибрав буде актуальна навіть через декілька 
десятиліть, тому що потреба людей в іграх нікуди не пропаде і вони будуть тільки 
потребувати більш продумані ігри та ближче зв’язані з реальністю. 
Метою виконання моєї дипломної роботи, полягає в тому, щоб користувачі 
які полюбляють жанр перегони отримали новий продукт який можна було б 
протестувати, та ознайомитися з його функціоналом, для розробки дипломної 
роботи мені знадобиться використати такі інструменти для створення гри як Unity 
який буде використовуватись як ігровий двигун, мову C# для  написання скриптів, 
веб-сервер Photon для написання мультиплеєру, також для гри буде створений 
сайт де користувачі зможуть спілкуватися з іншими гравцями, а також з 
розробниками гри.  
У моїй дипломній роботі повинні бути вирішенні такі завдання: 
1. Задоволення користувачів в потребах нових ігор 
2. Створити в грі дух конкуренції  
3. Створити сайт для гравців 
4. Надати можливість отримати фідбек від користувачів 
В моїй дипломній роботі можна буде спостерігати за створенням гри для 
користувачів які полюбляють жанри перегони, а також за створенням сайтом для 
них. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 5 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
В іграх які досягли значного успіху і мають доволі велику аудиторію мають 
свої сайти для направлення туди таргетованої реклами, а також мають акаунти 
ігри в соцільних мережах для покращення впізнавальності свого додатку. Сайти 
створюються для можливості отримання фідбеку від користувачів, а також для 
розуміння чи ця гра цікава гравцям чи ні, бо якщо використовувати для цього 
соціальну мережу то вона може не надавати весь той функціонал який потрібен 
розробникам ігор і користувачам. 
Моя дипломна робота підходить для використання в відкритому тестуванні, 
для того, щоб знайти більше багів та виправити їх, і вона може використовуватись 
як фундамент будь якої гри для онлайн перегон. 
Моя робота складається з таких розділів як: вступ, аналіз аналогів, опис ТЗ, 
реалізація продукту, Висновку, списку використаних джерел та додатків. 
 
  
Арк . 
ЧДТУ 232227.001 ПЗ 
 6 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
РОЗДІЛ 1 
ОГЛЯД ІСНУЮЧИХ АНАЛОГІВ 
 
 
На сьогодні є велика кількість аналогів які можуть відобразити мою ідею, 
але я вибрав лише декілька з них, і зараз ми їх розглянемо. 
Для аналізу аналогів, я використав інформацію яку подано в таких 
книжках як [1-3], за допомоги них я зміг зрозуміти як мені правильно провести 
аналіз своїх аналогів, для отримання максимальної користі. 
 
1.1. Гра «Rally Fury» як прототип майбутньої гри 
 
Аналогом який надихнув мене на створення своєї гри є гра “Rally fury” від 
розробників Refuel Games Pty Ltd. 
[4] В цій грі реалізовані перегони в онлайні та офлайн де 8 гравців можуть 
в одному заїзді дізнатися хто з них найкраще володіє автомобілем. В грі є 
декілька класів авто, щоб гравці поступово звикнувши до фізики управління авто 
в грі мали змогу їздити на автомобілях які можуть розвинути більшу швидкість.  
Гра має такі механіки: 
• Покращення авто 
• Покраска авто 
• Купівля бустерів для збільшення шансу на перемогу 
• Купівля різних шин для певного покриття дороги 
Також в грі реалізовано навчання нових гравців на тестових треках. 
Гра має рівні які замінюють твій значок щоб інші гравці розуміли що ти 
маєш досвід в керуванні авто. 
Фізика гри дозволяє використовувати брудну гру під час заїздів в онлайні, 
тому що гравець може легенько або на максимальній швидкості влетіть в іншого 
гравця і він улетить з дороги, а інший гравець може залишитись на дорозі і 
поїхати далі, але частіше всього буває, що обидва гравця вилітають з дороги і 
тому кому більше повезе виїде на дорогу бистріше. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 7 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
В грі реалізовані різні типи колес (рисунок 1), які дозволяють покращити 
час на деяких трасах. 
 
Рисунок 1.1 - Види шин які можна купити 
Також в грі реалізована покраска авто на свій смак (рисунок 2), можна 
додати деякі лінії на авто, а також змінити надпис на номерах, і додати підсвітку 
авто. 
 
Рисунок 1.2 - Інтерфейс покраски авто 
Арк . 
ЧДТУ 232227.001 ПЗ 
 8 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
В грі є надоїдлива реклама яка з’являється після кожної гонки.  
Інтерфейс гонки має такий вигляд, він доволі інформативний і не 
громіздкий (рисунок 3-4) 
 
Рисунок 1.3 - Інтерфейс гонки 
 
Рисунок 1.4 - Інтерфейс гонки 
Також в грі реалізовані доволі цікаві фішки які можна було інтегрувати в 
свою гру. Можна налаштувати управління авто під свій смак (рисунок 5). 
Арк . 
ЧДТУ 232227.001 ПЗ 
 9 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
 
Рисунок 1.5 – Налаштування гри 
Головне меню відображається на (рисунок 6), видно, що зліва по середині, 
можна вибрати на якому типі шин будеш їхати, а справа по середині, можна 
ознайомитись з характеристиками авто. 
В головному меню можна відразу вибрати авто на якому будеш їхати. 
Кнопка «кастомизировать» направляє нас в покраску, де ми можемо 
змінити зовнішній вигляд авто. 
 
Рисунок 1.6 – Вигляд головного меню 
Арк . 
ЧДТУ 232227.001 ПЗ 
 10 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Під час натискання на кнопку покращити, ми переходимо на іншу панель 
(рисунок 7), де ми можемо більш детально ознайомитись з характеристиками 
авто. 
 
Рисунок 1.7 – Панель характеристик авто 
З грою «Rally Fury» ми вже ознайомились, тепер переходимо до іншої гри. 
 
1.2. Гра «Drag racing:Уличні перегони» 
 
Цю гру я вибрав як аналог своєї майбутньої гри, тому що тут є безліч 
цікавих механік, які б можна було б використати для своєї гри. Але всі їх 
реалізовувати я їх не буду. Опишу ті які планую добавити в гру, і ті які можливо в 
майбутньому добавлю. 
[5]Ця гра 2Д, вона про драг-рейсинг, це перегони на рівному асфальті на 
дистанції 402-804 метра. 
Зовнішній вигляд гра має такий (рисунок 8). 
Арк . 
ЧДТУ 232227.001 ПЗ 
 11 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
 
Рисунок 1.8 – Головне меню гри 
Основну механіку яку я планую взяти з цієї гри, це налаштування кпп 
(рисунок 9), це дозволить гравцям підняти максимальну швидкість, але заставить 
їх погіршити розгін авто, тому потрібно буде під кожний тип траси 
налаштовувати іншу кпп, що дасть змогу гравцям які розуміють як ця механіка 
працює покращити свій результат і стати швидше, ніж інші гравці. 
 
Рисунок 1.9 – Інтерфейс налаштування кпп 
Тепер переглянемо механіки які в майбутніх оновленнях планується 
добавити, і перша з них це надання можливості налаштувати спойлер (рисунок 
10). 
Його задача давати авто додаткову прижимну силу, що буде покращувати 
його час розгону, і під час проходження поворотів  авто зможе їхати на більшій 
Арк . 
ЧДТУ 232227.001 ПЗ 
 12 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
швидкості, але через це погіршується максимальна швидкість, і від гравців 
потребується знаходження балансу. 
 
Рисунок 1.10 – Налаштування спойлера 
Наступна механіка яка буде добавлена, це налаштування підвіски (рисунок 
11), за допомоги неї авто можна буде налаштувати так, щоб авто майже чиркало 
дорогу, це якщо траса буде з асфальту, а якщо на трасі буде багато бугрів, то 
гравець матиме можливість підняти підвіску, для того, щоб авто більш плавніше 
їхало по такій дорозі. 
 
Рисунок 1.11 – Налаштування підвіски 
 
 
Арк . 
ЧДТУ 232227.001 ПЗ 
 13 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
1.3. Сайт гри «Forza horizon»  
 
Майже будь який сайт гри про перегони буде схожий один на одного, тому 
в вигляді аналога свого сайта, я вирішив вибрати гру «Forza horizon»[6]. 
 
Рисунок 1.12 – Головне меню сайту 
Як і всі сайти цей сайт має головне меню(рисунок 12), яке відразу 
відображає відео популярних гравців, а також трейлери самих розробників. 
Спустившись нижче, ми можемо тезесно ознайомитись з новинами 
(рисунок 13), а якщо захочемо більш детально ознайомитись, потрібно перейти на 
вкладку News.  
Арк . 
ЧДТУ 232227.001 ПЗ 
 14 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
 
Рисунок 1.13 -  Блок з тезисними новинами 
На головному меню також розповідається про механіки гри (рисунок 14), а 
саме в якому режимі ми можемо пограти в цю гру, та що в ній можна поробити, 
якщо потрібно просто відпочити і отримати емоції. 
 
Рисунок 1.14 – Інформація про режими в якому можна пограти 
Також тут є можливість авторизуватися (рисунок 15), для того, щоб 
переглянути свої нагороди, та переглянути які зараз доступні турніри. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 15 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
 
Рисунок 1.15 – Сторінка авторизації 
 На сайті реалізована окрема сторінка про ком’юніті гри, де можна 
дізнатися хто з стрімерів грає в цю гру (рисунок 16), та які люди грають в цю гру, 
і скільки часу вони вже грають в неї. 
 
Рисунок 1.16 – Сторінка з інформацією про ком’юніті гри 
На цьому сайті доволі велика кількість функціоналу, але для мене цього 
мало, тому що я хочу реалізувати також чат на сайті, і також реалізувати форуми 
на яких гравці можуть пропонувати свої ідеї по внесенню нових механік в гру. 
 
Арк . 
ЧДТУ 232227.001 ПЗ 
 16 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
1.4. Які завдання потрібно вирішити  
 
Під час виконання своєї дипломної роботи я повинен вирішити такі 
питання: 
1. Надати користувачам нову гру 
2. Надати можливість отримати задоволення від гри 
3. Створити сайт для фідбеку з користувачами 
4. Надати можливість користувачам задати запитання адміністраторам 
  
Арк . 
ЧДТУ 232227.001 ПЗ 
 17 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
РОЗДІЛ 2 
РОЗРОБКА ТЕХНІЧНОГО ЗАВДАННЯ 
2.1. Технічне завдання для сайту 
2.1.1. Призначення розроблювального продукту 
 
Продукт який розробляється призначений для задоволення потреб гравців 
в нових іграх. А сайт створюється для ком’юніті, щоб вони мали можливість 
переглядати новини про гру, а також надати фідбек розробникам про знайдені 
баги і побажання які б вони хотіли механіки додати в гру. 
 
2.1.2. Вимоги до дизайну  
 
Основні вимоги до дизайну сайту: 
• Колірна гама повинна бути приємна для очей і не визивати негативні 
емоціії 
• Шрифт тексту повинен бути великого розміру, щоб користувачі не 
напрягали свої очі під час читання тексту. 
 
2.1.3. Структура серверу та сторінок 
 
Логічна структура серверу повинна виконувати такі завдання: 
1. Користувацький інтерфейс сайту: 
• Головна сторінка з описом продукту 
• Сторінка чату гри 
• Сторінка підтримки  
• Перегляд новин та майбутніх оновлень 
2. Доступ до бази даних: 
• Таблиця «новини», з реалізованими формами для додавання та 
редагування новин, щоб адміністратору було легше створювати нові блоги 
Арк . 
ЧДТУ 232227.001 ПЗ 
 18 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
• Таблиця «Повідомлення від користувачів», таблиця призначена для 
збереження повідомлень від користувачів 
• Таблиця «Історія чату», таблиця призначена для збереження 
повідомлень від користувачів з подальшим відображенням їх користувачам. 
• Таблиця «Користувачі», тут зберігатимуться дані про акаунт 
користувача 
Фізична структура серверу: 
1. Апаратне забезпечення для сайту: 
• Серверний комп'ютер з процесором, оперативною пам'яттю та 
жорстким диском для сайту 
2. Операційна система: 
• Linux або Windows Server 
3. Веб-сервер: 
• Apache 
4. База даних: 
• MySQL 
Технології які потрібно використати для реалізації сайту: 
1. Мова на якій прописується бекенд сайту: 
• PHP – є поширеною мовою загального призначення, що 
інтерпретується, з відкритим вихідним кодом. PHP створювався спеціально для 
ведення веб-розробок, і код на ньому може впроваджуватися безпосередньо в 
HTML-код [7-10]. 
2. СУДБ: 
• Phpmyadmin - це безкоштовний програмний інструмент, написаний на 
PHP , призначений для адміністрування MySQL через Інтернет. phpMyAdmin 
підтримує широкий спектр операцій з MySQL і MariaDB. Операції, які часто 
використовуються (керування базами даних, таблицями, стовпцями, 
відношеннями, індексами, користувачами, дозволами тощо) можна виконувати 
Арк . 
ЧДТУ 232227.001 ПЗ 
 19 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
через інтерфейс користувача, у той час як у вас залишається можливість 
безпосередньо виконувати будь-який оператор SQL[11]. 
3. Додаткові технології: 
• AJAX - це набір технологій, що дозволяє здійснювати асинхронний 
обмін даними між веб-сторінкою і сервером без перезавантаження всієї сторінки. 
AJAX використовує комбінацію JavaScript, XMLHttpRequest-об'єкту та XML або 
інших форматів даних (наприклад, JSON) для обміну інформацією між браузером 
і сервером[12-13]. 
• JS - є високорівневою, інтерпретованою мовою програмування, яка 
використовується для розробки динамічних веб-сторінок і додавання 
інтерактивності до веб-додатків. Він є однією з ключових мов програмування для 
клієнтської (браузерної) частини веб-розробки[14-15]. 
• HTMl & CSS - є основними мовами розмітки та опису для створення 
та оформлення веб-сторінок. HTML використовується для визначення структури 
та елементів сторінки, а CSS відповідає за задання зовнішнього вигляду та стилю. 
HTML використовує теги для маркування різних елементів, а CSS визначає 
оформлення, кольори, шрифти, розміри тощо. Разом вони дозволяють створювати 
веб-сторінки зі структурою та зовнішнім виглядом[16-17]. 
 
2.1.4. Навігація продукту. 
 
Для користувачів на основному сайті навігаційне меню повинне бути 
розміщене горизонтально: 
• Розташоване вгорі сторінки 
• Елементи меню представлені горизонтальними посиланнями 
• Переходи між сторінками відбуваються при кліці на відповідний 
пункт меню 
• В меню повинні будуть відображені такі посилання: Головна, Чат, 
Підтримка, Новини, Пошта, Авторизація, Регістрація 
Арк . 
ЧДТУ 232227.001 ПЗ 
 20 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Меню адміністративної панелі для адмінів буде мати вертикальне 
розміщення: 
• На панелі будуть посилання на такі форми: «Додати нову новину»,  
«Перегляд таблиць бази даних», «Перегляд повідомлень до служби підтримки». 
• Перехід буде відбуватися під час кліку на певну назву форми і буде 
динамічне завантаження даних без оновлення сторінки. 
 
2.1.5. Вимоги до наповнення сторінок 
 
• Сайт повинен пройти тестування F-патерну  
• Заголовки і описи сторінок: 
o Кожна сторінка повинна мати унікальний заголовок, який точно 
відображає її зміст. 
o Опис сторінки повинен бути інформативним і коротким, 
заохочувати користувачів перейти на сторінку. 
• Текстовий контент: 
o Інформаційний контент, який чітко пояснює який продукт ви 
бачать перед собою. 
o Зрозумілий та легко читабельний текст. 
o Використання відповідної мови та стилю відповідно до цільової 
аудиторії. 
• Зображення: 
o Використання високоякісних зображень, які доповнюють 
контент та привертають увагу користувачів. 
o Оптимізація розміру файлів, щоб забезпечити швидке 
завантаження сторінок. 
• Контактна інформація: 
o Наявність контактних даних, таких як номер телефону, 
електронна пошта, адреса, форма зворотного зв'язку. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 21 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
o Зручність та видимість контактних даних для користувачів. 
• Посилання і кнопки: 
o Посилання на інші сторінки сайту або релевантний контент. 
o Використання чітких та легко розпізнаваних кнопок для 
виконання певних дій, таких як "Скачати гру", "Підтримка" 
• Адаптивність: 
o Забезпечення адаптивного дизайну, щоб контент відображався 
на різних пристроях і розмірах екранів, таких як комп'ютери, планшети та 
смартфони. 
• SEO-оптимізація: 
o Використання ключових слів у текстовому контенті, заголовках 
та описах сторінок для поліпшення видимості сайту у пошукових системах. 
o Встановлення мета-тегів для сторінок, щоб поліпшити їх 
індексацію та відображення у пошукових результатах. 
• Актуальність: 
o Регулярне оновлення контенту, включаючи інформацію про 
продукти, послуги, новини та події, щоб забезпечити актуальну інформацію 
для користувачів. 
o Це лише загальні приклади вимог до контенту, і фактичні 
вимоги можуть варіюватись в залежності від конкретного проекту та цілей 
веб-сайту. 
 
2.1.6. Адміністрування сайту: 
 
Вимоги до адміністрування сайту будуть такі: 
• Адміністрування сайту: 
o Можливість легко додавати, редагувати і видаляти контент на 
сайті через адміністративний інтерфейс. 
o Можливість керування структурою сайту. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 22 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
• Безпека і захист: 
o Регулярне оновлення і патчі для веб-сайту, щоб запобігти 
вразливостям та забезпечити безпеку даних. 
o Забезпечення резервного копіювання бази даних та файлів сайту 
для відновлення в разі потреби. 
o Моніторинг активності та захист від несанкціонованого 
доступу, включаючи захист від зламу та атак. 
• Технічна підтримка: 
o Надання служби технічної підтримки для вирішення проблем, 
які виникають під час експлуатації веб-сайту. 
o Швидка відповідь на запити користувачів та вирішення їх 
проблем. 
o Моніторинг роботи сайту та вчасна виявлення та усунення будь-
яких проблем з продуктивністю, недоступністю або помилками. 
• Розвиток і оновлення: 
o Можливість розширення функціональності сайту шляхом 
додавання нових модулів, функцій та інтеграцій. 
o Регулярне оновлення версій використовуваних платформ, 
фреймворків та зовнішніх компонентів для забезпечення сумісності та 
безпеки сайту. 
• Оптимізація продуктивності: 
o Виконання оптимізації швидкості завантаження сторінок для 
забезпечення швидкої та зручної роботи сайту. 
o Перевірка та вдосконалення роботи бази даних, серверного 
середовища та інфраструктури для покращення продуктивності сайту. 
• SEO-оптимізація: 
o Виконання постійної оптимізації для покращення видимості 
сайту у пошукових системах. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 23 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
o Оптимізація мета-тегів, ключових слів, URL-адрес та інших 
елементів для поліпшення ранжування сайту у пошукових результатів. 
• Навчання та документація: 
o Надання навчальних матеріалів та документації для 
адміністраторів сайту щодо використання та управління різними функціями 
сайту. 
 
2.2. Технічне завдання для гри 
2.2.1. Призначення розроблювального продукту 
 
Назва продукту: Онлайн гра «Racing online» 
Жанр: перегони 
Опис: Розроблювальний продукт призначений покрити потреби 
користувачів в нових іграх в жанрі перегони. Продукт повинен дати позитивні 
емоції під час керування автомобілем в грі, а також створити дух конкуренції під 
час онлайн заїздів, так як там буде таблиця лідерів.  
2.2.2. Технічні вимоги 
 
Платформа: Android 
Мови програмування та технології які потрібно використати для реалізації: 
C#, Unity, Photon 
Коротка інформація про інструменти які потрібно використати: 
• C# (вимовляється як "сі шарп") - сучасна об'єктно-орієнтована і 
типобезпечна мова програмування. C# дозволяє розробникам створювати різні 
типи безпечних та надійних програм, що виконуються в .NET. [18] 
• Unity зроблено, щоб дати вам можливість створити найкращі 
інтерактивні розваги або мультимедіа. Дане керівництво створено, щоб допомогти 
вам дізнатися, як використовувати Unity, від базових до продвинутих прийомів. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 24 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Його можна прочитати від початку до кінця, або використати в якості 
справочника. [19-20] 
• Photon - це нова високопродуктивна мережева бібліотека для 
синхронізації стану для Unity. Завдяки єдиному API він підтримує дві принципово 
різні топології мережі, а також режим для одного гравця без підключення до 
мережі. Його створено з урахуванням простоти, щоб природно інтегруватися в 
загальний робочий процес Unity, а також пропонує розширені функції, такі як 
стиснення даних, прогнозування на стороні клієнта та компенсація затримок із 
коробки [21] 
Звук: звук двигуна та покришок під час повороту 
 
2.2.3. Вимоги до дизайну 
 
Основні вимоги до дизайну гри: 
• Колірна гама повинна бути приємна для очей 
• Шрифт тексту повинен бути великого розміру, щоб користувачі не 
напружували свої очі під час читання тексту. 
• Якість графіки не повинна бути найкращого розширення, щоб не 
навантажувати телефони. 
 
2.2.4. Структура гри 
 
Користувацький інтерфейс гри: 
• Можливість вибрати авто на якому гравець хоче поїздити 
• Онлайн перегони 
• Налаштування типу керування авто 
 
2.2.5. Навігація продукту. 
 
Арк . 
ЧДТУ 232227.001 ПЗ 
 25 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Для користувачів в грі буде така навігація:  
• Спочатку йде завантаження головного меню 
Потім іде розгалуження 
• Вибір авто на якому користувач хоче поїхати гонку 
• Перегляд налаштування керування авто 
• Перехід в онлайн гонку 
Коли гравець вибирає «налаштування керування авто» він може змінити 
такі параметри: 
• Тип керування авто(стрілки або нахилом телефону) 
Якщо гравець натискає «Онлайн перегони» то він відправляється в лобі і 
чекає поки інші гравці зайдуть до нього. 
 Переходи в грі між сценами відбуваються при натисканні на кнопки 
 
2.2.6. Вимоги до наповнення гри 
 
• Зовнішній вигляд гри: 
o Гра повинна виглядить доволі якісною як для демо версії 
o Всі кнопки повинні мати однакові стилі 
o Текст який розміщений на кнопках повинен повністю описати 
куди саме попаде користувач під час натискання на цю кнопку. 
• Графіка: 
o Графіка не повинна бути розпливчастою, а повинна бути в 
одному стилі, і відображатись коректно. 
• Механіки гри: 
o Користувач повинен мати змогу змінити тип управління авто  
o Вибір авто на якому гравець поїде заїзд 
o Надати можливість грати в онлайні з іншими суперниками 
• Адаптивність: 
Арк . 
ЧДТУ 232227.001 ПЗ 
 26 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
o Забезпечення адаптивного дизайну, щоб контент відображався 
коректно на різних пристроях і розмірах екранів. 
• Актуальність:  
o Регулярне проведення оновлення механік гри, та додавання 
нових, для зацікавлення гравців залишитись в грі на триваліший час. 
 
2.2.7. Тестування  
 
Інформацію про які види тестування підійдуть саме моїй дипломній роботі, я 
отримав з таких ресурсів, як [22-25]. 
• Функціональне тестування: Виконати тестування окремих функцій 
гри, перевірити їх відповідність вимогам та виявити та усунути помилки. 
• Тестування мультиплеєрного режиму: Перевірити працездатність та 
стабільність мультиплеєрного режиму гри, виявити та усунути проблеми з 
підключенням та синхронізацією гравців. 
• Тестування на різних платформах: Виконати тестування гри на різних 
платформах, переконатися в її сумісності та оптимальній продуктивності. 
 
2.3. Економічна вигода 
 
Так як сайт та гра створюється перш за все для дипломної роботи, то 
бюджет на витрати не може мати велику ціну. Але давайте розглянемо скільки 
витрачено коштів на реалізацію цього продукту, і скільки в теорії може ще 
знадобитись витрати. 
Купити акаунт розробника в google play коштувало 25$, і це разова оплата. 
Сервер для онлайн перегон безкоштовний до 20 чоловік в онлайні, якщо 
буде більше то прийдеться заплатити 95$ за рік, для можливості підняти онлайн 
до 100 осіб. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 27 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Хостинг для сайту коштує 150-200грн (4-6$)  в місяць, це базовий хостинг 
який можна використовувати якщо не буде великої кількості людей, але в 
майбутньому знадобиться купити більш потужніший сервер. 
Вартість домену сягає від 200 до 500 грн (6-14$) на рік. 
Полягаючи з цих витрат можна сказати, що на реалізацію продукту 
потрібно витратити як мінімум 35$, а якщо потрібно буде підтримувати гру і вона 
стане більш популярною то прийдеться потратити більше 100$ на рік. 
Так як в моїй грі немає монетезації і на сайті також, то можна сказати, що 
гра буде жити поки розробники вкладують свої гроші, і ця гра завжди буде нести 
збитки, що є не доцільним.  
Але якщо в грі реалізувати донатну систему і отримання бонусів за 
перегляд реклами, то гра може стати прибутковою, або для початку буде 
працювати в нуль. 
 
  
Арк . 
ЧДТУ 232227.001 ПЗ 
 28 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
РОЗДІЛ 3 
РОЗРОБКА ПРОДУКТУ 
3.1. Засоби для реалізації сайту та гри 
 
Для реалізації сайу, я буду використовувати такі засоби. 
Редактор коду Draeamwear, тому що він зручний в використані, і має 
підказки, що спрощує написання коду, і має  можливість перегляду зовнішнього 
вигляду сайту прям в самому додатку і не потребує відкривати браузер і там 
переглядати чи коректно відображається сайт. 
Код я буду писати за допомоги мови php, бо це один з найвідоміших мов 
для програмування бекенду сайту, і є велика кількість інформації як правильно 
реалізувати той чи інший функціонал. 
Для реалізації гри, я буду використовувати такі засоби. 
• Ігровий двигун Unity. Він є безкоштовним і зручним для створення 
ігор, також є багато готових спрайтів які можна використати для створення своєї 
гри. 
• Бібліотека Photon для мультиплеєра. Я вибрав саме його, бо в них є 
тестовий сервер на 20 чоловік, для ознайомлення як саме реалізовуються онлайн 
ігри. І він безкоштовний  
• Редактор коду Visual Studio для написання скриптів, які повинні 
виконуватися під час взаємодії з грою користувачем 
• Мову C# використовується для написання скриптів. 
 
3.2. Реалізація продукту 
3.2.1 Створення таблиць в БД 
 
Для сайту я буду використовувати СУБД phpmyadmin тому що [2] це 
безкоштовний програмний інструмент, написаний на PHP, який призначений для 
керування сервером баз даних MySQL або MariaDB. Ви можете використовувати 
Арк . 
ЧДТУ 232227.001 ПЗ 
 29 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
phpMyAdmin для виконання більшості завдань адміністрування, включаючи 
створення бази даних, виконання запитів і додавання облікових записів 
користувачів. 
Перед створенням сайту, я вирішив створити таблиці в базі даних які мені 
знадобляться під час створення сайту. 
Перша таблиця це «новини» тут будуть зберігатись всі новини які 
відображатимуться на головному меню і в архіві новин. 
Таблиця має такі назви полів: ід, заголовок, дата створення, текст, 
категорія, чи рекомендована ця новина, посилання на фото 
Друга таблиця це «повідомлення підтримці» тут будуть зберігатись всі 
повідомлення до служби підтримки. 
Таблиця має такі назви полів: ід, ник акаунта, текст, тип запитання, дата 
Третя таблиця це «Чат» тут будуть зберігатись всі повідомлення які 
користувачі відправляють. 
Таблиця має такі назви полів: ід, ім’я гравця, дата відправлення, текст  
Четверта таблиця це «Користувачі» тут будуть зберігатись всі дані про 
користувачів. 
Таблиця має такі назви полів: ід, ім’я гравця, пароль 
 
3.2.2. Розробка сайту 
 
Розробка сайту розпочинається з перегляду аналогів для розуміння, що я 
можу взяти для майбутнього сайту. 
Після цього робиться ТЗ і переходимо до реалізації продукту. 
Для реалізації мого сайту мені знадобиться редактор коду  Dreamwear, 
мова PHP для написання бекенду і база даних. 
Перше що я створюю це головну сторінку, на ній відображається навігація 
по сайту, а також стислий контент про кожну з сторінок мого сайту з 
посиланнями на них. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 30 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
  
 
Рисунок 3.1 – Головна сторінка сайту. 
Для завантаження контенту на сторінку використовую php код який 
виконує запит до бази даних і виводить останні новини, також є блок з 
актуальними це ті які на даний момент найчастіше відвідували користувачі. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 31 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
 
Рисунок 3.2 – Код який виводить дані з бази даних на сайт 
Далі я перейшов до реалізації сторінки новини, це буде архів всіх новин, 
які є в БД і користувачі зможуть переглянути ті новини які їх цікавлять. 
 
 
Рисунок 3.3 – Фото архіву новин 
Код використовується майже схожий на той, що в головному меню. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 32 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Далі перейшов до реалізації сторінки чату для того, щоб користувач міг 
писати в чат йому потрібно авторизуватись на сайті і лише після цього він зможе 
писати в чат і спілкуватися з іншими гравцями 
 
Рисунок 3.4 – Зовнішній вигляд сторінки сайту 
Код зберігає дані в таблицю і виводить всім користувачам, код який 
використовується виводить останні 100 повідомлень, а адміністратор в панелі 
керування може переглядати всю історію, але після того як в таблиці буде більше 
2000 повідомлень код буде автоматично чистити БД. 
Нижче можна переглянути код який виконує дану роботу. 
 
Рисунок 3.5 – Код виводу повідомлень з БД. 
Після того як реалізував чат переходжу до створення сторінки 
«підтримка». 
Арк . 
ЧДТУ 232227.001 ПЗ 
 33 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Тут гравці матимуть змогу відправити повідомлення адміністраторам якщо 
в них виникають якісь питання, або вони бажають запропонувати якусь нову 
механіку для гри. 
 
Рисунок 3.6 – Вигляд форми для зв’язку з адміністраторами. 
Після створення всіх сторінок сайту для користувача переходжу до 
створення адмін панелі. Перехід буде відбуватися за допомоги написання біля 
домену/admin.php. 
Після цього ми попадаєм на форму авторизації, де потрібно правильно 
ввести логін і пароль, і якщо такого користувача не буде то далі в адмін панель не 
зайти. 
А коли адміністратор правильно вводить логін і пароль, проводиться 
тестове підключення і перенаправляє на адмін панель. 
 
Рисунок 3.7 – Вигляд авторизації в адмін панель 
Арк . 
ЧДТУ 232227.001 ПЗ 
 34 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Після коректного вводу даних нам відкривається адмін панель і там ми 
можемо користуватись такими формами як «додавання новин, «перегляд 
таблиць», «перегляд повідомлень до служби підтримки».  
 
Рисунок 3.8 – Вигляд адмін панелі адміністраторів 
В майбутньому можна буде додати ще деякий функціонал. 
Форма додавання новин надає нам можливостей додати нову новину, але 
фішка даної форми в тому, що в ній є попередній перегляд як саме буде виглядати  
блог на сайті. Для того, щоб створити красивий блог адміністратор повинен сам 
буде вказувати деякі теги при додаванні нового блогу. На малюнках нижче можна 
переглянути форму, і як саме працює попередній перегляд блогу. 
 
Рисунок 3.9 – Вигляд форми «додавання новин» 
Арк . 
ЧДТУ 232227.001 ПЗ 
 35 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
 
Рисунок 3.10- Попередній перегляд новини 
Для реалізації цього коду в мене є окрема сторінка яка копією сторінки 
новин, але засіб передачі id новини яку саме користувач вибрав відсутній, замість 
цього ми передаємо текст який користувач написав і переглядаємо як він буде 
відображатися на сайті. 
 
 
Рисунок 3.11 – Код який дає можливість зробити попередній перегляд. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 36 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
 Після того як адміністратор перегляне чи все коректно відображається 
він збереже текст. 
Далі реалізував форму «перегляд таблиць», тут адмін зможе переглядати 
всі дані таблиць. 
 
Рисунок 3.12 – Вигляд форми «перегляд таблиць» 
 Після того як адмін вибере яку саме хоче переглянути таблицю отримає дані 
в формі таблиці з певної таблиці БД.  
  
Рисунок 3.13 – Вигляд форми «перегляд таблиць» 
Після цього перейшов до реалізації останьої форми на адмін панелі, і це 
«перегляд повідомлень до служби підтримки». Форма показує повідомлення які 
надійшли від користувачів 
• Перегляд кожного повідомлення 
• Видалення повідомлення «якщо воно було без певного сенсу» 
Арк . 
ЧДТУ 232227.001 ПЗ 
 37 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
• Відповідь користувачам на їхнє запитання 
Форма має наступний вигляд 
 
Рисунок 3.14 – Вигляд форми «перегляд повідомлень до служби підтримки» 
На цьому можна сказати, що реалізація сайту завершена, але в майбутньому 
можна додати такий функціонал як: досягнення гравців, таблиця лідерів трас, 
створення окремого чату для друзів, також створити окремий чат для адмінів, 
додати можливість створення опитувань на сайті. 
 
3.2.3. Розробка гри 
 
 Розробку гри я розпочав з встановлення Unity та перегляду аналогів які 
описав в своїй дипломній роботі. 
На сайті Unity скачав готові безкоштовні асети, щоб не трати час на 
малювання графіки. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 38 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Скачав бібліотеку Photon для можливості створювати онлайн перегони, і 
перейшов до реалізації. 
Перше, що я розпочав створювати це сцену майбутньої авторизації де 
гравці будуть виконувати авторизацію через гугл, але на даний момент вона не 
буде реалізована. Тому цю сцену я використовую як перенаправлення по натиску 
кнопки на головне меню 
 
Рисунок 3.16 – Фото авторизації гри 
Далі перейшов до реалізації завантажувальної сцени, вона буде 
відображатись кожного разу коли буде відбуватись перехід між сценами 
 
Арк . 
ЧДТУ 232227.001 ПЗ 
 39 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Рисунок 3.17 – Фото завантажувальної сцени 
Тепер переходимо до реалізації головного меню, від нього ідуть подальші 
переходи на інші сцени, але завжди є можливість вернутись на головне меню. 
На головному меню відображені такі кнопки: лідери трас, мультиплеєр, 
налаштування. 
Також на головному меню реалізований вибір авто, для дипломної роботи 
було вирішено не робити заблоковані авто які потрібно купити, а надали 
можливість вибрати будь яке авто, і на ньому поїхати заїзд 
 
Рисунок 3.18 – Фото головного меню 
Кнопка мультиплеєра переводить нас в лоббі заїзду, де Photon 
підключається до рандомної кімнати, а якщо її немає то створює свою кімнату. 
Тут гравці очікують початку перегон.  
Арк . 
ЧДТУ 232227.001 ПЗ 
 40 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
 
Рисунок 3.19 – Фото лобби 
Після того, як таймер доходить до 0 всіх гравців перекидає на трасу, і там 
розпочинається відлік часу до старту, і після проходження траси появляється 
список хто який приїхав, після закінчення гонки користувач може вийти в меню. 
 
Рисунок 3.21 – Фото заїзду 
Після розробки лобі і заїзду, переходжу до створення можливості вибору 
керування автомобілем. В налаштуваннях буде запропоновано ввімкнути авто-газ, 
а також вибрати тип керування авто.  
Арк . 
ЧДТУ 232227.001 ПЗ 
 41 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
 
Рисунок 3.23 – Фото налаштувань управління 
 
3.3. Тестування продукту. 
 
Після реалізації продукту переходжу до його тестування, а саме виконую 
спочатку перевірку коректного відображення елеменентів на сайті та в грі. 
Проводжу функціональне тестування, і бачу, що всі завдання які ставились 
до сайту виконує, а саме реалізовані такі сторінки як:  Головна, Чат, Підтримка, 
Новини, Пошта, Авторизація, Регістрація. 
Кожна з цих сторінок перевірялась на коректне відображення та на 
виконання функцій які прописані в php файлі.  
Проводжу функціональне тестування сайту. 
На сторінці «головного меню» та «новини» було виявлено баг, що запис 
який виводиться з БД якщо він складається більше ніж з одного слова то не 
відкривається сторінка Блогу, щоб прочитати повну інформацію. Цей баг було 
виправлено. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 42 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
 
Рисунок 3.24 – Фото некоректного відображення 
Під час тестування було також виявлено деякі вразливості такі як не 
шифрування даних які відповідають за підключення до БД, а саме логіну і 
паролю. Ці вразливості також були виправлені. 
 
Рисунок 3.25 – Фото вразливостей які було виявлено 
Після цього перейшов до перевірки форми авторизацій та регістрації і 
переглянув як вони працюють. Багів не було виявлено і після цього перейшов до 
перевірки БД чи є якісь баги під час запису даних чи ні. 
Протестував всі запити які реалізовані в мене на сайті і ніяких багів не 
було виявлено.  
Після перевірки сайту виконую перевірку гри на функціональність. 
В головному меню, було виявлено баг, що вибрані автомобілі спавнились 
один на одного, і минулий авто не видалявся. На фото нижче відображено як 
виглядав цей баг. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 43 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Рисунок 3.26 – Фото бага яке було виявлено 
Далі перевірив інші функції гри, і багів не було виявлено. 
Після виконання функціонального тестування перейшов до тестування 
дизайну сайту. 
Сайт відповідає кольорам своєї тематиці але під час перевірки на коректне 
відображення під час зміни розширення екрану було виявлено некоретне 
відображення елементів. 
Рисунок 3.27 – Фото некоректного відображення елементів 
Дизайн гри має дещо спірний вигляд, але свого розробника він 
задовольняє. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 44 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
F патерн тестування, під час додавання нового запису було виявлено, що 
сайт трохи не відповідає цьому патерну, і для вирішення цього було вирішено 
змінити максимальний розмір ширини блогу, для того, щоб текст більше підходив 
для тестування F патерну. 
Тестування безпеки даних: 
В грі ніякі дані користувачів не використовуються і тому проводити 
тестування безпеки даних тут не будемо, а на сайті потрібно це тестування 
виконати.  
Після тестування сайту було виявлено, що сайт має декілька можливостей 
отримати доступ до сайту, а саме використати sql інєкцію, або знайти файл в 
якому є записаний пароль і логін до адмін панелі, і зайшовши в неї нанести вред 
сайту. 
Рисунок 3.28 – Фото місця можливої sql ін’єкції, а також викраденя логіну та 
паролю 
Виконую тестування продуктивності, і після виконання можу сказати, що 
сайт працює дуже добре, а в грі є деякі нюанси такі як. 
• Тривала загрузка траси після переходу з лобби на неї, що створює 
дискомфорт. 
• Падає фпс під час перегон на трасі, що робить менш привабливим гру. 
 Проводжу тестування навігації і можу сказати, що сайт перенаправляє на 
всі сторінки які повинен. 
Тестування навігації гри також показала себе чудово, що дуже сильно 
радує. Гра розроблена для версій android 5.0, тому проблем з сумісністю не 
повинно виникнути. 
Проводжу негативне тестування на сайті, зайшов в чат і в полі де треба 
вводити повідомлення поставив пробіл і натиснув кнопку відправити, і побачив, 
що повідомлення відправилось, а повинна була будь помилка, що поле пусте. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 45 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Рисунок 3.29 – Фото місця можливої sql ін’єкції, а також викрадення логіну та 
паролю 
Можу сказати, що тестування показало які сайт та гра має недоліки, для 
того, щоб в майбутньому їх виправити. 
 
3.4. Порівняння з аналогами 
 
Після реалізації своєї дипломної роботи можу провести порівняння за 
аналогами які я вибрав для свого проекту. І розпочнемо ми з сайту. 
Таблиця 3.4.1 – Порівняння з аналогами сайту 
Назва функції Мій сайт Сайт Forza horizon 
Перегляд новин + + 
Можливість + - 
спілкування з гравцями 
Надіслати повідомлення + + 
підтримці 
Авторизація та + + 
регістрація 
Скачати гру з сайта + - 
Перегляд досягнень в - + 
грі 
Арк . 
ЧДТУ 232227.001 ПЗ 
 46 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Як бачимо мій сайт має деяку перевагу, але я як розробник не вважаю, що 
він краще,  а навпаки мені мій сайт не повністю подобається тому що там не 
реалізовані повністю ті функції які хотілось би створити там. 
В плані дизайну мій сайт трохи програє, але в в загальному плані можна 
сказати, що дизайн в них однаковий, якщо мені створити більш плавні переходи з 
малюнка на просто кольоровий фон, і додати анімовані фотографії то мій сайт 
буде рівня аналогу. 
Що ж давайте переглянемо тепер як моя гра зможе конкурувати з 
аналогами і які в них є переваги над моєю грою.  
Таблиця 3.4.2 – Порівняння з аналогами гри 
Назва Моя гра Rally Fury Drag racing: 
вуличні перегони 
3д графіка + + - 
Авторизація через - - + 
гугл 
Онлайн перегони в + + + 
реальному часі 
Можливість + + -(так як це 2д гра 
вибрати тип то керування авто 
керування не потрібне як 
таке) 
Онлайн чат  - - + 
Характеристики - + + 
авто 
Налаштування кпп - - + 
Таблиця рекордів - - + 
Відсутність + - + 
реклами  
Арк . 
ЧДТУ 232227.001 ПЗ 
 47 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
Що ж переглядаючи таблицю можна сказати, що гра не краще своїх 
аналогів, і що її потрібно ще доробляти для того, щоб можна було конкурувати зі 
своїми аналогами. 
Якщо судити з економічної точки зору, то гра ще сира і її потрібно 
дороблювати, для того, щоб як тільки вона вийде офіційно в реліз могла отримати 
шалену популярність в фанатів цього жанру, і перевершити своїх аналогів. Так як 
в грі немає ніякої монетизації, то вона буде тільки приносити витрати, але якщо її 
доробити і залишити на Photon сервері з 20 лише користувачами, то вона не 
приноситиме ніяких витрат розробнику. 
  
Арк . 
ЧДТУ 232227.001 ПЗ 
 48 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
ВИСНОВКИ 
Після завершення роботи над своїм дипломним проектом можу сказати, 
що сайт мене повністю задовольняє, а гра ще потребує коректив. 
Після успішного завершення моєї дипломної роботи ми досягли наступних 
результатів: 
• Розроблено нову гру для користувачів, використовуючи Unity та мову C#. 
Гра відповідає вимогам та очікуванням наших цільових користувачів. 
• Задоволено потреби у нових іграх, пропонуючи інноваційний та 
захоплюючий геймплей. 
• Був проведений детальний аналіз готового продукту, включаючи виявлення 
та виправлення можливих помилок та недоліків. 
• Розроблений веб-сайт для ком'юніті гри, використовуючи PHP та деякі 
елементи JavaScript. Сайт надає користувачам доступ до інформації про гру, 
оновлення, форуми та інші спільноті функції. 
Мій продукт на даний момент не є економічно ефективним, і випускати 
його в реліз немає сенсу, так як сайт без гри не матиме змоги жити, а гру потрібно 
ще доробляти. 
Для сайту в майбутньому, я б додав ще б такі функції: 
• Додавання авторизації через гугл 
• Створив би досягнення для гравців 
• Покращив дизайн 
• Додав додатковий функціонал для адмінів такий як: створення опитування, 
бан гравця, відключення можливостей писати в чат. 
Для гри б я додав ще б такий функціонал: 
• Додав авторизацію через гугл 
• Створив таблицю рекордів 
• Покращив онлайн перегони, а саме передачу даних 
• Додав би такі механіки як: налаштування кпп, підвіски 
  
Арк . 
ЧДТУ 232227.001 ПЗ 
 49 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ 
1. Майкл Портер. Конкурентна стратегія. Техніки аналізу галузей і 
конкурентів, 2019. 100 с. 
2. Бабетт Бенсуссан, Крейг Флейшер. Аналіз бізнесу та конкуренції: 
ефективне застосування нових і класичних методів, 2008. 80 с. 
3. Ліз Вернон. Аналіз конкурентів: Як перетворити інформацію на успіх, 
2010. 70 с. 
4. Посилання на аналог Rally Fury ,  URL: 
https://play.google.com/store/apps/details?id=com.refuelgames.rally&hl=en_US 
5. Посилання на аналог Drag racing:вуличні перегони, URL: 
https://play.google.com/store/apps/details?id=mobi.square.sr.android&hl=ru 
6. Посилання на сайт аналога Forza Horizon,  URL: 
https://forums.forza.net/ 
7. Документація мови PHP, URL: https://www.php.net/manual/ru/index.php 
8. Мэтт Зандстра. PHP 8: об'єкти, шаблони та методики програмування, 
2021. 120 с. 
9. Кевин Татро, Питер Макинтайнер. Створюємо динамічні веб-сайти на 
PHP, 2021. 125 с.  
10.  Кевін Янк. PHP та MySQL: Від новачка до ніндзя, 7-е видання, 2020. 
50 с.  
11.  Документація СУБД phpmyadmin, URL: 
https://docs.phpmyadmin.net/en/latest/ 
12.  Олена Бенкен, Геннадій Самков. AJAX. Програмування для 
Інтернету, 2013. 43 с.  
13.  Дейв Крейн, Эрик Паскарелло, Даррен Джеймс. Ajax в действии, 
2007. 70 с. 
14.  Ілля Кантор. Сучасний підручник JavaScript, 2020. 20 с. 
15.  Флэнаган Дэвид. JavaScript. Подробное руководство, 2011, 31 с. 
16. Бен Фрэйн. Чуйний дизайн на HTML5 та CSS3 для будь-яких 
пристроїв, 2014. 80 с. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 50 
Зм н. Арк. №  докум. Підпис Дата 
 
 
 
17.  Джона Дакетта. HTML та CSS. Розробка та дизайн веб-сайтів, 2011. 
92 с. 
18.  Документація мови C#, URL: https://learn.microsoft.com/ru-
ru/dotnet/csharp/ 
19.  Джо Хокінсон. Unity у дії. Мультиплатформна розробка на C#, 2019. 
53 с.  
20. Майк Гейг. Розробка ігор на Unity 2018 за 24 години, 2020. 26 с. 
21. Документація бібліотеки Photon, URL: 
https://doc.photonengine.com/fusion/current/getting-started/fusion-intro 
22.  Роман Савін. Тестування DOT COM, або Посібник з жорстокого 
поводження з багами в інтернет стартапах, 2018. 10 с. 
23.  Борис Бейзер. Тестування чорного ящика. Технології 
функціонального тестування програмного забезпечення і систем, 2006, 20 с. 
24.  Святослав Куликов. Тестування програмного забезпечення. Базовий 
курс, 2019. 23 с. 
25. Джеймс А. Уіттакер. Як зламати програмне забезпечення: Практичний 
посібник з тестування, 2003. 10 с. 
Арк . 
ЧДТУ 232227.001 ПЗ 
 51 
Зм н. Арк. №  докум. Підпис Дата 
 
52 
 
ДОДАТОК А 
 
 
                                                                    ЗАТВЕРДЖЕНО 
                                                                    Зав.кафедри ІТП 
____________Тетяна ПРОКОПЕНКО 
“_____” _____________2023р. 
 
 
 
 
Коди сайту та гри 
 
 
Специфікація 
482 ЧДТУ 232227 – 01 
Листів 2 
 
        Н 
 
Розробник                            _____________                                   Роман БАКУМЕНКО 
Керівник                              _____________                                   Ярослав ТАРАСЕНКО  
Н. контроль                          _____________                                  Ярослав ТАРАСЕНКО 
 
                                                                                                                          
 
 
 
 
Черкаси, 2023  
53 
 
 
482 ЧДТУ 232227 – 01 
Позначення Найменування Примітка 
482 ЧДТУ 222144-01 12 01-1 Текст програми  
482 ЧДТУ 222144-01 12 01-2 Текст програми   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
 
54 
ДОДАТОК Б 
Код сайту  
 
 
 
 
 
 
 
482 ЧДТУ 232227 –  01 12 01 - 1 
Текст програми  
Листів 20 
 
 
                        Н 
 
Розробник                            __________________              Роман БАКУМЕНКО  
 
 
   
 
 
 
 
 
 
 
 
Черкаси, 2023  
55 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
Клієнтська частина 
Код index.php
   <a class="head_button"  
<!doctype html> href="form_send_mes.php">Підтримка</a> 
<html>   <a class="head_button"  
<head> href="autorization.php">Авторизація</a> 
<meta charset="utf-8">   <a class="head_button"  
<link rel="stylesheet" type="text/css" href="regiztraion.php">Регістрація</a> 
href="style/style.css">   <a class="head_button"  
<title>Головна</title> href="email.php">Пошта</a> 
<script>  </header> 
 function sendData(category, type) {  <div class="content"> 
    var xhr = new XMLHttpRequest();   <div class="short_des"> 
    xhr.onload = function() {    <h3 
        if (xhr.status === 200) { class="short_text">Машини</br> 
            var response = xhr.responseText;     Швидкість</br> 
   if(type == 'last_news'){     Конкуренція</br> 
             var output =    <button 
document.getElementById('content_new_news'); class="download">Скачати гру</button> 
   }    </h3> 
   if(type == 'actual'){    > 
             var output =   </div> 
document.getElementById('content_new_newss');   <div class="content_1"> 
   }    <h2 
   if(type == 'open_news'){  class="last_news">Останні новини 
       window.location.href =     <div 
response; class="form_last_news"> 
   }      <a 
            output.innerHTML = response; // Встановити class="button_last" 
вміст елементу onclick="sendData('all','last_news')">Всі</a> 
        } else {      <a 
            console.error(xhr.statusText); class="button_last" 
        } onclick="sendData('community','last_news')">Ком'юніті</
    }; a> 
      <a 
    var method = 'POST'; class="button_last" 
    var url = 'view_db.php'; onclick="sendData('game','last_news')">Гра</a> 
      <a 
    xhr.open(method, url, true); class="button_last" 
    xhr.setRequestHeader('Content-Type', 'application/x- onclick="sendData('other','last_news')">Інше</a> 
www-form-urlencoded');     </div> 
    </h2> 
 var params = 'category=' +    <div 
encodeURIComponent(category) + '&type=' + id="content_new_news"> 
encodeURIComponent(type);    </div> 
    <a class="news_button"  
    xhr.send(params); href="news.php">Більше новин >></a> 
}   </div> 
document.addEventListener('DOMContentLoaded',   <div class="content_2"> 
function() {    <h2 
  // Ваш код, який потрібно виконати після class="last_news">Рекомендовані новини 
завантаження сторінки     <div 
  sendData('all','last_news'); class="form_last_news"> 
  sendData('all','actual');      <a 
}); class="button_last" 
</script> onclick="sendData('all','actual')">Всі</a> 
</head>      <a 
<body> class="button_last" 
 <header class="head"> onclick="sendData('community','actual')">Ком'юніті</a> 
  <a class="head_button"      <a 
href="index.php">Головна</a> class="button_last" 
  <a class="head_button"  onclick="sendData('game','actual')">Гра</a> 
href="news.php">Новини</a>      <a 
  <a class="head_button"  class="button_last" 
href="chat.php">Чат</a> onclick="sendData('other','actual')">Інше</a> 
    </div> 
   </h2> 
56 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
   <div   </div> 
id="content_new_newss"></div>     <div class="footer-bottom"> 
   <a class="news_button"     &copy; 2023 Всі права 
href="news.php">Більше новин >></a> захищені 
  </div>     </div> 
  <div class="forum">  </footer> 
   <h2>Спілкуйтесь з іншими </body> 
гравцями та розробниками в нас на сайті</h2> </html> 
   
   <p>На нашому сайті ви  
можете поспілкуватись в онлайн чаті з іншими  
гравцями, для цього вам потрібно авторизуватись якщо Код autorization.php 
у вас є обліковий запис на цьому сайті, а якщо немає <!-- Форма авторизації на сторінці --> 
тоді створити свій.</p> <!DOCTYPE html> 
   <a class="chat_url" <html> 
href="chat.php">Перейти в чат</a> <head> 
  </div>     <title>Авторизація</title> 
  <div class="support">  <link rel="stylesheet" type="text/css" 
   <h2>Якщо у вас є якісь href="style/style.css"> 
проблеми або ви хочете запронувати свої ідеї, напишіть </head> 
в підтримку</h2>  <body> 
   <p>Для того, щоб написати  <header class="head"> 
в підтримку в и повинні авторизуватись або створити   <a class="head_button" 
свій акаунт, як тільки адміністратори нададуть href="index.php">Головна</a> 
відповідь на ваше запитання ви зможете переглянути   <a class="head_button"  
його на пошті сайту.</p> href="news.php">Новини</a> 
   <a class="chat_url"   <a class="head_button"  
href="chat.php">Написати підтримці</a> href="chat.php">Чат</a> 
  </div>   <a class="head_button"  
 </div> href="form_send_mes.php">Підтримка</a> 
 <footer class="footer">   <a class="head_button"  
   <div class="footer-content"> href="autorization.php">Авторизація</a> 
   <div class="footer-left">   <a class="head_button"  
     <h4>Контактна href="regiztraion.php">Регістрація</a> 
інформація</h4>   <a class="head_button"  
     <p>Телефон: href="email.php">Пошта</a> 
+380937741599</p>  </header> 
     <p>Email:  <div class="autorization"> 
[email protected]</p>   <h2>Введіть логін і пароль</h2> 
   </div>   <form method="post" > 
   <div class="footer-middle">    <table> 
     <h4>Навігація</h4>    <tr> 
     <ul>      <td><label 
    <li><a class="label">Ім'я користувача:</label></td> 
class="head_button" href="index.php">Головна</a></li>      <td><input class="text" 
    <li><a type="text" name="username" required></td> 
class="head_button" href="news.php">Новини</a></li>    </tr> 
    <li><a    <tr> 
class="head_button" href="chat.php">Чат</a></li>      <td><label 
    <li><a class="label">Пароль:</label></td> 
class="head_button" href="email.php">Пошта</a></li>      <td><input class="text" 
     </ul> type="password" name="password" required></td> 
   </div>    </tr> 
   <div class="footer-right">     </table> 
     <h4>Соціальні     <input class="chek_button" 
мережі</h4> type="submit" name="clikc" value="Увійти"></br> 
     <ul class="social-links">     <a class="chek_button"  
    <li><a href="regiztraion.php">Регістрація</a>  
class="head_button"   
href="https://facebook.com">Facebook</a></li>    <?php 
    <li><a include("autorization_chek.php"); ?> 
class="head_button"   </form> 
href="https://twitter.com">Twitter</a></li>  </div> 
    <li><a </body> 
class="head_button" </html> 
href="https://instagram.com">Instagram</a></li> 
     </ul> Код chat.php 
   </div> <!doctype html> 
57 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
<html> <meta charset="utf-8"> 
<head> <link rel="stylesheet" type="text/css" 
<meta charset="utf-8"> href="style/style.css"> 
<link rel="stylesheet" type="text/css" <title>Untitled Document</title> 
href="style/style.css"> </head> 
<title>Untitled Document</title>  
<script> <body> 
   function sendMessage() {  <header class="head"> 
        var message =   <a class="head_button" 
document.getElementById("messageInput").value; href="index.php">Головна</a> 
   <a class="head_button"  
        var xhr = new XMLHttpRequest(); href="news.php">Новини</a> 
        xhr.open("POST", "chat_user.php", true);   <a class="head_button"  
        xhr.setRequestHeader("Content-Type", "application/x- href="chat.php">Чат</a> 
www-form-urlencoded");   <a class="head_button"  
        xhr.onreadystatechange = function () { href="form_send_mes.php">Підтримка</a> 
            if (xhr.readyState === XMLHttpRequest.DONE   <a class="head_button"  
&& xhr.status === 200) { href="autorization.php">Авторизація</a> 
                document.getElementById("chat").innerHTML =   <a class="head_button"  
xhr.responseText; href="regiztraion.php">Регістрація</a> 
            }   <a class="head_button"  
        }; href="email.php">Пошта</a> 
        xhr.send("message=" +  </header> 
encodeURIComponent(message));  <div class="email"> 
    }   <?php include("email_view.php") ?> 
 </script>   <?= $data ?> 
</head>  </div> 
<body> </body> 
 <header class="head"> </html> 
  <a class="head_button" Код news.php 
href="index.php">Головна</a> <!doctype html> 
  <a class="head_button"  <html> 
href="news.php">Новини</a> <head> 
  <a class="head_button"  <meta charset="utf-8"> 
href="chat.php">Чат</a> <link rel="stylesheet" type="text/css" 
  <a class="head_button"  href="style/style.css"> 
href="form_send_mes.php">Підтримка</a> <title>Новини</title> 
  <a class="head_button"   <script> 
href="autorization.php">Авторизація</a>  function sendData(category, type) { 
  <a class="head_button"      var xhr = new XMLHttpRequest(); 
href="regiztraion.php">Регістрація</a>     xhr.onload = function() { 
  <a class="head_button"          if (xhr.status === 200) { 
href="email.php">Пошта</a>             var response = xhr.responseText; 
 </header>    if(type == 'actual_news'){ 
 <h2 style="text-align: center">Чат користувачів,              var output = 
тут ви можете спілкуватися з гравцями та document.getElementById('content_new_news'); 
розробниками в онлайні</h2>              output.innerHTML = response; 
 <div class="content_block">    } 
  <form id="myForm">    if(type == 'history_news'){ 
   <textarea type="text"              var output = 
name="text" id="messageInput" placeholder="Введіть document.getElementById('content_new_newss'); 
повідомлення"></textarea>              output.innerHTML = response; 
     <button type="button"    } 
id="messageButton" onclick="sendMessage()"    if(type == 'open_news'){  
>Відправити</button>        window.location.href = 
  </form> response; 
  <div id="chat">    } // Встановити вміст 
     <?php елементу 
include("chat_user.php"); ?>         } else { 
  </div>             console.error(xhr.statusText); 
 </div>         } 
</body>     }; 
</html>  
Код email.php     var method = 'POST'; 
<!doctype html>     var url = 'arhivnews.php'; 
<html>  
<head>     xhr.open(method, url, true); 
58 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
    xhr.setRequestHeader('Content-Type', 'application/x-    <div 
www-form-urlencoded'); id="content_newnewss"><?php 
 include("test.php");?></div> 
 var params = 'category=' +   </div> 
encodeURIComponent(category) + '&type=' +  </div> 
encodeURIComponent(type);  <footer class="footer"> 
    <div class="footer-content"> 
    xhr.send(params);    <div class="footer-left"> 
}      <h4>Контактна 
document.addEventListener('DOMContentLoaded', інформація</h4> 
function() {      <p>Телефон: 
  // Ваш код, який потрібно виконат +380937741599</p> 
 sendData('all','actual_news');      <p>Email: 
});</script> [email protected]</p> 
</head>    </div> 
<body>    <div class="footer-middle"> 
 <header class="head">      <h4>Навігація</h4> 
  <a class="head_button"      <ul> 
href="index.php">Головна</a>     <li><a 
  <a class="head_button"  class="head_button" href="index.php">Головна</a></li> 
href="news.php">Новини</a>     <li><a 
  <a class="head_button"  class="head_button" href="news.php">Новини</a></li> 
href="chat.php">Чат</a>     <li><a 
  <a class="head_button"  class="head_button" href="chat.php">Чат</a></li> 
href="form_send_mes.php">Підтримка</a>     <li><a 
  <a class="head_button"  class="head_button" href="email.php">Пошта</a></li> 
href="autorization.php">Авторизація</a>      </ul> 
  <a class="head_button"     </div> 
href="regiztraion.php">Регістрація</a>    <div class="footer-right"> 
  <a class="head_button"       <h4>Соціальні 
href="email.php">Пошта</a> мережі</h4> 
 </header>      <ul class="social-links"> 
 <div class="content_news_fon">     <li><a 
  <div class="content_news"> class="head_button" 
   <p href="https://facebook.com">Facebook</a></li> 
class="h2"><span>Новини</span><br>Тут ви можете     <li><a 
ознайомитись з усіма новинами які були за весь class="head_button" 
проміжок часу</p> href="https://twitter.com">Twitter</a></li> 
     </div>     <li><a 
 </div> class="head_button" 
 <div class="arhiv"> href="https://instagram.com">Instagram</a></li> 
  <div class="actual_news_all">       </ul> 
   <h2    </div> 
class="last_news">Рекомендовані новини   </div> 
    </h2>     <div class="footer-bottom"> 
   <div    &copy; 2023 Всі права 
id="content_new_news"></div> захищені 
  </div>     </div> 
  <div class="block_news_all">   </footer> 
   <h2 class="last_news">Всі </body> 
новини </html> 
     <div Код regiztraion.php 
class="form_last_news"> <!-- Форма авторизації на сторінці --> 
     <!DOCTYPE html> 
 <a class="button_last" <html> 
onclick="sendData('all')">Всі</a> <head> 
         <title>Авторизація</title> 
 <a class="button_last"  <link rel="stylesheet" type="text/css" 
onclick="sendData('community')">Ком'юніті</a> href="style/style.css"> 
     </head> 
 <a class="button_last" <body> 
onclick="sendData('game')">Гра</a>  <header class="head"> 
       <a class="head_button" 
 <a class="button_last" href="index.php">Головна</a> 
onclick="sendData('other')">Інше</a>   <a class="head_button"  
     </div> href="news.php">Новини</a> 
    </h2> 
59 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
  <a class="head_button"   </header> 
href="chat.php">Чат</a>  <div class="support_mess"> 
  <a class="head_button"    <p>Напишіть запитання яке ви 
href="form_send_mes.php">Підтримка</a> хочете поставити перед адміністраторами (якщо немає 
  <a class="head_button"  типу який охарактерезує вашу проблему то виберіть 
href="autorization.php">Авторизація</a> тип інше) </p> 
  <a class="head_button"    <form method="post" > 
href="regiztraion.php">Регістрація</a>    <table> 
  <a class="head_button"     <tr> 
href="email.php">Пошта</a>      <td><label 
 </header> class="label">Тип запитання:</label></td> 
 <div class="autorization">     <td><select 
  <h2>Введіть логін і пароль</h2> class="support_input" name='name_filter'> 
  <form method="post" >      <option 
   <table> value='game'>Гра</option> 
   <tr>      <option 
     <td><label value='debug'>Баги</option> 
class="label">Ім'я користувача:</label></td>      <option 
     <td><input class="text" value='new_ideas'>Нові ідеї</option> 
type="text" name="username" required></td>      <option 
   </tr> value='other'>Інше</option> 
   <tr>      </select> 
     <td><label     </td> 
class="label">Пароль:</label></td>    </tr> 
     <td><input class="text"    <tr> 
type="password" name="password" required></td>      <td><label 
   </tr> class="label">Текст запитання:</label></td> 
   <tr>      <td><textarea 
     <td><label class="support_input1" name="text" ></textarea></td> 
class="label">Повторіть пароль:</label></td>    </tr> 
     <td><input class="text"     </table> 
type="password" name="password" required></td>     <input class="chek_button" 
   </tr> type="submit" name="clikc" value="Надіслати 
    </table> дані"></br>  
    <input class="chek_button"    <?php 
type="submit" name="clikc" include("support_mess_save.php") ?>   
value="Зареєструватись"></br>      </form> 
   <?php  </div> 
include("reg_chek.php"); ?> <body> 
  </form> </body> 
 </div> </html> 
</body> Код support_mess_save.php 
</html> <?php  
Код form_send_mes.php session_start(); 
<!doctype html>  
<html>  
<head> if(isset($_POST['clikc']) and 
<meta charset="utf-8"> isset($_SESSION['username'])){ 
<link rel="stylesheet" type="text/css"   
href="style/style.css">  $username = "Admin"; 
<title>Новини</title>  $password = "Diplom2023"; 
</head>  $host = 'localhost';  // Хост, у нас все локально     
  <header class="head">  $db_name = 'race_db';   // Имя базы данных 
  <a class="head_button"  $link = mysqli_connect($host, $username, 
href="index.php">Головна</a> $password, $db_name);  
  <a class="head_button"   $date = date('Y-m-d'); 
href="news.php">Новини</a>  $sql = "INSERT INTO support_mes (type, text, 
  <a class="head_button"  username, date) VALUES ('{$_POST['name_filter']}', 
href="chat.php">Чат</a> '{$_POST['text']}', '{$_SESSION["username"]}', '$date')"; 
  <a class="head_button"   
href="form_send_mes.php">Підтримка</a>  if ($link->query($sql) === TRUE) { 
  <a class="head_button"    echo "Повідомлення успішно 
href="autorization.php">Авторизація</a> відправлене адміністраторам"; 
  <a class="head_button"   } else { 
href="regiztraion.php">Регістрація</a>   echo "Помилка відправлення 
  <a class="head_button"  повідомлення"; 
href="email.php">Пошта</a>  } 
60 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
}  
     // Перевірка введених даних в базі даних 
?>     $sql = "SELECT * FROM users WHERE username = 
Код arhivnews.php '$username' AND password = '$password'"; 
<?php     $result = $conn->query($sql); 
 $username = "Admin";  
 $password = "Diplom2023";     if ($result->num_rows == 1) { 
 $host = 'localhost';  // Хост, у нас все локально             // Користувача авторизовано успішно 
 $db_name = 'race_db';   // Имя базы данных         // Можна встановити сесію для зберігання 
 $link = mysqli_connect($host, $username, інформації про авторизацію 
$password, $db_name);          session_start(); 
         $_SESSION["username"] = $username; 
    $_SESSION['logged_in'] = true; 
 if (isset($_POST['category']) &&         header("Location: chat.php"); // Перенаправлення на 
isset($_POST['type']) && $_POST['type'] === сторінку вітання 
'actual_news') {     } else { 
     $sql = mysqli_query($link, 'SELECT * FROM         // Неправильні дані авторизації 
`news` WHERE choice ="yes" ORDER BY `date` DESC         echo "Неправильне ім'я користувача або пароль."; 
LIMIT 1');     } 
   while ($result = } 
mysqli_fetch_array($sql)) { ?> 
   echo "  
   <a class='newsblock' 
onclick=sendData('{$result['title']}','open_news') > Код chat_user.php 
   <img class='imgblock' <?php 
src='{$result['src_img1']}'> session_start(); 
   <h2>{$result['title']}</h2> if(isset($_POST['message']) && $_POST['message'] != ''){ 
   {$result['date']}</a>" ;                $host = 'localhost';   
   }     $user = 'root';    
 }     $pass = 'Diplom2023';  
     $db_name = 'race_db';    
 if (isset($_POST['category']) &&     $link = mysqli_connect($host, $user, $pass, $db_name); 
isset($_POST['type']) && $_POST['type'] ===  $date = date('H:i:s');      
'open_news') {  $text = $_POST['message'];        
    $username = $_SESSION['username'];  
  session_start();  
     $sql = mysqli_query($link, "SELECT * FROM  // Підготовка SQL-запиту з параметрами 
news WHERE title ={$_POST['category']}");  $sql = "INSERT INTO chat_history (date, text, 
   while ($result = username) VALUES (?, ?, ?)"; 
mysqli_fetch_array($sql)) {  $stmt = $link->prepare($sql); 
   $_SESSION['preview'] =   $stmt->bind_param("sss", $date, $text, 
$result['category'];          $username); 
   }  $stmt->execute(); 
   echo "test_site.php";    
 } } 
?>  
Код autorization_chek.php if (isset($_SESSION['logged_in']) && 
<?php $_SESSION['logged_in'] == true || 
// Підключення до бази даних isset($_POST['message']) && $_POST['message'] != '') { 
$servername = "localhost";  $data = "<table>"; 
$username = "root";     $host = 'localhost';   
$password = "Diplom2023";     $user = 'root';     
$dbname = "race_db";     $pass = 'Diplom2023';  
     $db_name = 'race_db';    
$conn = new mysqli($servername, $username, $password,     $link = mysqli_connect($host, $user, $pass, $db_name);  
$dbname);     $deff = 0; 
if ($conn->connect_error) {   
    die("Помилка підключення до бази даних: " . $conn-     $sql = mysqli_query($link, 'SELECT 
>connect_error); `id`,`date`,`text`,`username` FROM `chat_history` ORDER 
} BY id DESC LIMIT 100'); 
     while ($result = mysqli_fetch_array($sql)) { 
// Перевірка, чи користувач відправив форму         if ($result['username'] == $_SESSION['username']) { 
авторизації     $data .= "<tr> 
if (isset($_POST['clikc'])) {                 <td></td><td class='chat_td1'><username 
    // Отримання даних з форми class='sup1'>{$result['username']}</username></br><text 
    $username = $_POST["username"]; class='sub1'>{$result['text']} 
    $password = $_POST["password"]; <sub>{$result['date']}</sub></td>"; 
61 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
        } else { else{ 
            $data .= "<tr>  $data = "<p>Авторизуйтесь за посиланням 
                <td class='chat_td'><username нижче, або зарегеструйтесь для можливості 
class='sup'>{$result['username']}</username></br><text спілкуватись з іншими гравцями. 
class='sub'>{$result['text']}    <a 
<sub>{$result['date']}</sub></text></td><td></td>"; href='autorization.php'>Авторизація</a> 
        }    <a 
    } href='regiztraion.php'>Регістрація</a></p>"; 
 } 
    $data .= "</table>"; if(isset($_POST['clikc'])){ 
} else {  $data = ""; 
    $data = "<p>Авторизуйтесь за посиланням нижче, або  $host = 'localhost';  // Хост, у нас все локально 
зарегеструйтесь для можливості спілкуватись з іншими     $user = 'root';    // Имя созданного вами пользователя 
гравцями.     $pass = 'Diplom2023'; // Установленный вами пароль 
        <a href='autorization.php'>Авторизація</a> пользователю 
        <a href='regiztraion.php'>Регістрація</a></p>";     $db_name = 'race_db';   // Имя базы данных 
      $link = mysqli_connect($host, $user, $pass, $db_name); 
} // Соединяемся с базой 
echo($data);     $deff=0; 
?>   $sql = mysqli_query($link, "SELECT * FROM 
Код email_view.php support_mes_ready WHERE username = 
<?php '{$_SESSION['username']}'AND id 
session_start(); ='{$_POST['idvalue']}'"); 
if($_SESSION['logged_in'] == true){    while ($result = 
 $data = "<h2>Тут відображаються всі mysqli_fetch_array($sql)) { 
повідомлення які ви відправили адміністрації та вони         $data = "<div class='email_block'> 
написали вам відповідь</h2>   <h2>Ознайомтесь з відповіддю 
 <form method='post'><table class='table'> адміністрації<h2> 
  <tr>   <p>Ваше повідомлення: 
   <td class='table_numb'>Дата {$result['text']}</p> 
відправлення повідомлення</td>   <p>Повідомлення адміністрації: 
   <td class='table_numb'>Нік {$result['support_mes']}</p> 
користувача</td>   </div"; 
   <td class='table_numb'>Текст     
користувача</td>  } 
   <td class='table_numb'></td>  $data = $data . "</table></form>"; 
  </tr>"; } 
 $host = 'localhost';  // Хост, у нас все локально ?>  
    $user = 'root';    // Имя созданного вами пользователя Код admin_panel.php 
    $pass = 'Diplom2023'; // Установленный вами пароль <?php 
пользователю // Підключення до бази даних 
    $db_name = 'race_db';   // Имя базы данных $servername = "localhost"; 
    $link = mysqli_connect($host, $user, $pass, $db_name); $username = "root"; 
// Соединяемся с базой $password = "Diplom2023"; 
    $deff=0; $dbname = "race_db"; 
    // Ругаемся, если соединение установить не удалось  
    $sql = mysqli_query($link, "SELECT * FROM $conn = new mysqli($servername, $username, $password, 
`support_mes_ready` WHERE $dbname); 
username='{$_SESSION['username']}'"); if ($conn->connect_error) { 
   while ($result =     die("Помилка підключення до бази даних: " . $conn-
mysqli_fetch_array($sql)) { >connect_error); 
        $data = $data . "<tr> } 
  <td  
class='table_numb'>{$result['date']}</td> // Перевірка, чи користувач відправив форму реєстрації 
  <td if (isset($_POST['clikc'])) { 
class='table_numb'>{$result['username']}</td>     // Отримання даних з форми 
  <td     $username = $_POST["username"]; 
class='table_numb'>{$result['text']}</td>     $password = $_POST["password"]; 
  <td class='table_numb'><input  
type='hidden' name='idvalue' value='{$result['id']}'>     // Перевірка, чи користувач з таким іменем вже існує 
  <button class='button_email'     $check_query = "SELECT * FROM users WHERE 
name='clikc'> Переглянути відповідь </button></td> username = '$username'"; 
   </tr>";     $check_result = $conn->query($check_query); 
     
 }     if ($check_result->num_rows > 0) { 
 $data = $data . "</table></form>";         echo "Користувач з таким іменем вже існує."; 
}     } else { 
62 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
        // Додавання нового користувача до бази даних <link rel="stylesheet" type="text/css" 
        $insert_query = "INSERT INTO users (username, href="style/style.css"> 
password) VALUES ('$username', '$password')"; <title>Untitled Document</title> 
        if ($conn->query($insert_query) === TRUE) { </head> 
            echo "Реєстрація пройшла успішно."; <body> 
   header("Location:  <header class="head"> 
index.php");   <a class="head_button" 
        } else { href="index.php">Головна</a> 
            echo "Помилка реєстрації: " . $conn->error;   <a class="head_button"  
        } href="news.php">Новини</a> 
    }   <a class="head_button"  
} href="chat.php">Чат</a> 
?>   <a class="head_button"  
 href="form_send_mes.php">Підтримка</a> 
Код   <a class="head_button"  
test.php href="autorization.php">Авторизація</a> 
<?php   <a class="head_button"  
 $username = "Admin"; href="regiztraion.php">Регістрація</a> 
 $password = "Diplom2023";   <a class="head_button"  
 $host = 'localhost';  // Хост, у нас все локально     href="email.php">Пошта</a> 
 $db_name = 'race_db';   // Имя базы данных  </header> 
 $link = mysqli_connect($host, $username,  <div class="news"> 
$password, $db_name);    <?php include("preview.php") ?> 
 $perPage = 8;  </div> 
    $page = isset($_GET['page']) ? $_GET['page'] : 1; </body> 
    $offset = ($page - 1) * $perPage; </html> 
 
    $query = "SELECT * FROM `news` ORDER BY `date` Код admin.php 
DESC LIMIT $offset, $perPage"; <!doctype html> 
    $result = mysqli_query($link, $query); <html> 
 <head> 
    // Виведення новин <meta charset="utf-8"> 
    while ($row = mysqli_fetch_assoc($result)) { <link rel="stylesheet" type="text/css" 
        // Виведення даних новини href="style/style.css"> 
        echo " <title>Адмін панель</title> 
        <a class='newsblock' </head> 
onclick=sendData('{$row['title']}','open_news') >   
        <img class='imgblock' src='{$row['src_img1']}'> <body> 
        <h2>{$row['title']}</h2>  <form class="autorization_form" 
        {$row['date']}</a>"; method="post"> 
    }   <h2>Введіть правильний логін та 
 пароль</h2> 
    // Запит до БД для отримання загальної кількості   <label 
записів class="autorization_label"for="username">Логін:</label> 
    $totalQuery = "SELECT COUNT(*) as total FROM     <input class="autorization_input" 
`news`"; type="text" id="username" name="username"> 
    $totalResult = mysqli_query($link, $totalQuery);  
    $totalRows = mysqli_fetch_assoc($totalResult)['total'];     <label class="autorization_label" 
 for="password">Пароль:</label> 
    // Обчислення загальної кількості сторінок     <input class="autorization_input" 
    $totalPages = ceil($totalRows / $perPage); type="password" id="password" name="password"> 
 echo "</div><div class='page-numbers'>";   <button class="autorization_button" 
    // Виведення кнопок пагінації type="submit" name="click">Ввійти</button> 
    for ($i = 1; $i <= $totalPages; $i++) {  </form> 
        // Виведення посилань на сторінки  
        echo "<a class='list_numb'  <?php include("chek_autorization.php") ?> 
href='news.php?page=$i'>$i</a>"; </body> 
    } </html> 
 Код admin_panel.php 
?> <!doctype html> 
Адмінська частина <html> 
Код <head> 
news_preview.php <meta charset="utf-8"> 
<!doctype html> <title>Адмін панель</title> 
<html> <link rel="stylesheet" type="text/css" 
<head> href="style/style.css"> 
<meta charset="utf-8">  <script> 
 function changeInputType() { 
63 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
   var select =   header("Location: 
document.getElementById("inputTypeSelect"); http://diplom/admin_panel.php"); 
   var selectedValue = select.value;  } 
 } 
   var input =  
document.getElementById("myInput"); ?>  
 Код panel.php 
   input.type = selectedValue; <?php 
 session_start(); 
 } $titleValue = ""; 
 </script> $src_img1Value = ""; 
</head> $src_img2Value = ""; 
<body> $textValue = ""; 
 <?php include("panel.php") ?> $data = ""; 
 <h4>Вітаю в адмін панелі</h4> $username = $_SESSION['username']; 
 <div> $password = $_SESSION['password']; 
  <form class="admin_panel" $host = 'localhost';  // Хост, у нас все локально     
method="post"> $db_name = 'race_db';   // Имя базы данных 
   <button class="panel_butt" $link = mysqli_connect($host, $username, $password, 
name="new_news">Додати нову новину</button></br> $db_name);  
   <button class="panel_butt" // Отримання введеного користувачем логіна і пароля 
name="view_db">Перегляд таблиць бази  
даних</button></br> // Додавання нових новин 
   <button class="panel_butt" if(isset($_POST['new_news'])){ 
name="vied_mess_people">Перегляд повідомлень до  $_SESSION['last_click'] = 'new_news'; 
служби підтримки</button></br>   $data = "<form method='post' 
  </form> enctype='multipart/form-data'> 
  <div class="admin_block">     <label 
    <?= $data ?> class='label_form'>Введіть заголовок 
    блогу</label><input class='input_form' name='title'></br> 
  </div>     <label 
 </div> class='label_form'>Це рекомендована новина?</label> 
</body>     <input type='radio' 
</html> id='option-yes' name='choice' value='yes'> 
Код preview.php     <label for='option-
<?php yes'>Так</label> 
     <input type='radio' 
session_start(); id='option-no' name='choice' value='no'> 
echo $_SESSION['preview']     <label for='option-
?>  no'>Ні</label> 
Код chek_autorization.php     <label 
<?php class='label_form'>Виберіть категорію</label><select 
error_reporting(0); class='select_admin' id='inputTypeSelect' name='category' 
// Отримання введеного користувачем логіна і пароля onchange='changeInputType()'> 
if(isset($_POST['click'])){        <option 
 $username = $_POST['username']; value='game'>Гра</option> 
 $password = $_POST['password'];        <option 
 $host = 'localhost';  // Хост, у нас все локально     value='community'>Ком'юніті</option> 
 $db_name = 'race_db';   // Имя базы данных        <option 
 try{ value='other'>Інше</option> 
  $link = mysqli_connect($host,     </select>  
$username, $password, $db_name); // Соединяемся с     <label 
базой class='label_form'>Виберіть фото</label><input 
 } catch (Exception $e){ type='file' class='file-input' name='src_img1'></br> 
  $link = false;     <label 
 } class='label_form'>Виберіть фото</label><input 
 if (!$link) { type='file' class='file-input' name='src_img2'></br> 
  echo 'Не правильно вказані дані     <label 
користувача БД, введіть ще раз будь ласка: ';  class='label_form'>Напишіть текст з html 
   тегами</label><p>Для створення сторінки новини, 
  } використовуйте такі теги як h1-4,p,img з посиланням на 
 else{ файл, просто в src вкажіть такий шлях в двох лапках 
  session_start(); img/news/назва файлу та розширення через крапну  
  $_SESSION['username'] = в тому порядку як вам потрібно розмістити фотографії. 
$_POST['username']; Під час попереднього перегляду ви зможете побачити 
  $_SESSION['password'] = де у вас будуть відображені зоображення  </p><textarea 
$_POST['password']; 
64 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
style='height:300px; width:500px;' class='input_form'     <button 
name='text'></textarea></br> class='button_form' name='preview'>Попередній 
    <button перегляд</button> 
class='button_form' name='preview'>Попередній     <button 
перегляд</button> class='button_form' name='save'>Зберегти</button> 
    <button     </form>" ; 
class='button_form' name='save'>Зберегти</button>   
    </form>" ;  $_SESSION['preview'] = $_POST['text']; 
 $_SESSION['data'] = $data;  $pageURL = 'http://diplom/test_site.php'; 
}   $jsCode = sprintf('<script type="text/javascript" 
// попередній перегляд language="javascript">window.open("%s", 
elseif(isset($_POST['preview'])){ "_blank");</script>', $pageURL); 
 $_SESSION['title'] = $_POST['title'];  echo $jsCode; 
    $_SESSION['category'] = $_POST['category'];   
    $_SESSION['src_img1'] = $_FILES['src_img1']['name']; } 
 $_SESSION['src_img2'] = // збереження нового запису новин в БД 
$_FILES['src_img2']['name']; elseif(isset($_POST['save'])){ 
    $_SESSION['text'] = $_POST['text'];  $title = $_POST['title']; 
    $_SESSION['choice'] = $_POST['choice'];  $text = $_POST['text']; 
        
 $data = "<form method='post'     $targetDirectory = "img/news/"; // Каталог, в який буде 
enctype='multipart/form-data'> збережено завантажений файл 
    <label     $targetFile = $targetDirectory . 
class='label_form'>Введіть заголовок basename($_FILES['src_img1']['name']); // Шлях до 
блогу</label><input class='input_form' файлу 
value='{$_SESSION['title']}' name='title'>  $src_img1 = $targetFile; 
    <label     // Перевірка наявності помилок при завантаженні 
class='label_form'>Це рекомендована новина?</label> файлу 
    <input type='radio'     
id='option-yes'  value='{$_SESSION['choice']} if(move_uploaded_file($_FILES['src_img1']['tmp_name'], 
name='choice' value='yes'> $targetFile)) { 
    <label for='option-         echo "Файл успішно завантажено."; 
yes'>Так</label>     } else { 
    <input type='radio'         echo "Виникла помилка при завантаженні файлу."; 
id='option-no' value='{$_SESSION['choice']}     } 
name='choice' value='no'>  $targetFile = $targetDirectory . 
    <label for='option- basename($_FILES['src_img2']['name']); // Шлях до 
no'>Ні</label> файлу 
    <label  $src_img2 = $targetFile; 
class='label_form'>Виберіть категорію</label>     // Перевірка наявності помилок при завантаженні 
    <select файлу 
class='select_admin' id='inputTypeSelect' name='category'      
value='{$_SESSION['category']}' if(move_uploaded_file($_FILES['src_img2']['tmp_name'], 
onchange='changeInputType()'> $targetFile)) { 
       <option         echo "Файл успішно завантажено."; 
value='game'>Гра</option>     } else { 
       <option         echo "Виникла помилка при завантаженні файлу."; 
value='community'>Ком'юніті</option>     } 
       <option  $date =  date('Y-m-d'); 
value='other'>Інше</option>  $sql = "INSERT INTO news (title, src_img1, 
    </select>  src_img2, text, date, category, category, choice) VALUES 
    <label ('$title', '$src_img1', '$src_img2', '$text', 
class='label_form' style='color:red;'>Виберіть знову фото '$date','{$_POST['category']}','{$_POST['choice']}')"; 
яке ви хочете завантажити та категорію</label>  
    <label  if ($link->query($sql) === TRUE) { 
class='label_form'>Виберіть фото</label><input   echo "Дані успішно збережені в базі 
class='file-input'  type='file' даних"; 
value='{$_SESSION['src_img1']}' name='src_img1'>  } else { 
    <label   echo "Помилка при збереженні 
class='label_form'>Виберіть фото</label><input даних: " . $link->error; 
class='file-input'  type='file'  } 
value='{$_SESSION['src_img2']}' name='src_img2'>  
    <label } 
class='label_form'> Напишіть текст з html тегами</label> // Перегляд таблиць в БД 
    <textarea elseif($_SESSION['last_click']== 'view_db' and 
class='input_form' style='height:300px; width:500px;' isset($_POST['news']) or isset($_POST['support_mes'])  or 
name='text'>{$_SESSION['text']}</textarea></br> isset($_POST['chat_history'])){ 
  $data = "<form method='post'> 
65 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
     <label>Виберіть   elseif(isset($_POST['support_mes'])){ 
поле по якому хочете шукати запись</label>   $_SESSION['last_click'] = 
    <select 'support_mes'; 
class='select_admin' id='inputTypeSelect'    $sql = mysqli_query($link, 'SELECT * 
name='name_filter' onchange='changeInputType()'>"; FROM `support_mes`'); 
  if(isset($_POST['news'])){     $data = $data . " 
   $data = $data . "   <tr ><td>id</td> 
       <option   <td >date</td> 
value='text'>Назва новини</option>   <td >type</td> 
         <option   <td >text</td> 
value='date'>Дата</option>";   <td >username</td> 
  }   <td >   
  elseif(isset($_POST['support_mes'])){   </td></tr></form>" ;  
   $data = $data . "    while ($result = 
       <option mysqli_fetch_array($sql)) { 
value='text'>Тип повідомлення</option>         $data = $data . " 
       <option   <tr ><td>{$result['id']}</td> 
value='date'>Дата</option>";   <td >{$result['date']}</td> 
  }   <td >{$result['type']}</td> 
  elseif(isset($_POST['chat_history'])){   <td >{$result['text']}</td> 
   $data = $data . "   <td >{$result['username']}</td> 
       <option   <td >   
value='text'>Нік користувача</option>    <input type='hidden' 
       <option name='idvalue' value='{$result['id']}'> 
value='date'>Дата</option>";    <button class='admin_button' 
  } name='view'>Переглянути</button> 
  $data = $data . "    <button class='admin_button' 
    </select>  name='delete'>Видалити</button> 
    <input   </td></tr></form>" ;            
class='input_admin' id='myInput'    } 
name='search_text'><button class='admin_button'   } 
name='search'>Пошук</button>   elseif(isset($_POST['chat_history'])){ 
    </form>   $_SESSION['last_click'] = 
    <form 'chat_history'; 
method='post'><table class='table'>";    $sql = mysqli_query($link, 'SELECT 
  `id`,`date`,`text`,`username` FROM `chat_history`'); 
  if(isset($_POST['news'])){     $data = $data . " 
  $_SESSION['last_click'] = 'news';   <tr ><td>id</td> 
   $sql = mysqli_query($link, 'SELECT *   <td >date</td> 
FROM `news`');   <td >username</td> 
   $data = $data . "   <td >text</td> 
  <tr ><td>id</td>   <td >   
  <td >date</td>   </td></tr></form>" ;  
  <td >title</td>    while ($result = 
  <td >src_img1</td> mysqli_fetch_array($sql)) { 
  <td >src_img2</td>         $data = $data . " 
  <td >category</td>   <tr ><td>{$result['id']}</td> 
  <td >     <td >{$result['date']}</td> 
  </td></tr></form>" ;        <td >{$result['username']}</td> 
   while ($result =   <td >{$result['text']}</td> 
mysqli_fetch_array($sql)) {   <td >   
        $data = $data . "    <input type='hidden' 
  <tr ><td>{$result['id']}</td> name='idvalue' value='{$result['id']}'> 
  <td >{$result['date']}</td>    <button class='admin_button' 
  <td >{$result['title']}</td> name='view'>Переглянути</button> 
  <td >{$result['src_img1']}</td>    <button class='admin_button' 
  <td >{$result['src_img2']}</td> name='delete'>Видалити</button> 
  <td >{$result['category']}</td>   </td></tr></form>" ;            
  <td >      } 
   <input type='hidden'   } 
name='idvalue' value='{$result['id']}'>   $data = $data . "</table></form>"; 
   <button class='admin_button' } 
name='view'>Переглянути</button> // Пошук даних в БД 
   <button class='admin_button' elseif(isset($_POST['search'])){ 
name='delete'>Видалити</button>   $data = "<form method='post'><table 
  </td></tr></form>" ;            class='table'>"; 
   }   if($_POST['name_filter'] == 'text'){ 
  }   if($_SESSION['last_click'] == 'news'){ 
66 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
   $sql = "SELECT * FROM     <td 
{$_SESSION['last_click']} WHERE title LIKE ?"; >{$result['src_img2']}</td> 
  }     <td 
  elseif($_SESSION['last_click'] == >{$result['category']}</td>"; 
'support_mes'){    } 
   $sql = "SELECT * FROM    if($_SESSION['last_click']  
{$_SESSION['last_click']} WHERE type LIKE ?"; == 'chat_history'){ 
  }     $data = $data . " 
  elseif($_SESSION['last_click'] ==     <td 
'chat_history'){ >{$result['username']}</td>"; 
   $sql = "SELECT * FROM    } 
{$_SESSION['last_click']} WHERE username LIKE ?";    $data = $data . "<td > 
  }     <input type='hidden' 
  $stmt = $link->prepare($sql); name='idvalue' value='{$result['id']}'> 
  $searchPattern = '%' .     <button 
$_POST['search_text'] . '%'; class='admin_button' name='view'>Переглянути</button> 
  $stmt->bind_param("s",     <button 
$searchPattern); class='admin_button' name='delete'>Видалити</button> 
  $stmt->execute();    </td></tr>" ;            
   // Отримання результату запиту    } 
  $resultt = $stmt->get_result();      
    $data = $data . "   $data = $data . "</table></form>"; 
   <tr ><td>id</td>  } 
   <td >date</td>  elseif($_POST['name_filter'] == 'date'){ 
   <td >text</td>";   $sql = "SELECT * FROM 
   if($_SESSION['last_click'] {$_SESSION['last_click']} WHERE date=?"; 
== 'support_mes'){   $stmt = $link->prepare($sql); 
    $data = $data . "   $stmt->bind_param("s", 
    <td >username</td> $_POST['search_text']); 
    <td >type</td>";   $stmt->execute(); 
   }   // Отримання результату запиту 
    $resultt = $stmt->get_result();  
 elseif($_SESSION['last_click'] == 'news'){   while ($result = $resultt-
    $data = $data . " >fetch_assoc()) { 
    <td>title</td>     
    <td >src_img1</td>    $data = $data . " 
    <td >src_img2</td>    <tr ><td>{$result['id']}</td> 
    <td    <td >{$result['date']}</td> 
>category</td>";    <td >{$result['text']}</td>"; 
   }    if($_SESSION['last_click'] 
   if($_SESSION['last_click']  == 'support_mes'){ 
== 'chat_history'){     $data = $data . " 
    $data = $data . "     <td 
    <td >{$result['username']}</td> 
>username</td>";     <td 
   }  >{$result['type']}</td>"; 
  while ($result = $resultt-    } 
>fetch_assoc()) {   
   $data = $data . "  elseif($_SESSION['last_click'] == 'news'){ 
   <tr ><td>{$result['id']}</td>     $data = $data . " 
   <td >{$result['date']}</td>    
   <td >{$result['text']}</td>";  <td>{$result['title']}</td> 
   if($_SESSION['last_click']     <td 
== 'support_mes'){ >{$result['src_img1']}</td> 
    $data = $data . "     <td 
    <td >{$result['src_img2']}</td> 
>{$result['username']}</td>     <td 
    <td >{$result['category']}</td>"; 
>{$result['type']}</td>";    } 
   }    if($_SESSION['last_click']  
  == 'chat_history'){ 
 elseif($_SESSION['last_click'] == 'news'){     $data = $data . " 
    $data = $data . "     <td 
   >{$result['username']}</td>"; 
 <td>{$result['title']}</td>    } 
    <td     $data = $data . "  
>{$result['src_img1']}</td>     <td> 
67 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
     <input     <label 
type='hidden' name='idvalue' value='{$result['id']}'> class='label_form'>Введіть Посилання на 
     <button фото</label><input class='input_form' 
class='admin_button' name='view'>Переглянути</button> value='{$result['title']}'> 
     <button     <label 
class='admin_button' name='delete'>Видалити</button> class='label_form'>Введіть Посилання на 
    </td></tr>" ;            фото</label><input class='input_form' 
   }   value='{$result['src_img1']}'> 
  $data = $data . "</table></form>";     <label 
 } class='label_form'>Введіть Посилання на 
} фото</label><input class='input_form' 
 value='{$result['src_img2']}'></br> 
// Перегляд даних     <label 
elseif(isset($_POST['view'])){ class='label_form'>Виберіть категорію</label><select 
 if($_SESSION['last_click'] == 'news'){ class='select_admin' id='inputTypeSelect' name='category' 
  $sql = "SELECT * FROM news value='{$result['category']}' 
WHERE id=?"; onchange='changeInputType()'> 
 }        <option 
 elseif($_SESSION['last_click'] == value='game'>Гра</option> 
'support_mes'){        <option 
  $sql = "SELECT * FROM value='community'>Ком'юніті</option> 
`support_mes` WHERE id=?";        <option 
 } value='other'>Інше</option> 
 elseif($_SESSION['last_click'] ==     </select></br> 
'chat_history'){     <button 
  $sql = "SELECT * FROM class='admin_button' name='preview'>Попередній 
`chat_history` WHERE id=?"; перегляд</button>"; 
 }    } 
      $data = $data . " 
 $stmt = $link->prepare($sql);     <button 
 $stmt->bind_param("i", $_POST['idvalue']); class='admin_button' name='save_formating'>Зберегти 
 $stmt->execute(); змінену інформацію</button> 
 $resultt = $stmt->get_result();     </form>"; 
 while ($result = $resultt->fetch_assoc()) {  } 
   $data = $data . "<form><label } 
class='label_form'>Дата створення</label><input // Видалення даних з БД 
class='input_form' value='{$result['date']}'>"; elseif(isset($_POST['delete'])){ 
   if($_SESSION['last_click']  $id = $_POST['idvalue']; 
== 'support_mes'){  
   $data = $data . "  // Виконати запит на видалення 
    <label  $sql = "DELETE FROM 
class='label_form'>Введіть Посилання на {$_SESSION['last_click']} WHERE id = ?"; 
фото</label><input class='input_form'  $stmt = $link->prepare($sql); 
value='{$result['username']}'>  $stmt->bind_param("i", $id); 
    <label  
class='label_form'>Введіть Посилання на  if ($stmt->execute()) { 
фото</label><input class='input_form'   $data = "Запис успішно видалено."; 
value='{$result['type']}'></br>";  } else { 
   }   $data = "Сталася помилка при 
  видаленні запису: " . $stmt->error; 
 elseif($_SESSION['last_click'] ==  } 
'chat_history'){  
   $data = $data . "  } 
    <label // Вибір таблиці яку хочемо переглянути 
class='label_form'>Введіть Посилання на elseif(isset($_POST['view_db'])){ 
фото</label><input class='input_form'  $_SESSION['last_click'] = 'view_db'; 
value='{$result['username']}'></br>";  $data = "<h4>Виберіть яку саме таблицю 
   } хочете переглянути</h4> 
       <form method='post'> 
   $data = $data . "      <button 
    <label class='button_form' style='margin-top:10px;' name='news'> 
class='label_form'>Напишіть текст з html Новини </button></br> 
тегами</label><textarea     <button 
class='input_form'>{$result['text']}</textarea></br>"; class='button_form' style='margin-top:10px;' 
   if($_SESSION['last_click']  name='support_mes'> Повідомлення адмінам 
== 'news'){ </button></br> 
    $data = $data . " 
68 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
    <button   mysqli_stmt_bind_param($stmt, "i", 
class='button_form' style='margin-top:10px;' $_SESSION['id']); 
name='chat_history'> Історія чату </button></br>   mysqli_stmt_execute($stmt); 
   <form>";   $resultt = $stmt->get_result(); 
   while ($result = $resultt-
} >fetch_assoc()) { 
// Перегляд повідомлення від користувача     $data =  "<form 
elseif(isset($_POST['vied_mess_people'])){ method='post'><label class='label_form'>Дата 
  $_SESSION['last_click'] = створення</label><input class='input_form' name='date'  
'vied_mess_people';   value='{$result['date']}'> 
  $_SESSION['id'] = 1;      <label 
  $sql = "SELECT * FROM support_mes class='label_form'>Введіть Посилання на 
WHERE support_mes IS NULL ORDER BY id DESC фото</label><input class='input_form' name='username' 
LIMIT 1";  value='{$result['username']}'> 
  $stmt = $link->prepare($sql);      <label 
  $stmt->execute(); class='label_form'>Введіть Посилання на 
  $resultt = $stmt->get_result(); фото</label><input class='input_form' name='type' 
  while ($result = $resultt- value='{$result['type']}'>  
>fetch_assoc()) {      <label 
    $data =  "<form class='label_form'>Напишіть текст з html 
method='post'><label class='label_form'>Дата тегами</label><textarea class='input_form' 
створення</label><input class='input_form' name='date'  name='text'>{$result['text']}</textarea>  
  value='{$result['date']}'>     
     <label      <input 
class='label_form'>Введіть Посилання на type='hidden' name='idvalue' value='{$result['id']}'> 
фото</label><input class='input_form' name='username'      <label 
value='{$result['username']}'> class='label_form'>Відповідь 
     <label користувачу</label><textarea class='input_form' 
class='label_form'>Введіть Посилання на name='support_mess'></textarea></br> 
фото</label><input class='input_form' name='type'      <button 
value='{$result['type']}'>  class='admin_button' name='next_mess'>Настуний 
     <label запис</button> 
class='label_form'>Напишіть текст з html      <button 
тегами</label><textarea class='input_form' class='admin_button' name='back_mess'>Попередній 
name='text'>{$result['text']}</textarea>  запис</button> 
         <button 
     <input class='admin_button' name='delete'>Видалити 
type='hidden' name='idvalue' value='{$result['id']}'> запис</button> 
     <label      <button 
class='label_form'>Відповідь class='admin_button' name='send_mes'>Відправити 
користувачу</label><textarea class='input_form' повідомлення</button> 
name='support_mess'></textarea></br>      </form>"; 
     <button   } 
class='admin_button' name='next_mess'>Настуний } 
запис</button> // Минуле повідомлення 
     <button elseif(isset($_POST['back_mess'])){ 
class='admin_button' name='back_mess'>Попередній  $_SESSION['last_click'] = 'next_mess';  
запис</button>   $_SESSION['id'] = $_SESSION['id'] - 
     <button 1; 
class='admin_button' name='delete'>Видалити   if($_SESSION['id']<= 0){ 
запис</button>    $_SESSION['id'] = 0; 
     <button   } 
class='admin_button' name='send_mes'>Відправити   $sql = "SELECT * FROM support_mes 
повідомлення</button> ORDER BY id DESC LIMIT ?";  
     </form>";   $stmt = mysqli_prepare($link, $sql); 
 }   mysqli_stmt_bind_param($stmt, "i", 
} $_SESSION['id']); 
// Наступне повідомлення   mysqli_stmt_execute($stmt); 
elseif(isset($_POST['next_mess'])){   $resultt = $stmt->get_result(); 
  $_SESSION['last_click'] = 'next_mess';   while ($result = $resultt-
  >fetch_assoc()) { 
  $_SESSION['id'] = $_SESSION['id'] +     $data =  "<form 
1; method='post'><label class='label_form'>Дата 
  $sql = "SELECT * FROM support_mes створення</label><input class='input_form' name='date' 
WHERE support_mes IS NULL ORDER BY id DESC value='{$result['date']}'> 
LIMIT ?";       <label 
  $stmt = mysqli_prepare($link, $sql); class='label_form'>Введіть Посилання на 
69 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
фото</label><input class='input_form' name='username' if ($conn->connect_error) { 
value='{$result['username']}'>     die("Помилка підключення до бази даних: " . $conn-
     <label >connect_error); 
class='label_form'>Введіть Посилання на } 
фото</label><input class='input_form' name='type'  
value='{$result['type']}'>  // Перевірка, чи користувач відправив форму реєстрації 
     <label if (isset($_POST['clikc'])) { 
class='label_form'>Напишіть текст з html     // Отримання даних з форми 
тегами</label><textarea class='input_form'     $username = $_POST["username"]; 
name='text'>{$result['text']}</textarea>      $password = $_POST["password"]; 
     
     <input     // Перевірка, чи користувач з таким іменем вже існує 
type='hidden' name='idvalue' value='{$result['id']}'>     $check_query = "SELECT * FROM users WHERE 
     <label username = '$username'"; 
class='label_form'>Відповідь     $check_result = $conn->query($check_query); 
користувачу</label><textarea class='input_form'  
name='support_mess'></textarea></br>     if ($check_result->num_rows > 0) { 
     <button         echo "Користувач з таким іменем вже існує."; 
class='admin_button' name='next_mess'>Настуний     } else { 
запис</button>         // Додавання нового користувача до бази даних 
     <button         $insert_query = "INSERT INTO users (username, 
class='admin_button' name='back_mess'>Попередній password) VALUES ('$username', '$password')"; 
запис</button>         if ($conn->query($insert_query) === TRUE) { 
     <button             echo "Реєстрація пройшла успішно."; 
class='admin_button' name='delete'>Видалити    header("Location: 
запис</button> index.php"); 
     <button         } else { 
class='admin_button' name='send_mes'>Відправити             echo "Помилка реєстрації: " . $conn->error; 
повідомлення</button>         } 
     </form>";     } 
  } } 
} ?>  
// Зберегти відповідь користувачу Код reg_chek.php 
elseif(isset($_POST['send_mes'])){  <?php 
 $id = $_POST['idvalue'];  $username = "Admin"; 
 $date = $_POST['date'];  $password = "Diplom2023"; 
 $username = $_POST['username'];  $host = 'localhost';  // Хост, у нас все локально     
 $type = $_POST['type'];  $db_name = 'race_db';   // Имя базы данных 
 $text = $_POST['text'];  $link = mysqli_connect($host, $username, 
 $support_mess = $_POST['support_mess']; $password, $db_name);  
  
 $sql = "INSERT INTO support_mes_ready (date,  if (isset($_POST['category']) && 
username, type, text, support_mes) VALUES ('$date', isset($_POST['type']) && $_POST['type'] === 'last_news') 
'$username', '$type', '$text', '$support_mess')"; { 
   if($_POST['category']=='all'){ 
 if ($link->query($sql) === TRUE) {       $sql = mysqli_query($link, 'SELECT * 
  echo "Дані успішно збережені в базі FROM `news` ORDER BY `date` DESC LIMIT 4'); 
даних";   } 
  $sql = "DELETE FROM support_mes   if($_POST['category'] != 'all'){ 
WHERE id = $id";       $sql = mysqli_query($link, "SELECT * 
  $link->query($sql); FROM `news` WHERE choice='{$_POST['category']}' 
 } else { ORDER BY `date` DESC LIMIT 4"); 
  echo "Помилка при збереженні   } 
даних: " . $link->error;    while ($result = 
 } mysqli_fetch_array($sql)) { 
}    echo " 
?>    <a class='newsblock' 
Код reg_chek.php onclick=sendData('{$result['title']}','open_news') > 
<?php    <img class='imgblock' 
// Підключення до бази даних src='{$result['src_img1']}'> 
$servername = "localhost";    <h2>{$result['title']}</h2> 
$username = "root";    {$result['date']}</a>" ;            
$password = "Diplom2023";    } 
$dbname = "race_db";  } 
  elseif (isset($_POST['category']) && 
$conn = new mysqli($servername, $username, $password, isset($_POST['type']) && $_POST['type'] === 'actual') { 
$dbname); 
70 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
     $sql = mysqli_query($link, 'SELECT * FROM #content_newnewss{ 
`news` WHERE choice ="yes" ORDER BY `date` DESC  height: 700px; 
LIMIT 4'); } 
   while ($result = #content_new_newss + * { 
mysqli_fetch_array($sql)) {   display: block; 
   echo " } 
   <a class='newsblock' .arhiv{ 
onclick=sendData('{$result['title']}','open_news') >  width: 80%; 
   <img class='imgblock'  margin: auto; 
src='{$result['src_img1']}'> } 
   <h2>{$result['title']}</h2> .page-numbers { 
   {$result['date']}</a>" ;              display: flex; 
   }   justify-content: center; 
 }   margin-top: 20px; 
 elseif (isset($_POST['category']) && } 
isset($_POST['type']) && $_POST['type'] ===  
'open_news') { .page-numbers a { 
     margin: 0 5px; 
  session_start();   padding: 8px 12px; 
     $sql = mysqli_query($link, "SELECT * FROM   background-color: #f2f2f2; 
news WHERE title ={$_POST['category']}");   color: #333; 
   while ($result =   text-decoration: none; 
mysqli_fetch_array($sql)) {   border-radius: 4px; 
   $_SESSION['preview'] =  } 
$result['category'];           
   } .page-numbers a:hover { 
   echo "test_site.php";    background-color: #ddd; 
 } } 
 .content_1{ 
?>  float: none; 
Стилі сайту } 
Код .content{ 
style.css  width: 80%; 
@charset "utf-8";  margin: auto; 
/* CSS Document */ } 
body{ .short_des{ 
 margin: auto;  color: aliceblue; 
 padding: 0;  background-image: url("../img/fon_img.png"); 
 background-color: rgba(38,38,38,1.00);  background-size: cover; 
 color: aliceblue;     background-repeat: no-repeat; 
}     background-position: center; 
  min-height: 300px; 
.head{  text-align: center; 
 padding-left: 10%;  display: flex; 
 padding-right: 10%;    align-items: center; 
 margin: auto;  border-bottom-left-radius: 10px; 
 height: 50px;  border-bottom-right-radius: 10px; 
 font-size: 20px; } 
 text-align: center; .short_text{ 
 font-family: Georgia;  font-size: 45px; 
 background-color: black;  margin: auto; 
 display: flex; } 
   align-items: center; .download{ 
}  background-color: orange; 
  border-color: orange; 
.head_button{  padding: 5px; 
 text-decoration: none;  font-size: 25px; 
 color:aliceblue;  font-family: Gotham, "Helvetica Neue", 
 margin: auto; Helvetica, "sans-serif"; 
}  border-radius: 5px; 
.news_button{ } 
 text-decoration: none;  
 color:aliceblue; .last_news{ 
 margin: auto; } 
} .form_last_news{ 
#content_new_newss, #content_new_news {  float: right; 
 height: 360px; } 
} .content_2{ 
71 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
 float: none; .content_news{ 
}  margin: auto; 
.button_last{  width: 80%; 
 font-size:18px;    display: flex; 
 margin-right: 10px;    justify-content: center; 
 font-weight: normal;    align-items:flex-end; 
}  min-height: 560px; 
   
.forum{ } 
 margin-top: 20px; .h2{ 
 width: 45%;  width: 70%; 
 text-align: left;  font-weight: 400; 
 background-color: aliceblue;  font-size: 40px; 
 color: black;   
 padding: 20px; } 
 border-radius: 10px; span{ 
 border-bottom-right-radius:  50px;  font-weight: 1000; 
} } 
.chat_url{  
 text-decoration: none; .autorization{ 
 background-color: red;  width: 28%; 
 border-radius: 10px;  padding: 20px; 
 padding: 7px;  margin: auto; 
 color: black;  margin-top: 200px; 
 margin: auto;  background-color: aliceblue; 
 font-family: Georgia;  color: #333; 
 font-weight:1000;    font-weight: bold; 
   border-radius: 20px; 
} } 
.support{ .label{ 
 margin-top: 20px;  font-size: 25px; 
 margin-right: 0%;  float: right; 
 margin-left: auto; } 
 width: 45%; .text{ 
 text-align: left;   padding: 10px; 
 background-color: aliceblue;   border: 1px solid #ccc; 
 color: black;   border-radius: 5px; 
 padding: 20px;   transition: border-color 0.3s ease; 
 border-radius: 10px; } 
 border-top-left-radius:  50px; .text:focus { 
 margin-bottom: 50px;   outline: none; 
}   border-color: #007bff; 
.footer{ } 
 background-color: black; .chek_button{ 
}   display: inline-block; 
p{   font-size: 20px; 
 font-size: 18px;   margin-left: 210px; 
}   margin-bottom: 20px; 
   background-color: #007bff; 
.footer-content {   color: #fff; 
    display: flex;   border: none; 
    justify-content: center;   padding: 10px 20px; 
 margin: 0px;   border-radius: 5px; 
}   cursor: pointer; 
.footer-bottom{   font-family: "Times New Roman", "serif"; 
 margin: 0px;  
 padding: 0px; } 
 text-align: center; a{ 
 background-color: black;  text-decoration: none; 
} } 
.content_news_fon{ p{ 
 margin: auto;  font-size: 20px; 
 background-image: url("../img/img_race.png"); } 
 background-size: cover;  
    background-repeat: no-repeat; .support_mess{ 
    background-position: center;  width: 45%; 
 min-height: 560px;  padding: 20px; 
}  margin: auto; 
72 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
 margin-top: 200px;  color: black; 
 background-color: aliceblue;  background-color: white; 
 color: #333;  margin: auto; 
   font-weight: bold; } 
 border-radius: 20px;  
} .content_block{ 
  color: black; 
.support_input1 {  background-color: white; 
  width: 99%;  width: 66%; 
  height: 150px;  margin: auto; 
  padding: 10px;  padding: 10px; 
  font-size: 16px;  border-radius: 10px; 
  border: 1px solid #ccc; } 
  border-radius: 5px; td{ 
  resize: vertical;  width: 500px; 
} } 
 .sup{ 
.support_input {  float: left; 
  width: 100%;  display: flex; 
  padding: 10px; } 
  font-size: 16px; .sub{  
  border: 1px solid #ccc;  float: left; 
  border-radius: 5px; } 
  background-color: #f9f9f9; .sup1{ 
  color: #555;  float: right; 
}  display: flex; 
.email{  margin-right: 0px; 
 width: 80%;   
 margin: auto; } 
} .sub1{  
.table {  float: right; 
  width: 100%;  margin-right: 0px; 
  border-collapse: collapse; } 
} .chat_td{ 
  float: left; 
.table th,  max-width: 300px; 
.table td {  padding: 10px; 
  padding: 10px;  background-color: rgba(152,147,254,1.00); 
  text-align: center;  border-radius: 10px; 
  border: 1px solid #ccc; } 
} .chat_td1{ 
  max-width: 300px; 
.table th {  text-align: right; 
  background-color: #f2f2f2;  padding: 10px; 
  font-weight: bold;  background-color: rgba(152,147,254,1.00); 
}  border-radius: 10px; 
 } 
.table tr:hover { #messageInput{ 
  background-color: #f5f5f5;  display: block; 
  color: black;  float: left; 
}     width: 80%; 
     border: 1px solid #ccc; 
.table td:last-child {  margin-bottom: 10px; 
  text-align: right;  margin-right: 10px; 
}     border-radius: 5px; 
     font-size: 16px; 
.button_email{     outline: none; 
 background-color: green; } 
 border-color: green; #messageButton{ 
 border-radius: 4px;   display: inline-block; 
 padding: 6px;   padding: 10px 20px; 
}   background-color: #007bff; 
.email_block{   color: #fff; 
 width: 60%;   border: none; 
 margin: auto;   border-radius: 5px; 
}   cursor: pointer; 
.chat{   font-size: 16px; 
 width: 80%;   font-weight: bold; 
73 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
  text-decoration: none;   padding: 10px; 
  transition: background-color 0.3s ease;   font-size: 16px; 
}   border: 1px solid #ccc; 
#messageButton:hover {   border-radius: 5px; 
  background-color: #0056b3;   margin-bottom: 10px; 
} } 
  
.autorization_button{ .label_form{ 
  background-color: #007bff;  display: block; 
  color: #fff;   font-size: 20px; 
  cursor: pointer;   margin-bottom: 5px; 
  font-size: 20px; } 
  border-radius: 10px;  
  border-color: #007bff; .button_form{ 
}  width: 150px; 
.autorization_button:hover{   padding: 10px; 
   background-color: #0056b3;   font-size: 16px; 
}   font-weight: bold; 
.autorization_input{   text-align: center; 
 padding: 10px;   text-decoration: none; 
  border: 1px solid #ccc;   background-color: #007bff; 
  border-radius: 5px;   color: #fff; 
  font-size: 16px;   border: none; 
  outline: none;   border-radius: 5px; 
}   cursor: pointer; 
.autorization_label{ } 
  margin-bottom: 10px; .file-input { 
  font-weight: bold;   display: inline-block; 
}   background-color: #f1f1f1; 
.autorization_form{   border: none; 
 display: flex;   padding: 8px 16px; 
  flex-direction: column;   border-radius: 4px; 
  max-width: 400px;   cursor: pointer; 
  margin: 0 auto;   color: #555; 
}   font-size: 14px; 
 } 
.admin_panel{ .admin_button{ 
 float: left;   width: 150px; 
  flex-direction: column;   padding: 10px; 
  max-width: 400px;   margin-bottom: 10px;  
  margin: 0 auto;   font-size: 16px; 
}   font-weight: bold; 
   text-align: center; 
.panel_butt{   text-decoration: none; 
  display: inline-block;   background-color: #007bff; 
  width: 250px;   color: #fff; 
  padding: 10px;   border: none; 
  margin-bottom: 10px;   border-radius: 5px; 
  font-size: 16px;   cursor: pointer; 
  font-weight: bold; } 
  text-align: center;  
  text-decoration: none; .select_admin{ 
  background-color: #007bff;   padding: 8px; 
  color: #fff;   font-size: 14px; 
  border: none;   border: 1px solid #ccc; 
  border-radius: 5px;   border-radius: 4px; 
  cursor: pointer;   background-color: #fff; 
float: left;   width: 20%; 
}   box-sizing: border-box; 
.admin_block{ } 
 margin-left: 30px;  
 width: 80%; .input_admin{ 
 float: left;   padding: 8px; 
}   font-size: 14px; 
   border: 1px solid #ccc; 
.input_form{   border-radius: 4px; 
  width: 300px;   background-color: #fff; 
  height: 40px;   width: 29%; 
74 
482 ЧДТУ 232227 –  01 12 01 - 1 
 
  box-sizing: border-box; 
 margin-right: 10px; 
} 
 
.news{ 
 width: 80%; 
 margin: auto; 
} 
 
.newsblock{ 
 width: 20%; 
 float: left; 
 height: 300px; 
 margin: 10px; 
 background-color: aliceblue; 
 color: black; 
 padding: 10px; 
 border: 4px solid; 
 border-left-color: blue; 
 border-top-color: red; 
 border-right-color: yellow; 
 border-bottom-color: black; 
 border-radius: 20px; 
  transition: transform 0.3s ease; 
} 
.imgblock{ 
 width: 100%; 
 height: 160px; 
} 
 
.newsblock:hover { 
  transform: scale(1.1); 
} 
 
 
.actual_news{ 
 height: 400px; 
} 
 
75 
 
ДОДАТОК В 
Скріпти гри «Racing online» 
 
 
 
 
 
 
 
  
482 ЧДТУ 232227 –  01 12 01 – 2 
Текст програми  
Листів 12 
 
 
Н 
 
Розробник                          __________________                Роман БАКУМЕНКО  
 
 
 
 
 
 
 
 
 
 
Черкаси, 2023  
76 
482 ЧДТУ 232227 –  01 12 01 – 2 
 
Код CameraMove.cs
using System.Collections;   Y += Input.GetAxis("Mouse Y") * 
using System.Collections.Generic; sensitivity; 
using TMPro;   Y = Mathf.Clamp(Y, -limit, -12); 
using UnityEngine;   transform.localEulerAngles = new 
 Vector3(-Y, (float)X, 0); 
public class CameraMove : MonoBehaviour   transform.position = 
{ transform.localRotation * offset + target.position; 
 public List<GameObject> array = new  } 
List<GameObject>(); } 
 public Canvas canvas; Код car_controler2.cs 
 public TextMeshProUGUI dollar; using UnityEngine; 
 public Transform target; using TMPro; 
 public Vector3 offset; using UnityEngine.UI; 
 public float sensitivity; // чувствительность using UnityEngine.EventSystems; 
мышки using Photon.Pun; 
 public float limit; // ограничение вращения по using Photon.Realtime; 
Y using System; 
 public float zoom;  // чувствительность при using System.Diagnostics; 
увеличении, колесиком мышки using ExitGames.Client.Photon; 
 public float zoomMax; // макс. увеличение using Newtonsoft.Json; 
 public float zoomMin; // мин. увеличение using System.Collections.Generic; 
 private float Y; public class car_controler2 : MonoBehaviourPunCallbacks, 
 private double X; IOnEventCallback 
 private double pi = -0.05; { 
     public GameObject left; 
 void Start()     public GameObject right; 
 {     public GameObject gas; 
  if (Screen.width >     public GameObject back; 
Screen.safeArea.width)     private float speedd; 
        {  
   for(int i = 0; i < array.Count;     public AudioSource audioSource1; 
i++)     public AudioSource audioSource2; 
            {  
       public TextMeshProUGUI speed; 
 Debug.Log(array[i].transform.position.x);     public TextMeshProUGUI gear; 
    
 array[i].transform.position = new     public TextMeshPro time; 
Vector3(array[i].transform.position.x + (Screen.width -  
Screen.safeArea.width), array[i].transform.position.y,     public GameObject Player; 
array[i].transform.position.z);     public GameObject test; 
   }     public GameObject user; 
        }     public GameObject[] Point_list; 
  limit = Mathf.Abs(limit);  
  if (limit > 90) limit = 90;  
  offset = new Vector3(offset.x, offset.y,     private bool check = true; 
-Mathf.Abs(zoomMax) / 2);  
  transform.position = target.position +     private float acceleration = 2000; 
offset;     private float brakeForce = 10000; 
 }     private float currentSteerAngle; 
     private float number = 1; 
 void Update()     private float koef = 4; 
 {     private int number1 = 0; 
    
       int currentMinute; 
  dollar.text =     int currentSecond; 
SaveData.dollar.ToString();     public GameObject arrowImage; 
  if (Input.GetAxis("Mouse     public GameObject control; 
ScrollWheel") > 0) offset.z += zoom;  
  else if (Input.GetAxis("Mouse     private List<string> cars = new List<string>(); 
ScrollWheel") < 0) offset.z -= zoom;     private byte carsEventCode = 1; 
  offset.z = Mathf.Clamp(offset.z, -  
Mathf.Abs(zoomMax), -Mathf.Abs(zoomMin));     [SerializeField] private float motorForce; 
     [SerializeField] private float breakForce; 
  X = transform.localEulerAngles.y +     [SerializeField] private float maxSteerAngle = 30; 
Input.GetAxis("Mouse X") * sensitivity + pi;  
77 
482 ЧДТУ 232227 –  01 12 01 – 2 
    [SerializeField] private WheelCollider         frontLeftWheelTransform = 
frontLeftWheelCollider; GameObject.Find("FrontLeftWheel").transform; 
    [SerializeField] private WheelCollider         frontRightWheeTransform = 
frontRightWheelCollider; GameObject.Find("FrontRightWheel").transform; 
    [SerializeField] private WheelCollider         rearLeftWheelTransform = 
rearLeftWheelCollider; GameObject.Find("RearLeftWheel").transform; 
    [SerializeField] private WheelCollider         rearRightWheelTransform = 
rearRightWheelCollider; GameObject.Find("RearRightWheel").transform; 
  
    [SerializeField] private Transform         stopwatch.Start(); 
frontLeftWheelTransform;     } 
    [SerializeField] private Transform  
frontRightWheeTransform;     // Update is called once per frame 
    [SerializeField] private Transform     void Update() 
rearLeftWheelTransform;     { 
    [SerializeField] private Transform         
rearRightWheelTransform; UnityEngine.Debug.Log(Point_list[number1].transform.po
    Stopwatch stopwatch; sition.x); 
    // Start is called before the first frame update         if (Player == null) 
         { 
    void Start()             Start(); 
    {         } 
        if (SaveData.setting != true)         if (Player.transform.position.x > 
        { Point_list[number1].transform.position.x - 10 && 
            control.active = false; Player.transform.position.x < 
            car_controler2 script = Point_list[number1].transform.position.x + 10 && 
GetComponent<car_controler2>();             Player.transform.position.z > 
 Point_list[number1].transform.position.z - 10 && 
            // Встановити стан активності скрипта на false Player.transform.position.z < 
            script.enabled = false; Point_list[number1].transform.position.z + 10) 
            return;             { 
        }             if (Point_list.Length - 1 == number1 && check == 
        stopwatch = new Stopwatch(); true) 
        currentMinute = 0;             { 
        currentSecond = DateTime.Now.Second;                 UnityEngine.Debug.Log("Finish"); 
        gear.text = "1";                 check = false; 
        Player = GameObject.Find(SaveData.car.name);                 SaveData.race = false; 
        SaveData.finish = false;                 SaveData.finish = true; 
        Point_list = new                 SaveData.finish_list_car.Add(Player.name); 
GameObject[test.transform.childCount];                 SaveData.finish_list_time.Add(time.ToString()); 
                 SaveData.pozition_finish = 
        for (int i = 0; i < test.transform.childCount; i++) SaveData.finish_list_time.Count; 
        {  
            Point_list[i] =  
test.transform.GetChild(i).gameObject;                 ListContainer container = new 
        } ListContainer(SaveData.finish_list_car, 
 SaveData.finish_list_time); 
        frontLeftWheelCollider =  
GameObject.Find(Player.name +                 // Серіалізація контейнера в рядок 
"/Wheels/Colliders/FrontLeftWheel").GetComponent<Whe                 string serializedContainer = 
elCollider>(); JsonConvert.SerializeObject(container); 
        frontRightWheelCollider =  
GameObject.Find(Player.name +                 // Створення опцій для передачі події 
"/Wheels/Colliders/FrontRightWheel").GetComponent<Wh                 RaiseEventOptions raiseEventOptions = new 
eelCollider>(); RaiseEventOptions 
        rearLeftWheelCollider =                 { 
GameObject.Find(Player.name +                     Receivers = ReceiverGroup.All, // Отримувачі 
"/Wheels/Colliders/RearLeftWheel").GetComponent<Whe події (в даному випадку всі) 
elCollider>();                     CachingOption = EventCaching.DoNotCache 
        rearRightWheelCollider = // Кешування події (не кешувати) 
GameObject.Find(Player.name +                 }; 
"/Wheels/Colliders/RearRightWheel").GetComponent<Wh  
eelCollider>();                 // Виклик RaiseEvent для передачі 
 серіалізованого контейнера через Photon 
        frontLeftWheelCollider.forceAppPointDistance = 1;                 PhotonNetwork.RaiseEvent(carsEventCode, 
        frontRightWheelCollider.forceAppPointDistance = 1; serializedContainer, raiseEventOptions, 
        rearLeftWheelCollider.forceAppPointDistance = 1; SendOptions.SendReliable); 
        rearRightWheelCollider.forceAppPointDistance = 1;             } 
  
78 
482 ЧДТУ 232227 –  01 12 01 – 2 
            else if (check == true)                         { 
            {                             FullTroutl(); 
                number1++;                             audioSource1.volume = 0.5f; 
            }                         } 
                         if (selectedObject.name == "Deceleration") 
        }                         { 
        if (SaveData.finish == true)                             Back(); 
        {                             audioSource1.volume = 0.5f; 
            frontLeftWheelCollider.motorTorque = 0;                         } 
            frontRightWheelCollider.motorTorque = 0;                         if (selectedObject.name == "TurnLeft") 
            rearLeftWheelCollider.motorTorque = 0;                         { 
            rearRightWheelCollider.motorTorque = 0;                             number -= (float)2; 
            frontRightWheelCollider.brakeTorque = 1000000;                             TurnLeft(); 
            frontLeftWheelCollider.brakeTorque = 1000000;                             audioSource2.volume = 0.5f; 
            rearLeftWheelCollider.brakeTorque = 1000000;                         } 
            rearRightWheelCollider.brakeTorque = 1000000;                         if (selectedObject.name == "TurnRight") 
        }                         { 
                             number += (float)2; 
        time.text = stopwatch.Elapsed.ToString(@"mm\:ss");                             TurnRight(); 
        if( currentSecond == 59 ){                             audioSource2.volume = 0.5f; 
            currentMinute++;                         } 
        }                         if (selectedObject.name != "Acceleration" 
        speedd = && selectedObject.name != "Deceleration") 
(int)(Player.GetComponent<Rigidbody>().velocity.magnitu                         { 
de * 3.6f);                             StopCodeExecution(); 
        float currentSpeed = speedd; // Отримання поточної                             audioSource1.volume = 0; 
швидкості                         } 
        speed.text = speedd.ToString();                         if (selectedObject.name != "TurnRight" && 
        // Визначення кута повороту стрілки selectedObject.name != "TurnLeft") 
                         { 
        acceleration = 5000 * koef;                             number = 0; 
        float rotationAngle = 0f - (currentSpeed * koef);                             audioSource2.volume = 0; 
        if (rotationAngle < -250)  
        {                             frontLeftWheelCollider.steerAngle = 0; 
            koef -= 0.5f;                             frontRightWheelCollider.steerAngle = 0; 
            gear.text = (int.Parse(gear.text) + 1).ToString();                         }                      
        }                     } 
                 } 
        if (rotationAngle > -170 && int.Parse(gear.text) != 1)             } 
        {         } 
            koef += 0.5f;         if (number >= 0) 
            gear.text = (int.Parse(gear.text) - 1).ToString();         { 
        }             number--; 
        // Переведення швидкості в кут повороту         } 
         if (number <= 0) 
        // Оновлення кута повороту стрілки         { 
        arrowImage.transform.rotation = Quaternion.Euler(0f,             number++; 
0f, rotationAngle);         } 
        if (Input.touchCount > 0)         UpdateWheels(); 
        {     } 
            Touch touch = Input.GetTouch(0);  
     public void FullTroutl() 
            if (touch.phase == TouchPhase.Began || touch.phase     { 
== TouchPhase.Stationary)          
            {             frontLeftWheelCollider.motorTorque = 
                GameObject selectedObject = acceleration; 
EventSystem.current.currentSelectedGameObject;             frontRightWheelCollider.motorTorque = 
 acceleration; 
                if (selectedObject != null)             rearLeftWheelCollider.motorTorque = acceleration; 
                {             rearRightWheelCollider.motorTorque = 
                    Image selectedImage = acceleration; 
selectedObject.GetComponent<Image>();     } 
                    Button selectedButton =     public void Back() 
selectedObject.GetComponent<Button>();     { 
  
                    if (selectedImage != null && selectedButton !=         frontLeftWheelCollider.motorTorque = -brakeForce ;  
null)         frontRightWheelCollider.motorTorque = -brakeForce ;  
                    {         rearLeftWheelCollider.motorTorque = -brakeForce ;  
                        if (selectedObject.name == "Acceleration")         rearRightWheelCollider.motorTorque = -brakeForce ;  
79 
482 ЧДТУ 232227 –  01 12 01 – 2 
    }     private void UpdateSingleWheel(WheelCollider 
 wheelCollider, Transform wheelTransform) 
    public void TurnLeft()     { 
    {         Vector3 pos; 
        currentSteerAngle = (maxSteerAngle*number)/60;         Quaternion rot; 
        if(currentSteerAngle < -30)         wheelCollider.GetWorldPose(out pos, out rot); 
        {         wheelTransform.rotation = rot; 
            currentSteerAngle = -30;         wheelTransform.position = pos; 
     } 
            number = -60;     public void OnEvent(EventData photonEvent) 
        }     { 
        frontLeftWheelCollider.steerAngle =         if (photonEvent.Code == carsEventCode) 
currentSteerAngle;         { 
        frontRightWheelCollider.steerAngle =             // Отримання переданого масиву CarData від 
currentSteerAngle; іншого гравця 
         
        frontLeftWheelCollider.motorTorque = acceleration;             string serializedContainer = 
        frontRightWheelCollider.motorTorque = acceleration / (string)photonEvent.CustomData; 
2;  
        rearLeftWheelCollider.motorTorque = acceleration /             // Десеріалізація рядка в контейнер 
2;             ListContainer receivedContainer = 
        rearRightWheelCollider.motorTorque = acceleration / JsonConvert.DeserializeObject<ListContainer>(serializedC
2; ontainer); 
  
                     // Отримання списків з контейнера 
    }             SaveData.finish_list_car = receivedContainer.list1; 
                SaveData.finish_list_time = receivedContainer.list2; 
    public void TurnRight()  
    {             // Виконання подальшої обробки даних 
        currentSteerAngle = (maxSteerAngle * number) / 60;         } 
     } 
        if (currentSteerAngle > 30)  
        {     public override void 
            currentSteerAngle = 30; OnRoomPropertiesUpdate(ExitGames.Client.Photon.Hasht
            number = 60; able propertiesThatChanged) 
        }     { 
        frontLeftWheelCollider.steerAngle =         if (propertiesThatChanged.ContainsKey("Finish1")) 
currentSteerAngle;         { 
        frontRightWheelCollider.steerAngle =             // Отримати нове значення текстового поля 
currentSteerAngle;             SaveData.finish_list_car = 
 (List<string>)propertiesThatChanged["Finish1"]; 
        frontLeftWheelCollider.motorTorque = acceleration /             SaveData.finish_list_time = 
2; (List<string>)propertiesThatChanged["Finish2"]; 
        frontRightWheelCollider.motorTorque = acceleration;         } 
        rearLeftWheelCollider.motorTorque = acceleration /     } 
2; } 
        rearRightWheelCollider.motorTorque = acceleration /  
2;  
    } public class ListContainer {  
    private void StopCodeExecution()  
    {     public List<string> list1; 
        // Код, який зупиняє виконання     public List<string> list2; 
        frontLeftWheelCollider.motorTorque = 0 ;  
        frontRightWheelCollider.motorTorque = 0 ;     public ListContainer(List<string> list1, List<string> 
        rearLeftWheelCollider.motorTorque = 0 ; list2) 
        rearRightWheelCollider.motorTorque = 0 ;     { 
        // ...         this.list1 = list1; 
    }         this.list2 = list2; 
    private void UpdateWheels()     } 
    { } 
        UpdateSingleWheel(frontLeftWheelCollider,  
frontLeftWheelTransform); Код CarController.cs 
        UpdateSingleWheel(frontRightWheelCollider, using UnityEngine; 
frontRightWheeTransform); using TMPro; 
        UpdateSingleWheel(rearRightWheelCollider, using UnityEngine.UI; 
rearRightWheelTransform); using UnityEngine.EventSystems; 
        UpdateSingleWheel(rearLeftWheelCollider, using Photon.Pun; 
rearLeftWheelTransform); using Photon.Realtime; 
    } using System; 
80 
482 ЧДТУ 232227 –  01 12 01 – 2 
using System.Diagnostics;             CarController script = 
using ExitGames.Client.Photon; GetComponent<CarController>(); 
using Newtonsoft.Json;  
using System.Collections.Generic;             // Встановити стан активності скрипта на false 
             script.enabled = false; 
public class CarController : MonoBehaviourPunCallbacks,             return; 
IOnEventCallback         } 
{         Player = GameObject.Find(SaveData.car.name); 
    private float speed;         SaveData.finish = false; 
         Point_list = new 
 GameObject[test.transform.childCount]; 
    public AudioSource audioSource1;  
    public AudioSource audioSource2;         for (int i = 0; i < test.transform.childCount; i++) 
         { 
    public GameObject gas;             Point_list[i] = 
    public GameObject back; test.transform.GetChild(i).gameObject; 
    public GameObject arrowImage;         } 
  
    public TextMeshProUGUI speedd;         frontLeftWheelCollider = 
    public TextMeshProUGUI gear; GameObject.Find(Player.name + 
    public TextMeshPro time; "/Wheels/Colliders/FrontLeftWheel").GetComponent<Whe
 elCollider>(); 
    public GameObject Player;         frontRightWheelCollider = 
    public GameObject test; GameObject.Find(Player.name + 
    public GameObject user; "/Wheels/Colliders/FrontRightWheel").GetComponent<Wh
    public GameObject[] Point_list; eelCollider>(); 
    private int number = 0;         rearLeftWheelCollider = 
    private float koef = 4; GameObject.Find(Player.name + 
    private bool check = true; "/Wheels/Colliders/RearLeftWheel").GetComponent<Whe
    int currentMinute; elCollider>(); 
    int currentSecond;         rearRightWheelCollider = 
 GameObject.Find(Player.name + 
    public GameObject control; "/Wheels/Colliders/RearRightWheel").GetComponent<Wh
 eelCollider>(); 
    private List<string> cars = new List<string>();  
    private byte carsEventCode = 1;         frontLeftWheelCollider.forceAppPointDistance = 1; 
    [SerializeField] private float motorForce;         frontRightWheelCollider.forceAppPointDistance = 1; 
    [SerializeField] private float breakForce;         rearLeftWheelCollider.forceAppPointDistance = 1; 
    [SerializeField] private float maxSteerAngle;         rearRightWheelCollider.forceAppPointDistance = 1; 
  
    public TextMeshProUGUI textspeed;         frontLeftWheelTransform = 
    [SerializeField] private WheelCollider GameObject.Find("FrontLeftWheel").transform; 
frontLeftWheelCollider;         frontRightWheeTransform = 
    [SerializeField] private WheelCollider GameObject.Find("FrontRightWheel").transform; 
frontRightWheelCollider;         rearLeftWheelTransform = 
    [SerializeField] private WheelCollider GameObject.Find("RearLeftWheel").transform; 
rearLeftWheelCollider;         rearRightWheelTransform = 
    [SerializeField] private WheelCollider GameObject.Find("RearRightWheel").transform; 
rearRightWheelCollider;  
     } 
    [SerializeField] private Transform     private void Update() 
frontLeftWheelTransform;     { 
    [SerializeField] private Transform         if (Player == null) 
frontRightWheeTransform;         { 
    [SerializeField] private Transform             Start(); 
rearLeftWheelTransform;         } 
    [SerializeField] private Transform         speed = 
rearRightWheelTransform; Player.GetComponent<Rigidbody>().velocity.magnitude * 
    Stopwatch stopwatch; 3.6f; 
  
    void Start()         if (Player.transform.position.x > 
    { Point_list[number].transform.position.x - 10 && 
        stopwatch = new Stopwatch(); Player.transform.position.x < 
        currentMinute = 0; Point_list[number].transform.position.x + 10 && 
        currentSecond = DateTime.Now.Second;             
        gear.text = "1";            Player.transform.position.z > 
        if (SaveData.setting == true) Point_list[number].transform.position.z - 10 && 
        { Player.transform.position.z < 
            control.active = false; Point_list[number].transform.position.z + 10) 
81 
482 ЧДТУ 232227 –  01 12 01 – 2 
        {         motorForce = 5000 * koef; 
            if (Point_list.Length - 1 == number && check ==         float rotationAngle = 0f - (currentSpeed * koef); 
true)         if (rotationAngle < -250) 
            {         { 
                check = false;             koef -= 0.5f; 
                SaveData.race = false;             gear.text = (int.Parse(gear.text) + 1).ToString(); 
                SaveData.finish = true;         } 
                SaveData.finish_list_car.Add(Player.name);  
                SaveData.finish_list_time.Add(time.ToString());         if (rotationAngle > -170 && int.Parse(gear.text) != 1) 
                SaveData.pozition_finish =         { 
SaveData.finish_list_time.Count;             koef += 0.5f; 
             gear.text = (int.Parse(gear.text) - 1).ToString(); 
         } 
                ListContainer container = new         // Переведення швидкості в кут повороту 
ListContainer(SaveData.finish_list_car,  
SaveData.finish_list_time);         // Оновлення кута повороту стрілки 
         arrowImage.transform.rotation = Quaternion.Euler(0f, 
                // Серіалізація контейнера в рядок 0f, rotationAngle); 
                string serializedContainer =         if (Input.touchCount > 0) 
JsonConvert.SerializeObject(container);         { 
             Touch touch = Input.GetTouch(0); 
                // Створення опцій для передачі події  
                RaiseEventOptions raiseEventOptions = new             if (touch.phase == TouchPhase.Began || touch.phase 
RaiseEventOptions == TouchPhase.Stationary) 
                {             { 
                    Receivers = ReceiverGroup.All, // Отримувачі                 GameObject selectedObject = 
події (в даному випадку всі) EventSystem.current.currentSelectedGameObject; 
                    CachingOption = EventCaching.DoNotCache  
// Кешування події (не кешувати)                 if (selectedObject != null) 
                };                 { 
                     Image selectedImage = 
                // Виклик RaiseEvent для передачі selectedObject.GetComponent<Image>(); 
серіалізованого контейнера через Photon                     Button selectedButton = 
                PhotonNetwork.RaiseEvent(carsEventCode, selectedObject.GetComponent<Button>(); 
serializedContainer, raiseEventOptions,                     chekangle(); 
SendOptions.SendReliable);  
            }                     if (selectedImage != null && selectedButton != 
 null) 
            else if (check == true)                     { 
            {                         if (selectedObject.name == "Acceleration") 
                number++;                         { 
            }                             FullTroutl(); 
                             audioSource1.volume = 0.5f; 
        }                         } 
        if (SaveData.finish == true)                         if (selectedObject.name == "Deceleration") 
        {                         { 
            frontLeftWheelCollider.motorTorque = 0;                             Back(); 
            frontRightWheelCollider.motorTorque = 0;                             audioSource1.volume = 0.5f; 
            rearLeftWheelCollider.motorTorque = 0;                         } 
            rearRightWheelCollider.motorTorque = 0;                         if (selectedObject.name != "Acceleration" 
            frontRightWheelCollider.brakeTorque = 1000000; && selectedObject.name != "Deceleration") 
            frontLeftWheelCollider.brakeTorque = 1000000;                         { 
            rearLeftWheelCollider.brakeTorque = 1000000;                             StopCodeExecution(); 
            rearRightWheelCollider.brakeTorque = 1000000;                             audioSource1.volume = 0; 
            textspeed.text = speed.ToString();                         } 
        }                         if (selectedObject.name != "TurnRight" && 
        time.text = stopwatch.Elapsed.ToString(@"mm\:ss"); selectedObject.name != "TurnLeft") 
        if (currentSecond == 59)                         { 
        {                             number = 0; 
            currentMinute++;                             audioSource2.volume = 0; 
        }  
        speed =                             frontLeftWheelCollider.steerAngle = 0; 
(int)(Player.GetComponent<Rigidbody>().velocity.magnitu                             frontRightWheelCollider.steerAngle = 0; 
de * 3.6f);                         } 
        float currentSpeed = speed; // Отримання поточної                     } 
швидкості                 } 
        speedd.text = speed.ToString();             } 
        // Визначення кута повороту стрілки         } 
         if (number >= 0) 
82 
482 ЧДТУ 232227 –  01 12 01 – 2 
        {         UpdateSingleWheel(rearRightWheelCollider, 
            number--; rearRightWheelTransform); 
        }         UpdateSingleWheel(rearLeftWheelCollider, 
        if (number <= 0) rearLeftWheelTransform); 
        {     } 
            number++;  
        }     private void UpdateSingleWheel(WheelCollider 
        UpdateWheels(); wheelCollider, Transform wheelTransform) 
    }     { 
    public void chekangle()         Vector3 pos; 
    {         Quaternion rot; 
        float rotationX = Input.acceleration.x;         wheelCollider.GetWorldPose(out pos, out rot); 
        float rotationY = Input.acceleration.y;         wheelTransform.rotation = rot; 
        float rotationZ = Input.acceleration.z;         wheelTransform.position = pos; 
     } 
        // Обчислити кути повороту  
        float pitch = Mathf.Atan2(rotationY,     public void OnEvent(EventData photonEvent) 
Mathf.Sqrt(rotationX * rotationX + rotationZ * rotationZ))     { 
* Mathf.Rad2Deg;         if (photonEvent.Code == carsEventCode) 
        float roll = Mathf.Atan2(-rotationX, rotationZ) *         { 
Mathf.Rad2Deg;             // Отримання переданого масиву CarData від 
 іншого гравця 
        // Виконати дії з отриманими кутами повороту  
        // Наприклад, обертати об'єкт на сцені             string serializedContainer = 
 (string)photonEvent.CustomData; 
        frontLeftWheelCollider.steerAngle = roll;  
        frontRightWheelCollider.steerAngle = roll;             // Десеріалізація рядка в контейнер 
    }             ListContainer receivedContainer = 
 JsonConvert.DeserializeObject<ListContainer>(serializedC
    private void StopCodeExecution() ontainer); 
    {  
        // Код, який зупиняє виконання             // Отримання списків з контейнера 
        frontLeftWheelCollider.motorTorque = 0;             SaveData.finish_list_car = receivedContainer.list1; 
        frontRightWheelCollider.motorTorque = 0;             SaveData.finish_list_time = receivedContainer.list2; 
        rearLeftWheelCollider.motorTorque = 0;  
        rearRightWheelCollider.motorTorque = 0;             // Виконання подальшої обробки даних 
        // ...         } 
    }     } 
    public void Save_time_race()  
    {     public override void 
        OnRoomPropertiesUpdate(ExitGames.Client.Photon.Hasht
Save_new_time_race.Save_best_race_time(Player.name, able propertiesThatChanged) 
int.Parse(time.text), user.name);     { 
    }         if (propertiesThatChanged.ContainsKey("Finish1")) 
         { 
    public void FullTroutl()             // Отримати нове значення текстового поля 
    {             SaveData.finish_list_car = 
 (List<string>)propertiesThatChanged["Finish1"]; 
        frontLeftWheelCollider.motorTorque = motorForce;             SaveData.finish_list_time = 
        frontRightWheelCollider.motorTorque = motorForce; (List<string>)propertiesThatChanged["Finish2"]; 
        rearLeftWheelCollider.motorTorque = motorForce;         } 
        rearRightWheelCollider.motorTorque = motorForce;     } 
    } }  
    public void Back() Код SaveData.cs 
    { using System.Collections.Generic; 
 using UnityEngine; 
        frontLeftWheelCollider.motorTorque = -motorForce;  
        frontRightWheelCollider.motorTorque = -motorForce; public static class SaveData 
        rearLeftWheelCollider.motorTorque = -motorForce; { 
        rearRightWheelCollider.motorTorque = -motorForce;     public static string _levelStart; 
    }     public static string _car; 
     public static int car_cod; 
    private void UpdateWheels()  
    {     public static int money_dollar; 
        UpdateSingleWheel(frontLeftWheelCollider,     public static int money_gold; 
frontLeftWheelTransform);     public static int pozition_finish; 
        UpdateSingleWheel(frontRightWheelCollider,  
frontRightWheeTransform);     public static int id_code_car; 
    public static float dollar; 
83 
482 ЧДТУ 232227 –  01 12 01 – 2 
                 prize = Instantiate(test, new Vector3(posX2, 60, 
    public static GameObject car; 0), Quaternion.identity); 
    public static string name_car;                 prize.transform.SetParent(canvas.transform); 
    public static string name_map;                 int prizeAmount = (1000 / 
 SaveData.pozition_finish) + 200; 
                 prize.rectTransform.sizeDelta = new 
    public static bool setting; Vector2(screenWidth * 0.5f, screenHeight * 0.05f); 
                 prize.text = prizeAmount.ToString() + "$"; 
    public static bool finish;                 prize.color = Color.white; 
    public static bool race;                 prize.fontSize = 120; 
  
    public static List<string> finish_list_car = new                 SaveData.dollar += prizeAmount; 
List<string>();             } 
    public static List<string> finish_list_time = new             for (int i = count; i < 
List<string>(); SaveData.finish_list_time.Count; i++) 
             { 
    public static object finish_object = new object();                 float posX1 = screenWidth * 0.2f; 
                 float posX2 = screenWidth * 0.4f; 
    public static Dictionary<string, Dictionary<string,                 float posX3 = screenWidth * 0.75f; 
Dictionary<string, List<int>>>> top_time_track;// назва                 float posY = (i * -35) + (screenHeight * 0.9f); 
траси, ім'я гравця, авто ,рекорд траси  
}                 new_text = Instantiate(test, new Vector3(posX1, 
Код End_race.cs posY, 100), Quaternion.identity); 
using System;                 new_text.transform.SetParent(canvas.transform); 
using System.Collections;                 new_text.text = (i + 1).ToString(); 
using System.Collections.Generic;                 new_text.color = Color.white; // Зміна коліру на 
using TMPro; білий 
using UnityEngine;                 new_text.fontSize = 120; // Зміна розміру 
 шрифта на 120 
public class End_race : MonoBehaviour  
{                 new_text = Instantiate(test, new Vector3(posX2, 
    // Start is called before the first frame update posY, 100), Quaternion.identity); 
    public GameObject canvas;                 new_text.transform.SetParent(canvas.transform); 
    GameObject Player;                 new_text.rectTransform.sizeDelta = new 
    public TextMeshProUGUI new_text; Vector2(screenWidth * 0.5f, screenHeight * 0.05f); 
    public TextMeshProUGUI prize;                 new_text.text = 
    public TextMeshProUGUI test; SaveData.finish_list_car[i].ToString(); 
                 new_text.color = Color.white; // Зміна коліру на 
    private int count; білий 
    void Start()                 new_text.fontSize = 120; // Зміна розміру 
    { шрифта на 120 
        count = 0;  
        Player = GameObject.Find(SaveData.car.name);                 new_text = Instantiate(test, new Vector3(posX3, 
    } posY, 100), Quaternion.identity); 
                 new_text.transform.SetParent(canvas.transform); 
    // Update is called once per frame                 new_text.text = 
    void Update() SaveData.finish_list_time[i].ToString(); 
    {                 new_text.rectTransform.sizeDelta = new 
 Vector2(screenWidth * 0.5f, screenHeight * 0.05f); 
                 new_text.color = Color.white; // Зміна коліру на 
        if (SaveData.finish == true) білий 
        {                 new_text.fontSize = 120; // Зміна розміру 
            float screenWidth = Screen.width; шрифта на 120 
            float screenHeight = Screen.height;  
  
            canvas.SetActive(true);                 count = SaveData.finish_list_time.Count; 
            if (count == 0)             } 
            {         } 
                float posX1 = screenWidth * 0.3f;  
                float posX2 = screenWidth * 0.55f;     } 
                new_text = Instantiate(test, new Vector3(posX1,  
60, 0), Quaternion.identity);   
                new_text.transform.SetParent(canvas.transform); }  
                new_text.rectTransform.sizeDelta = new Код Random_map.cs 
Vector2(screenWidth * 0.5f, screenHeight * 0.05f); using System.Collections; 
                new_text.text = "Приз:"; using System.Collections.Generic; 
                new_text.color = Color.white; using System; 
                new_text.fontSize = 120; using System.IO; 
 using System.Collections; 
84 
482 ЧДТУ 232227 –  01 12 01 – 2 
using UnityEngine;     { 
using TMPro;         SaveData.setting = false; 
using UnityEngine.UI;         anglee.targetGraphic.color = new Color(1f, 1f, 1f, 
 0.5f); 
public class Random_map : MonoBehaviour         key.targetGraphic.color = new Color(0.5f, 0.75f, 1f); 
{     } 
    // Start is called before the first frame update  
    public Text timer;     public void angle() 
    public TextMeshProUGUI name_map;     { 
    public int cost;         SaveData.setting = true; 
    public int number_map;         anglee.targetGraphic.color = new Color(0.5f, 0.75f, 
    System.Random map = new System.Random(); 1f); 
    void Start()         key.targetGraphic.color = new Color(1f, 1f, 1f, 0.5f); 
    {     } 
        cost = new  
DirectoryInfo(@"Assets\Scenes\Race_map").GetFiles().Le     public void close_setting() 
ngth;     { 
        DirectoryInfo namemap = new         canvas.SetActive(false); 
DirectoryInfo(@"Assets\Scenes\Race_map");         canvas1.SetActive(true); 
        number_map = map.Next(0, cost / 2 );     } 
        } 
Debug.Log(namemap.GetFiles()[number_map*2].Name.Re  
move(namemap.GetFiles()[number_map*2].Name.Length - Код test.cs 
6)); using System.Collections; 
        name_map.text = number_map.ToString(); using System.Collections.Generic; 
        SaveData.name_map = using System.Threading; 
namemap.GetFiles()[number_map * using UnityEngine; 
2].Name.Remove(namemap.GetFiles()[number_map * using Photon.Pun; 
2].Name.Length - 6); using Photon.Realtime; 
    } using TMPro; 
 using ExitGames.Client.Photon; 
    // Update is called once per frame using Hashtable = System.Collections.Hashtable; 
    void Update()  
    { public class test : MonoBehaviourPunCallbacks 
       { 
    }     public TextMeshProUGUI timer; 
}     public TextMeshProUGUI title_race_map; 
     public GameObject testt; 
Код Setting.cs     public GameObject map; 
using System.Collections;     public Transform canvas; 
using System.Collections.Generic;     public Transform anchor; 
using UnityEngine;     string new_name_map = null; 
using UnityEngine.UI;     bool spawn = false; 
  
public class Setting : MonoBehaviour  
{     public GameObject[] Point_list; 
     public GameObject[] User_list; 
    public GameObject canvas;  
    public GameObject canvas1;     private int timer_start_race = 60; 
    public Toggle anglee;     // Start is called before the first frame update 
    public Toggle key;     void Start() 
    // Start is called before the first frame update     { 
    void Start()  
    {     } 
          
    }     // Update is called once per frame 
     void Update() 
    // Update is called once per frame     {        
    void Update()         // Оновити значення текстового поля в іншому 
    { користувача 
                 if (PhotonNetwork.CurrentRoom.PlayerCount > 0) 
    }         { 
    public void setting()  
    {             Player localPlayer = PhotonNetwork.LocalPlayer; 
        canvas.SetActive(true);             int playerIndex = localPlayer.ActorNumber; 
        canvas1.SetActive(false);  
    }             // Задати дані гравця 
             ExitGames.Client.Photon.Hashtable playerData = 
    public void keyboard() new ExitGames.Client.Photon.Hashtable(); 
85 
482 ЧДТУ 232227 –  01 12 01 – 2 
            playerData.Add("Car", SaveData.car.name);                             
            localPlayer.SetCustomProperties(playerData); Point_list[i].GetComponent<TextMeshProUGUI>().text = 
 player.NickName; 
            if (SaveData.name_map != null)                             
            { Point_list[i+1].GetComponent<TextMeshProUGUI>().text 
                ExitGames.Client.Photon.Hashtable name_map = = (string)player.CustomProperties["Car"]; 
new ExitGames.Client.Photon.Hashtable();//Передача                             User_list[player.ActorNumber - 
назви траси 1].SetActive(true); 
                name_map["TextFieldd"] =                             break; 
SaveData.name_map;                         } 
                                        if (player.ActorNumber == 1 + i / 2) 
PhotonNetwork.CurrentRoom.SetCustomProperties(name_                         { 
map);                             
 Point_list[i].GetComponent<TextMeshProUGUI>().text = 
                if (playerIndex == 1) player.NickName; 
                {                             
 Point_list[i+1].GetComponent<TextMeshProUGUI>().text 
                    string name_mini_map = "Race_mini_map/" + = (string)player.CustomProperties["Car"]; 
SaveData.name_map + "_mini";                             User_list[player.ActorNumber - 
                    map = 1].SetActive(true); 
(GameObject)Resources.Load(name_mini_map);                             break; 
                    title_race_map.text = SaveData.name_map;                         } 
                    testt = Instantiate(map, new Vector3(400, 305,                          
0), Quaternion.identity, canvas);                     } 
                    testt.transform.SetParent(anchor, false);                 } 
                    testt.transform.localPosition = Vector3.zero;             } 
                    testt.transform.localRotation =         } 
Quaternion.identity;         Thread.Sleep(900); 
                }     } 
                ExitGames.Client.Photon.Hashtable index = new     public override void OnPlayerEnteredRoom(Player 
ExitGames.Client.Photon.Hashtable();//Передача назви newPlayer) 
траси     { 
                index["Index"] = playerIndex.ToString();         Debug.LogFormat("Игрок {0} підключився ", 
                newPlayer.NickName); 
PhotonNetwork.CurrentRoom.SetCustomProperties(index);     } 
            }     public override void OnPlayerLeftRoom(Player 
            ExitGames.Client.Photon.Hashtable otherPlayer) 
customProperties = new     { 
ExitGames.Client.Photon.Hashtable();// передача часу до         Debug.LogFormat("Игрок {0} вийшов ", 
старту гонки otherPlayer.NickName); 
            customProperties["TextField"] =     } 
timer_start_race.ToString();  
                public override void 
PhotonNetwork.CurrentRoom.SetCustomProperties(custom OnRoomPropertiesUpdate(ExitGames.Client.Photon.Hasht
Properties); able propertiesThatChanged) 
                 { 
            timer_start_race -= 1;      
            if (timer_start_race < 2 && timer_start_race > 0)         // Отримати нове значення текстового поля 
            {         if 
                (propertiesThatChanged.ContainsKey("TextFieldd")) 
PhotonNetwork.LoadLevel(SaveData.name_map);         { 
                //Загрузка сцени гонки             new_name_map = 
                timer_start_race = 0; (string)propertiesThatChanged["TextFieldd"]; 
            }         } 
            if (timer_start_race < 0)         if (propertiesThatChanged.ContainsKey("Index")) 
            {         { 
                timer_start_race = 0;             string index = 
            } (string)propertiesThatChanged["Index"]; 
            if (PhotonNetwork.InRoom)             if (index == "1" && new_name_map != null && 
            { spawn == false) 
                Player[] players = PhotonNetwork.PlayerList;             { 
                foreach (Player player in players)                 string name_mini_map = "Race_mini_map/" + 
                { SaveData.name_map + "_mini"; 
                    for (int i = 0; i < Point_list.Length; i =+ 2)                 map = 
                    { (GameObject)Resources.Load(name_mini_map); 
                        Debug.Log(player.ActorNumber);                 testt = Instantiate(map,new Vector3(400, 305, 0), 
                        if (player.ActorNumber == i+1) Quaternion.identity, canvas); 
                        {                 testt.transform.SetParent(anchor, false); 
                                            testt.transform.localPosition = Vector3.zero; 
86 
482 ЧДТУ 232227 –  01 12 01 – 2 
                testt.transform.localRotation = using UnityEngine; 
Quaternion.identity; using TMPro; 
                SaveData.name_map = new_name_map; using UnityEngine.UI; 
                title_race_map.text = new_name_map; using Photon.Pun; 
                spawn = true;  
            } public class Lobby : MonoBehaviourPunCallbacks 
        } { 
    
        if (propertiesThatChanged.ContainsKey("TextField"))     // Start is called before the first frame update 
        {     void Start() 
            string newTextFieldValue =     { 
(string)propertiesThatChanged["TextField"];         PhotonNetwork.NickName = "Player " + 
            if (timer_start_race > Random.Range(1000, 9999); 
int.Parse(newTextFieldValue))         Debug.Log("Player add = " + 
            { PhotonNetwork.NickName); 
                timer_start_race = int.Parse(newTextFieldValue);  
            }         PhotonNetwork.AutomaticallySyncScene = true; 
            timer.text = timer_start_race.ToString();         PhotonNetwork.GameVersion = "1"; 
        }         PhotonNetwork.ConnectUsingSettings(); 
        // Оновити значення текстового поля в графічному  
інтерфейсі  
    }     } 
}  
     public override void OnConnectedToMaster() 
Код test.cs     { 
using System.Collections;         Debug.Log("OnConnectedToMaster"); 
using System.Collections.Generic;     } 
using System.Threading;  
using UnityEngine;     public void CreateRoom() 
using Photon.Pun;     { 
using Photon.Realtime;         Debug.Log("Створення нової кімнати"); 
using TMPro;         PhotonNetwork.CreateRoom(null, new 
using Cinemachine; Photon.Realtime.RoomOptions {MaxPlayers = 8 }); 
     } 
public class Multi_game : MonoBehaviourPunCallbacks     public void JoinRoom() 
{     { 
    public CinemachineVirtualCamera camera;       
    public GameObject car;         PhotonNetwork.JoinRandomRoom(); 
     } 
    public GameObject[] Start_position;  
    // Start is called before the first frame update     public override void OnJoinedRoom() 
    void Start()     { 
    {         Debug.Log("Підключення до рандомної карти"); 
        Player localPlayer = PhotonNetwork.LocalPlayer;         PhotonNetwork.LoadLevel("Race lobby"); 
        int playerIndex = localPlayer.ActorNumber-1;     } 
  
        string buffer = "Car/"+ SaveData.car.name;     public override void OnJoinRandomFailed(short 
        car = PhotonNetwork.Instantiate(buffer, new returnCode, string message) 
Vector3(2, 0), Quaternion.identity);     { 
                Debug.Log("Помилка підключення, створюєм нову 
car.transform.SetParent(Start_position[playerIndex].transfo кімнату"); 
rm, false);         CreateRoom(); 
        car.transform.localPosition = Vector3.zero;     } 
        car.transform.localRotation = Quaternion.identity;     // Update is called once per frame 
        car.name = SaveData.car.name;   
        camera.Follow = car.transform;     void Update() 
        camera.LookAt = car.transform;     { 
    }          
     } 
    // Update is called once per frame } 
    void Update()  
    { Код test.cs 
 using System.Collections; 
    } using System.Collections.Generic; 
} using TMPro; 
 using UnityEngine; 
Код test.cs using UnityEngine.SceneManagement; 
using System.Collections; using UnityEngine.UI; 
using System.Collections.Generic;  
87 
482 ЧДТУ 232227 –  01 12 01 – 2 
public class LoadScreen_gen2 : MonoBehaviour  
{  
    public string name_level; 
    public Slider bar; 
    private string _levelScene; 
 
    public TextMeshProUGUI _dollar; 
    public TextMeshProUGUI _gold; 
    // Start is called before the first frame update 
    void Start() 
    { 
        //_dollar.text = SaveData.money_gold.ToString(); 
        //_gold.text = SaveData.money_gold.ToString(); 
        if (SceneManager.GetActiveScene().name == 
"Loading games") 
        { 
            Load(); 
        } 
    } 
 
    // Update is called once per frame 
    void Update() 
    { 
 
    } 
 
    public void LoadScene(string nextScene) 
    { 
        SaveData._levelStart = nextScene; 
        AsyncOperation asyncLoad = 
SceneManager.LoadSceneAsync("Loading games"); 
    } 
    public void LoadScene() 
    { 
        SaveData._levelStart = SaveData.name_map; 
        AsyncOperation asyncLoad = 
SceneManager.LoadSceneAsync("Loading games"); 
    } 
 
    public void Load() 
    { 
        _levelScene = SaveData._levelStart; 
        
        if (_levelScene == null) 
        { 
            name_level = "Authorization"; 
        } 
        else if (_levelScene != null) 
        { 
            name_level = _levelScene; 
        } 
 
        StartCoroutine(LoadAsync()); 
    } 
 
    IEnumerator LoadAsync() 
    { 
        AsyncOperation asyncLoad = 
SceneManager.LoadSceneAsync(name_level); 
 
        while (!asyncLoad.isDone) 
        { 
            bar.value = asyncLoad.progress; 
            yield return null; 
        } 
    } 
}