<?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: Aleksey Litvinov</title>
    <description>The latest articles on DEV Community by Aleksey Litvinov (@myjsalterego).</description>
    <link>https://dev.to/myjsalterego</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%2F220851%2F0f90ef3f-2f07-4528-bef2-1e548b012f38.png</url>
      <title>DEV Community: Aleksey Litvinov</title>
      <link>https://dev.to/myjsalterego</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/myjsalterego"/>
    <language>en</language>
    <item>
      <title>Spirit Hunter - Retrospective</title>
      <dc:creator>Aleksey Litvinov</dc:creator>
      <pubDate>Sun, 06 Oct 2024 16:39:29 +0000</pubDate>
      <link>https://dev.to/myjsalterego/spirit-hunter-post-mortem-2np8</link>
      <guid>https://dev.to/myjsalterego/spirit-hunter-post-mortem-2np8</guid>
      <description>&lt;p&gt;Hello! This year I participated in &lt;a href="https://js13kgames.com/2024/" rel="noopener noreferrer"&gt;js13k games&lt;/a&gt; game jam for the second time and I’d like to share my experience and learnings. &lt;/p&gt;

&lt;p&gt;This year, my entry was &lt;a href="https://js13kgames.com/2024/games/spirit-hunter" rel="noopener noreferrer"&gt;Spirit Hunter&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Competition
&lt;/h2&gt;

&lt;p&gt;Is happening every year. In nutshell you need to create a browser game, which source code fits into 13kb archive and does not rely on external sources. Moreover, each year has a special theme and your game needs to match it somehow.&lt;/p&gt;

&lt;p&gt;As you may see, apart from making a game, the competition also challenges your technical skills with a size limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparation
&lt;/h2&gt;

&lt;p&gt;Learning from the last year I realised that having robust pipeline to test archive size with a type checker is crucial for development and decided to prepare one. There are many boilerplates available (&lt;a href="https://js13kgames.com/resources#boilerplates" rel="noopener noreferrer"&gt;https://js13kgames.com/resources#boilerplates&lt;/a&gt;), so you do not need to create one yourself. However, I wanted to have &lt;a href="https://flow.org" rel="noopener noreferrer"&gt;flowtype support&lt;/a&gt;, so created one for myself.&lt;/p&gt;

&lt;p&gt;If you follow the same path, you may want to check &lt;a href="https://www.npmjs.com/package/roadroller" rel="noopener noreferrer"&gt;roadroller&lt;/a&gt; for additional compression and &lt;a href="https://www.npmjs.com/package/ect-bin" rel="noopener noreferrer"&gt;ect-bin&lt;/a&gt; for zipping build artefacts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Design
&lt;/h2&gt;

&lt;p&gt;Early this year, I did game development with &lt;a href="https://love2d.org" rel="noopener noreferrer"&gt;Love2D engine&lt;/a&gt; (relies on Lua language) and was inspired by its approach, so decided to make something similar myself for the competition.&lt;/p&gt;

&lt;p&gt;I implemented &lt;a href="https://gameprogrammingpatterns.com/game-loop.html#play-catch-up" rel="noopener noreferrer"&gt;game loop pattern&lt;/a&gt; on top of the canvas with throttling to have 60 fps rendering and created helpers for drawing primitives and images. For interaction I created two hooks: update (for data management) and render (for display). This way I managed to get a very tiny engine saving space for the game.&lt;br&gt;
Note: if you want to go this way, keep in mind that rendering and positioning text might be challenging, so you may want to pivot towards simple approaches.&lt;/p&gt;

&lt;p&gt;For the game itself, to handle the logic I decided to try &lt;a href="https://gameprogrammingpatterns.com/state.html" rel="noopener noreferrer"&gt;State Machine&lt;/a&gt; and State Stack patterns. Those are very helpful for the screen management (for example, each screen — particular state) and can be used more granular. For example, I used state machines to handle character animation, interaction and player control. My fear was that it will consume a lot of space, however, on practice it itself showed very well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Graphics &amp;amp; Gameplay
&lt;/h2&gt;

&lt;p&gt;Initially, I wanted to make a Vampire Survivors and Legend of Zelda variation, but in ghostbusters settings with exorcism. While I was thinking on a gameplay and characters, I realised that I’ll need suitable assets to make the right impression. I’m not artist myself, so I ended up checking &lt;a href="https://kenney.nl" rel="noopener noreferrer"&gt;https://kenney.nl&lt;/a&gt; and &lt;a href="https://itch.io/game-assets/free" rel="noopener noreferrer"&gt;https://itch.io/game-assets/free&lt;/a&gt; for something suitable. Unfortunately, this step was a blocker for me and I spend couple of days on resolving my internal conflict. In the end, I decided to pick something looking suitable and adjust my expectations.&lt;/p&gt;

&lt;p&gt;As a learning, I’d say it is better to start working with something ready rather than spend time on resolving high expectations, since the time for the jam is limited.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sounds &amp;amp; Music
&lt;/h2&gt;

&lt;p&gt;Last year I failed to add sound and music to my game, so decided to pick one suggested libraries from the &lt;a href="https://js13kgames.com/resources#sound-and-music" rel="noopener noreferrer"&gt;resources&lt;/a&gt;. I ended up with &lt;a href="https://github.com/mneubrand/jsfxr" rel="noopener noreferrer"&gt;jsfxr&lt;/a&gt; for sound generation and &lt;a href="https://keithclark.github.io/ZzFXM/" rel="noopener noreferrer"&gt;zzfxm&lt;/a&gt; for the music. First one has a UI to generate custom sounds and second one — was helpful to provide some examples. Unfortunately, this step took roughly 6kb from my game, which is huge! &lt;/p&gt;

&lt;p&gt;Investigation showed, that &lt;strong&gt;jsfxr&lt;/strong&gt; commits 5kb. Moreover, it is not tree-shakable and comes with a sound generator, which is not necessary for the final game. Doing some optimization helped to save 1.8kb. However, later I realised that &lt;strong&gt;jsfxr&lt;/strong&gt; is not necessary at all, since there is a similar sound generator available for &lt;strong&gt;zzfx&lt;/strong&gt; (which is a part of &lt;strong&gt;zzfxm&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;Conclusion, go for &lt;strong&gt;zzfxm&lt;/strong&gt; and use &lt;a href="https://killedbyapixel.github.io/ZzFX/" rel="noopener noreferrer"&gt;https://killedbyapixel.github.io/ZzFX/&lt;/a&gt; to generate sounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Touches
&lt;/h2&gt;

&lt;p&gt;When I was adopting my game for mobile, I decided to make public version on GitHub pages (so it will be easier to test). This step helped me to uncover some issues with asset paths in the final archive.&lt;/p&gt;

&lt;p&gt;Another interesting observation was about &lt;strong&gt;.DS_Store&lt;/strong&gt; file. One was located in a &lt;strong&gt;public&lt;/strong&gt; folder with other assets and &lt;a href="https://vite.dev/guide/assets.html#the-public-directory" rel="noopener noreferrer"&gt;vitejs&lt;/a&gt; was packing it, consuming extra 0.2kb.&lt;/p&gt;

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

&lt;p&gt;My final version was about 12.7kb. Here is an approximate breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3.9kb graphical assets&lt;/li&gt;
&lt;li&gt;2.1kb engine&lt;/li&gt;
&lt;li&gt;0.9kb zzfxm&lt;/li&gt;
&lt;li&gt;0.5kb state machine / stack&lt;/li&gt;
&lt;li&gt;0.4kb entity base class&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest 4.9kb for the game logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Words
&lt;/h2&gt;

&lt;p&gt;The competition was fun and big thanks to Andrzej Mazur, to the team and judges for organising it!&lt;/p&gt;

</description>
      <category>js13k</category>
      <category>js13kgames</category>
    </item>
  </channel>
</rss>
