<?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: Martin J</title>
    <description>The latest articles on DEV Community by Martin J (@jerzakm).</description>
    <link>https://dev.to/jerzakm</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%2F274195%2F89a8381b-4cf3-407c-b39c-50cf42bf3c03.png</url>
      <title>DEV Community: Martin J</title>
      <link>https://dev.to/jerzakm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jerzakm"/>
    <language>en</language>
    <item>
      <title>What is your Supabase workflow? - Beginner question</title>
      <dc:creator>Martin J</dc:creator>
      <pubDate>Thu, 17 Feb 2022 14:27:55 +0000</pubDate>
      <link>https://dev.to/jerzakm/what-is-your-supabase-workflow-beginner-question-2jd7</link>
      <guid>https://dev.to/jerzakm/what-is-your-supabase-workflow-beginner-question-2jd7</guid>
      <description>&lt;p&gt;I'm a beginner who just started using Supabase (and postgres). I love it and for my needs, it feels like a step up from Firebase.&lt;/p&gt;

&lt;h1&gt;
  
  
  How do you work on Supabase with bigger projects?
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;What external tools can you recommend?&lt;/li&gt;
&lt;li&gt;What best are the best practices when it comes to Supabase development?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So many of the articles I find are just about simple authentication or adding one function with basic row level security, but not too many dig much deeper than that.&lt;/p&gt;

&lt;p&gt;I am finding it difficult to keep track of my functions, row level security rules etc.&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>help</category>
      <category>discuss</category>
      <category>database</category>
    </item>
    <item>
      <title>I just found this awesome EU Banking API for personal use </title>
      <dc:creator>Martin J</dc:creator>
      <pubDate>Sat, 22 Jan 2022 12:59:43 +0000</pubDate>
      <link>https://dev.to/jerzakm/i-just-found-this-awesome-eu-banking-api-for-personal-use-113a</link>
      <guid>https://dev.to/jerzakm/i-just-found-this-awesome-eu-banking-api-for-personal-use-113a</guid>
      <description>&lt;p&gt;&lt;strong&gt;Background&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I was looking to get a grip on my finances this year, but after looking into it I didn't find any apps suitable to my needs. I live in Poland and most of the offerings seem to be very US centric. I like data visualization so I figured it can't be that hard to roll out my own solution. Here's where I first learned about the concept of Open Banking and how I found Nordigen.&lt;br&gt;
Despite the looks of this post, I am not affiliated with Nordigen in any way, I'm just very excited to play with my own financial data and see what I can come up with 😁🤑&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Open Banking?
&lt;/h1&gt;

&lt;p&gt;Open banking, under European PSD2 regulation, aims to democratize the access to financial data, increase competition in financial sector and drive innovation. The tldr is that banks in European Economic Area are required to provide standardized, open access to financial data. From what I see it's a fairly new and exciting field. It fully went into effect on 31st of Dec 2020.&lt;br&gt;
I don't feel knowledgeable enough about the subject yet to provide definitive answers, I recommend reading these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wikipedia article about &lt;a href="https://en.wikipedia.org/wiki/Payment_Services_Directive" rel="noopener noreferrer"&gt;European Payment Services Directive&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Investopedia about &lt;a href="https://www.investopedia.com/terms/o/open-banking.asp" rel="noopener noreferrer"&gt;Open Banking&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nordigen.com/en/open-banking/psd2-explained-summary/" rel="noopener noreferrer"&gt;Nordigen on PSD2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Ok, but what's the deal with Nordigen.
&lt;/h1&gt;

&lt;p&gt;Nordigen allows you to connect multiple bank accounts to their service and use their &lt;a href="https://nordigen.com/en/account_information_documenation/integration/parameters-and-responses/" rel="noopener noreferrer"&gt;simple API&lt;/a&gt; to query it. I've just done it myself and considering that it's banking that we're talking about it was super easy. Anyone could do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nordigen boasts that it's available in 31 EEA countries and allows connection to 2197 banks.
&lt;/h2&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%2F1ijpve3cca5nlg8313w9.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%2F1ijpve3cca5nlg8313w9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  You can connect your banks and get a feel for it before using the API
&lt;/h2&gt;

&lt;p&gt;Nordigen has a simple, pretty barebones dashboard for account information. You can connect your bank accounts and View Transactions as JSON&lt;br&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%2Femftxc13nusn4x2nfzol.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%2Femftxc13nusn4x2nfzol.png" alt="Nordigen account list"&gt;&lt;/a&gt;&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%2Fmoty9nlnxk61hlcusgdc.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%2Fmoty9nlnxk61hlcusgdc.png" alt="Nordigen transaction view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What do you think about it? Can you recommend any other bank/financial APIs or services?
&lt;/h1&gt;

</description>
      <category>fintech</category>
      <category>openbanking</category>
      <category>api</category>
    </item>
    <item>
      <title>Physics based character controller with Rapier.rs and Pixi</title>
      <dc:creator>Martin J</dc:creator>
      <pubDate>Mon, 15 Nov 2021 14:31:13 +0000</pubDate>
      <link>https://dev.to/jerzakm/physics-based-character-controller-with-rapierrs-and-pixi-5e31</link>
      <guid>https://dev.to/jerzakm/physics-based-character-controller-with-rapierrs-and-pixi-5e31</guid>
      <description>&lt;p&gt;Following up on my recent 'discovery' of the &lt;a href="https://rapier.rs" rel="noopener noreferrer"&gt;Rapier.rs physics engine&lt;/a&gt; I make the first attempt at a character controller.&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jerzakm/gamedev-experiments/tree/main/rapier-pixi-character-controller-dynamic" rel="noopener noreferrer"&gt;Github Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rapier-keyboard-character-controller.netlify.app" rel="noopener noreferrer"&gt;Live example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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%2Fmedia.graphcms.com%2FclfiTnXlSbOQgUgThJ6m" 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%2Fmedia.graphcms.com%2FclfiTnXlSbOQgUgThJ6m" alt="RipHok4WkN.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Rigid-body choices for a character controller in Rapier.rs
&lt;/h2&gt;

&lt;p&gt;Except for &lt;code&gt;Static&lt;/code&gt; all other body types seem viable to make a controller, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;KinematicPositionBased&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;KinematicVelocityBased&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Dynamic&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kinematic bodies allow us to set their Position and Velocity, so at a first glance, it sounds like they'd make a good controller. Unfortunately, they come with a few caveats, making them harder to use than you'd think. The biggest drawback for a quick and easy character controller is the fact that they don't interact with static bodies out of the gate and will clip through them. Not great if we want our characters to stick to walls and platforms. Rapier provides us with a lot of options to handle this drawback. Scene queries and hooks are quite robust, allowing the user to implement custom collision logic, but it's not something I want to get into before learning a bit more about the engine.&lt;/p&gt;

&lt;p&gt;The last remaining choice, &lt;code&gt;Dynamic&lt;/code&gt; is a fully-fledged body that interacts with the entire world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;To not make this article unnecessarily long, I will skip the world and renderer setup and instead link the Github repo for the project. It should be easy enough to follow and you're always welcome to hit me up with any questions you might have.&lt;/p&gt;

&lt;p&gt;Before proceeding with character controller I setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rapier.rs physics world with gravity &lt;code&gt;{x: 0, y: 0}&lt;/code&gt; - for the topdown experience&lt;/li&gt;
&lt;li&gt;add walls to browser window bounds&lt;/li&gt;
&lt;li&gt;spawn Dynamic objects for our character to interact with later, in this case, 100 randomly sized balls&lt;/li&gt;
&lt;li&gt;render walls and balls with simple pixi.js graphics&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step by step
&lt;/h2&gt;

&lt;p&gt;Steps to implement a simple keyboard and point to click controller:&lt;/p&gt;

&lt;h3&gt;
  
  
  Player body setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a player physics body and place it in the middle of the screen with &lt;code&gt;setTranslation&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;world&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRigidBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;RAPIER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RigidBodyDesc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newDynamic&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;setTranslation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Make a collider description so the body has shape and size. It needs it to interact with the world. For this example, we're going with a simple circle. Translation in this step describes the collider's relative position to the body.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;colliderDesc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RAPIER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ColliderDesc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RAPIER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Ball&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setTranslation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create a collider, attach it to the body and add the whole thing to the world.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;collider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;world&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createCollider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;colliderDesc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Keyboard WASD control bindings
&lt;/h3&gt;

&lt;p&gt;In later steps, we will move the player's body based on the provided direction. To get that we're going to set up a basic WASD control scheme with listeners listening to &lt;code&gt;keydown&lt;/code&gt; and &lt;code&gt;keyup&lt;/code&gt;. They will manipulate a direction vector:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;When the key is pressed down, player begins to move:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;w&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Then, when the key is released, the movement on that particular axis (x or y) is set to 0.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keyup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;w&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Moving the body
&lt;/h3&gt;

&lt;p&gt;Now that we've made a way for us to input where the player has to go, it's time to make it happen. We will create an &lt;code&gt;updatePlayer&lt;/code&gt; function that will have to be called every frame.&lt;/p&gt;

&lt;p&gt;The most basic approach is as simple as the snippet below, we simply set the body's velocity to the &lt;code&gt;direction&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatePlayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLinvel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You might notice though, that the body isn't moving much. That's because we only set the direction vector to go from -1 to 1, and that isn't very fast. To combat that and make the code more reusable we add a &lt;code&gt;MOVE_SPEED&lt;/code&gt; variable and multiply the x and y of the direction.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MOVE_SPEED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatePlayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLinvel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;MOVE_SPEED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;MOVE_SPEED&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;That's more like it!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bonus method: Applying force to move the body&lt;/strong&gt;&lt;br&gt;
When I was playing around and writing this article I found another cool way to make our player's body move. Instead of setting the velocity directly, we "push" the body to make it go in the desired direction at the desired speed. It gives a smoother, more natural feeling movement right out of the gate.&lt;/p&gt;

&lt;p&gt;The whole thing is just these few lines of code but it's a little more complicated than the previous example.&lt;/p&gt;

&lt;p&gt;The concept is simple. We apply impulse in order to make the body move, but what if it starts going too fast or we want to stop?&lt;/p&gt;

&lt;p&gt;We check the body's current velocity with &lt;code&gt;const velocity = body.linvel();&lt;/code&gt;.Then, to determine what impulse should be applied next, we take the difference of the desired and current velocity for both axis &lt;code&gt;direction.x * MOVE_SPEED - velocity.x&lt;/code&gt;. If the body is moving too fast or in the wrong direction, a counteracting impulse is applied. We multiply it by &lt;code&gt;ACCELERATION&lt;/code&gt; constant to.. drumroll - make the body accelerate faster or slower.&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%2Fmedia.graphcms.com%2F3CtKK59cSQWohAcACggc" 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%2Fmedia.graphcms.com%2F3CtKK59cSQWohAcACggc" alt="Moving with impulse.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MOVE_SPEED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ACCELERATION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;linvel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;impulse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;MOVE_SPEED&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;ACCELERATION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;MOVE_SPEED&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;ACCELERATION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyImpulse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;impulse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You can achieve a similar effect by using the velocity method and applying some form of &lt;a href="https://developers.google.com/web/fundamentals/design-and-ux/animations/the-basics-of-easing" rel="noopener noreferrer"&gt;easing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note: For simplicity, I use &lt;code&gt;VELOCITY&lt;/code&gt; and &lt;code&gt;ACCELERATION&lt;/code&gt; in relation to one value of the vector. So velocity with the value of &lt;code&gt;2&lt;/code&gt; would look like this: &lt;code&gt;{x: 2, y: 2}&lt;/code&gt;, where in reality velocity is almost always the length of such vector - &lt;code&gt;const velocity = Math.sqrt(2**2 + 2**2)&lt;/code&gt; resulting in velocity of ~2.83!. This means that if we used my implementation in a game, moving diagonally would be 40% faster than going up and down!&lt;br&gt;
&lt;strong&gt;TLDR; Use correct velocity, calculated for example with Pythagorem's theorem.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  If you made it this far, thank you so much for reading. Let me know if you have any questions or maybe would like to see other things implemented.
&lt;/h3&gt;

</description>
      <category>javascript</category>
      <category>gamedev</category>
      <category>webassembly</category>
      <category>physics</category>
    </item>
    <item>
      <title>This little known javascript physics library blew my mind!</title>
      <dc:creator>Martin J</dc:creator>
      <pubDate>Mon, 01 Nov 2021 16:48:37 +0000</pubDate>
      <link>https://dev.to/jerzakm/this-little-known-javascript-physics-library-blew-my-mind-57oo</link>
      <guid>https://dev.to/jerzakm/this-little-known-javascript-physics-library-blew-my-mind-57oo</guid>
      <description>&lt;p&gt;In my previous game dev attempts with javascript I always struggled with physics engine performance. I always defaulted to matter.js - it's good documentation and plentiful examples outweighed the performance gains of other available libraries. I was very excited when I first learned about WASM and near-native performance it provides, but for the longest time Box2D was the only viable choice in that area and I truely hated using it. It had poor documentation and felt very archaic to use.&lt;/p&gt;

&lt;p&gt;Now, it seems like my woes might be over. In comes a new contender - Rapier.rs.&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%2Fmedia.graphcms.com%2FIxHiH6ZYRLuYapuZHFTT" 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%2Fmedia.graphcms.com%2FIxHiH6ZYRLuYapuZHFTT" alt="Rapier.rs logo"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://rapier.rs/" rel="noopener noreferrer"&gt;Rapier home&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rapier.rs is a rust physics library compiled to WASM with javscript bindings and good documentation. I was able to set it up in around 30 minutes and it provided an massive, instant boost to app performance.&lt;/p&gt;

&lt;p&gt;Rapier remained more stable and allowed me to add thousands of more active physics bodies to the world.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example from my last article with Rapier.rs instead of matter +300% performance &lt;a href="https://workerized-rapier-pixi.netlify.app/" rel="noopener noreferrer"&gt;LIVE&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jerzakm/gamedev-experiments/tree/main/rapier-pixi-worker" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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%2Fmedia.graphcms.com%2F6buI1RaOvW2KIklhMDAz" 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%2Fmedia.graphcms.com%2F6buI1RaOvW2KIklhMDAz" alt="nbrpJOCJQu.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Active bodies&lt;/th&gt;
&lt;th&gt;Matter FPS&lt;/th&gt;
&lt;th&gt;Rapier FPS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;4500&lt;/td&gt;
&lt;td&gt;38&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6000&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;79&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7500&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9000&lt;/td&gt;
&lt;td&gt;0 - crashed&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;0 - crashed&lt;/td&gt;
&lt;td&gt;31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12000&lt;/td&gt;
&lt;td&gt;0 - crashed&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15000&lt;/td&gt;
&lt;td&gt;0 - crashed&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Why you need to consider Rapier for your js physics needs
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Performance
&lt;/h3&gt;

&lt;p&gt;Javascript can't compare to an optimized Rust library compiled to WASM&lt;br&gt;
&lt;a href="https://medium.com/@torch2424/webassembly-is-fast-a-real-world-benchmark-of-webassembly-vs-es6-d85a23f8e193" rel="noopener noreferrer"&gt;WASM is just this fast&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Documentation
&lt;/h3&gt;

&lt;p&gt;Rapier page provides a good overview of the key features, information how to get started and an in-depth API documentation. All of this for Rust, Rust+bevy and Javascript.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Modern developer experience
&lt;/h3&gt;

&lt;p&gt;I found Rapier API very intuitive to work with, imho making it by far the best choice out of the few performant. It comes with &lt;strong&gt;typescript support&lt;/strong&gt;. Resulting code is readable and easy to reason with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@dimforge/rapier2d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;RAPIER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Use the RAPIER module here.&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;gravity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;9.81&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;world&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RAPIER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;World&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gravity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Create the ground&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;groundColliderDesc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;RAPIER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ColliderDesc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cuboid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;world&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createCollider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;groundColliderDesc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Create a dynamic rigid-body.&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;rigidBodyDesc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;RAPIER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RigidBodyDesc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newDynamic&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;setTranslation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;1.0&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;rigidBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;world&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRigidBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rigidBodyDesc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Create a cuboid collider attached to the dynamic rigidBody.&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;colliderDesc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;RAPIER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ColliderDesc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cuboid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;collider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;world&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createCollider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;colliderDesc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rigidBody&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Game loop. Replace by your own game loop system.&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;gameLoop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Step the simulation forward.&lt;/span&gt;
    &lt;span class="nx"&gt;world&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Get and print the rigid-body's position.&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rigidBody&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;translation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Rigid-body position: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gameLoop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;gameLoop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Cross-platform determinism &amp;amp; snapshotting
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Running the &lt;strong&gt;same simulation&lt;/strong&gt;, with the same initial conditions on different machines or distributions of Rapier (rust/bevy/js) &lt;strong&gt;will yield the same result.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easy data saving and restoring.&lt;/strong&gt; - &lt;em&gt;It is possible to take a snapshot of the whole physics world with &lt;code&gt;world.takeSnapshot&lt;/code&gt;. This results in a byte array of type Uint8Array that may be saved on the disk, sent through the network, etc. The snapshot can then be restored with &lt;code&gt;let world = World.restoreSnapshot(snapshot);&lt;/code&gt;&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;I am excited to keep working with Rapier, but in the meanwhile I think a proper physics benchmark is in order. The ones I've found while doing research were a bit dated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other: Vite usage errors
&lt;/h3&gt;

&lt;p&gt;I've ran into some issues adding Rapier to my Vite project, the solution can be found here: &lt;a href="https://github.com/dimforge/rapier.js/issues/49" rel="noopener noreferrer"&gt;https://github.com/dimforge/rapier.js/issues/49&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>gamedev</category>
      <category>rust</category>
      <category>webassembly</category>
    </item>
    <item>
      <title>Running JS physics in a webworker - proof of concept</title>
      <dc:creator>Martin J</dc:creator>
      <pubDate>Sun, 31 Oct 2021 01:25:46 +0000</pubDate>
      <link>https://dev.to/jerzakm/running-js-physics-in-a-webworker-part-1-proof-of-concept-ibj</link>
      <guid>https://dev.to/jerzakm/running-js-physics-in-a-webworker-part-1-proof-of-concept-ibj</guid>
      <description>&lt;h2&gt;
  
  
  series: Exploring Javascript physics world
&lt;/h2&gt;

&lt;p&gt;Web workers are a great way of offloading compute intensive tasks from the main thread. I have been interested in using them for quite a while, but none of the projects I worked on really justified using them. Until now! In this short series I'm going to explore using webworkers, physics, pixi.js and others to create interactive web experiences and games.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://workerized-matterjs-pixi.netlify.app/" rel="noopener noreferrer"&gt;Live&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jerzakm/gamedev-experiments/tree/main/matterjs-pixi-worker" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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%2Fmedia.graphcms.com%2F6buI1RaOvW2KIklhMDAz" 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%2Fmedia.graphcms.com%2F6buI1RaOvW2KIklhMDAz" alt="nbrpJOCJQu.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Webworkers tldr;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;scripts that run in background threads&lt;/li&gt;
&lt;li&gt;they communicate with the main thread by sending and receiving messages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In depth info, better than I could ever explain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.logrocket.com/using-webworkers-for-safe-concurrent-javascript-3f33da4eb0b2/" rel="noopener noreferrer"&gt;Using web workers for safe, concurrent JavaScript - Bruce Wilson, Logrocket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API" rel="noopener noreferrer"&gt;MDN entry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;The benefits of using webworkers are undeniable. Most importantly it &lt;strong&gt;keeps main thread responsive.&lt;/strong&gt; Frozen webpages and slow UI make for terrible user experience. In my case, even if the physics simulation slows down to 20-30 fps, mainthread renderer still runs at a constant 144 fps. It helps keep animations nice and juicy and the page responsive to user inputs.&lt;/p&gt;

&lt;p&gt;I am guilty of making very CPU intensive terrain generation in the past, it would freeze a user's browser for 2-3 seconds and it was terrible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proof of concept implementation:
&lt;/h2&gt;

&lt;p&gt;This is not a step by step tutorial, I wanted to keep this article more conceptual and code-light. You should be able to follow my Spaghetti code in &lt;a href="https://github.com/jerzakm/gamedev-experiments/tree/main/matterjs-pixi-worker" rel="noopener noreferrer"&gt;the project repo&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Vite bundler
&lt;/h3&gt;

&lt;p&gt;I decided against using any framework to avoid unnecessary complexity. For my bundler I decided to use Vite since I was familiar with it &lt;a href="https://github.com/vitejs/vite/tree/main/packages/create-vite" rel="noopener noreferrer"&gt;and the provided vanilla Typescript template&lt;/a&gt;. It provides an &lt;a href="https://vitejs.dev/guide/features.html#web-workers" rel="noopener noreferrer"&gt;easy way to import webworkers&lt;/a&gt; and their dependencies even from Typescript files.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Pixi.js renderer
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://pixijs.com/" rel="noopener noreferrer"&gt;Pixi.js&lt;/a&gt; is a fairly easy to use WebGL renderer. It will show what we're doing on screen. Everything I'm doing can be replicated by copying one of &lt;a href="https://pixijs.io/examples/#/demos-basic/container.js" rel="noopener noreferrer"&gt;the examples&lt;/a&gt;. All you need is to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;setup the renderer&lt;/li&gt;
&lt;li&gt;load texture and make sprites&lt;/li&gt;
&lt;li&gt;update sprite position and angle in the ticker&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Finally, making the worker!
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;make a file with a worker, like &lt;code&gt;physicsWorker.ts&lt;/code&gt;. Code gets executed on worker load.&lt;/li&gt;
&lt;li&gt;import and initialize the worker in the main thread - &lt;a href="https://vitejs.dev/guide/features.html#web-workers" rel="noopener noreferrer"&gt;vite docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;from now on you can setup listeners and send messages between main thread and the worker&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Physics engine in the worker.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://brm.io/matter-js/" rel="noopener noreferrer"&gt;Matter.js&lt;/a&gt; is a 2D physics engine I've decided to use. It's far from being the most performant, but it's user friendly and helps keep code complexity down.&lt;/p&gt;

&lt;p&gt;Engine, World and a 'gameloop' get created when web worker is loaded. Gameloop is a function that continuously runs and calls &lt;code&gt;Engine.update(physics.engine, delta);&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Communication &amp;amp; command pattern
&lt;/h3&gt;

&lt;p&gt;Like I mentioned before, worker and the thread communicate with messages. I found this to be a natural fit for a &lt;a href="https://gameprogrammingpatterns.com/command.html" rel="noopener noreferrer"&gt;command pattern&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Actor (either main or worker thread) sends an object that has all information required to perform an action by the subject. I decided to structure my commands like below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ADD_BODY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;restitution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To send the above command, main thread calls &lt;code&gt;worker.postMessage(command);&lt;/code&gt;. For a worker to receive it, we need to set up a listener.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Worker has to call 'self' to send and receive&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Worker receives a command to ADD_BODY&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ADD_BODY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// it does stuff&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;physics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Worker sends a command to main thread (BODY_CREATED)&lt;/span&gt;
    &lt;span class="c1"&gt;// it will be used to spawn a sprite&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BODY_CREATED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Here's a general overview of how this example works&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.graphcms.com%2Fgqr7vUh4SmuwgE5Rjs5c" 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%2Fmedia.graphcms.com%2Fgqr7vUh4SmuwgE5Rjs5c" alt="Untitled.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Features explained
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Create body
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Main thread sends a command &lt;code&gt;ADD_BODY&lt;/code&gt; with position, width, height and &lt;a href="https://brm.io/matter-js/docs/classes/Body.html#properties" rel="noopener noreferrer"&gt;physics options&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;When worker thread receives an &lt;code&gt;ADD_BODY&lt;/code&gt; it adds the body with given parameters to the world&lt;/li&gt;
&lt;li&gt;After body is added, worker sends &lt;code&gt;BODY_CREATED&lt;/code&gt; command back to main thread. &lt;strong&gt;The most important part of this message is the id&lt;/strong&gt;. This is how technically unrelated javascript objects (body in worker and sprite in main) will sync. It also sends width, height, position, angle&lt;/li&gt;
&lt;li&gt;When main thread receives &lt;code&gt;BODY_CREATED&lt;/code&gt; position it creates an object containing the data received as well as a &lt;code&gt;PIXI.Sprite&lt;/code&gt; it assigns to it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Synchronising object position between physics engine and renderer
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;each frame physics engine sends command &lt;code&gt;BODY_SYNC&lt;/code&gt;, it contains position and angle of every body in the physics world. It's stored in the hashmap format, with body id being the key.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;world&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bodies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;body&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="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BODY_SYNC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;mainthread receives the body &lt;code&gt;BODY_SYNC&lt;/code&gt;. It loops over every body previously added and updates it.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BODY_SYNC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;physData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;bodySyncDelta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;physicsObjects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;angle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;physData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rotation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  It works!
&lt;/h2&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%2Fmedia.graphcms.com%2F6buI1RaOvW2KIklhMDAz" 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%2Fmedia.graphcms.com%2F6buI1RaOvW2KIklhMDAz" alt="nbrpJOCJQu.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What went wrong:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Physics performance is lacking, but there are a lot of good areas for improvement.&lt;/li&gt;
&lt;li&gt;Sometimes objects got out of bounds and kept flying into x,y coords of 10000+, causing slowdown and eventual crash. I quickly dealt with it by freezing any object whose coordinate is more than 3000, it's not a perfect solution and something to look out for in the future.&lt;/li&gt;
&lt;li&gt;Simple command pattern worked fine here but it could get very complex in some use cases&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Future improvement considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Matter.js is slow
&lt;/h3&gt;

&lt;p&gt;According to &lt;a href="http://olegkikin.com/js-physics-engines-benchmark/" rel="noopener noreferrer"&gt;this outdated benchmark&lt;/a&gt; matter.js is one of the slowest available javascript physics engines. It's performance has improved since then, but there are other alternatives. I am especially interested in WASM libraries with js binding, like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/Birch-san/box2d-wasm" rel="noopener noreferrer"&gt;box2dwasm&lt;/a&gt; - an old, still maintained C++ library compiled to WASM. The documentation is lacking and developer experience seems poor.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://rapier.rs" rel="noopener noreferrer"&gt;rapier.rs&lt;/a&gt; - modern physics library written in Rust. It looks good and performant, at a first glance dev experience is a lot better than box2d. &lt;a href="https://rapier.rs/docs/user_guides/javascript/getting_started_js" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt; gives me hope!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In general, chosing a WASM engine over JS one should yield large performance gain.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Webworker messages
&lt;/h3&gt;

&lt;p&gt;Sending large amounts of data at high frequency (gameloop) between worker and mainthread with messages can cause large performance drops.&lt;/p&gt;

&lt;p&gt;In depth dive into the issue: &lt;a href="https://surma.dev/things/is-postmessage-slow/" rel="noopener noreferrer"&gt;"Is postmessage slow?" - surma.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Approaches to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON.stringify then JSON.parse of the data (this doesn't seem to boost performance for my usecase)&lt;/li&gt;
&lt;li&gt;Using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer" rel="noopener noreferrer"&gt;ArrayBuffer&lt;/a&gt; and transfering ownership between worker and main&lt;/li&gt;
&lt;li&gt;Using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer" rel="noopener noreferrer"&gt;SharedArrayBuffer&lt;/a&gt; so the origin retains ownership and both threads can access the data with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics" rel="noopener noreferrer"&gt;Atomics&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I guess it's time for my own benchmark!&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Using a webworker library instead of vanilla implementation
&lt;/h3&gt;

&lt;p&gt;I can imagine that communication with vanilla webworkers could get very complex. &lt;a href="https://github.com/GoogleChromeLabs/comlink" rel="noopener noreferrer"&gt;Comlink&lt;/a&gt; is something that's been on my list for a while and I'd like to try it out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From the &lt;a href="https://github.com/GoogleChromeLabs/comlink" rel="noopener noreferrer"&gt;Comlink Github page&lt;/a&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Comlink makes WebWorkers enjoyable. Comlink is a tiny library (1.1kB), that removes the mental barrier of thinking about postMessage and hides the fact that you are working with workers.&lt;/p&gt;

&lt;p&gt;At a more abstract level it is an RPC implementation for postMessage and ES6 Proxies.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Renderer interpolation
&lt;/h3&gt;

&lt;p&gt;If the use case doesn't call for more, I could keep the physics engine locked at 30 or 60 fps. The issue with this, is that the movement will look 'choppy'.&lt;br&gt;
I could use interpolation and use available position and velocity data to 'predict' object movement and generate the frames up to say 144fps for smooth animations.&lt;/p&gt;

&lt;h2&gt;
  
  
  The end.
&lt;/h2&gt;

&lt;p&gt;This turned out much longer than I expected. More to come?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>gamedev</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Part 1 - Making a portfolio with SvelteKit - the beginning 1/100DaysOfCode</title>
      <dc:creator>Martin J</dc:creator>
      <pubDate>Sat, 19 Jun 2021 18:35:57 +0000</pubDate>
      <link>https://dev.to/jerzakm/part-1-making-a-portfolio-with-sveltekit-the-beginning-1-100daysofcode-5d5j</link>
      <guid>https://dev.to/jerzakm/part-1-making-a-portfolio-with-sveltekit-the-beginning-1-100daysofcode-5d5j</guid>
      <description>&lt;p&gt;Part 1 of a journey to making my portfolio. This post will be boring as hell, but hopefully it's a beginning of a fairly interesting series. &lt;/p&gt;

&lt;h2&gt;
  
  
  Finally getting it together and making a portfolio with my work.
&lt;/h2&gt;

&lt;p&gt;I have been learning and playing with webdev for close to three years, but I never took it to another level. I have been (and as of the time of publishing this, still am) working a stable, boring office job. &lt;br&gt;
Working remote for over a year helped me gain some clarity and look inwards. My personal goals and plans don't align with my current employment, and it's relative safety has placated my hunger for pursuit of what I want, and what I want is TECH. I love modern technologies and am very passionate, nay - have an insatiable hunger for learning new things and solving puzzles.&lt;/p&gt;
&lt;h2&gt;
  
  
  SvelteKit 😍
&lt;/h2&gt;

&lt;p&gt;At the current stage it's a very barebones page with no real content, but I have already learned so much:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basics of &lt;a href="https://kit.svelte.dev/"&gt;SvelteKit&lt;/a&gt;- I have already been quite familiar with Svelte so it was quite easy to jump in. So far I'm really enjoying the framework and would strongly recommend for anyone to check it out.&lt;/li&gt;
&lt;li&gt;Very simple CI wiith Netlify&lt;/li&gt;
&lt;li&gt;setting up a domain through &lt;a href="https://porkbun.com"&gt;Porkbun&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other than showcasing my work and writings, I am going to keep myself accountable and attempt to keep as close to 100 lighthouse score as possible and follow best practices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qtsEHyDZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ekzczmlenatftdzotg8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qtsEHyDZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ekzczmlenatftdzotg8.gif" alt="Lighthouse performance scores, all 100s" width="868" height="242"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  It's live on (&lt;a href="https://jerzakm.com"&gt;https://jerzakm.com&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;Roadmap - next up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reviving a few of the projects from my project graveyard (AKA my github account)&lt;/li&gt;
&lt;li&gt;figuring out what content management system I want to use and hooking it up&lt;/li&gt;
&lt;li&gt;Accessibility. I can't wait to read more about it and start applying what I learned. InHuOffficial's A11y rants are awesome. &lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag__user ltag__user__id__551686"&gt;
  
    .ltag__user__id__551686 .follow-action-button {
      background-color: #c62aa4 !important;
      color: #131111 !important;
      border-color: #c62aa4 !important;
    }
  
    &lt;a href="/inhuofficial" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VQXAgM3l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--GddQJU2N--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_66%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/551686/52e35d4c-a986-401b-9bca-6ace4c8947d1.gif" alt="inhuofficial image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/inhuofficial"&gt;InHuOfficial&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/inhuofficial"&gt;Specialising in accessibility and website load speed / performance. If you have a question about [accessibility] or [page-speed-insights] ask away and I will help any way I can!&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  100 Days of Code
&lt;/h2&gt;

&lt;p&gt;This post also marks my entry and first day of progress for #100DaysOfCode&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Changes to project dependencies</title>
      <dc:creator>Martin J</dc:creator>
      <pubDate>Wed, 20 May 2020 16:03:35 +0000</pubDate>
      <link>https://dev.to/jerzakm/changes-to-project-dependencies-50e2</link>
      <guid>https://dev.to/jerzakm/changes-to-project-dependencies-50e2</guid>
      <description>&lt;h3&gt;
  
  
  What do you do when your project requires you to make changes to code of one of the dependencies?
&lt;/h3&gt;

&lt;p&gt;I'm a beginner developer and I've come across an issue in one of the packages I'm using. It was a pretty straightforward fix but it had lead me to wonder how to make the change clear and lasting. How do you deal with situations like this and what is the 'correct' way of going about it?&lt;/p&gt;

&lt;p&gt;Two most common solutions I found were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fork it&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/patch-package"&gt;patch-package&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I disliked forking the required dependency and building it myself. My github is already a mess and I feel like I don't need any more repos floating around, so I went with the other solution - &lt;a href="https://www.npmjs.com/package/patch-package"&gt;patch-package&lt;/a&gt;. it &lt;em&gt;'lets app authors instantly make and keep fixes to npm dependencies. It's a vital band-aid for those of us living on the bleeding edge.'&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;It's very simple to use:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;in package.json add a script: &lt;code&gt;"postinstall": "patch-package"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npm i patch-package&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;make changes to the package&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;npx patch-package package-name&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Et voilà! You're done. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So what happened?&lt;/p&gt;

&lt;p&gt;It created a &lt;strong&gt;&lt;em&gt;patches&lt;/em&gt;&lt;/strong&gt; directory and inside of it you can find a diff like file. You can now commit these changes and apply the small patch with a npm script.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tNX1CG2e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0a71lk9hvqckw4mqpkaf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tNX1CG2e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0a71lk9hvqckw4mqpkaf.png" alt="Alt Text" width="859" height="386"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Illustrated journey of what happened.
&lt;/h1&gt;
&lt;h3&gt;
  
  
  Oh no, big error
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D2Eaz7bs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r7712p9u3ue9lgo093j3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D2Eaz7bs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r7712p9u3ue9lgo093j3.png" alt="Console error code" width="561" height="265"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Sherlock mode activated 🕵️‍♂️
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tX3iahco--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nqeszrvln6v2qwbbsnrj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tX3iahco--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nqeszrvln6v2qwbbsnrj.png" alt="Chrome debugger issue tracing" width="769" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I found the &lt;strong&gt;&lt;em&gt;issue&lt;/em&gt;&lt;/strong&gt; (&lt;a href="https://github.com/sveltejs/svelte/issues/2086"&gt;https://github.com/sveltejs/svelte/issues/2086&lt;/a&gt;). Some of my dynamically creating and swapping around components that also had a a few reactive, dynamically created components inside of them. &lt;/p&gt;

&lt;p&gt;I added a simple if statement to check if node.parentNode exists and that was it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;detach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error: patch-package: svelte detach failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Later I revisited this small tweak and added a &lt;code&gt;console.warn&lt;/code&gt; to see when the error occurs in case it causes other issues down the line.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v-Bgk8in--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5qqgn8y0uz0xskoif5ot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v-Bgk8in--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5qqgn8y0uz0xskoif5ot.png" alt="Console.warn stack trace" width="637" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Now my first portfolio project is very close to being finished.
&lt;/h2&gt;

&lt;h3&gt;
  
  
  I'm working on a webapp that applies shader filters to images. WebGL + Svelte 🥰
&lt;/h3&gt;

&lt;p&gt;Making pixel art with shaders is the most fun I've had with it. Here's the &lt;a href="https://en.wikipedia.org/wiki/Giant%27s_Causeway"&gt;Giant's Causeway&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4oFtWKT---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jufks9s0sb74wj9rfn5b.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4oFtWKT---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jufks9s0sb74wj9rfn5b.jpg" alt="Giant's Causeway" width="880" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here it is after applying Color Palette limtier, Pixelate and Bloom shaders. &lt;a href="https://imgur.com/AKEqx9O"&gt;FullRez Link&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JBs5bhHd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/AKEqx9O.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JBs5bhHd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/AKEqx9O.png" alt="Giant's Causeway Pixelart" width="880" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>javascript</category>
      <category>npm</category>
    </item>
    <item>
      <title>What do you use for prototyping data structures?</title>
      <dc:creator>Martin J</dc:creator>
      <pubDate>Mon, 13 Jan 2020 13:45:42 +0000</pubDate>
      <link>https://dev.to/jerzakm/what-do-you-use-for-prototyping-data-structure-34ga</link>
      <guid>https://dev.to/jerzakm/what-do-you-use-for-prototyping-data-structure-34ga</guid>
      <description>&lt;p&gt;So far I've mostly used pen&amp;amp;paper. Tools for designing the data structure or graphing felt either a bit clunky or way too complex for my needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about you?
&lt;/h2&gt;

&lt;p&gt;Recently, since I picked up typescript I found using interfaces just for this purpose to be quite useful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Location&lt;/span&gt;
    &lt;span class="nx"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;geoBin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="c1"&gt;//uber h3?&lt;/span&gt;
    &lt;span class="nx"&gt;friends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="c1"&gt;//friend user id array&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Can even use jsdoc for stuff
 */&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Location&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;
    &lt;span class="nx"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Listing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="c1"&gt;//userId&lt;/span&gt;
    &lt;span class="nx"&gt;created&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="c1"&gt;//ts&lt;/span&gt;
    &lt;span class="nx"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="c1"&gt;//ts&lt;/span&gt;
    &lt;span class="nx"&gt;geoBin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Location&lt;/span&gt;
    &lt;span class="nx"&gt;system&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="c1"&gt;//array or string, array for more&lt;/span&gt;
    &lt;span class="nx"&gt;online&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="c1"&gt;//markdown&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Estimating user's GPU performance capabilities</title>
      <dc:creator>Martin J</dc:creator>
      <pubDate>Sat, 21 Dec 2019 15:12:48 +0000</pubDate>
      <link>https://dev.to/jerzakm/estimating-user-s-gpu-performance-capabilities-4efh</link>
      <guid>https://dev.to/jerzakm/estimating-user-s-gpu-performance-capabilities-4efh</guid>
      <description>&lt;p&gt;I slowly started making my portfolio site and I want to use Three.js and shaders.  I feel like I should have some sort of a fallback for mobile and low-end PCs.. &lt;/p&gt;

&lt;h1&gt;
  
  
  How do you adjust your web content to match client machine's performance?
&lt;/h1&gt;

&lt;p&gt;Currently for the sake of testing I put a pretty compute heavy shader that works fine on my home PC, but completely chunks down my mobile and office PCs: &lt;br&gt;
&lt;a href="https://www.jerzakm.com/"&gt;https://www.jerzakm.com/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_debug_renderer_info"&gt;WEBGL_debug_renderer_info&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Webgl context allows us to accurately (In most cases) get user's GPU. Sounds great but from a first glance it has two disadvantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User privacy. Knowing precise GPU model allows for ad targeting and unnecessary data mining.&lt;/li&gt;
&lt;li&gt;Keeping it up to date. New GPUs come out all the time, and it would become necessary to update GPU list and benchmarks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are libraries already available that do precisely that, but I'm not 100% happy with any of them.&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/detect-gpu"&gt;detect-gpu&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: Rendering a few first frames off-screen and checking performance before deciding how to proceed
&lt;/h3&gt;

&lt;p&gt;This takes care of privacy issues, but requires loading potentially unnecessary libraries and causing a browser freeze on first load.&lt;/p&gt;

</description>
      <category>help</category>
      <category>javascript</category>
      <category>webperf</category>
    </item>
    <item>
      <title>Impostor to a poster. Prologue to a career change.</title>
      <dc:creator>Martin J</dc:creator>
      <pubDate>Sun, 08 Dec 2019 12:20:45 +0000</pubDate>
      <link>https://dev.to/jerzakm/impostor-to-a-poster-prologue-to-a-career-change-2a9j</link>
      <guid>https://dev.to/jerzakm/impostor-to-a-poster-prologue-to-a-career-change-2a9j</guid>
      <description>&lt;h2&gt;
  
  
  Unnecessarily long background intro.
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Scroll if you like images more&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I've been a geek and the 'computer guy' of the family for pretty much my whole life. Everyone thought I'm going to study Computer Science, Engineering, Robotics or something similar, but that never happened. Throughout my late teens and early 20s, a mix of bad decisions and life kicking me in the butt has successfully kept me in dead-end low paying jobs.&lt;/p&gt;

&lt;p&gt;I caught a break when I started working for an online store. I began as an intern but rose up in the ranks quickly to become a sales executive responsible for a solid chunk of change. It's a relatively small company, so I get to influence product design, liaison with manufacturers from China, acquire new international clients and oversee general sales strategy for my products.&lt;/p&gt;

&lt;p&gt;Unlike in my previous jobs, I don't have a set of responsibilities assigned for every waking minute of my workday. I get to assign my own goals and work at my own pace. Quite quickly I noticed how inefficient our office runs, and how massive the tech debt has gotten at this point. I started doing some Java tutorials during my work hours and not long after I parsed CSVs and built data visualizations like there was no tomorrow. That was a little over two years ago. Since then I expanded and used my newfound coding skills countless of times and by now saved hundreds of manhours.&lt;/p&gt;

&lt;p&gt;Over time, as my tasks at work have become more repetitive. I love discovering new things and reaching my goals, but hardly anything new ever happens here. It must have been about a year ago that I've decided to shape up my coding skills and go through with a career change.&lt;/p&gt;

&lt;p&gt;Without a shadow of a doubt, I have greatly improved since then. I touched on just about every buzzword out there and I can hold my own in a tech conversation, yet I still didn't apply for a single position. My cushy job is holding me back. I live in a small town and I'd likely have to relocate for any tech job. I don't particularly mind moving. At the same time though, the prospect of having to move and the fact that it would be a while until I'd get equal or larger salary than that of my sales exec job has successfully dissuaded me from trying to apply.&lt;/p&gt;

&lt;p&gt;What if I'm not good enough? Maybe if I just learn one more library or a framework it will be enough. The impostor syndrome was real. That's when I read some stories from dev.to community and watched youtube videos about when one could get a first coding job and..&lt;/p&gt;

&lt;h2&gt;
  
  
  I should have applied a long time ago.
&lt;/h2&gt;

&lt;p&gt;I think I'll hate myself If I'm still in sales in a few years. I love solving problems, discovering new things and I think quick on my feet. Anything mundane and commonplace bores me, it sucks the soul out of me. When I solve problems with coding sparks fly and unicorns gallop across the rainbow-filled sky.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MJORd8y9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/F6zlGbo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MJORd8y9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/F6zlGbo.png" alt="My github activity" width="880" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imo, this looks like a GitHub of a person who shouldn't be afraid to apply.&lt;/p&gt;

&lt;p&gt;A few weeks ago I took part in a Ludum Dare game jam, and I have gotten a lot of great feedback. What I lacked in skill, I made up for with cheap humour and it turned out a lot better than I could have imagined. I made a &lt;a href="https://ldjam.com/events/ludum-dare/45/ludum-dare-simulator"&gt;Ludum Dare Simulator&lt;/a&gt;, a card game about people making games for the LD gamejam. So. Meta.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6aTRLiqs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://static.jam.vg/raw/620/72/z/2630b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6aTRLiqs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://static.jam.vg/raw/620/72/z/2630b.png" alt="Ludum Dare Simulator Screenshot" width="880" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What I lacked in skill, I made up for with cheap humour.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uZ5cSi4I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/fZWJHRX.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uZ5cSi4I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/fZWJHRX.png" alt="Ludum Dare Simulator cards" width="880" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing code for myself and never showing it to the world was a mistake.
&lt;/h3&gt;

&lt;p&gt;I'm oddly proud of this one. &lt;a href="https://imgur.com/xDUTEwW"&gt;Don't open if you're an orc right activist.&lt;/a&gt;  Why is it cool? Pixi.js webgl renderer, orc bodies splinter dynamically based on where the arrow hits them, arrow &amp;amp; orc physics with matter.js, custom blood emitter. It's not hosted anywhere right now, I broke it a little but it's high on my TODO list.&lt;/p&gt;

&lt;p&gt;My GitHub is a mess and I don't have a working portfolio as of yet, but I decided to get it all sorted out throughout this year's holiday season and start applying right after new years.&lt;/p&gt;

&lt;p&gt;I plan to share my experience, post tutorials and stuff about cool things I encounter on my journey.&lt;/p&gt;

&lt;p&gt;Next stop - portfolio to show off my skills.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PmyX5fNJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/O7Yx7aK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PmyX5fNJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/O7Yx7aK.png" alt="Portfolio design progress" width="880" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

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