\documentclass[a4paper, 14pt]{article}
\usepackage{fontspec, extsizes, geometry, setspace, titlesec, fancyhdr, graphicx, float, setspace, caption, array, tabularx, ulem, indentfirst, ragged2e, caption, appendix, url}
\usepackage[main=ukrainian, english]{babel} % підтримка мов
\usepackage[dotinlabels]{titletoc} 
\setmainfont[Ligatures=TeX]{Times New Roman}
\geometry{a4paper,left=3cm,top=2cm,bottom=2cm,right=1.5cm} % cтавить береги та формат а4
\def\changemargin#1#2{\list{}{\rightmargin#2\leftmargin#1}\item[]}\let\endchangemargin=\endlist % зручна команда для виставлення відступів
\makeatletter\newcommand\Dotfill{\leavevmode\leaders\hb@xt@0.5em{\hss.\hss}\hfill}\makeatother % команда для ставлення точок
\let\stdsection\section\renewcommand\section{\newpage\stdsection} % Новая секція -> нова сторінка
\addto\captionsukrainian{\renewcommand{\figurename}{Рисунок}} % підпис картинок не Рис. а Рисунок
\titleformat{\section}{\filcenter}{\bfseries{\thesection} }{0pt}{\bfseries\MakeUppercase} % Форматування заголовків всіх розділів
% \renewcommand{\thesubsection}{\arabic{section}.\arabic{subsection}} % Чиним номер подраздела
\titleformat{\subsection}{}{{\thesubsection} }{0pt}{} % нумерація підрозділів
\titlespacing*{\subsection}{\parindent}{1em}{1em} % рядок перед та пілся підрозділу та підрозділ з абзацу
\titleformat{\subsubsection}{}{{\thesubsubsection} }{0pt}{} % нумерація підпідрозділів
\titlespacing*{\subsubsection}{\parindent}{1em}{1em} % рядок перед та пілся підпідрозділу та підпідрозділ з абзацу
\titlespacing*{\section}{0pt}{1em}{1em} % рядок перед та пілся розділу
\captionsetup{labelsep=endash} % "Рис. 1 - замість Рис. 1:"
\fancyhf{}\renewcommand{\headrulewidth}{0pt}\newcommand{\changefont}{\fontsize{14}{14}\selectfont}\fancyhead[R]{\changefont \thepage}\fancypagestyle{plain}{\fancyhf{}\fancyhead[R]{\changefont \thepage}\renewcommand{\headrulewidth}{0pt}\renewcommand{\footrulewidth}{0pt}}\pagestyle{fancy} %номер страницы справа сверху на всех страничках [это ужас]
\linespread{1.43} % Інтервал абзацу полуторний
% \renewcommand{\contentsname}{ЗМІСТ} %изменяем название странички с содержанием
\def\numberline#1{#1. } % Фикс чтобы названия не налезали друг на друга в содержании
\titlecontents{section}[0pt]{\normalfont}{{\thecontentslabel} }{}{\Dotfill \contentspage} % оформление разделов, точек в содержании
\titlecontents{subsection}[15pt]{\normalfont}{{\thecontentslabel} }{}{\Dotfill \contentspage} % оформление подразделов, точек в содержании
\titlecontents{subsubsection}[30pt]{\normalfont}{{\thecontentslabel} }{}{\Dotfill \contentspage} % оформление подподразделов, точек в содержании
\counterwithin{figure}{section} % нумерация картинок с номером раздела
\counterwithin{table}{section} % нумерация таблиц с номером раздела
\usepackage[none]{hyphenat} % щоб слова переносились закоментуйте цей та наступний рядок
\justifying\sloppy % щоб текст розтягувався
\setlength{\parindent}{0.5in} % виставляємо відступ абзацу
\captionsetup[table]{format=hang,margin=0.5in, justification=raggedright, singlelinecheck=false} % підпис таблиць не по центру а з абзацу

% для форматування картинок та таблиць:
\setlength{\intextsep}{0pt}
\captionsetup[figure]{belowskip=-1em}
\newlength{\magicspace}\setlength{\magicspace}{2\baselineskip}
% щоб був рядок до і після картинки: 
\let\oldfigure\figure
\let\endoldfigure\endfigure
\renewenvironment{figure}[1][]{\begin{oldfigure}[#1]\vspace{1em}}{\vspace{1em}\end{oldfigure}}
% щоб був рядок до і після таблиці: зроблено експериментально :)
\let\oldtable\table
\let\endoldtable\endtable
\renewenvironment{table}[1][]{\begin{oldtable}[#1]\vspace{2em}}{\vspace{1em}\end{oldtable}}
% це капець.....

\addto\extrasukrainian{\renewcommand\refname{Перелік джерел посилання}} % змінити назву переліка посилань з Література на Перелік джерел посилання
% змінюємо нумерацію в переліку посилань з [1] на 1. :
\makeatletter
\renewcommand*\@biblabel[1]{#1.}
\makeatother

\usepackage{totcount}
% каунтер для референсів:
\newtotcounter{citnum}
\def\oldbibitem{} \let\oldbibitem=\bibitem
\def\bibitem{\stepcounter{citnum}\oldbibitem}

% каунтер для рисунків та таблиць:
\usepackage[figure,table]{totalcount}

% каунтер для додатків: (хз як це працює :) )
\AtBeginDocument{
    %% register a counter on the basis of the last chapter in totcounter
    \regtotcounter{section}
}

\usepackage{lastpage} % для каунтера сторінок

\usepackage{enumitem} % для прибирання зайвих відступів поміж ітемів списків
\setlist[]{noitemsep, nolistsep, left=\parindent}
\setlist[itemize]{label=--} % також заміняємо точку на тире
\setlist[enumerate]{label=\arabic*)} % ставимо дужку
% ------------------------------------------- Преамбула закінчилась -------------------------------------------

% ------------------------------------------- Титулка ---------------------------------------------------------
\begin{document}
% Титулка
\thispagestyle{empty}
\begin{center}
Міністерство освіти і науки України\\
Харківський національний університет радіоелектроніки \par
\null\par
Кафедра програмної інженерії \par
\null\par\null\par\null\par
КУРСОВА РОБОТА\\
ПОЯСНЮВАЛЬНА ЗАПИСКА\\
з дисципліни ``Об'єктно-орієнтоване програмування''\\
Ігровий застосунок "Boulder Dash" 
\end{center}
\par\null\par\null
\begin{changemargin}{-0.25cm}{0cm}
\begin{tabular}{ p{20em} p{11em} } 
Керівник , ст. викл.  & Ляпота В. М. \\
Студент гр. ПЗПІ-23-3 & Білоус А. А. \\
\end{tabular}
\par\null\par\null
\begin{tabular}{ l } 
Комісія: \\
\end{tabular}
\end{changemargin}
\begin{changemargin}{1cm}{0cm}
\begin{tabular}{ p{12em} p{7em} p{8em} }
    Проф. & \underline{\makebox[7em][c]{}} & Бондарєв В. М. \\
    Ст. викл. & \underline{\makebox[7em][c]{}} & Черепанова Ю. Ю. \\
    Ст. викл. & \underline{\makebox[7em][c]{}} & Ляпота В. М. \\
\end{tabular}
\vspace*{\fill}\end{changemargin}
\begin{center}
Харків -- \the\year{}
\end{center}
\newpage
% ------------------------------------------- Титулка закінчилась ---------------------------------------------

% ------------------------------------------- Аркуш завдання --------------------------------------------------
\begin{center}
    ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ
    \begin{changemargin}{1cm}{0cm}
        \begin{tabular}{ l l }
    Кафедра & \textit{програмної інженерії} \\
Рівень вищої освіти & \textit{перший (бакалаврський)} \\
Дисципліна & \textit{Об’єктно-орієнтоване програмування} \\
Спеціальність & 1\textit{21 Інженерія програмного забезпечення} \\
Освітня програма & \textit{Програмна інженерія} \\
\end{tabular}
    \end{changemargin}
\begin{tabularx}{\textwidth} { 
   >{\raggedright\arraybackslash}X 
   >{\centering\arraybackslash}X 
   >{\raggedleft\arraybackslash}X  }
 Курс \underline{\makebox[5em][c]{\textit{1}}}  & Група \underline{\makebox[5em][c]{\textit{ПЗПІ-23-3}}} & Семестр \underline{\makebox[5em][c]{\textit{2}}}\\
\end{tabularx}
\null\par\null
\textit{\textbf{ЗАВДАННЯ \\
на текстовий проєкт студента}} \par
\underline{\makebox[\textwidth][c]{Білоуса Антона Андрійовича}} \\
\scriptsize{(Прізвище, Ім'я, По батькові)} \\
\end{center}
1 Тема проєкту: \\
\uline{\makebox[\textwidth][c]{Ігровий застосунок "Boulder Dash" }} \\ 
2 Термін здачі студентом закінченого проекту: \textbf{\textit{``\underline{08}'' - червня - 2024 р.}} \\
3 Вихідні дані до проекту: \par
\uline{Методичні вказівки до виконання курсової роботи}  \par \null \par \noindent
Зміст розрахунково-пояснювальної записки: \par
\uline{Вступ, опис вимог, проектування програми, інструкція користувача, висновки} \\
\newpage
% ------------------------------------------- Аркуш завдання закінчився ---------------------------------------

% ------------------------------------------- Календарний план ------------------------------------------------
\noindent
\begin{center}
    КАЛЕНДАРНИЙ ПЛАН \par \null \par
    \end{center}
  \begin{tabular}{|p{1em} | p{17em} | p{11em}|}
     \hline
        \multicolumn{1}{|c|}{\textit{№}} & \multicolumn{1}{c}{\textit{Назва етапу}} & \multicolumn{1}{|c|}{\textit{Термін виконання}} \\ \hline
    1 & Видача теми, узгодження і затвердження теми & 13.02.2024 - 15.03.2024 р. \\ \hline
    2 & Формулювання вимог до програми & 15.02.2024 — 20.02.2024 р. \\ \hline
    3 & Розробка головної частини гри & 20.02.2024 — 4.03.2024 р. \\ \hline
    4 & Розробка парсера аргументів командної строки & 4.03.2024 — 14.03.2024 р. \\ \hline
    5 & Розробка основної логіки гри & 14.03.2024 — 3.04.2024 р. \\ \hline
    6 & Розробка відображення гри у терміналі та у вікні & 3.04.2024 — 23.04.2024 р. \\ \hline
    7 & Створення пояснювальної записки та документації до застосунку & 23.04.2024 — 10.05.2024 р. \\ \hline
    8 & Захист & \hspace{0.01em}03.\hspace{0.01em}06.2024 — \hspace{0.01em}08.\hspace{0.01em}06.2024 р. \\ \hline
  \end{tabular}

\par \null \par \null \par \null \par \null \par \null \par \noindent
\begin{tabularx}{\textwidth} { 
   >{\raggedright\arraybackslash}X 
   >{\raggedleft\arraybackslash}X  }
    Cтудент \underline{\hspace{10em}} \\
    \\
    Керівник \underline{\hspace{10em}} & \underline{\hspace{10em}} \\
     & \scriptsize{(Прізвище, Ім'я, По батькові)} \\
     << 21 >> \underline{\makebox[5em][l]{ лютого}} 2024 р.
\end{tabularx}
% ------------------------------------------- Календарний план закінчився -------------------------------------

% ------------------------------------------- Реферат ---------------------------------------------------------
\section*{РЕФЕРАТ}
Пояснювальна записка до курсової роботи на тему "Ігровий застосунок «Boulder Dash»".

Метою роботи є розробка клону гри «Boulder Dash», яка буде мати базовий геймплей
схожий на оригінальний, а також мінімальний редактор рівнів який дозволить створювати нові карти для гри.

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

В процесі розробки використано текстовий редактор Neovim, графічну бібліотеку Rust-SDL2\cite{Rust-SDL2} та біблеотеку абстакції терміналу console, мова програмування Rust\cite{rust} 2021 року видання.
% ------------------------------------------- Реферат закінчився ----------------------------------------------

% ------------------------------------------- Зміст -----------------------------------------------------------
\tableofcontents %генерація змісту
% ------------------------------------------- Зміст завершився ------------------------------------------------

% ------------------------------------------- Вступ -----------------------------------------------------------
\section*{Вступ}
\addcontentsline{toc}{section}{Вступ} %додаємо сторінку Вступу до змісту
Залежність від дофаміну є великою проблемаю сучасності, тому темою цієї курсової роботи є створення мінімального клону Boulder Dash який допоможе людству не померти від нудьги, а автору відточити свої навички програмування.

Boulder Dash — це 2D відеогра-лабіринт-головоломка, випущена в 1984 році компанією First Star Software для 8-бітних комп'ютерів Atari. Її створили канадські розробники Пітер Ліепа та Кріс Грей. Гравець керує персонажем, який збирає скарби, уникаючи падаючого на нього каміння та інших небезпек.

Для реалізації цього проекту була обрана мова програмування Rust. Вона є безсумнівно найкращою мовою сьогодення, яка є неймовінро швидкою та ефективною по викорисанню пам'яті, і не витрачає час виконня і ресурси процесора збирачом сміття. Rust може працювати з критично важливими до продуктивності сервісами, запускатися на вбудованих пристроях та легко інтегруватися з іншими мовами. Розширена математична система типів та модель власності цієї дивовижної мови гарантуює безпеку пам'яті та надзвичайно просте використання мультипоточності, що дозволяє усунути майже всі помилки ще на етапі компіляції.

Ця курсова робота була розроблена для Linux сумісних систем через зручність та наявність нормальних інструментів для програмування і користування застосунком.
% ------------------------------------------- Вступ закінчився ------------------------------------------------

% ------------------------------------------- Ну і далі сама ваша курсова -------------------------------------
\section{Опис вимог}
\label{sec:requirements} % можна позначати також розділи
\subsection{Основний задум гри}
Повинен бути створений мінімальний клон аркадної гри Boulder Dash.  Застосунок отримує список рівнів які треба пройти і дає змогу це зробити. Рівні це лабінт-печера, в ньому потрібно знайти спосіб зібрати всі кристалики оминаюче падаюче каміння, штовхаючи його вбік та оминати блокуючих ситуацій. Гравець з'являється на першому рівні який є печерою, він має пройти лабіринт що б попасти на наступний, або, якщо наступного рівня немає, закінчити гру перемогою.

\subsection{Ігрові об'єкти}
В оригінальній версії гри досить багато об'єктів. Через те що у цій роботі робиться лише клон, то мають бути реалізовані тільки ключові елементи. Застосунок має обов'язково містити в собі такі об'єкти:
\subsubsection{Гравець}
Гравець — об'єкт, яким користувач керує з клавіатури. Може переміщуватись у всіх чотирьох напрямках, ламати пісок та збирати алмази, а також штовхати каміння. Після руху гравець залишає порожнечу позаду себе.

Гравець має мати свій особистий клас який відповідає за поведінку, властивості та відображення цього об'єкту. Об'єкт має мати шляхи для взаємодії з усіма частинами застосунку. Реалізація класу повинна бути в окремому файлі.
\subsubsection{Кристал}
Кристал — статичний нерухомий об'єкт, який збільшує лічильник очок при знищені, та дає змогу завершити гру перемогою коли лічильник доходить до максимально значення, тобто було зібранне все каміння.

Кристал має мати свій особистий клас який відповідає за поведінку, властивості та відображення цього об'єкту. Об'єкт має мати шляхи для взаємодії з усіма частинами застосунку. Реалізація класу повинна бути в окремому файлі.
\subsubsection{Каміння}
Каміння — об'єкт який падає вниз якщо під ним порожнеча або по діагоналі якщо він находиться на краю, тобто клітина збоку та клітину знизу цього боку є порожніми. Коли під цим об'єктом знаходиться Гравець, та Гравець не зламав об'єкт який стримував каміння від падіння (Гравець може встигнути пробіжати під камінням, якщо воно не падало), то гра закінчується програшом. Гравець може рухати камень в бік якщо за цим каменем порожнеча.

Каміння має мати свій особистий клас який відповідає за поведінку, властивості та відображення цього об'єкту. Об'єкт має мати шляхи для взаємодії з усіма частинами застосунку. Реалізація класу повинна бути в окремому файлі.
\subsubsection{Стіна}
Стіна — статичний нерухомий та незламний об'єкт котрий обмежує рух об'єктів таких як гравець та камень. Цей об'єкт використовується для створення каркасу ріня і самого лабіринту цієї гри, тому вона має робити рамку навколо рівня.

Стіна має мати свій особистий клас який відповідає за поведінку, властивості та відображення цього об'єкту. Об'єкт має мати шляхи для взаємодії з усіма частинами застосунку. Реалізація класу повинна бути в окремому файлі.
\subsubsection{Пісок}
Пісок — статичний нерухомий об'єкт, який може бути зламаний гравцем. Цей об'єкт слугує для утримання каміння від падіння з ціллю формування більш цікавив та динамічних рівняв, в котрих існуть пастки.

Пісок має мати свій особистий клас який відповідає за поведінку, властивості та відображення цього об'єкту. Об'єкт має мати шляхи для взаємодії з усіма частинами застосунку. Реалізація класу повинна бути в окремому файлі.


\subsection{Режими відображення}
Гра має мати два режими відображення: консольний та графічний. Обидва режими мають мати спільну кодову базу, точніше мають бути незалежними від внутрішньої логіки гри і використовувати інтерфейси для взаємодії з нею, створюючи невеличке API для відображення логічних об'єктів на екран.

\subsubsection{Консольний режим відображення}
Консольний режим має мати такий же самий вигляд як і текствоий вигляд рівня у файлі. Цей файл має бути завантажений у пам'ять застосунку, та кожен символ має бути перетворений на відповідний об'єкт у матриці рівня.

Консльний режим має відображати весь інтерфейс гри символами в консолі, а також оброблювати натискання клавіатури та корректно реагувати на сполуки клавіш такі як Ctrl+C для виходу з гри.

\subsubsection{Графічний режим відображення}
Графічний режим має мати свою теку з текстурами для кожного ігрового об'єкту. За ім'ям кожного об'єкту цей режим завантажує в пам'ять застосунку відповідний файл в теці, піля чого при відображенні у графічному вікні загружена інформація перетворюється в текстуру.

Графічний режим має створити нове вікно де буде відображатись рівень та поточний статус застосунку. Вікно має автоматично змінювати свій розмір та коректно реагувати на події закриття, спроби зміни розміру вікна та натискання клавіш та їх сполук на клавіатурі.

\subsection{Редактор рівнів}
Застосунок має містити в собі редактор рінів. Цей режим застосунку дозволяє створювати нові рівні гри та мати змогу їх зберегти для проходження в режимі гри пізніше. Редактор має мати інтуітивно зрозумілий інтерфейс та бути зручним для використання. Розмір рівня який редагується має мати змогу динамічно змінюватись.

Редактор має коректно реагувати на невідомі об'єкти, коректно зберігати рівні у файл та підтримувати всі режими відрисовки. Для цього мають бути реалізовані відповідні інтерфейси та робота з файлами.

\section{Проєктування програми}

\subsection{Вимоги}
В ході реалізації проекту крім вимог наведених у першому пункті було також реалізовано наступні пункти:
\begin{itemize}
    \item незалежний від інших компонентів застосунку парсер командної строки;
    \item третій режим відображення який знаходиться між консольним та графічним, — псевдографічний;
    \item запам'товування налаштувань гри між різними рівнями;
    \item можливість перепройти програний рівень;
    \item режим паузи у котрому каміння падає тільки поки гравець рухається;
    \item регулювання швидкості гри яке дозволяє прискорити падіння каміння та рух гравця.
\end{itemize}

\subsection{Проектування}
При проектування застосунку було вирішено використовувати принципи SOLID. На протязі розробки ці принципи були кілька разів порушені через нові вимоги які раптово з'являлись, а також через відсутність повноцінного об'єктно орієнтованого програмування в Rust та його специфічну парадигму яку прийшлося пристосовувати до ООП. Після рефакторингу та змін в структурі застосунку, принципи SOLID були дотримні. Поліморфізм та наявність інтерфейсів зробили кодову базу набагато зрозуміліше та менше, даючи можливість дуже просто імплементувати нові речі, такі як об'єкти, режими взаємодії (консольний, псевдографічний та графічний) та режими застосунку( гра та редактор рівів).

\subsection{Етап запуску застосунку}
Застосунок запускається командою консолі, в якій він отримає аргументи для запуску, після чого ці аргументи передаються до парсерсу. Якщо якогось агрументу не має, то використовується параметр за замовчуванням. Коли було дано помилкове значення, то застосунок не запуститься, але напише який агрумент має некоректне значення. Отримати список всіх аргументів та їх параметрів можна за допомогою аргрумента "\texttt{-}h", або "\texttt{-{}-}help".

Реалізація парсеру аргументів повністю незалежна від інших компонетів гри, що відповідає принципам SOLID. Стуктура яку збирає цей парсер використовується по застосунку тільки для того, щоб компоненти могли ініціалізуватися дивлячись на конфігурацію задану користувачем. Вона передається у функцію run, яка сворює нові об'єкти режиму взаємодії та режиму гри. Після цього фукнція run передає контроль у створені об'єкти які можуть повернути помилку, в цьому випадку функція run поверне цю помилку у функцію main, де ця помилка буде виведена в консольний канал для помилок.

\subsection{Інтерфейси застосунку}
Цей застосунок має в собі п'ять інтерфейсів, які є самою головною частиною програми та значно полегшують розробку нового функціоналу. Можна виокремити дві групи: інтерфейси взаємодії та інтерфейси ігрових об'єктів.

Інтерфейси взаємодії дозволяють різним режимам взаємодії відображати різні режими застосунку, їх перелік:
\begin{itemize}
    \item "Drawable" — інтерфейс для режимів застосунку;
    \item "Interaction" — інтерфейс для режимів взаємодії.
\end{itemize}

Кожний ігровий об'єкт імплементує три інтерфейси:
\begin{enumerate}
    \item "Labels" — інтерфейс для позначення об'єкту;
    \item "Properties" — інтерфейс для отримання логічних властивостей об'єкту;
    \item "Behaviour" — інтерфейс для реалізації логіки об'єктів.
\end{enumerate}

\subsubsection{Інтерфейс малювання Drawable}
Цей інтерфейс має в собі функції для отримання графічних даних режима застосунка режимом взаємодії, а саме:
\begin{itemize}
    \item get\_cursor — повертає позицію курсову. Використовується режимом редактору рівнів;
    \item get\_width — повертає найбільшу ширишу рівня враховуючи ширину тексту статусу. Використовується в графічному режимі відображення;
    \item get\_height — повертає висоту відображаємого вмісту режиму застосунка;
    \item get\_status — повертає строку стану застосунку. Використовується для отримання актуальної інформації;
    \item get\_damaged — повертає набір точок які були змінені і котрі треба перемалювати. Використовується консольним та графічним режимами взаємодії;
    \item get\_objects — повертає матрицю з усіма ігровими об'єктами режима застосунку. Використовується всіма режимами взаємодії;
    \item get\_object — отримує позицію та повертає об'єкт котрий лежить у тій позиції. Використовується у сполуці з функцією get\_damaged.
\end{itemize}

\subsubsection{Інтерфейс взаємодії Interaction}
Цей інтерфейс має в собі функції для взаємодії режимів застосунку з зовнішнім світом, а саме:
\begin{itemize}
    \item get\_input — функція імлементація якої повинна зчитати ввід з клавіатури та повернути уніфіцирований тип застосунку для вводу Input;
    \item draw — функція імплементація якої повинна отримати об'єкт імплементуючий інтферфейс малювання Drawable, та відобразити його на екрані.
\end{itemize}

\subsubsection{Інтерфейс позначення Labels}
Цей інтерфейс має в собі функції для ідентифікації об'єкту, а саме:
\begin{itemize}
    \item char — повертає символ який використовується при збереженні об'єкта у файл, а також у консольному режиму взаємодії;
    \item emoji — повертає емоджи яке використовується у псевдографічному режимі взаємодії;
    \item name — повертає ім'я об'єкту яке використовується для отримання назви файлу з картинкою даного об'єкту для його відображення у графічному режиму взаємодії.
\end{itemize}
\subsubsection{Інтерфейс властивостей Properties}
Цей інтерфейс має в собі функції для отримання логічних властивостей об'єкту, а саме:
\begin{itemize}
    \item placeholder — об'єкти які просто займають місце у матриці рівня;
    \item can\_be\_moved — об'єкти які можуть бути подвинуті гравцем;
    \item player — об'єкт котрий являється гравцем;
    \item can\_be\_broken — об'єкт котрий може бути зламаний гравцем.
\end{itemize}
\subsubsection{Інтерфейс поведінки Behaviour}
Цей інтерфейс має в собі функції які імплементують ігрову логіку об'єкту, а саме:
\begin{itemize}
    \item init — функція яка викликається при створені об'єкту і відправляє запроси до рівня гри;
    \item on\_broken — функція яка викликається при знищенні об'єкту і відправляє запроси до рівня гри;
    \item tick — функція яка викликається коли оновлюється рівень, і відправляє запроси до рівня гри.
\end{itemize}

\subsection{Об'єкти взаємодії}
Ці об'єкти імплементують інтерфейс взаємодії Interaction та відображають об'єкти які імплементають інтерфейс відображення Drawabale. Це дозволяє ефективне використання поліморфізму для розширення застосунку. Інтерфейс взаємодії Interaction дозволяє режимам застосунку запросити дані з клавіатури, а інтерфейс взаємодії Drawable дає змогу відобразити зміни на екран.

\subsubsection{Графічний режим (Gui)}
Об'єкт взаємодії Gui створює нове вікно за допомогою Rust-SDL2\cite{Rust-SDL2} та обролює його події перетворюючи ввід з клавіатури в уніфіцирований тип вводу Input який використовуєтья по самому застосунку. Gui загружає всі файли спрайтів у бінарне дерево, за допомогою которого можна швидко знайти потрібну картинку об'єтку та перетворити її у текстуру.

\subsubsection{Псевдографічний режим (Tui)}
Об'єкт взаємодії Tui не свторює вікна, він отримує ввід з клавіатури та рисує графічні елементи у консолі за допомогою емоджи. Через те, що емоджи мають відмінну ширину від клітини консолі, реалізація відстеження пошкоджень не була імплементована, вона тільки додасть складності і зробить цей режим менш продуктивним. Щоб зробити відстеження пошкодженнь був створений консольний режим Cli.

\subsubsection{Консольний режим (Cli)}
Об'єкт взаємодії Cli має дуже зхожу кодову базу до Tui, він навіть використовує функцію для отримання вводу з клавіатури від нього, але функція відображення графіки відрізняється. У всіх режимах ця функція отримує об'єкт який імплементує інтерфейс для рисовки, він має в собі функцію для отримання змінених клітин. При відображенні інтерфейсу Cli не очищає екран, натомість він малює символ з нових клітин поверх старих, які повертає ця фунція. Ефективніть цього режиму дозволить дуже швидко малювати неймовірно великі рівні.

\subsection{Режими застосунку}
Режими застосунку дозволяють мати кілька програм в одній. Вони імплементують інтерфейс для графічного відображення Drawable. Цей інтерфейс дозволяє об'єктам взаємодії отримати необхідну їм інформацію від режиму застосунку для того, щоб його відобразити.

\subsubsection{Режим гри}
Коли запускається режим гри, створюється новий об'єкт гри який створює об'єкти рівней, і для нього запускаться функція run. Після об'єкт гри починає запускати рівні по черзі. Він викликає функції об'єкту взаємодії для обробки подій клавіатури та рисування рівня з статусом. Рівні повертають стан на якому гра була закінчена, якщо була повернена поразка, гра закінчується з повідомленням поразки, в іншому випадку гра продовжується поки не буде пройдений останній рівень і виведе повідомлення перемоги.

\subsubsection{Режим редактору рівнів}
Цей режим отримує назву файла, та відкриває його. Зміст файлу записується в внутрішні данні редактору, після чого можна можна побачити рівень на екрані, та редагувати його. Цей режим дуже схожий на гру, тільки він не так тісно взаємодіє з об'єктами. Після виходу з цього режиму рівень зберігається, а програма завершує своє виконання.

\subsection{Ігрові об'єкти}
У кожного об'єкту є власний файл де лежить його імплементація. Вони мають свою власну теку, і їх імпортує модуль який має рівну область видимості для всіх елементів застосунку. Ігрові об'єкти не належать лише до області режиму гри, бо вони активно використовуються іншими компонетами застосунку через інтерфейси.

\subsubsection{Гравець (Player)}
Цей об'єкт має параметр гравця. Йому передається ввід з клавіатури, після чого він рухається і ламає інші об'єкти. Також об'єкт гравця перевіряє камінь зверху щоб визначити чи може він впасти і закінчити гру програшом.

Згідно з умовами гравець має свій особистий клас який відповідає за поведінку об'єкту, його властивості та відображення. Також цей об'єкт за допомогою своїх інтерфейсів може взаємодіяти з ішними об'єктами використовуючи механізми ігрового рівня.

\subsubsection{Кристал (Gem)}
Кристал має параметр знищення. При ініціалізації він додає один бал до максимального значення лічильнику, а при знищенні збільшує лічильник. Якщо при знищенні лічильник досягне максимального значення, то рівень гри закінчується перемогою.

Згідно з умовами кристал має свій особистий клас який відповідає за поведінку об'єкту, його властивості та відображення. Також цей об'єкт за допомогою своїх інтерфейсів може взаємодіяти з ішними об'єктами використовуючи механізми ігрового рівня.

\subsubsection{Каміння (Rock)}
Каміння має параметр руху. Йому передається рівень та його поточні кординати. Камінь дивиться на стан об'єкту знизу, і якщо там порожнеча, то він падає вниз. Якщо камінь не зміг впасти в низ, то він перевіряє диагоналі, якщо вони вільні, то падіння відбудеться по диагоналі.

Згідно з умовами каміння має свій особистий клас який відповідає за поведінку об'єкту, його властивості та відображення. Також цей об'єкт за допомогою своїх інтерфейсів може взаємодіяти з ішними об'єктами використовуючи механізми ігрового рівня.

\subsubsection{Пісок (Dirt)}
Пісок має параметр знищення. В нього немає поведінки і він слугує тільки для втримування каміння на місці.

Згідно з умовами пісок має свій особистий клас який відповідає за поведінку об'єкту, його властивості та відображення. Також цей об'єкт за допомогою своїх інтерфейсів може взаємодіяти з ішними об'єктами використовуючи механізми ігрового рівня.

\subsubsection{Стіна (Wall)}
Стіна не має ані власних властивостей, ані поведінки. Від піску цей об'єкт відрізняє тільки те, що його не можна зламати.

Згідно з умовами стіна має свій особистий клас який відповідає за поведінку об'єкту, його властивості та відображення. Також цей об'єкт за допомогою своїх інтерфейсів може взаємодіяти з ішними об'єктами використовуючи механізми ігрового рівня.

\subsubsection{Пороженча (Void)}
Порожнеча має властивість заповнювача і не має поведінки. Він свторений просто для заповнювання порожніх клітин рівня, і не впливає на рух або існування об'єктів.

Порожнечі не було в умовах, але цей об'єкт теж має свій особистий клас який відповідає за поведінку об'єкту, його властивості та відображення. За допомогою своїх інтерфейсів він може взаємодіяти з ішними об'єктами використовуючи механізми ігрового рівня.

\subsubsection{Невідомий об'єкт (Unknown)}
Невідомий об'єкт має взалстивість заповнювача і не має поведінки. Від пороженчі його відрізняє тільки імплементація інтерфейсу позначення Labels, тобто цей елемент малюється по іншому. Він був створений при написанні режиму редактору рівнів для того що б позначати помилкові об'єкти, або об'єкти для яких не існує текстури.


\section{Інструкція користувача}
\subsection{Аргументи консолі}
Застосунок має такі аргументи командної строки:
\begin{itemize}
\item для отримання списку всіх аргументів застосунку "\texttt{-{}-}h" або "\texttt{-{}-}help";
\item обрати режим інтеракції можна за допомогою опції"\texttt{-{}-}m" або "\texttt{-{}-}mode" і написати "gui", "tui" або "cli" через пробіл після неї;
\item обрати підпрограму можна за допомогою опції "\texttt{-{}-}r" або "\texttt{-{}-}run" і написав "game" або "editor" через пробіл після неї;
\item поставити паузу в грі при запуску можна за допомогою опції "\texttt{-{}-}p" або "\texttt{-{}-}pause";
\item обрати розмір елементів у пікселях в графічному режимі можна за допомогою опції "\texttt{-{}-}s" або "\texttt{-{}-}size" та число через пробіл;
\item обрати затримку між кадрами в мілісекундах для гри можна за допомогою опції "\texttt{-{}-}d" або "\texttt{-{}-}delay"  та число через пробіл. 
\end{itemize}

Всі інші аргументи сприймаються як назви файлів рівнів.

\subsection{Керування застосунком}
Керування застосунком здійснюється з клавіатури виключно. Таке рішення було прийнято через багато факторів пов'язаних з легкістю імлементації та використання застосунка.

\subsubsection{Керування грою}
\begin{itemize}
\item рух здійснюється за допомогою стрілочек клавіатури;
\item перезапустити рівень можна за допомогою клавіші R;
\item пауза або її зняття виконоуються натисканням пробіла;
\item зменшення та збільшення затримки між кадрами здійснюється комою і крапою відповідно;
\item вийти з гри можна за допомогою клавіши Q, або  натиснув Ctrl+C.
\end{itemize}

\subsubsection{Керування редактором рівнів}
\begin{itemize}
\item рух здійснюється за допомогою стрілочек клавіатури;
\item перезагрузити рівень з файлу можна за допомогою клавіші R;
\item опустити або підняти перо виконоується натисканням пробіла;
\item обирати об'єкт можна комою та крапкою, вони обераютья попередній і наступний об'єкт відповідно;
\item вийти та зберегти рівень можна за допомогою клавіши Q, або  натиснув сполуку Ctrl+C.
\end{itemize}

\subsection{Позначення об'єктів}
В консольному режимі взаємодії та у файлі рівня ігрові об'єкти позначаються однаковими симоволами. Ось позначення кожного ігрового об'єкту в дужках:
\begin{itemize}
\item гравець: "p";
\item кристал: "+";
\item каміння: "O";
\item пісок: "*";
\item стіна: "\#";
\item порожнеча: "\ ";
\item невідомий об'єкт: "?".
\end{itemize}

Якщо в рівні видно невідомий об'єкт, значить в файлі рівня є символи які гра не може інтепретувати. Вирішити це можна використав режим редактору, або, якщо рівень вже запущений в грі, власноруч відредагувати файл у текствому редакторі та натиснути клавішу R для перезагрузки рівня.


% ------------------------------------------- Курсова завершилась ---------------------------------------------

% ------------------------------------------- Висновки --------------------------------------------------------
\section*{Висновки}
\addcontentsline{toc}{section}{Висновки} %додаємо сторінку Вступу до змісту
Було створено застосунок який має три режими вводу/виводу, гру та редактор рівнів. За допомогою інтерфейсів та поліморфізму можна дуже легко додати ще один режим вводу/виводу або розширити програму як це було зроблено з редактором рівнів. Застосунок дуже швидко працює та має такі оптимізації як відстеження пошкоджених клітинок та буферизацію графічних елементів.

В ході виконання цієї роботи я отримав багато практики, знань і навичок програмування на Rust, і став комфортно працювати з великою кількістю файлів, системою контролю версій git і пакетним менеджером cargo.
% ------------------------------------------- Висновки закінчилися --------------------------------------------

% ------------------------------------------- Перелік джерел посилання ----------------------------------------
\raggedright % увімкнути вирівнювання вліво
\begin{thebibliography}{99} % починаємо перелік та вставляємо туди наші посилання
    \addcontentsline{toc}{section}{Перелік джерел} % додаємо перелік до змісту 
    \bibitem{dstu}  Grafiati: Оформити списки використаних джерел онлайн. Grafiati: Оформити списки використаних джерел онлайн. URL: https://www.grafiati.com/uk/ (дата звернення: 09.05.2024).
    \bibitem{Rust-SDL2} GitHub - Rust-SDL2/rust-sdl2: SDL2 bindings for Rust. GitHub. URL: https://github.com/Rust-SDL2/rust-sdl2 (дата звернення: 2.06.2024).
    \bibitem{rust} Rust Programming Language. Rust Programming Language. URL: https://www.rust-lang.org/ (дата звернення: 10.05.2024).
\end{thebibliography}

% ------------------------------------------- Перелік джерел посилання закінчився -----------------------------

% ------------------------------------------- Перелік джерел посилання закінчився -----------------------------

% ------------------------------------------- Додатки (якщо треба) --------------------------------------------
\titleformat{\section}[display]{\filcenter}{\MakeUppercase{\bfseries{Додаток \thesection}}}{0pt}{} % зміна форматування заголовків у додатках
\titlecontents{section}[0pt]{\normalfont}{Додаток {\thecontentslabel} }{}{\Dotfill \contentspage} % зміна форматування додатків у змісті
\appendix
\setlength{\parindent}{0.5in}
% додавайте додатки: додатки додаються так само секціями

\section{Код програми}
Актуальну версію коду можна занйти за посиланням \url{https://github.com/oxid8/nure/tree/main/2/coursework/src}


% ------------------------------------------- Додатки (якщо треба) закінчилися -------------------------------

\end{document}
