<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Procedural-Generation on despatches</title><link>https://icle.es/tags/procedural-generation/</link><description>Recent content in Procedural-Generation on despatches</description><generator>Hugo</generator><language>en</language><lastBuildDate>Fri, 06 Feb 2026 14:15:43 +0000</lastBuildDate><atom:link href="https://icle.es/tags/procedural-generation/index.xml" rel="self" type="application/rss+xml"/><item><title>Procedural Asteroid Field Generation</title><link>https://icle.es/2025/05/10/asteroid-field/</link><pubDate>Sat, 10 May 2025 10:07:08 +0000</pubDate><guid>https://icle.es/2025/05/10/asteroid-field/</guid><description>&lt;p>In this post, I am going to cover procedural asteroid field generation. At a
high level, I wanted:&lt;/p>
&lt;ul>
&lt;li>An asteroid field that feels infinite&lt;/li>
&lt;li>Natural-looking distribution and density&lt;/li>
&lt;li>A safe starting area for the player&lt;/li>
&lt;/ul>
&lt;h2 id="spawning-asteroids">Spawning Asteroids&lt;/h2>
&lt;p>I explored strategies for spawning multiple asteroids on screen without overlaps
and avoiding the player’s starting zone. Initially, I considered a brute-force
collision check for each spawn candidate, but quickly realized it wouldn’t scale
well with many asteroids.&lt;/p>
&lt;p>I decided to split the screen into a grid. If the maximum radius of an asteroid
is &lt;code>r&lt;/code>, then each grid would be &lt;code>2r x 2r&lt;/code>, and would be able to accommodate
asteroids at their full size. The asteroid size is determined randomly, with a
minimum size. It also offsets the center of the x by a random amount, up to a
maximum of &lt;code>r&lt;/code>.&lt;/p></description><content:encoded><![CDATA[<p>In this post, I am going to cover procedural asteroid field generation. At a
high level, I wanted:</p>
<ul>
<li>An asteroid field that feels infinite</li>
<li>Natural-looking distribution and density</li>
<li>A safe starting area for the player</li>
</ul>
<h2 id="spawning-asteroids">Spawning Asteroids</h2>
<p>I explored strategies for spawning multiple asteroids on screen without overlaps
and avoiding the player’s starting zone. Initially, I considered a brute-force
collision check for each spawn candidate, but quickly realized it wouldn’t scale
well with many asteroids.</p>
<p>I decided to split the screen into a grid. If the maximum radius of an asteroid
is <code>r</code>, then each grid would be <code>2r x 2r</code>, and would be able to accommodate
asteroids at their full size. The asteroid size is determined randomly, with a
minimum size. It also offsets the center of the x by a random amount, up to a
maximum of <code>r</code>.</p>
<p>
  <figure>
    <img src="/assets/2025/05/asteroid-map.png" alt="The grid visualised" class="figcaption-img">
    <figcaption>The asteroid grid</figcaption>
  </figure>

</p>
<p>In theory, this means that if two adjacent cells spawn the full size asteroid
and offset in the &ldquo;wrong&rdquo; direction, they could start off overlapping. I&rsquo;ve not
seen this happen yet, likely because the full size asteroids are not that
common.</p>
<p>The grid has an additional offset in the x axis for each row. With this offset,
even if every asteroid was placed at the x center of each grid, they would not
look uniform.</p>
<p>Finally, for each grid cell, there is some further randomisation that determines
whether the asteroid will get spawned at all.</p>
<p>In hindsight - there might be more randomisation than we need. It works well
though.</p>
<p>The asteroids are also given a low starting velocity, both linearly and
rotationally.</p>
<p>Even if asteroids do overlap on spawn, the physics will correct it through the
collision detection.</p>
<h2 id="spawning-the-ship">Spawning the Ship</h2>
<p>The code for this part is a little icky right now. It checks the y position of
the ship and avoids spawning asteroids in any grid cell that overlaps the
starting location.</p>
<p>Of course, this should only matter for the asteroids spawned on the starting
screen. The rest of the asteroids don&rsquo;t need this check. It works just fine
though - for now :)</p>
<h2 id="making-it-infinite">Making it &ldquo;Infinite&rdquo;</h2>
<p>I pondered the best way to make it feel infinite without risk of slowdowns and
issues. A quadtree was an obvious answer. However, it felt too complicated since
I&rsquo;d never written one before, and I was worried about how I would move each
asteroid between each section as it moved. (Spoiler alert: I should have just
used quadtrees, and intend to move to it later.)</p>
<p>In the meantime, I wanted to build something which felt simpler, which was
basically to create chunks of asteroids, with each chunk being a little larger
than the size of the screen.</p>
<p>The system could then, based on the current y position, track just the current,
previous, and next chunks, and process only these asteroids.</p>
<p>When I got it working, it was pretty ok. The main problem I had now was the
asteroids leaving the screen and never coming back.</p>
<p>After I&rsquo;d implemented this, I ended up watching
<a href="https://www.youtube.com/watch?v=OJxEcs0w_kE">Coding Challenge #98: Quadtree</a>,
and boy did I feel silly about being scared about quadtrees. They were promptly
demystified and felt like a much simpler solution than what I have here - so
I&rsquo;ll add that to the list to change.</p>
<h2 id="asteroids-drifting-offscreen">Asteroids Drifting Offscreen</h2>
<p>One of the problems was that the asteroids would drift offscreen. Because I
wasn&rsquo;t updating all the asteroids, they&rsquo;d never come back on to the screen. In
fact, even if I updated <em>all</em> the asteroids, the screen would eventually clear.
I believe this was because there is a lot of offscreen space (mainly on the left
and right of the screen) that the asteroids could fly off to.</p>
<p>I tried various ways of wrapping the asteroids around after they hit a few
hundred pixels past the edge. I didn&rsquo;t want it to look like a wraparound, and
pretending like the screen was about twice the width helped.</p>
<p>However, the problem was now with the asteroids slinking out the bottom of the
screen (and the top too), and there wasn&rsquo;t an easy way to tackle those.</p>
<p>In the end, I ended up
<a href="https://www.youtube.com/watch?v=OAcXnzRNiCY">using an attractor</a>, which I
placed on the center of each chunk.</p>
<p>This worked surprisingly well that I didn&rsquo;t even need the horizontal wraparound.</p>
<p>I had also ended up making the <code>Chunk</code> struct a little heavy, and I ended up
refactoring it. While refactoring, I overoptimized it to only update asteroids
on the screen. This &ldquo;fix&rdquo; meant that asteroids off-screen aren&rsquo;t attracted to
the center of the chunk anymore, and the screen ends up clearing again.
Something to fix later - maybe when I implement the quadtree.</p>
<h2 id="debug-panel">Debug Panel</h2>
<p>There were various points when I was trying to track down issues that I reverted
to my habit of printing stuff out - but that was a nightmare because it was
printing the same thing in each frame.</p>
<p>Eventually, I got into the habit of displaying stuff on screen and drawing
different colours etc. I then wanted a way to see things easier and toggle some
of the debug features. To do this, I needed a GUI.</p>
<p>I looked at <a href="https://github.com/raysan5/raygui">raygui</a>, which looked good but
probably too basic for me. I don&rsquo;t enjoy GUI work and I figured something a
little more fleshed out would help.</p>
<p>I had already looked at <a href="https://github.com/david-vanderson/dvui">dvui</a> before
and it looked like it could be a good candidate.</p>
<p>Integrating it into <em>triangle</em> was pretty straightforward - at least once I
figured out how to add it to <code>build.zig</code>.</p>
<h2 id="next-steps">Next Steps</h2>
<p>Right now, the field feels big enough (around 15 chunks), but not truly
infinite. I&rsquo;m thinking of implementing a circular buffer - say, 8 or 10 chunks -
where old ones are recycled as the player moves forward. If a player backtracks,
most asteroids will have drifted off anyway, and replacements will blend in just
fine.</p>
<p>I’ll probably tackle that - and maybe finally add a quadtree - soon.</p>
<p><strong>Next up:</strong>
<a href="https://icle.es/2025-05-20-crafting-machines.md">crafting systems and how I’m handling material drops and recipes.</a></p>
<h2 id="other-posts">Other posts</h2>
<ul>
<li><a href="https://youtu.be/RXcBDC8Ki1w">Companion vlog for this post</a></li>
<li><a href="https://icle.es/2025-05-08-basic-gameplay.md">Basic Gameplay</a></li>
<li><a href="https://icle.es/2025-05-13-materials.md">Next: Materials &amp; Pickups</a></li>
</ul>]]></content:encoded></item></channel></rss>