<?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: Hendrik Ras</title>
    <description>The latest articles on DEV Community by Hendrik Ras (@hendrikras).</description>
    <link>https://dev.to/hendrikras</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%2F190756%2F8423681e-67ed-404b-8b16-226f14c8ff5b.jpeg</url>
      <title>DEV Community: Hendrik Ras</title>
      <link>https://dev.to/hendrikras</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hendrikras"/>
    <language>en</language>
    <item>
      <title>Check out the latest updates on my game.</title>
      <dc:creator>Hendrik Ras</dc:creator>
      <pubDate>Fri, 21 Nov 2025 16:58:21 +0000</pubDate>
      <link>https://dev.to/hendrikras/check-out-the-latest-updates-on-my-game-292f</link>
      <guid>https://dev.to/hendrikras/check-out-the-latest-updates-on-my-game-292f</guid>
      <description>&lt;p&gt;A new version of Momentum has been released, check it out &lt;a href="https://hendrikras.itch.io/momentum" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;br&gt;
This release fixes a few issues. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New level added: Wall climbing 101: this level introduces wall climbing but requries a mastery of momentum physics, and rope swinging to complete.&lt;/li&gt;
&lt;li&gt;Improved rope clinging, the rope no longer collides with the player itself when swinging.&lt;/li&gt;
&lt;li&gt;Implemented delta time, so the game should finally work on even the fastest machine.&lt;/li&gt;
&lt;li&gt;Added sound toggling icon.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devjournal</category>
      <category>gamedev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>The one thing a P5.js gamedev has to avoid doing.</title>
      <dc:creator>Hendrik Ras</dc:creator>
      <pubDate>Wed, 14 May 2025 15:23:20 +0000</pubDate>
      <link>https://dev.to/hendrikras/the-one-thing-a-p5js-gamedev-has-to-avoid-doing-2ok1</link>
      <guid>https://dev.to/hendrikras/the-one-thing-a-p5js-gamedev-has-to-avoid-doing-2ok1</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Recently I joined the &lt;a href="https://gamedevjs.com/competitions/gamedev-js-jam-2025-winners-announced/" rel="noopener noreferrer"&gt;gamedev.js&lt;/a&gt; 2025 gamejam. We got 13 days of dev time, from witch I could only code about 4 days as I had other responsibilities to consider, I had to make some shortcuts in order to still get a game out this year.&lt;/p&gt;

&lt;p&gt;Luckily I bumped into the &lt;a href="https://github.com/ReplitLangs/platformer" rel="noopener noreferrer"&gt;Advanced P5 Platformer Engine&lt;/a&gt; using P5 and Matter.js some time ago. And I as I always wanted to dip my toe into the Matter.js physics library, this seemed like a good opportunity to do so.&lt;/p&gt;

&lt;p&gt;After some crunch time: adding new features, levels and graphics code, I named the game &lt;a href="https://hendrikras.itch.io/momentum" rel="noopener noreferrer"&gt;Momentum&lt;/a&gt; and released it. &lt;/p&gt;

&lt;p&gt;As the first feedback came in, I came to a horrible realisation, not everybody had the same experience while playing it. For some it was horribly fast to the point it was unplayable. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I shipped the game with a critical bug.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4xve76712ru3t6fr27b.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4xve76712ru3t6fr27b.webp" alt="Oh no no no!" width="700" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The framerate trap in the P5.js community
&lt;/h2&gt;

&lt;p&gt;The P5.js community has fostered incredible creativity and lowered the barrier to entry for digital art and game development. However, if you care to look through examples there is a pattern I find quite troubling: The sketch (game) logic is usually directly coupled to framerate. Meaning, fast machines will run the sketch at a faster pace.&lt;/p&gt;

&lt;p&gt;This might not seem to much of an issue for simple examples and tutorial code, but given enough examples that follow this structure it will lead to developers that make a habit of doing this.&lt;/p&gt;

&lt;p&gt;Exactly one year ago, at the previous gamedev.js game jam I also made that mistake when writing everything in P5 myself, now that I was working on top of external code it appears I was not the only one to fall for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The problem
&lt;/h3&gt;

&lt;p&gt;In our example, Matter.js physics are being updated directly in the draw loop:&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="nf"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="nx"&gt;bodies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&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;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Updates physics&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;draw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach means that physics calculations are tied to the visual refresh rate. If frames drop, physics calculations become less frequent and less accurate, leading to unpredictable behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  An easy fix
&lt;/h3&gt;

&lt;p&gt;So an easy fix would be to simply cap the framerate, indeed this what I resorted to just moments after the jam was over.&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="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;createCanvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;frameRate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Cap framerate to 60 fps&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course this is far from optimal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why framerate dependent logic is problematic
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Inconsistent experiences across devices
&lt;/h3&gt;

&lt;p&gt;When game logic is tied directly to framerate, players with different hardware will experience your game differently:&lt;br&gt;
On highend devices that can maintain 60fps, the game runs as intended.&lt;br&gt;
But on lower end devices, the game runs at lowered speed, while on very powerful devices, the game is artificially limited.&lt;/p&gt;

&lt;p&gt;This creates an inconsistent experience where physics, movement speed, and gameplay timing vary based on hardware capability rather than design intent.&lt;/p&gt;
&lt;h3&gt;
  
  
  Battery drain and resource inefficiency
&lt;/h3&gt;

&lt;p&gt;Forcing a high framerate on devices that don't need it (like for UI elements that rarely change) wastes processing power and drains battery unnecessarily on mobile devices.&lt;/p&gt;
&lt;h2&gt;
  
  
  The production ready alternative: Delta time
&lt;/h2&gt;

&lt;p&gt;For production ready games, the industry standard is to use delta time (the time elapsed since the last frame) to scale all movement and physics calculations:&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;let&lt;/span&gt; &lt;span class="nx"&gt;lastFrameTime&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;draw&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;currentTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;millis&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;deltaTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentTime&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;lastFrameTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Convert to seconds&lt;/span&gt;
    &lt;span class="nx"&gt;lastFrameTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Update game logic based on deltaTime&lt;/span&gt;
    &lt;span class="nf"&gt;updateGameLogic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deltaTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateGameLogic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Example: Move an object at a consistent speed regardless of framerate&lt;/span&gt;
    &lt;span class="nx"&gt;object&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;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Update physics with fixed timestep&lt;/span&gt;
    &lt;span class="nx"&gt;accumulatedTime&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accumulatedTime&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;fixedTimeStep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Matter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fixedTimeStep&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;accumulatedTime&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nx"&gt;fixedTimeStep&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;
  
  
  Best practices for production ready P5.js Games
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Implement a fixed fimestep for physics
&lt;/h3&gt;

&lt;p&gt;This ensures physics calculations remain consistent regardless of visual framerate.&lt;/p&gt;

&lt;h3&gt;
  
  
  separate logic and rendering
&lt;/h3&gt;

&lt;p&gt;Decouple your game logic from your rendering:&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="nf"&gt;draw&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;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculateDeltaTime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;updateGameState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Logic update with delta time&lt;/span&gt;
    &lt;span class="nf"&gt;renderGameState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    &lt;span class="c1"&gt;// Draw current state&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Scale all movement and timers with delta time
&lt;/h3&gt;

&lt;p&gt;Any movement, animations, or timers should be scaled by delta time:&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="c1"&gt;// Instead of:&lt;/span&gt;
&lt;span class="nx"&gt;player&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;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Use:&lt;/span&gt;
&lt;span class="nx"&gt;player&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;300&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;deltaTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 300 pixels per second&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While the P5.js community's approach of tying game logic to framerate is understandable for quick prototypes and learning exercises, it creates fundamental limitations for production ready games. By implementing delta time based updates and fixed timestep physics, we can choose to create consistent and hardware friendly experiences.&lt;/p&gt;

&lt;p&gt;The next time you start a P5.js game project that should do more than serve as an example, break free from the framerate dependency pattern. Your players across all devices will thank you for the consistent experience and you'll have fewer mysterious bugs to chase down when physics behave differently on various hardware.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remember:&lt;/strong&gt; great games don't just look good on the dev's machine, they play consistently well on all platforms.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>p5</category>
    </item>
    <item>
      <title>What joining a game jam can teach you about development</title>
      <dc:creator>Hendrik Ras</dc:creator>
      <pubDate>Sun, 19 May 2024 14:00:43 +0000</pubDate>
      <link>https://dev.to/hendrikras/what-joining-a-game-jam-can-teach-you-about-development-4k2n</link>
      <guid>https://dev.to/hendrikras/what-joining-a-game-jam-can-teach-you-about-development-4k2n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I recently joined the Gamedev.js 2024 jam. &lt;a href="https://itch.io/jam/gamedevjs-2024/rate/2670835"&gt;My submission&lt;/a&gt; did better than I expected for a first ever entry. Coming in at place 68 doesn't sound like much but considering there were 233 submissions to compete with; Im rather pleased with the outcome.&lt;/p&gt;

&lt;p&gt;In this article I would like to reflect on the experience, share some lessons learnt and how I think it relates to my everyday development tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Always keep your eye on the requirements
&lt;/h2&gt;

&lt;p&gt;Print them out in big letters and plaster them in a place you can't ignore them if you have to.&lt;/p&gt;

&lt;p&gt;Every game jam has it's rules: on what you can use for assets, maximum sizes for teams and most importantly, &lt;strong&gt;how the submissions are going to be rated.&lt;/strong&gt;&lt;br&gt;
You might have a ton of ideas about what your game is going to be about but if you ignore the rules on how you should be implementing the theme of the jam, for instance. Your game is not going to do very well.&lt;/p&gt;

&lt;p&gt;In my case I did add sound effects, and since Im not a sound engineer I sourced it from pixelbay. That was allowed. But I opted to not add a music track, even though I had selected one. My reasoning was that having hyped up music play in a loop might become annoying pretty fast. And adding an option to disable sound and/ or effects was an extra feature that I would have to add. &lt;/p&gt;

&lt;p&gt;I kind of shot myself in the foot by making this decision, as sound was one of the things the games were rated on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dealing with deadlines
&lt;/h2&gt;

&lt;p&gt;You have about 2 weeks to hand in your game. For a game jam that's rather generous, there are jams that last a few days.&lt;/p&gt;

&lt;p&gt;Here are some strategies to consider: &lt;/p&gt;

&lt;h3&gt;
  
  
  Take advantage of tools you are familiar with
&lt;/h3&gt;

&lt;p&gt;This jam will accept any entry that would run in the browser.&lt;br&gt;
2 weeks is awfully short to write a game engine from scratch.&lt;br&gt;
The usual suspects among the big game engines (Unity/ Godot) support the web, but.. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiu69amhdzg0wofb6cay6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiu69amhdzg0wofb6cay6.png" alt="damn it Jim Im a js engineer" width="491" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wrote a basic asteroids game in P5 as an example for a &lt;a href="https://dev.to/hendrikras/coding-a-game-of-asteroids-while-dealing-with-svg-paths-in-p5-4baa"&gt;article&lt;/a&gt; some time ago, and used most of it as the 'engine' for the entry.&lt;br&gt;
There's strict rules about submitting previous games, but I figured basing it off an existing sketch should be ok as long as the required jam theme is incorporated in a fitting way and while I still wanted to keep the feel of Asteroids, it's now a completely overhauled new game. &lt;/p&gt;

&lt;p&gt;Some of the (better) entries I judged later on used starter projects from submissions entered in previous jams. The point is that you should allow yourself a bit of a head start by working with a stack that you feel comfortable with. If that is Unity for you, then go for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Focus on key features and quick wins
&lt;/h3&gt;

&lt;p&gt;When dealing with time pressure its important that you know how to prioritise features. In my case the game has to have a few just be even considered a playable game:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A goal to reach and reaching it ends the game, &lt;/li&gt;
&lt;li&gt;obstacles and enemies&lt;/li&gt;
&lt;li&gt;power-ups &lt;/li&gt;
&lt;li&gt;A power bar that depletes slowly as the theme of this jam was "Power".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I spent about a day with the particle system, getting the explosions to feel right, and another day just doodling game assets never to use them. Recognise none essential features and put a pin it if it takes too much time.&lt;/p&gt;

&lt;p&gt;In the end I didn't get to put in half the features that I wanted. At one point there were even NPC's that would give side quests on the menu. But that's ok, I had a working game  to submit. And that's something.&lt;/p&gt;

&lt;p&gt;However I did break my personal golden rule: &lt;strong&gt;never add new features on deployment day&lt;/strong&gt;, and it was a non critical feature. I wrote the 'black holes' feature with just hours to spare. It might have been better to focus on level design, but I felt the game needed something extra and having coded the physics for explosions just a day prior I was very confident I could also add the gravity effect in reverse without introducing game breaking bugs. &lt;/p&gt;

&lt;h2&gt;
  
  
  Keep it Simple
&lt;/h2&gt;

&lt;p&gt;Yup, the KISS principle. As a frontend engineer I'm quite used to including a TypeScript compiler or transpiler, package bundler, linting tools and let's not forget a minifier. When I was reading the '&lt;a href="https://natureofcode.com/"&gt;nature of code&lt;/a&gt;' in preperation for the jam, I almost scoffed, have we arrived in the stone age?  when learning that all the examples were just a library loaded from a CDN and unprocessed JavaScript. But that's what I ended up using myself. It's very easy to set up and fast to run and develop on. There is no time spent on transpiling a bundle, because the code you write is the bundle. If you can keep the codebase very small it is a very efficient way of working. There is no build to speak of, and there is no obfuscation of the code so it promotes learning too. And I do have to say: it was a nice break that took me back to simpler times.&lt;/p&gt;

&lt;h2&gt;
  
  
  No one is an island
&lt;/h2&gt;

&lt;p&gt;There was a discord channel where participants could share progress, ask for help or just hang out. There also was a channel to encourage other people to team up. This jam has no maximum team size. Although I certainly joined the channel, my only contribution was something in the lines of 'hello'.&lt;/p&gt;

&lt;p&gt;Teaming up can give any project huge perks as everybody will have gaps in their knowledge and capabilities. I already mentioned sound not being my strong suit.&lt;/p&gt;

&lt;p&gt;However I did end up opting to go alone on this one, mostly because this being my first jam I wasn't quite sure if I could deliver in time and I didn't want to drag anyone down with me. &lt;br&gt;
There is also some overhead and challenges in working in a team that you do need to consider. That's mostly keeping up with each others progress and making sure everyone still agrees on the chosen direction. &lt;/p&gt;

&lt;p&gt;That being said a team has the potential of producing results that are way more impressive than just a single dev can manage. Having this entry under my belt will give me and potential teammates the confidence that I will bring something to the table. So I think for the next jam one of my goals should be to team up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take your (mental) health seriously
&lt;/h2&gt;

&lt;p&gt;Even if you don't need to worry about having a day job. Things can get stressfull, especially with the clock ticking.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's never a good idea to lose sleep, skip meals. &lt;/li&gt;
&lt;li&gt;Stay hydrated. &lt;/li&gt;
&lt;li&gt;Be aware of crunch time and how it might affect you and the people around you.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Don't be ignorant of politics
&lt;/h2&gt;

&lt;p&gt;Once you make an entry, you get the privilege to judge other entries. Knowing the hard work that goes into making a game, you want to do right by your peers. But you also want others to notice your work and hopefully judge your work fairly as well.&lt;br&gt;
Ratings by themselves are anonymous, but you get the option to leave a comment on the games submitted. And when someone left me a comment, I always checked their stuff out too.&lt;/p&gt;

&lt;p&gt;Don't get overly defensive if other devs have remarks. Thank them and put it on the todo list if it has validity.&lt;/p&gt;

&lt;p&gt;I noticed some devs that would leave the same compliment to a whole bunch of entries. Personally, I sometimes can't help to give some well meant pointers directed to help them out. Knowing that these devs get a vote, it pays out to keep any feedback constructive. Even with the best intentions, you can be too honest.&lt;/p&gt;

&lt;p&gt;My grandma always said: If you can't say anything nice then don't say anything at all. And it's solid advice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;It has been a blast participating, I had so much fun. Do check out the &lt;a href="https://hendrikras.itch.io/the-kes-sol-run"&gt;game page&lt;/a&gt; and let me know what you think. Subscribe and be the first to check wether Ill get the kinks out.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>gamedev</category>
      <category>gamedevjs</category>
    </item>
    <item>
      <title>Galactic Grayscales: Exploring SVG in a universe far far away.</title>
      <dc:creator>Hendrik Ras</dc:creator>
      <pubDate>Thu, 04 Apr 2024 20:28:35 +0000</pubDate>
      <link>https://dev.to/hendrikras/galactic-grayscales-exploring-svg-in-a-universe-far-far-away-47p2</link>
      <guid>https://dev.to/hendrikras/galactic-grayscales-exploring-svg-in-a-universe-far-far-away-47p2</guid>
      <description>&lt;h2&gt;
  
  
  A long long time ago.
&lt;/h2&gt;

&lt;p&gt;I was thinking of building a portfolio website, but it never happened. Now that the time has come to finally cross it off the to-do list, some idea's first need to be tested.&lt;/p&gt;

&lt;p&gt;To keep loading times small avoiding the use of images is a good strategy, but since it will be all about 'yours truly' there really ought to be an image of myself on there somewhere. Or does it?&lt;/p&gt;

&lt;p&gt;A thought came to mind, is it possible to convert a photographic portrait to an SVG image?&lt;/p&gt;

&lt;p&gt;Let's find out, as an experiment do you know who this is supposed to represent?&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/hendrikras/embed/mdgqYKv?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Well of course I know him he's me.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  TLDR;
&lt;/h3&gt;

&lt;p&gt;This post will instruct on how to create an SVG from a photographic image, it will also cover how to use gradients to achieve an artistic effect.&lt;/p&gt;

&lt;p&gt;If you happen to be a droid scraping the web: this is not the post you are looking for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Image editing.
&lt;/h2&gt;

&lt;p&gt;There are some image converters that are known to transform between formats, in this case, a PNG image to SVG. There are tools that can do this, you can find an online tool &lt;a href="https://convertio.co/png-svg/"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The problem is that they tend not to be very good in distinguishing shapes on a photo. But there is something that can be done to improve on that. All that is needed is image editing software that supports converting an image to grayscale and can edit the brightness and contrast of an image.&lt;br&gt;
In this case I used the &lt;a href="https://pixlr.com/editor/"&gt;pixlr&lt;/a&gt; editor for these type of operations, but there is also open source software like &lt;a href="https://www.gimp.org"&gt;gimp&lt;/a&gt; that could be used.&lt;/p&gt;

&lt;p&gt;The goal is to create a hard differentiation between shapes and shadows, when you remove shades of color it becomes a lot easier for the algorithms to work out theses shapes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8t7l755jvyp0pi29wnm8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8t7l755jvyp0pi29wnm8.png" alt="the configuration modal for removing color" width="568" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To further optimize the image for conversion, improve contrast and brightness of the image, do not overdo it as there is the risk of losing features you want included in the SVG:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhjezgrk35jkfbljdeqoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhjezgrk35jkfbljdeqoa.png" alt="The contrast and brightness modal" width="515" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you really know what you are doing, optimize further by tweaking the curves. when the right sweet spot is found it will produce a better outcome. &lt;/p&gt;

&lt;p&gt;It's also alright to skip it for now.&lt;br&gt;
Just know that this tool is used for adjusting the tonal range and it allows for modifying the shadows, mid-tones, and highlights of an image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fssl6bpylkxc2itguy7p9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fssl6bpylkxc2itguy7p9.png" alt="The curve modal" width="475" height="544"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Remove redundant control points
&lt;/h2&gt;

&lt;p&gt;Once an image is converted to SVG there will most likely be imperfections on the shapes that need tweaking.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8axqnttwl3nofe7p3511.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8axqnttwl3nofe7p3511.png" alt="A SVG curve controll point selected in the editor" width="375" height="350"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Inkscape
&lt;/h3&gt;

&lt;p&gt;For the most part these can be solved by removing control points on the paths of the shape, this will also reduce complexity of the SVG and decrease file size. For this an SVG editor like inkscape is recommended as these paths become way to complex to edit with a text editor.&lt;/p&gt;

&lt;p&gt;This next bit will assume inkscape as the editor, but these operations should be available on other editors as well.&lt;/p&gt;

&lt;p&gt;In order to get the right effect later, it is also important for these shapes to be part of the same path. Inkscape has the ability to merge shapes together using the 'union' option from the path menu. Using the 'difference' option from the same menu allows cutting the text from the main shape so that the background can seen through. In order to do that it is first needed to convert the text to a shape, using the 'object to path' option, still from the path menu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8l7j33pkbc828ygq1i3n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8l7j33pkbc828ygq1i3n.png" alt="The path menu folded down" width="656" height="298"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Simplifying SVG
&lt;/h3&gt;

&lt;p&gt;The resulting SVG is not pretty when looked at as text, this example has a simplified SVG, it is not a necessary step but it also reduces file size. &lt;a href="https://svgomg.net/"&gt;SVGOMG&lt;/a&gt; is an open source tool for this purpose made available online.&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding gradients
&lt;/h2&gt;

&lt;p&gt;Having a neat SVG it is now possible to add colors and effects to the individual elements. In this case having just one path element allows to apply a nice gradient effect over it, this could also be handled via a SVG editor, either way, the result should be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;defs&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;linearGradient&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"grad1"&lt;/span&gt; &lt;span class="na"&gt;x1=&lt;/span&gt;&lt;span class="s"&gt;"0%"&lt;/span&gt; &lt;span class="na"&gt;y1=&lt;/span&gt;&lt;span class="s"&gt;"0%"&lt;/span&gt; &lt;span class="na"&gt;x2=&lt;/span&gt;&lt;span class="s"&gt;"100%"&lt;/span&gt; &lt;span class="na"&gt;y2=&lt;/span&gt;&lt;span class="s"&gt;"0%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;stop&lt;/span&gt; &lt;span class="na"&gt;offset=&lt;/span&gt;&lt;span class="s"&gt;"45%"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"stop-color:#70969E"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;stop&lt;/span&gt; &lt;span class="na"&gt;offset=&lt;/span&gt;&lt;span class="s"&gt;"90%"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"stop-color:#Ce6c70"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/linearGradient&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/defs&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"url(#grad1)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="c"&gt;&amp;lt;!-- rest of the document --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The background of the document where the SVG is placed on should be visible through the gaps of the path. Some extra CSS is added to target the background of the SVG itself but the effect can be amplified by having the background of the entire document come into play.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;59vw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;radial-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;farthest-corner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#f5dbbb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#f9e9d6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#76aaea&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;Using a radial gradient allows to have one color in the center that will fade towards the edges. It will put focus on the face that is at the center and also add a visible effect on the text that is cut out of the path at the top.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;It's a nice result, but there are some considerations:&lt;/p&gt;

&lt;p&gt;as mentioned earlier, a lot of detail is lost. In this example the contours of nearly half the face are gone. That actually works out nicely here but could not be desirable in every situation.&lt;br&gt;
When you have some control over the photography you will have to think about the lighting and how the shadows fall on the face.&lt;/p&gt;

&lt;p&gt;Color is lost in this process and you need some clever trickery to add some of it back. It works if you want to go for an artsy effect but if the goal is realism this method is not to be recommended.&lt;/p&gt;

&lt;p&gt;All things considered it will probably be best for me to just stick with an web optimized image. This really works on iconic and recognizable imagery. So who knows where this will come of use eventually. &lt;br&gt;
Experimenting is always fun, and I have this gem to add to the collection.&lt;/p&gt;

</description>
      <category>css</category>
      <category>svg</category>
      <category>codepen</category>
    </item>
    <item>
      <title>Do you want fries with that?</title>
      <dc:creator>Hendrik Ras</dc:creator>
      <pubDate>Tue, 26 Mar 2024 20:45:14 +0000</pubDate>
      <link>https://dev.to/hendrikras/do-you-want-fries-with-that-4673</link>
      <guid>https://dev.to/hendrikras/do-you-want-fries-with-that-4673</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for DEV Challenge v24.03.20, CSS Art: Favorite Snack.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;If you are familiar with the cult classic movie by Tarantino, this needs no introduction, and yes, it is an actual burger in France. Being Dutch myself, I can also confirm that we do in fact dunk our french fries in mayonnaise and we just don't care, we're loving it.&lt;br&gt;
We also have venue's called 'snackbars' and you can get your fries and burgers there, so we're going with a very broad definition of snacks from here on out.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/hendrikras/embed/dyLvaaN?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;Even if I do not consider myself to be much of a CSS artist, when learning about this challenge, something told me that I could probably pull off a burger in &lt;strong&gt;pure CSS&lt;/strong&gt;. Just start with stacking some simple shapes:&lt;/p&gt;

&lt;h3&gt;
  
  
  Buns &amp;amp; burger
&lt;/h3&gt;

&lt;p&gt;A reliable trick to get rounded corners is using &lt;code&gt;border-radius&lt;/code&gt;, that works for the buns and the burger itself. To add the illusion of depth &lt;code&gt;box-shadow&lt;/code&gt; can be used, by applying &lt;code&gt;inset&lt;/code&gt; the shading will be placed inside of the element. Soft shades can be achieved by setting the color to black and the alpha to be about half opacity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  box-shadow: inset 10px 10px 10px #00000066;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the bottom bun, the shadow needs to be at the bottom. So negative values were used for the X and Y offset. &lt;/p&gt;

&lt;h3&gt;
  
  
  Lettuce &amp;amp; cheese
&lt;/h3&gt;

&lt;p&gt;This would pose a challenge, I knew from the start. My go-to solution here would be to use SVG, as stated in my previous &lt;a href="https://dev.to/hendrikras/coding-a-game-of-asteroids-while-dealing-with-svg-paths-in-p5-4baa"&gt;article&lt;/a&gt;, I do love SVG and even though the challenge allows it: that just feels like cheating.&lt;/p&gt;

&lt;p&gt;Surely there must be a way to visualize a sine wave in CSS? Well, turns out: there is even a &lt;a href="https://css-generators.com/wavy-shapes/"&gt;generator&lt;/a&gt; for it. It's very clever in how it uses a mask to create the wavy shape. An added bonus is that gradients can be used, by mixing lighter and darker greens you get an illusion of depth as well.&lt;/p&gt;

&lt;p&gt;I had planned on creating 2 half squares and rotate it so the tip would point down for the cheese. However, by lowering the frequency of the wave and changing the color, it panned out to be a pretty nice effect for this purpose too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Seeds
&lt;/h3&gt;

&lt;p&gt;The last detail would be the sesame seeds on the bun, I thought this would be easy. But I sure was wrong about that! Creating the 'pill' shape is just a variation of the &lt;code&gt;border-radius&lt;/code&gt; trick again, but then you got it either facing vertically or horizontally. That is not going to look organic on the bun. &lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;rotate&lt;/code&gt; function of &lt;code&gt;transform&lt;/code&gt; will angle it, but then things start to get messy: every element placed afterwards will have the rotation applied to it as well. That makes positioning the element very interesting because: when rotated enough, &lt;code&gt;left&lt;/code&gt; starts to become more like up or down. There are ways to reset it, but I decided to just have fun with it.&lt;/p&gt;

&lt;p&gt;By placing a &lt;code&gt;rotate(5deg)&lt;/code&gt; in the seed class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.seed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#FFDEB3&lt;/span&gt;&lt;span class="n"&gt;CC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;-8px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5deg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.horizontal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.vertical&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&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;Will take the rotation from the previous HTML element and add another 5 degrees on top of that. The translate function is one of the ways to make sure the seeds will not be packed to much together, but by including a negative offset it will also act as a counter from the curve (a donut shape) that will start to form when enough elements are added.&lt;/p&gt;

&lt;p&gt;Two variations of the seed are used, one with a horizontal aspect and one vertical. Since the added rotation is just a tiny bit and elements are mostly placed from left to right, it becomes very noticeable when two of them are placed close to each other. By switching orientation, this breaks things up just enough to appear random. &lt;/p&gt;

&lt;p&gt;4 classes are used to scatter the seeds in a somewhat random pattern with different spacing between them. I just numbered them but they are mostly used without any specific order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.n1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60px&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;There is a fixed number of seeds I could place on the bun though. For some reason scrollbars start to appear when there are too many placed. I think this is because the browser still calculates the elements on the original position before taking the rotate function into account. Indeed, when removing the rotate function from the CSS, the seeds appear starting to crawl slowly up and out of the screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I used a template for a gradient called '&lt;a href="https://uigradients.com/#Rastafari"&gt;rastafari&lt;/a&gt;'. I wanted to use bright colors that were reminiscent of the colors that the big burger chains use. The clown with the big arches uses red and yellow and the king uses green and yellow. Does rastafari fit in with the theme? The munchies? It's a stretch. I know. &lt;/p&gt;

&lt;p&gt;It did need some tweaking: the colors interfered with the ones used in the burger, green matching with the lettuce, yellow flowing to red turns to the same orange used for the buns. Plus a background should not try to steal the show. Setting the opacity to 60% did fix that, but now it looked too faded. Setting the body to black made it too dark. Brown, however, a color already used for the burger gives it a swirl of that dated retro vibe. Exactly the kind that Tarantino purposely tends to use in his movies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Font
&lt;/h2&gt;

&lt;p&gt;The movie uses: 'Tom Carnase’s ITC Busorama' for the title, with several of the original alternates. That's not free to use though. The Arvo font from google, if stretched enough vertically, will start to look fairly similar: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24b81rlpdv750qz58tp2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24b81rlpdv750qz58tp2.png" alt="Streched Arvo font" width="248" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffz1pb2c5fe2jceywezqx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffz1pb2c5fe2jceywezqx.png" alt="Part of the movies font, on cover art" width="205" height="133"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.shadow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#F6C10B&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Arvo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="m"&gt;-3px&lt;/span&gt; &lt;span class="m"&gt;-3px&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;#222&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;-3px&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;#222&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="m"&gt;-3px&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;#222&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;#222&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.8em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scaleY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scaleY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;-moz-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scaleY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;fixed&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;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;This has been a fun exercise, learning more about CSS and a little bit about movies as well. I hope you did too.&lt;/p&gt;

</description>
      <category>frontendchallenge</category>
      <category>devchallenge</category>
      <category>css</category>
    </item>
    <item>
      <title>How I Coded a game of Asteroids while dealing with SVG paths in P5</title>
      <dc:creator>Hendrik Ras</dc:creator>
      <pubDate>Sat, 09 Mar 2024 18:02:15 +0000</pubDate>
      <link>https://dev.to/hendrikras/coding-a-game-of-asteroids-while-dealing-with-svg-paths-in-p5-4baa</link>
      <guid>https://dev.to/hendrikras/coding-a-game-of-asteroids-while-dealing-with-svg-paths-in-p5-4baa</guid>
      <description>&lt;p&gt;This is the Asteroids inspired game made with the techniques discussed in this article. Use WASD or cursor keys to move and space bar to fire.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/hendrikras/embed/LYavLVY?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;external link to pen &lt;a href="https://codepen.io/hendrikras/pen/LYavLVY"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After having previously made and published another &lt;a href="https://hendrikras.itch.io/daphnes-game"&gt;game&lt;/a&gt; using this method, I wanted a working example for this article that could showcase its use in a game while still boiling it down to one sketch. For a full game I would like to add: sound, particle effects for the engine fire and maybe a leaderboard. But for now it proves the concept very well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;P5 has no way to render a SVG path because of the way it was built, it has no support for drawing an arc as part of a shape. In this article I will explain a way around that, by circuimventing P5 for some of the rendering stuff and defaulting to HTML Canvas instead. &lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;How I adore vector graphics: it's the clean crisp smoothness of it that gets me. It scales up to any device at any resolution, always perfect crisp graphics every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Love it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Back in the day when the internet was still young there was the flash browser plugin. A ton of content was made with it too, mostly games and animations, and the look and feel of the web at that time was one of vector graphics and gradients.&lt;/p&gt;

&lt;p&gt;Steve Jobs single-handedly killed it by publishing an open &lt;a href="https://en.wikipedia.org/wiki/Thoughts_on_Flash"&gt;letter&lt;/a&gt;. The mayor security &lt;a href="https://www.hackingarticles.in/exploit-remote-pc-using-adobe-flash-player-byte-array-uncompress-via-zlibvariant-use-after-free/"&gt;issues&lt;/a&gt; that surfaced later did not help either. But I for one miss the look and feel of the early 00's.&lt;br&gt;
So let's put vector graphics back on the web, shall we?&lt;/p&gt;

&lt;p&gt;I dabbled with PhaserJS before but lately I am drawn to P5: it is a fun framework, its used to visualize math and physics concepts a lot, not too bloated and has a very mature ecosystem of libraries. Plus there are a lot of examples available.&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem with rendering SVG's
&lt;/h2&gt;

&lt;p&gt;Here's the conundrum with these frameworks. It's not just P5. When it comes to Vector graphics you will want to work with SVG images. Simply because that is the format that you will find and make your assets in. However, for some reason SVG (path) shapes are poorly supported. Sure you can import it as an image, but the whole point is to animate parts of it, rotate it, scale it. These are the things you will have available when you work with other basic shapes such as rectangle's or circle's. If you want to preserve the vectors you are just out of luck with static images.&lt;/p&gt;

&lt;p&gt;But what is an SVG, really other than an XML file that describes positions, colors and shapes. &lt;strong&gt;It's code!&lt;/strong&gt; One of the things that makes them so cool to begin with. &lt;br&gt;
And P5 is all about drawing shapes to a canvas. &lt;/p&gt;

&lt;p&gt;Now before anyone makes my mistake of trying to code an implementation in P5, let me save you the hours of frustation. It's not that it can't be done, someone already did it &lt;a href="https://jsfiddle.net/bobcook/2p9tqzze/"&gt;here&lt;/a&gt;. It's just that it is insanely complicated: first you need to parse the SVG and its paths. Then you would need to map the commands of the svg path to a single shape. Implementing that will surely make your head spin.&lt;/p&gt;

&lt;p&gt;So why doesn't P5 support it? Doing a deepdive into P5's code and you will find that P5 seems to struggle's with the arc shape, under the hood, they are resorting to using bezier curves to emulate drawing an arc.&lt;br&gt;
A very peculiar way of going about it, especially since the Canvas API &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc"&gt;supports&lt;/a&gt; it out of the box. Now P5 uses Canvas by default for its rendering but, similar to PhaserJS, it also supports WebGL too. So I'm assuming it's hard to unify them both for Canvas and WebGL in one framework.&lt;/p&gt;
&lt;h2&gt;
  
  
  The eureka moment.
&lt;/h2&gt;

&lt;p&gt;Interestingly enough, P5 &lt;a href="https://p5js.org/reference/#/p5/drawingContext"&gt;allows&lt;/a&gt; for referring to the Canvas directly. &lt;/p&gt;

&lt;p&gt;And HTML Canvas support loading in a entire SVG path by just providing it to Path2D constructor. That is really not complicated at all, take a look at this:&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;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&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;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;"&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;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Path2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M10 10 h 80 v 80 h -80 Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It has to be said: going down this route will prevent any chance of utilizing WebGL features later on. Fortunately, programming GL shaders is way past what I'm usually trying to do. So if settling for Canvas sounds good, let's proceed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting the SVG paths.
&lt;/h2&gt;

&lt;p&gt;First we need to create SVG's. I used inkscape and opted to shape everything like a circle. That's not only because I wanted to show off the ability to draw arcs in paths, it's also because collision detection with circles is easy as π.&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="nf"&gt;checkCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gameObject&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;dist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;p5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gameObject&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="k"&gt;this&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mag&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;gameObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handleCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gameObject&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;P5 does have a &lt;a href="https://github.com/bmoren/p5.collide2D"&gt;library&lt;/a&gt; for that very purpose but lets not bother with any of that right now.&lt;/p&gt;

&lt;p&gt;A clever way to access the SVG is to just include it in the DOM. So simply pasting them in the HTML document will do. Because were not interested in showing them outside of the canvas, use the following CSS to hide them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;P5 comes with the 'select' utility functions to query the DOM, in the setup function:&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="nf"&gt;getPathsAndColors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;svgElements&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;svgElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fill&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;span class="c1"&gt;//... in global setup function.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#svgElement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;elt&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;svgAsteroid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#asteroid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;elt&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;asteroidShapes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getPathsAndColors&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;svgAsteroid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&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;craftShapes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getPathsAndColors&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Note that although we could destructure the path elements from the elements children property; it is not an array but an iterable object. Using the &lt;code&gt;Array.from&lt;/code&gt; method or spread syntax you can still pass it to a function like getPathsAndColors that expects an array and will map the elements.&lt;/p&gt;

&lt;p&gt;Now all we need to do is render the paths, first we have to get the canvas context. Make sure this happens in the global Draw function every sketch will have:&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;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;drawingContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then pass it to wherever the drawing takes place.&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="nf"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...rotation and scaling logic&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shapes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shape&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;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Path2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&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;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

   &lt;span class="c1"&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 actually all there is to it, if you just wanted to display an SVG path, but what about scaling, rotating and positioning it?&lt;/p&gt;

&lt;p&gt;For this canvas has another nifty feature up it's sleeve: the transformation matrix. It basically allows for scaling and rotating all of the shapes together, without having to calculate all the individual coordinates separately.&lt;/p&gt;

&lt;p&gt;Canvas has several methods that apply to the transformation matrix, there is rotate, translate, scale. &lt;br&gt;
But you can also do all of them together in one go by using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setTransform"&gt;setTransform&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Seriously, how cool is that?&lt;/p&gt;

&lt;p&gt;So first we calculate the scale that is needed. In this case we are scaling down, but unlike raster based graphics you can use any scale without losing image quality. To calculate the scale we need first to know the measurements that were used in the SVG. There usually is a viewBox property present, otherwise 1:1 is assumed. It has 4 values, the first 2 are basically offset values, but the latter indicate width and height. By taking those values in the constructor of the SVGPath class and combining them with the size that is desired, you then have the values that are use full for scaling with the transformation matrix.&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;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;minX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;minY&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;width&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course all the objects in the example could be heading in any direction, so for that we need to rotate the paths.&lt;br&gt;
By first calculating the cos and sin values from the known angle, then multiplying those with the previously mentioned scale variables, rotation can be achieved.&lt;br&gt;
Lastly, to position the object you can simply put the x and y position as the last two parameters to display the object at that location.&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;const&lt;/span&gt; &lt;span class="nx"&gt;cos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&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;sin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&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;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createVector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&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;offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createVector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&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;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTransform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleX&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleX&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleY&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleY&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;p&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;p&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;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&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;pos&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you may notice there is an extra translation step in the end. Also there is a lot of Vector magic going on, this is because the rotation origin, the center around where the rotation occurs, is located in the far left corner of the object that is being drawn.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg312d20t49qt5e9isd90.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg312d20t49qt5e9isd90.png" alt="The rotated shape, with origin indicated" width="250" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It needs to be offset after the rotation is done in order to move the rotation origin to the center. &lt;/p&gt;

&lt;p&gt;Perhaps this could also be done in one step. Please do let me know in the comments if you figure it out.&lt;/p&gt;

&lt;p&gt;The last thing is always to reset the transformation matrix once we are done with all the shapes that are part of the whole object.&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="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTransform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;span class="mi"&gt;1&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;p&gt;That way we prevent all the transformations getting applied to whatever needs to be rendered next.&lt;/p&gt;

&lt;p&gt;And that is basically all there is too it. The shapes that P5 provides can still be used, but I would like to note that you have to be very careful using canvas context to set color as it can mess things up quite a bit if you plan on drawing with P5 later on. It is better to use P5's fill method at all times. &lt;br&gt;
The same goes for starting a shape with P5's &lt;a href="https://p5js.org/reference/#/p5/beginShape"&gt;beginShape&lt;/a&gt; and then trying to use Canvas rendering context methods like arcTo to finish the path started by P5.&lt;/p&gt;

&lt;p&gt;Lastly, before I forget: Big shout out to &lt;a href="https://www.youtube.com/@redhen"&gt;Redhen&lt;/a&gt;. His tutorial on creating a snooker simulation helped me out a lot with the physics that were used. Really interesting stuff that is definitely worth checking out.&lt;/p&gt;

</description>
      <category>p5</category>
      <category>svg</category>
      <category>javascript</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Using VIM macro's in favor of migration scripts.</title>
      <dc:creator>Hendrik Ras</dc:creator>
      <pubDate>Sat, 11 Feb 2023 16:18:14 +0000</pubDate>
      <link>https://dev.to/hendrikras/using-vim-macros-in-favor-of-migration-scripts-2p5i</link>
      <guid>https://dev.to/hendrikras/using-vim-macros-in-favor-of-migration-scripts-2p5i</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0u8cgq1k74zsyjith2l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0u8cgq1k74zsyjith2l.gif" alt="Image description" width="636" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Once, the company I worked for had refactored its entire system with a new architecture and was looking for a way to import its legacy data into it.&lt;/p&gt;

&lt;p&gt;When migrating data from one system to to another, you may find yourself in the need for mapping data structures. This is true especially when dealing with API's. Even when the data format is the same. The structure could be completely different.&lt;/p&gt;

&lt;p&gt;Writing migration scripts can be cumbersome, but what if.. &lt;em&gt;you wouldn't need to write any code at all!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When converting text data formats, such as CSV or JSON, Have you considered using nothing more than a Text Editor? There are many great text editors out there that can perform simple repeating task for you. There are many tools out there that support macros', But if you can be bothered with a bit of a learning curve, few compare to the power that VIM brings to the table imho.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR;
&lt;/h2&gt;

&lt;p&gt;Consider the following JSON structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
     “time”: 1409522400000,
  },
...

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

&lt;/div&gt;



&lt;p&gt;So this is basicly a JSON object that includes an array of objects.&lt;/p&gt;

&lt;p&gt;Now to import this kind of data into the new system, the JSON needs to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
     “t”:” 2015-01-25T07:00:00″
  },
...
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mockdata used for this article can be found &lt;a href="https://gist.github.com/hendrikras/22c17c4b24c685859d6408ef5c66c7d4" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Imagine 24 of these objects, as there are hours in a day. Then take a year or so of data and you will no doubt understand the need for this to be automated.&lt;/p&gt;

&lt;p&gt;In the first excerpt you may notice the dates as a timestamp (nr. of milliseconds from 1st of jan 1970) while the second is formatted in the more readable ISO date.&lt;/p&gt;

&lt;p&gt;So now we find ourselves in need of a way to automatically convert many lines of JSON from one format to the other calculating a timestamp into a date in every step of the way.&lt;/p&gt;

&lt;p&gt;What makes VIM great is that it comes with some basic internal programming functions, including the &lt;strong&gt;strftime&lt;/strong&gt; function.&lt;/p&gt;

&lt;p&gt;Try entering the command &lt;strong&gt;:help functions&lt;/strong&gt; in the command mode of VIM to see them all Strftime’s origins are in the C programming language. Its used for formatting timestamps into date formats, exactly what we are looking for.&lt;/p&gt;

&lt;p&gt;As arguments strftime takes a date formatting string and a timestamp. By entering “man strftime” in a terminal, the &lt;a href="https://man7.org/linux/man-pages/man3/strftime.3.html" rel="noopener noreferrer"&gt;documentation &lt;/a&gt;for the c implementation reveals that the formatting string &lt;strong&gt;“%FT%T”&lt;/strong&gt; will output the desired notation in this case. Try executing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;:echo strftime("%FT%T",0)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;VIM will now neatly output the first of jan 1970 in the desired format: 1970-01-01T01:00:00&lt;/p&gt;

&lt;h2&gt;
  
  
  Macros
&lt;/h2&gt;

&lt;p&gt;VIM allows you to record the editing you do on line(s) and repeat these steps. There are many great examples out there on how this feature can save you a ton of work. In this case we have repeating structure of data that we would like to convert into another representation of that data. VIM Macro’s are perfect for such tasks.&lt;/p&gt;

&lt;p&gt;Just hit the ‘q’ key to start recording, followed by any key to bind the recording to that key. Hit ‘q’ again to stop recording. You can then execute the recording by hitting the ‘@’ key followed by the key used to store the recording. Then use “@@” to use the last recording or “@” and the key of your macro of choice to execute it.&lt;/p&gt;

&lt;p&gt;At this point we could go in depth into the basics of VIM, explaining how to navigate to words in VIM and setting it into edit mode. But that's not really in scope of this article and others have covered &lt;a href="https://opensource.com/article/19/3/getting-started-vim" rel="noopener noreferrer"&gt;this&lt;/a&gt; so much better than I ever could. &lt;/p&gt;

&lt;p&gt;Skipping all that for now, to convert the "time" string to "t", we could enter commands keys in VIM that would look something like this in a row "j j w l dw". And that might seem weird if you are not used to VIM. But for now, lets pretend that was the easy part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Registers
&lt;/h2&gt;

&lt;p&gt;Every time a line or word in VIM gets removed or yanked, it can be pasted later using “p”. This is done because the removed selection is being kept in a buffer, also called a register.&lt;/p&gt;

&lt;p&gt;VIM keeps internal registers for a lot of things, including the outcome of its internal functions such as strftime. The contents of these registers can actually be used as part of VIM commands. That makes them very useful.&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;help:registers&lt;/strong&gt; in vim to learn more.&lt;/p&gt;

&lt;p&gt;What is of interest in this case is that deleted and yanked texts are stored in the unnamed register:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;""&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(yes, just the quotes), or:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"0&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To get the contents from the the unnamed register in the command line, open the command line by pressing “:”  followed by pressing the “CTRL” and “r” keys at the same time.&lt;/p&gt;

&lt;p&gt;A quote character will appear in the command line. By entering the “ character or “0” the previously deleted word will appear.&lt;/p&gt;

&lt;p&gt;For more detailed information insert &lt;strong&gt;:help i_ctrl-r&lt;/strong&gt; in VIM. This trick will enable the strftime command to use the deleted timestamp as part of its input.&lt;/p&gt;

&lt;p&gt;When editing text in insert mode of VIM, the same key combination will work to paste a register value. A quote character will then appear at the position where you would like to paste the value inside the document.&lt;/p&gt;

&lt;p&gt;However strftime’s output will be stored in something called an expression (“=”) register.  VIM will first prompt for an expression to be entered from the command line before you can paste that register.&lt;/p&gt;

&lt;p&gt;By deleting the timestamp in the file and use the unnamed register as input for strftime, then the outcome, from the expression register, can be inserted to the file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;delete the timestamp by using a command sequence like “dw”&lt;/li&gt;
&lt;li&gt;enter edit mode by pressing "i" or "a"&lt;/li&gt;
&lt;li&gt;then holding “ctrl” and “r”, followed by “=”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;the command line will open starting with an “=”&lt;/p&gt;

&lt;p&gt;by entering:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;strftime("%FT%T",&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;followed by holding “ctrl”and “r” then “0”&lt;/p&gt;

&lt;p&gt;the timestamp is pasted into the command line. And the function can be ended by entering &lt;strong&gt;“)”&lt;/strong&gt; followed by hitting the enter key, the timestamp is now replaced with a date notation. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;[edit] last time I tried this on my Mac, I had to add "/1000" before closing the parentheses to prevent encountering a year 2038 problem, where a 32-bit signed integer Unix timestamp will overflow and become negative. [edit]&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;Performing these steps while still recording a macro, enables to repeat these steps converting all JSON objects in the file into the new format. Just navigate to the next opening bracket of the following object and stop recording. Then enter ‘@@’ to convert the next object in the list.&lt;/p&gt;

&lt;p&gt;But entering a command for each object to be converted is repetitive work on its own, VIM can handle that as well. You can use macros within macros. So its not that hard to run one macro to convert the whole file. when the length of the file is known by running the function &lt;strong&gt;=line("$")&lt;/strong&gt; (:help line) Its easy to calculate how many JSON objects are to be converted.&lt;/p&gt;

&lt;p&gt;What made this case easier is that the original JSON objects was exactly 10 lines in length (it was simplified in the example). So after the file is stripped to be just the list of objects and is a 1000 lines long a command like ‘100@w’ can be run, if the macro to convert the object was bound to the “w” key.&lt;/p&gt;

&lt;p&gt;But why do any work at all? If the line function will produce the number of lines, that value can be used to calculate the amount of times a macro is to be run. All that is needed now is a way to have vim run the value of line(“$”) times the macro.&lt;/p&gt;

&lt;h2&gt;
  
  
  normal
&lt;/h2&gt;

&lt;p&gt;Whenever in command line mode wanting to write a command out, and execute it as if it were in normal mode, use the normal command. You guessed it, just type&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;:help normal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;in the command line and learn all about it.&lt;/p&gt;

&lt;p&gt;So by typing “=” in the command line, VIM will prompt for an expression to be entered, in this case line(“$”)/10 follow this by the :normal command and, in this case, the @W will result in the macro being repeated by a tenth of the number of lines&lt;/p&gt;

&lt;h2&gt;
  
  
  Storing macros
&lt;/h2&gt;

&lt;p&gt;It’s quite annoying that VIM does not store these registers by default. After exiting VIM, your macro’s are gone. However, here is a little trick to get around that anyway.&lt;/p&gt;

&lt;p&gt;Earlier on I explained a bit about ‘binding’ macro’s to keys. What actually happens here is that after the ‘q’ key is hit in normal mode, whatever is typed next gets stored in the register corresponding to that key.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;use :registers to find out how your macro’s look like&lt;/li&gt;
&lt;li&gt;then open the hidden vimrc file, if none is present create one in VIMS home directory&lt;/li&gt;
&lt;li&gt;for POSIX (MAC, Linux) systems: &lt;strong&gt;~/.vimrc&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;use the “let” command, this allows a register to be set to a particular value.&lt;/li&gt;
&lt;li&gt;in this case the lines to add look something like.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let @w = 'jddldwiv^[wwi"^[A&amp;lt;80&amp;gt;kb",^[jdddddddwdwdwdwi"t": "^["=strftime("%FT%T",^R"&amp;lt;80&amp;gt;kb&amp;lt;80&amp;gt;kb&amp;lt;80&amp;gt;kb)^Mpa"^[lxjddddj’

let @e = '"=line('$')/10^M:normal ^R=^M@w^MdGGo]^[ggO[^['

let @r = '3dd@e^[:w^M'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By opening the file to convert in VIM the macro’s should be preloaded in the registers. In this case Executing “@r” will convert the entire file.&lt;/p&gt;

</description>
      <category>python</category>
      <category>swift</category>
      <category>machinelearning</category>
      <category>ai</category>
    </item>
    <item>
      <title>Airconsole for free</title>
      <dc:creator>Hendrik Ras</dc:creator>
      <pubDate>Sun, 12 Apr 2020 13:43:55 +0000</pubDate>
      <link>https://dev.to/hendrikras/airconsole-for-free-87l</link>
      <guid>https://dev.to/hendrikras/airconsole-for-free-87l</guid>
      <description>&lt;p&gt;Airconsole is a pretty neat app that can turn any screen into a gaming console for mainly old arcade games.&lt;/p&gt;

&lt;p&gt;I like it because there are so few gaming concepts out there that sport split screen multiplayer like them old days.&lt;/p&gt;

&lt;p&gt;Starting today its free for two weeks. So I guess that's how Ill be spending easter.&lt;/p&gt;

&lt;p&gt;Happy quarantine. Stay safe people.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdzalzpnfpkex20ixbq3g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdzalzpnfpkex20ixbq3g.jpg" alt="Alt Text" width="512" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>airconsole</category>
    </item>
  </channel>
</rss>
