\documentclass{projdoc} \title{Software Design} \begin{document} \tablestables \newpage \section{Introduction} This document outlines the design and development process of the cr\^epe game engine, detailing the key decisions made during its creation. The primary goal of this engine is to offer a streamlined, Unity-like experience tailored for developing 2D games similar to Jetpack Joyride. The cr\^epe engine is designed to ease the transition for developers familiar with Unity, ensuring minimal friction when switching platforms. Our aim is to preserve many of Unity’s core features while introducing a lightweight and open-source alternative, licensed under the MIT License. The engine is primarily aimed at indie developers who have prior experience with Unity and are looking for a flexible, cost-effective solution with familiar workflows. \section{Overview} \subsection{Core} \subsection{Patterns} \section{Design} \subsection{Rendering} \subsection{Physics} \subsection{Scripting} The scripting interface was designed around a `target' \gls{api} (described by \cref{req:script:interface,req:script:user-class,req:script:direct-instance,req:script:direct-run}). An example of this \gls{api} is shown below:\noparbreak \begin{blockcode} class MyScript : public BehaviorScript { void update() { // update code here } // init() also exists, but is empty by default }; { // in scene initialization GameObject & obj = ...; obj.add_component(); } \end{blockcode} The above call to \codeinline{GameObject::add_component} cannot work correctly without significantly increasing the complexity of the component manager, so the following restrictions were taken into account when creating the script system architecture:\noparbreak \begin{itemize} \item The first template parameter passed to \codeinline{GameObject::add_component} \emph{must} be a base `script \emph{component}' class, so each derived user script class is instantiated in the same generic script list. \item C++ does not allow passing types (i.e.~\codeinline{MyScript} in this case) as function parameters, so a function call like \codeinline{add_component(MyScript)} cannot be realized. \end{itemize} \subsubsection{Architecture} The restrictions detailed at the start of this section are mitigated as follows:\noparbreak \begin{itemize} \item User scripts are split into two classes--- \begin{enumerate} \item a script \emph{interface} class (\codeinline{Script}) \item a script \emph{component} class (\codeinline{BehaviorScript}) \end{enumerate} \item \codeinline{GameObject::add_component} receives the script \emph{component} as template parameter \item \codeinline{GameObject::add_component} now always returns a reference to the component instance \item The script component class has a setter function that takes a template parameter for classes derived from the base script \emph{interface} class \end{itemize} \Cref{fig:class-scripts} shows the resulting structure as a class diagram. It contains the following classes:\noparbreak \begin{description} \item[Script] This is the script \emph{interface}, and is used by the game programmer to create derived script classes. All methods in this class are declared virtual and have an empty implementation. This class' methods are protected by default, and a friend relation to \codeinline{ScriptSystem} is used to ensure only \codeinline{ScriptSystem} is able to call these methods. Only classes derived from \codeinline{Script} can be used with \codeinline{BehaviorScript::set_script}'s template parameter \codeinline{T}. This function returns a reference to the \codeinline{BehaviorScript} instance it was called on so it can be chained after the call to \codeinline{GameObject::add_component}. \item[BehaviorScript] This is the script \emph{component}, and is given as the template parameter to \codeinline{GameObject::add_component}. This class also uses a friend relation to \codeinline{ScriptSystem} to restrict access to its private reference member \codeinline{script}. \item[ScriptSystem] This is the system class that runs the methods implemented in the derivative instances of \codeinline{Script}. \end{description} \begin{figure} \centering \includepumldiag{img/class-scripts.puml} \caption{User script class diagram} \label{fig:class-scripts} \end{figure} \subsection{Audio} \subsubsection{Library} \subsubsection{Fa\c{c}ade} \Cref{fig:class-audio-facade} shows a class diagram of the audio fa\c{c}ade. It contains the following classes: \begin{description} \item[SoundContext] This is a wrapper around the \codeinline{SoLoud::soloud} `engine' class, and is therefore implemented as a singleton. This ensures the audio engine is initialized before \codeinline{Sound} is able to use it. This class is friends with \codeinline{Sound}, so only \codeinline{Sound} is able to get the \codeinline{SoundContext} instance. \item[Sound] This is a wrapper around the \codeinline{SoLoud::Wav} class, and uses cr\^epe's \codeinline{Asset} class to load an audio sample instead. \end{description} \begin{figure} \centering \includepumldiag{img/facade-audio.puml} \caption{Audio fa\c{c}ade class diagram} \label{fig:class-audio-facade} \end{figure} \subsection{Input} \subsection{Physics} \section{Tools} \section{Conclusion} \end{document}