<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pavel Zabelin</title>
    <description>The latest articles on DEV Community by Pavel Zabelin (@painkiller).</description>
    <link>https://dev.to/painkiller</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1113257%2F2020b236-0d68-4969-a798-448819c02f06.jpg</url>
      <title>DEV Community: Pavel Zabelin</title>
      <link>https://dev.to/painkiller</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/painkiller"/>
    <language>en</language>
    <item>
      <title>2D Physics Engine with c++</title>
      <dc:creator>Pavel Zabelin</dc:creator>
      <pubDate>Mon, 06 Jan 2025 07:11:40 +0000</pubDate>
      <link>https://dev.to/painkiller/2d-physics-engine-with-c-208l</link>
      <guid>https://dev.to/painkiller/2d-physics-engine-with-c-208l</guid>
      <description>&lt;h2&gt;
  
  
  Introduction to the Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  About the Project
&lt;/h3&gt;

&lt;p&gt;About three months ago, I came across a video about a homemade 2D physics engine and immediately got inspired to recreate the project myself. The idea was to build an engine in C++ that can render basic shapes and calculate their collisions. Along the way, I wanted to revisit 9th-grade physics concepts, gain a better understanding of the architecture behind such projects, and most importantly — have some fun.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5oezux06uiqsyyld7gr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5oezux06uiqsyyld7gr.png" alt="Demo of the Project" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, I’ll describe the core functionality of my project and how it was implemented. The code is open-source, so feel free to dive into it right away. Here’s the GitHub link: &lt;a href="https://github.com/trier111/2DPhysicsEngine" rel="noopener noreferrer"&gt;2DPhysicsEngine&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Structure and Tools
&lt;/h3&gt;

&lt;p&gt;For this project, I used a template from Cherno’s channel: &lt;a href="https://github.com/TheCherno/ProjectTemplate" rel="noopener noreferrer"&gt;TheCherno/ProjectTemplate&lt;/a&gt;. This template splits the program into two modules right from the start (in my case, &lt;code&gt;ShowCase&lt;/code&gt; and &lt;code&gt;Engine&lt;/code&gt;) and works out of the box with the &lt;strong&gt;Premake&lt;/strong&gt; build system, which ensures compatibility across different platforms and IDEs. For rendering, I chose the &lt;strong&gt;SFML&lt;/strong&gt; library as it’s one of the simplest and most popular solutions.&lt;/p&gt;

&lt;p&gt;This template, with its two-module separation, essentially forces you to write cleaner and more architecturally logical code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interaction Between Modules (&lt;code&gt;ShowCase&lt;/code&gt; and &lt;code&gt;Engine&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;As mentioned earlier, the project is divided into two modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ShowCase&lt;/strong&gt;
This module is responsible for the main loop, handling tasks such as rendering graphics, processing input, and calling the &lt;code&gt;update()&lt;/code&gt; method on the engine side.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engine&lt;/strong&gt;
This module handles all calculations related to rigid bodies and their collisions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each shape in the &lt;code&gt;ShowCase&lt;/code&gt; module corresponds to a component in the &lt;code&gt;Engine&lt;/code&gt; module that represents it in the physical world.&lt;/p&gt;

&lt;h3&gt;
  
  
  Engine Module
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Engine Architecture: Main Loop
&lt;/h4&gt;

&lt;p&gt;The engine stores an array of all physical bodies and iterates through them each frame to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check for collisions.&lt;/li&gt;
&lt;li&gt;Resolve any collisions if present.&lt;/li&gt;
&lt;li&gt;Apply gravity.&lt;/li&gt;
&lt;li&gt;Call the &lt;code&gt;Update(DeltaTime)&lt;/code&gt; method on each physical body.&lt;/li&gt;
&lt;li&gt;Remove marked objects.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;DeltaTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;CheckCollisions&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RigidBodies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;RigidBodies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;Body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ApplyGravity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Gravity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeltaTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsMarkedForDeletion&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RigidBodies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;erase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down how this process works in detail&lt;/p&gt;

&lt;h5&gt;
  
  
  2.2. Collision System
&lt;/h5&gt;

&lt;p&gt;For each pair of physical objects, separate collision checks are used. For two circles, it's enough to compare the distance between them with the sum of their radii, while for two AABBs (simplified rectangles), the formula will be different.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv02xgvhznz5u94jezgqh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv02xgvhznz5u94jezgqh.jpg" alt="Circle Collision Example" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first interesting challenge I encountered was determining which pair of objects needed a collision check. Since the engine's array stores a pointer to the base class &lt;code&gt;RigidBodyComponent&lt;/code&gt;, and collision pair checks will occur many times every tick, the solution I chose was the &lt;strong&gt;double dispatch&lt;/strong&gt; system. Let me explain how this works.&lt;/p&gt;

&lt;p&gt;The base class for physical bodies has a pure virtual overloaded method that can accept a reference to either a base class object or a reference to any of its derived classes in the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;CheckCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RigidBodyComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;CheckCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CircleComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;CheckCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AABBComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's examine how the derived classes should override these methods using the circle as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;CircleComponent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CheckCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RigidBodyComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;CircleComponent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CheckCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CircleComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HandleCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;CircleComponent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CheckCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AABBComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HandleCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, if we know which class we need to check for collision with, we call a static method in the engine, passing a reference to the circle and a reference to the second object. However, if we receive a reference to the base class, we pass that object a reference to itself, thus invoking the &lt;code&gt;CheckCollision(CircleComponent&amp;amp; other)&lt;/code&gt; method on the second object.&lt;/p&gt;

&lt;p&gt;For this to work on the engine side, we also need methods to handle collision checks for all pairs of objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;HandleCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CircleComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AABBComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;aabb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;HandleCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CircleComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;Circle1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CircleComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;Circle2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;HandleCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AABBComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;aabb1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AABBComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;aabb2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As I understand it, this works because in order to call the &lt;code&gt;CheckCollision&lt;/code&gt; method with a reference to the base class from within the object, an upcast must be performed. This results in the method that accepts a reference to the derived class taking priority.&lt;/p&gt;

&lt;h4&gt;
  
  
  2.3. Collision Response
&lt;/h4&gt;

&lt;p&gt;In the case of a "successful" collision, we calculate the collision normal and the depth of penetration between the objects, then call the &lt;code&gt;ResolveCollision&lt;/code&gt; method, where we calculate and apply the impulse to the objects based on their velocities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ResolveCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RigidBodyComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RigidBodyComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;FVector2D&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;CollisionNormal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDynamic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDynamic&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;MassA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDynamic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetMass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FLT_MAX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;MassB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDynamic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetMass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FLT_MAX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;FVector2D&lt;/span&gt; &lt;span class="n"&gt;RelativeVelocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetVelocity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetVelocity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;VelocityAlongNormal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RelativeVelocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CollisionNormal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VelocityAlongNormal&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;ImpulseMagnitude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;VelocityAlongNormal&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;MassA&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;MassB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;FVector2D&lt;/span&gt; &lt;span class="n"&gt;Impulse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CollisionNormal&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ImpulseMagnitude&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDynamic&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetVelocity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetVelocity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;Impulse&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;MassA&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDynamic&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetVelocity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetVelocity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Impulse&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;MassB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we call the &lt;code&gt;PositionalCorrection&lt;/code&gt; method to fix any objects getting stuck inside each other, which can happen due to high velocities or during spawning.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PositionalCorrection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RigidBodyComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RigidBodyComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;FVector2D&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;CollisionNormal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;PenetrationDepth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;CorrectionFactor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;FVector2D&lt;/span&gt; &lt;span class="n"&gt;Correction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CollisionNormal&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;PenetrationDepth&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;CorrectionFactor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDynamic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDynamic&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Correction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Correction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDynamic&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BodyA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetPosition&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;Correction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDynamic&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BodyB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetPosition&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Correction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2.4. The Update Method for Physical Bodies
&lt;/h4&gt;

&lt;p&gt;Every tick, the engine calls the &lt;code&gt;Update&lt;/code&gt; method for all physical bodies, where the velocity and position are updated, acceleration is reset, and the object is marked for destruction if necessary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;RigidBodyComponent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;DeltaTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;bIsDynamic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;Velocity&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;Acceleration&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;DeltaTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;Velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Velocity&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;EngineConfig&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;DAMPING_FACTOR&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;DeltaTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;Position&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;Velocity&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;DeltaTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;Acceleration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FVector2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;NotifyPositionObservers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IsOutOfBounds&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;MarkForDeletion&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this article, I don't delve into the physics of these processes. In this case, we use conclusions drawn from basic dynamics formulas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F10pd3ojjaqhfpgkoz51l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F10pd3ojjaqhfpgkoz51l.png" alt="Screenshot with formulas" width="323" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2.5. Observers
&lt;/h3&gt;

&lt;p&gt;You might have already noticed the call to the &lt;code&gt;NotifyPositionObservers()&lt;/code&gt; method in your project. To notify about changes on the engine side, I decided to use the Observer pattern. In fact, I even have an article on this topic: &lt;a href="https://dev.to/painkiller/-delegates-observer-pattern-implementation-in-unreal-engine-2lmo"&gt;Delegates &amp;amp; Observer Pattern Implementation in Unreal Engine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's break it down with the position observer example. Anyone who wants to receive information about the position of a physical object must implement the following interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IRigidBodyPositionObserver&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;OnRigidBodyPositionUpdated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;FVector2D&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;NewPosition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To "subscribe" to updates, you need to call the method &lt;code&gt;void AddPositionObserver(IRigidBodyPositionObserver* Observer)&lt;/code&gt; on the object you're interested in and pass &lt;code&gt;this&lt;/code&gt; (the current instance) as the observer.&lt;/p&gt;

&lt;p&gt;Meanwhile, the physical body, when updating its position, will loop through the list of subscribers and call the interface method on each of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  ShowCase Module
&lt;/h3&gt;

&lt;h4&gt;
  
  
  3.1. Component Initialization
&lt;/h4&gt;

&lt;p&gt;I prefer a minimalist &lt;code&gt;main&lt;/code&gt;, so everything related to initialization (including the physics engine, window creation, and font loading) is contained within the &lt;code&gt;ShowCase&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64nleprlafz7rnpp5ol7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64nleprlafz7rnpp5ol7.png" alt="Screenshot of the main function" width="385" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3.2. Main Loop of ShowCase
&lt;/h4&gt;

&lt;p&gt;After initialization, we enter the main loop, where rendering, updating, and processing of input and other events occur.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;ShowCase&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;SpawnLevel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ProcessEvents&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Render&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ShowCase also has an array of all the shapes that need to be rendered, and their &lt;code&gt;Draw&lt;/code&gt; method is called every frame.&lt;br&gt;&lt;br&gt;
In the &lt;code&gt;Update&lt;/code&gt; method, we calculate the &lt;code&gt;DeltaTime&lt;/code&gt; variable and pass it to the engine by calling &lt;code&gt;PhysicsEngine.Update(DeltaTime)&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
We also clean our array of shapes to be rendered, similar to how it's done in the engine, and handle shape spawning here as well. Since spawning occurs 20 times per second, in the input processing, we only change boolean variables that indicate whether mouse buttons are held down.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;ShowCase&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;DeltaTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Clock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;asSeconds&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;PhysicsEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeltaTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;ClearMarkedShapes&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;TryToSpawnShape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeltaTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Conclusion
&lt;/h3&gt;

&lt;h4&gt;
  
  
  4.1. Future Plans
&lt;/h4&gt;

&lt;p&gt;In the future, I plan to optimize collision calculations between objects. There's no need to calculate collisions for every object with every other object. For example, we could divide the area into a grid and then determine which objects need collision checks with each other. Additionally, multithreading could be used to improve performance. Another idea is to add new shapes or combinations of shapes, such as chains of multiple bodies.&lt;/p&gt;

&lt;h4&gt;
  
  
  4.2. Recommendations to Readers
&lt;/h4&gt;

&lt;p&gt;I highly recommend writing your own project with the implementation of some basic game engine module, whether it's physics, rendering, or something else.&lt;br&gt;&lt;br&gt;
Aside from improving your skills as a developer, it brings a lot of satisfaction. Seriously, I had almost forgotten the magic of development—when you first draw something on the screen or two circles start bouncing off each other correctly. I hope my article helps you take your first steps.&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>phycics</category>
      <category>engine</category>
      <category>sfml</category>
    </item>
    <item>
      <title>Project Zomboid: A Decade-Long Adventure</title>
      <dc:creator>Pavel Zabelin</dc:creator>
      <pubDate>Thu, 26 Dec 2024 12:14:39 +0000</pubDate>
      <link>https://dev.to/painkiller/project-zomboid-a-decade-long-adventure-4dnd</link>
      <guid>https://dev.to/painkiller/project-zomboid-a-decade-long-adventure-4dnd</guid>
      <description>&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;Recently, the 42nd build of &lt;em&gt;Project Zomboid&lt;/em&gt; was released, and as a player who first encountered the project 10 years ago, I decided to write an introductory article about it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Zomboid&lt;/em&gt; is an isometric sandbox set in a zombie apocalypse world. And I ask you not to jump to conclusions—this is not at all the type of zombie survival game you might be thinking of. While you can experience something grind-heavy like &lt;em&gt;DayZ&lt;/em&gt; or similar projects, this is just a small part of &lt;em&gt;Zomboid&lt;/em&gt;, which can only be found on specific servers that I highly do not recommend playing on.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Zomboid&lt;/em&gt; is about a well-developed and deeply engaging gameplay. Here, any mistake can be your last.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosgtdhquw9rn5paafki8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosgtdhquw9rn5paafki8.gif" alt="Gif of a character being devoured" width="171" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The interaction with characters, enemies, and the surrounding world is astonishingly unique (though not without some frustrating flaws). I would compare it to a combination of third-person action and old console quest games, where you had to input your actions via text.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6862y1ir7i1xx4lo1hm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6862y1ir7i1xx4lo1hm.png" alt="Screenshot from a console quest from Rick and Morty" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Meeting the Author and the Game
&lt;/h2&gt;

&lt;p&gt;The author first encountered the project as a child back in 2014, when he saw it on a friend's laptop screen. What impressed the 11-year-old boy the most was the need to close windows with curtains so zombies wouldn’t react to the light, the ability to throw a blanket over the windows, and the necessity of barricading windows and doors with planks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsc7p49wl6glfspffj581.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsc7p49wl6glfspffj581.gif" alt="Gif of old build gameplay" width="1280" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Combined with resource management for food, the ability to craft and modify weapons, it felt like the perfect survival sandbox—despite the lack of full 3D and outdated graphics. Unfortunately, it wasn’t possible to play it back then, but the memory of such an unusual game stayed with me for a long time.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Why You Always Want to Return to PZ
&lt;/h2&gt;

&lt;p&gt;An important factor in an interesting project is the regular desire to return to it, and this is true for &lt;em&gt;Zomboid&lt;/em&gt;. The intensity of gameplay in the early stages, along with a whole list of challenges for a character who knows nothing, has no gear, weapons, or anything else, combined with the unique take on basic mechanics, literally sucks you into the game.&lt;/p&gt;

&lt;p&gt;Perhaps the first stage of the game, where you’re naked and trying to find at least a dead rat (stale and raw) to quench your hunger, is the core gameplay of &lt;em&gt;Zomboid&lt;/em&gt;. In it, you gather loot, improve your skills, develop a base, find a car, and more. You can add mods, change world settings (zombie generation, their behavior and strength, loot spawn, etc.), invite friends to your party, but the essence of &lt;em&gt;Zomboid&lt;/em&gt; lies in what I’ve mentioned above.&lt;/p&gt;

&lt;p&gt;No matter how I think about it, &lt;em&gt;Zomboid&lt;/em&gt; can be called a true sandbox, offering completely different gameplay experiences to anyone who wants it. If surviving in the urban outskirts isn’t for you, you can always head into the woods, sleep in a tent, and survive by foraging or hunting (which, by the way, has been revamped in the 42nd build). Don’t like tents? You can build your own house, paint the walls, set up plumbing, drag in a generator with a stove, and even organize a garden on the roof.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmdlelii7tccb5a0e6m7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmdlelii7tccb5a0e6m7.png" alt="Screenshot of a cool base" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, it’s important to mention the difficulty of the project. The loading slogan “This is the story of your death” is very self-descriptive. To get used to its somewhat unique mechanics, you’ll need time, effort, and many new characters. Bites here are lethal unless you disable that in the settings (which I highly do not recommend, and generally, don’t mess with those settings early on). And it’s the difficulty of survival in the world of &lt;em&gt;Zomboid&lt;/em&gt; that makes all your achievements in it so valuable, from the first axe you find to a car that’s in good enough condition to drive to the nearest warehouse outside the city.&lt;/p&gt;

&lt;p&gt;Although I’ve spent most of my time in &lt;em&gt;Zomboid&lt;/em&gt; playing solo or with a friend, I can’t help but mention the wide selection of multiplayer servers. You can find practically anything, from grind-heavy projects like &lt;em&gt;DayZ&lt;/em&gt; or &lt;em&gt;Rust&lt;/em&gt;, with regular PvP content, resource gathering, and many bandits (ranging from entire clans to groups of 3 survivors), to unique RP servers without the disgusting casinos and monotonous earning for a fancy car.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy030a2o6kvrm3uk1wmq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy030a2o6kvrm3uk1wmq9.png" alt="Screenshot from multiplayer" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve even seen ads for RP servers with invisible game masters, almost like in D&amp;amp;D. They are responsible for random events, zombie spawns, and the intensity of the adventure.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Development of Project Zomboid
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Project Zomboid&lt;/em&gt; has come a long way since its early access release in 2013. When the first beta was released, there was no full 3D or sandbox mode. There was only a small story where the player had to take care of their bitten wife until her death.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejysnb1t8i33yyntfujb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejysnb1t8i33yyntfujb.png" alt="Screenshot with wife from early builds" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, this story remains only as a background image in the main menu.&lt;/p&gt;

&lt;p&gt;Personally, I consider the key changes to be those of the 41st build, as if the mass player base discovered the project because of it. The reworked animations, fully realized 3D characters with visible clothing and equipment, and much more. I’ve never been a very attentive person and didn’t follow the dev blog, so I found out about the beta of the new build somewhere a year after its release, during a stream by one of the &lt;em&gt;PZ&lt;/em&gt; streamers. :-)&lt;/p&gt;

&lt;p&gt;And as much as I was excited about the new features, I was just as disappointed by the lack of multiplayer. And the &lt;em&gt;PZ&lt;/em&gt; community had to endure a lot of grief, as the beta test of the 41st build lasted four long years. I still remember how I’d visit the discussion page on Steam every year, hoping for good news, scrolling through all the messages, even those I had read a year ago.&lt;/p&gt;

&lt;p&gt;As for the 42nd build – I haven’t played enough hours yet, but the impressions are pleasant. It’s the same &lt;em&gt;PZ&lt;/em&gt;, just polished and much more refined in many ways. The rebalancing of the fighting system, the character skill system, and the improved sounds and lighting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F29q2e7ljqx8694cab53q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F29q2e7ljqx8694cab53q.png" alt="Screenshot with new lighting" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Community Modding Involvement
&lt;/h2&gt;

&lt;p&gt;When discussing &lt;em&gt;Project Zomboid&lt;/em&gt;, it’s impossible not to mention the Steam Workshop and the variety of modifications available. There is literally everything. You can expand the weaponry options, add clothes and gear, and there are many mods that solve logical problems in &lt;em&gt;Zomboid&lt;/em&gt;, which are often added to the next builds, like the mod that allows you to light cigarettes from a stove. &lt;/p&gt;

&lt;p&gt;Just, my god, there’s even a furry mod here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyilxubycue0afpwce935.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyilxubycue0afpwce935.png" alt="Screenshot with furry mod" width="800" height="758"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key is not to overdo it; this can negatively affect performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, I highly recommend you try &lt;em&gt;Project Zomboid&lt;/em&gt; yourself. The entry barrier might be high, so it’s better to try it in a party with a friend who is familiar with the game. If you manage to push through and not give up after the first ten deaths, &lt;em&gt;Zomboid&lt;/em&gt; can offer you adventures for dozens, if not hundreds, of hours.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhr4lyw2ad7chaoif0mlu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhr4lyw2ad7chaoif0mlu.gif" alt="Meme with Spiffo" width="1280" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>projectzomboid</category>
      <category>theindiestone</category>
      <category>build42</category>
    </item>
    <item>
      <title># Delegates: Observer Pattern Implementation in Unreal Engine</title>
      <dc:creator>Pavel Zabelin</dc:creator>
      <pubDate>Wed, 18 Dec 2024 12:13:12 +0000</pubDate>
      <link>https://dev.to/painkiller/-delegates-observer-pattern-implementation-in-unreal-engine-2lmo</link>
      <guid>https://dev.to/painkiller/-delegates-observer-pattern-implementation-in-unreal-engine-2lmo</guid>
      <description>&lt;p&gt;Delegates are an implementation of the Observer pattern in Unreal Engine, a behavioral design pattern that allows an object (the publisher) to inform its subscribed objects (observers) of important changes while maintaining low coupling between objects. This enables changes in the logic of different modules without worrying about unwanted consequences.&lt;/p&gt;

&lt;p&gt;It is likely that Unreal Engine developers first encountered delegates when using the &lt;code&gt;UShapeComponent&lt;/code&gt;, where they subscribed to the &lt;code&gt;OnComponentBeginOverlap&lt;/code&gt; or &lt;code&gt;OnComponentEndOverlap&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example with addDynamic subscription to callback&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** Code for when something overlaps this component */&lt;/span&gt;
&lt;span class="n"&gt;UFUNCTION&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnSphereBeginOverlap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UPrimitiveComponent&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;OverlappedComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AActor&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;OtherActor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;UPrimitiveComponent&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;OtherComp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;int32&lt;/span&gt; &lt;span class="n"&gt;OtherBodyIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;bFromSweep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;FHitResult&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;SweepResult&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;UTP_PickUpComponent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BeginPlay&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Super&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BeginPlay&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Register our Overlap Event&lt;/span&gt;
    &lt;span class="n"&gt;OnComponentBeginOverlap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDynamic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;UTP_PickUpComponent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OnSphereBeginOverlap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if this happens through the Event Dispatcher, which provides the same functionality as delegates but in the Blueprint editor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Screenshot of Event Dispatcher from OnComponentBeginOverlap&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3ab1iio2734b97laxwa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3ab1iio2734b97laxwa.png" alt="Screenshot of Event Dispatcher" width="512" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To start using delegates, you need to:&lt;/p&gt;

&lt;p&gt;1 Declare it using a macro, at the end of which you specify the number of parameters that the delegate will pass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example of delegate with explained parameters&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FOnPickUp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AObserverExampleCharacter&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PickUpCharacter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 Declare the presence of an instance of this delegate. To make the delegate work in Blueprints, use &lt;code&gt;UPROPERTY(BlueprintAssignable)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example of the delegate object&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** Delegate to whom anyone can subscribe to receive this event */&lt;/span&gt;
&lt;span class="n"&gt;UPROPERTY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BlueprintAssignable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Interaction"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;FOnPickUp&lt;/span&gt; &lt;span class="n"&gt;OnPickUp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 Design and implement the logic where the delegate will notify subscribers about an event and use the &lt;code&gt;Broadcast()&lt;/code&gt; method at this point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example with broadcast&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;OnPickUp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Broadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Character&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Use the &lt;code&gt;AddDynamic()&lt;/code&gt; method in all subscribers, passing the subscriber object and callback function. The method must accept the same parameters that the delegate will send. It should also be marked with &lt;code&gt;UFUNCTION&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example with subscription to the event and callback method declaration&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;UFUNCTION&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;HandlePickUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AObserverExampleCharacter&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;PickUpCharacter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;UExampleComponent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BeginPlay&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Super&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BeginPlay&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;AActor&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetOwner&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;UTP_PickUpComponent&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;PickUpComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Owner&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;FindComponentByClass&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UTP_PickUpComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PickUpComponent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;PickUpComponent&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;OnPickUp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDynamic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;UYourComponent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HandlePickUp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Now let's repeat it with an example
&lt;/h3&gt;

&lt;p&gt;Let's develop a health system and a response to damage received. We'll start with the health component, which will store variables related to health, handle taking damage, and also notify about the damage received using a delegate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ki2tx1oe2t1f3h0dmgf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ki2tx1oe2t1f3h0dmgf.png" alt="Delegate declaration" width="512" height="63"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx912pin2p9hb4jge71ed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx912pin2p9hb4jge71ed.png" alt="Delegate callback" width="512" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also want to spawn a camera shake when damage is taken. Let's delegate this to the DamageVisualizationComponent. In the BeginPlay, we'll find the health component on the owner and subscribe to the OnDamageReceived event.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3i9deyjll4f19pp5g0z2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3i9deyjll4f19pp5g0z2.png" alt="Subscribe to delegate" width="512" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, let's make the damage apply effects to the character. We'll create an Effects Component, do the same as before—subscribe in BeginPlay and handle the OnDamageReceived event.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5irpff2v53lrkfmp5zgx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5irpff2v53lrkfmp5zgx.png" alt="Subscribe to delegate" width="512" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the example, we also need to figure out how to take damage. Let's create a platform, where stepping on it will cause the player to take damage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb5aw7ca8rk03n3qaqwhv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb5aw7ca8rk03n3qaqwhv.png" alt="Damage event" width="512" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here's the result: the health component notifies all of its subscribers, who can then implement the necessary logic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86t4kl5qncfr4mgymcks.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86t4kl5qncfr4mgymcks.gif" alt="Delegae usage example" width="500" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In some cases, using delegates may be excessive, but an architecture where responsibility is divided between modules is always convenient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Types of Delegates
&lt;/h3&gt;

&lt;p&gt;In this article, only the &lt;code&gt;Dynamic_Multicast&lt;/code&gt; delegate was used, but this is not always necessary. Use &lt;code&gt;Dynamic&lt;/code&gt; if the delegate will be used in Blueprints. If there will only be one subscriber, use &lt;code&gt;Single&lt;/code&gt; instead of &lt;code&gt;Multicast&lt;/code&gt; when declaring the delegate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Why use the Observer pattern:
&lt;/h4&gt;

&lt;p&gt;The Observer pattern is useful in complex applications and games because it enhances modularity and minimizes coupling between components. Instead of interacting directly with each other, components can subscribe to events occurring in other parts of the system. This reduces dependencies between components, making them easier to test and modify since one component can be changed or replaced without rewriting the other parts of the system. In games, this is especially important because the logic often changes based on the game state or player actions, and the Observer pattern allows such changes to be handled easily.&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary:
&lt;/h4&gt;

&lt;p&gt;Delegates in Unreal Engine are a powerful tool for implementing the Observer pattern, which helps manage notifications between different components of the system with minimal coupling. Although delegates may be unnecessary in some cases, their use promotes a cleaner and more structured architecture, making it easier to maintain and expand the project. Thus, delegates play a key role in simplifying and improving the architecture of gameplay in Unreal Engine, making the system more flexible and easily modifiable.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
