<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Braeden Richards</title>
    <description>The latest articles on DEV Community by Braeden Richards (@braeday).</description>
    <link>https://dev.to/braeday</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F918228%2F9588cd09-bd1b-4353-8413-a1bb20354c7a.jpg</url>
      <title>DEV Community: Braeden Richards</title>
      <link>https://dev.to/braeday</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/braeday"/>
    <language>en</language>
    <item>
      <title>Forest Defender Devlog 2: Basic Camera and Movement</title>
      <dc:creator>Braeden Richards</dc:creator>
      <pubDate>Fri, 28 Oct 2022 17:59:12 +0000</pubDate>
      <link>https://dev.to/braeday/forest-defender-devlog-2-basic-camera-and-movement-62m</link>
      <guid>https://dev.to/braeday/forest-defender-devlog-2-basic-camera-and-movement-62m</guid>
      <description>&lt;h2&gt;
  
  
  Forest Defender Devlog 2: Basic Camera and Movement
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Written on October 28th, 2022&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
 Preface 

&lt;ul&gt;
&lt;li&gt; General Accomplishments &lt;/li&gt;
&lt;li&gt; Why movement and camera motion is so important &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt; Movement &lt;/li&gt;
&lt;li&gt;
 Gravity and Collisions 

&lt;ul&gt;
&lt;li&gt; Gravity &lt;/li&gt;
&lt;li&gt; A bit about aspects&lt;/li&gt;
&lt;li&gt; Collisions &lt;/li&gt;
&lt;li&gt; Other Additions &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt; Camera Enhancements &lt;/li&gt;
&lt;li&gt; Finishing Notes &lt;/li&gt;
&lt;li&gt; Resources / Further Reading &lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--maLz3knc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r141ab70wqjtase7jrh5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--maLz3knc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r141ab70wqjtase7jrh5.gif" alt="GIF of current game state." width="426" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This week's results of development. Each piece will be explained below.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;a id="preface"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;&lt;a id="general-accomplishments"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  General Accomplishments
&lt;/h4&gt;

&lt;p&gt;Since the previous devlog, &lt;a href="https://dev.to/braeday/forest-defender-devlog-1-development-setup-21a2"&gt;Forest Defender: development setup&lt;/a&gt;, a lot of groundwork has been completed. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9gYRUHq---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/249geoizgj75cnz6rs12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9gYRUHq---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/249geoizgj75cnz6rs12.png" alt="Spritesheet" width="320" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now have created a simple tileset. After some searching for a nice but small color palette, we settled on using the &lt;a href="https://www.schemecolor.com/wild-jungle.php"&gt;Wild Jungle Color Scheme&lt;/a&gt; as it had the right feel of jungle vibes. It is also very narrow in its color range, really just being brown and green, which is exactly what we were looking for. I am a big fan of games built around minimal color differences since it reminds me of original Nintendo GameBoy games. In the created tileset, you can see we have just a handful of tiles to start with and two entities: a mushroom entity and the player. These will be expanded into animations later on.&lt;/p&gt;

&lt;p&gt;We then took that tileset and created a basic testing level for movement by using &lt;a href="https://www.mapeditor.org/"&gt;Tiled&lt;/a&gt;. Building the level is easy and there are plenty of tutorials for reading the export from Tiled into a Python project via a custom import function. I will have a couple tutorials and examples linked in the further reading section at the end of this devlog.&lt;/p&gt;

&lt;p&gt;Once the level was created, we plopped in our player's character and added in some gravity and controls. Using force based physics, it is easy to tweak movement to feel just right. We also added in a nice camera to follow the player around to get the first steps of this project complete. I have detailed how I did these movement and physics additions in the following sections.&lt;/p&gt;

&lt;p&gt;&lt;a id="movement-importance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Why movement and camera motion are the most important piece of a game
&lt;/h4&gt;

&lt;p&gt;General motion of the game (camera and player movement) is often overlooked by first time game developers. Many people either put in a simple system early on and work on improving it later in development, or they just use an out of the box solution. In my opinion, general motion is the most important part of a game and should be designed and made as perfect as possible for your end goal at the beginning of development. I am willing to play most games with great motion feel regardless of graphics, animation, etc. but I will usually get frustrated in a game if there are lots of collision problems, clunky movement, etc. even with beautiful graphics.&lt;/p&gt;

&lt;p&gt;Let's start with what makes good movement in a game. In general, good movement refers to smooth motion, intuitive controls, and accurate collisions. Since there are various types of games, all with different ideal movements, let's just focus on our Forest Defender game. &lt;/p&gt;

&lt;p&gt;Since our game is 2-D, collisions are pretty easy. We really only need to worry about vertical collisions and horizontal collisions. We aren't going to have any tiles with special collision properties (such as steep slopes), so there isn't much more to plan for.&lt;/p&gt;

&lt;p&gt;Our character is a 'fairy' type creature, so we designed the sprite with wings. While this won't help the fairy fly, this helps the character not fall too quickly and lets the player change direction mid-air. Therefore, when the character is falling or has jumped we want the player to be able to still move the character left and right just like the player was still on the ground.&lt;/p&gt;

&lt;p&gt;Camera movement comes in too many varieties to describe them all. For our game, we are going with a simple camera movement. Essentially, when your character moves right, the camera moves right. When your character moves left, your camera moves left, etc. The biggest quality of life enhancement we are making to the camera is to give it a slight delay in its movement by using forces on the camera. This gives the camera a smoother look instead of jarring motion. This will be described more further down in this devlog.&lt;/p&gt;




&lt;p&gt;&lt;a id="movement"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Movement
&lt;/h2&gt;

&lt;p&gt;The goal of our character movement is to be smooth and intuitive while fitting the character design.&lt;/p&gt;

&lt;p&gt;Keeping motion smooth is generally easy. We will be using a force based system. So if the player presses the key to move right, a force will be applied to the character and it's acceleration will raise. The acceleration is then applied to the character's velocity each frame, which will move the character's position. The calculations are below, with dt being the time between last frame and current frame to make sure this process is frame-rate independent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;force&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;
&lt;span class="n"&gt;acceleration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;acceleration&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;force&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acceleration&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="gravity-collisions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Gravity and Collisions
&lt;/h2&gt;

&lt;p&gt;&lt;a id="gravity"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Gravity
&lt;/h4&gt;

&lt;p&gt;Gravity as a concept in 2-D physics is relatively straightforward: if down in the window is the ground, that is where the acceleration of gravity will point.&lt;/p&gt;

&lt;p&gt;&lt;a id="aspects"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To add gravity to our character (and any future entities), we will include it as an &lt;em&gt;aspect&lt;/em&gt;. An &lt;em&gt;aspect&lt;/em&gt; is essentially an additional property you can add to an entity in the Python game engine we are creating for this project. To explain it simply, each entity can have 0+ &lt;em&gt;aspects&lt;/em&gt; that it runs through each frame of the game. These &lt;em&gt;aspects&lt;/em&gt; can be for animation, physics, random checks, etc. We could create each of these as their own function or class, but that would make our entity class contain many properties that need to be maintained and entered individually. Instead, we can have a base &lt;em&gt;aspect&lt;/em&gt; class that other classes, like our gravity or physics movement, can inherit from. Then, we can simply add this new &lt;em&gt;aspect&lt;/em&gt; into a list of &lt;em&gt;aspects&lt;/em&gt; the entity holds onto and runs through each frame. Much easier and cleaner!&lt;/p&gt;

&lt;p&gt;Back to gravity. Since in our game gravity will always be pointing downward in the window, we can just give the gravity acceleration a positive &lt;em&gt;y&lt;/em&gt; value. This is because in Pygame, downward is a positive value and upward is a negative value. You will notice I mentioned giving gravity a positive &lt;strong&gt;acceleration&lt;/strong&gt;, not a &lt;strong&gt;force&lt;/strong&gt;. This is due to gravity being a constant, and therefore the acceleration never changes.&lt;/p&gt;

&lt;p&gt;To add our gravity in, we do a calculation very similar to the calculation for our movement, since it is essentially the same thing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;acceleration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;acceleration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gravity&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acceleration&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we only modify the y value of the vectors since gravity only affects the player's vertical position. The result can be seen in the GIF below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J55d7Pdc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zr7dhpxip710op4u7ghe.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J55d7Pdc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zr7dhpxip710op4u7ghe.gif" alt="GIF showing gravity working in the game." width="426" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="collisions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Collisions
&lt;/h4&gt;

&lt;p&gt;Collisions can become as complicated as you need them to be. For us, collisions will be on the simpler side. We will only be adding vertical collisions and horizontal collisions. Put even simpler, checking if an entity hits an object with the top of its head or the bottom of its body, or if it hits an object with the left or right side of its body.&lt;/p&gt;

&lt;p&gt;While it sounds easy and simple, the code for this still looks a bit complicated. In the code snippet below, we are adding the movement to the entity in the x and y directions, then checking if it is within (therefore &lt;em&gt;hitting&lt;/em&gt;) another object. For checking if there is a hit, we are using Pygame's built in sprite hit detection function &lt;em&gt;colliderect&lt;/em&gt;. In the snippet, this is called with self.get_hits(tiles) which is a wrapper function I wrote and is included below.&lt;/p&gt;

&lt;p&gt;If there was a collision detected with the entity, we add that hit to the collision_type dictionary to be referenced later in repositioning the entity so they are just outside the collided object (therefore colliding instead of going through). We also modify the velocity of the entity so the entity loses its inertia upon a collision.&lt;/p&gt;

&lt;p&gt;The code we used for now is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_hits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tiles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tile&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;colliderect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tile&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tiles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;collision_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bottom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"right"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"left"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;
        &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_hits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tiles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tile&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;
                &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
                &lt;span class="n"&gt;collision_types&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"right"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;
                &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
                &lt;span class="n"&gt;collision_types&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"left"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;
        &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_hits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tiles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tile&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bottom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;
                &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
                &lt;span class="n"&gt;collision_types&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"bottom"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bottom&lt;/span&gt;
                &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
                &lt;span class="n"&gt;collision_types&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;collision_types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="other-physics"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Other
&lt;/h4&gt;

&lt;p&gt;Besides the above mentioned additions to the game, we mainly added quality of life additions. These mainly include applying maxes to velocity so the player can't move infinitely fast, a slight delay allowed when jumping i.e. you can be a few frames off a platform (like walking off) and still be able to jump, which improves the feeling of the game, and small force tweaks.&lt;/p&gt;

&lt;p&gt;The applying of maxes is simple, as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_maxes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_speed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_speed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_speed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_speed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_speed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_speed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_jump_speed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_jump_speed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;a id="camera-enhancements"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Camera Enhancements
&lt;/h2&gt;

&lt;p&gt;Basic camera movement is easy to implement. Simply place your camera's center position on the player character at the end of each frame when all the updates are done. This leads to harsh behavior of the camera though. The motion of the camera would feel jarring when changing directions.&lt;/p&gt;

&lt;p&gt;We resolved this by instead applying forces to the camera for movement. Essentially we take the difference in position between the player's center and the camera's center positions and apply that to the default force applied to the camera. This means the further away the camera is from the player, the faster the camera will move toward the player. This is done easily in the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;centerx&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;centery&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives a sort of 'lag behind' motion of the camera that smooths any jarring movements. You can see that in the GIF below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uHrP4Jri--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/58vsu0ca17s6jn3lki8g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uHrP4Jri--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/58vsu0ca17s6jn3lki8g.gif" alt="GIF showing smoothed camera motion." width="426" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that instead of the camera being exactly on the player at all times, the camera sort of 'lags' behind the player. The distance * force feature we have added means the camera will never fall too far behind.&lt;/p&gt;




&lt;p&gt;&lt;a id="conclusion"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finishing Notes
&lt;/h2&gt;

&lt;p&gt;That is about all that was completed during this last bit of development. I will try to get these blogs out at least every two weeks, though the next few may be quicker since I have a lot of development worked on and just need to get it into devlogs.&lt;/p&gt;

&lt;p&gt;If you have any questions, feel free to leave a comment and I will do my best to answer it!&lt;/p&gt;




&lt;p&gt;&lt;a id="resources"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources / Further Reading
&lt;/h2&gt;

&lt;p&gt;&lt;b&gt; Reading from Tiled into Python &lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pygame.org/project-Tiled+TMX+Loader-2036-.html"&gt;Pygame&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=37phHwLtaFg&amp;amp;ab_channel=CDcodes"&gt;CDcodes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt; Resources for Physics &lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=OmkAUzvwsDk"&gt;DaFluffyPotato Frame Independence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=abH2MSBdnWc&amp;amp;t=1291s"&gt;DaFluffyPotato Physics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://quorumlanguage.com/tutorials/physics/forceandvelocity2D.html"&gt;Quorum&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt; Other &lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.aseprite.org/"&gt;Aseprite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pygame.org/news"&gt;Pygame&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mapeditor.org/"&gt;Tiled&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gamedev</category>
      <category>pygame</category>
      <category>python</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Forest Defender Devlog 1: Development Setup</title>
      <dc:creator>Braeden Richards</dc:creator>
      <pubDate>Wed, 26 Oct 2022 21:35:08 +0000</pubDate>
      <link>https://dev.to/braeday/forest-defender-devlog-1-development-setup-21a2</link>
      <guid>https://dev.to/braeday/forest-defender-devlog-1-development-setup-21a2</guid>
      <description>&lt;h1&gt;
  
  
  Forest Defender Devlog 1: Development Setup
&lt;/h1&gt;



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

&lt;p&gt;&lt;a href="https://www.freepik.com/free-vector/video-game-developer-concept-illustration_13746511.htm#query=game%20development&amp;amp;position=3&amp;amp;from_view=keyword" rel="noopener noreferrer"&gt;Image by storyset&lt;/a&gt; on Freepik&lt;/p&gt;

&lt;p&gt; Written on October 25th, 2022&lt;/p&gt;



&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; Preface &lt;/li&gt;
&lt;li&gt; Development Machine &lt;/li&gt;
&lt;li&gt; Development Tool Installation / Updating &lt;/li&gt;
&lt;li&gt; Virtual Environment &lt;/li&gt;
&lt;li&gt; Installing Libraries &lt;/li&gt;
&lt;li&gt; Checking Everything Works! &lt;/li&gt;
&lt;li&gt; Resources / Further Reading &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="preface"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;The goal of this devlog is to show how I set up my environment for development of this game. Future devlogs will focus on higher level topics, such as game development updates, topics and discussion of the game, etc., instead of lower level topics like this devlog.&lt;/p&gt;

&lt;p&gt;That is not to say I won't go into any details / code in future devlogs. If there is an interesting challenge I face or a topic I think is helpful to explain or show, I will certainly add it to the devlog.&lt;/p&gt;

&lt;p&gt;&lt;a id="development-machine"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  What will be used as the development machine?
&lt;/h2&gt;



&lt;p&gt;The development machine chosen to create a game is important as it sets the main target OS for the game build, creates the subset of tools that can be used, and sets the development environment as a whole.&lt;/p&gt;

&lt;p&gt;My development machine is a Windows 10 desktop computer. The specifications are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Motherboard: ASUS ROG STRIX Z390-E Gaming&lt;/li&gt;
&lt;li&gt;Processor: Intel Core i9 9900k&lt;/li&gt;
&lt;li&gt;RAM: 32GB of CORSAIR 3.0GHz DDR4&lt;/li&gt;
&lt;li&gt;Storage:

&lt;ul&gt;
&lt;li&gt;Samsung 970 EVO Plus 500GB&lt;/li&gt;
&lt;li&gt;Samsung 970 EVO Plus 500GB (second one)&lt;/li&gt;
&lt;li&gt;Western Digital 1TB Hard drive&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Graphics Card: NVIDIA GeForce RTX 2080 SUPER&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This machine is certainly overkill for any development we are doing at this scale, especially since we are working on a 2-D game using Python. The machine also serves as a gaming computer for me, which is why these are its specifications.&lt;/p&gt;

&lt;p&gt;Since I am using Windows 10 as my development OS, we are locked into tools that are available on Windows 10. While this does cut off a lot of Linux tools, we are still left with plenty. We are also locked into targeting Windows 10 for the main audience for the game. Python and the libraries we are using are able to run on the three major operating systems (Windows, macOS, Linux), but we will be testing and developing on the above system, so any testing on Linux and macOS will come at the end of development.&lt;/p&gt;

&lt;p&gt;Ultimately, this is perfectly fine since most games are released on Windows versus the other operating systems and therefore most gamers use Windows to play games. So our audience is still the biggest 'chunk' of people.&lt;/p&gt;

&lt;p&gt;&lt;a id="installation-updating"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Development Tool Installation / Updating
&lt;/h2&gt;



&lt;p&gt;We won't be needing too many tools to get started with this project. We will install the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VS Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.aseprite.org/" rel="noopener noreferrer"&gt;Aseprite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mapeditor.org/" rel="noopener noreferrer"&gt;Tiled&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;VS Code will be used as our text editor of choice. This is for planning of the game, project file management, and writing the actual code.&lt;/p&gt;

&lt;p&gt;Aseprite will be used to create all the assets for the game, including the animations.&lt;/p&gt;

&lt;p&gt;Tiled is our choice for taking those assets created in Aseprite and using them to create levels.&lt;/p&gt;

&lt;p&gt;&lt;a id="virtual-environment"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Virtual Environment
&lt;/h2&gt;



&lt;p&gt;We want to keep our environment (module installations, Python version, etc.) separate from the OS wide installations. In order to do so, we need to create a separate container to store the environment. The way we will achieve this during this development run will be with Python's &lt;a href="https://docs.python.org/3/library/venv.html" rel="noopener noreferrer"&gt;Virtual Environment&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is extremely easy to setup. Ensure you have some version of Python 3+ installed on your machine, and run the following in the terminal / CMD:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; python &lt;span class="nt"&gt;-m&lt;/span&gt; venv &lt;span class="nb"&gt;env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this command, we are telling Python to run the venv command, which creates a virtual environment in the current directory, and call it 'env.'&lt;/p&gt;

&lt;p&gt;To enter the virtual environment while in the Windows OS, simply traverse to the directory containing it and enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;env&lt;/span&gt;/scripts/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="installing-libraries"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Installing Libraries
&lt;/h2&gt;



&lt;p&gt;To get started with the game, we don't need too many libraries. For now, we will only be using Pygame.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;pygame
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="checking-everything-works"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Checking Everything Works!
&lt;/h2&gt;



&lt;p&gt;Now that we have the environment setup, all that is left to do before beginning with development is make sure it all works. We will be checking that the Python environment and Pygame installation were properly done. To accomplish this check, we will run the below Python script which opens a Pygame window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pygame&lt;/span&gt;

&lt;span class="n"&gt;background_color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;
&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;span class="n"&gt;window_title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Window Test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pygame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_mode&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;pygame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_caption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window_title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;background_color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;pygame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;keep_running&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;keep_running&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pygame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;pygame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QUIT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;keep_running&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the above script is run, the following window appears:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fii8vlzv2wev6a8cc0bfr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fii8vlzv2wev6a8cc0bfr.png" alt="Image of Pygame application window"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="further-reading"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Resources / Further Reading
&lt;/h2&gt;

&lt;p&gt;&lt;b&gt; Text Editor &lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VS Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://atom.io/" rel="noopener noreferrer"&gt;Atom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.jetbrains.com/pycharm/" rel="noopener noreferrer"&gt;PyCharm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sublimetext.com/" rel="noopener noreferrer"&gt;Sublime&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vim.org/" rel="noopener noreferrer"&gt;VIM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://visualstudio.microsoft.com/" rel="noopener noreferrer"&gt;Visual Studio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt; Other &lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.aseprite.org/" rel="noopener noreferrer"&gt;Aseprite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pygame.org/news" rel="noopener noreferrer"&gt;Pygame&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mapeditor.org/" rel="noopener noreferrer"&gt;Tiled&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gamedev</category>
      <category>pygame</category>
      <category>python</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Pygame: Can you make an industry-standard game?</title>
      <dc:creator>Braeden Richards</dc:creator>
      <pubDate>Fri, 02 Sep 2022 18:36:48 +0000</pubDate>
      <link>https://dev.to/braeday/pygame-can-you-make-an-industry-standard-game-125p</link>
      <guid>https://dev.to/braeday/pygame-can-you-make-an-industry-standard-game-125p</guid>
      <description>&lt;h2&gt;
  
  
  Pygame: Can you make an industry-standard game?
&lt;/h2&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NfSyLySq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rqozr5v1927llnydxrwh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NfSyLySq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rqozr5v1927llnydxrwh.png" width="640" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Written on May 10th, 2022&lt;/p&gt;



&lt;h2&gt;
  
  
  What is Pygame?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.pygame.org/docs/"&gt;Pygame&lt;/a&gt; is a game framework available for use in Python3. You may notice that I called it a framework, not a game engine. Pygame is a set of modules that act as a wrapper around &lt;a href="https://www.libsdl.org/"&gt;SDL&lt;/a&gt; (Simple DirectMedia Layer). This differs from a Game Engine which generally provides a GUI, pre-built game resources, etc. for the user. &lt;/p&gt;

&lt;p&gt;As a game framework for Python, Pygame makes window creation, sprite management, controls mapping, and more much easier for the user. I will have a series of development blogs posted on this site to show how to take advantage of Pygame's strengths to develop a &lt;a href="https://en.wikipedia.org/wiki/Shoot_%27em_up"&gt;bullet-hell&lt;/a&gt; style platformer from planning to release.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LP7j9cYI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e238a31j60vqb106fvlr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LP7j9cYI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e238a31j60vqb106fvlr.jpg" width="300" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example of bullet hell game (Enter the Gungeon)&lt;/p&gt;



&lt;h2&gt;
  
  
  Let's talk Python
&lt;/h2&gt;

&lt;p&gt;Python is known as either a godsend or slow language depending on the software developer asked. In the end, it is a tool that is amazing at some tasks and lackluster in others just like any other language. Python is generally not the first choice when creating a video game. However, with today's common computing power and C-based modules like Pygame available, Python can be plenty capable when it comes to creating a 2-dimensional game.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wzebFaZE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wgq59mmf8ldenh426s6h.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wzebFaZE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wgq59mmf8ldenh426s6h.jpg" width="735" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example of Pygame created game (Shifting Edge)&lt;/p&gt;



&lt;p&gt;Games with less assets on the screen work best for Python and Pygame. A bullet-hell genre game breaks this "light rule" since by definition it contains many assets (bullets and enemies) on screen at once. This leads to an interesting project / challenge since we will need to be careful to design a well-optimized entity manager and particle effects (which will be talked about more in the next section).&lt;/p&gt;

&lt;p&gt;Python is also plagued with the GIL, or Global Interpreter Lock, which limits the number of cores useable by a Python application to 1. Therefore while multi-threading can still function (all on a single core), multi-processing is not possible in Python without having multiple applications running with the multiprocessing library, which is out of scope of this dev blog. Pygame gets around this problem by 'unlocking' the GIL - something that is only possible using the C language in modules.&lt;/p&gt;

&lt;p&gt;So then why will we be using Python for this game? Well, Python is still a strong and mature language with many pros to it. Python has been around since 1991, and in that time a tremendous community has grown that has built many modules and documentation - making Python extremely powerful. Python's relative 'slowness' as a language also stems from pros of the language: being easy to write (no pointers / low level memory management), no compiling required (due to being an interpreted language), and ease of startup (from starting a project to having a running version).&lt;/p&gt;



&lt;h2&gt;
  
  
  Understanding of basic optimizing
&lt;/h2&gt;

&lt;p&gt;We have discussed some high-level cons of using Python, so how will we get around it?&lt;/p&gt;

&lt;p&gt;Let's start with the GIL. As mentioned above, this won't be an issue since Pygame actually gets around this. Pygame is also designed to be used without any threading by the user, so as far as thread/core management needed by us - there is none!&lt;/p&gt;

&lt;p&gt;Next we have the relative slowness of Python. Our game will be doing some demanding stuff for an application: calculating, rendering, and modifying many objects each frame while aiming to maintain a 60 fps (frames per second) minimum on an average computer. Part of the solution, as mentioned above, is Pygame. But Pygame doesn't solve the rendering of text quickly, particle and entity management, etc. for us. For this, we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;build a custom entity manager&lt;/li&gt;
&lt;li&gt;build a custom font / text renderer&lt;/li&gt;
&lt;li&gt;build a custom particle system&lt;/li&gt;
&lt;li&gt;build any C modules as needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is by no means the only custom or optimized pieces we will create, but it will be the most important when it comes to performance.&lt;/p&gt;

&lt;p&gt;A custom entity manager will allow us to choose what is being rendered / updated to the screen and how often that occurs. It will also allow us to use Python's strong list / dict comprehension to maintain integrity of the data while still doing all we need to do.&lt;/p&gt;

&lt;p&gt;A custom font / text renderer is needed because (this may come as a surprise to many) text rendering is one of the tougher / time consuming processes for a game. Pygame has a text system built in to present text to the screen, but this requires the full string texture to be updated and re-rendered each update to the text. Instead, we will build a system that only creates the textures for rendering once for each symbol and will then blip this to the screen to create text. Since creating those textures is a heavy process, this will greatly increase the capabilities of our game.&lt;/p&gt;

&lt;p&gt;Pygame doesn't have a particle system, so we need to create our own. Creation of any large number of entities brings the potential for poorly written code to slow down the game. Thankfully, we will be able to create a particle system that looks nice, functions according to the requirements we set, and is optimized enough to be used in our game.&lt;/p&gt;

&lt;p&gt;Lastly, I suspect we can write 100% of our game in Python. However, if we run into some calculation or function that is unable to meet our speed goals, we can always create a C module. Even if this is not needed in the end, I will still do a blog post on how to create a C module for those that are interested.&lt;/p&gt;



&lt;h2&gt;
  
  
  What can we build to?
&lt;/h2&gt;

&lt;p&gt;Python runs on nearly every OS and device. However, when it comes to making a game, we are limited to what we can distribute to due to limits of PyInstaller, device specifications, etc. Therefore, our goal with this game will be to have a distributable application available for Windows, MacOS, and Ubuntu Linux.&lt;/p&gt;

&lt;p&gt;For any other OS or device someone would want to build to, we will have the source code available.&lt;/p&gt;



&lt;h2&gt;
  
  
  Leaders in Pygame development / Resources
&lt;/h2&gt;

&lt;p&gt;Pygame has been around since the year 2000, so there are plenty of games and applications written with Pygame that you can look through and follow. However, when it comes to people pushing the limits of Pygame and creating well-written applications, the main two I like to follow would be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/DaFluffyPotato"&gt;DaFluffyPotato&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/ClearCode"&gt;ClearCode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For other resources / documentation, the following may be useful to you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/"&gt;Python documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3schools.com/python/python_lists_comprehension.asp"&gt;Python list comprehension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.python.org/moin/GlobalInterpreterLock"&gt;GIL explanation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pygame.org/docs/"&gt;Pygame documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pyinstaller.org/en/stable/"&gt;PyInstaller documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gamefromscratch.com/gamedev-glossary-library-vs-framework-vs-engine/"&gt;Game Library vs Framework vs Engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.libsdl.org/"&gt;SDL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>pygame</category>
      <category>python</category>
      <category>gamedev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Forest Defender Devlog 0: Design</title>
      <dc:creator>Braeden Richards</dc:creator>
      <pubDate>Wed, 31 Aug 2022 04:12:28 +0000</pubDate>
      <link>https://dev.to/braeday/shoot-em-up-devlog-0-design-2gm9</link>
      <guid>https://dev.to/braeday/shoot-em-up-devlog-0-design-2gm9</guid>
      <description>&lt;h2&gt;
  
  
  Shoot 'em up Devlog 0: Design
&lt;/h2&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5o4CoVsJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gnchqkxx2587egbypt6d.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5o4CoVsJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gnchqkxx2587egbypt6d.jpg" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Written on May 12th, 2022&lt;/p&gt;



&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What goes into Designing a game&lt;/li&gt;
&lt;li&gt;Useful tools&lt;/li&gt;
&lt;li&gt;Design ideas for this game&lt;/li&gt;
&lt;li&gt;Technology and tool choices&lt;/li&gt;
&lt;li&gt;Resources / further reading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="designing-a-game"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  What goes into designing a game?
&lt;/h2&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Hsboq0bf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6coknqi3sygjp1edoqgf.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Hsboq0bf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6coknqi3sygjp1edoqgf.jpeg" width="880" height="619"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Designing a game sounds easy - and it certainly can be at times - but it is actually a long process with many choices to make. These choices can impact development environment, artistic direction, technology used, build goals, etc. The main design choices I find myself making at the beginning of a project are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What style will this game be in?

&lt;ul&gt;
&lt;li&gt;2D, 2.5D, 3D, VR, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Based on the above answer, what technology will I use?

&lt;ul&gt;
&lt;li&gt;Game Engine / Frameworks: Unity, Unreal, Monogame, Pygame, Love, etc.&lt;/li&gt;
&lt;li&gt;Languages (heavily depended on the game engine / framework answer)

&lt;ul&gt;
&lt;li&gt;C#, C++, Python, Lua, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;What external tools would be helpful?

&lt;ul&gt;
&lt;li&gt;Art tools (Photoshop, Illustrator, GIMP)&lt;/li&gt;
&lt;li&gt;Text Editor (VSCode, VS Studio, PyCharm)&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;How many people will be working on this project?&lt;/li&gt;
&lt;li&gt;What source control system will I be using?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can then go into the actual game design choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Artstyle and color pallete&lt;/li&gt;
&lt;li&gt;Theme&lt;/li&gt;
&lt;li&gt;Unique attribute to the game

&lt;ul&gt;
&lt;li&gt;This would be what separates it from other games&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;What games can we pull inspiration from?&lt;/li&gt;
&lt;li&gt;What is the MVP or Minimal Viable Product

&lt;ul&gt;
&lt;li&gt;Essentially what is the minimum needed to get the game ready for demoing / playtesting&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="useful-tools"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Useful tools
&lt;/h2&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U8fXlMWn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3mw0g3qelbyp6kbl0vlc.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U8fXlMWn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3mw0g3qelbyp6kbl0vlc.jpeg" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;As mentioned in the previous section, there are many tools that are useful during game development. Essentially if there is something you'd think "I wish there was a ___ to make development quicker", there probably is! Below are useful tools I have used in the past and can recommend:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Art Tools:&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Higher resolution

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.adobe.com/products/photoshop.html"&gt;Photoshop&lt;/a&gt; (paid)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://affinity.serif.com/en-us/"&gt;Affinity&lt;/a&gt; (paid)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gimp.org/"&gt;Gimp&lt;/a&gt; (free)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pixel Art

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.aseprite.org/"&gt;Asperite&lt;/a&gt; (paid)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pixaki.com/"&gt;Pixaki&lt;/a&gt; (paid)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apps.microsoft.com/store/detail/paint/9PCFS5B6T72H?hl=en-us&amp;amp;gl=US"&gt;Microsoft Paint&lt;/a&gt; (yes, this can be used! Free)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Game Engines / Frameworks:&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://unity.com/"&gt;Unity&lt;/a&gt; (free for most)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://godotengine.org/"&gt;Godot&lt;/a&gt; (free)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.monogame.net/"&gt;Monogame&lt;/a&gt; (free)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.pygame.org/news"&gt;Pygame&lt;/a&gt; (free)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://love2d.org/"&gt;Love2D&lt;/a&gt; (Lua) (free)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Source Control:&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://git-scm.com/"&gt;Git&lt;/a&gt; with &lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt; or &lt;a href="https://bitbucket.org/product"&gt;Bitbucket&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Task Management:&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://trello.com/"&gt;Trello&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Text Editor:&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/"&gt;VSCode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://visualstudio.microsoft.com/"&gt;Visual Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sublimetext.com/"&gt;Sublime&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://atom.io/"&gt;Atom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.jetbrains.com/pycharm/"&gt;PyCharm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vim.org/"&gt;VIM&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="design-for-this-game"&gt; &lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Design ideas for this game
&lt;/h2&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bTIeguZj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvy1vuoyggub6mzyuz5h.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bTIeguZj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvy1vuoyggub6mzyuz5h.jpeg" width="880" height="583"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Theme
&lt;/h3&gt;

&lt;p&gt;The game we will be creating will be a  Shoot'em Up  /  Bullet Hell  style game. As the player, you will need to avoid the large number of projectiles while attacking and destroying the enemies. Once the level's enemies have been destroyed, the player can move to the next level.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Design
&lt;/h3&gt;

&lt;p&gt;This will be a pixel art styled game. The color palette will be chosen in a later devlog once the basics of the engine has been built. In my past projects it has been difficult to make smooth animation of pixel-based graphics, so a goal of mine for this project is to have smooth and meaningful animation of the environment and entities.&lt;/p&gt;

&lt;p&gt;I will also be spending much more time than usual on the graphics and feel of the environment. In the past, most of my time has been on the player and other entities of the game, leaving the environment the player lives in to be lacking in feel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Goals of project
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Smooth / understandable / easy controls&lt;/li&gt;
&lt;li&gt;Smooth animations&lt;/li&gt;
&lt;li&gt;Minimum FPS of 60 on an average computer&lt;/li&gt;
&lt;li&gt;Visually pleasing environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Story of game
&lt;/h3&gt;

&lt;p&gt;Fungus is a natural and important piece of any healthy ecosystem, but what happens when the fungus becomes sentient and begins to cause damage to the ecosystem for their own gain? As the protector of the forest, your goal is to destroy the villainous fungus and return the land to a balanced and healthy life. You must fight your way through the defenses of the fungus to challenge the Life Mushroom to a battle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supported platforms
&lt;/h3&gt;

&lt;p&gt;We will support and build this game on Windows 10 and up, MacOS, and Ubuntu Linux.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supported devices
&lt;/h3&gt;

&lt;p&gt;This game will be playable with a controller or keyboard / mouse.&lt;/p&gt;

&lt;p&gt;&lt;a id="technology_and_tool_choices"&gt; &lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Technology and tool choices
&lt;/h2&gt;

&lt;p&gt;So based on my goal for this game and the underlying knowledge I have, I will choose the following from the &lt;b&gt;Useful Tools&lt;/b&gt; section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;b&gt;Art Tools:&lt;/b&gt; Pixaki and Asperite&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Game Engine and Language:&lt;/b&gt; Python with Pygame&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Source Control:&lt;/b&gt; GitHub&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Task Management:&lt;/b&gt; Trello&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Text Editor:&lt;/b&gt; VSCode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="further-reading"&gt; &lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Resources / further reading
&lt;/h2&gt;

&lt;p&gt;&lt;b&gt; General: &lt;/b&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://unity.com/how-to/beginner/10-game-design-tips-new-developers"&gt;10 game design tips for new developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.freecodecamp.org/news/from-zero-to-game-designer-how-to-start-building-video-games-even-if-you-dont-have-any-experience-5e2f9f45f4bb/"&gt;From Zero to Game Designer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt; Art tools: &lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://affinity.serif.com/en-us/"&gt;Affinity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.aseprite.org/"&gt;Asperite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gimp.org/"&gt;Gimp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apps.microsoft.com/store/detail/paint/9PCFS5B6T72H?hl=en-us&amp;amp;gl=US"&gt;Microsoft Paint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.adobe.com/products/photoshop.html"&gt;Photoshop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pixaki.com/"&gt;Pixaki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt; Game Engines / Frameworks: &lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://godotengine.org/"&gt;Godot&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://love2d.org/"&gt;Love2D&lt;/a&gt; (Lua)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.monogame.net/"&gt;Monogame&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pygame.org/news"&gt;Pygame&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://unity.com/"&gt;Unity&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt; Text Editor: &lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://atom.io/"&gt;Atom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.jetbrains.com/pycharm/"&gt;PyCharm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sublimetext.com/"&gt;Sublime&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vim.org/"&gt;VIM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/"&gt;VSCode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://visualstudio.microsoft.com/"&gt;Visual Studio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt; Other &lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/"&gt;Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bitbucket.org/product"&gt;Bitbucket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://trello.com/"&gt;Trello&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gamedev</category>
      <category>devlog</category>
      <category>python</category>
      <category>devjournal</category>
    </item>
  </channel>
</rss>
