\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{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 At the start of the project we had about 1 Semester of C++ Programming under our belt \item All shared a common interest in C++ Programming + a curiosity for 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 \end{itemize} \Rightarrow We could then build on what we have while simultaneously having an implementation using 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 next to each other after it has previously been generously mixed with some *juicy* pasta sauce. In other words, quite a messy endeavor\dots \end{frame} \begin{frame}{Roadmap} \nth{3} Semester - learning SDL \nth{4} and \nth{5} Semester - making the engine \end{frame} \section{Learnings} \subsection{Project environment} \begin{frame}{Baby's first \texttt{CMakeLists.txt}} \begin{itemize} \item On UAS: Only ever Make or no project setup \end{itemize} \end{frame} \begin{frame}{Visual Studio} Hate \end{frame} \begin{frame}{How the \_ do I import a library?} \begin{itemize} \item git-modules \end{itemize} \end{frame} \note[itemize]{ \item SDL is a library, static compile \item git-modules - do not bloat contributions } \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> components; ComponentArray componentArray = {}; ComponentBitSet componentBitSet; public: void update(uint_fast16_t diffTime) const; template bool hasComponent() const { return componentBitSet[getComponentTypeID()]; } template T& getComponent() const { auto ptr(componentArray[getComponentTypeID()]); return *static_cast(ptr); } template T& addComponent(TArgs&&...mArgs) { T* c(new T(std::forward(mArgs)...)); c->entity = this; std::unique_ptr uPtr{ c }; this->components.emplace_back(std::move(uPtr)); componentArray[getComponentTypeID()] = c; componentBitSet[getComponentTypeID()] = 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(pos.x, pos.y, 32, 32, scale); projectile.addComponent(texture, 4); // 4 => zIndex projectile.addComponent(range, speed, velocity, owner); projectile.addComponent(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 uPtr{ e }; this->entities.emplace_back(std::move(uPtr)); return *e; } private: std::vector> 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( [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(); \end{minted} \end{frame} \note[itemize]{ \item context: \item readable (sort of), efficient (not really due to to) \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(entity, Vector2D(positionChange.x, 0), colliders)) & IntersectionBitSet("0011")) | (CollisionHandler::getIntersectionWithBounds(entity, Vector2D(0, positionChange.y)) | (this->entity->getManager().getGame()->collisionHandler ->getAnyIntersection(entity, Vector2D(0, positionChange.y), colliders)) & IntersectionBitSet("1100")); \end{minted} \end{frame} \note{\dots not very readable} %code example \begin{frame}[fragile]{Hello, World!} \begin{minted}[linenos,autogobble]{c} #include int main() { printf("Hello, World!"); return 0; } \end{minted} \end{frame} \note{This is just a slide for testing the minted package} \end{document}