diff --git a/Thesis/RUDNICKI_ENGINERING_THESIS.pdf b/Thesis/RUDNICKI_ENGINERING_THESIS.pdf index 3e4e873..4a1a7f8 100644 Binary files a/Thesis/RUDNICKI_ENGINERING_THESIS.pdf and b/Thesis/RUDNICKI_ENGINERING_THESIS.pdf differ diff --git a/Thesis/Thesis.tex b/Thesis/Thesis.tex index 97a49ed..644f153 100644 --- a/Thesis/Thesis.tex +++ b/Thesis/Thesis.tex @@ -141,6 +141,32 @@ breaklines=true, breakatwhitespace=true } + +\lstdefinestyle{mystyle}{ + backgroundcolor=\color{gray!10}, + basicstyle=\ttfamily\footnotesize, + breakatwhitespace=false, + breaklines=true, + captionpos=b, + keepspaces=true, + numbers=left, + numbersep=5pt, + showspaces=false, + showstringspaces=false, + showtabs=false, + tabsize=2, + language=Python, + morekeywords={os, re}, +} + +% for blank page after title +\usepackage{afterpage} + +\newcommand\blankpage{% + \null + \thispagestyle{empty}% + \addtocounter{page}{-1}% + \newpage} \newfontfamily{\adagio}{Adagio_Slab} \newfontfamily{\adagioLight}{Adagio Slab Light} @@ -199,11 +225,12 @@ {\fontsize{12}{12}\helveticaLight WARSAW 2023} \end{center} - - +\afterpage{\null\newpage} \end{titlepage} + + \subsubsection{Streszczenie pracy} {\fontsize{12}{12} \tytul \\ @@ -251,11 +278,12 @@ Good coding practices\} \section{Background and Motivation} Among us, computer science students, video games were—and still are—one of the driving forces pushing us into the field of IT. Video games allow people with technical background to express their artistic side and create visually stunning projects. In particular "Match Three" games, characterized by their intuitive mechanics and satisfying gameplay, have attracted millions of players around the globe. They offer statisfying experience of aligning three or more similar game pieces, often resulting in gratyfying chain reactions. This lead to success of titles like "Candy Crush Saga" and "Bejeweled", staple titles for both mobile and desktop market. -\begin{figure}[h] - +\begin{centering} +\begin{figure}[htp] \includegraphics[scale=0.5]{allgates} -\caption{Minecraft redstone offers introduciton to logical gates \cite{raspberrypi2023}} +\caption{Minecraft redstone offers introduciton to logical gates \cite{redstoneGates}} \end{figure} +\end{centering} Match three games are from technological point of view relatively easy to make, despite that there is no dedicated open-source game engine designed just for them. This engineering thesis aims to fill this void, to give back to the world of game developers and open-source projects. @@ -2128,36 +2156,289 @@ void Shader::Compile(const char* vertexSource, const char* fragmentSource, const \subsection{Dependency Management} There are several libraries: OpenGL, GLFW, stb\_image and freetype being integrated into engine, they are simply included at the top of any files that need them. -\chapter{Case Study: Development of a Prototype Match Three Game} +\chapter{Practical Use of Engine} +In the previous chapters, we explained on the architecture, design, and construction of our match-three game engine This chapter focuses on practical application of this engine by illustrating the creation of a functional match-three game from scratch. + +\section{Initial Setup and Configuration} +Before we start creating the game, We need to set up the development environment to utilize our game engine's capabilities fully. Using a modern IDE (Integrated Development Environment) like Visual Studio or Code::Blocks can ease the process. + +\paragraph{Importing the engine} Initiate a new C++ project and import our game engine's header and source files. Ensure that the necessary libraries related to OpenGL are linked. + +\paragraph{Configuration of OpenGL} Validate that the OpenGL version compatible with our engine is installed. This often involves setting up GLEW (OpenGL Extension Wrangler Library) or similar middleware. + +\subsection{Choosing assets} +Choosing assets is the most important part of our match three engine design \\ +We are going to use site \href{https://opengameart.org/}{https://opengameart.org/} which offers free game assets with permissive license, wcansFilterede are going to search for assets with the most permisible CC0 license which is an equivalent to public license + +\begin{figure}[H] +\centering +\includegraphics[scale=1.00]{images/openGameArt.png} +\caption{Searching for 2D art on OpenGameArt} +\label{} +\end{figure} + +\begin{figure}[H] +\centering +\includegraphics[scale=1.00]{images/OGASearch.png} +\caption{Searching for CC0 licensed assets} +\label{} +\end{figure} + +\paragraph{Filtering non tiles assets} +Our first step is to filter all assets that refer to graphics that cannot be used as tiles, for example UI elements, icons or buttons + +\subsubsection{Filtering tile assets} +We end up with 4 assets to choose from, based on 2 parameters we filtered 3 of them + +\paragraph{Using mechanics not available in engine} +First we filter asset pack that uses dynamic falling mechanic which is not present in our engine + +\begin{figure}[htp] +\centering +\includegraphics[scale=0.4]{images/cans.png} +\caption{Cans have different sprite depending on if they are falling or not, we do not have such mechanic in our engine \cite{cansFiltered}} +\label{} +\end{figure} + +\paragraph{Too much details} +Two more tile assets use too much details inside the tiles, this would require our game to react to those details to make sure that the gameplay experience is compatible with the tiles look. + +\begin{figure}[htp] +\centering + +\begin{minipage}{0.45\textwidth} +\centering +\includegraphics[scale=0.50]{images/tooMuchDetailsOne.png} +\caption{First assets with too much details inside the detail \cite{tooMuchOne}} +\label{fig:tooMuchDetailsOne} +\end{minipage}\hfill +\begin{minipage}{0.45\textwidth} +\centering +\includegraphics[scale=1.00]{images/tooMuchDetailsTwo.png} +\caption{Second assets with too much details inside the detail \cite{tooMuchTwo}} +\label{fig:tooMuchDetailsTwo} +\end{minipage} + +\end{figure} + +\paragraph{Chosen assets} +Finally we settled on these tiles, they look simple, work well with our shaders and engine gameplay and offer high quality non-pixelated files + +\begin{figure}[htp] +\centering +\includegraphics[scale=1.00]{images/gemMatchThree.png} +\caption{Chosen assets \cite{assetsMatchThree}} +\label{} +\end{figure} + +\subsection{Loading assets} +In order to use our assets in the game engine we need to define their names in the engine code and put the files into correct folder + +\paragraph{Setting files} +All non-code files used in our engine are stored in resources older \\ +Textures in particular are stored in "textures" folder \\ +That is where we unpack our tiles, files in the unzipped folder are named with a pattern: "Gem Type[number] [color].png" \\ +In order to simplify importing assets name we created a short python script that renames all tiles to "g[number][color].png" + +\begin{lstlisting}[style=mystyle][caption=Python code for renaming files] +import os +import re + +def rename_files_in_directory(directory_path): + # List all files in the directory + for filename in os.listdir(directory_path): + # Match filenames using regex + match = re.match(r"Gem Type(\d+) (\w+)\.png", filename) + if match: + number = match.group(1) + color = match.group(2).lower() # Convert to lowercase + new_filename = f"g{number}{color}.png" + # Rename files + os.rename( + os.path.join(directory_path, filename), + os.path.join(directory_path, new_filename) + ) + +# Call the function with the path to your directory +rename_files_in_directory("./") +\end{lstlisting} + +\paragraph{Setting tiles names in constants file} +After choosing tiles we are going to use we modify constants.hpp file, namespace textures and add our tiles tot textures array + +\begin{lstlisting}[style=C++Style] +namespace textures { + static constexpr TextureInfo textures[] = { + {"resources/textures/background.jpg", "background"}, + {"resources/textures/g1black.png", "block_black"}, + {"resources/textures/g2blue.png", "block_blue"}, + {"resources/textures/g3green.png", "block_green"}, + {"resources/textures/g4purple.png", "block_purple"} + }; +} +\end{lstlisting} + \section{Game Concept and Design} -In order to gauge the usability of our game engine, we decided to create a sample match three game using royalty free assets. First part of this process was game design -\subsection{Game Theme and Narrative} +\subsection{Game Concept} +A game concept encapsulates the core idea or essence of a game. It's the core vision that drives the entire game development process, giving direction to the gameplay and user experience. In match-three games, the primary concept is to align three or more similar game elements in a row or column to achieve points. -We decided to create a classic gem filled match three game, comparable to old bejeweled games. +\paragraph{Our concept} +In order to benchmark our game engine we are going to focus on simplicity and rudimentary features of match-three games. We are going to implement a game that while offers only elementary features can still be called a match-three game and can be won or lost + +\subsection{Game Design} +Game design describes how a game should be structured and played. It's the process of deciding game rules, creating levels, setting challenges, and determining how players interact with the game. While the game concept is the overarching idea, game design provides the detailed blueprint. In match-three games factors such as how new elements are introduced, the complexity of levels, the scoring system and win/fail condistions are all vital components of the design. + +\subsubsection{Our design} + +\paragraph{Scoring system} +Let's devise a scoring system for a match-three game with increasing difficulty levels. We will also differentiate the scores based on matching 3, 4, or 5 tiles. \\ + +First, let's determine the scores for each matching set: +\begin{enumerate} +\item Match 3 tiles = 10 points +\item Match 4 tiles = 20 points +\item Match 5 tiles = 40 points +\end{enumerate} + +When devising the point system for matching sets in the game, there are several considerations we kept in mind: + +\newpage +\paragraph{Progressive Increase} +We wanted the points to represent a clear progression, making matches of larger sets more valuable, incentivizing players to aim for them. \\ +3-tile matches are the baseline, so they were assigned a modest 10 points. \\ +4-tile matches are rarer and more difficult to create than 3-tile matches, so they're assigned 20 points, doubling the value from the 3-tile matches. \\ +5-tile matches are even rarer, so they were given a point value that's a bit more than the sum of 3-tile and 4-tile matches, settling at 40 points. \\ + +\paragraph{Simple numbers} +Using round numbers like 10, 20, and 35 makes it easy for players to quickly understand and calculate their scores. Complexity can deter casual gamers, and match-three games are typically aimed at a wide audience, including those who may prefer simpler mechanics. + + +\paragraph{Winning} +Given these scores, let's decide the target scores for each difficulty level. We'll set these target scores based on an estimated number of matches a player might make in a given game, we will create Easy, Normal and Hard levels + +\begin{itemize} + + \item Easy Level: + \begin{itemize} + + \item Target: 400 points + \item This might involve roughly 40 matches 3 tiles, or a combination of fewer 4 and 5 tile matches. This offers the player plenty of room for errors and learning the game mechanics. + + \end{itemize} + \item Normal Level: + \begin{itemize} + + \item Target: 600 points + \item For this target, the player might need to make 60 matches of 3 tiles, which will not be possible since we set up the limit of matches to 40 or a combination of fewer 4 and 5 tile matches, which will force the player to use bigger matches. This requires the player to make more strategic matches and utilize power-ups or special moves (if any). + + \end{itemize} + \item Hard Level: + \begin{itemize} + \item Target: 800 points + \item Achieving this score might involve 80 matches of 3 tiles, or a combination of fewer 4 and 5 tile matches. With our limit of matches set up to 40 will force the player to keep the average matching to at least 20 points per match. This level is challenging and will likely require the player to plan moves carefully and maximize opportunities to match 4 or 5 tiles for higher scores. + \end{itemize} + +\end{itemize} + +\paragraph{Losing} +The game is lost whenever player reaches 40 turns, this forces the player to act under limited moveset and ensures that the game offers a challenge \\ +Number 40 was chosen based on the similar choice in professional match-three games, it is the same number used for matching 5 tiles, it offers gameplay that is not too short neither too long and it is a "nice" number, even, round and with many divisors + +\newpage +\paragraph{Setting up values in constants file} +In order to implement this design in our game engine we need to again modify constants.hpp file in following way: + +\begin{lstlisting}[style=C++Style] +struct DifficultySettings { + const std::string name; + const int points; + const int limit; + const std::vector matchScores; + + DifficultySettings(const std::string& n, int p, int l, const std::vector& scores) + : name(n), points(p), limit(l), matchScores(scores) {} +}; + +namespace difficulty { + std::vector settings = { + DifficultySettings("easy", 400, 40, {10, 20, 40}), + DifficultySettings("normal", 600, 40, {10, 20, 40}), + DifficultySettings("hard", 80, 40, {10, 20, 40}) + }; +} + +\end{lstlisting} \subsection{Core Mechanics and Gameplay} Game utilizes full functionality of our engine, player needs to match three or more gems, chaining matches or achieving higher combos grants the player higher score +\paragraph{Generating levels} +We used python script to first generate levels user can choose from in order to simplify our work so we do not need to create the levels on our own \\ +Later in a course of our game the game engine handles generating new random blocks when old ones are replaced + \subsection{User Interface and User Experience} +The Heads-Up Display is minimalistic, showcasing only essential elements, score and moves left. -\begin{itemize} - \item Game HUD: The Heads-Up Display is minimalistic, showcasing only essential elements like score and moves left. +\paragraph{Choosing level and difficulty} +User can choose both level and difficulty on the menu screen using WSAD keys - \item, Feedback Mechanics: Animations, particles and shaders provide feedback for successful matches and combos. +\begin{figure}[htp] +\centering -\end{itemize} +\begin{minipage}{0.32\textwidth} +\centering +\includegraphics[scale=0.40]{images/easy.png} +\caption{UI when choosing easy level} +\label{fig:easy} +\end{minipage} +\hfill +\begin{minipage}{0.32\textwidth} +\centering +\includegraphics[scale=0.40]{images/normal.png} +\caption{UI when choosing normal level} % Adjusted the caption +\label{fig:normal} +\end{minipage} +\hfill +\begin{minipage}{0.32\textwidth} +\centering +\includegraphics[scale=0.40]{images/hard.png} +\caption{UI when choosing hard level} % Adjusted the caption +\label{fig:hard} +\end{minipage} -\section{Application of the Engine in Real-world Development} -After designing the game, we started creating it using our game engine. +\end{figure} -\subsection{Seamless Integration with Game Design} -Since the engine was created exactly with this type of game in mind, brining design decisions to life was very easy +\begin{figure}[H] +\centering +\includegraphics[scale=1.00]{images/scoreMoves.png} +\caption{Score and moves left text} +\label{} +\end{figure} -\subsection{Challenges in Implementation} +\begin{figure}[H] +\centering +\includegraphics[scale=1.00]{images/redMoves.png} +\caption{Score and moves left text, when there are less than 10 moves left} +\label{} +\end{figure} -Biggest challenge was our toolset, we had to either modify the existing engine solutions or create new one from scratch. +\paragraph{Losing and winning} +Whenever player loses (reaches max number of turns) or wins (reaches target points), game stops, clears the level and displays a message +\begin{figure}[htp] +\centering +\includegraphics[scale=0.50]{images/losing.png} +\caption{Game message when lost} +\label{} +\end{figure} + +\begin{figure}[htp] +\centering +\includegraphics[scale=0.50]{images/win.png} +\caption{Game message when won} +\label{} +\end{figure} \subsection{Advantages of a Custom-built Engine} @@ -2245,8 +2526,6 @@ Using multiple different libraries and integrating them with our game engine was \subsection{Time management} Lastly, probably the biggest challenge was managing time for this thesis. Finishing it required a lot of determination, setting barriers and working every day to ensure that the thesis is finished on time. Thankfully past experiences helped in guiding through this task that could be compared to colossus. -\chapter{Appendices} - \bibliography{references} diff --git a/Thesis/images/OGASearch.png b/Thesis/images/OGASearch.png new file mode 100644 index 0000000..dc35f92 Binary files /dev/null and b/Thesis/images/OGASearch.png differ diff --git a/Thesis/images/cans.png b/Thesis/images/cans.png new file mode 100644 index 0000000..edf72d2 Binary files /dev/null and b/Thesis/images/cans.png differ diff --git a/Thesis/images/easy.png b/Thesis/images/easy.png new file mode 100644 index 0000000..6e90951 Binary files /dev/null and b/Thesis/images/easy.png differ diff --git a/Thesis/images/hard.png b/Thesis/images/hard.png new file mode 100644 index 0000000..0cca6d2 Binary files /dev/null and b/Thesis/images/hard.png differ diff --git a/Thesis/images/losing.png b/Thesis/images/losing.png new file mode 100644 index 0000000..d2e88e8 Binary files /dev/null and b/Thesis/images/losing.png differ diff --git a/Thesis/images/menu.png b/Thesis/images/menu.png new file mode 100644 index 0000000..18444c2 Binary files /dev/null and b/Thesis/images/menu.png differ diff --git a/Thesis/images/normal.png b/Thesis/images/normal.png new file mode 100644 index 0000000..f3aae27 Binary files /dev/null and b/Thesis/images/normal.png differ diff --git a/Thesis/images/openGameArt.png b/Thesis/images/openGameArt.png new file mode 100644 index 0000000..420f947 Binary files /dev/null and b/Thesis/images/openGameArt.png differ diff --git a/Thesis/images/redMoves.png b/Thesis/images/redMoves.png new file mode 100644 index 0000000..6605ebf Binary files /dev/null and b/Thesis/images/redMoves.png differ diff --git a/Thesis/images/scoreMoves.png b/Thesis/images/scoreMoves.png new file mode 100644 index 0000000..3526c92 Binary files /dev/null and b/Thesis/images/scoreMoves.png differ diff --git a/Thesis/images/tooMuchDetailsOne.png b/Thesis/images/tooMuchDetailsOne.png new file mode 100644 index 0000000..40a0a8e Binary files /dev/null and b/Thesis/images/tooMuchDetailsOne.png differ diff --git a/Thesis/images/tooMuchDetailsTwo.png b/Thesis/images/tooMuchDetailsTwo.png new file mode 100644 index 0000000..7e95c59 Binary files /dev/null and b/Thesis/images/tooMuchDetailsTwo.png differ diff --git a/Thesis/images/win.png b/Thesis/images/win.png new file mode 100644 index 0000000..e12d415 Binary files /dev/null and b/Thesis/images/win.png differ diff --git a/Thesis/references.bib b/Thesis/references.bib index 9cd75d2..d1cd8d6 100644 --- a/Thesis/references.bib +++ b/Thesis/references.bib @@ -10,48 +10,48 @@ title = {Windows Mac Linux Logo}, year = {2009}, % Adjust the year if you know the specific publication year. url = {https://www.nicepng.com/downpng/u2w7w7y3e6a9r5i1_windows-mac-linux-logo/}, - note = {Accessed: 2023-08-20} - organization = {NicePNG} + note = {Accessed: 2023-08-20}, + author = {NicePNG} } @online{glfwLogo, title = {GLFW Logo}, year = {2013}, % Adjust the year if you know the specific publication year. url = {https://www.glfw.org/}, - note = {Accessed: 2023-08-20} - organization = {The GLFW Development Team} + note = {Accessed: 2023-08-20}, + author = {The GLFW Development Team} } @online{bejeweledGameplay, title = {Bejeweled gameplay}, year = {2001}, % Adjust the year if you know the specific publication year. url = {https://www.youtube.com/watch?v=ZEXtEUVexzA}, - note = {Accessed: 2023-08-20} - organization = {PopCap Games and Electronic Arts} + note = {Accessed: 2023-08-20}, + author = {PopCap Games and Electronic Arts} } @online{marketShareChart, title = {Desktop Operating System Market Share Worldwide Chart}, year = {2023}, % Adjust the year if you know the specific publication year. url = {https://gs.statcounter.com/os-market-share/desktop/worldwide}, - note = {Accessed: 2023-08-20} - organization = {Global Stats} + note = {Accessed: 2023-08-20}, + author = {Global Stats} } @online{unityLogo, title = {Unity Game Engine Logo}, year = {2005}, % Adjust the year if you know the specific publication year. url = {brand.unity.com}, - note = {Accessed: 2023-08-20} - organization = {Unity Technologies} + note = {Accessed: 2023-08-20}, + author = {Unity Technologies} } @online{unrealLogo, title = {Unreal Game Engine Logo}, year = {2014}, % Adjust the year if you know the specific publication year. url = {www.unrealengine.com}, - note = {Accessed: 2023-08-20} - organization = {Epic Games} + note = {Accessed: 2023-08-20}, + author = {Epic Games} } @online{godotLogo, @@ -116,4 +116,29 @@ url = {https://opengameart.org/content/gem-match-3-set}, note = {Accessed: 2023-08-26} author = {Sylly} +} + +@online{cansFiltered, + title = {Soda Pop Can-Themed Game Pieces}, + year = {2012}, + url = {https://opengameart.org/content/soda-pop-can-themed-game-pieces}, + note = {Accessed: 2023-09-08}, + author = {Donald Pelikan} +} + +@online{tooMuchOne, + title = {Vector Match Three Blocks}, + year = {2017}, + url = {https://opengameart.org/content/vector-match-three-blocks}, + note = {Accessed: 2023-09-08}, + author = {ChiliGames} +} + +@online{tooMuchTwo, + title = {Color Match Puzzle Rainbow Panels +}, + year = {2021}, + url = {https://opengameart.org/content/color-match-puzzle-rainbow-panels}, + note = {Accessed: 2023-09-08}, + author = {Haley Halcyon} } \ No newline at end of file