<?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: Kapendev</title>
    <description>The latest articles on DEV Community by Kapendev (@kapendev).</description>
    <link>https://dev.to/kapendev</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%2F3285120%2F7c2b2ebc-6c2f-451e-880a-e6d2d62b333d.png</url>
      <title>DEV Community: Kapendev</title>
      <link>https://dev.to/kapendev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kapendev"/>
    <language>en</language>
    <item>
      <title>Parin Game Engine Devlog – October 2025</title>
      <dc:creator>Kapendev</dc:creator>
      <pubDate>Tue, 28 Oct 2025 11:43:08 +0000</pubDate>
      <link>https://dev.to/kapendev/parin-game-engine-devlog-october-2025-5dfi</link>
      <guid>https://dev.to/kapendev/parin-game-engine-devlog-october-2025-5dfi</guid>
      <description>&lt;p&gt;&lt;em&gt;Welcome to the October 2025 devlog for &lt;a href="https://github.com/Kapendev/parin" rel="noopener noreferrer"&gt;Parin&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🫐 Backend Support
&lt;/h2&gt;

&lt;p&gt;A lot of time this month went into adding support for multiple backends. By "backend," I mean the ability to swap the current platform layer, &lt;strong&gt;raylib&lt;/strong&gt;, for a different one. This required some breaking changes to make everything work correctly and pushed Parin toward a more abstract design.&lt;/p&gt;

&lt;p&gt;In practice, this means that every engine resource (&lt;code&gt;Texture&lt;/code&gt;, &lt;code&gt;Font&lt;/code&gt;, &lt;code&gt;Sound&lt;/code&gt;, &lt;code&gt;Viewport&lt;/code&gt;) is now only represented by an ID and the backend is responsible for what is will do with that ID. For example, &lt;code&gt;Viewport&lt;/code&gt; as a structure no longer exists and you have to use something called a &lt;code&gt;ViewportId&lt;/code&gt;. As with every ID before this change, you'll need to use one of the &lt;code&gt;load*&lt;/code&gt; functions to obtain a new ID. A nice side effect of this system is that engine resources are safer to use (no state bugs, etc.) and the Parin API is simpler since there's only one way to do things.&lt;/p&gt;

&lt;p&gt;The main benefit of this change is that Parin will be able to use something like &lt;a href="https://www.libsdl.org/" rel="noopener noreferrer"&gt;SDL&lt;/a&gt;, &lt;a href="https://github.com/ZILtoid1991/pixelperfectengine" rel="noopener noreferrer"&gt;PixelPerfectEngine&lt;/a&gt;,  or even &lt;a href="https://godotengine.org/" rel="noopener noreferrer"&gt;Godot&lt;/a&gt; as a platform layer in the future. In the case of Godot, it would take a lot of work because of how Godot works, but it's definitely possible. The Godot backend is on my "for fun" TODO list.&lt;/p&gt;

&lt;h2&gt;
  
  
  🍵 Deprecation Removal &amp;amp; Changes
&lt;/h2&gt;

&lt;p&gt;Because of the changes mentioned above, I figured it was a good time to remove all the deprecated names and functions that had built up over time for backward compatibility. For example, the alias &lt;code&gt;format&lt;/code&gt; for the &lt;code&gt;fmt&lt;/code&gt; function no longer exists.&lt;/p&gt;

&lt;p&gt;Loading functions also changed a bit. They now support absolute paths and always return a value directly, instead of sometimes wrapping it in an option/maybe type. If an error occurred while loading, then a "null" value is returned. To get more information about what kind of error happened, you can use the &lt;code&gt;lastLoadOrSaveFault&lt;/code&gt; function. This is similar to how Godot handles errors and over time I have come to think it's a perfectly fine way of doing things, at least for game code.&lt;/p&gt;

&lt;p&gt;The next big deprecation removal will come with version &lt;strong&gt;0.2.0&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 No External Dependencies
&lt;/h2&gt;

&lt;p&gt;After thinking about this for a long long long time, I decided it was finally the right moment to vendor every dependency Parin had. This means Parin can now be built simply by cloning the repository. No dependency management through DUB or Git is needed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But why? Don't you like package managers?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is not about liking or disliking package managers. I just prefer simple things. Being able to download Parin and use it right away feels great. Building is simpler, &lt;a href="https://en.wikipedia.org/wiki/Grep" rel="noopener noreferrer"&gt;grepping&lt;/a&gt; is simpler, &lt;a href="https://grok.com/" rel="noopener noreferrer"&gt;grokking&lt;/a&gt; is simpler, ... This change just makes everything nicer overall, for both DUB and no DUB users.&lt;/p&gt;

&lt;p&gt;Don't worry, I'm not about to go on a "unstructured" package-manager rant like &lt;a href="https://www.gingerbill.org/article/2025/09/08/package-managers-are-evil/" rel="noopener noreferrer"&gt;gingerBill&lt;/a&gt; or &lt;a href="https://forum.dlang.org/post/dycuopbvjjqiwkzadnyd@forum.dlang.org" rel="noopener noreferrer"&gt;monkeyyyy&lt;/a&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%2Fto5pbqa2lu8q7xplhimg.png" 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%2Fto5pbqa2lu8q7xplhimg.png" alt="ME IRL" width="436" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🧭 Documentation
&lt;/h2&gt;

&lt;p&gt;I went over some code in &lt;code&gt;math.d&lt;/code&gt;, &lt;code&gt;ascii.d&lt;/code&gt;, and &lt;code&gt;engine.d&lt;/code&gt;, and refactored parts of them. Functions should now follow a more logical order in most places and a lot of code that previously lacked documentation comments now has them. Overall, this should make things much easier to understand.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/Kapendev/parin/blob/main/CHEATSHEET.md" rel="noopener noreferrer"&gt;Parin cheatsheet&lt;/a&gt; also got an update. Its structure changed and now includes the first line of each function's documentation comment, making it easier to rely on it for quick information on how to do things.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌤️ What's Next
&lt;/h2&gt;

&lt;p&gt;Well, no idea. Parin is in a good state right now. Mostly bug-free and provides a nice experience for the types of games I want to make. The thing I'll probably focus on next is Parin UI, the WebAssembly scripts, and maybe shaders. The next Parin devlog will likely take a bit longer to release.&lt;/p&gt;

&lt;p&gt;That's mostly it. If you try Parin out, let me know what you think in the &lt;a href="https://github.com/Kapendev/parin/discussions" rel="noopener noreferrer"&gt;GitHub discussions&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>programming</category>
      <category>godotengine</category>
    </item>
    <item>
      <title>Parin Game Engine Devlog – September 2025</title>
      <dc:creator>Kapendev</dc:creator>
      <pubDate>Thu, 25 Sep 2025 12:20:29 +0000</pubDate>
      <link>https://dev.to/kapendev/parin-game-engine-devlog-september-2025-517o</link>
      <guid>https://dev.to/kapendev/parin-game-engine-devlog-september-2025-517o</guid>
      <description>&lt;p&gt;&lt;em&gt;Welcome to the September 2025 devlog for &lt;a href="https://github.com/Kapendev/parin" rel="noopener noreferrer"&gt;Parin&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎨 New Palettes
&lt;/h2&gt;

&lt;p&gt;This month, 8 predefined color palettes were added. Two are inspired by the Game Boy and NES, while others bring in Linux nerd stuff like Gruvbox.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight d"&gt;&lt;code&gt;&lt;span class="n"&gt;HexPalette&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="n"&gt;gb4&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;HexPalette&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="n"&gt;nes8&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;HexPalette&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="n"&gt;gruvboxDark&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;HexPalette&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="n"&gt;gruvboxLight&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;HexPalette&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="n"&gt;oneDark&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;HexPalette&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="n"&gt;oneLight&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;HexPalette&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="n"&gt;solarizedDark&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;HexPalette&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="n"&gt;solarizedLight&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On top of that, there is now a helper function to parse palettes from a CSV file called &lt;code&gt;csvRowToPalette&lt;/code&gt;. Monkeyyy is happy.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ Drawing Go Brrr
&lt;/h2&gt;

&lt;p&gt;A version called &lt;code&gt;ParinSkipDrawChecks&lt;/code&gt; was added for situations where speed matters more than safety. Invalid draw values will crash your game, so use it only if you know what you are doing.&lt;/p&gt;

&lt;p&gt;This version also disables debug shapes when attempting to draw empty (not loaded) resources. If you are not familiar with debug shapes, here's how they look:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With loaded resources&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%2Fr4525duhj6ogu4hjltpb.png" 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%2Fr4525duhj6ogu4hjltpb.png" alt="Game Yes" width="640" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without loaded resources&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%2F1x2dw7jvbj9dxboj218q.png" 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%2F1x2dw7jvbj9dxboj218q.png" alt="Game No" width="640" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the game &lt;a href="https://kapendev.itch.io/runani" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🗂️ Frame Allocator &amp;amp; Better Containers
&lt;/h2&gt;

&lt;p&gt;The engine now provides a frame allocator for temporary memory. Allocations from it only live for the current frame and are automatically cleared at the end. This is useful for scratch data like strings or small objects created every frame without worrying about freeing them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight d"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;frameMalloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Sz&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Sz&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;frameRealloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Sz&lt;/span&gt; &lt;span class="n"&gt;oldSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Sz&lt;/span&gt; &lt;span class="n"&gt;newSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Sz&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;frameMakeBlank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;frameMake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;frameMakeSliceBlank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;Sz&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;frameMakeSlice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;Sz&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The engine already uses this allocator internally for functions like &lt;code&gt;loadTempText&lt;/code&gt; and &lt;code&gt;prepareTempText&lt;/code&gt;. Alongside this, the built-in containers got more generic in terms of allocation strategy. Previously, they only supported heap allocation. Now they can also be stack-allocated or backed by external memory.&lt;/p&gt;

&lt;p&gt;One practical example is tile map layers in the map module, which now use fixed-sized containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight d"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Fixed-sized container.&lt;/span&gt;
&lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;TileMapLayerData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FixedList&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="kt"&gt;short&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxTileMapLayerCapacity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Fixed-sized container.&lt;/span&gt;
&lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;TileMapLayer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="n"&gt;TileMapLayerData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TileMapLayerData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Dynamic container.&lt;/span&gt;
&lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;TileMapLayers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;TileMapLayer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🧩 Memory Tracking
&lt;/h2&gt;

&lt;p&gt;Parin got a lightweight memory tracking system that can detect leaks or invalid frees in debug builds. By default, leaks will be printed at shutdown only if they are detected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight d"&gt;&lt;code&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isLoggingMemoryTrackingInfo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;setIsLoggingMemoryTrackingInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IStr&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Memory Leaks: 4 (total 699 bytes, 5 ignored)
  1 leak, 20 bytes, source/app.d:24
  1 leak, 53 bytes, source/app.d:31
  2 leak, 32 bytes, source/app.d:123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't strictly a Parin feature. It comes from &lt;a href="https://github.com/Kapendev/joka" rel="noopener noreferrer"&gt;Joka&lt;/a&gt;, the library Parin uses for memory allocations. Anything allocated through Joka is automatically tracked. You can check whether memory tracking is active with &lt;code&gt;static if (isTrackingMemory)&lt;/code&gt;, and if it is, you can inspect the current tracking state via &lt;code&gt;_memoryTrackingState&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;_memoryTrackingState&lt;/code&gt; is thread-local, so each thread has its own separate tracking state. When you look at the state or summary, remember that it's primarily a debug tool. In general, this information is normal in debug builds and doesn't indicate an error.&lt;/p&gt;

&lt;p&gt;Some leaks can be ignored with the &lt;code&gt;ignoreLeak&lt;/code&gt; function like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight d"&gt;&lt;code&gt;&lt;span class="c1"&gt;// struct Game { int hp; int mp; }&lt;/span&gt;
&lt;span class="c1"&gt;// Game* game;&lt;/span&gt;
&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jokaMake&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;ignoreLeak&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This feature might seem simple, but it can provide valuable insight into what's happening with memory. For example, it helped me cut the number of heap allocations in one part of the engine from 19 down to 9.&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 Extras Collection
&lt;/h2&gt;

&lt;p&gt;A new extras collection of optional libraries was added. At the moment, it only includes &lt;a href="https://github.com/Kapendev/parin/blob/main/examples/integrations/microui.d" rel="noopener noreferrer"&gt;microui&lt;/a&gt;, but more may be added over time. This is mostly a batteries included thing and lets internal Parin code use libraries without any dependencies that need to be downloaded.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎚️ Easing
&lt;/h2&gt;

&lt;p&gt;Two new structs were added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Tween&lt;/code&gt;: Eases between two float values&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SmoothToggle&lt;/code&gt;: Handles smooth transitions between two states, usually on/off.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a basic example that creates a basic transition effect with the &lt;code&gt;SmoothToggle&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight d"&gt;&lt;code&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cyan&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SmoothToggle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'q'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isPressed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;smoothstep&lt;/span&gt;&lt;span class="p"&gt;(-&lt;/span&gt;&lt;span class="n"&gt;resolutionHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resolutionHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isAtEnd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toggleSnap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ubyte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;randi&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ubyte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;randi&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ubyte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;randi&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="p"&gt;};&lt;/span&gt;
    &lt;span class="n"&gt;drawRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&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;Both are designed to be small in size, so they can be easily iterated in an animation array, for example. &lt;code&gt;Tween&lt;/code&gt; is 20 bytes and &lt;code&gt;SmoothToggle&lt;/code&gt; is 8 bytes. &lt;code&gt;Tween&lt;/code&gt; also supports vectors through the types &lt;code&gt;Tween2&lt;/code&gt;, &lt;code&gt;Tween3&lt;/code&gt; and &lt;code&gt;Tween4&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🖨️ Faster Formatting &amp;amp; Printing Improvements
&lt;/h2&gt;

&lt;p&gt;Projects should compile faster thanks to a simpler &lt;code&gt;fmt&lt;/code&gt; implementation. The &lt;code&gt;fmt&lt;/code&gt; template, used for string formatting, is now just 8 lines of code and delegates all the work to a non-template function called &lt;code&gt;fmtIntoBufferWithStrs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A new struct called &lt;code&gt;Sep&lt;/code&gt; was also added as a handy separator marker for printing functions. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight d"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Will print: "1 2 3 Go!"&lt;/span&gt;
&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Sep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" "&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;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Go!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows you to easily control separators when printing, which is great for quick debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  🐇 Bunnymark
&lt;/h2&gt;

&lt;p&gt;It's not a classic "bunnymark." More like "wormmark." I put together a quick test to see how well the current physics system works, and the results seem fine. The test runs with 30,000 worms, and each one is a physics object moving around the room. It's close to 60 FPS on a &lt;strong&gt;Ryzen 3 2200G&lt;/strong&gt; with &lt;strong&gt;16 GB of memory&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%2F0dso31dp4px00gti3mvy.png" 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%2F0dso31dp4px00gti3mvy.png" alt="Game Screenshot" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the code for the game &lt;a href="https://github.com/Kapendev/worms" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Just change the &lt;code&gt;appendWorm&lt;/code&gt; function.&lt;/p&gt;

&lt;h2&gt;
  
  
  📍 Fin
&lt;/h2&gt;

&lt;p&gt;That's mostly it. If you try Parin out, let me know what you think in the &lt;a href="https://github.com/Kapendev/parin/discussions" rel="noopener noreferrer"&gt;GitHub discussions&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Please read my rant.</title>
      <dc:creator>Kapendev</dc:creator>
      <pubDate>Tue, 02 Sep 2025 12:02:42 +0000</pubDate>
      <link>https://dev.to/kapendev/please-read-my-rant-1k1p</link>
      <guid>https://dev.to/kapendev/please-read-my-rant-1k1p</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/kapendev/raylib-is-great-for-small-games-someone-said-again-388l" class="crayons-story__hidden-navigation-link"&gt;Raylib Is Great for Small Games, Someone Said Again...&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/kapendev" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3285120%2F7c2b2ebc-6c2f-451e-880a-e6d2d62b333d.png" alt="kapendev profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/kapendev" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Kapendev
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Kapendev
                
              
              &lt;div id="story-author-preview-content-2813645" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/kapendev" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3285120%2F7c2b2ebc-6c2f-451e-880a-e6d2d62b333d.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Kapendev&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/kapendev/raylib-is-great-for-small-games-someone-said-again-388l" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 1 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/kapendev/raylib-is-great-for-small-games-someone-said-again-388l" id="article-link-2813645"&gt;
          Raylib Is Great for Small Games, Someone Said Again...
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gamedev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gamedev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/raylib"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;raylib&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/odinlang"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;odinlang&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/kapendev/raylib-is-great-for-small-games-someone-said-again-388l" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;6&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/kapendev/raylib-is-great-for-small-games-someone-said-again-388l#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>gamedev</category>
      <category>programming</category>
      <category>raylib</category>
      <category>odinlang</category>
    </item>
    <item>
      <title>Raylib Is Great for Small Games, Someone Said Again...</title>
      <dc:creator>Kapendev</dc:creator>
      <pubDate>Mon, 01 Sep 2025 23:57:13 +0000</pubDate>
      <link>https://dev.to/kapendev/raylib-is-great-for-small-games-someone-said-again-388l</link>
      <guid>https://dev.to/kapendev/raylib-is-great-for-small-games-someone-said-again-388l</guid>
      <description>&lt;p&gt;I keep hearing this line, mostly on the Odin Discord server. What is that? It's a bunch of nerds who like a programming language called Odin.&lt;/p&gt;

&lt;p&gt;Now, why am I even writing a blog about this stupid line that makes no sense anyway? Good question. The answer is: because someone has to tell nerds when they are being nerds, so they stop nerding out so hard.&lt;/p&gt;

&lt;p&gt;This is me being nice, actually. I'm just trying to make the Odin Discord server a better place.&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%2Fmedia1.tenor.com%2Fm%2F5KrDexj2ok8AAAAC%2Ftelevision-tv-shows.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%2Fmedia1.tenor.com%2Fm%2F5KrDexj2ok8AAAAC%2Ftelevision-tv-shows.gif" width="498" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Line
&lt;/h2&gt;

&lt;p&gt;Every time someone says it, it sounds like they are giving raylib a compliment. But it's not really a compliment, is it? Maybe sometimes, but not in the Odin server. Remember, we are dealing with evil nerds here. It's more like a backhanded "good job, I guess."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But it is great for small games. What's wrong with saying that? - gingereebill&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem isn't that raylib can't be used for small games. Of course it can. It's actually really easy to make games with it. The problem is the way people say it as if that's all it's good for. Like raylib is just a toy library you will eventually grow out of once you are ready for the "real stuff."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To be clear, "simple games" isn't an insult, to the games or to raylib. - barizodin&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yeah, I'm used to that same line from game engine people. It's just a nice thing to say.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Of course you can use it for non-learning and slightly less simple games. But it was created for learning - karlzylonski&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And? That's irrelevant to what raylib actually is. It has a lot of solid, well-written code. The creator can use it however he wants, but that doesn't limit anyone else. Lua, for example, was created to be a nice config file language, and look how it's used now. Also, thanks for the "slightly less simple games" upgrade. I get it, not an insult, just like the line above.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You are just complaining and trying to have strong opinions. - karlzylonski&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bro, who is having strong opinions here? Also why is this blog becoming like a Discord chat?&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%2Fmedia1.tenor.com%2Fm%2FaqO17ONw1E4AAAAC%2Fdoctor-who.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%2Fmedia1.tenor.com%2Fm%2FaqO17ONw1E4AAAAC%2Fdoctor-who.gif" width="498" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Strong Opinions
&lt;/h2&gt;

&lt;p&gt;The Odin server has more graphics devs, so it makes sense they look at anything even slightly high-level as "simple" or "just for learning." That's the culture. But that context doesn't make the line true. It just means you are hearing it from people who would rather make their own "better" abstractions. And that's fine. I'm waiting to see how Gordon2D (a library by gingereebill) and Karl2D (a library by karlzylonski) will evolve.&lt;/p&gt;

&lt;p&gt;These people also assume raylib will always be used "as is." But that's not the case. If you need something different, you can just fork it and make the changes you want. There's really no serious problem you can't solve with a custom fork for your project.&lt;/p&gt;

&lt;p&gt;By the way, just search "OOP" in the Odin Discord server. It's currently mentioned 2,716 times and counting. For comparison, the D Discord server has 1,331 mentions of OOP, and that's a language with OOP support. Odin is one of those no-OOP langs. Strong opinions, huh?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;no, like, raylib is close to the ideal; its got allot of c apis nonsense, but still it is just a list of functions that are well named and has the right kind and ammount of docs - monkyyy&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Me
&lt;/h2&gt;

&lt;p&gt;Anyway, that's enough ranting. For what it's worth, I'm currently using raylib as the base for my own little game engine/framework/library (never cared about the distinction) called Parin. I might switch things up in the future, but right now raylib is perfect for what I need. If you are curious, here's the &lt;a href="//github.com/Kapendev/parin"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Worms Within - A bite-sized escape room game.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kapendev.itch.io/worms-within" rel="noopener noreferrer"&gt;&lt;img alt="Game 1" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.itch.zone%2FaW1hZ2UvMzU4OTk2OC8yMTM5MTYyMC5wbmc%3D%2Foriginal%2FfWBA1L.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;So yeah, raylib works. That's all that matters to me.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>programming</category>
      <category>raylib</category>
      <category>odinlang</category>
    </item>
  </channel>
</rss>
