<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ gaming - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ gaming - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 09 Jun 2026 10:26:12 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/gaming/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Change Mouse DPI Settings in Windows 10 ]]>
                </title>
                <description>
                    <![CDATA[ If your work requires a lot of precision, like graphic design and gaming, then you might want to adjust how fast or slow your external mouse or keyboard is. In this guide, I will show you how you can make your mouse more sensitive or less sensitive b... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-change-mouse-dpi-settings-in-windows-10/</link>
                <guid isPermaLink="false">66adf1042d0eb5bfdd6b0c22</guid>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ graphic design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ how-to ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kolade Chris ]]>
                </dc:creator>
                <pubDate>Tue, 02 Nov 2021 17:05:06 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/11/oscar-ivan-esquivel-arteaga-ZtxED1cpB1E-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If your work requires a lot of precision, like graphic design and gaming, then you might want to adjust how fast or slow your external mouse or keyboard is.</p>
<p>In this guide, I will show you how you can make your mouse more sensitive or less sensitive by changing its DPI.</p>
<h2 id="heading-what-is-dpi">What is DPI?</h2>
<p>DPI stands for dots per inch. It is the measurement of mouse sensitivity and cursor speed. </p>
<p>The higher your mouse DPI, the faster your mouse responds to movement per inch and the farther it travels. The slower the DPI, the slower your mouse responds to movement.</p>
<h2 id="heading-how-to-change-your-mouse-dpi-on-windows-10">How to Change your Mouse DPI on Windows 10</h2>
<p>You can change your mouse DPI through the Settings app.</p>
<p><strong>Step 1</strong>: Click on Start or press the <code>WIN</code> (Windows) key on your keyboard and select Settings.
<img src="https://www.freecodecamp.org/news/content/images/2021/11/ss-1-1.jpg" alt="ss-1-1" width="600" height="400" loading="lazy"></p>
<p><strong>Step 2</strong>: Out of the menu items you see, select "Devices".
<img src="https://www.freecodecamp.org/news/content/images/2021/11/ss-2-1.jpg" alt="ss-2-1" width="600" height="400" loading="lazy"></p>
<p><strong>Step 3</strong>: Click on the Mouse tab on the Devices page, then select "Additional mouse options" under “Related settings”.
<img src="https://www.freecodecamp.org/news/content/images/2021/11/ss-3-1.jpg" alt="ss-3-1" width="600" height="400" loading="lazy"></p>
<p><strong>Step 4</strong>: A pop-up will appear. Click on the "Pointer options" tab.</p>
<p><strong>Step 5</strong>: You will see a slider under "Select pointer speed" which you can use to adjust your mouse DPI. Move the slider to the left to reduce the DPI and to the right to increase it.
<img src="https://www.freecodecamp.org/news/content/images/2021/11/ss-4-1.jpg" alt="ss-4-1" width="600" height="400" loading="lazy"></p>
<p><strong>Step 6</strong>: Click the "Apply" button to save changes and click "Ok" to close the pop-up.
<img src="https://www.freecodecamp.org/news/content/images/2021/11/ss-5-1.jpg" alt="ss-5-1" width="600" height="400" loading="lazy"></p>
<p>Advanced mice such as those used for gaming often have buttons or sliders for adjusting their DPI, so you can change the DPI of those mice without opening the Settings app.
<img src="https://www.freecodecamp.org/news/content/images/2021/11/antonio-manaligod-T_2UFB_xwzw-unsplash--1-.jpg" alt="antonio-manaligod-T_2UFB_xwzw-unsplash--1-" width="600" height="400" loading="lazy"></p>
<h2 id="heading-final-words">Final Words</h2>
<p>In this guide, you learned what DPI is and how to change it on your Windows 10 computer.</p>
<p>Changing the DPI is useful if what you do requires a lot of precision. </p>
<p>If you game on your PC, you probably need a faster DPI to beat intervals. And if you're a designer, you might need the DPI slower for the sake of precision. </p>
<p>I hope this article helps you change your mouse DPI. If you find it useful, please share it with your friends and family.</p>
<p>Thank you for reading.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What Graphics Card Do I Have? How to Check Your GPU in Windows 10 [PC GUIDE] ]]>
                </title>
                <description>
                    <![CDATA[ Every computer has a graphics card that handles the rendering of every pixel you see on the monitor. This graphics card also plays a crucial role in displaying videos, running applications, and most especially, handling video game graphics.  Computer... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-graphics-card-do-i-have-how-to-check-your-gpu-in-windows-10-pc-guide/</link>
                <guid isPermaLink="false">66adf25c8c7074f6c488523d</guid>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Windows ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Windows 10 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kolade Chris ]]>
                </dc:creator>
                <pubDate>Wed, 13 Oct 2021 17:01:26 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/10/pexels-francesco-ungaro-1670977.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Every computer has a graphics card that handles the rendering of every pixel you see on the monitor. This graphics card also plays a crucial role in displaying videos, running applications, and most especially, handling video game graphics. </p>
<p>Computers also have a graphics processing unit (GPU), which renders images and videos. Your computer has a GPU from either Intel, AMD, or NVIDIA. </p>
<p>If your computer doesn’t have a graphics card with a powerful GPU, you might be unable to play the latest games, run infographics, and use video-intensive apps. And certain apps might not render correctly.</p>
<p>In this guide, I will show you 3 ways you can check your GPU in Windows 10, so you can know what you have and whether you need to upgrade it.</p>
<h2 id="heading-how-to-check-gpu-with-the-directx-diagnostic-tool">How to Check GPU with the DirectX Diagnostic Tool</h2>
<p><strong>Step 1</strong>: Click on the Start menu, search for “dxdiag”, and open it.
<img src="https://www.freecodecamp.org/news/content/images/2021/10/ss-1-1.png" alt="ss-1-1" width="600" height="400" loading="lazy"></p>
<p><strong>Step 2</strong>: You might be prompted to select “Yes”. Make sure you select “Yes” to proceed.</p>
<p><strong>Step 3</strong>: Click on the Display tab and you will see your GPU vendor, model, and other info:
<img src="https://www.freecodecamp.org/news/content/images/2021/10/ss-2-3.jpg" alt="ss-2-3" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-check-the-gpu-through-device-manager">How to Check the GPU Through Device Manager</h2>
<p><strong>Step 1</strong>: To check the GPU of your Windows 10 computer under Device Manager, click on start or the search icon and search “device manager”. Then click on Device Manager or press Enter.
<img src="https://www.freecodecamp.org/news/content/images/2021/10/ss-3-2.png" alt="ss-3-2" width="600" height="400" loading="lazy"></p>
<p><strong>Step 2</strong>: Expand the Display adapters branch to view the model and vendor of your computer’s GPU:
<img src="https://www.freecodecamp.org/news/content/images/2021/10/ss-4-2.jpg" alt="ss-4-2" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-check-the-gpu-through-settings">How to Check the GPU Through Settings</h2>
<p><strong>Step 1</strong>: To check your computer’s GPU in Settings, click on Start and click on the gear icon to open settings.
<img src="https://www.freecodecamp.org/news/content/images/2021/10/ss-5-3.png" alt="ss-5-3" width="600" height="400" loading="lazy"></p>
<p><strong>Step 2</strong>: Select “System” from the list you see:
<img src="https://www.freecodecamp.org/news/content/images/2021/10/ss-6-1.jpg" alt="ss-6-1" width="600" height="400" loading="lazy"></p>
<p><strong>Step 3</strong>: Make sure “Display” is selected. Though its always the first in the list.</p>
<p><strong>Step 4</strong>: Under “Multiple displays”, click on “Advanced display settings”:
<img src="https://www.freecodecamp.org/news/content/images/2021/10/ss-7-1.jpg" alt="ss-7-1" width="600" height="400" loading="lazy"></p>
<p><strong>Step 5</strong>: You should see the GPU info of the default display right away, including the model and vendor (Intel, AMD, NVIDIA).</p>
<p>If you have multiple displays installed, select the one for which you want to view the GPU info. 
<img src="https://www.freecodecamp.org/news/content/images/2021/10/ss-8.jpg" alt="ss-8" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this guide, you learned about 3 different ways you can check the graphics processing unit of your Windows 10 computer. This will help you learn more about your device and also know what next to do if the GPU is not powerful enough for your needs.</p>
<p>Thank you for reading. If you find this article helpful, please share it with your friends and family.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ RNG Meaning – What does RNG Stand for in Gaming? ]]>
                </title>
                <description>
                    <![CDATA[ If everything is predictable in a game, that isn't much fun. RNGs, or Random Number Generators, are a way to introduce a touch of randomness and causality you need to spice it up. In this article, we'll learn how random number generators work. How an... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/rng-meaning-what-does-rng-stand-for-in-gaming/</link>
                <guid isPermaLink="false">66b0c3ab4d2b90ec4a447a58</guid>
                
                    <category>
                        <![CDATA[ #Game Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Math ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ random ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ilenia Magoni ]]>
                </dc:creator>
                <pubDate>Wed, 15 Sep 2021 21:55:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/09/pexels-pixabay-37534.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If everything is predictable in a game, that isn't much fun. RNGs, or Random Number Generators, are a way to introduce a touch of randomness and causality you need to spice it up.</p>
<p>In this article, we'll learn how random number generators work.</p>
<h2 id="heading-how-an-analogic-random-number-generator-works">How an Analogic Random Number Generator Works</h2>
<p>The simplest form of a RNG is throwing dice or flipping coins.</p>
<p>Using a single die or coin means that each value has the same probability of occurring. Using multiple dice or coins instead will give a lower probability to the highest and lower values, and a higher probability to the middle values.</p>
<p>The oldest known tabletop game, <a target="_blank" href="https://en.wikipedia.org/wiki/Royal_Game_of_Ur">the Royal Game of Ur</a>, uses four 4-sided dice. Each die can give a value of 0 or 1 meaning that the value obtained by a single dice throw can go from 0 to 4.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/image-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>All the possible combinations obtained by throwing 4 dice, each can give a value of 0 or 1</em></p>
<p>There are 16 possible combinations, of which one gives a value of 0, 4 gives a value of 1, 6 gives a value of 2, 4 gives a value of 3, and one gives a value of 4.</p>
<p>In this case there is a 1/16 or 6.25% chance of getting 0, 1/4 or 25% chance of getting 1, 3/8 or 37.5% chance of getting 2, 1/4 or 25% chance of getting 3 and 1/16 or 6.25% change of getting 4.</p>
<p>More complex games have manuals full of tables to determine something randomly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/image-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Part of a table for random effects after drinking a potion. <a target="_blank" href="https://luetkemj.github.io/160419/random-potion-effects-table">Here's the whole table</a>.</em></p>
<p>Any game that uses dice has an analogic random number generator.</p>
<h2 id="heading-how-random-number-generators-work-in-video-games">How Random Number Generators Work in Video Games</h2>
<p>In video games, RNGs are much less noticeable and more complex, and players might not even be aware they exist. <a target="_blank" href="https://www.freecodecamp.org/news/random-number-generator/">There are many ways you can generate a Random Number</a>, but how do you actually use one?</p>
<p>Breaking it down into the simplest terms, using a RNG is not dissimilar from what you saw above with the dice throw used to determine an effect from a table. You just don't see the dice throw.</p>
<p>In a video game, you can use a RNG to determine what kind of loot might be dropped by a fallen enemy, or what you can find in a chest, or what kind of random encounter will await you, or even what the weather will be.</p>
<p>RNGs are used, for example, to live up open world games without the developers having to code every single section of forests and roads and deserts. Instead, developers code some possibilities and let chance determine what happens when the player reaches a certain point in the map. </p>
<p>Will you meet a bear, a wolf pack, or some bandits? The game does its version of rolling a die to determine that.</p>
<p>Let's see how to code a simple example of a Random Number Generator to better understand how they actually work.</p>
<h2 id="heading-how-to-code-a-random-number-generator">How to Code a Random Number Generator</h2>
<p>Most programming languages contain a <code>random</code> function. This function returns a random number, and what kind of random number depends on its implementation.</p>
<p>For example, in <a target="_blank" href="https://www.freecodecamp.org/news/javascript-math-random-method-explained/">JavaScript</a>, <a target="_blank" href="https://www.freecodecamp.org/news/javascript-math-random-method-explained/"><code>Math.random()</code></a> returns a random number between 0 (included) and 1 (not included). In Python, <code>randint</code> from the <code>random</code> module returns a whole number in a range (Python has also a function that does the same as JavaScript's <code>Math.random</code>).</p>
<p>Let's consider a pretty common video game situation: we have an enemy that often drops a common item, but now and then drops something rare. This enemy may be, for example, a wolf that could drop a wolf pelt (common) or a wolf fang (rare). </p>
<p>How do you determine what is "rare"? That depends on you – it can be that 1 in 10 drops is a rare item, or that 1 in 100 drops is a rare item. A middle ground may be a chance of 1 in 25 for a rare items. And to complicate it a bit, there could be also a 1 in 10 chance of no item.</p>
<p>In this case you would need a function that returns a value between 0 and 1.</p>
<p>A chance of 1 in 25 is 4%, and a chance of 1 in 10 is 10%. In decimal form that would be 0.04 and 0.1, respectively. </p>
<p>In this case you can say that a number in the range from 0 to 0.04 gives the rare item, and a number in the range from 0.9 to 1 gives no item.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/image-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>The percentage breakdown of the wolf drop</em></p>
<p>To avoid sticking to one language, let's first see how we can code this using <a target="_blank" href="https://www.freecodecamp.org/news/what-is-pseudocode-in-programming/">pseudocode</a>. This is not a real programming language – rather, it's a way to break down the code logic. It's like taking notes, as it's personal and will have varied syntax depending on the person writing it.</p>
<pre><code>FUNCTION wolfDrop
  randomNumber = random(<span class="hljs-number">0</span>,<span class="hljs-number">1</span>)
  IF
    randomNumber &lt; <span class="hljs-number">0.04</span>
    THEN
     -&gt; wolf fang
  ELSE IF
    randomNumber &lt; <span class="hljs-number">0.9</span>
    THEN
     -&gt; wolf pelt
  ELSE
    -&gt; empty
  END IF
END FUNCTION
</code></pre><p>Or a more verbose version:</p>
<blockquote>
<p>Create a function called <code>wolfDrop</code> and inside it store a random number between 0 (included) and 1 (excluded) in the <code>randomNumber</code> variable. If <code>randomNumber</code> has a value less than <code>0.04</code> the drop will be a wolf fang, else if the <code>randomNumber</code> has a value less than <code>0.9</code> the drop will be a wolf pelt, and otherwise there will be no drop.</p>
</blockquote>
<p>With the pseudocode ready, we can implement the code snippet in any language. Let's see, for example, how to code it in a few different languages:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">wolfDrop</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> randomNumber = <span class="hljs-built_in">Math</span>.random();
  <span class="hljs-keyword">if</span> (randomNumber &lt; <span class="hljs-number">0.04</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Wolf fang"</span>;
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (randomNumber &lt; <span class="hljs-number">0.9</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Wolf pelt"</span>;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span>;
  }
}
</code></pre>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> random
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wolfDrop</span>():</span>
  randomNumber = random.random()
  <span class="hljs-keyword">if</span> randomNumber &lt; <span class="hljs-number">0.04</span>:
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Wolf fang"</span>
  <span class="hljs-keyword">elif</span> randomNumber &lt; <span class="hljs-number">0.9</span>:
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Wolf pelt"</span>
  <span class="hljs-keyword">else</span>
    <span class="hljs-keyword">return</span>
</code></pre>
<pre><code class="lang-clojure">(<span class="hljs-keyword">defn</span> <span class="hljs-title">wolf-drop</span> []
  (<span class="hljs-name"><span class="hljs-builtin-name">let</span></span> [random-number (<span class="hljs-name"><span class="hljs-builtin-name">rand</span></span>)]
    (<span class="hljs-name"><span class="hljs-builtin-name">cond</span></span> (<span class="hljs-name"><span class="hljs-builtin-name">&lt;</span></span> random-number <span class="hljs-number">0.04</span>) <span class="hljs-string">"Wolf fang"</span>
          (<span class="hljs-name"><span class="hljs-builtin-name">&lt;</span></span> random-number <span class="hljs-number">0.9</span>) <span class="hljs-string">"Wolf pelt"</span>)))
</code></pre>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">wolfDrop</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    randomNumber := rand.Float64()
    <span class="hljs-keyword">switch</span> {
        <span class="hljs-keyword">case</span> randomNumber &lt; <span class="hljs-number">0.04</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-string">"Wolf fang"</span>
        <span class="hljs-keyword">case</span> randomNumber &lt; <span class="hljs-number">0.9</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-string">"Wolf pelt"</span>
        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>
    }
}
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">wolfDrop</span><span class="hljs-params">()</span></span>: String {
    <span class="hljs-keyword">val</span> randomNumber = Random.nextFloat()
    <span class="hljs-keyword">when</span> {
        randomNumber &lt; <span class="hljs-number">0.04</span> -&gt; <span class="hljs-keyword">return</span> <span class="hljs-string">"Wolf fang"</span>
        randomNumber &lt; <span class="hljs-number">0.9</span> -&gt; <span class="hljs-keyword">return</span> <span class="hljs-string">"Wolf pelt"</span>
        <span class="hljs-keyword">else</span> -&gt; <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>
    }
}
</code></pre>
<pre><code class="lang-elixir"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wolf_pelt</span></span>() <span class="hljs-keyword">do</span>
  random_number = <span class="hljs-symbol">:rand</span>.uniform()
  <span class="hljs-keyword">cond</span> <span class="hljs-keyword">do</span>
    random_number &lt; 0.04 -&gt; <span class="hljs-string">"Wolf fang"</span>
    random_number &lt; 0.<span class="hljs-number">9</span> -&gt; <span class="hljs-string">"Wolf pelt"</span>
    <span class="hljs-keyword">true</span> -&gt; <span class="hljs-keyword">nil</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<pre><code class="lang-c#"><span class="hljs-function"><span class="hljs-keyword">string</span> <span class="hljs-title">WolfPelt</span>(<span class="hljs-params"></span>)</span> {
  <span class="hljs-keyword">var</span> random = <span class="hljs-keyword">new</span> Random();
  <span class="hljs-keyword">double</span> randomNumber = random.NextDouble();
  <span class="hljs-keyword">if</span> (randomNumber &lt; <span class="hljs-number">0.04</span>) <span class="hljs-keyword">return</span> <span class="hljs-string">"Wolf fang"</span>;
  <span class="hljs-keyword">if</span> (randomNumber &lt; <span class="hljs-number">0.9</span>) <span class="hljs-keyword">return</span> <span class="hljs-string">"Wolf pelt"</span>;
  <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
</code></pre>
<pre><code class="lang-rust"><span class="hljs-keyword">extern</span> <span class="hljs-keyword">crate</span> rand;

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">wolf_drop</span></span>() -&gt; &amp;<span class="hljs-symbol">'static</span> <span class="hljs-built_in">str</span> {
  <span class="hljs-keyword">let</span> random_number: <span class="hljs-built_in">f64</span> = rand::random();
  <span class="hljs-keyword">if</span> random_number &lt; <span class="hljs-number">0.04</span> {
    <span class="hljs-string">"Wolf fang"</span>
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> random_number &lt; <span class="hljs-number">0.9</span> {
    <span class="hljs-string">"Wolf pelt"</span>
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-string">""</span>
  }
}
</code></pre>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdlib.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;string.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;time.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">wolf_drop</span><span class="hljs-params">(<span class="hljs-keyword">char</span> *drop_item)</span> </span>{
  srand((<span class="hljs-keyword">unsigned</span>) time(<span class="hljs-number">0</span>));
  <span class="hljs-keyword">double</span> random_number = <span class="hljs-number">1.0</span> * rand() / RAND_MAX;
  <span class="hljs-keyword">if</span> (random_number &lt; <span class="hljs-number">0.04</span>) {
    <span class="hljs-built_in">strncpy</span>(drop_item, <span class="hljs-string">"wolf fang\0"</span>, <span class="hljs-number">10</span>);
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (random_number &lt; <span class="hljs-number">0.9</span>) {
    <span class="hljs-built_in">strncpy</span>(drop_item, <span class="hljs-string">"wolf pelt\0"</span>, <span class="hljs-number">10</span>);
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">strncpy</span>(drop_item, <span class="hljs-string">"\0"</span>, <span class="hljs-number">1</span>);
  }
  <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<pre><code class="lang-julia"><span class="hljs-keyword">function</span> wolfdrop()
    randomnumber = rand()
    <span class="hljs-keyword">if</span> randomnumber &lt; <span class="hljs-number">0.04</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"wolf fang"</span>
    <span class="hljs-keyword">elseif</span> randomnumber &lt; <span class="hljs-number">0.9</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"wolf pelt"</span>
    <span class="hljs-keyword">else</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>
    <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>(Thanks to <a target="_blank" href="https://forum.freecodecamp.org/u/alpox">alpox</a> for the code snippets in Clojure, Golang, Kotlin, Elixir and C#, and to <a target="_blank" href="https://www.freecodecamp.org/news/author/jeremylt/">Jeremy</a> for the snippets in Rust, C, and Julia.)</p>
<h3 id="heading-other-examples-of-mathrandom">Other examples of math.random</h3>
<p>If you want to learn more about all this, you can read this article about the <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-javascript-math-random-as-a-random-number-generator/">Math.random function in JavaScript</a> and create a Dice Rolling Game. </p>
<p>You can also read this <a target="_blank" href="https://www.freecodecamp.org/news/how-to-make-your-own-procedural-dungeon-map-generator-using-the-random-walk-algorithm-e0085c8aa9a/">article on using the random walk algorithm</a> and create a random dungeon map with JavaScript to experiment some more with RNGs.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Random Number Generators, or RNGs, are used in many games. In this article, you have learned how and why they are used, and you've seen an example implementation. </p>
<p>Next time you play a video game, will you be able to spot where a RNG may be used?</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to make your Tic Tac Toe game unbeatable by using the minimax algorithm ]]>
                </title>
                <description>
                    <![CDATA[ I struggled for hours scrolling through tutorials, watching videos, and banging my head on the desk trying to build an unbeatable Tic Tac Toe game with a reliable Artificial Intelligence. So if you are going through a similar journey, I would like to... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-make-your-tic-tac-toe-game-unbeatable-by-using-the-minimax-algorithm-9d690bad4b37/</link>
                <guid isPermaLink="false">66ac8afb0f96f64ded4b7bd3</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Artificial Intelligence ]]>
                    </category>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ahmad Abdolsaheb ]]>
                </dc:creator>
                <pubDate>Sat, 02 May 2020 04:50:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/1_y2B2auvIpUI0vSLtT2KWyg-1.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I struggled for hours scrolling through tutorials, watching videos, and banging my head on the desk trying to build an unbeatable Tic Tac Toe game with a reliable Artificial Intelligence. So if you are going through a similar journey, I would like to introduce you to the Minimax algorithm.</p>
<p>Like a professional chess player, this algorithm sees a few steps ahead and puts itself in the shoes of its opponent. It keeps playing ahead until it reaches a terminal arrangement of the board (<strong>terminal state</strong>) resulting in a tie, a win, or a loss. Once in a terminal state, the AI will assign an arbitrary positive score (+10) for a win, a negative score (-10) for a loss, or a neutral score (0) for a tie.</p>
<p>At the same time, the algorithm evaluates the moves that lead to a terminal state based on the players’ turn. It will choose the move with maximum score when it is the AI’s turn and choose the move with the minimum score when it is the human player’s turn. Using this strategy, Minimax avoids losing to the human player.</p>
<p>Try it for yourself in the following game preferably using a Chrome browser.</p>
<div class="embed-wrapper"><iframe height="454" style="width:100%" src="https://codepen.io/abdolsa/embed/vgjoMb?height=454&amp;theme-id=light&amp;default-tab=js,result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/abdolsa/pen/vgjoMb">minimax 4 medium</a> by Ahmad Abdolsaheb
  (<a href="https://codepen.io/abdolsa">@abdolsa</a>) on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>A Minimax algorithm can be best defined as a recursive function that does the following things:</p>
<ol>
<li>return a value if a terminal state is found (+10, 0, -10)</li>
<li>go through available spots on the board</li>
<li>call the minimax function on each available spot (recursion)</li>
<li>evaluate returning values from function calls</li>
<li>and return the best value</li>
</ol>
<p>If you are new to the concept of recursion, I recommend watching this <a target="_blank" href="https://www.youtube.com/watch?v=VrrnjYgDBEk">video</a> from Harvard’s CS50.</p>
<p>To completely grasp the Minimax’s thought process, let’s implement it in code and see it in action in the following two sections.</p>
<h3 id="heading-minimax-in-code">Minimax in Code</h3>
<p>For this tutorial you will be working on a near end state of the game which is shown in figure 2 below. Since minimax evaluates every state of the game (hundreds of thousands), a near end state allows you to follow up with minimax’s recursive calls easier (9).</p>
<p>For the following figure, assume the AI is X and the human player is O.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/iYDAcMcMvbr0lBISCQqM-mBbfhqDx2sPqcYl" alt="Image" width="800" height="317" loading="lazy">
<em>figure 2 sample of game state</em></p>
<p>To work with the Ti Tac Toe board more easily, you should define it as an array with 9 items. Each item will have its index as a value. This will come in handy later on. Because the above board is already populated with some X and Y moves, let us define the board with the X and Y moves already in it (<em>origBoard</em>).</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> origBoard = [<span class="hljs-string">"O"</span>,<span class="hljs-number">1</span>,<span class="hljs-string">"X"</span>,<span class="hljs-string">"X"</span>,<span class="hljs-number">4</span>,<span class="hljs-string">"X"</span>,<span class="hljs-number">6</span>,<span class="hljs-string">"O"</span>,<span class="hljs-string">"O"</span>];
</code></pre>
<p>Then declare <em>aiPlayer</em> and <em>huPlayer</em> variables and set them to “X” and “O” respectively<em>.</em></p>
<p>Additionally, you need a function that looks for winning combinations and returns true if it finds one, and a function that lists the indexes of available spots in the board.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/* the original board
 O |   | X
 ---------
 X |   | X
 ---------
   | O | O
 */</span>
<span class="hljs-keyword">var</span> origBoard = [“O”,<span class="hljs-number">1</span> ,”X”,”X”,<span class="hljs-number">4</span> ,”X”, <span class="hljs-number">6</span> ,”O”,”O”];

<span class="hljs-comment">// human</span>
<span class="hljs-keyword">var</span> huPlayer = “O”;

<span class="hljs-comment">// ai</span>
<span class="hljs-keyword">var</span> aiPlayer = “X”;

<span class="hljs-comment">// returns list of the indexes of empty spots on the board</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">emptyIndexies</span>(<span class="hljs-params">board</span>)</span>{
  <span class="hljs-keyword">return</span>  board.filter(<span class="hljs-function"><span class="hljs-params">s</span> =&gt;</span> s != <span class="hljs-string">"O"</span> &amp;&amp; s != <span class="hljs-string">"X"</span>);
}

<span class="hljs-comment">// winning combinations using the board indexies</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">winning</span>(<span class="hljs-params">board, player</span>)</span>{
 <span class="hljs-keyword">if</span> (
 (board[<span class="hljs-number">0</span>] == player &amp;&amp; board[<span class="hljs-number">1</span>] == player &amp;&amp; board[<span class="hljs-number">2</span>] == player) ||
 (board[<span class="hljs-number">3</span>] == player &amp;&amp; board[<span class="hljs-number">4</span>] == player &amp;&amp; board[<span class="hljs-number">5</span>] == player) ||
 (board[<span class="hljs-number">6</span>] == player &amp;&amp; board[<span class="hljs-number">7</span>] == player &amp;&amp; board[<span class="hljs-number">8</span>] == player) ||
 (board[<span class="hljs-number">0</span>] == player &amp;&amp; board[<span class="hljs-number">3</span>] == player &amp;&amp; board[<span class="hljs-number">6</span>] == player) ||
 (board[<span class="hljs-number">1</span>] == player &amp;&amp; board[<span class="hljs-number">4</span>] == player &amp;&amp; board[<span class="hljs-number">7</span>] == player) ||
 (board[<span class="hljs-number">2</span>] == player &amp;&amp; board[<span class="hljs-number">5</span>] == player &amp;&amp; board[<span class="hljs-number">8</span>] == player) ||
 (board[<span class="hljs-number">0</span>] == player &amp;&amp; board[<span class="hljs-number">4</span>] == player &amp;&amp; board[<span class="hljs-number">8</span>] == player) ||
 (board[<span class="hljs-number">2</span>] == player &amp;&amp; board[<span class="hljs-number">4</span>] == player &amp;&amp; board[<span class="hljs-number">6</span>] == player)
 ) {
 <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
 } <span class="hljs-keyword">else</span> {
 <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
 }
}
</code></pre>
<p>Now let’s dive into the good parts by defining the Minimax function with two arguments <em>newBoard</em> and <em>player</em>. Then, you need to find the indexes of the available spots in the board and set them to a variable called <em>availSpots</em>.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// the main minimax function</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">minimax</span>(<span class="hljs-params">newBoard, player</span>)</span>{

    <span class="hljs-comment">//available spots</span>
    <span class="hljs-keyword">var</span> availSpots = emptyIndexies(newBoard);
</code></pre>
<p>Also, you need to check for terminal states and return a value accordingly. If O wins you should return -10, if X wins you should return +10. In addition, if the length of the <em>availableSpots</em> array is zero, that means there is no more room to play, the game has resulted in a tie, and you should return zero.</p>
<pre><code class="lang-javascript">
  <span class="hljs-comment">// checks for the terminal states such as win, lose, and tie </span>
  <span class="hljs-comment">//and returning a value accordingly</span>
  <span class="hljs-keyword">if</span> (winning(newBoard, huPlayer)){
     <span class="hljs-keyword">return</span> {<span class="hljs-attr">score</span>:<span class="hljs-number">-10</span>};
  }
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (winning(newBoard, aiPlayer)){
    <span class="hljs-keyword">return</span> {<span class="hljs-attr">score</span>:<span class="hljs-number">10</span>};
    }
  <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (availSpots.length === <span class="hljs-number">0</span>){
      <span class="hljs-keyword">return</span> {<span class="hljs-attr">score</span>:<span class="hljs-number">0</span>};
  }
</code></pre>
<p>Next, you need to collect the scores from each of the empty spots to evaluate later. Therefore, make an array called <em>moves</em> and loop through empty spots while collecting each move’s index and score in an object called <em>move</em>.</p>
<p>Then, set the index number of the empty spot that was stored as a number in the <em>origBoard</em> to the index property of the <em>move</em> object. Later, set the empty spot on the <em>newboard</em> to the current player and call the <em>minimax</em> function with other player and the newly changed <em>newboard</em>. Next, you should store the object resulted from the <em>minimax</em> function call that includes a <em>score</em> property to the <em>score</em> property of the <em>move</em> object.</p>
<blockquote>
<p><em>If the minimax function does not find a terminal state, it keeps recursively going level by level deeper into the game. This recursion happens until it reaches a terminal state and returns a score one level up.</em></p>
</blockquote>
<p>Finally, Minimax resets <em>newBoard</em> to what it was before and pushes the <em>move</em> object to the <em>moves</em> array.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// an array to collect all the objects</span>
  <span class="hljs-keyword">var</span> moves = [];

  <span class="hljs-comment">// loop through available spots</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; availSpots.length; i++){
    <span class="hljs-comment">//create an object for each and store the index of that spot </span>
    <span class="hljs-keyword">var</span> move = {};
      move.index = newBoard[availSpots[i]];

    <span class="hljs-comment">// set the empty spot to the current player</span>
    newBoard[availSpots[i]] = player;

    <span class="hljs-comment">/*collect the score resulted from calling minimax 
      on the opponent of the current player*/</span>
    <span class="hljs-keyword">if</span> (player == aiPlayer){
      <span class="hljs-keyword">var</span> result = minimax(newBoard, huPlayer);
      move.score = result.score;
    }
    <span class="hljs-keyword">else</span>{
      <span class="hljs-keyword">var</span> result = minimax(newBoard, aiPlayer);
      move.score = result.score;
    }

    <span class="hljs-comment">// reset the spot to empty</span>
    newBoard[availSpots[i]] = move.index;

    <span class="hljs-comment">// push the object to the array</span>
    moves.push(move);
  }
</code></pre>
<p>Then, the minimax algorithm needs to evaluate the best <em>move</em> in the <em>moves</em> array. It should choose the <em>move</em> with the highest score when AI is playing and the <em>move</em> with the lowest score when the human is playing. Therefore, If the <em>player</em> is <em>aiPlayer</em>, it sets a variable called <em>bestScore</em> to a very low number and loops through the <em>moves</em> array, if a <em>move</em> has a higher <em>score</em> than <em>bestScore</em>, the algorithm stores that <em>move</em>. In case there are moves with similar score, only the first one will be stored.</p>
<p>The same evaluation process happens when <em>player</em> is <em>huPlayer</em>, but this time <em>bestScore</em> would be set to a high number and Minimax looks for a move with the lowest score to store.</p>
<p>At the end, Minimax returns the object stored in <em>bestMove</em>.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// if it is the computer's turn loop over the moves and choose the move with the highest score</span>
  <span class="hljs-keyword">var</span> bestMove;
  <span class="hljs-keyword">if</span>(player === aiPlayer){
    <span class="hljs-keyword">var</span> bestScore = <span class="hljs-number">-10000</span>;
    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; moves.length; i++){
      <span class="hljs-keyword">if</span>(moves[i].score &gt; bestScore){
        bestScore = moves[i].score;
        bestMove = i;
      }
    }
  }<span class="hljs-keyword">else</span>{

<span class="hljs-comment">// else loop over the moves and choose the move with the lowest score</span>
    <span class="hljs-keyword">var</span> bestScore = <span class="hljs-number">10000</span>;
    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; moves.length; i++){
      <span class="hljs-keyword">if</span>(moves[i].score &lt; bestScore){
        bestScore = moves[i].score;
        bestMove = i;
      }
    }
  }

<span class="hljs-comment">// return the chosen move (object) from the moves array</span>
  <span class="hljs-keyword">return</span> moves[bestMove];
}
</code></pre>
<blockquote>
<p><em>That is it for the minimax function. :) you can find the above algorithm on <a target="_blank" href="https://github.com/ahmadabdolsaheb/minimaxarticle">github</a> and <a target="_blank" href="https://codepen.io/abdolsa/pen/mABGoz?editors=1011">codepen</a>. Play around with different boards and check the results in the console.</em></p>
</blockquote>
<p>In the next section, let’s go over the code line by line to better understand how the minimax function behaves given the board shown in figure 2.</p>
<h3 id="heading-minimax-in-action">Minimax in action</h3>
<p>Using the following figure, let’s follow the algorithm’s function calls (<strong>FC</strong>) one by one.</p>
<p>Note: In figure 3, large numbers represent each function call and levels refer to how many steps ahead of the game the algorithm is playing.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/1_VG79nxl-mJQrsp6p3q79qA--1-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Figure 3 Minimax function call by function call</em></p>
<p><strong><em>1.</em></strong><em>origBoard</em> and <em>aiPlayer</em> is fed to the algorithm. The algorithm makes a list of the three empty spots it finds, checks for terminal states, and loops through every empty spot starting from the first one. Then, it changes the <em>newBoard</em> by placing the <em>aiPlayer</em> in the first empty spot. After that, it calls itself with <em>newBoard</em> and the <em>huPlayer</em> and waits for the FC to return a value.</p>
<p><strong>2.</strong> While the first FC is still running, the second one starts by making a list of the two empty spots it finds, checks for terminal states, and loops through the empty spot starting from the first one. Then, it changes the <em>newBoard</em> by placing the <em>huPlayer</em> in the first empty spot. After that it calls itself with <em>newBoard</em> and the <em>aiPlayer</em> and waits for the FC to return a value.</p>
<p><strong>3.</strong> Finally the algorithm makes a list of the empty spots, and finds a win for the human player after checking for terminal states. Therefore, it returns an object with a score property and value of -10.</p>
<blockquote>
<p><em>Since the second FC listed two empty spots, Minimax changes the</em> newBoard <em>by placing</em> huPlayer <em>in the second empty spot. Then, it calls itself with the new board and the</em> aiPlayer<em>.</em></p>
</blockquote>
<p><strong>4.</strong> The algorithm makes a list of the empty spots, and finds a win for the human player after checking for terminal states. Therefore, it returns an object with a score property and value of -10.</p>
<blockquote>
<p><em>On the second FC, the algorithm collects the values coming from lower levels (3rd and 4th FC). Since</em> huPlayer<em>’s turn resulted in the two values, the algorithm chooses the lowest of the two values. Because both of the values are similar, it chooses the first one and returns it up to the first FC.</em></p>
<p><em>At this point the first FC has evaluated the score of moving</em> aiPlayer <em>in the first empty spot. Next, it changes the</em> newBoard <em>by placing</em> aiPlayer <em>in the second empty spot. Then, it calls itself with the</em> newBoard <em>and the</em> huPlayer<em>.</em></p>
</blockquote>
<p><strong>5.</strong> On the fifth FC, The algorithm makes a list of the empty spots, and finds a win for the human player after checking for terminal states. Therefore, it returns an object with a score property and value of +10.</p>
<blockquote>
<p><em>After that, the first FC moves on by changing the</em> newBoard <em>and placing</em> aiPlayer <em>in the third empty spot. Then, it calls itself with the new board and the</em> huPlayer<em>.</em></p>
</blockquote>
<p><strong>6.</strong> The 6th FC starts by making a list of two empty spots it finds, checks for terminal states, and loops through the two empty spots starting from the first one. Then, it changes the <em>newBoard</em> by placing the <em>huPlayer</em> in the first empty spot. After that, it calls itself with <em>newBoard</em> and the <em>aiPlayer</em> and waits for the FC to return a score.</p>
<p><strong>7.</strong> Now the algorithm is two level deep into the recursion. It makes a list of the one empty spot it finds, checks for terminal states, and changes the <em>newBoard</em> by placing the <em>aiPlayer</em> in the empty spot. After that, it calls itself with <em>newBoard</em> and the <em>huPlayer</em> and waits for the FC to return a score so it can evaluate it.</p>
<p><strong>8.</strong> On the 8th FC, the algorithm makes an empty list of empty spots, and finds a win for the <em>aiPlayer</em> after checking for terminal states. Therefore, it returns an object with score property and value of +10 one level up (7th FC).</p>
<blockquote>
<p><em>The 7th FC only received one positive value from lower levels (8th FC). Because</em> aiPlayer’s turn <em>resulted in that value, the algorithm needs to return the highest value it has received from lower levels. Therefore, it returns its only positive value (+10) one level up (6th FC).</em></p>
<p><em>Since the 6th FC listed two empty spots, Minimax changes</em> newBoard <em>by placing</em> huPlayer <em>in the second empty spot. Then, calls itself with the new board and the</em> aiPlayer<em>.</em></p>
</blockquote>
<p><strong>9.</strong> Next, the algorithm makes a list of the empty spots, and finds a win for the <em>aiPlayer</em> after checking for terminal states. Therefore, it returns an object with score properties and value of +10.</p>
<blockquote>
<p><em>At this point, the 6 FC has to choose between the score (+10)that was sent up from the 7th FC (returned originally from from the 8 FC) and the score (-10) returned from the 9th FC. Since</em> huPlayer<em>’s turn resulted in those two returned values, the algorithm finds the minimum score (-10) and returns it upwards as an object containing score and index properties.</em></p>
<p><em>Finally, all three branches of the first FC have been evaluated ( -10, +10, -10). But because aiPlayer’s turn resulted in those values, the algorithm returns an object containing the highest score (+10) and its index (4).</em></p>
</blockquote>
<p><strong>In the above scenario, Minimax concludes that moving the X to the middle of the board results in the best outcome. :)</strong></p>
<h3 id="heading-the-end">The End!</h3>
<p>By now you should be able to understand the logic behind the Minimax algorithm. Using this logic try to implement a Minimax algorithm yourself or find the above sample on <a target="_blank" href="https://github.com/ahmadabdolsaheb/minimaxarticle">github</a> or <a target="_blank" href="https://codepen.io/abdolsa/pen/mABGoz?editors=1011">codepen</a> and optimize it.</p>
<p><em>Thanks for reading! If you liked this story, don't forget to share it on social media.</em></p>
<p><em>Special thanks to Tuba Yilmaz, Rick McGavin, and Javid Askerov</em> <em>for reviewing this article.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Minecraft Forge: How to Download, Install, and Use Forge ]]>
                </title>
                <description>
                    <![CDATA[ If you are reading this article you probably already know Minecraft. We use Forge to manipulate the game Minecraft to make it do what we want. This could be anything, ranging from new cool creatures to entire new systems in the game. Forge is a moddi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/minecraft-forge-how-to-download-install-and-use-forge/</link>
                <guid isPermaLink="false">66c35b5c9de50ee9ca7fa707</guid>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ minecraft ]]>
                    </category>
                
                    <category>
                        <![CDATA[ toothbrush ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 10 Jan 2020 22:59:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9dfd740569d1a4ca3ac2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you are reading this article you probably already know Minecraft. We use Forge to manipulate the game Minecraft to make it do what we want. This could be anything, ranging from new cool creatures to entire new systems in the game.</p>
<p>Forge is a modding API. Minecraft Forge (or Forge for short) is a layer between our code and Minecraft itself. </p>
<p>We cannot directly ask Minecraft to add items and do special cool things. That’s why we need an API (application programming interface) to handle our logic and make Minecraft recognise it.</p>
<h2 id="heading-sounds-cool-how-do-i-get-started"><strong>Sounds cool! How do I get started?</strong></h2>
<ul>
<li>You’ll need the JDK (Java development kit) which is a set of libraries, tools and the runtime environment to make Java programs and run them.</li>
<li>A Minecraft account which can be bought from their official website. (<a target="_blank" href="https://minecraft.net/en-us/store/">https://minecraft.net/en-us/store/</a>)</li>
<li>An IDE (Eclipse or IntelliJ are recommended for Minecraft development)</li>
</ul>
<p>After installing/acquiring these pieces of software, download your desired Forge version at <a target="_blank" href="https://files.minecraftforge.net/">https://files.minecraftforge.net/</a>.</p>
<p><strong>Tip</strong>: Hover over the information button and press direct download to avoid an Adfly virus! </p>
<p>Once you have downloaded this ZIP you’ll be able to unzip it. Do so and cd (cmd/command) into the directory with all of the Forge files. Run <code>gradlew setupDecompWorkspace</code>.</p>
<p>Next up is picking your IDE (integrated development environment). </p>
<ul>
<li>Eclipse? <code>gradlew eclipse</code>. </li>
<li>IntelliJ? Import the build.gradle file in your IntelliJ setup.</li>
</ul>
<h2 id="heading-okay-now-what-how-do-i-add-fancy-new-items-basic-mod-setup"><strong>Okay now what? How do I add fancy new items? (Basic mod setup)</strong></h2>
<p>Hold your horses. There’s much more to it. You’ll have to texture an item of course, add code and so much more! In this article we’ll only look at some simple sample code which I also use for my own mods. Here it is!</p>
<p>`@Mod.EventBusSubscriber @Mod(modid = Version.MOD_ID, name = Version.MOD_NAME, version = Version.VERSION) public class TheMod {</p>
<pre><code class="lang-text">public static ModMetadata metadata;

public static File baseDir;
public static Configuration config;

@SidedProxy(clientSide="com.ciphry.client.ClientProxy", serverSide="com.ciphry.common.CommonProxy")
public static CommonProxy proxy;

@Mod.EventHandler
public void preInit(FMLPreInitializationEvent event) {
    proxy.preInit(event);

    baseDir = new File(event.getModConfigurationDirectory(), MOD_ID);
    config = new Configuration(event.getSuggestedConfigurationFile());

    if (!baseDir.exists())
        baseDir.mkdir();
}

@Mod.EventHandler
public void init(FMLInitializationEvent event) {
    proxy.init(event);

}

@Mod.EventHandler
public void postInit(FMLPostInitializationEvent event) {
    proxy.postInit(event);
}
</code></pre>
<p>Use this code as you please. Just make sure you edit, for instance, the proxy strings and more. This should give you a basic overview of what a basic mod class looks like.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Play the No Internet Google Chrome Dinosaur Game - Both Online and Offline ]]>
                </title>
                <description>
                    <![CDATA[ Several years ago, Google added a fun little Easter egg to Chrome: if your internet went down and you tried to visit a web page, you'd see the message "Unable to connect to the Internet"  or "No internet" with a little pixilated dinosaur next to it. ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-play-the-no-internet-google-chrome-dinosaur-game-both-online-and-offline/</link>
                <guid isPermaLink="false">66b1fa4509c44225ad2c3904</guid>
                
                    <category>
                        <![CDATA[ Google Chrome ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Games ]]>
                    </category>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ internet ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Abigail Rennemeyer ]]>
                </dc:creator>
                <pubDate>Wed, 25 Dec 2019 21:02:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/01/image-27-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Several years ago, Google added a fun little Easter egg to Chrome: if your internet went down and you tried to visit a web page, you'd see the message "Unable to connect to the Internet"  or "No internet" with a little pixilated dinosaur next to it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/image-26-opt.png" alt="Image" width="600" height="400" loading="lazy">
<em>Dino says no internet today</em></p>
<p>Many people probably just thought the dinosaur was a cute little icon to keep them company while their connection was down. But then someone pressed the space bar. And the dino started running.</p>
<p>This little Easter egg has become a beloved game. But what if you just want to play it (careful, it's addictive) when you're online and need a break? In this article, you'll learn how to play the game when you're both off and online.</p>
<h2 id="heading-how-to-play-the-chrome-dino-or-trex-game-offline">How to play the Chrome dino or Trex game offline</h2>
<p>If your internet is down, just open Chrome. Or if you're already in Chrome, try to visit any web page. You'll see that little dinosaur next to its error message.</p>
<p>Simply press the space bar (or up arrow) and the dino will start running. Press the up arrow to jump over the obstacles (like cacti) in your path. The longer you hold the up arrow, the higher dino will jump.</p>
<p>If you need to duck under something, press the down arrow.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/image-27-opt.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The longer you play, the faster dino runs/the ground moves. Once you crash into something, the game is over and you have to restart (your score resets, too). You can play again by hitting the space bar.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/image-28-opt-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-play-the-chrome-dino-or-trex-game-online">How to play the Chrome dino or Trex game online</h2>
<p>Great, you have some entertainment while waiting for your internet to come back up. But what if you want to play it while online? There are a few ways to do so.</p>
<h3 id="heading-visit-the-dino-url">Visit the dino URL</h3>
<p>The simplest way to play the game online is by visiting this URL: <a target="_blank">chrome://dino/</a>. Just access that link and voilà, there's your little dino and "no internet" message.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/image-29.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once you see that message, just hit the spacebar and start jumping over cacti.</p>
<p>There is also an unofficial <a target="_blank" href="https://chromedino.com/">Chrome Dino website</a> where you can play a replica of the game with different sound and graphics themes, such as this Super Mario Bros. theme:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/running-mario-opt.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Or this Batman theme with 1960s Batman sound effects:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/batman-opt.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-bonus-another-way-to-find-the-game">Bonus: Another way to find the game</h3>
<p>Maybe you didn't get the dino error message when your internet was down. Or maybe you don't want to purposely turn off your wifi to play the game. </p>
<p>So, if you have internet but want to disable your connection in Chrome dev tools, hit F12 to open up dev tools.</p>
<p>Click the "Network" tab at the top towards the right, and then look for the Online/Offline tab, second row down:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/image-30-cropped.png" alt="Image" width="600" height="400" loading="lazy">
<em>Look for the little dropdown arrow next to where it says "online".</em></p>
<p>Look for the little dropdown arrow, click it, and select "Offline" (instead of "Online", where it should be set if you currently have a connection).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/image-31-cropped.png" alt="Image" width="600" height="400" loading="lazy">
<em>Toggle to "Offline"</em></p>
<p>Once you've done that, if you try to visit a web page, you'll get the dinosaur! You can exit dev tools and hit the space bar, as usual, to get dino running.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/image-32-cropped.png" alt="Image" width="600" height="400" loading="lazy">
<em>Play away!</em></p>
<p>Now you know how to find the dino/Trex game without AND with internet connectivity. Have fun!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Robotic Influencers of our Future: Experimenting With a Minecraft-playing, Twitch-streaming Robot ]]>
                </title>
                <description>
                    <![CDATA[ By Minja Axelsson In this article, I'll discuss how we reached young audiences by combining robotics with e-sports. What on Earth? Ever heard of anything like it before? Me neither. The robot was created as part of Futurice’s project with Yle, the na... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-robotic-influencers-of-our-future-a-minecraft-playing-twitch-streaming-robot/</link>
                <guid isPermaLink="false">66d460423a8352b6c5a2aaae</guid>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ minecraft ]]>
                    </category>
                
                    <category>
                        <![CDATA[ robotics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ streaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Twitch ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 01 Oct 2019 21:26:15 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/10/twitchrobot.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Minja Axelsson</p>
<p>In this article, I'll discuss how we reached young audiences by combining robotics with e-sports.</p>
<h2 id="heading-what-on-earth">What on Earth?</h2>
<p>Ever heard of anything like it before? Me neither. The robot was created as part of <a target="_blank" href="https://www.futurice.com/">Futurice</a>’s project with <a target="_blank" href="https://yle.fi/">Yle</a>, the national broadcast company of Finland. </p>
<p>Yle produces content for TV, radio, and the web. It has a broad reach of older audiences, but has had trouble reaching younger ones. The goal of this project was to use new technology to reach young audiences — specifically teenagers.</p>
<p>Yle’s content has traditionally been non-participatory: the performers perform, and the audience watches. However, younger audiences generally view content that is more participatory, such as YouTube videos or streams. </p>
<p>We wanted to create participatory content — the performer should interact with their audience. Yle’s journalists specialized in teenage audiences pointed out that gaming and e-sports are popular content. We realized that gaming was the perfect context for this: the audience could play together with the performer. We wanted to explore what an entertainer, or even influencer of the future could look like. So why not create a streaming robot gamer?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/0_QW08nV9GgKS589PJ.png" alt="Image" width="600" height="400" loading="lazy">
<em>Yle’s journalists and Futurice’s roboticists coming up with the idea of a robot gamer</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/0_XdFOgvs4DhZVaHnW.png" alt="Image" width="600" height="400" loading="lazy">
<em>First drafts</em></p>
<h2 id="heading-what-was-this-robot-like">What Was This Robot Like?</h2>
<p>We chose two games for the robot to play: Flappy Bird and Minecraft.</p>
<p>Flappy Bird was a cult game that had a brief period of extreme popularity in 2014. We chose Flappy Bird because the mechanisms of the game are simple, and allowed for the game to be played with machine learning. We wanted to try a <a target="_blank" href="https://xviniette.github.io/FlappyLearning/">neuroevolution algorithm</a>, which evolved new birds into the game based on which birds did best in the previous generation. This way we could see how the audience reacted when a computer was playing the game.</p>
<p>We chose Minecraft for its communal features, which allow interaction between players. Players can co-operate or fight each other, trade with each other, and chat with each other. They can “grief” each other — i.e. be a nuisance. Players can also mine materials, and turn them into items, or even build cities. They can store precious things, farm the land, herd animals, and fight monsters. </p>
<p>Minecraft also has a material called redstone, which players can use to build logic. Effectively, players can build an entire computer inside of Minecraft. Poetic, eh?</p>
<p>For playing Minecraft, we decided that a human should control the robot. The game is complicated, and having authentic interactions with other players would require a human on the other end.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/0_zNxCX_zKJ3ikRM-y.png" alt="Image" width="600" height="400" loading="lazy">
<em>Flappy Bird and the robot</em></p>
<p>Our team of Yle’s journalists and Futurice roboticists defined some clear advantages for using a robot in this context:</p>
<ul>
<li>A robot is tireless — it can play forever, and provide content 24/7. It’s an ideal streamer.</li>
<li>A robot can be gender neutral. Gamers and gaming audiences are typically male, but a gender neutral robot could potentially attract more diverse audiences.</li>
<li>A robot can reflect gamers’ behaviour, stirring emotions. Gaming culture is often aggressive. The robot could be aggressive in turn, making gamers reflect on their own behaviour.</li>
<li>A robot can interact within the game and chat simultaneously. Humans are limited to one output, a robot can have several.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/1_-eTZqndK5kdFckQ5-lXpMg.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Testing our streaming equipment and having problems with interference from the robot’s face screen.</em></p>
<p>We decided on a six hour gaming session, alternating between Minecraft and Flappy Bird. To nail down the user experience for the session, we defined guidelines for our design of the robot:</p>
<ul>
<li>Experimental user experience — the user should be able to explore within the interaction with the robot.</li>
<li>Streamers are usually strong characters. The robot is a character with a strong personality.</li>
<li>The robot can cause “WTF?” reactions in players. We wanted the experience to be memorable, rather than bland.</li>
<li>The culture and space of online gaming is unique, and should be designed for.</li>
</ul>
<p>Based on these guidelines, we created the character IQ_201. IQ_201 is based on aggressive online gamers that are convinced of their own superior intelligence (see <a target="_blank" href="https://knowyourmeme.com/memes/200-iq">this meme about having an IQ over 200</a>). The robot would be rude and reactive, meant to get a reaction out of adolescents interacting with it.</p>
<p>Before implementation, the team also wanted to take into account some ethical considerations:</p>
<ul>
<li>Transparency about how the robot is operated is needed. If this robot was going to be put into production, users should be able to find information on how it works.</li>
<li>The robot should treat all the players the same. This was also part of the decision to make the robot appear gender neutral. And due to the sometimes angry, hateful, even racist or sexist culture of gaming, we needed to design the robot’s personality carefully. It could be out-there, even rude, but never hateful. We didn’t want any heated gaming moments.</li>
<li>The robot should be rude, but not too over-the-top.</li>
<li>The chat needed to be moderated. As stated, gaming culture can be toxic. We wanted to keep a careful eye on both the Minecraft and Twitch chats, to ensure no shenanigans would go on.</li>
</ul>
<p>To fulfill all these requirements, we selected the <a target="_blank" href="https://www.furhatrobotics.com/">Furhat robot</a>. The Furhat robot had a relatively easy-to-use teleoperation interface, which allowed for the user to input text to be turned into the robot’s speech, as well as perform gestures at the click of a button.</p>
<h2 id="heading-flowers-and-violence">Flowers and Violence</h2>
<p>We had a 6 hour stream, starting at 2pm and ending at 8pm. We alternated between games: 2-3pm was Flappy Bird, 3-5pm Minecraft, 5-6pm Flappy Bird, then 6-8pm Minecraft again. This schedule allowed the robot operators playing Minecraft to have a much-needed break in the middle.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/twitchrobot-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Our robot</em></p>
<p>In the beginning, a few people joined. Gradually, we gained more and more people. We reached our peak at 4:20 — 49 simultaneous viewers on Twitch. Overall, we had 431 unique viewers. In Minecraft, there were around 30 active players. Considering how minimal our advertising was (one forum post and a few tweets), we were pleasantly surprised by the turnout.</p>
<p>The Minecraft sessions were directed by two robot operators (myself and another Minja). The other Minja played Minecraft, and I operated the robot’s voice and gestures. A third person was answering messages on chat.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/8kKPoYx7rMs" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>Minecraft was overwhelming. The robot’s provocative character provoked teenagers into repeatedly killing it. After fleeing to the mountains to be with the llamas a couple of times and being killed yet again, we modified the robot’s behaviour to be more friendly. We wanted to create more constructive interactions.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/0_pMMw-X8ZYwIOH_cU.png" alt="Image" width="600" height="400" loading="lazy">
<em>Two Minjas as robot operators</em></p>
<p>Toward the end of the second Minecraft stream, teenagers were cooperating with the robot. They protected it from the few aggressive players that were left, and gave it gifts such as flowers. Some even complimented the robot directly, to make it happy. The players started following the robot, agreeing to cooperate when it initiated building a lighthouse. They also built a house, and captured and named a llama: IQ_201 Junior.</p>
<p>There were two clear factions in the game: some were intent to kill the robot throughout the entire game, and some protected it throughout. Some became more comfortable with the robot as the stream went on, switching sides. Either way, the robot aroused strong emotions. Teenagers sought out genuine interaction with it. No-one ignored the robot, or was bored.</p>
<p>Discussions about how the robot worked were had throughout the stream. No-one asked the robot itself though, maybe out of respect or fear of annoying it. Discussions focused on whether the robot was “real”, i.e. whether it was truly automatic, or a human was operating it. Was it typing with actual physical hands? Or had it “hacked into” the game and was playing via code?</p>
<h2 id="heading-i-will-miss-you-robot">“I Will Miss You Robot!”</h2>
<p>16 people responded to our survey afterward. 80% of players were under 18, most were 13 to 15-year-olds. 80% of players interacted with the robot. This was extremely positive, we succeeded in making a robot that was compelling to users. 75% of players rated the robot as 3 or above, out of 5.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/0_7k1TlGnl986zyBKQ.png" alt="Image" width="600" height="400" loading="lazy">
<em>Viewers over time</em></p>
<p>We collected comments from the players from the survey, as well as the Minecraft game chat. They are translated from Finnish, and reflect some of the thoughts our players had on the robot.</p>
<h4 id="heading-the-critical-first">The critical first:</h4>
<p><strong>“It was pretty fun and cool. But it somehow felt like a set-up.” [Referring to the robot possibly having a human operator]</strong></p>
<p>A lot of players were wondering how the robot actually worked. This comment brings us back to the ethical consideration we talked about earlier: transparency about how the robot was operated. </p>
<p>Though we intended to be transparent at first, we decided to not inform users of the robot’s teleoperated nature for this first pilot. We made this choice because we wanted to keep the “suspension of disbelief” of the user active, meaning that we wanted the participants to play along with the fact they were talking to a “real robot” (an autonomous robot) (Duffy &amp; Zawieska, 2012). </p>
<p>The negative response we received regarding the unclarity on the robot’s functioning made it clear to us that if this pilot were extended, it is highly important to be more transparent. It is possible to hold suspension of disbelief and be honest of the robot’s operation simultaneously (we do all know that television shows are not reality, after all).</p>
<p><strong>“The robot was a bit simple in certain things, and sometimes talked meanly to people, and was condescending. This was a bit anxiety inducing… Was this intentional?”</strong></p>
<p>Some players felt that the robot’s rude behaviour crossed the boundary into condescending. They wished that the robot would be more considerate in the future. This indicates that even a robot can hurt feelings. In future versions, making IQ_201 more empathic, and less focused on the superiority of robots over humans, could have positive results.</p>
<p><strong>“The robot looked a bit blue in the face, and its voice was a bit weird.”</strong></p>
<p>Two teenagers did not enjoy the robot’s appearance and voice. One remarked especially about its blue face, asking why we did not make it “normal colored”. </p>
<p>This may have been due to the robot falling into the “uncanny valley” for these players. Uncanny valley is a theory developed by robotics researcher Masahiro Mori (Mori et al., 2012). His theory posits that as the appearance of a robot approaches human-likeness, there is a dip when the appearance gets very close. Zombies and corpses fall into this valley. </p>
<p>To get rid of this effect with our robot, it could be wise to alter the robot’s appearance and voice in future solutions.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/0_g5B15D6hFSmG0bbi.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Uncanny Valley by Masahiro Mori. Wikimedia commons.</em></p>
<h4 id="heading-and-then-the-positive">And then the positive:</h4>
<p><strong>“It was really interesting gaming with the robot. :) Hopefully in the future we can have this type of event again. :)”</strong></p>
<p>The majority of the teenagers enjoyed playing with the robot, and watching the stream. Their feedback complimented the robot’s sense of humour, and its playing skills. A continuation of the pilot would surely find an interested audience.</p>
<p><strong>[to the robot] “Some people have trouble with new things. In this case, these players are having trouble with a robot, since you’re new.”</strong></p>
<p>This player consoled the robot in-game, as other players were giving it a hard time by continuously killing it. This comment was moving: the player felt bad for the robot, and thought the robot might feel bad as well, attempting to change that. This is a clear empathic response toward the robot.</p>
<p><strong>[to the robot] “I will miss you robot!”</strong></p>
<p>A few players gave the robot heartfelt goodbyes when it left Minecraft. These players found the robot approachable, and even formed an emotional bond with it. This means we succeeded in creating a compelling character, even during what was only a 6 hour stream. </p>
<p>For future builds of the robot, the players should be informed how the robot operates. This could help them calibrate an appropriate level of emotional bond to the robot.</p>
<h2 id="heading-are-robotic-influencers-our-future">Are Robotic Influencers Our Future?</h2>
<p>Players took an active interest in the robot. They approached it, interacted with it, and formed opinions on it. The robot also provoked emotional reactions — both positive and negative. Some participants really loved the robot and wished for more interaction in the future, and some were heavily critical. </p>
<p>This indicates that robot influencers have the capacity to affect our emotions — whether this capacity will ever reach the level of human entertainers, I do not know. Whether that is desirable, I also do not know.</p>
<p>What positively surprised me was that the young user base of the robot were media literate: they critically examined the robot’s mode of operation. The players had a good idea of what is possible with AI today, and what is not. They were not easily duped.</p>
<p>This makes me hopeful for our future, whether it contains robotic entertainers or not. When viewers remain critical, they can understand that robots are machines with no actual emotional capacity, even if viewers do choose to suspend disbelief. </p>
<p>Interacting with the robot can be though of as a form of <a target="_blank" href="https://en.wikipedia.org/wiki/Parasocial_interaction">parasocial interaction</a> for the viewer — where the viewer may feel that their relationship with the robot is close — even though it is not truly reciprocal. This in itself is not necessarily harmful, as long as we are honest about what the relationship truly is. We should understand that robots are putting on a performance to elicit emotions in us — like human entertainers do</p>
<p><a target="_blank" href="https://areena.yle.fi/1-50168989?source=post_page-----702735f678a8----------------------"><strong>A video about the project.</strong></a></p>
<p>First published on <a target="_blank" href="https://towardsdatascience.com/the-robotic-influencers-of-our-future-a-minecraft-playing-twitch-streaming-robot-702735f678a8">Towards Data Science.</a></p>
<hr>
<p><em>Duffy, B. R., &amp; Zawieska, K. (2012, September). Suspension of disbelief in social robotics. In 2012 IEEE RO-MAN: The 21st IEEE International Symposium on Robot and Human Interactive Communication (pp. 484–489). IEEE.</em></p>
<p><em>Mori, M., MacDorman, K. F., &amp; Kageki, N. (2012). The uncanny valley: The original essay by Masahiro Mori. IEEE Spectrum, 98–100.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to use AI to play Sonic the Hedgehog. It’s NEAT! ]]>
                </title>
                <description>
                    <![CDATA[ By Vedant Gupta Generation after generation, humans have adapted to become more fit with our surroundings. We started off as primates living in a world of eat or be eaten. Eventually we evolved into who we are today, reflecting modern society. Throug... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-ai-to-play-sonic-the-hedgehog-its-neat-9d862a2aef98/</link>
                <guid isPermaLink="false">66c35585a6c3eebadae8d2d9</guid>
                
                    <category>
                        <![CDATA[ Artificial Intelligence ]]>
                    </category>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Reinforcement Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 02 Apr 2019 16:28:11 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*RYknGhjxRw8arZlI-_ib4A.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Vedant Gupta</p>
<p>Generation after generation, humans have adapted to become more fit with our surroundings. We started off as primates living in a world of eat or be eaten. Eventually we evolved into who we are today, reflecting modern society. Through the process of evolution we become smarter. We are able to work better with our environment and accomplish what we need to.</p>
<p>The concept of learning through evolution can also be applied to Artificial Intelligence. We can train AIs to perform certain tasks using NEAT, Neuroevolution of Augmented Topologies. Simply put, NEAT is an algorithm which takes a batch of AIs (genomes) attempting to accomplish a given task. The top performing AIs “breed” to create the next generation. This process continues until we have a generation which is capable of completing what it needs to.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/kB3DscigQ-nDtQhS5em32jfdsFdAKp236CXt" alt="Image" width="600" height="337" loading="lazy">
<em>Clip of AI playing STH</em></p>
<p>NEAT is amazing because it eliminates the need for pre-existing data required to train our AIs. Using the power of NEAT and OpenAI’s Gym Retro I trained an AI to play Sonic the Hedgehog for the SEGA Genesis. Let’s learn how!</p>
<h3 id="heading-a-neat-neural-network-python-implementation">A NEAT Neural Network (Python Implementation)</h3>
<h4 id="heading-github-repository">GitHub Repository</h4>
<p><a target="_blank" href="https://github.com/Vedant-Gupta523/sonicNEAT"><strong>Vedant-Gupta523/sonicNEAT</strong></a><br><a target="_blank" href="https://github.com/Vedant-Gupta523/sonicNEAT">_Contribute to Vedant-Gupta523/sonicNEAT development by creating an account on GitHub._github.com</a></p>
<p><strong>Note:</strong> All of the code in this article and the repo above is a slightly modified version of Lucas Thompson's Sonic AI Bot Using Open-AI and NEAT <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-ai-to-play-sonic-the-hedgehog-its-neat-9d862a2aef98/Sonic%20AI%20Bot%20Using%20Open-AI%20and%20NEAT%20Tutorial">YouTube tutorials</a> and <a target="_blank" href="https://gitlab.com/lucasrthompson/Sonic-Bot-In-OpenAI-and-NEAT">code</a>.</p>
<h4 id="heading-understanding-openai-gym">Understanding OpenAI Gym</h4>
<p>If you are not already familiar with OpenAI Gym, look through the terminology below. They will be used frequently throughout the article.</p>
<p><strong>agent —</strong> The AI player. In this case it will be Sonic.</p>
<p><strong>environment —</strong> The complete surroundings of the agent. The game environment.</p>
<p><strong>action —</strong> Something the agent has the option of doing (i.e. move left, move right, jump, do nothing).</p>
<p><strong>step —</strong> Performing 1 action.</p>
<p><strong>state —</strong> A frame of the environment. The current situation the AI is in.</p>
<p><strong>observation —</strong> What the AI observes from the environment.</p>
<p><strong>fitness —</strong> How well our AI is performing.</p>
<p><strong>done —</strong> When the AI has completed its task or can’t continue any further.</p>
<h4 id="heading-installing-dependencies">Installing Dependencies</h4>
<p>Below are GitHub links for OpenAI and NEAT with installation instructions.</p>
<p><strong>OpenAI</strong>: <a target="_blank" href="https://github.com/openai/retro">https://github.com/openai/retro</a></p>
<p><strong>NEAT</strong>:<a target="_blank" href="https://github.com/CodeReclaimers/neat-python">https://github.com/CodeReclaimers/neat-python</a></p>
<p><strong>Pip install</strong> libraries such as cv2, numpy, pickle etc.</p>
<h4 id="heading-import-libraries-and-set-environment">Import libraries and set environment</h4>
<p>To start, we need to import all of the modules we will use:</p>
<pre><code class="lang-py"><span class="hljs-keyword">import</span> retro
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> cv2
<span class="hljs-keyword">import</span> neat
<span class="hljs-keyword">import</span> pickle
</code></pre>
<p>We will also define our environment, consisting of the game and the state:</p>
<pre><code class="lang-py">env = retro.make(game = <span class="hljs-string">"SonicTheHedgehog-Genesis"</span>, state = <span class="hljs-string">"GreenHillZone.Act1"</span>)
</code></pre>
<p>In order to train an AI to play Sonic the Hedgehog, you will need the game’s ROM (game file). The simplest way to get it is by purchasing the game off of <a target="_blank" href="https://store.steampowered.com/app/71113/Sonic_The_Hedgehog/">Steam</a> for $5. You could also find free find downloads of the ROM online, however it is illegal, so don’t do this.</p>
<p>In the OpenAI repository at <strong>retro/retro/data/stable/</strong> you will find a folder for Sonic the Hedgehog Genesis. Place the game’s ROM here and make sure it is called rom.md. This folder also contains .state files. You can choose one and set the state parameter equal to it. I chose GreenHillZone Act 1 since it is the very first level of the game.</p>
<h4 id="heading-understanding-datajson-and-scenariojson">Understanding data.json and scenario.json</h4>
<p>In the Sonic the Hedgehog folder you will have these two files:</p>
<p><strong>data.json</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"info"</span>: {
    <span class="hljs-attr">"act"</span>: {
      <span class="hljs-attr">"address"</span>: <span class="hljs-number">16776721</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"|u1"</span>
    },
    <span class="hljs-attr">"level_end_bonus"</span>: {
      <span class="hljs-attr">"address"</span>: <span class="hljs-number">16775126</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"|u1"</span>
    },
    <span class="hljs-attr">"lives"</span>: {
      <span class="hljs-attr">"address"</span>: <span class="hljs-number">16776722</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"|u1"</span>
    },
    <span class="hljs-attr">"rings"</span>: {
      <span class="hljs-attr">"address"</span>: <span class="hljs-number">16776736</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"&gt;u2"</span>
    },
    <span class="hljs-attr">"score"</span>: {
      <span class="hljs-attr">"address"</span>: <span class="hljs-number">16776742</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"&gt;u4"</span>
    },
    <span class="hljs-attr">"screen_x"</span>: {
      <span class="hljs-attr">"address"</span>: <span class="hljs-number">16774912</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"&gt;u2"</span>
    },
    <span class="hljs-attr">"screen_x_end"</span>: {
      <span class="hljs-attr">"address"</span>: <span class="hljs-number">16774954</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"&gt;u2"</span>
    },
    <span class="hljs-attr">"screen_y"</span>: {
      <span class="hljs-attr">"address"</span>: <span class="hljs-number">16774916</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"&gt;u2"</span>
    },
    <span class="hljs-attr">"x"</span>: {
      <span class="hljs-attr">"address"</span>: <span class="hljs-number">16764936</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"&gt;i2"</span>
    },
    <span class="hljs-attr">"y"</span>: {
      <span class="hljs-attr">"address"</span>: <span class="hljs-number">16764940</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"&gt;u2"</span>
    },
    <span class="hljs-attr">"zone"</span>: {
      <span class="hljs-attr">"address"</span>: <span class="hljs-number">16776720</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"|u1"</span>
    }
  }
}
</code></pre>
<p><strong>scenario.json</strong></p>
<pre><code class="lang-py">{
  <span class="hljs-string">"done"</span>: {
    <span class="hljs-string">"variables"</span>: {
      <span class="hljs-string">"lives"</span>: {
        <span class="hljs-string">"op"</span>: <span class="hljs-string">"zero"</span>
      }
    }
  },
  <span class="hljs-string">"reward"</span>: {
    <span class="hljs-string">"variables"</span>: {
      <span class="hljs-string">"x"</span>: {
        <span class="hljs-string">"reward"</span>: <span class="hljs-number">10.0</span>
      }
    }
  }
}
</code></pre>
<p>Both these files contain important information pertaining to the game and its training.</p>
<p>As it sounds, the data.json file contains information/data on different game specific variables (i.e. Sonic’s x-position, number of lives he has, etc.).</p>
<p>The scenario.json file allows us to perform actions in sync with the values of the data variables. For example we can reward Sonic 10.0 every time his x-position increases. We could also set our done condition to true when Sonic’s lives hit 0.</p>
<h4 id="heading-understanding-neat-feedforward-configuration">Understanding NEAT feedforward configuration</h4>
<p>The config-feedforward file can be found in my GitHub repository linked above. It acts like a settings menu to set up our training. To point out a few simple settings:</p>
<pre><code class="lang-py">fitness_threshold     = <span class="hljs-number">10000</span> <span class="hljs-comment"># How fit we want Sonic to become</span>
pop_size              = <span class="hljs-number">20</span> <span class="hljs-comment"># How many Sonics per generation</span>
num_inputs            = <span class="hljs-number">1120</span> <span class="hljs-comment"># Number of inputs into our model</span>
num_outputs           = <span class="hljs-number">12</span> <span class="hljs-comment"># 12 buttons on Genesis controller</span>
</code></pre>
<p>There are tons of settings you can experiment with to see how it effects your AI’s training! To learn more about NEAT and the different settings in the feedfoward configuration, I would highly recommend reading the documentation <a target="_blank" href="https://neat-python.readthedocs.io/en/latest/">here</a></p>
<h4 id="heading-putting-it-all-together-creating-the-training-file">Putting it all together: Creating the Training File</h4>
<p><strong>Setting up configuration</strong></p>
<p>Our feedforward configuration is defined and stored in the variable config.</p>
<pre><code class="lang-py">config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, <span class="hljs-string">'config-feedforward'</span>)
</code></pre>
<p><strong>Creating a function to evaluate each genome</strong></p>
<p>We start by creating the function, eval_genomes, which will evaluate our genomes (a genome could be compared to 1 Sonic in a population of Sonics). For each genome we reset the environment and take a random action</p>
<pre><code class="lang-py"><span class="hljs-keyword">for</span> genome_id, genome <span class="hljs-keyword">in</span> genomes:
        ob = env.reset()
        ac = env.action_space.sample()
</code></pre>
<p>We will also record the game environment’s length and width and color. We divide the length and width by 8.</p>
<pre><code class="lang-py">inx, iny, inc = env.observation_space.shape
inx = int(inx/<span class="hljs-number">8</span>)
iny = int(iny/<span class="hljs-number">8</span>)
</code></pre>
<p>We create a <a target="_blank" href="https://searchenterpriseai.techtarget.com/definition/recurrent-neural-networks">recurrent neural network</a> (RNN) using the NEAT library and input the genome and our chosen configuration.</p>
<pre><code class="lang-py">net = neat.nn.recurrent.RecurrentNetwork.create(genome, config)
</code></pre>
<p>Finally, we define a few variables: current_max_fitness (the highest fitness in the current population), fitness_current (the current fitness of the genome), frame (the frame count), counter (to count the number of steps our agent takes), xpos (the x-position of Sonic), and done (whether or not we have reached our fitness goal).</p>
<pre><code class="lang-py">current_max_fitness = <span class="hljs-number">0</span>
fitness_current = <span class="hljs-number">0</span>
frame = <span class="hljs-number">0</span>
counter = <span class="hljs-number">0</span>
xpos = <span class="hljs-number">0</span>
done = <span class="hljs-literal">False</span>
</code></pre>
<p>While we have not reached our done requirement, we need to run the environment, increment our frame counter, and shape our observation to mimic that of the game (still for each genome).</p>
<pre><code class="lang-py">env.render()
frame += <span class="hljs-number">1</span>
ob = cv2.resize(ob, (inx, iny))
ob = cv2.cvtColor(ob, cv2.COLOR_BGR2GRAY)
ob = np.reshape(ob, (inx,iny))
</code></pre>
<p>We will take our observation and put it in a one-dimensional array, so that our RNN can understand it. We receive our output by feeding this array to our RNN.</p>
<pre><code class="lang-py">imgarray = []
imgarray = np.ndarray.flatten(ob)
nnOutput = net.activate(imgarray)
</code></pre>
<p>Using the output from the RNN our AI takes a step. From this step we can extract fresh information: a new observation, a reward, whether or not we have reached our done requirement, and information on variables in our data.json (info).</p>
<pre><code class="lang-py">ob, rew, done, info = env.step(nnOutput)
</code></pre>
<p>At this point we need to evaluate our genome’s fitness and whether or not it has met the done requirement.</p>
<p>We look at our “x” variable from data.json and check if it has surpassed the length of the level. If it has, we will increase our fitness by our fitness threshold signifying we are done.</p>
<pre><code class="lang-py">xpos = info[<span class="hljs-string">'x'</span>]

<span class="hljs-keyword">if</span> xpos &gt;= <span class="hljs-number">10000</span>:
        fitness_current += <span class="hljs-number">10000</span>
        done = <span class="hljs-literal">True</span>
</code></pre>
<p>Otherwise, we will increase our current fitness by the reward we earned from performing the step. We also check if we have a new highest fitness and adjust the value of our current_max_fitness accordingly.</p>
<pre><code class="lang-py">fitness_current += rew

<span class="hljs-keyword">if</span> fitness_current &gt; current_max_fitness:
        current_max_fitness = fitness_current
        counter = <span class="hljs-number">0</span>
<span class="hljs-keyword">else</span>:
        counter += <span class="hljs-number">1</span>
</code></pre>
<p>Lastly, we check if we are done or if our genome has taken 250 steps. If so, we print information on the genome which was simulated. Otherwise we keep looping until one of the two requirements has been satisfied.</p>
<pre><code class="lang-py"><span class="hljs-keyword">if</span> done <span class="hljs-keyword">or</span> counter == <span class="hljs-number">250</span>:
        done = <span class="hljs-literal">True</span>
        print(genome_id, fitness_current)

genome.fitness = fitness_current
</code></pre>
<p><strong>Defining the population, printing training stats, and more</strong></p>
<p>The absolute last thing we need to do is define our population, print out statistics from our training, save checkpoints (in case you want to pause and resume training), and pickle our winning genome.</p>
<pre><code class="lang-py">p = neat.Population(config)

p.add_reporter(neat.StdOutReporter(<span class="hljs-literal">True</span>))
stats = neat.StatisticsReporter()
p.add_reporter(stats)
p.add_reporter(neat.Checkpointer(<span class="hljs-number">1</span>))

winner = p.run(eval_genomes)

<span class="hljs-keyword">with</span> open(<span class="hljs-string">'winner.pkl'</span>, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> output:
    pickle.dump(winner, output, <span class="hljs-number">1</span>)
</code></pre>
<p>All that’s left is the matter of running the program and watching Sonic slowly learn how to beat the level!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/caPrOTLL9OmL9C2V3BLMmUYtx1g0ckxZF1wu" alt="Image" width="600" height="337" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/FsO5NOjcc5S9cQiDjO56TbQLlOQIzFfdwmwc" alt="Image" width="600" height="337" loading="lazy">
<em>Earlier generation vs Later generation</em></p>
<p><strong>To see all of the code put together check out the Training.py file in my GitHub repository.</strong></p>
<h4 id="heading-bonus-parallel-training">Bonus: Parallel Training</h4>
<p>If you have a multi-core CPU you can run multiple training simulations at once, exponentially increasing the rate at which you can train your AI! Although I will not go through the specifics on how to do this in this article, I highly suggest you check the <strong>sonicTraning.py</strong> implementation in my GitHub repository.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>That’s all there is to it! With a few adjustments, this framework is applicable to any game for the NES, SNES, SEGA Genesis, and more. If you have any questions or you just want to say hello, feel free to email me at vedantgupta523[at]gmail[dot]com ?</p>
<p>Also, be sure to check out Lucas Thompson's Sonic AI Bot Using Open-AI and NEAT <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-ai-to-play-sonic-the-hedgehog-its-neat-9d862a2aef98/Sonic%20AI%20Bot%20Using%20Open-AI%20and%20NEAT%20Tutorial">YouTube tutorials</a> and <a target="_blank" href="https://gitlab.com/lucasrthompson/Sonic-Bot-In-OpenAI-and-NEAT">code</a> to see what originally inspired this article.</p>
<h3 id="heading-key-takeaways">Key Takeaways</h3>
<ol>
<li><strong>Neuroevolution of Augmenting Topologies (NEAT)</strong> is an algorithm used to train AI to perform certain tasks. It is modeled after genetic evolution.</li>
<li><strong>NEAT</strong> eliminates the need for pre-existing data when training AI.</li>
<li>The process of implementing <strong>OpenAI</strong> and <strong>NEAT</strong> using Python to train an AI to play any game.</li>
</ol>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Ultimate Beginners Guide To Game Development In Unity ]]>
                </title>
                <description>
                    <![CDATA[ By Hugo Dolan Unity is a great tool for prototyping everything from games, to interactive visualisations. In this article, we run through all you need to know to get started using Unity. First, a little bit about me: I’m a hobbyist unity developer, 3... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-ultimate-beginners-guide-to-game-development-in-unity-f9bfe972c2b5/</link>
                <guid isPermaLink="false">66d45f31b6b7f664236cbdca</guid>
                
                    <category>
                        <![CDATA[ Game Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unity ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 21 Mar 2019 20:27:47 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca41d740569d1a4ca6043.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Hugo Dolan</p>
<p>Unity is a great tool for prototyping everything from games, to interactive visualisations. In this article, we run through all you need to know to get started using Unity.</p>
<p>First, a little bit about me: I’m a hobbyist unity developer, 3d modeler and graphic designer who’s worked with Unity and Blender for over 5 years. I’m now a Financial Maths student at University College Dublin, and occasionally I do freelance graphic design, web prototyping, and game prototyping.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Q-bD3OdyDZX2X2cmqgyyRIFwRpy9mngdYAtC" alt="Image" width="800" height="630" loading="lazy">
_Concept art is one of the earliest phases in the game dev process, over the last 5 years i’ve got a lot of exposure to all areas of game design. Check out my [Portfolio ](http://hugodolan.com/portfolio" rel="noopener" target="<em>blank" title=")of Graphic, UX, Concept Art, Game Dev etc…</em></p>
<h3 id="heading-introduction">Introduction</h3>
<p>This article is aimed at anyone who has never used Unity before, but has some previous experience programming or in web design / development. By the end of this article, you should have a good general overview of the engine as well as all the necessary functions and code to start making a basic game.</p>
<h3 id="heading-why-unity">Why Unity?</h3>
<h4 id="heading-if-you-want-to-make-games">If you want to make games</h4>
<p>There’s really very few options when it comes to Indie Game development. The three main choices if you want to build games are Unreal, Unity or GameMaker.</p>
<p>Unity is probably the least opinionated of the 3 platforms. It gives you a very raw product out of the box, but is highly flexible, well-documented, and highly extensible to build pretty much any genre of game you can think of.</p>
<p>There are plenty of highly successful games such as Escape from Tarkov (FPS), Monument Valley (Puzzler), and This War of Mine (Strategy / Survival) all built in Unity.</p>
<p>In reality the engine you build your first game on is probably not critical, so my advice is just to pick one and go with it.</p>
<h4 id="heading-if-you-want-to-prototype-user-experiences">If you want to prototype user experiences</h4>
<p>Since unity is just an engine with a bunch of physics, animation, and real time 3d rendering, it’s also a great space to make fully fledged interactive prototypes for UX studies.</p>
<p>Unity has full support for VR and AR and hence could be a great tool for exploring architecture, automations and simulations with clients.</p>
<h3 id="heading-sections-to-this-article"><strong>Sections to this article</strong></h3>
<ul>
<li><strong>Why Unity?</strong></li>
<li><strong>Unity Editor Window</strong></li>
<li><strong>Unity Game Objects</strong></li>
<li><strong>Unity Builtin Components</strong></li>
<li><strong>Creating Custom Components</strong></li>
<li><strong>Structure of a MonoBehaviour</strong></li>
<li><strong>Manipulating GameObjects</strong></li>
<li><strong>Raycasting</strong></li>
<li><strong>Collision detection</strong></li>
<li><strong>Advanced Features</strong></li>
<li><strong>Advice For Newcomers</strong></li>
<li><strong>Nice Resources and Communities</strong></li>
<li><strong>Conclusion</strong></li>
</ul>
<h3 id="heading-unity-editor-window"><strong>Unity editor window</strong></h3>
<p>The editor window is split up into a couple of sections. We will cover this very briefly as we will refer to it constantly throughout the article. If your familiar with this already just skip past!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/hOKvEBDHVZj2N1udUtho7ksnzXmcdbMTWAWh" alt="Image" width="800" height="498" loading="lazy"></p>
<blockquote>
<p><strong>Scene View:</strong> Allows placement and movement of GameObjects in the Scene</p>
<p><strong>Game View:</strong> Previews how the player will see the scene from the camera</p>
<p><strong>Inspector:</strong> Provide details on the selected GameObject in the scene.</p>
<p><strong>Assets / Project:</strong> All prefabs, textures, models, scripts etc are stored here</p>
<p><strong>Hierarchy:</strong> Enables nesting and structuring of GameObjects within the scene</p>
</blockquote>
<p>Now we’re good to start!</p>
<h3 id="heading-unity-game-objects">Unity Game Objects</h3>
<h4 id="heading-what-are-gameobjects">What are GameObjects</h4>
<p>GameObjects are the core building block of everything in the Unity games engine. The name almost gives it away:</p>
<blockquote>
<p>Anything you place within a scene in Unity must be wrapped in a ‘game object.’</p>
</blockquote>
<p>If you’ve got a web design background, you can think of GameObjects as being a lot like </p><div> elements! Extremely boring containers, but are highly extensible to create complex functionality or visuals.<p></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/vlXNfFyr4lsQgC-DL05daoOtSWT35ZFUcA1l" alt="Image" width="432" height="446" loading="lazy">
<em>I’ve lifted this straight out of the Unity editor window just to make this point.</em></p>
<p>Literally everything from particle effects, cameras, players, UI elements, … (the list goes on) is a GameObject.</p>
<h4 id="heading-creating-hierarchy">Creating Hierarchy</h4>
<p>Like a </p><div> in web development, a GameObject is also a container. Just as you nest <div>s to create varied and desirable layouts or abstractions you may wish to do the same with games objects.<p></p>
<blockquote>
<p>The logic behind nesting game objects is much the same as web development, I’ll give a few examples…</p>
</blockquote>
<p><strong>Clutter &amp; Efficiency</strong></p>
<blockquote>
<p><strong><em>Web Analogy:</em></strong> <em>You’ve got many similar elements which may be dynamically generated on the fly in response to user interaction and want to keep them tidy.</em></p>
<p><strong><em>Unity Translation:</em></strong> <em>Your building a Minecraft clone and you’ve loads of blocks in the scene, you need to add and remove ‘chunks’ of blocks from the scene for performance reasons. Thus having them parented to an empty GameObject for each chunk makes sense, as deleting the chunk parent removes all the children blocks.</em></p>
</blockquote>
<p><strong>Positioning</strong></p>
<blockquote>
<p><strong><em>Web Analogy:</em></strong> <em>You want to keep the position of the content contained ‘relative’ to the container and not to the web page.</em></p>
<p><strong><em>Unity Translation:</em></strong> <em>You’ve created a bunch of helper drones which hover around the player. You would really not rather write code to tell them to chase after the player, so instead you instantiate them as children of the player game object.</em></p>
</blockquote>
<h3 id="heading-unity-builtin-components">Unity Builtin Components</h3>
<h4 id="heading-the-actor-component-model">The Actor Component Model</h4>
<p>GameObjects on their own are pretty useless — as we’ve seen they’re pretty much just containers. In order to add functionality to them we have to add components, which are essentially scripts written in either C# or Javascript.</p>
<p>Unity works off an Actor Component model, put simply the GameObjects are the actors and the Components are your scripts.</p>
<p>If you’ve written any web apps before you’ll be familiar with the idea of creating small reusable components such as buttons, form elements, flexible layouts that have various different directives and customisable properties. Then assembling these small components into larger web pages.</p>
<p>The big advantage of this approach is the level of reusability and clearly defined communication channels between elements. Likewise in game development, we want to minimise the risk of unintended side effects. Small bugs tend to spiral out of control if you’re not careful, and are extremely difficult to debug. Thus creating small, robust and reusable components is critical.</p>
<h4 id="heading-key-built-in-components">Key Built-in Components</h4>
<p>I think it’s time for a few examples of the built in components provided by the Unity Games engine.</p>
<ul>
<li><strong>MeshFilter:</strong> Allows you to assign materials to a 3D mesh to a GameObject</li>
<li><strong>MeshRender:</strong> Allows you to assign materials to a 3D Mesh</li>
<li><strong>[Box | Mesh]Collider:</strong> Enables detection of GameObject during collisions</li>
<li><strong>Rigidbody:</strong> Enables realistic physic simulation to act on GameObjects with 3d Meshes and will be trigger detection events on box colliders</li>
<li><strong>Light:</strong> Illuminates portions of your scene</li>
<li><strong>Camera:</strong> Defines the player viewport to be attached to a GameObject</li>
<li>Various UI Canvas Components for displaying GUIs</li>
</ul>
<p>There are loads more, but these are the main ones you’ll need to get familiar with. One tip is that you can access all the docs for these through the unity manual and scripting reference offline wherever you are:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/CNB5Rb4DWImRiHh04xThXYtZnojyCj5OJJ1f" alt="Image" width="704" height="196" loading="lazy">
<em>Just click on the help section, the docs in general are pretty good</em></p>
<h3 id="heading-creating-custom-components">Creating Custom Components</h3>
<p>The builtin components control physics and visuals primarily, but to really make a game, you’re going to need to accept user input and manipulate those standard components as well as the GameObjects themselves.</p>
<blockquote>
<p>To start creating components, go into the desired GameObject &gt; Add Component &gt; type the name of your new component in the search bar &gt; new script (c#).</p>
</blockquote>
<p>As a general recommendation I’d advise against using Javascript in Unity. It hasn’t been kept updated with all the great stuff that came with ES6, and most of the more advanced stuff relies on C# stuff ported over to Javascript… It just becomes a one giant work-around in my experience.</p>
<h3 id="heading-structure-of-a-monobehaviour">Structure of a MonoBehaviour</h3>
<h4 id="heading-key-functions">Key Functions</h4>
<p>All components inherit from the MonoBehaviour Class. It includes several standard methods, most importantly:</p>
<ul>
<li><strong>void Start()</strong> which is called whenever an object containing the script is instantiated in the scene. This is useful anytime we want to perform some initialisation code, eg. set a player’s equipment after they spawn into a match.</li>
<li><strong>void Update()</strong> which is called every frame. This is where the bulk of code involving user input will go, updating various properties such as the motion of the player in the scene.</li>
</ul>
<h4 id="heading-inspector-variables">Inspector Variables</h4>
<p>Often we want to make components as flexible as possible. For example all weapons might have a different damage, rate of fire, has_sight etc. Whilst all the weapons are essentially the same thing we may want to be able to create different variations quickly through the unity editor.</p>
<p>Another example where we might want to do this is when creating a UI component that tracks user mouse movements and places a cursor in the viewport. Here we might want to control the sensitivity of the cursor to movements (if the user was using a joystick or gamepad vs a computer mouse). Thus it would make sense to have these variable easy to change both in edit mode and also experiment with them during runtime.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ARiWcy5AEsVyRicp7demoZnzQR0MjPQnFzXJ" alt="Image" width="598" height="232" loading="lazy">
<em>Variables in the inspector window can be changed at any time during runtime or edit mode. Note: Changes made during runtime will not be permanent.</em></p>
<p>We can do this easily by simply declaring them as public variables in the body of the component.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/dMqFuop796E9p2Y4urYkJtsuM3Rh6oM07cIJ" alt="Image" width="800" height="475" loading="lazy">
<em>Notice how we can make variables have different levels of access, private, public, or public but not displayed in the inspector window.</em></p>
<h4 id="heading-accepting-user-input">Accepting user input</h4>
<p>Of course, we want our game to respond to user input. The most common ways to do that are using the following methods in the Update() function of a component (or anywhere else you like):</p>
<ul>
<li>Input.GetKey(KeyCode.W) Returns True W key is being held down</li>
<li>Input.GetKeyDown(KeyCode.W) Returns True when W key is first pressed</li>
<li>Input.GetAxis(“Vertical”), Input.GetAxis(“Horizontal”) Returns between -1,1 mouse input movement</li>
</ul>
<h3 id="heading-manipulating-gameobjects">Manipulating GameObjects</h3>
<p>Once we have user input we want GameObjects within our scene to respond. There are several types of responses we may consider:</p>
<ul>
<li>Translation, Rotation, Scale</li>
<li>Create new GameObjects</li>
<li>Sending messages to existing GameObjects / components</li>
</ul>
<h4 id="heading-transformations">Transformations</h4>
<p>GameObjects all have a transform property which enable various useful manipulations on the current game object to be performed.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/cqutjhXkSZxKNCywMSjGbxewqeDo5GCp0R-d" alt="Image" width="800" height="226" loading="lazy"></p>
<p>The methods above are fairly self explanatory, just note that we use lowercase <em>gameObject</em> to refer to the GameObject which owns this specific instance of the component.</p>
<p>In general it’s a good practice to use <em>local[Position,Rotation]</em> rather than the global position / rotation of an object. This usually makes it easier to move objects in a manner that makes sense, as the local space axis will be oriented and centered on the parent object rather than the world origin and x,y,z directions.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/sgr4nHfYLQYqjEEPSxlxPA0BhCrNjgzzvOmW" alt="Image" width="800" height="482" loading="lazy">
<em>The benefits of local space become a little more obvious with a diagram!</em></p>
<p>If you need to convert between local and world space (which often is the case) you can use the following:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/vNEw9xUc-B2vZOaeAqXcQn5W-lxfmJbLiEZw" alt="Image" width="800" height="145" loading="lazy"></p>
<p>As you can imagine, there is some fairly simple linear algebra behind this hinted at by the ‘Inverse’ in the method name.</p>
<h4 id="heading-creating-new-gameobjects">Creating new GameObjects</h4>
<p>Since GameObjects are basically everything in your scene, you might want to be able to generate them on the fly. For example if your player has some sort of projectile launcher you might want to be able to create projectiles on the fly which have their own encapsulated logic for flight, dealing damage, etc…</p>
<p>First we need to introduce the notion of a <em>Prefab</em>. We can create these simply by dragging any GameObject in the scene hierarchy into the assets folder.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/BEBGqpePGsVgtEY5y89WrnLAbdZjPHZiagjZ" alt="Image" width="164" height="150" loading="lazy">
<em>What prefab looks like in the Asset tab</em></p>
<p>This essentially stores a template of the object we just had in our scene with all the same configurations.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/wFLWTKOYgxfMEAEzUjgMsTCETSmTA3JIPLGp" alt="Image" width="800" height="293" loading="lazy">
<em>An example of a custom brick object which is used to dynamically generate Lego bricks in a scene, it has a bunch of components attached to it with various default values.</em></p>
<p>Once we have these prefab components we can assign them to inspector variables (as we talked about earlier) on any component in the scene, so that we can create new GameObjects as specified by the prefab at any time.</p>
<p>We can then perform ‘instantiation’ of the prefab and manipulate it to the desired location in the scene and establish the necessary parent relationships.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/xAzUlbgEAIkyS8bsX8W0xlVI0YiSTiVyMljj" alt="Image" width="800" height="286" loading="lazy"></p>
<h3 id="heading-accessing-other-gameobjects-and-components">Accessing other GameObjects and Components</h3>
<p>Often we need to communicate with other GameObjects as well as their associated components. Once you have a reference to a game object this is pretty simple.</p>
<blockquote>
<p>ComponentName comp = some_game_object.GetComponent();</p>
</blockquote>
<p>After that you can access any of the public methods / variables of the component in order to manipulate the GameObject. This is the straightforward bit, however actually obtaining the reference to the GameObject can be done in several ways…</p>
<h4 id="heading-access-via-inspector-variable">Access via inspector variable</h4>
<p>This is the most straightforward. Simply create a public variable for the GameObject, as we’ve demonstrated earlier with the prefabs, and manually drag and drop it onto the component via the inspector. Then access the variable as above.</p>
<h4 id="heading-access-via-tagging">Access via tagging</h4>
<p>We can tag GameObjects or prefabs via the inspector and then use the find game object functions to locate references to them.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/9Ur13zYuVV3r17CGo9hDMnyCoG44jTXCwv4g" alt="Image" width="628" height="166" loading="lazy"></p>
<p>This is simply done as below.</p>
<blockquote>
<p>GameObject some_game_object = GameObject.FindGameObjectWithTag(“Brick”);</p>
</blockquote>
<h4 id="heading-access-via-transform">Access via transform</h4>
<p>If we wish to access components in some parent object we can easily do this via the transform attribute.</p>
<blockquote>
<p>ComponentName comp = gameObject.transform.parent.GetComponent();</p>
</blockquote>
<h4 id="heading-access-via-sendmessage">Access via SendMessage</h4>
<p>Alternatively if we want to send a message to many other components or wish to message an object which is far up a nested hierarchy, we can use the send message functions, which accept the name of the function followed by the arguments.</p>
<blockquote>
<p>gameObject.SendMessage(“MethodName”,params); // Broadcast message</p>
<p>gameObject.SendMessageUpwards(“MethodName”, params); // Only received by components which are nested above.</p>
</blockquote>
<h3 id="heading-raycasting">Raycasting</h3>
<p>You may have heard of this before when people compare FPS games that are ‘physics based’ or ‘ray based’. Raycasting is essentially like having a laser pointer which, when it comes into contact with a ‘collider’ or ‘rigidbody’, it returns a ‘hit’ and passes back the details of the object.</p>
<p>There are two scenarios where this comes in handy (There’s probably loads more):</p>
<ol>
<li>If you were designing a weapon system for a game, you could use raycasting for hit detection, and even customise the length of the ray so that melee items ‘hit’ only at short ranges</li>
<li>Create a ray from the mouse pointer to a point in 3d space, ie if you wish the user to be able to select units with their mouse in a strategy game.</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/GcxZnE2hbosbWwoDp94ecEd1g8aVlwrFKOhB" alt="Image" width="800" height="453" loading="lazy">
<em>Example 2 detailed above</em></p>
<p>As you can see, the code for this is a little bit more involved. The key thing to understand is that to cast a ray to where the mouse is pointing in 3d space requires the ScreenPointToRay transformation. The reason for this is the camera is rendering a 3d space as a 2d viewport on your laptop screen, so naturally there is a projection involved to transfer back to 3d.</p>
<h3 id="heading-collision-detection">Collision detection</h3>
<p>Earlier we mentioned the Collider and Rigidbody components which can be added to an object. The rule for collisions is that one object in the collision must have a rigidbody and the other a collider (or both have both components). Note that when using raycasting, rays will only interact with objects with collider components attached.</p>
<p>Once setup within any custom component attached to the object, we can use the OnCollisionEnter, OnCollisionStay and OnCollisionExit methods to respond to collisions. Once we have the collision information we can get the GameObject responsible and use what we learned earlier to interact with components attached to it as well.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ppKZgvdAjKDqbW80Nin2wG9izk08UjyuaqAt" alt="Image" width="776" height="134" loading="lazy"></p>
<p>One thing to note is that rigid-bodies provide physics such as gravity for objects, so if you want this turned off you will need to check the _is<em>kinematic</em> on.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/I9UU3oy-UoVWOwjhXUy9PRiGDT5eFO4O9-IB" alt="Image" width="606" height="338" loading="lazy">
<em>Check on is kinematic to disable unwanted physics but retain nice collision detection.</em></p>
<h3 id="heading-advanced-features">Advanced Features</h3>
<p>We won’t go into any of this now but perhaps in a future article — just to make you aware that they exist.</p>
<h4 id="heading-creating-guis">Creating GUI’s</h4>
<p>Unity has a fully fledged UI engine for laying out the GUI for your game. In general these components work pretty similarly to the rest of the engine.</p>
<h4 id="heading-extending-the-unity-editor">Extending the Unity Editor</h4>
<p>Unity enables you to add custom buttons to your inspectors so that you can affect the world during edit mode. For example, to help with world building you might develop a custom tool window for building modular houses.</p>
<h4 id="heading-animation">Animation</h4>
<p>Unity has a graph-based animation system which enables you to blend and control animations on various objects such as players implementing a bone based animation system.</p>
<h4 id="heading-materials-and-pbr">Materials and PBR</h4>
<p>Unity runs off a physically-based rendering engine which enables real time lighting and realistic materials. The reality is you will either need to learn 3d modeling first or use models made and optimised by someone else before you get to this, in order to make stuff that actually looks good.</p>
<h3 id="heading-advice-for-newcomers">Advice For Newcomers</h3>
<p>If you’re planning on writing your first game, don’t underestimate the complexity and time it takes to write even the most trivial of games. Remember most of the games that come out on Steam have teams working on them for years full-time!</p>
<p>Pick a simple concept and break it down into small achievable milestones. It’s highly recommended to separate your game into as small independent components as possible, as you’re much less likely to run into bugs if you keep the components simple rather than monolithic code blocks.</p>
<p>Before you go and write any code for any part of your game, go and research what someone else has done before to solve the same problem — chances are they’ll have a much slicker solution.</p>
<h3 id="heading-nice-resources-and-communities">Nice Resources and Communities</h3>
<p>Game design has one of the best communities of any out there, and there are loads of highly skilled pros in the industry who put content up for free or for next to nothing. It’s a field that requires 3d Modelers, Concept Artists, Game Designers, Programmers and so on. I’ve linked some great general resources that I’ve come across for each of these fields below:</p>
<p><strong>Concept Art</strong></p>
<ul>
<li><a target="_blank" href="https://www.youtube.com/channel/UCbdyjrrJAjDIACjCsjAGFAA">Feng Zhu Design School</a> (Over 90 hour long concept art tutorials)</li>
<li><a target="_blank" href="https://www.youtube.com/channel/UCm9pCim4dDN4KJZUILGizgA">Tyler Edlin Art</a> (Great BST art community with feedback from pros on monthly challenges)</li>
<li><a target="_blank" href="https://www.youtube.com/channel/UCyGGrJ-wQlvcWujLKHzB42w">Art Cafe</a> (Interviews and Workshops with Famous Concept Artists)</li>
<li><a target="_blank" href="https://www.youtube.com/channel/UCmRm1xtLIpBhuWjTyD411pA">Trent Kaniuga</a> (Illustrator and 2D artist who’s also making his own game)</li>
</ul>
<p><strong>3D Modelling</strong></p>
<ul>
<li><a target="_blank" href="https://cgcookie.com/course/mesh-modeling-bootcamp/?utm_source=youtube&amp;utm_medium=social&amp;utm_campaign=course&amp;utm_term=description&amp;utm_content=modeling-bootcamp-lessons">CG Cookie</a> (Best Mesh Modeling Basics in Blender Ever, they’ve loads of other excellent content for blender)</li>
<li><a target="_blank" href="https://www.youtube.com/channel/UCDmOobbSOonY66M6fsJO7GQ">Tor Frick</a> (Hard Surface Modelers &amp; Sculptors in Blender)</li>
<li><a target="_blank" href="https://www.youtube.com/channel/UCVA3cYOgsTN4hs3v7pjne7w">Gleb Alexandrov</a> (Short powerful rendering tutorials in Blender)</li>
</ul>
<p><strong>Game Design</strong></p>
<ul>
<li><a target="_blank" href="https://www.youtube.com/watch?v=juJikoClDxw&amp;list=PLIhLvue17Sd7riA8vb8h1kP3jCFS_qtTM">DoubleFine Amnesia Fortnight</a> (GameDevs who do a 2 week hackathon and record their entire design process)</li>
<li><a target="_blank" href="https://www.youtube.com/channel/UCqJ-Xo29CKyLTjn6z2XwYAw">GameMakers Toolkit</a> (Examines Game Design Principles)</li>
</ul>
<p><strong>Programming</strong></p>
<ul>
<li><a target="_blank" href="https://www.youtube.com/channel/UCaTznQhurW5AaiYPbhEA-KA">Handmade Hero</a> (Writing a game and engine from scratch in C)</li>
<li><a target="_blank" href="https://www.youtube.com/channel/UCCuoqzrsHlwv1YyPKLuMDUQ">Jonathan Blow</a> (Indie dev who livestreams his game development)</li>
<li><a target="_blank" href="https://www.youtube.com/channel/UCYbK_tjZ2OrIZFBvU6CCMiA">Brackeys</a> (Nice Unity Tutorials)</li>
</ul>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Hope you guys liked this tutorial! I do a bit of graphic design work as well as game and UI prototypes so check out <a target="_blank" href="http://hugodolan.com/portfolio"><strong>my portfolio</strong></a>! I’m also on <strong>linked in</strong>.</p>
<p><a target="_blank" href="https://hugodolandesigns.portfoliobox.net"><strong>Portfolio</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/hugo-dolan-62971a174/"><strong>LinkedIn</strong></a></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/NwkVR7XrAVlrJUTy9x0Cc30JmbmpAayM69HK" alt="Image" width="800" height="411" loading="lazy">
<em><a target="_blank" href="http://eepurl.com/gkV7ov">http://eepurl.com/gkV7ov</a></em></p>
</div></div></div> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What I learned from creating a video game with just over a year of coding experience ]]>
                </title>
                <description>
                    <![CDATA[ By Marlo Asis Video games have always played a big role in my life. Final Fantasy II taught me how to read (Super Nintendo Entertainment System, so actually FF4). Yes, my early vocabulary included “chocobo” and “spoony bard.” I remember when Street F... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-i-created-a-video-game-with-just-over-a-year-of-coding-experience-6bc585acef76/</link>
                <guid isPermaLink="false">66c34d86912fb29c4f156bf4</guid>
                
                    <category>
                        <![CDATA[ Game Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 05 Mar 2019 16:51:29 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*WQvfCLvnMAF8y3qJTmYoUA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Marlo Asis</p>
<p>Video games have always played a big role in my life. Final Fantasy II taught me how to read (Super Nintendo Entertainment System, so actually FF4).</p>
<p>Yes, my early vocabulary included “chocobo” and “spoony bard.” I remember when Street Fighter II came out. My brothers and I would spend hours and quarters at the arcades.</p>
<p>I’d spend entire days at the arcade playing Dance Dance Revolution (DDR) with my brother, my cousin, and our other friends. We even had a “DDR crew” and “battled” other local crews.</p>
<p>I recently started playing Overwatch, and it has reconnected me with friends from 5, even 10 years ago. My wife and I strengthen (or test) our relationship by playing Overcooked.</p>
<p>To say that I love video games is an understatement! ?</p>
<p>Video games teach, spark imagination, challenge people, and connect people. Video games bring joy into people’s lives. On the other hand, much of my current profession is filled with suffering - not necessarily my own suffering, but the suffering of others.</p>
<p>I’m currently a resident physician (meaning I’ve finished medical school, but I’m still training under the supervision of other doctors). In my short career, I’ve heard too many parents talk about their child’s bright future before their child ended up in the hospital in critical condition.</p>
<p>I’ve heard too many regrets of patients lying on their deathbed. I’m frequently reminded of how short life is. It’s too short to have a dream and not try to pursue it.</p>
<p>So, I decided to make my dream of being a game developer a reality. In this article, I’ll share what I learned on my journey thus far, and some of the challenges I faced, with hopes of helping others who share this dream.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/R2Hji3QZihj1xDVgOhMw9LYu3HV3fysiDLUq" alt="Image" width="800" height="600" loading="lazy">
<em>Overcooked 2 — a game that will reveal the true nature of your relationship(s)</em></p>
<h4 id="heading-learning-how-to-code"><strong>Learning how to code</strong></h4>
<p>So how did I get started? When I started residency, I saw an ad for a Udemy course on how to make video games on Unity. Finally having an income, I bought it. I quickly became too busy to get into it. I left it alone like a game I just bought during a Steam sale.</p>
<p>Two years later, my fiancée (now wife) came home from a difficult day at work. She said she was just going to learn how to code and quit her job. Like a good partner, I said, “Oh! Me too!” I opened up that Udemy course and downloaded everything. However, at that time, my wife and I were a 4 hour drive apart. By the time I had installed everything, it was time to leave and drive to her.</p>
<p>I decided to download and listen to some podcasts for the drive. This brings me to the first lesson I learned. Podcasts are super helpful. Listening to podcasts really accelerated my progress. It was on <a target="_blank" href="https://www.codenewbie.org/podcast">CodeNewbie</a> that I learned about <a target="_blank" href="https://www.freecodecamp.org/">freeCodeCamp</a>. Through freeCodeCamp, I learned about the importance of being part of a community. The <a target="_blank" href="https://simpleprogrammer.libsyn.com/">Simple Programmer Podcast</a> inspired me to keep going and stay focused.</p>
<p>In terms of game development related podcasts, <a target="_blank" href="https://www.idlethumbs.net/designernotes/">Designer Notes</a>, <a target="_blank" href="http://thedebuglog.com/category/podcast/">The Debug Log</a>, and <a target="_blank" href="https://www.gamedevunchained.com/about-us">Game Dev Unchained</a> introduced me to the experiences of other game developers. Their stories encouraged me. I learned the lingo. I learned from the mistakes they had already made. I did all this during those 4 hour drives when I would visit my fiancée. Podcasts transformed what would’ve been idle time into productive time.</p>
<p>The other thing that helped me learn more quickly was that I dove right in. <a target="_blank" href="https://medium.freecodecamp.org/i-entered-a-hackathon-with-13-days-of-coding-experience-here-is-what-i-learnt-5538d73ee7ce">I entered a hackathon (by accident) with just 13 days of coding experience</a>. It was here that I learned about the community and the <a target="_blank" href="http://developers.vegas/">local meetups</a>.</p>
<p>At the local meetups, I learned about the possibilities of what could be made. It pushed me to make something so I could show them at the local demo day. It made me want to keep creating and sharing.</p>
<p>As I created and shared, I got feedback and advice from those around me. That’s how I got better. That’s how I got the crazy idea that I could make and release a game by myself with such limited experience.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/sBUvOzjIzLYokmry-F9GN61fmQMn7S2RbATD" alt="Image" width="800" height="581" loading="lazy">
<em>My got second place with my first hackathon team: Developers.Vegas</em></p>
<h4 id="heading-challenges-of-building-and-releasing-a-game-for-the-first-time"><strong>Challenges of building and releasing a game for the first time.</strong></h4>
<p>Actually making my own first game to be released had its challenges of making the art and writing the code. I improved with time, practice, and a lot of Googling.</p>
<p>One technique I found helpful was to write things out in diagrams and in “pseudocode.” The diagrams helped me visualize how everything would connect, and the pseudocode helped me stay on track with what I wanted my code to accomplish. From there, it was a lot of trial and error, and doing the process all over again.</p>
<p>I found it challenging to process and implement people’s feedback. As I began to send my game for people to try, they would make suggestions. One reason this was difficult was because I didn’t know how to do what they were requesting. Another reason was I wanted to actually complete and release my game.</p>
<p>I’ve heard stories of people giving up on their project because they get overwhelmed with too many features. I wanted to stay within my scope and minimal viable product. On the other hand, I wanted to make a product that people actually wanted. I imagine this will continue to be a struggle for me and any game developer/designer.</p>
<p>During this process, I also realized that a lot of the hurdles came from within. When working on my own project, by myself, it’s easy to get lazy and get distracted. It’s easy to just stop working on something and say it’s “good enough”. It’s just as easy as spending way too much time working on something that “isn’t good enough”. What I found helpful was to make deadlines for myself and to write out goals for each block of time I had to work on my game.</p>
<p>The biggest internal challenge, one that I imagine I’ll continue to face, is “impostor syndrome”. At multiple points in this process, I’d ask myself, “Who am I to make and release a game?” When I first uploaded my game to the Google Play Store for internal testing, it was rejected. I wanted to give up right then, despite the fact I had put in the work to complete the project. I didn’t even look at the reason why it was rejected! Thankfully, I snapped out of it and investigated the issue. It turned out to be a simple, fixable mistake. Imagine if I just gave up.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/RBemhqJstP1wIKOR-Vthc4tom3cDuJRKc3EB" alt="Image" width="800" height="627" loading="lazy">
<em>My setup frequently transforms from the top half to the bottom half</em></p>
<h4 id="heading-game-release-and-beyond"><strong>Game Release and Beyond</strong></h4>
<p>Pressing the button to release my game to the public was scary. What if people hated my game? What if something was completely broken? At least so far, those fears were unwarranted. In fact, I have been very satisfied with the response to my game thus far. By no means is it a super successful game with only about <strong>90 total downloads</strong>, and a <strong>grand total of $0.00 in revenue</strong> ? at the time of this writing. ?</p>
<p>However, at this stage, success is seeing people enjoy my game. It’s seeing someone who was about to leave a party stay another hour because someone beat his high score. It’s seeing people post screenshots of their high scores. It’s having someone beat my high score (although I died a little bit on the inside). It’s seeing that people challenge themselves. It’s seeing that joy when they reach a new level of accomplishment.</p>
<p>So, where do I go from here? I think I want to try incorporating multiplayer, or at least figuring out how to do a ranking system. People seem really into getting a high score. I also need to learn more about the business/marketing aspect of things.</p>
<p>I think I’ll start now. I invite you to try my game “Squircle Circle Tap” for <a target="_blank" href="https://itunes.apple.com/us/app/squircle-circle-tap/id1452644588?mt=8">iOS</a> or <a target="_blank" href="https://play.google.com/store/apps/details?id=com.asisgames.squricles">Android</a>. While you try the game out, I’ll continue building my skills to move toward those games that impacted me so much throughout my life. Thank you for reading, happy coding.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to use Firebase for building multiplayer Android games ]]>
                </title>
                <description>
                    <![CDATA[ By Shukant Pal Have you just built your board game for Android? Want to get it online? You are in the right place — let’s build it together! We are going to implement match-making with the Firebase Realtime Database in this article. For that, you ne... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/match-making-with-firebase-hashnode-de9161e2b6a7/</link>
                <guid isPermaLink="false">66c35b1c9de50ee9ca7fa6ff</guid>
                
                    <category>
                        <![CDATA[ android app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Firebase ]]>
                    </category>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 10 Feb 2019 22:16:35 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*cUxtuiNpwNevTBxw3oAY4g.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Shukant Pal</p>
<p>Have you just built your board game for Android? Want to get it online? You are in the right place — let’s build it together!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*cUxtuiNpwNevTBxw3oAY4g.png" alt="Image" width="800" height="420" loading="lazy"></p>
<p>We are going to implement match-making with the Firebase Realtime Database in this article. For that, you need Firebase setup in your Android project — see how to do that <a target="_blank" href="https://firebase.google.com/docs/database/android/start">here</a>.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li><strong>Firebase users</strong> — here, we are assuming you were able to login your user into Firebase using any method. This is necessary to identify whom to communicate with after the match-making is finished.</li>
<li><strong>Gradle Dependencies</strong> — Add these to the <code>dependencies</code> block in your app module's grade file.</li>
</ul>
<pre><code>implementation <span class="hljs-string">'com.google.firebase:firebase-core:16.0.6'</span> implementation <span class="hljs-string">'com.google.firebase:firebase-auth:16.1.0'</span> implementation <span class="hljs-string">'com.google.firebase:firebase-database:16.0.6'</span>
</code></pre><ul>
<li>You aren’t done after implementing match-making. That’s because you’ve only found two players that will play — but haven’t implemented how their moves will propagate over the network.</li>
</ul>
<h3 id="heading-our-model">Our model</h3>
<p>We will use a node in the Firebase database called the game room which will store all the active challenges that users have pushed. Each user will search for existing challenges within the game room and will accept the first one found. Otherwise, the user will upload their own challenge and wait until someone accepts the challenge.</p>
<p>You will be able to add more features in your match-making implementation like matching based on similar performance ratings, friends, regional-bias, etc.</p>
<h3 id="heading-how-the-heck-are-we-gonna-implement-that">How the heck are we gonna implement that?</h3>
<p>I’ve divided our problem into three objects:</p>
<ul>
<li><strong>Matcher</strong>: Finds any existing matches in the game room.</li>
<li><strong>SelfChallengeManager</strong>: Manages the challenge a user uploads if Matcher fails to find any one.</li>
<li><strong>SelfChallengeCanceller</strong>: Cancels the match-making process if this user doesn’t wanna play anymore.</li>
</ul>
<p>In addition, we will require a “Challenge” object that has two properties — communication node reference and the challenger’s user ID (get why we need to login to Firebase now?). This object will be uploaded into the game-room by <code>SelfChallengeManager</code>.</p>
<h3 id="heading-writing-our-components-first">Writing our components first</h3>
<p>Before writing our three components, we need to understand what a Firebase <a target="_blank" href="https://firebase.google.com/docs/database/android/read-and-write#save_data_as_transactions">transaction</a> is. We don’t want two users accepting the same challenge at the same time — which would corrupt our database and make our precious users angry. Transactions come to the rescue by preventing concurrent operations on a node in the database (which will be the game room).</p>
<p>How does that relate to our components? — Our components will be modeled as transactions as inner classes in our ‘FirebasePlayerMatchMaker’ class.</p>
<p><a target="_blank" href="https://gist.github.com/SukantPal/2c1f5daedfaee784bfeb622d4e26736e">https://gist.github.com/SukantPal/2c1f5daedfaee784bfeb622d4e26736e</a></p>
<p>We use two callback interfaces — <code>OnMatchMadeCallback</code> and internally <code>OnFailCallback</code>. The factory method takes a <code>OnMatchMadeCallback</code> which is called whenever a match is made. The <code>OnFailCallback</code> is invoked whenever <strong>MatchMaker</strong> fails to find a match.</p>
<p>Here, <code>findMatch</code> runs on a separate thread and creates an <code>OnFailCallback</code> if <code>Matcher</code> doesn't find a match. In that case, we have to create a <code>SelfChallengeManager</code> and run it as a transaction.</p>
<ol>
<li><strong>Matcher</strong></li>
</ol>
<p>Here, the <code>doTransaction()</code> method iterates over all the children of the game room node and searches for a <code>Challenge</code> that is compatible for our user. By default, <code>isChallengeCompat</code> returns <code>true</code>, but you can change that by adding additional constraints like ratings. The first compatible challenge is then stored and the challenge node is deleted (by setting the value to <code>null</code>) in the database. Note that by deleting the node, the other player will be notified of the acceptance.</p>
<ol start="2">
<li><strong>SelfChallengeManager</strong></li>
</ol>
<p>Here, the <code>doTransaction</code> method adds a child node to the <code>GAME_RECORD</code> node in our database. This is where the game moves will be communicated after the match-making. It then uploads a <code>Challenge</code> to the game room and adds itself as a <code>ValueEventListener</code>. Whenever another user accepts the request, they will delete this node and this user will get notified as we are listening.</p>
<ol start="3">
<li><strong>SelfChallengeCanceller</strong></li>
</ol>
<p>Our code just deletes the node created in by <code>SelfChallengeManager</code> by iterating over all the game room and finding our challenge. BUT IT’S INCOMPLETE!! You (optionally) should add a feature where the this user automatically resigns from the game if the match was accepted already.</p>
<p>In the <code>OnMatchMadeCallback</code> you provide to <code>FirebasePlayerMatchMaker.newInstance</code>, you must initialize the game communication to be done in the node (by path) <code>mGamePath</code>.</p>
<p>Yo, you’ve done it. Thanks for reading!</p>
<p><em>Originally published at <a target="_blank" href="https://hashnode.com/post/match-making-with-firebase-cjrzgoi6k0010ads2xqojc7a1">hashnode.com</a>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How I built a DIY Fortnite gaming rig for just $1,001 (with my 12-year old) ]]>
                </title>
                <description>
                    <![CDATA[ By John Saddington (Do not publish) So, my 12-year old decided that she needed a more powerful computer for her favorite video game, Fortnite. And I promised her, years ago, that we’d find a time to custom-build her own computer. Finally, I’ve been a... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/an-epic-fortnite-gaming-rig-for-1-001-758040ff27a1/</link>
                <guid isPermaLink="false">66c343dc4f1fc448a3678f92</guid>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ hardware ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Life lessons ]]>
                    </category>
                
                    <category>
                        <![CDATA[ live streaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 15 Oct 2018 16:49:28 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*toofoTkP9rbRDeLc.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By John Saddington (Do not publish)</p>
<p>So, my 12-year old decided that she needed a more powerful computer for her favorite video game, <a target="_blank" href="https://www.epicgames.com/fortnite/en-US/buy-now/battle-royale">Fortnite</a>. And I promised her, years ago, that we’d find a time to custom-build her own computer.</p>
<p>Finally, I’ve been able to make good on my word!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Tc7Ni6PTIsuk3QkkzLXagvoTg839ndum4Gq8" alt="Image" width="800" height="1066" loading="lazy">
<em>The Purchase List</em></p>
<p>I wanted my daughter to lead the process end-to-end, so she was responsible for not only finding the right parts but also price-comparing them and making her ultimate “purchase list” so that we could talk through it.</p>
<p>We discussed the pros and cons of larger motherboards to allow for larger expansion opportunities and power consumption requirements for smaller (or more powerful) components, like the CPU or GPU.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/rKPwZpC8IBmI7nej8L10O7BEqIDORzJm1HLr" alt="Image" width="800" height="600" loading="lazy">
<em>Starting to arrive!</em></p>
<p>A little bit of math was required to ensure that we got the right PSU (Power Supply Unit) to handle her components, but it wasn’t that hard to put the master list together. What was the most fun was talking through each part and the reasons for it and why, as well as trying to maximize expected experience (such as — the end result) and the budget that I had outlined for her.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/lxRwtY16WvvzfxLXP474sUOT8ujeVMWohues" alt="Image" width="800" height="1066" loading="lazy">
<em>Core i5~</em></p>
<h3 id="heading-our-goal-and-budget">Our Goal and Budget</h3>
<p>What we wanted to do was build an “epic gaming rig” specifically for Fortnite that would be able to handle near-maximum graphic settings @ 60FPS for less than $1,000. We ended up spending a bit more on peripherals like a gaming mouse and keyboard as well as headset and a nice 24" widescreen monitor. But the core computer (mid-tower) we wanted to keep below $1,000 if we could.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/r3NdotJOZIS81bkX6FEdfDdGib9dSGUSeqQW" alt="Image" width="800" height="600" loading="lazy">
<em>Time to build!</em></p>
<p>Here’s the master list of core components that we purchased…</p>
<ol>
<li><strong>CPU:</strong> <a target="_blank" href="https://amzn.to/2RShU8e">Intel Core i5–8600K</a> Desktop Processor 6 Cores up to 4.3 GHz unlocked LGA 1151 300 Series 95W</li>
<li><strong>CPU Cooler:</strong> <a target="_blank" href="https://amzn.to/2CJLt7l">Cooler Master Hyper 212 Evo</a> (RR-212E-20PK-R2) CPU Cooler with PWM Fan, Four Direct Contact Heat Pipes</li>
<li><strong>Graphics:</strong> <a target="_blank" href="https://amzn.to/2RKtKkF">Gigabyte AORUS Radeon RX 580</a> 8GB Graphic Cards GV-RX580AORUS-8GD</li>
<li><strong>Motherboard:</strong> <a target="_blank" href="https://amzn.to/2CjGV6V">GIGABYTE B360 HD3</a> (LGA1151/Intel/B360/ATX/USB 3.1 Gen 2 (USB3.1) Type A/DDR4/Motherboard)</li>
<li><strong>RAM:</strong> <a target="_blank" href="https://amzn.to/2CiDjSz">Patriot Viper Elite Series DDR4 16GB</a> (2x8GB) 2666MHz PC4–21300 Dual Memory Kit (Black/Grey)</li>
<li><strong>SSD:</strong> <a target="_blank" href="https://amzn.to/2pUGwjV">Kingston A400 SSD 480GB SATA 3 2.5” Solid State Drive</a> SA400S37/480G — Increase Performance</li>
<li><strong>Power Supply:</strong> <a target="_blank" href="https://amzn.to/2NMZAKs">EVGA Supernova 650 G3</a>, 80 Plus Gold 650W</li>
<li><strong>Case:</strong> <a target="_blank" href="https://amzn.to/2NIC5Sv">Phanteks PH-EC416PTG_BW Eclipse P400 Steel ATX Mid Tower Case</a> Black/White,Tempered Glass Edition Cases</li>
</ol>
<p>Most builds suggest getting a HDD, like a <a target="_blank" href="https://amzn.to/2Ci7Tvt">1TB 7200RPM</a> but we opted to maximize boot and load times with the SSD first. She may end up getting a more typical HDD sooner rather than later as she wants to start capturing her gameplay and even live-streaming as well.</p>
<p>The total cost of these 8 components ended up being <strong>$1,001</strong>!</p>
<p>Of course, she also needed some sweet peripherals which added to the total cost of ownership:</p>
<ol>
<li><strong>Keyboard:</strong> <a target="_blank" href="https://amzn.to/2EkqTMw">CORSAIR Strafe Mechanical Gaming Keyboard</a> — Red LED Backlit — USB Passthrough — Linear and Quiet — Cherry MX Red Switch</li>
<li><strong>Monitor:</strong> <a target="_blank" href="https://amzn.to/2yHNrR8">Acer XF250Q Cbmiiprx 24.5" Full HD</a> (1920 x 1080) Zero Frame TN Gaming Monitor with AMD FREESYNC Technology — 1ms | 240Hz Refresh (Display, HDMI 2.0, HDMI 1.4 ports)</li>
<li><strong>Mouse:</strong> <a target="_blank" href="https://amzn.to/2CLqK3k">Logitech G502 Proteus Spectrum RGB Tunable Gaming Mouse</a>, 12,000 DPI On-The-Fly DPI Shifting, Personalized Weight and Balance Tuning with (5) 3.6g Weights, 11 Programmable Buttons</li>
<li><strong>Headphones:</strong> <a target="_blank" href="https://amzn.to/2RKvri1">Logitech G Pro Gaming Headset</a> with Pro Grade Mic for Pc, PC VR, Mac, Xbox One, Playstation 4, Nintendo Switch</li>
<li><strong>Gaming Chair:</strong> <a target="_blank" href="https://amzn.to/2CJFgZl">Homall Gaming Chair</a> Racing Style High-Back PU Leather Office Chair Computer Desk Chair Executive and Ergonomic Style Swivel Chair with Headrest and Lumbar Support (White) — We ended up returning this because it wouldn’t fit in our current setup… she’ll have to figure out another seating system.</li>
</ol>
<p>Oh, and finally, we purchased these three important things that we would definitely need:</p>
<ol>
<li><a target="_blank" href="https://amzn.to/2pV2h2P">Anti Static Wrist Straps</a> — 3 Pack — Reusable Anti-Static Wrist Straps equipped with Grounding Wire and Alligator Clip — Enables you to Ground Yourself while working on Sensitive Electronics</li>
<li><a target="_blank" href="https://amzn.to/2NIFot5">ARCTIC MX-4 Thermal Compound Paste</a>, Carbon Based High Performance, Heatsink Paste, CPU for All Coolers, Interface Material, 4 Grams with Tool</li>
<li><a target="_blank" href="https://amzn.to/2NJ4Uy6">Windows 10 Home USB</a> — Make sure you get the USB so you can boot to it on installation!</li>
</ol>
<p>You’ll obviously also need some screwdrivers and a bunch of other small-ish tools that most folks already have.</p>
<p>Now, it was time to build:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/OyE8mxO84XmfiXXguhjZUaX0HPGbe5cqYakV" alt="Image" width="800" height="1066" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/rtm5j6oHvLv8LEpbI5SamNp9MIpwmY9c5j8S" alt="Image" width="800" height="600" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/3Ov1ju6uJRyh4oj11afTcEuDjOkm5yZCjJtN" alt="Image" width="800" height="600" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/532Q5PX7WCVFOIyyrJBcjYEdhpFZhdcbnxc3" alt="Image" width="800" height="600" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Lc1QKg3bqaMoIayDepPcUs74-MbOV67H8FvB" alt="Image" width="800" height="1066" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Ds-6CEiw14Fvv5sXGv3DK0DerzEfRBsf3iJ5" alt="Image" width="800" height="600" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/mIBEbqbFBMdshnHAFmqTzCqM1c-wDDTNdLoP" alt="Image" width="800" height="1066" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ZUi7b4h12JZGjZBFl-AHUDbWCir5dMz1Yw1x" alt="Image" width="800" height="1066" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Jmat2VRqtHOzReMcevJjV5lawFFTzU8aBwnY" alt="Image" width="800" height="1066" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/vF8C99l75-DmskkY9CsjP9k45CqwMmE0tRjO" alt="Image" width="800" height="1066" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/xcd7BsYz0Ii1wCVuyFPV7ALIY5wAzWOyPZ4d" alt="Image" width="800" height="600" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/OxgabEKclNi1NTRJ4KiZy3N-09vjftWQ5buX" alt="Image" width="800" height="600" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Wcz72PTAI1MvwtUgYs3mAgHSbktfn1UAIRnu" alt="Image" width="800" height="600" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/CID9lhpWQUtag887JaTMi5gBXlGvfqACkFR-" alt="Image" width="800" height="600" loading="lazy"></p>
<p>The entire process took about 6 hours, from start to finish, which surprised me. I had planned to take most (if not all) of the morning to put it together. And, there were definitely a few moments where I thought we were either <em>missing</em> a component or I had thought that we had possibly purchased parts that wouldn’t work together, but, the last above was perfectly configured.</p>
<p>And… it booted the first time!</p>
<p>I’m really proud of her and she’s now having the time of her life playing her favorite game at <strong>max settings @ 60FPS</strong> and I couldn’t be happier because there’s nothing like building your own computer and then using it for the things that you love!</p>
<p>And yes… she learned a ton about computer hardware and software and I definitely consider this part of her <a target="_blank" href="https://john.do/category/hacking-school/">hackschooling</a> education. What a win… and seriously fun stuff.</p>
<p><em>PS: Feel free to follow my <a target="_blank" href="https://www.youtube.com/channel/UCipmSm7mureyl0S6v-vZEQg">daughter on YouTube</a>!</em></p>
<p><em>Originally published at <a target="_blank" href="https://john.do/fortnite-rig/">John Saddington</a>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to create a two-player game with Python and Vue ]]>
                </title>
                <description>
                    <![CDATA[ By Neo Ighodaro In this tutorial, we will create a realtime tic-tac-toe game using Python and Pusher channels. Here’s a demo of how the game will look and behave upon creation: You will need Python 3+, virtualenv, and Flask installed on your machine... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-two-player-game-with-python-and-vue-4220c5592d53/</link>
                <guid isPermaLink="false">66c35115d73001a6c0054be9</guid>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 30 Aug 2018 23:35:04 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*nvqAP0AgGAWA6-vu.gif" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Neo Ighodaro</p>
<p>In this tutorial, we will create a realtime tic-tac-toe game using Python and Pusher channels. Here’s a demo of how the game will look and behave upon creation:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/MuzX8tcbRETbqqNijym55kvnzPcPcsOqZbJp" alt="Image" width="1598" height="824" loading="lazy"></p>
<p>You will need Python 3+, virtualenv, and Flask installed on your machine.The advent of the PC and the internet has redefined the term “entertainment” and the means by which it can be obtained. While a console or some special hardware would have been required to play games in the past, games are only a click away in today’s world of technology.</p>
<p>This multiplayer game will allow a player to connect using their preferred username (or generate a random username where a player doesn’t connect with a username) and choose to play with another player from a list of other online players.</p>
<p>The game itself follows the conventional principles of the popular <a target="_blank" href="https://en.wikipedia.org/wiki/Tic-tac-toe">tic-tac-toe</a> game. The “online player(s)” feature is powered by <a target="_blank" href="https://pusher.com/docs/client_api_guide/client_presence_channels">Pusher presence channels</a> and the realtime updates of a player’s move across multiple windows is powered by <a target="_blank" href="https://pusher.com/docs/client_api_guide/client_private_channels">Pusher private channels.</a> The source code for this tutorial is available here <a target="_blank" href="https://github.com/neoighodaro/python-pusher-multiplayer-game">GitHub</a>.</p>
<p>Let’s get started.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>To follow along, a basic knowledge of Python, Flask, JavaScript (ES6 syntax) and Vue is required. You will also need the following installed on your machine:</p>
<ol>
<li><a target="_blank" href="https://www.python.org/">Python (v3.x)</a></li>
<li><a target="_blank" href="https://virtualenv.pypa.io/en/stable/">Virtualenv</a></li>
<li><a target="_blank" href="http://flask.pocoo.org/">Flask</a></li>
</ol>
<p>Virtualenv is great for creating isolated Python environments, so we can install dependencies in an isolated environment without polluting our global packages directory.</p>
<h3 id="heading-setting-up-the-environment">Setting up the environment</h3>
<p>We will create the project folder and activate a virtual environment within it:</p>
<pre><code class="lang-bash">$ mkdir python-pusher-mutiplayer-game
    $ <span class="hljs-built_in">cd</span> python-pusher-mutiplayer-game
    $ virtualenv .venv
    $ <span class="hljs-built_in">source</span> .venv/bin/activate <span class="hljs-comment"># Linux based systems</span>
    $ \path\to\env\Scripts\activate <span class="hljs-comment"># Windows users</span>
</code></pre>
<p>We will install <a target="_blank" href="http://flask.pocoo.org/">Flask</a> using this command:</p>
<pre><code class="lang-bash">$ pip install flask
</code></pre>
<h3 id="heading-setting-up-pusher">Setting up Pusher</h3>
<p>To integrate Pusher into the multiplayer game, we need to create a Pusher channels application from the Pusher dashboard. If you don’t already have a Pusher account, head over to the <a target="_blank" href="https://pusher.com/">Pusher website</a> and create one.</p>
<p>After creating an account, create a new channels application and enable client events from the application dashboard. To enable client events, click on <strong>App settings</strong> and scroll to the bottom of the page then select the option that says <strong>Enable client events,</strong> and update the <strong>App settings.</strong></p>
<h3 id="heading-building-the-backend-server">Building the backend server</h3>
<p>Back in the project directory, let’s install the <a target="_blank" href="https://github.com/pusher/pusher-http-python">Python Pusher library</a> with this command:</p>
<pre><code class="lang-bash">$ pip install pusher
</code></pre>
<p>We will create a new file and call it <code>app.py</code>, this is where we will write all the code for the Flask backend server. We will also create a folder and call it <code>templates</code>, this folder will hold the markup files for this application.</p>
<p>Let’s write some code to register the endpoints for the game and serve the view, open the <code>app.py</code> file and paste the following code:</p>
<pre><code class="lang-py">// File: ./app.py
    <span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, render_template, request, jsonify, make_response, json
    <span class="hljs-keyword">from</span> pusher <span class="hljs-keyword">import</span> pusher
    app = Flask(__name__)
    pusher = pusher_client = pusher.Pusher(
      app_id=<span class="hljs-string">'PUSHER_APP_ID'</span>,
      key=<span class="hljs-string">'PUSHER_APP_KEY'</span>,
      secret=<span class="hljs-string">'PUSHER_APP_SECRET'</span>,
      cluster=<span class="hljs-string">'PUSHER_APP_CLUSTER'</span>,
      ssl=<span class="hljs-literal">True</span>
    )
    name = <span class="hljs-string">''</span>
<span class="hljs-meta">    @app.route('/')</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">index</span>():</span>
      <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">'index.html'</span>)
<span class="hljs-meta">    @app.route('/play')</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">play</span>():</span>
      <span class="hljs-keyword">global</span> name
      name = request.args.get(<span class="hljs-string">'username'</span>)
      <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">'play.html'</span>)
<span class="hljs-meta">    @app.route("/pusher/auth", methods=['POST'])</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">pusher_authentication</span>():</span>
      auth = pusher.authenticate(
        channel=request.form[<span class="hljs-string">'channel_name'</span>],
        socket_id=request.form[<span class="hljs-string">'socket_id'</span>],
        custom_data={
          <span class="hljs-string">u'user_id'</span>: name,
          <span class="hljs-string">u'user_info'</span>: {
            <span class="hljs-string">u'role'</span>: <span class="hljs-string">u'player'</span>
          }
        }
      )
      <span class="hljs-keyword">return</span> json.dumps(auth)
    <span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
        app.run(host=<span class="hljs-string">'0.0.0.0'</span>, port=<span class="hljs-number">5000</span>, debug=<span class="hljs-literal">True</span>)
    name = <span class="hljs-string">''</span>
</code></pre>
<blockquote>
<p>_Replace the <code>PUSHER_APP_*</code> keys with the values on your Pusher dashboard._</p>
</blockquote>
<p>In the code above, we defined three endpoints, here’s what they do:</p>
<ul>
<li><code>/</code> - renders the front page that asks a player to connect with a username.</li>
<li><code>/play</code> - renders the game view.</li>
<li><code>/pusher/auth</code> - authenticates Pusher’s presence and private channels for connected players.</li>
</ul>
<h3 id="heading-building-the-frontend">Building the frontend</h3>
<p>In the <code>templates</code> folder, we will create two files:</p>
<ol>
<li><code>index.html</code></li>
<li><code>play.html</code></li>
</ol>
<p>The <code>index.html</code> file will render the connection page, so open the <code>templates/index.html</code> file and paste the following code:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- File: ./templates/index.html --&gt;</span>
    <span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1, shrink-to-fit=no"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">""</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"author"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"Neo Ighodaro"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>TIC-TAC-TOE<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
                  <span class="hljs-selector-pseudo">:root</span> {
                    <span class="hljs-attribute">--input-padding-x</span>: .<span class="hljs-number">75rem</span>;
                    <span class="hljs-attribute">--input-padding-y</span>: .<span class="hljs-number">75rem</span>;
                  }
                  <span class="hljs-selector-tag">html</span>,
                  <span class="hljs-selector-tag">body</span>, <span class="hljs-selector-tag">body</span> &gt; <span class="hljs-selector-tag">div</span> {
                    <span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;
                  }
                  <span class="hljs-selector-tag">body</span> &gt; <span class="hljs-selector-tag">div</span> {
                    <span class="hljs-attribute">display</span>: -ms-flexbox;
                    <span class="hljs-attribute">display</span>: flex;
                    <span class="hljs-attribute">-ms-flex-align</span>: center;
                    <span class="hljs-attribute">align-items</span>: center;
                    <span class="hljs-attribute">padding-top</span>: <span class="hljs-number">40px</span>;
                    <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-number">40px</span>;
                    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#f5f5f5</span>;
                  }
                  <span class="hljs-selector-class">.form-signin</span> {
                    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
                    <span class="hljs-attribute">max-width</span>: <span class="hljs-number">420px</span>;
                    <span class="hljs-attribute">padding</span>: <span class="hljs-number">15px</span>;
                    <span class="hljs-attribute">margin</span>: auto;
                  }
                  <span class="hljs-selector-class">.form-label-group</span> {
                    <span class="hljs-attribute">position</span>: relative;
                    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">1rem</span>;
                  }
                  <span class="hljs-selector-class">.form-label-group</span> &gt; <span class="hljs-selector-tag">input</span>,
                  <span class="hljs-selector-class">.form-label-group</span> &gt; <span class="hljs-selector-tag">label</span> {
                    <span class="hljs-attribute">padding</span>: <span class="hljs-built_in">var</span>(--input-padding-y) <span class="hljs-built_in">var</span>(--input-padding-x);
                  }
                  <span class="hljs-selector-class">.form-label-group</span> &gt; <span class="hljs-selector-tag">label</span> {
                    <span class="hljs-attribute">position</span>: absolute;
                    <span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
                    <span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
                    <span class="hljs-attribute">display</span>: block;
                    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
                    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">0</span>; <span class="hljs-comment">/* Override default `&lt;label&gt;` margin */</span>
                    <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.5</span>;
                    <span class="hljs-attribute">color</span>: <span class="hljs-number">#495057</span>;
                    <span class="hljs-attribute">cursor</span>: text; <span class="hljs-comment">/* Match the input under the label */</span>
                    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid transparent;
                    <span class="hljs-attribute">border-radius</span>: .<span class="hljs-number">25rem</span>;
                    <span class="hljs-attribute">transition</span>: all .<span class="hljs-number">1s</span> ease-in-out;
                  }
                  <span class="hljs-selector-class">.form-label-group</span> <span class="hljs-selector-tag">input</span><span class="hljs-selector-pseudo">::-webkit-input-placeholder</span> {
                    <span class="hljs-attribute">color</span>: transparent;
                  }
                  <span class="hljs-selector-class">.form-label-group</span> <span class="hljs-selector-tag">input</span><span class="hljs-selector-pseudo">:-ms-input-placeholder</span> {
                    <span class="hljs-attribute">color</span>: transparent;
                  }
                  <span class="hljs-selector-class">.form-label-group</span> <span class="hljs-selector-tag">input</span><span class="hljs-selector-pseudo">::-ms-input-placeholder</span> {
                    <span class="hljs-attribute">color</span>: transparent;
                  }
                  <span class="hljs-selector-class">.form-label-group</span> <span class="hljs-selector-tag">input</span><span class="hljs-selector-pseudo">::-moz-placeholder</span> {
                    <span class="hljs-attribute">color</span>: transparent;
                  }
                  <span class="hljs-selector-class">.form-label-group</span> <span class="hljs-selector-tag">input</span><span class="hljs-selector-pseudo">::placeholder</span> {
                    <span class="hljs-attribute">color</span>: transparent;
                  }
                  <span class="hljs-selector-class">.form-label-group</span> <span class="hljs-selector-tag">input</span><span class="hljs-selector-pseudo">:not(</span><span class="hljs-selector-pseudo">:placeholder-shown)</span> {
                    <span class="hljs-attribute">padding-top</span>: <span class="hljs-built_in">calc</span>(var(--input-padding-y) + <span class="hljs-built_in">var</span>(--input-padding-y) * (<span class="hljs-number">2</span> / <span class="hljs-number">3</span>));
                    <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-built_in">calc</span>(var(--input-padding-y) / <span class="hljs-number">3</span>);
                  }
                  <span class="hljs-selector-class">.form-label-group</span> <span class="hljs-selector-tag">input</span><span class="hljs-selector-pseudo">:not(</span><span class="hljs-selector-pseudo">:placeholder-shown)</span> ~ <span class="hljs-selector-tag">label</span> {
                    <span class="hljs-attribute">padding-top</span>: <span class="hljs-built_in">calc</span>(var(--input-padding-y) / <span class="hljs-number">3</span>);
                    <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-built_in">calc</span>(var(--input-padding-y) / <span class="hljs-number">3</span>);
                    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">12px</span>;
                    <span class="hljs-attribute">color</span>: <span class="hljs-number">#777</span>;
                  }
            </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-signin"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center mb-4"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-4"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://thestore.gameops.com/v/vspfiles/photos/Tic-Tac-Go-14.gif"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"72"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"72"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"h3 mb-3 font-weight-normal"</span>&gt;</span>TIC-TAC-TOE<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>PUT IN YOUR DETAILS TO PLAY<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-label-group"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"inputUsername"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"username"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Username"</span> <span class="hljs-attr">required</span>=<span class="hljs-string">""</span> <span class="hljs-attr">autofocus</span>=<span class="hljs-string">""</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"inputUsername"</span>&gt;</span>Username<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-label-group"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"inputEmail"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email address"</span> <span class="hljs-attr">autofocus</span>=<span class="hljs-string">""</span> <span class="hljs-attr">required</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"inputEmail"</span>&gt;</span>Email address<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-primary btn-block"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> @<span class="hljs-attr">click.prevent</span>=<span class="hljs-string">"login"</span>&gt;</span>Connect<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mt-5 mb-3 text-muted text-center"</span>&gt;</span>© 2017-2018<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/vue/dist/vue.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
            <span class="hljs-keyword">var</span> app = <span class="hljs-keyword">new</span> Vue({
              <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>,
              <span class="hljs-attr">methods</span>: {
                <span class="hljs-attr">login</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
                  <span class="hljs-keyword">let</span> username = <span class="hljs-built_in">this</span>.$refs.username.value
                  <span class="hljs-keyword">let</span> email = <span class="hljs-built_in">this</span>.$refs.email.value
                  <span class="hljs-built_in">window</span>.location.replace(<span class="hljs-string">`/play?username=<span class="hljs-subst">${username}</span>&amp;email=<span class="hljs-subst">${email}</span>`</span>);
                }
              }
            })
            </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>When a player visits the connection page and puts in a username and email, the browser window will be redirected to the game view.</p>
<p>Let’s write the markup for the game view. Open the <code>play.html</code> file and paste the following code:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- file: ./templates/play.html --&gt;</span>
    <span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1, shrink-to-fit=no"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>TIC-TAC-TOE<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container-fluid"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container-fluid clearfix mb-3 shadow"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"float-left my-3"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://thestore.gameops.com/v/vspfiles/photos/Tic-Tac-Go-14.gif"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"62px"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"62px"</span>
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"float-right w-25 py-3"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"my-3 mx-3 rounded-circle border"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"http://dfsanonymous.club/wp-content/uploads/2017/11/DFSAnonymous-NewLogo.png"</span>
              <span class="hljs-attr">height</span>=<span class="hljs-string">"62px"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"62px"</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d-inline"</span>&gt;</span> {% raw %} {{ username }} {% endraw %} <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row mx-5"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"height: 50vh"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-8 h-50 align-self-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row border rounded invisible h-50 w-75 m-auto"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"font-size: 3.6rem"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"gameboard"</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"playerAction"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"h-100 pr-2 col border border-dark"</span> <span class="hljs-attr">data-id</span>=<span class="hljs-string">"1"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"1"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col pr-2 border border-dark"</span> <span class="hljs-attr">data-id</span>=<span class="hljs-string">"2"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"2"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col pr-2 border border-dark"</span> <span class="hljs-attr">data-id</span>=<span class="hljs-string">"3"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"3"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-100"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"h-100 pr-2 col border border-dark"</span> <span class="hljs-attr">data-id</span>=<span class="hljs-string">"4"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col pr-2 border border-dark"</span> <span class="hljs-attr">data-id</span>=<span class="hljs-string">"5"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"5"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col pr-2 border border-dark"</span> <span class="hljs-attr">data-id</span>=<span class="hljs-string">"6"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"6"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-100"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"h-100 pr-2 col border border-dark"</span> <span class="hljs-attr">data-id</span>=<span class="hljs-string">"7"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"7"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col pr-2 border border-dark"</span> <span class="hljs-attr">data-id</span>=<span class="hljs-string">"8"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"8"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col pr-2 border border-dark"</span> <span class="hljs-attr">data-id</span>=<span class="hljs-string">"9"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"9"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-4 pl-3"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row h-100"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col border h-75 text-center"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background: rgb(114, 230, 147);"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"my-3"</span>&gt;</span> {% raw %} {{ players }} {% endraw %} online player(s) <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">hr</span>/&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"m-auto py-3 text-dark"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"cursor: pointer;"</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"member in connectedPlayers"</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"choosePlayer"</span>&gt;</span>
                  {% raw %} {{ member }} {% endraw %}
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-100"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col text-center py-3 border h-25"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background: #b6c0ca; font-size: 1em; font-weight: bold"</span>&gt;</span>
                {% raw %} {{ status }} {% endraw %}
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/vue/dist/vue.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://js.pusher.com/4.2/pusher.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>The code above defines the layout of the game view but does not contain any interactivity or realtime features. In the scripts section, before the closing <code>body</code> tag, we included the Vue and Pusher libraries because they are required for the game to work.</p>
<p>Let’s include the JavaScript code that will drive the entire game process and define its logic.</p>
<p>In the same file, add the code below in between the <code>script</code> tag that is just before the closing <code>body</code> tag:</p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> app = <span class="hljs-keyword">new</span> Vue({
      <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>,
      <span class="hljs-attr">data</span>: {
        <span class="hljs-attr">username</span>: <span class="hljs-string">''</span>,
        <span class="hljs-attr">players</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">connectedPlayers</span>: [],
        <span class="hljs-attr">status</span>: <span class="hljs-string">''</span>,
        <span class="hljs-attr">pusher</span>: <span class="hljs-keyword">new</span> Pusher(<span class="hljs-string">'PUSHER_APP_KEY'</span>, {
          <span class="hljs-attr">authEndpoint</span>: <span class="hljs-string">'/pusher/auth'</span>,
          <span class="hljs-attr">cluster</span>: <span class="hljs-string">'PUSHER_APP_CLUSTER'</span>,
          <span class="hljs-attr">encrypted</span>: <span class="hljs-literal">true</span>
        }),
        <span class="hljs-attr">otherPlayerName</span>: <span class="hljs-string">''</span>,
        <span class="hljs-attr">mychannel</span>: {},
        <span class="hljs-attr">otherPlayerChannel</span>: {},
        <span class="hljs-attr">firstPlayer</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">turn</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">boxes</span>: [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
      },
      created () {
        <span class="hljs-keyword">let</span> url = <span class="hljs-keyword">new</span> URL(<span class="hljs-built_in">window</span>.location.href);
        <span class="hljs-keyword">let</span> name = url.searchParams.get(<span class="hljs-string">"username"</span>);
        <span class="hljs-keyword">if</span> (name) {
          <span class="hljs-built_in">this</span>.username = name
          <span class="hljs-built_in">this</span>.subscribe();
          <span class="hljs-built_in">this</span>.listeners();
        } <span class="hljs-keyword">else</span> {
          <span class="hljs-built_in">this</span>.username = <span class="hljs-built_in">this</span>.generateRandomName();
          location.assign(<span class="hljs-string">"/play?username="</span> + <span class="hljs-built_in">this</span>.username);
        }
      },
      <span class="hljs-attr">methods</span>: {
        <span class="hljs-comment">// We will add methods here</span>
      }
    });
</code></pre>
<blockquote>
<p>_Replace the <code>PUSHER_APP_*</code> keys with the keys on your Pusher dashboard._</p>
</blockquote>
<p>Above, we create a new instance of Vue and we target the <code>#app</code> selector. We define all the defaults in the <code>data</code>object and then in the <code>create()</code> function which is called automatically when the Vue component is created, we check for a user and assign the user to the username if one was supplied.</p>
<p>We also make calls to the <code>subscribe</code> and <code>listeners</code> methods. Let’s define those inside the <code>methods</code> object. Inside the <code>methods</code> object, paste the following functions:</p>
<pre><code class="lang-js"><span class="hljs-comment">// [...]</span>
    <span class="hljs-attr">subscribe</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">let</span> channel = <span class="hljs-built_in">this</span>.pusher.subscribe(<span class="hljs-string">'presence-channel'</span>);
      <span class="hljs-built_in">this</span>.myChannel = <span class="hljs-built_in">this</span>.pusher.subscribe(<span class="hljs-string">'private-'</span> + <span class="hljs-built_in">this</span>.username)
      channel.bind(<span class="hljs-string">'pusher:subscription_succeeded'</span>, <span class="hljs-function">(<span class="hljs-params">player</span>) =&gt;</span> {
        <span class="hljs-built_in">this</span>.players = player.count - <span class="hljs-number">1</span>
        player.each(<span class="hljs-function">(<span class="hljs-params">player</span>) =&gt;</span> {
          <span class="hljs-keyword">if</span> (player.id != <span class="hljs-built_in">this</span>.username)
            <span class="hljs-built_in">this</span>.connectedPlayers.push(player.id)
        });
      });
      channel.bind(<span class="hljs-string">'pusher:member_added'</span>, <span class="hljs-function">(<span class="hljs-params">player</span>) =&gt;</span> {
        <span class="hljs-built_in">this</span>.players++;
        <span class="hljs-built_in">this</span>.connectedPlayers.push(player.id)
      });
      channel.bind(<span class="hljs-string">'pusher:member_removed'</span>, <span class="hljs-function">(<span class="hljs-params">player</span>) =&gt;</span> {
        <span class="hljs-built_in">this</span>.players--;
        <span class="hljs-keyword">var</span> index = <span class="hljs-built_in">this</span>.connectedPlayers.indexOf(player.id);
        <span class="hljs-keyword">if</span> (index &gt; <span class="hljs-number">-1</span>) {
          <span class="hljs-built_in">this</span>.connectedPlayers.splice(index, <span class="hljs-number">1</span>)
        }
      });
    },
    <span class="hljs-attr">listeners</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
      <span class="hljs-built_in">this</span>.pusher.bind(<span class="hljs-string">'client-'</span> + <span class="hljs-built_in">this</span>.username, <span class="hljs-function">(<span class="hljs-params">message</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (confirm(<span class="hljs-string">'Do you want to start a game of Tic Tac Toe with '</span> + message)) {
          <span class="hljs-built_in">this</span>.otherPlayerName = message
          <span class="hljs-built_in">this</span>.otherPlayerChannel = <span class="hljs-built_in">this</span>.pusher.subscribe(<span class="hljs-string">'private-'</span> + <span class="hljs-built_in">this</span>.otherPlayerName)
          <span class="hljs-built_in">this</span>.otherPlayerChannel.bind(<span class="hljs-string">'pusher:subscription_succeeded'</span>, <span class="hljs-function">() =&gt;</span> {
            <span class="hljs-built_in">this</span>.otherPlayerChannel.trigger(<span class="hljs-string">'client-game-started'</span>, <span class="hljs-built_in">this</span>.username)
          })
          <span class="hljs-built_in">this</span>.startGame(message)
        } <span class="hljs-keyword">else</span> {
          <span class="hljs-built_in">this</span>.otherPlayerChannel = <span class="hljs-built_in">this</span>.pusher.subscribe(<span class="hljs-string">'private-'</span> + message)
          <span class="hljs-built_in">this</span>.otherPlayerChannel.bind(<span class="hljs-string">'pusher:subscription_succeeded'</span>, <span class="hljs-function">() =&gt;</span> {
            <span class="hljs-built_in">this</span>.otherPlayerChannel.trigger(<span class="hljs-string">'client-game-declined'</span>, <span class="hljs-string">""</span>)
          })
          <span class="hljs-built_in">this</span>.gameDeclined()
        }
      }),
      <span class="hljs-built_in">this</span>.myChannel.bind(<span class="hljs-string">'client-game-started'</span>, <span class="hljs-function">(<span class="hljs-params">message</span>) =&gt;</span> {
        <span class="hljs-built_in">this</span>.status = <span class="hljs-string">"Game started with "</span> + message
        <span class="hljs-built_in">this</span>.$refs.gameboard.classList.remove(<span class="hljs-string">'invisible'</span>);
        <span class="hljs-built_in">this</span>.firstPlayer = <span class="hljs-number">1</span>;
        <span class="hljs-built_in">this</span>.turn = <span class="hljs-number">1</span>;
      })
      <span class="hljs-built_in">this</span>.myChannel.bind(<span class="hljs-string">'client-game-declined'</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">this</span>.status = <span class="hljs-string">"Game declined"</span>
      })
      <span class="hljs-built_in">this</span>.myChannel.bind(<span class="hljs-string">'client-new-move'</span>, <span class="hljs-function">(<span class="hljs-params">position</span>) =&gt;</span> {
        <span class="hljs-built_in">this</span>.$refs[position].innerText = <span class="hljs-built_in">this</span>.firstPlayer ? <span class="hljs-string">'O'</span> : <span class="hljs-string">'X'</span>
      })
      <span class="hljs-built_in">this</span>.myChannel.bind(<span class="hljs-string">'client-your-turn'</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">this</span>.turn = <span class="hljs-number">1</span>;
      })
      <span class="hljs-built_in">this</span>.myChannel.bind(<span class="hljs-string">'client-box-update'</span>, <span class="hljs-function">(<span class="hljs-params">update</span>) =&gt;</span> {
        <span class="hljs-built_in">this</span>.boxes = update;
      })
      <span class="hljs-built_in">this</span>.myChannel.bind(<span class="hljs-string">'client-you-lost'</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">this</span>.gameLost();
      })
    },
    <span class="hljs-comment">// [...]</span>
</code></pre>
<p>In the <code>subscribe</code> method, we subscribe to our Pusher presence channel, and then subscribe to the private channel for the current user. In the <code>listeners</code> method we register the listeners for all the events we are expecting to be triggered on the private channel we subscribed to.</p>
<p>Next, we will add other helper methods to our methods class. Inside the methods class, add the following functions to the bottom after the <code>listeners</code> method:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Generates a random string we use as a name for a guest user</span>
    <span class="hljs-attr">generateRandomName</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">let</span> text = <span class="hljs-string">''</span>;
      <span class="hljs-keyword">let</span> possible = <span class="hljs-string">'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'</span>;
      <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">6</span>; i++) {
        text += possible.charAt(<span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * possible.length));
      }
      <span class="hljs-keyword">return</span> text;
    },
    <span class="hljs-comment">// Lets you choose a player to play as.</span>
    <span class="hljs-attr">choosePlayer</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
      <span class="hljs-built_in">this</span>.otherPlayerName = e.target.innerText
      <span class="hljs-built_in">this</span>.otherPlayerChannel = <span class="hljs-built_in">this</span>.pusher.subscribe(<span class="hljs-string">'private-'</span> + <span class="hljs-built_in">this</span>.otherPlayerName)
      <span class="hljs-built_in">this</span>.otherPlayerChannel.bind(<span class="hljs-string">'pusher:subscription_succeeded'</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">this</span>.otherPlayerChannel.trigger(<span class="hljs-string">'client-'</span> + <span class="hljs-built_in">this</span>.otherPlayerName, <span class="hljs-built_in">this</span>.username)
      });
    },
    <span class="hljs-comment">// Begins the game</span>
    <span class="hljs-attr">startGame</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">name</span>) </span>{
      <span class="hljs-built_in">this</span>.status = <span class="hljs-string">"Game started with "</span> + name
      <span class="hljs-built_in">this</span>.$refs.gameboard.classList.remove(<span class="hljs-string">'invisible'</span>);
    },
    <span class="hljs-comment">// User declined to play</span>
    <span class="hljs-attr">gameDeclined</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
      <span class="hljs-built_in">this</span>.status = <span class="hljs-string">"Game declined"</span>
    },
    <span class="hljs-comment">// Game has ended with current user winning</span>
    <span class="hljs-attr">gameWon</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
      <span class="hljs-built_in">this</span>.status = <span class="hljs-string">"You WON!"</span>
      <span class="hljs-built_in">this</span>.$refs.gameboard.classList.add(<span class="hljs-string">'invisible'</span>);
      <span class="hljs-built_in">this</span>.restartGame()
    },
    <span class="hljs-comment">// Game has ended with current user losing</span>
    <span class="hljs-attr">gameLost</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
      <span class="hljs-built_in">this</span>.turn = <span class="hljs-number">1</span>;
      <span class="hljs-built_in">this</span>.boxes = [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
      <span class="hljs-built_in">this</span>.status = <span class="hljs-string">"You LOST!"</span>
      <span class="hljs-built_in">this</span>.$refs.gameboard.classList.add(<span class="hljs-string">'invisible'</span>);
      <span class="hljs-built_in">this</span>.restartGame()
    },
    <span class="hljs-comment">// Restarts a game</span>
    <span class="hljs-attr">restartGame</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">for</span> (i = <span class="hljs-number">1</span>; i &lt; <span class="hljs-number">10</span>; i++) {
        <span class="hljs-built_in">this</span>.$refs[i].innerText = <span class="hljs-string">""</span>
      }
      <span class="hljs-built_in">this</span>.$refs.gameboard.classList.remove(<span class="hljs-string">'invisible'</span>);
    },
    <span class="hljs-comment">// Checks tiles to see if the tiles passed are a match</span>
    <span class="hljs-attr">compare</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">1</span>; i &lt; <span class="hljs-built_in">arguments</span>.length; i++) {
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">arguments</span>[i] === <span class="hljs-number">0</span> || <span class="hljs-built_in">arguments</span>[i] !== <span class="hljs-built_in">arguments</span>[i - <span class="hljs-number">1</span>]) {
          <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
        }
      }
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    },
    <span class="hljs-comment">// Checks the tiles and returns true if theres a winning play</span>
    <span class="hljs-attr">theresAMatch</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.compare(<span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">0</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">1</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">2</span>]) ||
        <span class="hljs-built_in">this</span>.compare(<span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">3</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">4</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">5</span>]) ||
        <span class="hljs-built_in">this</span>.compare(<span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">6</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">7</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">8</span>]) ||
        <span class="hljs-built_in">this</span>.compare(<span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">0</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">3</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">6</span>]) ||
        <span class="hljs-built_in">this</span>.compare(<span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">1</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">4</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">7</span>]) ||
        <span class="hljs-built_in">this</span>.compare(<span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">2</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">5</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">8</span>]) ||
        <span class="hljs-built_in">this</span>.compare(<span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">2</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">4</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">6</span>]) ||
        <span class="hljs-built_in">this</span>.compare(<span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">0</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">4</span>], <span class="hljs-built_in">this</span>.boxes[<span class="hljs-number">8</span>])
    },
    <span class="hljs-comment">// Checks to see if the play was a winning play</span>
    <span class="hljs-attr">playerAction</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
      <span class="hljs-keyword">let</span> index = e.target.dataset.id - <span class="hljs-number">1</span>
      <span class="hljs-keyword">let</span> tile = <span class="hljs-built_in">this</span>.firstPlayer ? <span class="hljs-string">'X'</span> : <span class="hljs-string">'O'</span>
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.turn &amp;&amp; <span class="hljs-built_in">this</span>.boxes[index] == <span class="hljs-number">0</span>) {
        <span class="hljs-built_in">this</span>.turn = <span class="hljs-number">0</span>
        <span class="hljs-built_in">this</span>.boxes[index] = tile
        e.target.innerText = tile
        <span class="hljs-built_in">this</span>.otherPlayerChannel.trigger(<span class="hljs-string">'client-your-turn'</span>, <span class="hljs-string">""</span>)
        <span class="hljs-built_in">this</span>.otherPlayerChannel.trigger(<span class="hljs-string">'client-box-update'</span>, <span class="hljs-built_in">this</span>.boxes)
        <span class="hljs-built_in">this</span>.otherPlayerChannel.trigger(<span class="hljs-string">'client-new-move'</span>, e.target.dataset.id)
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.theresAMatch()) {
          <span class="hljs-built_in">this</span>.gameWon()
          <span class="hljs-built_in">this</span>.boxes = [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
          <span class="hljs-built_in">this</span>.otherPlayerChannel.trigger(<span class="hljs-string">'client-you-lost'</span>, <span class="hljs-string">''</span>)
        }
      }
    },
</code></pre>
<p>Above, we have added several helper methods that the game needs to function properly and before each method, we have added a comment to show what the method does.</p>
<p>Let’s test the game now.</p>
<h3 id="heading-testing-the-game">Testing the game</h3>
<p>We can test the game by running this command:</p>
<pre><code class="lang-bash">$ flask run
</code></pre>
<p>Now if we visit <a target="_blank" href="http://localhost:5000/">localhost:5000</a>, we should see the connection page and test the game:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Vmj8BM420J2JpEiLvfPO7qrLxfYiPHIGuwI6" alt="Image" width="1598" height="824" loading="lazy"></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>In this tutorial, we have learned how to leverage the Pusher SDK in creating an online multiplayer game powered by a Python backend server.</p>
<p>The source code for this tutorial is available on <a target="_blank" href="https://github.com/neoighodaro/python-pusher-multiplayer-game">GitHub</a></p>
<p>This post first appeared on the <a target="_blank" href="https://pusher.com/tutorials/game-python-vue">Pusher Blog</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to create realistic Grand Theft Auto 5 graphics with Deep Learning ]]>
                </title>
                <description>
                    <![CDATA[ By Chintan Trivedi This project is a continuation of my previous article. In it, I explained how we can use CycleGANs for image style transfer, and apply it to convert Fortnite graphics and make it look like PUBG. CycleGAN is a type of Generative Adv... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-realistic-grand-theft-auto-5-graphics-with-deep-learning-cc092c4a69f0/</link>
                <guid isPermaLink="false">66c35143d73001a6c0054bf7</guid>
                
                    <category>
                        <![CDATA[ Artificial Intelligence ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 01 Aug 2018 20:37:49 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*BgjLO87og9PUnDNtU7Ip7Q.gif" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Chintan Trivedi</p>
<p>This project is a continuation of my <a target="_blank" href="https://towardsdatascience.com/turning-fortnite-into-pubg-with-deep-learning-cyclegan-2f9d339dcdb0">previous article</a>. In it, I explained how we can use CycleGANs for image style transfer, and apply it to convert Fortnite graphics and make it look like PUBG.</p>
<p>CycleGAN is a type of Generative Adversarial Network that is capable of mimicking the visual style of one image and transfering it onto another. We can use it to make a game’s graphics look like that of another game or the real world.</p>
<p>In this article, I wanted to share some more results using the same <a target="_blank" href="https://junyanz.github.io/CycleGAN/">CycleGAN algorithm</a> which I covered in my previous work. First, I’ll try to improve GTA 5 graphics by adapting them to look like the real world. Next, I’ll cover how we can achieve the same photo-realistic results, without having to render high-detailed GTA graphics in the first place.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*EZ0j8XVuf30B-ar3GXCIzg.png" alt="Image" width="800" height="340" loading="lazy">
_Both the datasets that I’ve used for this are available at [this link](https://junyanz.github.io/CycleGAN/" rel="noopener" target="<em>blank" title=") on the original author’s project page.</em></p>
<p>For the first task, I have taken screenshots of the game as our source domain which we want to convert into something photo-realistic. The target domain comes from the cityscapes dataset that represents the real world (which we aim to make our game resemble).</p>
<h3 id="heading-cyclegan-results">CycleGAN results</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*3ZD4OtDtLVqQWExjydt6OA.gif" alt="Image" width="600" height="338" loading="lazy"></p>
<p>Based on about three days of training for about 100 epochs, the Cyclegan model seems to do a very nice job of adapting GTA to the real world domain. I really like how the smaller details are not lost in this translation and the image retains its sharpness even at such a low resolution.</p>
<p>The main downside is that this neural network turned out to be quite materialistic: it hallucinates a Mercedes logo everywhere, ruining the almost perfect conversion from GTA to real world. (It’s because the cityscapes dataset was collected by a Mercedes owner.)</p>
<h3 id="heading-how-to-achieve-the-same-photo-realistic-graphics-with-less-effort">How to achieve the same photo-realistic graphics with less effort</h3>
<p>While this approach may seem very promising in improving game graphics, I do not think the real potential lies in following this pipeline. By that I mean that it seems impractical to render such a highly detailed image and then convert it to something else.</p>
<p>Wouldn’t it be better to synthesize a similar quality image but with much less time and effort in designing the game in the first place? I think the real potential lies in rendering objects with low detail and letting the neural net synthesize the final image from this rendering.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*1DZl_0oqSQzKhUuL5GUh5g.png" alt="Image" width="800" height="470" loading="lazy"></p>
<p>So, based on the semantic labels available in the cityscapes dataset, I segmented objects in a screenshot of GTA giving us a representation of low detail graphics. Consider this as a game rendering of only a few objects, like the road, car, houses, sky, and so on without designing them in detail. This will act as the input to our image style transfer model instead of the highly detailed screenshot from the game.</p>
<p>Let’s see what quality of final images can be generated from such low detail semantic maps using CycleGANs.</p>
<h3 id="heading-results-of-image-synthesis-from-semantic-maps">Results of image synthesis from semantic maps</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*kNx9TrAXmaGHUeivjwQReg.gif" alt="Image" width="800" height="225" loading="lazy">
<em>Recreating photo-realistic scenes from the semantic maps of GTA 5.</em></p>
<p>Here are a few examples of how it looks when we recreate GTA graphics from semantic maps. Note that I have not created these maps by hand. That seemed really tedious, so I simply let another CycleGAN model do it (it is trained to perform image segmentation using the cityscapes dataset).</p>
<p>It seems like a good conversion from far away, but looking closely its quite obvious that the image is fake and lacks any kind of details.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*XqPMGvpKwd4U7uN93dk6yQ.png" alt="Image" width="800" height="449" loading="lazy"></p>
<p>Now, these results are 256p and have been generated on a GPU with 8 GB of memory. However, the authors of the original paper have shown that it is possible to create a much more detailed 2048 x 1024p image using a GPU with over 24 GB of memory. It uses the supervised learning version of CycleGAN, called <a target="_blank" href="https://github.com/NVIDIA/pix2pixHD">pix2pixHD</a>, that is trained to perform the same task. And boy does the fake image look pretty darn convincing!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*SJ09ZfgwAUw52XoL07jDGA.png" alt="Image" width="800" height="449" loading="lazy">
_[Here’s the full video](https://www.youtube.com/watch?v=3AIpPlzM_qs&amp;t=23s" rel="noopener" target="<em>blank" title=") uploaded by the authors of this paper.</em></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>GANs have great potential to change how the entertainment industry will produce content going forward. They are capable of producing much better results than humans and in much less time.</p>
<p>The same is applicable to the gaming industry as well. I’m sure that in a few years, this will revolutionize how game graphics are generated. It will be much easier to simply mimic the real world than to recreate everything from scratch.</p>
<p>Once we attain that, rolling out new games will also be much faster. Exciting times ahead with these advancements in Deep Learning!</p>
<h4 id="heading-more-results-in-video-format">More results in video format</h4>
<p>All the above results and more can be found on my <a target="_blank" href="https://www.youtube.com/c/DeepGamingAI">YouTube channel</a> and in the video embedded below. If you liked it, feel free to <a target="_blank" href="http://www.youtube.com/subscription_center?add_user=DeepGamingAI">subscribe</a> to my channel to follow more of my work.</p>
<p>Thank you for reading! If you liked this article, please follow me on <a target="_blank" href="https://medium.com/@chintan.t93">Medium</a>, <a target="_blank" href="https://github.com/ChintanTrivedi">GitHub</a>, or subscribe to my <a target="_blank" href="http://youtube.com/c/DeepGamingAI">YouTube channel</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ From Zero to Game Designer: how to start building video games even if you don’t have any experience ]]>
                </title>
                <description>
                    <![CDATA[ By Angela He 2 years ago I was just 17 year old high school student who knew nothing about coding. But I pushed forward anyway, and within a few months I published my first game on Steam. Now, I’ve made over 10 games for desktop, web, and mobile, wit... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/from-zero-to-game-designer-how-to-start-building-video-games-even-if-you-dont-have-any-experience-5e2f9f45f4bb/</link>
                <guid isPermaLink="false">66c34aec4f7405e6476b01bb</guid>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ gaming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ startup ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 10 Jun 2018 20:06:23 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*ceUs59K42Htx2517TdSvQg.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Angela He</p>
<p>2 years ago I was just 17 year old high school student who knew nothing about coding. But I pushed forward anyway, and within a few months I published my first game on Steam.</p>
<p>Now, I’ve made over <a target="_blank" href="https://zephyo.itch.io/">10 games for desktop, web, and mobile</a>, with over 1.9 million plays combined.</p>
<p>No matter your skill level, you can make a game too. 2 years ago, I thought it was impossible, but tried anyways. It was the hardest thing I’d ever done. But it was worth it. Now, I realize game development is like any skill — you only get better by doing, failing, then improving.</p>
<p>I taught myself everything I know. And now I’m going to teach you.</p>
<h3 id="heading-to-make-a-game-you-must-go-through-the-6-stages-of-game-development-design-art-code-audio-polish-market">To make a game, you must go through the 6 stages of game development: Design. Art. Code. Audio. Polish. Market.</h3>
<p>The rest of my post will structure each stage into the following:</p>
<ul>
<li>?A<strong>dvice I</strong>’ve curated from my and others’ experiences.</li>
<li>?R<strong>esources</strong> I’ve found most helpful.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*VZbUqT8oEH34kK0XXBcwzg.png" alt="Image" width="800" height="472" loading="lazy"></p>
<h3 id="heading-1-design">1. Design ?</h3>
<h4 id="heading-advice">Advice?</h4>
<p>You’ve got a great idea. *</p>
<p>But how do you capture it in writing?</p>
<p>Everyone’ll have their own way of doing that best. Some compose 60-page design documents. Others, like me, write a page of badly-written notes, unreadable to anyone else. I don’t know what’s best for you. <strong>But I can give suggestions on <em>what to write about</em>:</strong></p>
<ul>
<li><strong>Hook.</strong> <em>What makes your game idea great?</em> For me, this is the most important to write down. Once you capture this, you can write down the next three points much easier. Is your game about something thought-provoking? Scandalous? Is it putting a new twist to an old classic? Or, is it doing something that’s never been done before?</li>
<li><strong>Mechanics.</strong> <em>What does your player do? And for what purpose?</em> This is your gameplay. It can be as simple as pressing QWOP to move in the game QWOP, to tapping buttons to chat in Mystic Messenger, to the tons of key combos in Dwarf Fortress.</li>
<li><strong>Story.</strong> <em>What story should players remember your game by? What emotions should they leave your game with?</em> Every game has a story. If the story isn’t obvious, it is created by the player. A story can be created from the increasing numbers in 2048, the rising empires in Civilization, and the silent interactions in Monument Valley. Think about what story’ll be found in your game.</li>
<li><strong>Mood.</strong> <em>What impression does your game make? What are the visuals? Sound?</em> First impressions matter. First impressions will hook — then keep — the player playing. Perhaps, you’ll give your game a retro vibe with <a target="_blank" href="https://www.youtube.com/watch?v=1Hojv0m3TqA">pixel graphics and chiptune music</a>. Or, a modern, clean look with <a target="_blank" href="https://www.youtube.com/watch?v=GatTHt8SUiA">flat geometries and instrumentals</a>.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*Zm7Qnuq-zJcdKP6d.gif" alt="Image" width="58" height="20" loading="lazy"></p>
<p><strong>* Having a hard time thinking of an idea?</strong> Creative block hits us all.</p>
<ul>
<li><em>Join a game hackathon/jam.</em> You and other participants’ll be tasked to make a game in a short amount of time. Throughout, and after, you’ll be met with support from other jammers. And the excitement and creativity during a jam? Infectious. Don’t know where to get started? <a target="_blank" href="https://ldjam.com/">Try Ludum Dare</a>, one of the largest game jams.</li>
<li><em>Keep a list of ideas.</em> I and other developers I know jot down our ideas. That way, we can refer back to our old ones when we run out of new.</li>
</ul>
<p>When the muse hits, stop whatever you’re doing. Write that idea down. The next time creativity ghosts, you won’t be left grasping for straws.</p>
<h4 id="heading-resources">Resources ?</h4>
<p>All of the below are tried and true. (?) means I use it currently.</p>
<p><strong>Note-taking:</strong></p>
<ul>
<li>Notes for Mac (?)</li>
<li>Google Docs (?)</li>
<li>Trello</li>
</ul>
<p><strong>Collaboration (for teams):</strong></p>
<ul>
<li>Google Drive</li>
<li>GitHub (?). R<em>equires git and Unity .gitignore.</em></li>
<li>Unity Collab. <em>Easiest out of the three. The free version has limitations.</em></li>
</ul>
<p>Heads up — Unity is the game engine I use to make games, so I’ll be mentioning it throughout. Feel free to use a different engine.</p>
<p><strong>Game design:</strong></p>
<ul>
<li><a target="_blank" href="https://www.google.com/search?q=jesse+schell+book+of+lenses&amp;oq=jesse+schell+book&amp;aqs=chrome.0.0j69i57j0l2.3902j0j1&amp;sourceid=chrome&amp;ie=UTF-8">The Art of Game Design by Jesse Schell</a></li>
<li><a target="_blank" href="https://www.gamasutra.com/">Gamasutra</a></li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*gThJElasWJawt867DTcr2w.png" alt="Image" width="800" height="450" loading="lazy"></p>
<h3 id="heading-2-art">2. Art ?</h3>
<h4 id="heading-advice-1">Advice?</h4>
<p>You’ve planned out your idea; congrats, that’s amazing! Now, you can work on the actual game.</p>
<p><em>(<strong>If you don’t know how to code</strong>, I suggest doing stage 3, Code, before Art. You don’t want to create art that you’ll trash later because you can’t code it in.)</em></p>
<blockquote>
<p><strong><em>Don’t know how to draw?</em></strong> _Do not fret. Anyone can make something beautiful with the <a target="_blank" href="https://en.wikipedia.org/wiki/Visual_design_elements_and_principles">3 basic visual principles</a>: color, shape, space._</p>
</blockquote>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*E0eirD4x5D_CejDi." alt="Image" width="800" height="406" loading="lazy">
<em>Thomas Was Alone — a beautiful yet simple game</em></p>
<h4 id="heading-ui"><strong>UI</strong></h4>
<p>Think about how you can make it <strong><em>unique</em></strong> — have a distinct color scheme, font(s), shape(s), and icon(s) — while <strong><em>functional</em></strong>. Is the important information readable and obvious? Do the colors/fonts/icons distract from that at all?</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*7oMigOwvb5hZw8oNYc4yEA.png" alt="Image" width="800" height="869" loading="lazy">
<em>Who would win? ?</em></p>
<h4 id="heading-2d-animations"><strong>2D animations</strong></h4>
<p>You have two options:</p>
<ul>
<li><strong><em>Frame-by-frame.</em></strong> Draw out each frame of the animation. For this, you should use sprite sheets with <a target="_blank" href="https://www.codeandweb.com/texturepacker">TexturePacker</a> (or if you’re using Unity, <a target="_blank" href="https://docs.unity3d.com/Manual/SpritePacker.html">Sprite Packer</a>).</li>
<li><strong><em>Bone-based.</em></strong> Draw each animated limb, then animate the limb’s position, rotation, and whatnot in-game. Can be faster, easier, and save memory. If you’re doing 2D and using Unity, try editing the pivots of sprites or <a target="_blank" href="https://assetstore.unity.com/packages/essentials/unity-anima2d-79840">Anima2D</a>.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*hIZxk2xfmyTYCL38." alt="Image" width="1295" height="645" loading="lazy"></p>
<h4 id="heading-misc"><strong>Misc</strong></h4>
<p>Here are some general miscellaneous art tips that apply to not only art in games, but in other software as well.</p>
<ul>
<li><strong><em>Tile</em></strong> patterned assets to create tiled images and save memory.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*kJidu4j0jdoKiSak.png" alt="Image" width="487" height="237" loading="lazy">
<em>Untiled to tiled</em></p>
<ul>
<li><strong><em>9-patch/9-slice</em></strong> assets with unscalable borders but a scalable center to create scalable images and save memory.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*2JhJt6iStsR1P8hy.png" alt="Image" width="720" height="265" loading="lazy">
<em>?The blue ditto grows, but its corners stay the same!</em></p>
<ul>
<li>Make the dimensions of each asset <a target="_blank" href="https://www.gamasutra.com/blogs/RobertBasler/20180202/313739/DXT_Texture_Compression_in_2018.php">a multiple of 4</a> or <a target="_blank" href="https://docs.unity3d.com/Manual/HOWTO-ArtAssetBestPracticeGuide.html">a power of 2</a> to save memory. Which one depends on how you’re compressing the assets.</li>
<li>If you’re using Photoshop, use “File &gt; Export &gt; Layers to Files” to quickly export each layer as a file (e.g. PNG, JPEG).</li>
</ul>
<h4 id="heading-resources-1">Resources ?</h4>
<p><strong>Creating UI:</strong></p>
<ul>
<li>Photoshop (?).</li>
<li>Sketch.</li>
</ul>
<p><strong>UI principles:</strong></p>
<ul>
<li><a target="_blank" href="https://material.io/design/">Google Material Design</a> (?).</li>
<li><a target="_blank" href="https://developer.apple.com/design/tips/">Apple’s UI Do’s and Don’ts</a>.</li>
</ul>
<p><strong>Creating 2D assets:</strong></p>
<ul>
<li>Photoshop (?).</li>
<li>Gimp.</li>
<li>Paint Tool SAI. <em>Good for smooth/anime styles.</em></li>
</ul>
<p><strong>Creating 3D assets:</strong></p>
<ul>
<li>Blender (?). P<em>owerful but steep learning curve.</em></li>
<li>Maya. <em>Good for animation.</em></li>
<li>Max. <em>Good for rendering.</em></li>
</ul>
<p><strong>Free assets:</strong></p>
<ul>
<li><a target="_blank" href="https://www.behance.net/">Behance</a> (?). F<em>onts + icons + other designs.</em></li>
<li><a target="_blank" href="https://kenney.nl/">KennyNL</a>. <em>HQ, game-ready UI/2D/3D art.</em></li>
<li><a target="_blank" href="https://opengameart.org/">Open Game Dev Art</a>. <em>Large library of user-generated art.</em></li>
</ul>
<p><strong>Inspiration:</strong></p>
<ul>
<li><a target="_blank" href="https://dribbble.com/">Dribbble.</a> <em>Designs from invite-only designers.</em></li>
<li><a target="_blank" href="https://www.behance.net/">Behance</a> (?). D<em>esigns from anyone with an account.</em></li>
<li><a target="_blank" href="http://itch.io/">itch.io</a> (?). B<em>eautiful indie games.</em></li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*TMF40Hb52oFS-GlvLRs4Gg.gif" alt="Image" width="800" height="450" loading="lazy"></p>
<h3 id="heading-3-code">3. Code ?</h3>
<h4 id="heading-advice-2">Advice?</h4>
<pre><code>Debug.Log(“Oh boy! Time to code!! ^_^”);
</code></pre><p><strong>Your first step?</strong> Decide on a <strong>game engine</strong> and an <strong>IDE</strong> (Integrated Development Environment — basically, an app that lets you code). My recommended game engines+IDEs are in Resources below.</p>
<p><strong>Your second step?</strong> Code.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*PMyxT_fjoTaVsDcs.gif" alt="Image" width="76" height="20" loading="lazy"></p>
<p><strong>Don’t know how to code?</strong> No worries. I got you. You can learn.</p>
<p>These CS fundamentals should be enough to start. (All code examples here are in C++, one of the main languages the Unity 3D game development framework uses.)</p>
<p><strong>1) Data types and variables.</strong> At the root of all code is data. That data is stored in variables. You can declare a variable like this:</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>;
</code></pre>
<p>Let’s break that down.</p>
<p><code>int</code> is the data type. <code>i</code> is the variable name. And that <code>= 0</code> assigns zero as the variable value.</p>
<p>So what’s this?</p>
<pre><code class="lang-cpp"><span class="hljs-built_in">string</span> s = <span class="hljs-string">"pusheen is best cat"</span>;
</code></pre>
<p><code>string</code> is the data type. <code>s</code> is the variable name. And yep — you guessed it — <code>“pusheen is best cat”</code> is the variable value.</p>
<p>Some common data types: <code>int</code> and <code>long</code> are <code>integers</code>. <code>float</code> and <code>double</code> are decimal numbers. And string is any sentence. (Even an empty one — <code>“”</code>!)</p>
<p>Want to know more? Go through <a target="_blank" href="https://lifehacker.com/5736011/learn-how-to-code-part-i-variables-and-basic-data-types">this</a> and <a target="_blank" href="https://lifehacker.com/5742493/learn-to-code-part-ii-working-with-variables">this</a>.</p>
<p><strong>2) If statements.</strong> If statements evaluate if a certain condition is true. If it is, run the code that’s inside the <code>if</code> statement:</p>
<pre><code><span class="hljs-keyword">if</span> (<span class="hljs-literal">true</span>){ <span class="hljs-comment">//true is always true!</span>

    doThings(); <span class="hljs-comment">//I'm inside the if statement's brackets; run me!</span>
}
</code></pre><p>If the condition isn’t true, we can evaluate other conditions with <code>else if</code>:</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>;

<span class="hljs-keyword">if</span> (i == <span class="hljs-number">0</span>){ 

   doThings(); 
}
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (i == <span class="hljs-number">1</span>){

   doOtherThings(); <span class="hljs-comment">//I'm gonna be run!</span>

}
</code></pre>
<p>Or, just run some other code with <code>else</code>:</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">int</span> i = <span class="hljs-number">60000</span>;

<span class="hljs-keyword">if</span> (i == <span class="hljs-number">0</span>){

  doThings(); 

} <span class="hljs-keyword">else</span> {

  doOtherThings(); <span class="hljs-comment">//I'm still gonna be run.</span>

}
</code></pre>
<p><strong>3) For/while loops.</strong> While loops continue while a certain condition is still true, executing the same lines of code over and over again. When the condition is false, the while loop exits.</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">while</span> (someBool == <span class="hljs-literal">true</span>){ <span class="hljs-comment">//condition</span>

   doThings(); <span class="hljs-comment">//We'll keep doing things until someBool is false</span>

}
</code></pre>
<p>Think: how long does this while loop last?</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>){

  doThings();

}
</code></pre>
<p>For loops are basically while loops where:</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>;
<span class="hljs-keyword">while</span> (i &lt; condition){ 

    doThings();

    i++; <span class="hljs-comment">//increment after doing things</span>
}
</code></pre>
<p>That’s equivalent to:</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; condition; i++){

    doThings();
}
</code></pre>
<p><strong>4) Basic data structures.</strong> So, we have data, and we ways to evaluate and manipulate that data. We can also store that data into some structure — a data structure. Data structures you should know are <a target="_blank" href="https://www.geeksforgeeks.org/introduction-to-arrays/">arrays</a>, <a target="_blank" href="https://www.geeksforgeeks.org/linked-list-set-1-introduction/">lists</a>, <a target="_blank" href="https://www.geeksforgeeks.org/queue-data-structure/">queues</a>, <a target="_blank" href="https://www.geeksforgeeks.org/stack-data-structure/">stacks</a>, and <a target="_blank" href="https://www.geeksforgeeks.org/hashing-set-1-introduction/">sets</a>.</p>
<p>Here’s a quick example of an array:</p>
<pre><code class="lang-cpp"><span class="hljs-comment">/*
Say you have numbers 0 through 9 that you want to store somewhere. You can store it in an array!
*/</span>
<span class="hljs-keyword">int</span>[] arr = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">10</span>]; 
<span class="hljs-comment">/*
The [] brackets declare an array. We assign a new array to arr of size 10 - that means it can hold 10 elements. Arr now looks like this:

arr = [ 0 0 0 0 0 0 0 0 0 0 ]
*/</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>; i&lt;<span class="hljs-number">10</span>; i++){

    arr[i]=i; <span class="hljs-comment">//We assign whatever i is to the the ith index of arr.</span>

<span class="hljs-comment">//Did you know data structures' indices start at 0? ? </span>
}

<span class="hljs-comment">/*
After the for loop, our array data structure should look like this!
arr = [ 0 1 2 3 4 5 6 7 8 9 ]
*/</span>
</code></pre>
<p>To solidify your knowledge of 2–4, go through <a target="_blank" href="https://lifehacker.com/5742494/learn-to-code-part-iii-arrays-and-logic-statements">this</a>.</p>
<p><strong>5) Functions and exceptions.</strong> Functions are basically a small line of code describing a big bunch of code. For example, if you call:</p>
<pre><code class="lang-cpp">EatBread();
</code></pre>
<p>And EatBread() looks like:</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">EatBread</span><span class="hljs-params">()</span></span>{ <span class="hljs-comment">//&lt;---this is a function. </span>

   breadAte=<span class="hljs-literal">true</span>;

   <span class="hljs-built_in">printf</span>(<span class="hljs-string">"I CAN FEEL THE CARBS COURSING THROUGH MY BODY"</span>);

}
</code></pre>
<p>Then the call to <code>EatBread()</code> is actually a call to the two statements within the <code>EatBread()</code> function.</p>
<p>If you do something bad in your code, an exception might get thrown. They’re angry red errors there to tell you, hey, back up, what you did right there just ain’t ‘workin out logically. Go revise it.</p>
<p>To learn more about functions, <a target="_blank" href="https://lifehacker.com/5742495/learn-to-code-part-iv-understanding-functions-and-making-a-guessing-game">go here</a>; for exceptions, <a target="_blank" href="http://www.tutorialspoint.com/java/java_exceptions.htm">go here.</a></p>
<p>Then, there’re other things you should know:</p>
<p><strong>6) Language.</strong> What language are you going to code in? C++? Javascript? C#? Every language is written somewhat differently and can let you do different things.</p>
<p><strong>7) API (Application Programming Interface).</strong> Once you know the basics, you’ll have to learn the specific API of your game engine. APIs are essentially a bunch of powerful tools wrapped in simple classes and functions that you can call. APIs make life easier. Way easier.</p>
<p>Lastly:</p>
<p><strong>8) Look at an example project in your chosen game engine.</strong> <a target="_blank" href="https://docs.unrealengine.com/en-us/Resources">Unreal</a> and <a target="_blank" href="https://unity3d.com/learn/resources/downloads">Unity</a> both have a ton of free example projects. This’ll let you discover how everything comes together. Plus, you can build your game idea off of the project. (I built my first game off of <a target="_blank" href="http://corgi-engine.moremountains.com/">Corgi Engine</a>.)</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">if</span> (you.getThisFar()==<span class="hljs-literal">true</span>){
  veryProud=<span class="hljs-literal">true</span>;
  you.didIt(); <span class="hljs-comment">//CURRENT MOOD: THE SH⭐⭐KEST ???</span>

}
</code></pre>
<p><strong>A word of encouragement:</strong> I know. Coding is scary at first. Nothing makes sense, you’re hitting constant roadblocks, and you might want to quit in the face of failures and exceptions. It doesn’t mean you’re bad at coding. Coding is challenging. It’s understandable to feel incompetent at first.</p>
<p>But it just takes time, like any other skill. It’ll get easier. And it’ll get fun (at least, it did for me).</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*276fFujnYO2MY-5j.gif" alt="Image" width="79" height="20" loading="lazy"></p>
<p><strong>Important game programming concepts:</strong></p>
<ul>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/Object-oriented_programming"><em>Object orientation.</em></a> Makes programming feel more natural.</li>
<li><a target="_blank" href="https://stackoverflow.com/questions/421965/anyone-else-find-naming-classes-and-methods-one-of-the-most-difficult-parts-in-p"><em>Naming conventions.</em></a> Name your classes, methods, and variables as something that obviously conveys its purpose. For instance, a melee attack function should be named meleeAttack(), not mA() or protecbutalsoattac(). You (and others who read your code) should know what’s going on.</li>
<li><a target="_blank" href="https://cs.stanford.edu/people/nick/compdocs/Decomposition_and_Style.pdf"><em>Decomposition.</em></a> Put code that repeats itself into a separate function. Call that function instead of duplicating the repeatable code.</li>
<li><a target="_blank" href="http://gameprogrammingpatterns.com/singleton.html"><em>Singleton design pattern.</em></a> Allows data that a lot of things need to be stored in one place.</li>
<li><em>Static avoidance.</em> Beyond singletons, I’d avoid making static variables— their lifetime is the game’s lifetime, <a target="_blank" href="https://jacksondunstan.com/articles/1713">they’re slower,</a> and they can have unexpected behaviors in the editor.</li>
<li><a target="_blank" href="http://gameprogrammingpatterns.com/observer.html"><em>Observer design pattern</em></a><em>.</em> Allows things that must happen depending on another thing to not waste the computer’s time checking that other thing.</li>
</ul>
<p><strong>Important Unity-specific things:</strong></p>
<ul>
<li><a target="_blank" href="https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html"><em>Coroutines.</em></a> IEnumerators and Coroutines allow you to start doing things, continue doing things until some time has passed, then stop. I use them <em>all the time:</em> for bursts of visual effects; for lerping movement; for waiting for a scene to load before grabbing the scene’s objects.</li>
<li><a target="_blank" href="https://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/scriptable-objects"><em>ScriptableObject.</em></a> These contain data with less overhead than MonoBehaviors.</li>
</ul>
<h4 id="heading-resources-2">Resources ?</h4>
<p><strong>Game engines:</strong></p>
<ul>
<li>Make your own. <em>Requires C/C++. Low level. Really, really low.</em></li>
<li><a target="_blank" href="https://t.umblr.com/redirect?z=http%3A%2F%2Funity.com&amp;t=YTA4MGJkNmI1N2Q5MTUxODI4ZWNkOGEwZGVhMjA3ZDNiZmQ1ODJlYyxxRDFMV0V3eA%3D%3D&amp;b=t%3AlfGQjHHkXZBrPEtOysXejA&amp;p=http%3A%2F%2Fzephyo.tumblr.com%2Fpost%2F166397059953%2Fhello-first-off-i-want-to-say-that-i-really-love&amp;m=1">Unity</a> (?). 2<em>D/3D. Requires Javascript/C#. Mid-level. Cross-platform.</em></li>
<li><a target="_blank" href="https://t.umblr.com/redirect?z=https%3A%2F%2Fwww.unrealengine.com&amp;t=NjMyOGZkMjcyNDA3ZmUwN2JhNGI4NzA1MTFlOTNkMWRiZWM4MTMxMSxxRDFMV0V3eA%3D%3D&amp;b=t%3AlfGQjHHkXZBrPEtOysXejA&amp;p=http%3A%2F%2Fzephyo.tumblr.com%2Fpost%2F166397059953%2Fhello-first-off-i-want-to-say-that-i-really-love&amp;m=1">Unreal Engine</a>. <em>2D/3D. Requires C++. Mid-level. Cross-platform. Notes: 2D support is not great.</em></li>
<li><a target="_blank" href="http://www.pixijs.com/">pixi.js</a> (?). <em>2D. Requires Javascript. Mid-level. Web.</em></li>
<li><a target="_blank" href="https://t.umblr.com/redirect?z=https%3A%2F%2Fwww.yoyogames.com%2Fgamemaker&amp;t=ODE1NjZlZGViNGRlZjAyNjIwODhkNWNmYThmNmJhMDI2N2FlM2ZmYyxxRDFMV0V3eA%3D%3D&amp;b=t%3AlfGQjHHkXZBrPEtOysXejA&amp;p=http%3A%2F%2Fzephyo.tumblr.com%2Fpost%2F166397059953%2Fhello-first-off-i-want-to-say-that-i-really-love&amp;m=1">GameMaker Studio</a>. <em>2D/3D. Requires GML. Beginner level. Cross-platform.</em></li>
<li><a target="_blank" href="https://coronalabs.com/">Corona</a>. <em>2D. Requires Lua. Beginner level. Cross-platform.</em></li>
</ul>
<p><strong>IDEs:</strong></p>
<ul>
<li>Visual Studio Code (?). F<em>or MacOS. Gives me no lag and has awesome, VSCode-exclusive features (such as inline reference info, quick navigation (⌘T)).</em></li>
<li>Visual Studio (?). F<em>or Windows.</em></li>
<li>MonoDevelop. <em>Comes with Unity. Tends to lag.</em></li>
</ul>
<p><strong>Free Unity assets:</strong></p>
<p>For Unity, tons of free assets exist on the Unity Asset Store, GitHub, bitbucket, and other sites. I use at least 2 in every project. Make your life easier with assets, but realize they’re not perfect. If you spot mistakes, don’t hesitate to fix them and/or ping the developers.</p>
<ul>
<li><a target="_blank" href="https://www.assetstore.unity3d.com/en/?stay#!/content/84126">TextMeshPro</a> (?).</li>
<li><a target="_blank" href="https://www.assetstore.unity3d.com/en/?stay#!/content/3595">LeanTween</a> (?).</li>
<li><a target="_blank" href="https://assetstore.unity.com/packages/templates/systems/fungus-34184">Fungus</a>.</li>
<li><a target="_blank" href="http://corgi-engine.moremountains.com/">Corgi Engine.</a></li>
<li><a target="_blank" href="http://www.pixelcrushers.com/dialogue-system/">Dialogue System</a>.</li>
<li><a target="_blank" href="https://assetstore.unity.com/packages/essentials/post-processing-stack-83912">Post Processing Stack.</a></li>
<li><a target="_blank" href="https://github.com/keijiro">Keijiro Takahashi.</a> <em>Works at Unity. Has</em> amazing <em>open source Unity visual effects projects!</em></li>
</ul>
<blockquote>
<p>Last but not least, my #1 solution for coding problems: Google!</p>
</blockquote>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*NI1eGAQJ23f8EBOI.jpg" alt="Image" width="800" height="450" loading="lazy"></p>
<h3 id="heading-4-audio">4. Audio ?</h3>
<h4 id="heading-advice-3">Advice?</h4>
<p>First: <strong>Do you want audio?</strong></p>
<p>Audio can do <a target="_blank" href="https://dl.acm.org/citation.cfm?id=2146327"><em>wonders</em> for immersion and mood</a>. But, it can cost memory.</p>
<p>If the answer’s yes, what audio?</p>
<p>Will you include <strong>music</strong>? <strong>Sound effects</strong>? <strong>Voiceovers</strong> or <strong>narration</strong>?</p>
<p>For any of the above, record and mix them in a way that matches your game’s <strong>mood</strong>. For example, Bastion uses organic mouth and instrument sounds, matching its game world. Crypt of the Necrodancer uses a blend of electronic beats and chiptune rock to match the colorful, rhythmic game.</p>
<blockquote>
<p>“Immersion is king.”  </p>
<p><a target="_blank" href="http://twvideo01.ubm-us.net/o1/vault/gdc2012/slides/Audio%20Track/KORB_DARREN_BUILD%20THAT%20WALL.pdf">-Darren Korb, Supergiant Games</a></p>
</blockquote>
<p>If your audio doesn’t match your game’s <strong>mood,</strong> it could detract from immersion. How will <em>your</em> audio match your game?</p>
<h4 id="heading-resources-3">Resources ?</h4>
<p><strong>Audio tools:</strong></p>
<ul>
<li>Logic Pro. <em>$200. MacOS only.</em></li>
<li>FL Studio (?). $<em>99–899. Has free demo.</em></li>
<li>Reaper. <em>$60–225.</em></li>
<li>Audacity (?). F<em>ree. Limited capabilities. Useful for cleaning audio.</em></li>
</ul>
<p><strong>Retro sound effect generators:</strong></p>
<ul>
<li><a target="_blank" href="http://sfbgames.com/chiptone/">Chiptone</a>.</li>
<li><a target="_blank" href="https://www.bfxr.net/">Bfxr</a>.</li>
<li><a target="_blank" href="https://www.leshylabs.com/apps/sfMaker/">Leshy SFMaker</a>.</li>
<li><a target="_blank" href="http://www.superflashbros.net/as3sfxr/">as3sfxr</a>.</li>
</ul>
<p><strong>Free sounds:</strong></p>
<ul>
<li><a target="_blank" href="http://soundcloud.com/">Soundcloud</a> (?). S_oundcloud has a t_on o<em>f gorgeous gems under Creative Commons (CC). H<a target="_blank" href="https://soundcloud.com/tilohensel/sets/creative-commons-music">ere’s a playlist to get started.</a> Make sure to provide attribution if needed.</em></li>
<li><a target="_blank" href="https://incompetech.com/music/">Incompetech</a> (?). C<em>C music. Must attribute.</em></li>
<li><a target="_blank" href="https://www.bensound.com/royalty-free-music">Bensound</a>. <em>CC music. Must attribute.</em></li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*JKnp8SVLbSaIyBtj8wyehw.gif" alt="Image" width="800" height="450" loading="lazy"></p>
<h3 id="heading-5-polish">5. Polish ?</h3>
<h4 id="heading-advice-4">Advice?</h4>
<p>Hey! You’re here! You made it; that’s <strong><em>absolutely incredible</em></strong> (I’m serious, if you get this far, I’d love to hear about your game; hit me up)!</p>
<p>You’re done.. right?</p>
<p>Well. There’s a 99.99999% chance there’re bugs.</p>
<p>It’s time to bug test.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*hAs_R5zvpdfkKKiV.gif" alt="Image" width="81" height="20" loading="lazy"></p>
<h4 id="heading-bug-testing-your-game"><strong>Bug testing your game</strong></h4>
<ol>
<li><em>Get others — not you — to play it.</em> Preferably in front of you, because if they encounter a bug, they might not realize or have a hard time describing it.</li>
<li><em>Play it on all targeted platforms.</em> It may work in the editor, but does it work where it matters? For Linux and the different versions of Android especially, I find that things get a little wonky.</li>
</ol>
<p>Alright. <strong>You’ve found a bug. What now?</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*GFIXUr8X6BwoXdgb.jpg" alt="Image" width="335" height="352" loading="lazy"></p>
<ol>
<li><em>Check the console for exceptions.</em> Found one? Great! Find the file and line number where the exception was thrown. If the exception sounds like something from Mars, Google it and learn about it. Then figure out why that line number is throwing that exception.</li>
<li><em>Still can’t figure it out? Write to console.</em> Start tossing in them log statements in the place(s) you think is causing you trouble. Print variable values, and see whether what’s printed is what’s expected. If not, fix that.</li>
<li><em>When worse comes to worse, check logs.</em> The logs of your project will give you way more info than the console. Read the last lines where the exception occurred. Google anything you don’t know. Can you fix it now?</li>
<li><em>Sleep.</em> It’ll get fixed in the morning. This is just a bad dream. Right? ?</li>
</ol>
<h4 id="heading-common-errors"><strong>Common errors</strong></h4>
<ul>
<li><em>NullReferenceException.</em></li>
</ul>
<pre><code class="lang-cpp">var.doThing(); <span class="hljs-comment">//throws NullReferenceException: Object reference not set to an instance of an object</span>
</code></pre>
<p><em>Problem:</em> You’re doing a thing on a <strong>null</strong> (nonexistent) variable.</p>
<p><em>Quick fix:</em> Check if the variable is null before doing the thing.</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">if</span>(var != null)
    {
        var.doThing(); <span class="hljs-comment">// do the thing safely!</span>
    }
</code></pre>
<ul>
<li><em>SyntaxErrorException.</em></li>
</ul>
<p><em>Problem:</em> Your code has invalid syntax.</p>
<p><em>Quick fix:</em> In the Exception message, it should tell you what character is throwing the error. Change that character.</p>
<p><em>Note:</em> If the character is a double quote, make sure you’re using dumb quotes instead of smart quotes:</p>
<pre><code class="lang-cpp"><span class="hljs-string">" //dumb quote
” //smart quote. I promise these'll give you trouble at some point in your life. ?</span>
</code></pre>
<ul>
<li>Pink or black screen.</li>
</ul>
<p><em>Possible problem:</em> Some shader can’t render.</p>
<p><em>Possible causes:</em> You’re using a 3D shader for a 2D game. Or, you’re using some shader feature unsupported by the target OS. Be sure to use mobile shaders for mobile games.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*YpNXKqqy_Nka3RYp.gif" alt="Image" width="129" height="20" loading="lazy"></p>
<p>After you’re done debugging, <strong>polish your game off by optimizing its memory usage and performance.</strong> This’ll make it download faster and heat up people’s devices less.</p>
<h4 id="heading-general-optimization-tips"><strong>General optimization tips</strong></h4>
<ul>
<li><a target="_blank" href="http://resetoter.cn/UnityDoc/ScriptReference/Application-targetFrameRate.html"><em>Set the target frame rate.</em></a> The frame rate could be 20 for a visual novel or 60 for a first-person shooter. A lower than default target frame rate allows the game to spend less time rendering frames.</li>
<li><em>Animation / <a target="_blank" href="https://blogs.unity3d.com/2016/12/20/unitytips-particlesystem-performance-culling/">particles</a> / <a target="_blank" href="https://docs.unity3d.com/Manual/OcclusionCulling.html">occlusion culling</a>.</em> Culling means that things invisible to the camera aren’t rendered. Characters’ll only animate, particles’ll only update, and 3D models will only be rendered when in view.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*--aqZp6ZFl7wMVWI.jpg" alt="Image" width="800" height="259" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*sOU-nKokr1HlJP3a.jpg" alt="Image" width="800" height="259" loading="lazy"></p>
<ul>
<li><em>Compress textures and audio.</em> <a target="_blank" href="https://blogs.unity3d.com/2017/12/15/crunch-compression-of-etc-textures/">Crunch compress textures.</a> <a target="_blank" href="https://medium.com/@hex3r_/making-your-unity-game-scream-and-shout-and-not-killing-it-in-the-process-673a7384693c">Stream music and decompress sound effects on load.</a> Decrease the audio quality. Note that compression may or may not decrease the quality of assets noticeably.</li>
<li><a target="_blank" href="https://unity3d.com/learn/tutorials/topics/scripting/object-pooling"><em>Object pooling.</em></a> Avoid instantiating and destroying many objects at once to prevent huge spikes. Instead, object pool them in a List, Queue, or other data structure. Things like bullets should be object pooled.</li>
<li><a target="_blank" href="https://create.unity3d.com/Unity-UI-optimization-tips"><em>Don’t let raycasts hit things that don’t need input.</em></a> Raycasts are like little rays that shoot from your fingers or mouse everytime you tap or click. Remove objects that don’t react to those inputs from raycast calculations.</li>
</ul>
<h4 id="heading-if-youre-up-for-a-challenge"><strong>If you’re up for a challenge:</strong></h4>
<ul>
<li><em>Optimize shaders.</em> Give each renderer a material. This’ll save resources in the beginning since the game doesn’t have to create new materials for everything. Have the shader for the material only include what’s functionally needed (for example, a button that doesn’t need masking can use a Sprite shader instead).</li>
<li><em>In Unity, <a target="_blank" href="https://blogs.unity3d.com/2017/04/12/asset-bundles-vs-resources-a-memory-showdown/">Use AssetBundles instead of Resources.</a></em> AssetBundles will save memory by pulling from online (e.g. dropbox) or local storage (e.g. hard disk). I haven’t tried too much due to the poor documentation, though.</li>
</ul>
<h4 id="heading-resources-4">Resources ?</h4>
<p>All of these are from Unity but can be applicable to other engines.</p>
<p><strong>Scripts:</strong></p>
<ul>
<li><a target="_blank" href="https://unity3d.com/learn/tutorials/topics/performance-optimization/optimizing-scripts-unity-games">Optimizing scripts in Unity games</a> (?)</li>
</ul>
<p><strong>Art:</strong></p>
<ul>
<li><a target="_blank" href="https://unity3d.com/learn/tutorials/topics/best-practices/guide-optimizing-unity-ui">A guide to optimizing Unity UI</a> (?)</li>
<li><a target="_blank" href="https://docs.unity3d.com/Manual/HOWTO-ArtAssetBestPracticeGuide.html">Art Asset best practice guide</a> (?)</li>
</ul>
<p><strong>Memory:</strong></p>
<ul>
<li><a target="_blank" href="https://docs.unity3d.com/Manual/ReducingFilesize.html">Reducing the file size of your build</a> (?)</li>
<li><a target="_blank" href="https://docs.unity3d.com/Manual/BestPracticeUnderstandingPerformanceInUnity2.html">Memory</a></li>
</ul>
<p><strong>Platform-specific:</strong></p>
<ul>
<li><a target="_blank" href="https://docs.unity3d.com/Manual/MobileOptimizationPracticalGuide.html">Practical guide to optimization for mobiles</a> (?)</li>
<li><a target="_blank" href="https://docs.unity3d.com/Manual/webgl-performance.html">WebGL performance considerations</a> (?)</li>
<li><a target="_blank" href="https://docs.unity3d.com/Manual/webgl-memory.html">Memory Considerations when targeting WebGL</a> (?)</li>
<li><a target="_blank" href="https://unity3d.com/how-to/optimize-mobile-VR-games">Olly’s seven stages of optimizations for mobile VR</a></li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*0kiegwenNUvH_1CV.png" alt="Image" width="800" height="412" loading="lazy"></p>
<h3 id="heading-6-market">6. Market ?</h3>
<h4 id="heading-advice-5">Advice?</h4>
<p><strong>Congrats!</strong> ?? You’ve made something. It’s time to show the world what you’ve made.</p>
<p>Personally, marketing is my most anxiety-inducing stage. If you, too, get doubtful, the <strong>game developer community</strong> is helpful. You’re not alone in this. And you’ve come so far — might as well get through to the end, right?</p>
<blockquote>
<p>You’ll never know if it’ll be a hit unless you try.</p>
</blockquote>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*qFXvryTQVsP8UCcn.gif" alt="Image" width="80" height="20" loading="lazy"></p>
<ol>
<li><strong>Draft.</strong> Create drafts of your game page on all your targeted game distribution platforms. Find a list of platforms in <strong>Resources</strong> below.</li>
<li><strong>Network.</strong> If you go the full networking mile, you’ll want to email <strong>game press</strong>, showcase in <strong>festivals</strong>, and attend <strong>conferences</strong>.</li>
</ol>
<p><em>With game press,</em> email your unlisted game page a week before release. Give people some time to write about it. It’s likely they won’t write about it at all. I’ve found that press loves a compelling developer story, unique/controversial concept, and, most importantly, a <a target="_blank" href="http://dopresskit.com/">presskit</a>.</p>
<p><strong>How do you find emails?</strong> You can..</p>
<ol>
<li>Find writers you like and Google their name. Their email is bound to come up somewhere: Twitter, LinkedIn, etc. Or..</li>
<li>Find the magazine/new’s company-wide email on their <em>About</em> page. It’s usually in the format of <strong>tips@company.com.</strong></li>
</ol>
<p><strong>Do not</strong> email press about your game if they explicitly don’t cover your genre/targeted platform.</p>
<p><em>Festivals</em> can get you awards and/or professional recognition by other developers and press.</p>
<p><em>Conferences</em> are what you make of it: they can be all about networking with other developers, companies, and press (go get them business cards!); updating your latest game dev know-how; playing others’ games; or meeting up with internet friends.</p>
<p>Game conference tickets are <em>expensive.</em> If you’re a student, think about applying for scholarships for them. The <a target="_blank" href="http://scholars.igdafoundation.org/">IGDA Scholars program</a> gives you some especially amazing networking and event opportunities.</p>
<ol start="3">
<li><p><strong>Youtubers/Streamers.</strong> You can get video coverage of your game by:</p>
</li>
<li><p><em>Ranking high</em> on game distribution platforms.</p>
</li>
<li><em>Emailing.</em> If you email, don’t talk about yourself; talk about the game. Keep it sweet, short, and compelling. Use eye-catching photos and gifs.</li>
</ol>
<p><strong>How do you find emails?</strong> Look at their About page. If you can’t find it there, Google them and see if their other social media have it.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*8Y35x-rZIuBapR5WFNpFqQ.png" alt="Image" width="800" height="410" loading="lazy">
<em>’tis an email</em></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*ISj787elwqyMUQOHo3o40g.png" alt="Image" width="800" height="430" loading="lazy">
<em><em>dances in the air</em></em></p>
<ol start="4">
<li><strong>Social media.</strong></li>
</ol>
<p>Social media is an <em>amazing</em> marketing tool. <a target="_blank" href="https://www.rockpapershotgun.com/2018/02/22/the-rise-and-rise-of-io-games/">Agar.io found its rise from 4chan</a>, <a target="_blank" href="https://twitter.com/brii_u/status/909114732287627264?lang=en">Butterfly Soup got mad boosts from Twitter</a>, and some form of social media always ends up in my top 4 referrers:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*9zJi8w4bKAqD4FlAmlc6DA.png" alt="Image" width="800" height="127" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*XXB_AREPwK0K0ozaTaBKNg.png" alt="Image" width="800" height="126" loading="lazy">
<em>Live Portrait Maker (left), YOU LEFT ME. (right)</em></p>
<p>My favorite social media platforms for marketing are in <strong>Resources</strong> below.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*Z0LdyJ-sK4zD3-iZ.gif" alt="Image" width="80" height="20" loading="lazy"></p>
<p><strong>A last note</strong> — <strong>Publisher or self-publish?</strong> Game marketing is a lot. Do you want a publisher to take care of all that? Want to go the Hotline Miami x Devolver Digital route, or rely on Farmville and Doki Doki Literature Club’s word-of-mouth?</p>
<p>With a publisher, you’ll have to do your research to find a good one. After, you’ll sign paperwork and go through legal hoops. Plus, it’s a huge financial investment.</p>
<p>By yourself, you’ll have to put a lot of time and effort into learning marketing. You may love it. You may hate it. And you might not do a great job of it, either. But it’s free, and you learn valuable skills.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*abfGrvwSMrEaha8ViVHzww.png" alt="Image" width="800" height="479" loading="lazy">
<em>Yay organic, self-publishing growth~ (But is it non-GMO though?)</em></p>
<p>For me, I’ll always self-publish. <em>I love learning new things. Also, I firmly believe that a truly great game will succeed no matter what, as long as</em> some <em>marketing effort was put.</em></p>
<ol start="6">
<li>Hit that <strong>Publish</strong> button!</li>
</ol>
<p>??Yooo, you D<strong>ID i</strong>t!! ?Now relax, sit back, grab a yummy drink, and take some time for yourself! You’ve worked so hard. You deserve it.</p>
<p>And remember that, even if your game doesn’t get the reception you expected, that’s ok. It’s not gonna be perfect your first time. My first game on Steam only has 255 downloads.</p>
<p>The facts are, you made a game. You learned so much. That’s enough.</p>
<p>And there’s always a next time!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*oSrrX_kk-L4Lwion.gif" alt="Image" width="76" height="20" loading="lazy"></p>
<h4 id="heading-resources-5">Resources ?</h4>
<p><strong>Game distribution platforms:</strong></p>
<ul>
<li><a target="_blank" href="https://store.steampowered.com/">Steam</a> (?). P<em>C. Requires $100 USD fee per game.</em></li>
<li><a target="_blank" href="https://www.origin.com/">Origin</a>. <em>PC.</em></li>
<li><a target="_blank" href="https://www.gog.com/">GOG</a>. <em>PC. Free to publish. Game must get accepted.</em></li>
<li><a target="_blank" href="https://developer.apple.com/macos/distribution/">Mac App Store</a>. <em>MacOS. Requires Apple Developer account.</em></li>
<li><a target="_blank" href="http://itch.io/">itch.io</a> (?). P<em>C/Web. Free to publish.</em></li>
<li><a target="_blank" href="http://gamejolt.com/">Game Jolt</a> (?). P<em>C/Web. Free to publish.</em></li>
<li><a target="_blank" href="http://developers.armorgames.com/">Armor Games</a> (?). F<em>ree to publish. Must apply to be a developer.</em></li>
<li><a target="_blank" href="http://www.kongregate.com/">Kongregate</a> (?). W<em>eb. Free to publish.</em></li>
<li><a target="_blank" href="http://www.newgrounds.com/">Newgrounds</a> (?). W<em>eb. Free to publish.</em></li>
<li><a target="_blank" href="https://github.com/">GitHub</a> (?). W<em>eb. Free to publish on your own site with domain name formatted as “</em><strong>__.github.io”</strong>._</li>
<li><a target="_blank" href="https://developer.amazon.com/app-submission">Amazon.</a> <em>Web/Mobile. Free to publish.</em></li>
<li><a target="_blank" href="https://play.google.com/store">Google Play</a> (?). M<em>obile. Requires one-time $25 USD fee.</em></li>
<li><a target="_blank" href="https://itunes.apple.com/us/genre/ios">iOS App Store</a> (?). M<em>obile. Requires Apple Developer account.</em></li>
</ul>
<p><strong>Game press:</strong></p>
<ul>
<li><a target="_blank" href="http://indiegames.com/">IndieGames.</a></li>
<li><a target="_blank" href="http://www.siliconera.com/">Siliconera.</a></li>
<li><a target="_blank" href="https://www.freegameplanet.com/live-portrait-maker-browser-game/">FreeGamesPlanet</a>. <em>Super nice admin.</em></li>
<li><a target="_blank" href="https://www.pcgamer.com/">PCGamer.</a></li>
<li><a target="_blank" href="https://kotaku.com/">Kotaku.</a></li>
<li><a target="_blank" href="https://www.rockpapershotgun.com/">Rock Paper Shotgun.</a></li>
<li><a target="_blank" href="https://www.polygon.com/gaming/2012/9/17/3348450/zynga-a-bit-lucky-acquisition-zynga-san-francisco-john-tobias">Polygon.</a></li>
<li><a target="_blank" href="https://www.giantbomb.com/florence/3030-66441/similar-games/">Giant Bomb.</a></li>
<li><a target="_blank" href="https://www.eurogamer.net/">EuroGamer.</a></li>
</ul>
<p><strong>Game festivals:</strong></p>
<ul>
<li><a target="_blank" href="http://www.igf.com/">Independent Games Festival (IGF).</a> <em>Deadline around October.</em></li>
<li><a target="_blank" href="https://www.indiecade.com/">Indiecade.</a> <em>Deadline around May/June.</em></li>
<li><a target="_blank" href="https://www.gameawards.se/">Swedish Game Awards.</a> <em>Deadline around July.</em></li>
<li><a target="_blank" href="https://gaming.sxsw.com/awards/">South by Southwest Festival (SXSW)</a>. <em>Deadline around December.</em></li>
<li><a target="_blank" href="http://thegameawards.com/">The Game Awards.</a> <em>Deadline around November.</em></li>
</ul>
<p><strong>Game conferences:</strong></p>
<ul>
<li>Game Developer’s Conference (GDC). <em>San Francisco.</em></li>
<li>Penny Arcade Expo (PAX). <em>Seattle/Boston/Philadelphia/Melbourne.</em></li>
<li>Electronic Entertainment Expo (E3). <em>Los Angeles.</em></li>
<li>Tokyo Game Show. <em>Japan.</em></li>
<li>Steam Dev Days. <em>Seattle. For Steam developers only.</em></li>
</ul>
<p><strong>Emailing:</strong></p>
<ul>
<li><a target="_blank" href="http://dopresskit.com/">presskit()</a></li>
</ul>
<p><strong>Social media:</strong></p>
<ul>
<li>reddit (?). P<em>ick an appropriate subreddit. Some of my favorites are /r/WebGames,</em> <em>/r/IndieGaming/, and /r/visualnovels.</em></li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*uXjTNgJQLRD6GxREPjLWZg.png" alt="Image" width="800" height="278" loading="lazy">
<em>/r/WebGames.</em></p>
<ul>
<li>Facebook (?). P<em>ost on your Facebook Page (if you have one) and personal facebook (if you’re comfortable). There’s also tons of Facebook Groups where you can show off your game! Here’s some:</em></li>
</ul>
<p><a target="_blank" href="https://www.facebook.com/groups/GameDevShowAndTest"><strong>GameDev Show and Test</strong></a><br><a target="_blank" href="https://www.facebook.com/groups/GameDevShowAndTest"><em>Welcome to GameDev Show and Test - a sister group to the Indie Game developer groups. The purpose of this group is to…</em></a></p>
<p><a target="_blank" href="https://www.facebook.com/groups/IndieGameDevs/"><strong>Indie Game Developers</strong></a><br><a target="_blank" href="https://www.facebook.com/groups/IndieGameDevs/"><em>Independent Game Developers group for small companies and individuals designing and publishing their own games. **READ…</em></a></p>
<p><a target="_blank" href="https://www.facebook.com/groups/IndieGamePromo/1066211690197686/"><strong>Indie Game Promo</strong></a><br><a target="_blank" href="https://www.facebook.com/groups/IndieGamePromo/1066211690197686/"><em>Indie Game Promo has 47,645 members. Sister group to Indie Game Dev and Indie Game Chat for the purpose of promoting…</em></a></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*I4pg-w5UL-nkA4IOSqndpw.png" alt="Image" width="800" height="870" loading="lazy">
<em>Indie Game Promo.</em></p>
<ul>
<li>Tumblr (?).</li>
<li>Twitter (?). T<em>ry using tags like #gamedev, #indiedev, and #screenshotsaturday to get discovered.</em></li>
</ul>
<p><strong>Community:</strong></p>
<ul>
<li><a target="_blank" href="https://www.reddit.com/r/gamedev">/r/gamedev</a> (?).</li>
<li><a target="_blank" href="https://ldjam.com/">Ludum Dare</a> (?).</li>
<li><a target="_blank" href="https://www.facebook.com/groups/IndieGameDevs/">Indie Game Devs</a> (?).</li>
</ul>
<h3 id="heading-conclusion"><strong>Conclusion</strong></h3>
<p>There’s no cheat code to making a game. It’s just a lot of determination and effort.</p>
<blockquote>
<p>“Behind every Half Life, Minecraft and Uncharted, there are OCEANS of blood, sweat and tears.”  </p>
<p><a target="_blank" href="https://medium.com/@IGLevine/so-lots-of-people-have-responded-to-my-encouragement-to-get-into-the-industry-asking-how-do-i-get-e2d0cd738733">— Ken Levine</a></p>
</blockquote>
<p>You’ll get confused. You’ll make mistakes. You might even cry (I did—and still do).</p>
<p>But that’s okay. It means you’re growing. If you‘re putting in that much effort, I believe in you and your game: <strong>You can do it.</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*IH1bpE4Hf0crXYVd." alt="Image" width="540" height="540" loading="lazy">
<em>supportive foxtato by Emily’s Diary</em></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*cc_Fm6yLJIZaCGRB.gif" alt="Image" width="80" height="20" loading="lazy"></p>
<p>If you liked reading my first article, be sure to give a ?(or several — did you know you can give more than one?) It’d mean the world ?</p>
<p>You can also follow/DM me on <a target="_blank" href="https://twitter.com/zephybite">Twitter</a>, <a target="_blank" href="http://zephyo.tumblr.com/">Tumblr</a>, and <a target="_blank" href="https://github.com/zephyo">GitHub</a>, and <a target="_blank" href="https://ko-fi.com/J3J6DIQC">buy me a coffee</a> if you wish.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
