\documentclass[aspectratio=169]{beamer}

% pdfpc slides.pdf --notes=right
% comment out to disable notes
\setbeameroption{show notes on second screen=right}

\usetheme{metropolis}

\usepackage{outlines}
\usepackage{graphicx}
\usepackage{minted}
\setminted{fontsize=\footnotesize,samepage=true}
%\usepackage{xcolor}
%\definecolor{codecolor}{HTML}{FFC300}

\usepackage[super]{nth}
\usepackage{csquotes}

\title{VEGO-Engine}
\subtitle{A student project}
\author{Benedikt, Nicole}

\begin{document}

\maketitle
\note{Tone: light hearted "What did we learn"}

\begin{frame}{Outline}
\tableofcontents
\end{frame}

\section{Context}

\subsection{The team}
\begin{frame}{Who are we?}
\begin{itemize}
    \item Group of 5 people
    \item 1 Semester of C++ programming under our belt at the start
    \item Common interest: C++ programming + game development
\end{itemize}
\end{frame}
\subsection{The project}
\begin{frame}{The assigment}
\begin{itemize}
    \item \enquote{Development of a fantasy game console} (similar to Pico8)
    \item For simple Arcade like games (think Pong/Space Invaders)
    \item Goal was to teach how to manage and program within a larger project
\end{itemize}
\end{frame}
\begin{frame}{Our interpretation and goals}
\begin{itemize}
    \item Started out with a Minigame
    \item Realized we can split it into \enquote{Engine} and \enquote{Game Specific content}
    \item Goal: make easy to use engine without GUI
\end{itemize}
    \Rightarrow We could then build an engine from existing code while using our game as a proof of concept for the engine
    
    Smart right :D ?\dots
\end{frame}
\begin{frame}
    What awaited us was about the equivalent of trying to neatly sort single spaghetti strands after
    they had previously been vigorously jumbled up and mixed with some *juicy* pasta sauce.
    
    In other words, quite a messy endeavor\dots
\end{frame}
\begin{frame}{Roadmap}
\nth{3} semester - learning SDL and the principles of game development

\nth{4} and \nth{5} semester - making the engine

At this point we were certain this would be a walk in the park as it would essentially *just* be some refactoring, right?
\end{frame}
\note[itemize]{
    \item Somewhere around this time we realized there was more to compiling a C++ program than pressing the run button in Visual Studio.
    \item (subtle foreshadowing about how using VS set us back many many hours :,))
    \item There was quite the naive optimism at the end of this semester (i.e wheeee we made a whole game on our own we are unstoppable :D)
    \item (about 4th/5th semester): separating the project into the game and the parts of the program that could be reused for other games.
}

\begin{frame}{Overcoming naivety}
Realization: Doing it right the first time is better than fixing it later.

And no, don't \enquote{just start programming because the architecture will solve itself later}
\end{frame}

\section{Learnings}

\begin{frame}[allowframebreaks, fragile]{Spaghetti, an example}
\begin{itemize}
    \item Original Ticket: \enquote{Attack speed stat needs reimplementation}
    
\framebreak

Step one, make it so Stateffects are not hardcoded in Engine
    
\begin{minted}[linenos,autogobble,samepage=false,breaklines]{c++}
void chickengame::pickupables::movementSpeedEffect(Entity* player)
{
    player->getComponent<StatEffectsComponent>() .modifyStatDur(Stats::MOVEMENT_SPEED, BUFF_DURATION, BUFF_VALUE);
}
\end{minted}

\framebreak

Step two \dots uh oh how do i manage a stateffects life cycle?

\begin{minted}[linenos,autogobble,samepage=false,breaklines]{c++}
void StatEffectsComponent::update()
{
	for (int i = 0; i < MAX_STATS; i++)
	{
		if (this->buffs.at(i) == 0) continue;
		if (this->buffs.at(i) - 1 == 0)
		{
			this->resetStatValue((Stats)i);
		}
		this->buffs.at(i) -= 1;
	}
}

void StatEffectsComponent::modifyStatDur(Stats stat, int duration, int value)
{
	if(this->buffs.at((uint8_t)stat) == 0) this->modifyStatValue(stat, value);
	this->buffs.at((uint8_t)stat) += duration;
}
\end{minted}

\framebreak

Step three \dots oh no why are stat types hardcoded in the engine?

\begin{minted}[linenos,autogobble,samepage=false,breaklines]{c++}
void StatEffectsComponent::modifyStatValue(Stats stat, int modifier)
enum class Stats
{
    MOVEMENT_SPEED,
    ATTACK_SPEED
};
\end{minted}

\framebreak

    \item Step 3.2 uhhhhhh i should make it so developers can add their own stats
    \item Step 3.2.4 how does one elegantly access those set stats so the engine can also work with them
    \item Step ??? help why is this one commit touching 15 files and still not remotely done???
\end{itemize}
\framebreak

\begin{minted}[linenos,autogobble,samepage=false,breaklines]{c++}
void chickengame::pickupables::movementSpeedEffect(Entity* player)
{
    int basePlayerSpeed = player->getComponent<DataComponent>() .getEntry<int>("speed"). value_or(0);
    player->getComponent<DataComponent>().setEntry("speed", 4);
    player->getComponent<StatEffectsComponent>() .addEffect(BUFF_DURATION, [&]() {
        player->getComponent<DataComponent>() .setEntry("speed", basePlayerSpeed);
    });
}
\end{minted}
\end{frame}

\subsection{Project environment}

\begin{frame}{Baby's first \texttt{CMakeLists.txt}}
\begin{itemize}
    \item At UAS: Only \texttt{make} is taught, most subjects didn't have further requirements for project setup
    \item CMake is well documented, works out of the box with most IDEs, is directly supported by all used libraries
\end{itemize}
\end{frame}
\note[itemize]{
    \item side notes: static linking, compile time
    \item transition to VS (\enquote{before we used a CMake file though\dots})
}

\begin{frame}[allowframebreaks]{Visual Studio}
Advantages:
\begin{itemize}
    \item Works out of the box*
    \item Easy to start a project with
\end{itemize}
\framebreak
Disadvantages:
\begin{itemize}
    \item Undefined behaviour\footnote{Turns out we had \texttt{heap-use-after-free} errors, but with VS objects were still in memory most of the time} behaves different to \texttt{gcc}
    \item What is a \enquote{solution}?
    \item VS copied the \texttt{assets/} folder to a different location, which wasn't checked into git
\end{itemize}
\end{frame}
\note[itemize]{
    \item Undefined behaviour first noticed by "huh but it works for me :p"
    \item When trying to access assets things went weird
    \item adding a file doesn't add the file
}

\begin{frame}{How the \_ do I import a library?}
\begin{itemize}
    \item git modules
    \item CMake's \texttt{add\_subdirectory()} command
\end{itemize}
\end{frame}
\note[itemize]{
    \item first start: someone checked SDL into git. Was the windows version. Project worked on my machine because I had SDL installed locally. Issues due to different versions
    \item SDL is a library, static compile
    \item git-modules - do not bloat contributions
    \item \enquote{which worked without issues\dots  no, of course not, requires git command to update submodules when switching branches}
    \item could have used a dependency manager (like conan), didn't know that was a thing
}

\subsection{ECS}
% ECS slides, split into 3 sections
\begin{frame}[fragile]{We made an ECS}
Why an ECS - Entity Component System?
\begin{itemize}
    \item Encourages reusable code
    \item "Plug-and-play" to add functionality
    \item We found a video tutorial series for it
    \item Simplified implementation: Entities propagate updates to the components
\end{itemize}
\end{frame}
\note[itemize]{
    \item Reusable code mainly on engine side, but also applies to game dev components
    \item plug and play mostly an advantage for game dev - i.e. "I want physics, here are physics"
    \item \enquote{video series} - tease issue of abruptly ending
    \item Components usually only have data, and are querried by the system (hence ecS)
    \item System part used for rendering
}
\begin{frame}[allowframebreaks, fragile]{We made an ECS - Implementation}
\begin{minted}[linenos,autogobble,samepage=false]{c++}
class Entity {
private:
    std::vector<std::unique_ptr<Component>> components;
    ComponentArray componentArray = {};
    ComponentBitSet componentBitSet;
public:
    void update(uint_fast16_t diffTime) const;
    template <typename T> bool hasComponent() const {
        return componentBitSet[getComponentTypeID<T>()];
    }
    template <typename T> T& getComponent() const {
        auto ptr(componentArray[getComponentTypeID<T>()]);
        return *static_cast<T*>(ptr);
    }
    template <typename T, typename...TArgs> T& addComponent(TArgs&&...mArgs) {
        T* c(new T(std::forward<TArgs>(mArgs)...));
        c->entity = this;
        std::unique_ptr<Component> uPtr{ c };
        this->components.emplace_back(std::move(uPtr));

        componentArray[getComponentTypeID<T>()] = c;
        componentBitSet[getComponentTypeID<T>()] = true;

        c->init();
        return *c;
    };
};
\end{minted}
\end{frame}
\note[itemize]{
    \item appologize for formatting - for the sake of compactness
    \item TypeID: increments through all components - copied from video tutorial
    \item NOT beginner friendly
}
\begin{frame}[fragile]{We made an ECS - Usage}
Very easy to use:
\begin{minted}[linenos,autogobble]{c++}
auto& projectile(this->manager->addEntity());
projectile.addComponent<TransformComponent>(pos.x, pos.y, 32, 32, scale);
projectile.addComponent<SpriteComponent>(texture, 4); // 4 => zIndex
projectile.addComponent<ProjectileComponent>(range, speed, velocity, owner);
projectile.addComponent<ColliderComponent>(0.6f);
\end{minted}
\end{frame}
\note{mention: this ease of use is our goal}

\subsection{Memory Management}
\begin{frame}[allowframebreaks, fragile]{Memory Management}
\begin{minted}[linenos,autogobble]{c++}
class Manager
{
public:
    Entity& addEntity()
    {
        Entity* e = new Entity(*this);
        std::unique_ptr<Entity> uPtr{ e };
        this->entities.emplace_back(std::move(uPtr));
        return *e;
    }
private:
    std::vector<std::unique_ptr<Entity>> entities;
}
\end{minted}
\framebreak
Does that solve memory management? Not quite:
\begin{itemize}
    \item Missing separation of concern - manager also propagates update call
    \item Does not allow "saving" existing entities
\end{itemize}
Architectural issues like this are hard to solve this late in development

However it does solve memory management\footnote{For \texttt{Entity} classes only, there are some leaks due to bad usage of the \texttt{SDL\_mixer} library}
\end{frame}
\note[itemize]{
    \item \enquote{Perfect example of why our ECS is not ideal}
    \item scene management - would replace manager - however manager is too widely used - break API consistency
    \item classic example of good on surface level only for a beginner; transition to more such examples
}

% Beginner traps
\subsection{C++ beginner traps}
\begin{frame}[fragile]{C++ - Friend or Foe?}
\enquote{I just learned about \underline{\hspace{1cm}}, so I'm going to use it everywhere\dots}

Please do not take any of our claims as factually accurate or best practice
\end{frame}
\begin{frame}[fragile]{C++ - Friend or Foe? - Ternary operator}
If used in moderation:
\begin{minted}[linenos,autogobble,samepage=false,breaklines]{c}
void TextureManager::draw( /* ... */, bool flipped)
{
    SDL_FlipMode flip = flipped ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
    // ...
}
\end{minted}
\end{frame}
\begin{frame}[allowframebreaks, fragile]{C++ - Friend or Foe? - \texttt{std::ranges}}
\begin{minted}[linenos,autogobble,samepage=false,breaklines]{c++}
    // for each tile set
    auto tileConstructorRange = std::views::iota(0)
    | std::views::take(this->mapData.tileSets->size())
    // return the tile set metadata
    | std::views::transform([&](uint16_t i) { /* ... */ })
    | std::views::transform([=, this](const TileSetData& data) {
        // for each tile on the tile set
        return std::views::iota(0)
        | std::views::take(this->mapData.mapSize->x * this->mapData.mapSize->y)
        // only take tiles that are on the ID range of the tile set
        | std::views::filter([=](uint16_t idx) { /* ... */ })
        // extract tile data
        | std::views::transform([=, this](uint16_t idx) {
            /* ... */
            return std::function<Entity*()>(
                [tilePosX, tilePosY, capture0 = *this->mapData.mapTileSize, u, v, zIndex, capture1 = data.texturePath, collision] {
                    return Map::addTile(tilePosX, tilePosY, capture0, u, v, zIndex, capture1, collision);
                }
            );
        });
    })
    // 2D view to 1D vector
    | std::views::join
    | std::ranges::to<std::vector>();
\end{minted}
\end{frame}
\note[itemize]{
    \item context: 
    \item readable (sort of), efficient (not really due to to<vector>)
    \item issues with c++23 (requires at least gcc14)
}
\begin{frame}[fragile]{C++ - Friend or Foe? - \texttt{std::bitset}}
Might be efficient, but\dots
\begin{minted}[linenos,autogobble,samepage=false,breaklines]{c++}
IntersectionBitSet intersections =
    (CollisionHandler::getIntersectionWithBounds(entity, Vector2D(positionChange.x, 0)) |
        (this->entity->getManager().getGame()->collisionHandler ->getAnyIntersection<IntersectionBitSet>(entity, Vector2D(positionChange.x, 0), colliders)) & IntersectionBitSet("0011")) |
    (CollisionHandler::getIntersectionWithBounds(entity, Vector2D(0, positionChange.y)) |
        (this->entity->getManager().getGame()->collisionHandler ->getAnyIntersection<IntersectionBitSet>(entity, Vector2D(0, positionChange.y), colliders)) & IntersectionBitSet("1100"));
\end{minted}
\end{frame}
\note{\dots not very readable}

\begin{frame}{Naming conventions and formatting}
The project currently uses \texttt{camelCase}, \texttt{snake\_case}, sometimes with \texttt{m\_variablePrefixes} for member variables.

The solution? \texttt{clang-format}

\dots however, what formatting should be used?
\begin{figure}
    \includegraphics[width=\linewidth]{formatting.png}
\end{figure}
\end{frame}
\note{transistion to project management}

\section{Showcase}
\section*{Thank you}

\begin{frame}{Resources}
The project can be found on \href{https://github.com/orgs/VEGO-Engine/}{GitHub}, but will not be actively maintained.

The presentation on my personal \href{https://gitea.nanopenguin.at/nanopenguin/cppusergroup-vego-pres}{Gitea} instance.
\end{frame}
\note{Will be published (if ok with rene)}

%code example
\begin{frame}[fragile]{Hello, World!}
\begin{minted}[linenos,autogobble]{c}
#include <stdio.h>

int main()
{
  printf("Hello, World!");
  return 0;
}
\end{minted}
\end{frame}
\note{This is just a slide for testing the minted package}

\end{document}