637 lines
26 KiB
HTML
637 lines
26 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta name="generator" content="Hugo 0.139.0"><script src="/livereload.js?mindelay=10&v=2&port=1313&path=livereload" data-no-instant defer></script>
|
|
<meta charset="utf-8">
|
|
<title>Entity Component System - It's not a system</title>
|
|
|
|
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><link rel="stylesheet" href="/reveal-js/dist/reset.css">
|
|
<link rel="stylesheet" href="/reveal-js/dist/reveal.css"><link rel="stylesheet" href="/reveal-js/dist/theme/black.css" id="theme">
|
|
<link rel="stylesheet" href="/highlight-js/default.min.css">
|
|
</head>
|
|
<body>
|
|
|
|
<div class="reveal">
|
|
<div class="slides">
|
|
|
|
|
|
<section><h1 id="entity-component-system">Entity Component System</h1>
|
|
</section><section>
|
|
<h2 id="what-is-an-ecs">What is (an) ECS?</h2>
|
|
<ul>
|
|
<li><span class='fragment '
|
|
>
|
|
unnecessary
|
|
</span></li>
|
|
<li><span class='fragment '
|
|
>
|
|
useful
|
|
</span></li>
|
|
<li><span class='fragment '
|
|
>
|
|
not a system
|
|
</span></li>
|
|
</ul>
|
|
|
|
|
|
|
|
<aside class="notes"><p>Talk about structure of presentation here:</p>
|
|
<ul>
|
|
<li>define terms like “entity”, “component”, “system”</li>
|
|
<li>go over other approaches to “motivate” ECS</li>
|
|
<li>main 3 game engines will be mentioned (Unity, Unreal, Godot)</li>
|
|
<li>talking about the level of programming engines, not games</li>
|
|
</ul>
|
|
</aside>
|
|
</section><section>
|
|
<h2 id="what-are-entities">What are entities?</h2>
|
|
<p><img src="lol.jpg" alt="lol"><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
|
|
</section><section>
|
|
<h2 id="what-are-entities-1">What are entities?</h2>
|
|
<p><img src="aoe.jpg" alt="aoe"><sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
|
|
</section><section>
|
|
<h2 id="what-are-entities-2">What are entities?</h2>
|
|
<ul>
|
|
<li>Objects in a game (or simulation)</li>
|
|
<li>Can have different behaviours</li>
|
|
<li><span class='fragment '
|
|
>
|
|
Basically everything
|
|
</span></li>
|
|
</ul>
|
|
</section><section>
|
|
<h1 id="inheritance">INHERITANCE</h1>
|
|
</section>
|
|
|
|
|
|
<section data-shortcode-section>
|
|
<section data-noprocess data-shortcode-slide
|
|
data-transition="none">
|
|
<h2 id="inheritance">Inheritance</h2>
|
|
<div class="mermaid">graph TD;
|
|
Entity-->MoveableEntity;
|
|
Entity-->PhysicsEntity;
|
|
</div>
|
|
|
|
<aside class="notes"><p>Entity: Basic information like transform and mesh in our example
|
|
MoveableEntity: Entity with functions to move with and support animations
|
|
PhysicsEntity: Walls, Falling Boulders and stuff; Colliders and Gravity</p>
|
|
</aside>
|
|
</section>
|
|
<section data-noprocess data-shortcode-slide
|
|
data-transition="none">
|
|
<h2 id="inheritance-1">Inheritance</h2>
|
|
<div class="mermaid">graph TD;
|
|
Entity-->MoveableEntity;
|
|
Entity-->PhysicsEntity;
|
|
MoveableEntity-->Character;
|
|
PhysicsEntity-->BoxColliderEntity;
|
|
</div>
|
|
|
|
<aside class="notes"><p>Entity: Basic information like transform and mesh in our example
|
|
MoveableEntity: Entity with functions to move with and support animations
|
|
PhysicsEntity: Walls, Falling Boulders and stuff; Colliders and Gravity</p>
|
|
</aside>
|
|
</section>
|
|
<section data-noprocess data-shortcode-slide
|
|
data-transition="none">
|
|
<h2 id="inheritance-2">Inheritance</h2>
|
|
<div class="mermaid">graph TD;
|
|
Entity-->MoveableEntity;
|
|
Entity-->PhysicsEntity;
|
|
MoveableEntity-->Character;
|
|
Character-->Player;
|
|
Character-->NPC;
|
|
PhysicsEntity-->BoxColliderEntity;
|
|
</div>
|
|
|
|
<aside class="notes"><p>Entity: Basic information like transform and mesh in our example
|
|
MoveableEntity: Entity with functions to move with and support animations
|
|
PhysicsEntity: Walls, Falling Boulders and stuff; Colliders and Gravity</p>
|
|
</aside>
|
|
|
|
</section>
|
|
</section><section>
|
|
<h2 id="godot">Godot</h2>
|
|
<p><img src="./GodotInheritanceEditor.png" alt="GodotInheritance">
|
|
<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p>
|
|
</section><section>
|
|
<p><img src="godot_news.png" alt=""></p>
|
|
</section><section>
|
|
<h2 id="godot-code">Godot Code</h2>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="nohighlight" data-noescape><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Node2D</span> <span style="color:#f92672">:</span> <span style="color:#66d9ef">public</span> CanvasItem {
|
|
</span></span><span style="display:flex;"><span>...
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span><span style="display:flex;"><span>.
|
|
</span></span><span style="display:flex;"><span>.
|
|
</span></span><span style="display:flex;"><span>.
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PhysicsBody2D</span> <span style="color:#f92672">:</span> <span style="color:#66d9ef">public</span> CollisionObject2D {
|
|
</span></span><span style="display:flex;"><span>...
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">CharacterBody2D</span> <span style="color:#f92672">:</span> <span style="color:#66d9ef">public</span> PhysicsBody2D {
|
|
</span></span><span style="display:flex;"><span>...
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p><sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup></p>
|
|
</section>
|
|
|
|
|
|
<section data-shortcode-section>
|
|
<section data-noprocess data-shortcode-slide
|
|
data-transition="none">
|
|
<h2 id="inheritance">Inheritance</h2>
|
|
<div class="mermaid">graph TD;
|
|
Entity-->MoveableEntity;
|
|
Entity-->PhysicsEntity;
|
|
MoveableEntity-->Character;
|
|
Character-->Player;
|
|
Character-->NPC;
|
|
PhysicsEntity-->BoxColliderEntity;
|
|
MoveableEntity-->Vehicle;
|
|
</div>
|
|
|
|
</section>
|
|
<section data-noprocess data-shortcode-slide
|
|
data-transition="none">
|
|
<h2 id="multiple-inheritance">Multiple Inheritance</h2>
|
|
<div class="mermaid">graph TD;
|
|
Entity-->MoveableEntity;
|
|
Entity-->PhysicsEntity;
|
|
MoveableEntity-->Character;
|
|
Character-->Player;
|
|
Character-->NPC;
|
|
PhysicsEntity-->BoxColliderEntity;
|
|
MoveableEntity-->Vehicle;
|
|
BoxColliderEntity-->Vehicle;
|
|
</div>
|
|
|
|
|
|
</section>
|
|
</section>
|
|
<section data-noprocess>
|
|
<h1>Godot</h1>
|
|
<div style="display: flex; flex-direction: row; justify-content: center; align-items: center;">
|
|
<img style="margin-right: 10%;" src="Godot_player_scene_nodes.webp">
|
|
<ul>
|
|
<li class="fragment" >uses hierarchy instead</li>
|
|
<li class="fragment" >child nodes as "components"</li>
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
</section><section>
|
|
<h2 id="what-are-components">What are components?</h2>
|
|
<ul>
|
|
<li><span class='fragment '
|
|
>
|
|
Split entities from behaviour
|
|
</span></li>
|
|
<li><span class='fragment '
|
|
>
|
|
Data associated with a certain "behaviour"
|
|
</span></li>
|
|
</ul>
|
|
</section><section>
|
|
<h1 id="composition">COMPOSITION</h1>
|
|
</section><section>
|
|
<h1 id="composition-1">Composition</h1>
|
|
<div class="mermaid">graph LR;
|
|
EntityA-->BoxColliderComponent;
|
|
EntityA-->StaticMeshComponent;
|
|
EntityB-->SphereColliderComponent;
|
|
EntityB-->DynamicMeshComponent;
|
|
EntityB-->PlayerControllerComponent;
|
|
linkStyle default stroke:lime,stroke-width:4px;
|
|
</div>
|
|
|
|
</section><section>
|
|
<h2 id="composition-2">Composition</h2>
|
|
<ul>
|
|
<li><span class='fragment '
|
|
>
|
|
Entities have minimal data and behaviour
|
|
</span></li>
|
|
<li><span class='fragment '
|
|
>
|
|
Entities hold their components or references to them
|
|
</span></li>
|
|
</ul>
|
|
|
|
|
|
<span class='fragment ' ><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="nohighlight" data-noescape><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Component</span>;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Entity</span> {
|
|
</span></span><span style="display:flex;"><span><span style="color:#75715e">//...
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">private</span><span style="color:#f92672">:</span>
|
|
</span></span><span style="display:flex;"><span> std<span style="color:#f92672">::</span>unordered_map<span style="color:#f92672"><</span>std<span style="color:#f92672">::</span>type_info, Component<span style="color:#f92672">*></span> m_components;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div></span>
|
|
|
|
|
|
|
|
|
|
|
|
<aside class="notes"><p>Wanted to have a look at Unreal Source code, but…</p>
|
|
</aside>
|
|
</section><section>
|
|
<p><img src="gnupolice_unreal.png" alt=""></p>
|
|
</section><section>
|
|
<h2 id="unreal">Unreal</h2>
|
|
<p>Code in Unreal’s AActor class<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup>:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="nohighlight" data-noescape><span style="display:flex;"><span><span style="color:#75715e">/**
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">* All ActorComponents owned by this Actor. Stored as a Set as actors may have a large number of components
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">* @see GetComponents()
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
|
|
</span></span><span style="display:flex;"><span>TSet<span style="color:#f92672"><</span>TObjectPtr<span style="color:#f92672"><</span>UActorComponent<span style="color:#f92672">>></span> OwnedComponents;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#75715e">/**
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">* Get all components derived from class 'ComponentType' and fill in the OutComponents array with the result.
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">* It's recommended to use TArrays with a TInlineAllocator to potentially avoid memory allocation costs.
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">* TInlineComponentArray is defined to make this easier, for example:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">* {
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">* TInlineComponentArray<UPrimitiveComponent*> PrimComponents(Actor);
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">* }
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">* @param bIncludeFromChildActors If true then recurse in to ChildActor components and find components of the appropriate type in those Actors as well
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">template</span><span style="color:#f92672"><</span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ComponentType</span>, <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">AllocatorType</span><span style="color:#f92672">></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> GetComponents(TArray<span style="color:#f92672"><</span>ComponentType, AllocatorType<span style="color:#f92672">>&</span> OutComponents, <span style="color:#66d9ef">bool</span> bIncludeFromChildActors <span style="color:#f92672">=</span> false) <span style="color:#66d9ef">const</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">typedef</span> TPointedToType<span style="color:#f92672"><</span>ComponentType<span style="color:#f92672">></span> T;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> OutComponents.Reset();
|
|
</span></span><span style="display:flex;"><span> ForEachComponent_Internal<span style="color:#f92672"><</span>T<span style="color:#f92672">></span>(T<span style="color:#f92672">::</span>StaticClass(), bIncludeFromChildActors, [<span style="color:#f92672">&</span>](T<span style="color:#f92672">*</span> InComp)
|
|
</span></span><span style="display:flex;"><span> {
|
|
</span></span><span style="display:flex;"><span> OutComponents.Add(InComp);
|
|
</span></span><span style="display:flex;"><span> });
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div>
|
|
|
|
|
|
<aside class="notes"><p>next, Unity, but…</p>
|
|
<p><em>b. Distributing Examples
|
|
You may Distribute Examples (including as modified by you) in Source Code or object code to any third party.</em></p>
|
|
</aside>
|
|
</section><section>
|
|
<p><img src="gnupolice_unity.png" alt=""></p>
|
|
</section><section>
|
|
<h2 id="unity">Unity</h2>
|
|
<p><img src="unity_inspector.jpg" alt=""><sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup></p>
|
|
|
|
|
|
|
|
<aside class="notes"><ul>
|
|
<li>can’t confirm what Unity uses (no source found)</li>
|
|
<li>interface suggests composition</li>
|
|
<li>Unity DOTS?</li>
|
|
</ul>
|
|
</aside>
|
|
</section><section>
|
|
<p><img src="mario_ecs_castle.png" alt=""></p>
|
|
</section><section>
|
|
<h2 id="what-are-systems">What are systems?</h2>
|
|
<ul>
|
|
<li><span class='fragment '
|
|
>
|
|
███████████████████
|
|
</span></li>
|
|
<li><span class='fragment '
|
|
>
|
|
█████████████████
|
|
</span></li>
|
|
<li><span class='fragment '
|
|
>
|
|
████████████████████
|
|
</span></li>
|
|
</ul>
|
|
|
|
|
|
|
|
<aside class="notes"><p>We’ll talk about it later.</p>
|
|
</aside>
|
|
</section><section>
|
|
<h1 id="entity-component-system-1">Entity Component System</h1>
|
|
</section><section>
|
|
<p><img src="dracula_ecs.png" alt=""></p>
|
|
|
|
|
|
|
|
<aside class="notes"><p>ECS is Data-Oriented rather than Object-Oriented</p>
|
|
</aside>
|
|
</section><section>
|
|
<h2 id="entity-component-system-2">Entity Component System</h2>
|
|
<ul>
|
|
<li><span class='fragment '
|
|
>
|
|
split components even more from entities
|
|
</span></li>
|
|
<li><span class='fragment '
|
|
>
|
|
entities are minimal data
|
|
</span></li>
|
|
<li><span class='fragment '
|
|
>
|
|
components store data associated with certain behaviours
|
|
</span></li>
|
|
<li><span class='fragment '
|
|
>
|
|
components aren't managed by their entities
|
|
</span></li>
|
|
</ul>
|
|
|
|
|
|
|
|
<aside class="notes"><ul>
|
|
<li></li>
|
|
<li>entities can just be ids</li>
|
|
<li>component manager</li>
|
|
</ul>
|
|
</aside>
|
|
</section><section>
|
|
<p><img src="zerowing_component_manager.png" alt=""></p>
|
|
</section><section>
|
|
<h2 id="what-are-systems-1">What are systems?</h2>
|
|
<ul>
|
|
<li><span class='fragment '
|
|
>
|
|
main way of interacting with components
|
|
</span></li>
|
|
<li><span class='fragment '
|
|
>
|
|
loop over every component of a type
|
|
</span></li>
|
|
<li><span class='fragment '
|
|
>
|
|
e.g. Rendering System, Physics System...
|
|
</span></li>
|
|
</ul>
|
|
|
|
|
|
|
|
<aside class="notes"><ul>
|
|
<li>due to systems, want to optimise for iterating over components of a type</li>
|
|
</ul>
|
|
</aside>
|
|
</section><section>
|
|
<h2 id="examples">Examples:</h2>
|
|
<ul>
|
|
<li><a href="https://unity.com/dots">Unity DOTS</a></li>
|
|
<li><a href="https://bevyengine.org/">Bevy</a></li>
|
|
<li><a href="https://github.com/skypjack/entt">EnTT</a></li>
|
|
</ul>
|
|
|
|
|
|
<span class='fragment ' ><blockquote>
|
|
<p>One thing known to most is that <em>EnTT</em> is also used in Minecraft.
|
|
Given that the game is available literally everywhere, I can confidently say that the library has been sufficiently tested on every platform that can come to mind.</p>
|
|
</blockquote>
|
|
</span>
|
|
|
|
|
|
|
|
|
|
|
|
<aside class="notes"><p>Bevy ECS used for <a href="https://store.steampowered.com/app/2198150/Tiny_Glade/">Tiny Glade</a></p>
|
|
</aside>
|
|
</section><section>
|
|
<h2 id="cache">Cache</h2>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>CPU</th>
|
|
<th>L1</th>
|
|
<th>L2</th>
|
|
<th>L3</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>Pentium N4200</td>
|
|
<td>96 KiB</td>
|
|
<td>128 KiB</td>
|
|
<td>2 MiB</td>
|
|
</tr>
|
|
<tr>
|
|
<td>i7 14700HX</td>
|
|
<td>1800 KB</td>
|
|
<td>28 MB</td>
|
|
<td>33 MB</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
|
|
|
|
<aside class="notes"><p>top: silas’ laptop
|
|
bottom: mine</p>
|
|
<p>Mine are probably also KiB/MiB, because Windows is doing Windows things</p>
|
|
<p>Cache Locality less important with newer cpus, but will probably still lead to benefits.
|
|
Storing data contigous should reduce cache misses, since accesses are more predictable.
|
|
Collider Component may have 3*float64 position + 4*float64 rotation + 3*float64 size + 10*float64 miscellanious = 160 Byte
|
|
300 of those = 48 KB
|
|
500 of those = 80 KB</p>
|
|
</aside>
|
|
</section><section>
|
|
<h2 id="how-to-implement-it-in-c">How to implement it in C++</h2>
|
|
<h3 id="entities">Entities:</h3>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="nohighlight" data-noescape><span style="display:flex;"><span><span style="color:#75715e">//one possibility
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">typedef</span> uint_32t UID;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> UID Entity;
|
|
</span></span></code></pre></div></section><section>
|
|
<h2 id="how-to-implement-it-in-c-1">How to implement it in C++</h2>
|
|
<h3 id="components">Components:</h3>
|
|
<p>A <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p0429r9.pdf">std::flat_map</a> is a fitting datatype.</p>
|
|
|
|
|
|
<span class='fragment ' ><table>
|
|
<thead>
|
|
<tr>
|
|
<th>GCC libstdc++</th>
|
|
<th>Clang libc++</th>
|
|
<th>MSVC STL</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>not implemented</td>
|
|
<td>partially implemented</td>
|
|
<td>not implemented</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</span>
|
|
|
|
|
|
<p><sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup></p>
|
|
</section><section>
|
|
<h2 id="how-to-implement-it-in-c-2">How to implement it in C++</h2>
|
|
<h3 id="components-1">Components:</h3>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="nohighlight" data-noescape><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ComponentManager</span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">template</span><span style="color:#f92672"><</span><span style="color:#66d9ef">typename</span> comp_type<span style="color:#f92672">></span> <span style="color:#66d9ef">requires</span> std<span style="color:#f92672">::</span>is_base_of<span style="color:#f92672"><</span>Component, comp_type<span style="color:#f92672">></span>
|
|
</span></span><span style="display:flex;"><span> foreachComponent(std<span style="color:#f92672">::</span>function func){
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">//...
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> }
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">template</span><span style="color:#f92672"><</span><span style="color:#66d9ef">typename</span> comp_type<span style="color:#f92672">></span> <span style="color:#66d9ef">requires</span> std<span style="color:#f92672">::</span>is_base_of<span style="color:#f92672"><</span>Component, comp_type<span style="color:#f92672">></span>
|
|
</span></span><span style="display:flex;"><span> addComponentToEntity(Entity entity){
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">//...
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> }
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">//some type of ComponentMap store
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div>
|
|
|
|
|
|
<aside class="notes"><p>possible ComponentMap store:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="nohighlight" data-noescape><span style="display:flex;"><span>std<span style="color:#f92672">::</span>unordered_map<span style="color:#f92672"><</span>std<span style="color:#f92672">::</span><span style="color:#66d9ef">typeid</span>, std<span style="color:#f92672">::</span>size_t<span style="color:#f92672">></span> m_typeOffsetMap;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> m_componentMaps;
|
|
</span></span></code></pre></div></aside>
|
|
</section><section>
|
|
<h2 id="how-to-implement-it-in-c-3">How to implement it in C++</h2>
|
|
<h3 id="componentmap">ComponentMap:</h3>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="nohighlight" data-noescape><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672"><</span><span style="color:#66d9ef">typename</span> component_type<span style="color:#f92672">></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ComponentMap</span>
|
|
</span></span><span style="display:flex;"><span> std<span style="color:#f92672">::</span>vector<span style="color:#f92672"><</span>component_type<span style="color:#f92672">></span> m_values;
|
|
</span></span><span style="display:flex;"><span> std<span style="color:#f92672">::</span>unordered_map<span style="color:#f92672"><</span>Entity, size_type<span style="color:#f92672">></span> m_mapping;
|
|
</span></span></code></pre></div></section><section>
|
|
<p><img src="metroid_ending.gif" alt=""></p>
|
|
</section><section>
|
|
<h2 id="links">Links</h2>
|
|
<ul>
|
|
<li>Images from <a href="https://deathgenerator.com">deathgenerator.com</a></li>
|
|
<li>Helpful <a href="https://trepo.tuni.fi/bitstream/handle/123456789/27593/H%C3%A4rk%C3%B6nen.pdf">thesis by Toni Härkönen</a></li>
|
|
<li><a href="https://t-machine.org/index.php/2014/03/08/data-structures-for-entity-systems-contiguous-memory/">Data Structures for Entity Systems: Contiguous memory</a></li>
|
|
</ul>
|
|
<div class="footnotes" role="doc-endnotes">
|
|
</section><section>
|
|
<ol>
|
|
<li id="fn:1">
|
|
<p><a href="https://br.ign.com/league-of-legends-wild-rift/89123/feature/wild-rift-tudo-sobre-o-lol-mobile">https://br.ign.com/league-of-legends-wild-rift/89123/feature/wild-rift-tudo-sobre-o-lol-mobile</a> ; Image: Riot Games <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
|
|
</li>
|
|
<li id="fn:2">
|
|
<p><a href="https://pressakey.com/gameinfos,4981,screenshots,,,Age-of-Empires-Definitive-Edition,.html">https://pressakey.com/gameinfos,4981,screenshots,,,Age-of-Empires-Definitive-Edition,.html</a> <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p>
|
|
</li>
|
|
<li id="fn:3">
|
|
<p>Screenshot: Godot Engine <a href="#fnref:3" class="footnote-backref" role="doc-backlink">↩︎</a></p>
|
|
</li>
|
|
<li id="fn:4">
|
|
<p><a href="https://github.com/godotengine/godot">https://github.com/godotengine/godot</a> <a href="#fnref:4" class="footnote-backref" role="doc-backlink">↩︎</a></p>
|
|
</li>
|
|
<li id="fn:5">
|
|
<p>Engine/Source/Runtime/Engine/Classes/GameFramework/Actor.h <a href="#fnref:5" class="footnote-backref" role="doc-backlink">↩︎</a></p>
|
|
</li>
|
|
<li id="fn:6">
|
|
<p><a href="https://docs.unity3d.com/6000.0/Documentation/Manual/UsingTheInspector.html">https://docs.unity3d.com/6000.0/Documentation/Manual/UsingTheInspector.html</a> <a href="#fnref:6" class="footnote-backref" role="doc-backlink">↩︎</a></p>
|
|
</li>
|
|
<li id="fn:7">
|
|
<p><a href="https://en.cppreference.com/w/cpp/compiler">https://en.cppreference.com/w/cpp/compiler</a>_support/23 <a href="#fnref:7" class="footnote-backref" role="doc-backlink">↩︎</a></p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</section>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
<script type="text/javascript" src=/reveal-hugo/object-assign.js></script>
|
|
|
|
|
|
<script src="/reveal-js/dist/reveal.js"></script>
|
|
|
|
|
|
<script type="text/javascript" src="/reveal-js/plugin/markdown/markdown.js"></script>
|
|
|
|
<script type="text/javascript" src="/reveal-js/plugin/highlight/highlight.js"></script>
|
|
|
|
<script type="text/javascript" src="/reveal-js/plugin/zoom/zoom.js"></script>
|
|
|
|
<script type="text/javascript" src="/reveal-js/plugin/notes/notes.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
|
|
|
|
function camelize(map) {
|
|
if (map) {
|
|
Object.keys(map).forEach(function(k) {
|
|
newK = k.replace(/(\_\w)/g, function(m) { return m[1].toUpperCase() });
|
|
if (newK != k) {
|
|
map[newK] = map[k];
|
|
delete map[k];
|
|
}
|
|
});
|
|
}
|
|
return map;
|
|
}
|
|
|
|
var revealHugoDefaults = { center: true, controls: true, history: true, progress: true, transition: "slide" };
|
|
var revealHugoSiteParams = {};
|
|
var revealHugoPageParams = {};
|
|
|
|
var revealHugoPlugins = {
|
|
|
|
plugins: [RevealMarkdown,RevealHighlight,RevealZoom,RevealNotes]
|
|
};
|
|
|
|
|
|
var options = Object.assign({},
|
|
camelize(revealHugoDefaults),
|
|
camelize(revealHugoSiteParams),
|
|
camelize(revealHugoPageParams),
|
|
camelize(revealHugoPlugins));
|
|
|
|
Reveal.initialize(options);
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript" src="/mermaid.min_16862243754454536095.js"></script>
|
|
<script type="text/javascript">
|
|
mermaid.initialize({startOnLoad: false});
|
|
let render = (event) => {
|
|
let mermaidElems = event.currentSlide.querySelectorAll('.mermaid');
|
|
if (!mermaidElems.length){
|
|
return
|
|
}
|
|
mermaidElems.forEach(mermaidElem => {
|
|
let processed = mermaidElem.getAttribute('data-processed');
|
|
if (!processed){
|
|
|
|
mermaid.init(undefined, mermaidElem);
|
|
}
|
|
});
|
|
};
|
|
|
|
render({currentSlide: Reveal.getCurrentSlide()});
|
|
|
|
Reveal.on('slidechanged', render);
|
|
Reveal.on('ready', render);
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
</body>
|
|
</html>
|