From 69f8fcfb593641174b3a83049ad4acc1abf1a102 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Fri, 18 Oct 2024 14:37:21 +0200 Subject: add scripting design documentation --- design.tex | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ img/class-scripts.puml | 48 +++++++++++++++++++++++++++++ reqs.toml | 33 ++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 img/class-scripts.puml diff --git a/design.tex b/design.tex index 7b232fe..a89303a 100644 --- a/design.tex +++ b/design.tex @@ -36,6 +36,90 @@ workflows. \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} diff --git a/img/class-scripts.puml b/img/class-scripts.puml new file mode 100644 index 0000000..8fc36c9 --- /dev/null +++ b/img/class-scripts.puml @@ -0,0 +1,48 @@ +@startuml +!include theme.ipuml +skinparam Linetype ortho +skinparam Nodesep 75 +skinparam Ranksep 30 + +class ComponentManager <> + +package api { + class Component <> + + class Script { + # init() <> + # update() <> + -- + - Script() + } + + class BehaviorScript { + # BehaviorScript() + + ~BehaviorScript() + -- + + set_script() : this & + -- + # script : Script * + } + + BehaviorScript -u-|> Component + Script .u.> BehaviorScript +} + +class System <> +class ScriptSystem <> { + + get_instance() : ScriptSystem & <> + + update() + -- + - ScriptSystem() + - ~ScriptSystem() +} + +System <|-- ScriptSystem +ScriptSystem .[norank]> ComponentManager + +ScriptSystem .[norank]> api.Script : < friend +ScriptSystem .[norank]> api.BehaviorScript : < friend +ComponentManager .[norank]> api.BehaviorScript : < friend + +@enduml diff --git a/reqs.toml b/reqs.toml index ed0b451..a83208e 100644 --- a/reqs.toml +++ b/reqs.toml @@ -84,3 +84,36 @@ Windows. # TODO: library documentation as quality factor? # TODO: modularity over less libraries? (i.e. why don't we just SDL2 everything?) +[script:interface] +type = 'system' +priority = 'must' +description = ''' +There is a base \codeinline{Script} class that has empty default +implementations for functions that may be implemented by the game programmer. +''' + +[script:user-class] +type = 'system' +priority = 'must' +description = ''' +The game programmer implements scripts by creating classes derived from the +\codeinline{Script} class. +''' + +[script:direct-instance] +type = 'system' +priority = 'must' +description = ''' +Unless explicitly changed by the game programmer, derived script classes cannot +be instantiated directly, and must be instantiated by the component manager. +''' + +[script:direct-run] +type = 'system' +priority = 'must' +description = ''' +Unless explicitly changed by the game programmer, methods on instances of +\codeinline{Script} (and derivative) classes cannot be called directly, and +must be called by the script system. +''' + -- cgit v1.2.3 From eb9e756b5f5435c0892e411576d5206b3f6f8f74 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Fri, 18 Oct 2024 14:48:22 +0200 Subject: move audio research to audio design --- design.tex | 42 ++++++++++++++++++++++++++++++++++++++++-- research.tex | 45 --------------------------------------------- 2 files changed, 40 insertions(+), 47 deletions(-) diff --git a/design.tex b/design.tex index a89303a..08ea7cc 100644 --- a/design.tex +++ b/design.tex @@ -122,9 +122,47 @@ contains the following classes:\noparbreak \subsection{Audio} -\subsubsection{Library} +Since writing a custom real-time audio mixing engine is outside the scope of this +project\mref and C++ does not provide a built-in cross-platform audio \gls{api}, the +audio system inside the cr\^epe engine is implemented as a fa\c{c}ade around an +existing audio library. + +\subsubsection{Libraries} +\label{sec:audio:libs} + +This subsection compares various standalone audio libraries for suitability. After +searching for libraries (search terms: `dynamic/adaptive audio', `real-time audio', +`audio library', `game audio engine'), several libraries were found. These libraries +were checked against the audio engine requirements \autocite{crepe:requirements} and +then tested by writing the same benchmark-style \gls{poc} using the remaining +qualifying libraries:\noparbreak +\begin{enumerate} + \item Load a background track (Ogg Vorbis) + \item Load three short samples (WAV) + \item Start the background track + \item Play each sample sequentially while pausing and resuming the background track + \item Play all samples simultaniously + \item Stop all audio and exit +\end{enumerate} + +Of these libraries the following were determined to be unsuitable for use in this +project:\noparbreak +\begin{description} + \item[FMOD \autocite{lib:fmod}] Is proprietary (violates \cref{req:lib:license}). + \item[PortAudio \autocite{lib:portaudio}] Does not handle mixing. + \item[miniaudio \autocite{lib:miniaudio}] Tested by implementing a \gls{poc}, but + dropped due to very limited codec support (WAV, MP3 and FLAC only); Also does not + have an \gls{api} reference (only programming manual). + \item[YSE \autocite{lib:yse}] Attempted to write \gls{poc}, but CMake configuration + in repository is broken; This project seems to have been abandoned. +\end{description} -\subsubsection{Fa\c{c}ade} +The only library that remained after these tests is SoLoud \autocite{lib:soloud}. It +is Zlib/LibPng licensed and provides a high-level object-oriented C++ \gls{api}. +\Cref{sec:audio:architecture} describes the fa\c{c}ade written for this library. + +\subsubsection{Architecture} +\label{sec:audio:architecture} \Cref{fig:class-audio-facade} shows a class diagram of the audio fa\c{c}ade. It contains the following classes: diff --git a/research.tex b/research.tex index 1b8a5ab..f39e6f6 100644 --- a/research.tex +++ b/research.tex @@ -427,51 +427,6 @@ licensing flexibility. \subsection{Conclusion} -\section{Audio} - -The game engine is required to have an audio system -\autocite[\ref{req:audio}]{crepe:requirements}. Since writing a custom real-time -audio mixing engine is outside the scope of this project\mref, this section compares -various standalone audio libraries for suitability in the engine. - -\subsection{Libraries} -\label{sec:audio:libs} - -After searching for libraries (search terms: `dynamic/adaptive audio', `real-time -audio', `audio library', `game audio engine'), several libraries were found. These -libraries were checked against the audio engine requirements -\autocite{crepe:requirements} and then tested by writing the same benchmark-style -\gls{poc} using the remaining qualifying libraries:\noparbreak -\begin{enumerate} - \item Load a background track (Ogg Vorbis) - \item Load three short samples (WAV) - \item Start the background track - \item Play each sample sequentially while pausing and resuming the background track - \item Play all samples simultaniously - \item Stop all audio and exit -\end{enumerate} - -Of these libraries the following were determined to be unsuitable for use in this -project due to various reasons:\noparbreak -\begin{description} - \item[FMOD \autocite{lib:fmod}] Is proprietary (violates \cref{req:lib:license}) - \item[PortAudio \autocite{lib:portaudio}] Does not handle mixing - \item[miniaudio \autocite{lib:miniaudio}] With finished \gls{poc}, but dropped due - to very limited codec support (WAV, MP3 and FLAC only); Also does not have an - \gls{api} reference (only programming manual) - \item[YSE \autocite{lib:yse}] Attempted to write \gls{poc}, but CMake configuration - in repository is broken; This project seems to have been abandoned -\end{description} - -The only library that remained after these tests is SoLoud \autocite{lib:soloud}. It -is Zlib/LibPng licensed and provides a high-level object-oriented C++ \gls{api}. - -\subsection{Conclusion} -\label{sec:audio:conclusion} - -Due to a severe shortage of libraries that fit our requirements, SoLoud appears to be -the most suitable (and only) audio library for use in this project. - \section{Physics} \subsection{Introduction} -- cgit v1.2.3 From 1f9a3e27c13a90e2585f5145323db58c18cf8e43 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Tue, 22 Oct 2024 16:45:55 +0200 Subject: update time.txt --- time.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/time.txt b/time.txt index c814b34..bacc961 100644 --- a/time.txt +++ b/time.txt @@ -78,6 +78,7 @@ loek: 2024-10-18 1h40m docs :: design :: scripting interface loek: 2024-10-20 30m review :: PR review (#37) loek: 2024-10-21 1h30m implementation :: global config interface loek: 2024-10-21 10m review :: PR review (#7) +loek: 2024-10-22 15m review :: incorporate feedback and merge PR (#7 and #37) max: 2024-09-02 1h project kickoff max: 2024-09-02 45m first project meeting -- cgit v1.2.3 From fe0ad1db3a166da0ff706c33cbcd4d8a52514f29 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 23 Oct 2024 13:18:53 +0200 Subject: update time.txt --- time.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/time.txt b/time.txt index bacc961..205c617 100644 --- a/time.txt +++ b/time.txt @@ -79,6 +79,7 @@ loek: 2024-10-20 30m review :: PR review (#37) loek: 2024-10-21 1h30m implementation :: global config interface loek: 2024-10-21 10m review :: PR review (#7) loek: 2024-10-22 15m review :: incorporate feedback and merge PR (#7 and #37) +loek: 2024-10-23 30m implementation :: refactoring max: 2024-09-02 1h project kickoff max: 2024-09-02 45m first project meeting -- cgit v1.2.3