<div dir="ltr"><div class="" itemprop="text">
<p>Hi,<br></p><p>I am trying to make a basic 2D engine with haskell and the SDL1.2 bindings (for fun, I am just learning).
Ideally the world is to be procedurally generated, chunk by chunk, allowing free exploration.</p>
<p>Right now my chunk is composed of 200*200 tiles which I represent using a type:</p>
<p><span style="font-family:monospace,monospace"><code>Mat [Tile] = Vec.Vector (Vec.Vector [Tile])</code></span></p>
<p>and these functions:</p>
<pre style class=""><code><span class="">fromMat </span><span class="">::</span><span class=""> </span><span class="">[[</span><span class="">a</span><span class="">]]</span><span class=""> </span><span class="">-></span><span class=""> Mat a
fromMat xs </span><span class="">=</span><span class=""> Vec.fromList </span><span class="">[</span><span class="">Vec.fromList xs' </span><span class="">|</span><span class=""> xs' </span><span class=""><-</span><span class=""> xs</span><span class="">]</span><span class="">
</span><span class="">(§)</span><span class=""> </span><span class="">::</span><span class=""> Mat a </span><span class="">-></span><span class=""> </span><span class="">(</span><span class="">Int</span><span class="">,</span><span class=""> Int</span><span class="">)</span><span class=""> </span><span class="">-></span><span class=""> a
v </span><span class="">§</span><span class=""> </span><span class="">(</span><span class="">r</span><span class="">,</span><span class=""> c</span><span class="">)</span><span class=""> </span><span class="">=</span><span class=""> </span><span class="">(</span><span class="">v Vec</span><span class="">.!</span><span class=""> r</span><span class="">)</span><span class=""> Vec</span><span class="">.!</span><span class=""> c</span></code></pre>
<p>I am using cyclic list of tiles in order to allow for sprite animation, and later for dynamic behaviour. </p>
<p>Each frame of the game loop, the program reads the part of the vector
relevant to the current camera position, display the corresponding
tiles and return a new vector in which every of these cyclic lists has
been replaced by it's tail.</p>
<p>Here is the code responsible for this:</p>
<pre style class=""><code><span class="">applyTileMat </span><span class="">::</span><span class=""> Chunk </span><span class="">-></span><span class=""> SDL.Surface </span><span class="">-></span><span class=""> SDL.Surface </span><span class="">-></span><span class=""> IO Chunk
applyTileMat ch src dest </span><span class="">=</span><span class="">
</span><span class="">let</span><span class=""> m </span><span class="">=</span><span class=""> chLand </span><span class="">$!</span><span class=""> ch
</span><span class="">(</span><span class="">x</span><span class="">,</span><span class="">y</span><span class="">)</span><span class=""> </span><span class="">=</span><span class=""> chPos ch
wid </span><span class="">=</span><span class=""> Vec.length </span><span class="">(</span><span class="">m Vec</span><span class="">.!</span><span class=""> </span><span class="">0</span><span class="">)</span><span class=""> </span><span class="">-</span><span class=""> </span><span class="">1</span><span class="">
hei </span><span class="">=</span><span class=""> </span><span class="">(</span><span class="">Vec.length m</span><span class="">)</span><span class=""> </span><span class="">-</span><span class=""> </span><span class="">1</span><span class="">
</span><span class="">(</span><span class="">canW</span><span class="">,</span><span class="">canH</span><span class="">)</span><span class=""> </span><span class="">=</span><span class=""> canvasSize ch </span><span class="">in</span><span class="">
</span><span class="">do</span><span class=""> sequence </span><span class="">$</span><span class=""> </span><span class="">[</span><span class=""> applyTile </span><span class="">(</span><span class="">head </span><span class="">(</span><span class="">m </span><span class="">§</span><span class=""> </span><span class="">(</span><span class="">i</span><span class="">,</span><span class="">j</span><span class="">)))</span><span class=""> </span><span class="">(</span><span class="">32</span><span class="">*(</span><span class="">j</span><span class="">-</span><span class="">x</span><span class="">),</span><span class=""> </span><span class="">32</span><span class="">*(</span><span class="">i</span><span class="">-</span><span class="">y</span><span class="">))</span><span class=""> src dest </span><span class="">|</span><span class=""> i </span><span class=""><-</span><span class=""> </span><span class="">[</span><span class="">y</span><span class="">..(</span><span class="">y</span><span class="">+</span><span class="">canH</span><span class="">)],</span><span class=""> j </span><span class=""><-</span><span class=""> </span><span class="">[</span><span class="">x</span><span class="">..(</span><span class="">x</span><span class="">+</span><span class="">canW</span><span class="">)]]</span><span class="">
m' </span><span class=""><-</span><span class="">sequence </span><span class="">$</span><span class=""> </span><span class="">[</span><span class="">sequence </span><span class="">[(</span><span class="">return </span><span class="">$!</span><span class=""> tail </span><span class="">(</span><span class="">m </span><span class="">§</span><span class=""> </span><span class="">(</span><span class="">i</span><span class="">,</span><span class="">j</span><span class="">)))</span><span class=""> </span><span class="">|</span><span class=""> j </span><span class=""><-</span><span class=""> </span><span class="">[</span><span class="">0</span><span class="">..</span><span class="">wid</span><span class="">]]</span><span class=""> </span><span class="">|</span><span class=""> i </span><span class=""><-</span><span class=""> </span><span class="">[</span><span class="">0</span><span class="">..</span><span class="">hei</span><span class="">]]</span><span class=""> </span><span class="">--weird :P</span><span class="">
return ch </span><span class="">{</span><span class=""> chLand </span><span class="">=</span><span class=""> fromMat m' </span><span class="">}</span></code></pre>
<p>the first sequence does the display part, the second one returns the new vector m'.</p>
<p>At first I was using the following comprehension to get m'</p>
<pre style class=""><code><span class="">let</span><span class=""> </span><span class="">!</span><span class="">m' </span><span class="">=</span><span class=""> </span><span class="">[</span><span class="">id </span><span class="">$!</span><span class=""> </span><span class="">[(</span><span class="">tail </span><span class="">$!</span><span class=""> </span><span class="">(</span><span class="">m </span><span class="">§</span><span class=""> </span><span class="">(</span><span class="">i</span><span class="">,</span><span class="">j</span><span class="">)))</span><span class=""> </span><span class="">|</span><span class=""> j </span><span class=""><-</span><span class=""> </span><span class="">[</span><span class="">0</span><span class="">..</span><span class="">wid</span><span class="">]]</span><span class=""> </span><span class="">|</span><span class=""> i </span><span class=""><-</span><span class=""> </span><span class="">[</span><span class="">0</span><span class="">..</span><span class="">hei</span><span class="">]]</span></code></pre>
<p>but doing so results in ever increasing memory usage. I think it has
to do with lazy evaluation preventing the data to be properly garbage
collected, but I don't really understand why. </p>
<p>In this particular case, it doesn't really mater since I have to look
at the whole vector. But I don't know how I should do if I wanted to
only "update" part of my chunk each frame, thus making a new chunk with
only part of the data from the previous one.</p>
<p>I am probably not using Data.Vector the way it's intended, but it's the simplest data structure I found with O(n) random access.</p>
<p>The whole code is there:
<a href="https://github.com/eniac314/wizzard/blob/master/tiler.hs" rel="nofollow">https://github.com/eniac314/wizzard/blob/master/tiler.hs</a></p>
</div></div>