<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="/rss.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Andrey Listopadov</title>
    <link>https://andreyor.st/categories/gamedev/</link>
    <image>
      <title>Andrey Listopadov</title>
      <link>https://andreyor.st/categories/gamedev/</link>
      <url>https://andreyor.st/categories/gamedev/favicon-64.png</url>
    </image>
    <description>Posts from the 'gamedev' category by Andrey Listopadov</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>Andrey Listopadov 2020-2026 - This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</copyright>
    <lastBuildDate>Fri, 09 Jan 2026 04:11:00 +0300</lastBuildDate>
    <atom:link href="https://andreyor.st/categories/gamedev/feed.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Slopes in AABB collision systems</title>
      <link>https://andreyor.st/posts/2026-01-09-slopes-in-aabb-collision-systems/</link>
      <guid>https://andreyor.st/posts/2026-01-09-slopes-in-aabb-collision-systems/</guid>
      <description>&lt;p&gt;Recently (again, &lt;a href=&#34;https://andreyor.st/posts/2024-09-08-boredom-and-gamedev/&#34;&gt;bored on a vacation&lt;/a&gt;), I started working on a game I&amp;rsquo;ve planned for a long time.
I wasn&amp;rsquo;t satisfied with my &lt;a href=&#34;https://tic80.com/play?cart=3473&#34; target=&#34;_blank&#34;&gt;existing implementations&lt;/a&gt; of a player controller&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, so I started working on a new one.
After a bit of fiddling around, I came to something I&amp;rsquo;m satisfied with, for now, at least, but while working on it, I wanted to add something I haven&amp;rsquo;t done in any of my projects yet - I decided to add slopes to my game.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m no game developer, to be honest, it&amp;rsquo;s not even my hobby, although I enjoy the process to some extent.
Game development offers immediate visual and interactive feedback, unlike many other areas in programming, and I like that.
So, while working on this player controller and figuring out how to implement slopes, I&amp;rsquo;ve searched the web to see if someone already did something similar in a system I&amp;rsquo;m working with, but I didn&amp;rsquo;t manage to find anything.
Maybe I simply wasn&amp;rsquo;t specific enough in my search requests, or didn&amp;rsquo;t search deep enough, and there&amp;rsquo;s actually a guide on how to do that somewhere on the web, I decided to write this post anyway.&lt;/p&gt;
&lt;h2 id=&#34;aabb-collisions&#34;&gt;AABB collisions&lt;/h2&gt;
&lt;p&gt;First, let&amp;rsquo;s discuss what AABB actually means.&lt;/p&gt;
&lt;p&gt;For those unfamiliar with collision detection, there are many ways of checking if two objects collide.
A lot of them, actually, each with its pros and cons.
Some give very accurate collisions for objects of any shape, but are not real-time viable, others are real-time, but far less accurate.
It&amp;rsquo;s an ongoing research, and new ways of detecting complex collisions as fast as possible &lt;a href=&#34;https://www.youtube.com/watch?v=2c8o65JiPQY&amp;amp;pp=ygURb25lIG1pbnV0ZSBwYXBlcnM%3D&#34; target=&#34;_blank&#34;&gt;appear every now and then&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m mainly developing games in either TIC-80 or LÖVE2D.
LÖVE2D actually comes with a collision detection library, called &lt;a href=&#34;https://box2d.org/about/&#34; target=&#34;_blank&#34;&gt;Box2D&lt;/a&gt;.
My games are sprite-based, and since I often use TIC-80, I can&amp;rsquo;t really commit to Box2D, so instead I opt for a simpler collision detection logic.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s where AABB comes - it&amp;rsquo;s an Axis-Sligned Bounding Box collision detection system:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/aabb.png&#34;
         alt=&#34;Figure 1: Axis-aligned rectangles are quite easy to check for intersections, since all we need to know is their origin and dimensions.&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 1: &lt;/span&gt;Axis-aligned rectangles are quite easy to check for intersections, since all we need to know is their origin and dimensions.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The general idea is that if the bounding box of object A is completely to the left or to the right of object B, the objects don&amp;rsquo;t collide.
Similarly, if the object A is above or below object B, there&amp;rsquo;s no collision either.
And when all four of these situations are not true, then there&amp;rsquo;s a collision.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a rather simple solution, but it can yield satisfying results.
Implementing this by hand is trivial, but there&amp;rsquo;s a lot more to checking collisions - we need to make it quite optimized, and handle object interactions.&lt;/p&gt;
&lt;p&gt;Thankfully, there&amp;rsquo;s an amazing pure Lua library called &lt;a href=&#34;https://github.com/kikito/bump.lua&#34; target=&#34;_blank&#34;&gt;bump.lua&lt;/a&gt;, that implements these AABB checks and more.
And it&amp;rsquo;s near perfect for sprite-based games, since everything is aligned to the grid, so that&amp;rsquo;s what I&amp;rsquo;m using in TIC-80 and Love2D.
Perfect, until we want something other than a rectangle.
For example, slopes.&lt;/p&gt;
&lt;h2 id=&#34;implementing-slopes-with-bump-dot-lua&#34;&gt;Implementing slopes with &lt;code&gt;bump.lua&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;To be honest, there&amp;rsquo;s not that much to it for implementing slopes in an AABB collision system.
Actually, I could just give you the formula and be done with it.
Even more, actually - I&amp;rsquo;m sure you can figure it out if you think about it for just a bit.
But that&amp;rsquo;s not fun!
So instead, I&amp;rsquo;ll walk you through from the beginning - creating a TIC project, adding &lt;code&gt;bump.lua&lt;/code&gt;, loading entities to the world, adding collisions, simple physics, and finally, slopes.&lt;/p&gt;
&lt;p&gt;But, if you want, you can skip directly to the &lt;a href=&#34;#implementing-slopes-with-aabb-collisions&#34;&gt;slope implementation section&lt;/a&gt;, no worries!&lt;/p&gt;
&lt;h3 id=&#34;tic-80&#34;&gt;TIC-80&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://tic80.com/&#34; target=&#34;_blank&#34;&gt;TIC-80&lt;/a&gt; is a small game engine that supports Lua as one of its main languages to develop games, along with other ones, like &lt;a href=&#34;https://fennel-lang.org/&#34; target=&#34;_blank&#34;&gt;Fennel&lt;/a&gt;.
I primarily do my projects in Fennel, as I like it a little bit more than Lua&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;, but for this post, I chose Lua, as I want this to be a more general tutorial, applicable to a wider audience.&lt;/p&gt;
&lt;p&gt;Even though TIC-80 is a fantasy computer, I believe it is capable of being an engine that you can use to make full-fledged games with.
Two years ago, &lt;a href=&#34;https://www.playbalatro.com/&#34; target=&#34;_blank&#34;&gt;Balatro&lt;/a&gt; again proved that Love2D is fully suited for making massively successful games, without the need for something more, like Godot or Unity.
I think TIC-80 can shine &lt;a href=&#34;https://tic80.com/play?cart=4496&#34; target=&#34;_blank&#34;&gt;similarly&lt;/a&gt;, but it seems that far fewer people consider it as a viable alternative, even fewer than with Love2D.&lt;/p&gt;
&lt;p&gt;The other thing I often think about is that games don&amp;rsquo;t have to be implemented with the best technology to be &lt;em&gt;good games&lt;/em&gt;.
I&amp;rsquo;ve played a few games on Game Boy Color and especially Game Boy Advance, and they were amazing even today.
And these consoles were quite limited even for the time.
Yet, people are still making games for them.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s another reason why I want to write this post more as a tutorial on TIC-80, as it can maybe make you want to try it!&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s start by firing up TIC-80:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/tic80.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;By default, TIC-80 starts you in a console-like environment.
It&amp;rsquo;s a fantasy &lt;em&gt;computer&lt;/em&gt;, after all.&lt;/p&gt;
&lt;p&gt;By pressing &lt;kbd&gt;Esc&lt;/kbd&gt;, you can go into the code editor:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/tic80-code-editor.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;You can also switch to a built-in sprite editor by pressing &lt;kbd&gt;F2&lt;/kbd&gt; or clicking on a ghost icon in the top bar:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/tic80-sprite-editor.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;There&amp;rsquo;s also a map editor, which we&amp;rsquo;ll look into a bit later, you can create sound effects with a built-in synthesizer and write music in the tracker!
It&amp;rsquo;s a fully self-contained system that you can develop your games in, and not just games - people write music in it, create beautiful &lt;a href=&#34;https://tic80.com/play?cat=5&amp;amp;sort=2&#34; target=&#34;_blank&#34;&gt;entries&lt;/a&gt; for Demo Scene contests, and more.&lt;/p&gt;
&lt;p&gt;I won&amp;rsquo;t be using the inbuilt code editor, though, as I&amp;rsquo;m much more comfortable writing in Emacs, and you can use any external editor with TIC, but we&amp;rsquo;ll be using the sprite and map editors.
So, let&amp;rsquo;s start!&lt;/p&gt;
&lt;h3 id=&#34;creating-a-project-and-adding-bump-dot-lua&#34;&gt;Creating a project and adding &lt;code&gt;bump.lua&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Actually, if you did start the TIC-80 with me, you don&amp;rsquo;t have to create anything - by default, TIC creates a sample cart that you can edit right away.
That&amp;rsquo;s what we&amp;rsquo;ll do.
First, let&amp;rsquo;s edit the metadata at the top of the cart:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- title:   AABB Slopes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- author:  Andrey Listopadov&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- desc:    Making slopes wiht AABB collisions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- site:    https://andreyor.st&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- license: MIT License&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- version: 0.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- script:  lua&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We could also delete default sprites right now, but we&amp;rsquo;ll do it later.
Right now, we need to add &lt;code&gt;bump.lua&lt;/code&gt; to the cart.&lt;/p&gt;
&lt;p&gt;TIC-80 doesn&amp;rsquo;t really provide access to your filesystem - it is expected for the cart to contain everything, much like game cartridges did in the early days of home consoles.
Because of that, it&amp;rsquo;s not possible to install &lt;code&gt;bump.lua&lt;/code&gt; via LuaRocks, or download it and place the file near your cart.
We&amp;rsquo;ll have to embed it directly.&lt;/p&gt;
&lt;p&gt;Luckily for us, it&amp;rsquo;s really easy to do so in Lua!
All we need is to set &lt;code&gt;package.preload.bump&lt;/code&gt; to a function that contains &lt;a href=&#34;https://raw.githubusercontent.com/kikito/bump.lua/refs/heads/master/bump.lua&#34; target=&#34;_blank&#34;&gt;all of the library code&lt;/a&gt;.
And even greater, that &lt;code&gt;bump.lua&lt;/code&gt; is a simple, single-file, self-contained Lua library.&lt;/p&gt;
&lt;p&gt;So we can do it like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;package.preload.bump = &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- Copy the bump.lua file contens here.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- Yes, as is.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we can use &lt;code&gt;require&lt;/code&gt; to bring this library to our game, and create the world:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; bump = require &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;bump&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; world = bump.newWorld(24)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Great! Now let&amp;rsquo;s draw some sprites we&amp;rsquo;ll use!&lt;/p&gt;
&lt;h3 id=&#34;creating-sprites-and-using-the-map-editor&#34;&gt;Creating sprites and using the map editor&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s nothing much to talk about here, as TIC features a rather simplistic sprite editor:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/sprites.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;However, we&amp;rsquo;ll be using some of its advanced features, which can be revealed by pressing this switch in the top left corner of the editor:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/sprites-advanced.png&#34;
         alt=&#34;Figure 2: Advanced mode switch (red arrow), flags (green arrow)&#34; width=&#34;50%&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 2: &lt;/span&gt;Advanced mode switch (red arrow), flags (green arrow)&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;One of such features is the flags we can set on a sprite.
These flags act as a bit mask, so you can set up to 256 combinations of flags, which is enough, since TIC has space for exactly 256 sprites.
Did I mention how cool the design of TIC is yet?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve set bit 1 here to indicate that this sprite is a ball, and I set bit 0 for all of the solid objects drawn near it.
This way, when we load these sprites to the game world, we&amp;rsquo;ve created with &lt;code&gt;bump.lua&lt;/code&gt;, we will be able determine what this object should be.&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s use these sprites in the map editor:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/map-editor.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;In the map editor, you can choose from either 256 tiles or 256 sprites to draw your map with.
TIC actually has two sprite-sets: tiles and sprites.
The only distinction between them is that you&amp;rsquo;re limited to either of those sets when you design your map.
Other than that, they&amp;rsquo;re the same.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve created a small test scene, with our ball and some walls:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/map.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Now we can start implementing our game logic, as right now if we run this cart, nothing would happen yet.&lt;/p&gt;
&lt;h3 id=&#34;loading-entities-to-the-world&#34;&gt;Loading entities to the world&lt;/h3&gt;
&lt;p&gt;We&amp;rsquo;ll start by editing the &lt;code&gt;TIC&lt;/code&gt; function in our standard cart:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;TIC&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cls(0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    map(0, 0, 31, 18, 0, 0, 0, 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, if we run our cart, we&amp;rsquo;ll see the same thing we&amp;rsquo;ve seen in the map editor:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/first-run.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;However, nothing moves yet, as we haven&amp;rsquo;t implemented any of the game&amp;rsquo;s logic.
Before we can do that, we&amp;rsquo;ll need to populate our world with rectangles, so let&amp;rsquo;s do that.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;load_map&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; x=0, 240 * 8, 8 &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; y=0, 136 * 8, 8 &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; obj = is_obj(x, y)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; obj &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                world:add(obj, obj.x, obj.y, obj.w, obj.h)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here, I&amp;rsquo;m loading the &lt;strong&gt;entire&lt;/strong&gt; map to the world.
It&amp;rsquo;s not necessary to do that, since we&amp;rsquo;re only going to use one map screen, but it doesn&amp;rsquo;t hurt.
The key function here is the &lt;code&gt;is_obj&lt;/code&gt; predicate, which we&amp;rsquo;re going to write next:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; balls = {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;is_obj&lt;/span&gt;(x, y)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; id = id_at(x, y)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; is_solid(id) &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; {x = x, y = y, h = 8, w = 8}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;elseif&lt;/span&gt; is_ball(id) &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; ball = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            x = x,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            y = y,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            h = 8,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            w = 8,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            xvel = 0,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            yvel = 0,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            is_ball = &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        balls[ball] = &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; ball
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First things first, we need to get the ID of the tile at coordinates &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;.
We do so by using TIC&amp;rsquo;s built-in function &lt;code&gt;mget&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;id_at&lt;/span&gt;(x, y)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; mget(x // 8, y // 8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, we&amp;rsquo;ll define a set of predicates that, given an &lt;code&gt;id&lt;/code&gt; will tell if the object we&amp;rsquo;re inspecting is a wall, or a ball:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;is_solid&lt;/span&gt;(id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; fget(id, 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;is_ball&lt;/span&gt;(id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; fget(id, 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So the &lt;code&gt;is_obj&lt;/code&gt; function we&amp;rsquo;ve defined above gets the tile &lt;code&gt;id&lt;/code&gt;, and checks if it is a ball, or a wall tile.
If so, it creates an object that we can add to the &lt;code&gt;bump.lua&lt;/code&gt; world.
Each object has a set amount of required properties, but you can also have additional ones, like the &lt;code&gt;is_ball&lt;/code&gt; field, in the case of the ball object.
We also add a ball to the list of balls, in case we might want to add more than one ball later.&lt;/p&gt;
&lt;p&gt;Now, we can load the map.
We do so in the &lt;code&gt;BOOT&lt;/code&gt; function, which executes when the cart is being loaded.
You can also write the call at the top level if you want, and it may make the code a little bit more portable, as older versions of TIC didn&amp;rsquo;t have &lt;code&gt;BOOT&lt;/code&gt;, but I&amp;rsquo;m not targeting those, so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;BOOT&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    load_map()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With that in place, we can implement some simple physics for the ball.&lt;/p&gt;
&lt;h3 id=&#34;working-with-bump-dot-lua&#34;&gt;Working with &lt;code&gt;bump.lua&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Since we&amp;rsquo;ve loaded everything into the world we&amp;rsquo;ve created with &lt;code&gt;bump.lua&lt;/code&gt;, we can now manipulate things in it.
We&amp;rsquo;ll be mainly manipulating balls, so let&amp;rsquo;s add some methods to the &lt;code&gt;balls&lt;/code&gt; table:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;setmetatable(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    balls,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        __index = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            update = &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt;(self)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; ball &lt;span style=&#34;font-weight:bold&#34;&gt;in&lt;/span&gt; pairs(self) &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    ball.yvel = lerp(ball.yvel, 5, 0.1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    ball.xvel = lerp(ball.xvel, 0, 0.1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    ball.x, ball.y, cols, len = world:move(ball, ball.x + ball.xvel, ball.y + ball.yvel)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; i = 1, len &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; col = cols[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; col.normal.y == -1 &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            ball.yvel = -(ball.yvel * 0.9)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; col.normal.x ~= 0 &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            ball.xvel = -(ball.xvel * 0.9)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            draw = &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt;(self)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; ball &lt;span style=&#34;font-weight:bold&#34;&gt;in&lt;/span&gt; pairs(self) &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    spr(1, ball.x, ball.y, 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve added two methods: &lt;code&gt;draw&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt;.
It&amp;rsquo;s not necessary to separate these, you could do everything in one call, but it&amp;rsquo;s a bit easier to reason about them this way.
Yeah, I know, looping over all of the balls two times just to update each, and then draw each is bad design, since we could do it in one loop, but that&amp;rsquo;s not the main focus here.
But it&amp;rsquo;s great that you&amp;rsquo;ve pointed this out!
Ten points to the TIC house!&lt;/p&gt;
&lt;p&gt;Anyway, we&amp;rsquo;re looping over all of the balls in the table, which we don&amp;rsquo;t have that many yet, only one, and updating each one.
The important part here is that we compute the ball&amp;rsquo;s X and Y velocity, and then use them to move the ball in the world, by calling &lt;code&gt;world:move()&lt;/code&gt;.
I&amp;rsquo;m using linear interpolation, defined as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lerp&lt;/span&gt;(a, b, t)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; ((1 - t) * a) + (t * b)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We don&amp;rsquo;t care that much about delta-time here, as TIC runs at a consistent 60 frames per second even when you push it to the limits.
You can, of course, slow it down with bad code, and we already have two loops instead of one, which is concerning, but we&amp;rsquo;ll be fine, don&amp;rsquo;t worry.
Lua is quite fast.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ball.x, ball.y, cols, len = world:move(ball, ball.x + ball.xvel, ball.y + ball.yvel)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So by calling &lt;code&gt;world:move()&lt;/code&gt; with the ball object, we receive new X and Y positions of that ball after it was moved with respect to collisions.
We&amp;rsquo;re not going to build a sophisticated physics engine here, but we will need to handle some collisions.
&lt;code&gt;bump.lua&lt;/code&gt; actually has different &lt;a href=&#34;https://github.com/kikito/bump.lua?tab=readme-ov-file#collision-resolution&#34; target=&#34;_blank&#34;&gt;collision types&lt;/a&gt;, like &lt;code&gt;bounce&lt;/code&gt;, that we could use here, but for our purposes the default &lt;code&gt;slide&lt;/code&gt; is better.&lt;/p&gt;
&lt;p&gt;In addition to the new X and Y positions, this function returns a list of collisions that happened during the move.
We can loop over those and update our ball&amp;rsquo;s properties, such as its velocity.
We do so in the following loop&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; i = 1, len &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; col = cols[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; col.normal.y == -1 &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ball.yvel = -(ball.yvel * 0.9)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; col.normal.x ~= 0 &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ball.xvel = -(ball.xvel * 0.9)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;re slowly decreasing the ball&amp;rsquo;s velocity, also switching directions on contact.
That&amp;rsquo;s pretty much what the &lt;code&gt;bounce&lt;/code&gt; collision would do for us.&lt;/p&gt;
&lt;p&gt;For the &lt;code&gt;draw&lt;/code&gt; method, we simply draw the ball sprite using another TIC&amp;rsquo;s builtin function &lt;code&gt;spr&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Having these implemented, we can add them to the &lt;code&gt;TIC&lt;/code&gt; function, like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;TIC&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cls(0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    map(0, 0, 31, 18, 0, 0, 0, 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    balls:update()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    balls:draw()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, if we run our game, we&amp;rsquo;ll see our ball bouncing:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/ball-bounce.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Uh oh, why are there two balls, and one floating over the ground?
Did we forget to add it to the &lt;code&gt;balls&lt;/code&gt; table, so it gets updated?
If we did, why is it even drawn - we loop over balls in both functions.&lt;/p&gt;
&lt;p&gt;If you look closer, you&amp;rsquo;ll see the problem.
We&amp;rsquo;ve loaded the map to the world, and we&amp;rsquo;re drawing the ball using the &lt;code&gt;spr&lt;/code&gt; function.
But we&amp;rsquo;re still drawing the original map in the &lt;code&gt;TIC&lt;/code&gt; function by calling &lt;code&gt;map&lt;/code&gt;!
And our map still has the ball.&lt;/p&gt;
&lt;p&gt;We can go two ways here.
One would be to use the &lt;code&gt;mset&lt;/code&gt; function and replace the ball tile with nothing in our map when we&amp;rsquo;re loading it.
Or, we can hide the ball at runtime using &lt;code&gt;map&lt;/code&gt; function&amp;rsquo;s special remapping feature.
Let&amp;rsquo;s do that instead, as it is a bit cleaner:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;remap&lt;/span&gt;(id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; is_ball(id) &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; id
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we update our &lt;code&gt;TIC&lt;/code&gt; function to use this &lt;code&gt;remap&lt;/code&gt; function in our &lt;code&gt;map&lt;/code&gt; call:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;TIC&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cls(0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    map(0, 0, 31, 18, 0, 0, 0, 1, remap)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    balls:update()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    balls:draw()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And, presto!&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/basic-physics.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;h3 id=&#34;handling-mouse-events&#34;&gt;Handling mouse events&lt;/h3&gt;
&lt;p&gt;Our introduction to TIC isn&amp;rsquo;t over yet, because I always wanted to try using the mouse integration.
Our ball is currently pretty stiff, so we&amp;rsquo;ll tweak its physics along the way.
Having mouse support will make it easier to test things out, as doing so by updating the code is a bit cumbersome.
And I don&amp;rsquo;t know how to make sensible controls for a ball with arrow keys - it&amp;rsquo;s just a bouncing ball, what do you expect it to do, roll by itself when you press a magic key??
Let&amp;rsquo;s drag the balls instead.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll start by creating a small storage variable that we&amp;rsquo;ll assign to the currently grabbed ball:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; grabbed = &lt;span style=&#34;font-weight:bold&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s uninitialized by default, we&amp;rsquo;ll set it later in the &lt;code&gt;update&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; mx, my, is_pressed = mouse()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; is_pressed &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;not&lt;/span&gt; grabbed &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; items = world:queryPoint(mx, my, &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt;(obj) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; obj.is_ball &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; next(items) &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        grabbed = items[1]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;elseif&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;not&lt;/span&gt; is_pressed &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; grabbed &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        grabbed.xvel = (grabbed.x - grabbed.prev_x)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        grabbed.yvel = (grabbed.y - grabbed.prev_y)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        grabbed.prev_x, grabbed.prev_y = &lt;span style=&#34;font-weight:bold&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;font-weight:bold&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    grabbed = &lt;span style=&#34;font-weight:bold&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We add this before the main loop over all balls in the &lt;code&gt;update&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;mouse&lt;/code&gt; function in TIC returns a set of values, X and Y coordinates, and states of each mouse button.
We&amp;rsquo;re only interested in the left mouse button, so that&amp;rsquo;s what we store.&lt;/p&gt;
&lt;p&gt;Then, if the button is pressed, we use a method from the &lt;a href=&#34;https://github.com/kikito/bump.lua?tab=readme-ov-file#querying-with-a-point&#34; target=&#34;_blank&#34;&gt;Intermediate API&lt;/a&gt; section of &lt;code&gt;bump.lua&lt;/code&gt;.
It returns a list of items, and since we don&amp;rsquo;t have anything that overlaps, we can safely take the first item in the list.
We&amp;rsquo;re also using a similar feature to the &lt;code&gt;map&lt;/code&gt; function&amp;rsquo;s remap here - we&amp;rsquo;re providing a filtering function that will make sure that we can only grab ball objects, not other tiles.&lt;/p&gt;
&lt;p&gt;When the button is released, its state will change, and we need to release the ball.
If there was a ball grabbed, we set its velocity to conserve the momentum from moving it by the mouse, which we&amp;rsquo;ll handle later.
Then we unset the &lt;code&gt;grabbed&lt;/code&gt; storage variable.&lt;/p&gt;
&lt;p&gt;Next, in the &lt;code&gt;for&lt;/code&gt; loop responsible for updating the balls, we check if the current ball is the one we&amp;rsquo;ve grabbed, and we override its movement:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; ball &lt;span style=&#34;font-weight:bold&#34;&gt;in&lt;/span&gt; pairs(self) &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; ball == grabbed &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; x, y = lerp(grabbed.x, mx-4, 0.3), lerp(grabbed.y, my-4, 0.3)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        grabbed.prev_x, grabbed.prev_y = grabbed.x, grabbed.y
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ball.x, ball.y = world:move(ball, x, y)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- no changes to the old logic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, as you can see, we&amp;rsquo;re moving the ball to the mouse pointer coordinates, still with respect to collisions.
We also store additional information in the &lt;code&gt;grabbed&lt;/code&gt; object, mainly the previous X and Y positions that we use in that momentum conservation code a bit earlier.
And with that, we can drag the ball around:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/mouse-drag.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;This is as basic as it gets - you&amp;rsquo;ll notice that if we add more balls, we can&amp;rsquo;t move other balls with the one we&amp;rsquo;re dragging.
You can, of course, make a more sophisticated physics simulation - handle collisions better, so it would move other balls as well, transfer the momentum to other objects, make balls roll off each other, as right now they&amp;rsquo;re basically squares, and so on.&lt;/p&gt;
&lt;p&gt;So you can do something like that if you try experimenting with collision resolution a bit more:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/ball-interactions.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Now, we&amp;rsquo;re pretty much set for working towards the main topic of this post - slopes.&lt;/p&gt;
&lt;h2 id=&#34;implementing-slopes-with-aabb-collisions&#34;&gt;Implementing slopes with AABB collisions&lt;/h2&gt;
&lt;p&gt;Phew, FINALLY, all that just to tell you that to handle slopes you just need to do&amp;hellip;&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/aabb-slope-handling.png&#34;
         alt=&#34;Figure 3: &amp;amp;hellip;is this.&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 3: &lt;/span&gt;&amp;hellip;is this.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;OK, this is anticlimactic, so let&amp;rsquo;s implement this.
But first, what is a slope in our case?&lt;/p&gt;
&lt;p&gt;Because we can only have axis-aligned rectangles, we need to create a special kind of object in our world that will still be a rectangle, but handle collisions differently.
Since our game is tile-based, we don&amp;rsquo;t have a lot of meaningful angles to support.
The most common slope in games is a segment with dimensions of &lt;code&gt;16x8&lt;/code&gt;.
It spans exactly two tiles and takes you one tile height up.
Let&amp;rsquo;s draw it:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/slope-sprites.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;You can see that I&amp;rsquo;ve set bit 2 to the slope tile here, so we can correctly handle it while loading our map to the world.
If we add these to the world right now, they won&amp;rsquo;t work, obviously, since these are regular rectangles:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/slopes-dont-work-yet.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s change that:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;is_up_slope&lt;/span&gt;(id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; fget(id, 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;is_down_slope&lt;/span&gt;(id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; fget(id, 3)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;ll start by defining two more predicates, and then use them in our &lt;code&gt;is_obj&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;is_obj&lt;/span&gt;(x, y)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; id = id_at(x, y)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; is_solid(id) &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; {x = x, y = y, h = 8, w = 8}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;elseif&lt;/span&gt; is_up_slope(id) &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; {x = x, y = y, h = 8, w = 16, slope = slope, dir = 1}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;elseif&lt;/span&gt; is_down_slope(id) &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; {x = x, y = y, h = 8, w = 16, slope = slope, dir = -1}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;elseif&lt;/span&gt; is_ball(id) &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; ball = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            x = x,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            y = y,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            h = 8,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            w = 8,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            xvel = 0,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            yvel = 0,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            is_ball = &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        balls[ball] = &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; ball
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, these are regular rectangles, except in our world, the &lt;code&gt;8x8&lt;/code&gt; tile creates a &lt;code&gt;16x8&lt;/code&gt; rectangle.
The other half of the slope is just decoration.&lt;/p&gt;
&lt;p&gt;We also have the &lt;code&gt;slope&lt;/code&gt; and &lt;code&gt;dir&lt;/code&gt; fields here.
The &lt;code&gt;slope&lt;/code&gt; is a function responsible for handling collisions that we&amp;rsquo;ll implement shortly.
The &lt;code&gt;dir&lt;/code&gt; field determines if this is an up-slope, raising from left to right, or a down-slope, lowering from left to right (or raising from right to left).
We need to know the direction, otherwise, we won&amp;rsquo;t be able to calculate normals and properly map coordinates to new values.&lt;/p&gt;
&lt;h3 id=&#34;calculating-slope-collision-coordinates&#34;&gt;Calculating slope collision coordinates&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s the &lt;code&gt;slope&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;slope&lt;/span&gt;(obj)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; obj.yvel &amp;gt;= 0 &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; _, _, cols, len = world:check(obj, obj.x, obj.y + obj.yvel, slope_filter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; i=1, len &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; col = cols[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; col.normal.y ~= 1 &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt; &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- -1 or 0 will do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; slope_floor = col.other.y - col.other.h
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; delta = clamp(0, (obj.x + obj.w / 2) - col.other.x, col.other.w) / col.other.w
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; y_off = &lt;span style=&#34;font-weight:bold&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; col.other.dir &amp;gt; 0 &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    y_off = lerp(col.other.h, 0, delta)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    y_off = lerp(0, col.other.h, delta)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; newy = slope_floor + y_off
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; math.floor(newy), slope_normal(col.other)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, that&amp;rsquo;s a lot to take in.
Let&amp;rsquo;s go through step by step.&lt;/p&gt;
&lt;p&gt;First, we check if the object&amp;rsquo;s velocity is going at least downwards.
We don&amp;rsquo;t want to trigger slope collisions when objects move away from the slope, so that&amp;rsquo;s pretty simple.&lt;/p&gt;
&lt;p&gt;Next, as usual, we need to handle collisions.
However, there&amp;rsquo;s a catch - since our slopes are rectangles in disguise, we can&amp;rsquo;t just use the normal &lt;code&gt;world:move()&lt;/code&gt; and be done.
Instead, we need to kinda implement the &lt;code&gt;world:move()&lt;/code&gt; in terms of &lt;code&gt;world:check()&lt;/code&gt; and &lt;code&gt;world:update()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;check&lt;/code&gt; method does the same stuff as &lt;code&gt;move&lt;/code&gt; except it doesn&amp;rsquo;t move anything.
It pretends that the object has moved, and returns a list of collisions and coordinates where it would end up if it actually moved.
That&amp;rsquo;s perfect for our needs.
The &lt;code&gt;update&lt;/code&gt; method can move the object around without checking for any collisions, and that&amp;rsquo;s the other piece of the puzzle.&lt;/p&gt;
&lt;p&gt;But right now, the ball collides with the slope rectangle, and it can&amp;rsquo;t go further, what can we do?
We use filtering, of course.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;world:check()&lt;/code&gt; also accepts the collision filter, as &lt;code&gt;world:move()&lt;/code&gt; does.
We&amp;rsquo;ll need to add two new filter functions, one for checking slopes specifically, and the other to allow balls to move through slope rectangles freely:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;slope_filter&lt;/span&gt;(_, other)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; other.slope &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;cross&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ball_filter&lt;/span&gt;(_, other)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; other.slope &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;cross&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;slide&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With that out of the way, we can go into collision checking.&lt;/p&gt;
&lt;p&gt;As usual, we iterate over a list of collisions.
We then check if the collision&amp;rsquo;s Y component of the normal vector points at least up.
If so, we have our collision, but we are just getting started.&lt;/p&gt;
&lt;p&gt;Next, we calculate the slope floor Y position.
This is the lowest coordinate our collision could possibly have:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; slope_floor = col.other.y - col.other.h
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, we calculate the delta:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; delta = clamp(0, (obj.x + obj.w / 2) - col.other.x, col.other.w) / col.other.w
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is how far from the left edge of the slope rectangle the collision is going to happen.
We try to measure in the center of the colliding tile, and normalize it to be a value from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next, we need to determine the Y coordinate on that slope:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; y_off = &lt;span style=&#34;font-weight:bold&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; col.other.dir &amp;gt; 0 &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    y_off = lerp(col.other.h, 0, delta)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    y_off = lerp(0, col.other.h, delta)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We do so by checking the slope direction, and do a linear interpolation between &lt;code&gt;0&lt;/code&gt; and slope height, using our delta value.
Linear interpolation will move us in a straight diagonal line from the bottom corner of the slope to the top corner of the slope.
Direction is simply used to flip the interpolation.&lt;/p&gt;
&lt;p&gt;Finally, we&amp;rsquo;re calculating a ney Y position, and normals to return:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; newy = slope_floor + y_off
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; math.floor(newy), slope_normal(col.other)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Our Y position from &lt;code&gt;lerp&lt;/code&gt; is relative to the slope, so we add back the &lt;code&gt;slope_floor&lt;/code&gt; position to translate it back to world coordinates.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s pretty much just a small part of it!
Wait&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;handling-slope-collisions&#34;&gt;Handling slope collisions&lt;/h3&gt;
&lt;p&gt;We still need to adjust the object&amp;rsquo;s position to that coordinate - why didn&amp;rsquo;t we do so in the slope function itself?
Well, because reasons&amp;hellip;&lt;/p&gt;
&lt;p&gt;I mean, I tried to do that, but it didn&amp;rsquo;t work well, there are many outside factors that we may need to consider, and it&amp;rsquo;s not the best way to move it to this function.
So let&amp;rsquo;s change our &lt;code&gt;update&lt;/code&gt; method of the &lt;code&gt;balls&lt;/code&gt; table.&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s handle normal ball collisions.
Mouse collisions will come later:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; ball &lt;span style=&#34;font-weight:bold&#34;&gt;in&lt;/span&gt; pairs(self) &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; ball == grabbed &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;--- 8&amp;lt; ---&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ball.yvel = lerp(ball.yvel, 5, 0.075)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ball.xvel = lerp(ball.xvel, 0, 0.03)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ball.x, ball.y, cols, len = world:move(ball, ball.x + ball.xvel, ball.y + ball.yvel, ball_filter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; i = 1, len &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; col = cols[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; col.other.slope &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; newy, xnorm, ynorm = col.other.slope(ball)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; newy &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; ball.y &amp;gt;= newy &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    world:update(ball, ball.x, newy, ball.w, ball.h)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    ball.y = newy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    ball.xvel = ball.xvel + xnorm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    ball.yvel = (- ball.yvel - ynorm) * 0.5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; col.normal.y ~= 0 &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    ball.yvel = -(ball.yvel * 0.9)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    ball.xvel = ball.xvel * 0.75
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; col.normal.x ~= 0 &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    ball.xvel = -(ball.xvel * 0.9)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;Code Snippet 1:&lt;/span&gt;
  Imagine if I didn&#39;t stack the &lt;code&gt;end&lt;/code&gt; keywords on the same line? This post would be even longer! It&#39;s already a bit too long&amp;#x2026;
&lt;/div&gt;
&lt;p&gt;Main differences from before: we added &lt;code&gt;ball_filter&lt;/code&gt; to the &lt;code&gt;world:move()&lt;/code&gt; call, and split collision handling logic into two separate branches.
The first branch checks if the collision happens with a slope and handles it.
The second branch is the same as before.&lt;/p&gt;
&lt;p&gt;The collision handling is pretty simple, really - we check if &lt;code&gt;slope&lt;/code&gt; actually returned a new coordinate, and if the ball&amp;rsquo;s current Y position is lower than that, we need to handle the collision.
The &lt;code&gt;ball_filter&lt;/code&gt; sets slope collisions to &lt;code&gt;cross&lt;/code&gt;, and it allows balls to move through slope blocks as if they&amp;rsquo;re not there, except we still get collision information.
So if the ball&amp;rsquo;s Y coordinate is less than the slope collision coordinate, it means that we need to push the ball out of the slope.
We do it straight up, without concerns about the normal vector to the slope, but it is possible to do so (I&amp;rsquo;m just lazy).&lt;/p&gt;
&lt;p&gt;Calling &lt;code&gt;world:update()&lt;/code&gt; sets the ball to a new position, and we also update its fields to set the new coordinate, and update velocities.
We also break from this loop, as we don&amp;rsquo;t really want to handle any other collision, since it could get messy.&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s do the same for mouse movement:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; ball &lt;span style=&#34;font-weight:bold&#34;&gt;in&lt;/span&gt; pairs(self) &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; ball == grabbed &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; x, y = lerp(ball.x, mx-4, 0.3), lerp(ball.y, my-4, 0.3)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ball.prev_x, ball.prev_y = ball.x, ball.y
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ball.x, ball.y, cols, len = world:move(ball, x, y, ball_filter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; i = 1, len &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; col = cols[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; col.other.slope &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; yvel = ball.yvel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ball.yvel = 1 &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- needed for the slope check to happen&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; newy = col.other.slope(ball)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ball.yvel = yvel &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- restore the original velocity&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; newy &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; ball.y &amp;gt;= newy &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    world:update(ball, ball.x, newy, ball.w, ball.h)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    ball.y = newy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;--- 8&amp;lt; ---&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s pretty similar to the one above, except we need to do a small trick.&lt;/p&gt;
&lt;p&gt;Notice how we set the ball&amp;rsquo;s velocity to &lt;code&gt;1&lt;/code&gt; right before the check?
Since the ball is moved by the mouse, its velocity is not really updated.
Don&amp;rsquo;t ask me how long I was debugging why the collision doesn&amp;rsquo;t happen&amp;hellip;&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s pretty much it!&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/slopes-work.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;We can also add a different kind of slope to show that this approach is generic enough:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/more-slopes.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This is still, by no means, a proper physics simulation of slopes.
Balls bounce off slopes in the wrong direction at certain angles, normals are ignored when handling collisions, but hey, this might not be a problem in your game at all!&lt;/p&gt;
&lt;p&gt;For instance, in my original case, the player is the main object I need to be able to interact with slopes, and I have a pretty simplistic game-oriented physics.
So I don&amp;rsquo;t need the player to jump in a weird way when it&amp;rsquo;s on a slope - jumps should remain predictable.
There are no projectiles that bounce off walls either, and thus, this implementation works fine.&lt;/p&gt;
&lt;p&gt;You can, of course, use these principles to implement a more sophisticated engine.
And there&amp;rsquo;s still a lot of room for improvement, too.&lt;/p&gt;
&lt;p&gt;For instance, the way we define slopes is quite limited.
Sure, we can adjust the slope angle, but because we&amp;rsquo;re building large slopes from small building blocks, there&amp;rsquo;s a wonky collision at these blocks&amp;rsquo; corners.
Instead, we could define two points and programmatically generate map tiles along the slope angle up to its end, using predefined sprites.
And for non-sprite-based games, it doesn&amp;rsquo;t make sense to limit slopes to certain angles - you can define arbitrary-sized rectangles, making slopes as steep as needed.&lt;/p&gt;
&lt;p&gt;Alternatively, you can refactor this code and define slopes as mathematical functions.
Thus, you&amp;rsquo;ll be able to create splines and have curved slopes.
Normal vector calculation will be a bit tougher, though.&lt;/p&gt;
&lt;p&gt;And actually, if you happen to know some blog posts on the matter, please send them!
I&amp;rsquo;m quite interested.&lt;/p&gt;
&lt;p&gt;If you want to experiment with the code, here&amp;rsquo;s a cart that you can load with TIC-80, or you can &lt;a href=&#34;https://tic80.com/play?cart=4497&#34; target=&#34;_blank&#34;&gt;experiment online&lt;/a&gt; on TIC&amp;rsquo;s website:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2026-01-09-slopes-in-aabb-collision-systems/aabb-slopes.png&#34;
         alt=&#34;Figure 4: That&amp;amp;rsquo;s an actual game cartridge you can load into TIC-80!&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 4: &lt;/span&gt;That&amp;rsquo;s an actual game cartridge you can load into TIC-80!&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;That&amp;rsquo;s all from me.
Hope you&amp;rsquo;ve enjoyed this write-up as much as I did, and see you next time!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Code responsible for controlling the player object - movement, abilities, general game logic&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;Fennel &lt;strong&gt;is&lt;/strong&gt; Lua, but it adds a few features on top, like macros that allow additional metaprogramming capabilities, and fixes a bunch of Lua&amp;rsquo;s shortcomings.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;This looks so much tighter in Fennel, gosh:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold&#34;&gt;each &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;col&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ipairs&lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cols&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;font-weight:bold&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;col.normal.y&lt;/span&gt; -1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;font-weight:bold&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ball.yvel&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;= &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ball.yvel&lt;/span&gt; 0.9))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;font-weight:bold&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;not= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;col.normal.x&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;font-weight:bold&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ball.xvel&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;= &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ball.xvel&lt;/span&gt; 0.9)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Slopes in AABB collision systems&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 09 Jan 2026 04:11:00 +0300</pubDate>
    </item><item>
      <title>Interactive game development with LÖVE</title>
      <link>https://andreyor.st/posts/2024-09-08-interactive-game-development-with-love/</link>
      <guid>https://andreyor.st/posts/2024-09-08-interactive-game-development-with-love/</guid>
      <description>&lt;p&gt;This is a continuation of the &lt;a href=&#34;https://andreyor.st/posts/2024-09-08-boredom-and-gamedev/&#34;&gt;previous post&lt;/a&gt; on game development with the LÖVE game engine.
I&amp;rsquo;m slowly appreciating the freedom it gives, compared to the TIC-80 experience.
One of such freedoms is the fact, that LÖVE is a well-behaving console application.&lt;/p&gt;
&lt;p&gt;When you launch TIC, it boots up into a console:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2024-09-08-interactive-game-development-with-love/tic.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;If you do so from a terminal emulator, you can see that the same console is there too:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; TIC-80 tiny computer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; version 1.1.2837 Pro (be42d6f)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; https://tic80.com (C) 2017-2024
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; hello! type help for help
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;ls
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[tic80.com]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mtd.lua
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, writing in this prompt doesn&amp;rsquo;t do anything - it&amp;rsquo;s not sent back into TIC.
And unfortunately, there&amp;rsquo;s no way of reading from standard IN, because there&amp;rsquo;s no &lt;code&gt;io&lt;/code&gt; namespace provided.
One could, theoretically, fiddle with sockets, if it is even possible to load them into TIC, which I&amp;rsquo;m not so sure about.&lt;/p&gt;
&lt;p&gt;In LÖVE, however, you get full Lua experience and more!
As you may know, Lua&amp;rsquo;s &lt;code&gt;io.read()&lt;/code&gt; is blocking, and there&amp;rsquo;s no real way of making it non-blocking or checking the input buffer.
However, that&amp;rsquo;s not a problem for LÖVE, as it has threads!
So we can set up a separate thread that reads from the &lt;code&gt;stdin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Why would we want that?
Well, you see, when it comes to Lua, I usually do my programming in Fennel, and Fennel has a decent &lt;abbr title=&#34;Read Eval Print Loop&#34;&gt;REPL&lt;/abbr&gt; for doing interactive development.
I love the idea of programming with a REPL, I do it a lot for my hobby projects, and at work with Clojure.
Interactive development makes iterations much faster, and, in my experience, minimizes the amount of bugs in the resulting program.
And we can leverage that during game development too.&lt;/p&gt;
&lt;h2 id=&#34;adding-the-repl&#34;&gt;Adding the REPL&lt;/h2&gt;
&lt;p&gt;The way we&amp;rsquo;re going to set this up is as follows:&lt;/p&gt;
&lt;p&gt;We create a new, asynchronous handler for the REPL, and spawn it on the main thread.
Then, we&amp;rsquo;re going to spawn another thread, that will listen on &lt;code&gt;stdin&lt;/code&gt;, and send everything it reads to the main thread.
Finally, once the main thread finishes the evaluation, it sends the data back to the IO thread for printing.
After that, I&amp;rsquo;m going to spice things up by using the Fennel Proto REPL package I made for Emacs for a better REPL experience.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look at the REPL code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;require &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:love.event&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fennel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;require &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lib.fennel&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;read&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cont?&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;io.write &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cont?&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;..&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;gt;&amp;gt; &amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;io.flush&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;.. &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;tostring &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;io.read&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;channel&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;while &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;match &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;channel&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:demand&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:write&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;-&amp;gt; &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;channel&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:demand&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;table.concat &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;\t&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;io.stdout&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:write&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:error&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;-&amp;gt; &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;channel&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:demand&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;io.stderr&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:write&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:read&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;-&amp;gt;&amp;gt; &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;channel&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:demand&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;read&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.event.push&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event-type&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;chan&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.thread.newChannel&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;repl&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;coroutine.wrap &lt;/span&gt;#(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fennel.repl&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;$...&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;repl&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:readChunk&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;[{&lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stack-size&lt;/span&gt;}]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;chan&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:push&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:read&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;chan&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:push&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;&amp;lt; &lt;/span&gt;0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stack-size&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;coroutine.yield&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:onValues&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vals&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;chan&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:push&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:write&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;chan&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:push&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vals&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:onError&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;errtype&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;err&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;chan&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:push&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;chan&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:push&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;err&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:moduleName&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;lib.fennel&amp;#34;&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;-&amp;gt; &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.filesystem.read&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;lib/repl.fnl&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (#(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fennel.compile-string&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;$&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.filesystem.newFileData&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;repl&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.thread.newThread&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:start&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:eval&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;chan&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.handlers.eval&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;repl&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Simply requiring this file would start a REPL.
You may be confused, about how&amp;rsquo;s it going to work, the &lt;code&gt;while true&lt;/code&gt; may look especially concerning.&lt;/p&gt;
&lt;p&gt;When we require this file, the &lt;code&gt;...&lt;/code&gt; is bound to the module name, so the &lt;code&gt;case&lt;/code&gt; doesn&amp;rsquo;t match, as it expects two values an &lt;code&gt;event-type&lt;/code&gt; and the &lt;code&gt;channel&lt;/code&gt;.
Then we fall into the &lt;code&gt;let&lt;/code&gt; block, which defines the channel &lt;code&gt;chan&lt;/code&gt;, the REPL handler &lt;code&gt;repl&lt;/code&gt;, starts the REPL coroutine, which pushes the &lt;code&gt;:read&lt;/code&gt; message to the channel.
Finally, we load this file again, using &lt;code&gt;love.filesystem.read&lt;/code&gt;, compile it to Lua, and start a new thread with &lt;code&gt;:eval&lt;/code&gt; for the &lt;code&gt;event-type&lt;/code&gt;, and &lt;code&gt;chan&lt;/code&gt; for the &lt;code&gt;channel&lt;/code&gt;.
This makes &lt;code&gt;case&lt;/code&gt; match and starts the &lt;code&gt;while&lt;/code&gt; loop, whose sole purpose is to take values off the &lt;code&gt;channel&lt;/code&gt; and act accordingly.&lt;/p&gt;
&lt;p&gt;Finally, we set the &lt;code&gt;love.handlers.eval&lt;/code&gt; handler, matching our &lt;code&gt;:eval&lt;/code&gt; event type to call the &lt;code&gt;repl&lt;/code&gt; as a callback when the event occurs.
The event occurs only when we get the &lt;code&gt;:read&lt;/code&gt; message from the channel, then we use &lt;code&gt;read&lt;/code&gt; to get data from the &lt;code&gt;stdio&lt;/code&gt;, and we push it back to the &lt;code&gt;eval&lt;/code&gt; handler so the &lt;code&gt;repl&lt;/code&gt; callback can be called.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s pretty much it!
Now, let&amp;rsquo;s put it to the test!&lt;/p&gt;
&lt;h2 id=&#34;changing-code-at-runtime&#34;&gt;Changing code at runtime&lt;/h2&gt;
&lt;p&gt;Here, I have a simple player controller and a bunch of values that correspond to how the player behaves:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fall-vel&lt;/span&gt; 300)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;jump-vel&lt;/span&gt; -300)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;run-vel&lt;/span&gt; 200)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;player&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:name&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;player&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:color&lt;/span&gt; [0.3 0.7 0.3 1]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:xvel&lt;/span&gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:yvel&lt;/span&gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 50
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 50
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:flip?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:width&lt;/span&gt; 16
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:height&lt;/span&gt; 24
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:state&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:idle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:extra-jump&lt;/span&gt; 10
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:draw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;p&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; omitted&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:update&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;[{&lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;xvel&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;yvel&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extra-jump&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;flip?&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &amp;amp;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;p&lt;/span&gt;} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dt&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; omitted&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     )})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can try and change the &lt;code&gt;run-vel&lt;/code&gt; and see if it is picked up by the game:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2024-09-08-interactive-game-development-with-love/repl-doesnt-work.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Seems it&amp;rsquo;s not.
Perhaps, we need to recompile the game module?&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2024-09-08-interactive-game-development-with-love/error.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Aw, snap!&lt;/p&gt;
&lt;p&gt;By recompiling the entire module, we undefined some variables, and the game crashed!
By the way, the reason changing the run speed value didn&amp;rsquo;t apply is that we were actually defining a completely new speed value, that is not part of the module we&amp;rsquo;re editing.
That&amp;rsquo;s a quirk of how Lua modules work and how Fennel REPL works.
So let&amp;rsquo;s fix this!&lt;/p&gt;
&lt;h3 id=&#34;modules-and-state&#34;&gt;Modules and state&lt;/h3&gt;
&lt;p&gt;While Lua has some lisp characteristics, it is understandably not an actual lisp.
So, unfortunately, we can&amp;rsquo;t expect the same level of interactivity from it.&lt;/p&gt;
&lt;p&gt;In Lua, a module is an ordinary table.
When you write Lua, you return the value at the bottom of the file, usually a table, or sometimes a function.
Any local variables, defined in that module are locals, stored as closures for the functions that reference them in the exported value.&lt;/p&gt;
&lt;p&gt;Because of that, there&amp;rsquo;s no such thing as &lt;em&gt;entering a module&lt;/em&gt; like in many other lisps.
The REPL has its own kind of module space, where all locals, defined in the REPL are stored.
The same goes for any code that we send to the REPL.
So, while we do have a REPL, we can&amp;rsquo;t enter a specific module and change it partially - the only way to do that is to recompile the module and put the updated version in the &lt;code&gt;package.loaded&lt;/code&gt; table.
Which we can do.&lt;/p&gt;
&lt;p&gt;However, there&amp;rsquo;s another problem lurking around - state.
The video above shows that the error message was:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./game.fnl:68: attempt to index upvalue &amp;#39;world&amp;#39; (a nil value)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When we&amp;rsquo;ve recompiled the module, &lt;code&gt;world&lt;/code&gt; became &lt;code&gt;nil&lt;/code&gt;, why?
Well, because &lt;code&gt;world&lt;/code&gt; is defined as a &lt;code&gt;nil&lt;/code&gt;, and later set in the &lt;code&gt;love.load&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; ---- 8&amp;lt; ----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.load&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bump.newWorld&lt;/span&gt; 64))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;each &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;pairs &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;level&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall.x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall.y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall.width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall.height&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;player&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;player.x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;player.y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;player.width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;player.height&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, the &lt;code&gt;love.load&lt;/code&gt; runs only when the game starts, and hence after recompiling the module, &lt;code&gt;world&lt;/code&gt; becomes &lt;code&gt;nil&lt;/code&gt; again, and our game doesn&amp;rsquo;t really expect that.
The same would happen to any other state we&amp;rsquo;re setting up when the game loads.&lt;/p&gt;
&lt;p&gt;Unfortunately, Fennel doesn&amp;rsquo;t have a &lt;code&gt;defonce&lt;/code&gt; or anything like it.
The &lt;code&gt;defonce&lt;/code&gt; macro is available in many lisps, and its purpose is to ensure that when we&amp;rsquo;re redefining something in the REPL or re-evaluating the whole module/namespace/package (whatever you guys call it) the value doesn&amp;rsquo;t get redefined.
Fennel lacks this because there&amp;rsquo;s no way of doing this in Lua, because of how locals are stored (as closed variables).&lt;/p&gt;
&lt;p&gt;But there&amp;rsquo;s a way around this, we can move the definitions to another module, and use &lt;code&gt;require&lt;/code&gt; to load them.
In Lua &lt;code&gt;require&lt;/code&gt; caches everything it loads, so when we run &lt;code&gt;require&lt;/code&gt; again, it doesn&amp;rsquo;t really do anything except get the value from the &lt;code&gt;package.loaded&lt;/code&gt; table.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how we can define the &lt;code&gt;world&lt;/code&gt; module:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bump&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;require &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lib.bump&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bump.newWorld&lt;/span&gt; 64)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;Code Snippet 1:&lt;/span&gt;
  &lt;code&gt;state/world.fnl&lt;/code&gt;
&lt;/div&gt;
&lt;p&gt;That&amp;rsquo;s it.
Now, we can bring it to the main game module using &lt;code&gt;require&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;require &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:state.world&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This way, when we recompile the module, we get the same &lt;code&gt;world&lt;/code&gt; as before, unless we were to recompile the &lt;code&gt;world&lt;/code&gt; module.&lt;/p&gt;
&lt;p&gt;I moved most of the game state in such modules, and now we can use our REPL.&lt;/p&gt;
&lt;h2 id=&#34;using-the-repl&#34;&gt;Using the REPL&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s an example of tweaking the player&amp;rsquo;s motion speed again:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2024-09-08-interactive-game-development-with-love/repl-work.webm&#34; type=&#34;video/webm&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m sending the code to the REPL, instead of reloading the module, just because it&amp;rsquo;s a bit more convenient.
This way tweaking the game is much nicer and frictionless, although it doesn&amp;rsquo;t reach the same heights as that one video from &lt;a href=&#34;https://www.youtube.com/watch?v=EGqwXt90ZqA&#34; target=&#34;_blank&#34;&gt;Bret Victor&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s me using a REPL to make an ad-hoc level editor:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2024-09-08-interactive-game-development-with-love/level-editor.webm&#34; type=&#34;video/webm&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately, there&amp;rsquo;s no way of using the REPL on Android, since there&amp;rsquo;s no way of running LÖVE from the same environment as Emacs, without installing X11 and running everything through Termux.
Probably doable, but I don&amp;rsquo;t want to go this route.
Android development is more backup route anyway, since I have access to my PC again.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Interactive game development with LÖVE&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 08 Sep 2024 21:00:00 +0300</pubDate>
    </item><item>
      <title>Boredom and gamedev</title>
      <link>https://andreyor.st/posts/2024-09-08-boredom-and-gamedev/</link>
      <guid>https://andreyor.st/posts/2024-09-08-boredom-and-gamedev/</guid>
      <description>&lt;p&gt;I spent the previous ten days on vacation.
Usually, I try to go off once or twice a year to somewhere where I can just passively relax - usually, it is some sea resort.
This year I decided to go to the Republic of Türkiye and spend my time at the beach without any major attractions.
The problem is - I get bored pretty quickly and my brain wants to do something.&lt;/p&gt;
&lt;p&gt;I took with me my trusty Nintendo 2DS in case I have an urge to spend some time looking at the screen and to get myself occupied on the plane, and a phone with some books to read while I&amp;rsquo;m lying on the beach.
However, my phone is also my computer, and I do a lot of coding on it in my spare time, usually when I don&amp;rsquo;t have access to a proper PC.&lt;/p&gt;
&lt;p&gt;The last time I went on such a vacation I got so bored, that I decided that I wanted to do some game dev, and started a &lt;a href=&#34;https://andreyor.st/posts/2023-06-09-gamedev-plans/&#34;&gt;personal game dev marathon&lt;/a&gt;.
Originally, I planned to start once I got back from vacation, but I was so eager that I &lt;a href=&#34;https://andreyor.st/posts/2023-06-30-game1/&#34;&gt;started early&lt;/a&gt;, while I was still at the beach.
The marathon was a crunch, and I had mixed feelings about it in the end, which ultimately led to burnout, and I put the idea of making games on the shelf for a while.
And while the last time I started doing this I only drew some sprites, the only reason for that was that I couldn&amp;rsquo;t get any game engine on my phone.
This time around, I got so bored that I started programming a game while gradually getting sunburns and taking breaks to go and actually swim in the sea.&lt;/p&gt;
&lt;h2 id=&#34;making-games-on-android&#34;&gt;Making games on Android&lt;/h2&gt;
&lt;p&gt;Basically, if the only thing you have is a phone you have two main options - &lt;a href=&#34;https://tic80.com/&#34; target=&#34;_blank&#34;&gt;TIC-80&lt;/a&gt; and &lt;a href=&#34;https://love2d.org/&#34; target=&#34;_blank&#34;&gt;löve2d&lt;/a&gt;.
tic has everything you need - an integrated code editor, a sprite editor, a map editor, and even a sound editor if you&amp;rsquo;re that versatile.
however, the experience of using TIC for doing everything is not great, especially on the phone.
I mean, that&amp;rsquo;s what you have to deal with:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2024-09-08-boredom-and-gamedev/TIC-80.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Not a lot of screen space to view the code, the keyboard is abysmal, and the editor experience itself has a lot to be desired.
Yes, it is authentic, I get it, it&amp;rsquo;s just not what I&amp;rsquo;m personally after.&lt;/p&gt;
&lt;p&gt;On PC you can actually get a PRO version of TIC-80, which allows you to write a game in an external editor, and load it into the engine.
Technically, you could do the same on Android, but there&amp;rsquo;s a problem - I use Android 14, which has storage restrictions for apps.
And TIC-80 can&amp;rsquo;t access anything except files in its directory stored at &lt;code&gt;/sdcard/Android/data/com.nesbox.tic80/&lt;/code&gt;.
Which can&amp;rsquo;t be accessed directly on the phone either - you need a PC to access it.
So even if you have a separate text editor, you can&amp;rsquo;t do your game development with TIC on Android.
Moreover, you can&amp;rsquo;t even get your game out of the engine unless you have a PC at hand.&lt;/p&gt;
&lt;p&gt;The other option, as I said, is LÖVE2D.
It has the same problem as TIC, as you can&amp;rsquo;t launch the game from anywhere but &lt;code&gt;/sdcard/Android/data/org.love2d.android/&lt;/code&gt;, however, newer versions have a separate dedicated launcher, that can load &lt;code&gt;.love&lt;/code&gt; files from anywhere on the filesystem, which is good enough.
Alternatively, an older version, like 11.3 can be installed that bypasses the sandboxing restrictions.
So that was the route I took.&lt;/p&gt;
&lt;h3 id=&#34;making-games-on-android-with-löve&#34;&gt;Making games on Android with LÖVE&lt;/h3&gt;
&lt;p&gt;I have little experience with LÖVE2D.
Previously, I did a bunch of tests with it and made a few demos like the one described in my &lt;a href=&#34;https://andreyor.st/posts/2020-10-15-raymarching-with-fennel-and-love/&#34;&gt;raymarching post&lt;/a&gt;, or the &lt;a href=&#34;https://gitlab.com/andreyorst/love-fabrik&#34; target=&#34;_blank&#34;&gt;F.A.B.R.I.K.&lt;/a&gt; algorithm I implemented back in the day.
So nothing major.
The raymarching demo barely runs on a PC, and there&amp;rsquo;s no way to control it on the phone without connecting a gamepad.
Unfortunately, I had no gamepad with me this time, so if I wanted to make a game on the phone I had to implement one myself.
Fortunately, I have a lot of experience playing games with the on-screen gamepad, so I&amp;rsquo;m at least well accustomed to the idea.&lt;/p&gt;
&lt;p&gt;I had no idea how to interact with the touch screen though, so I found a drop-in gamepad implementation for LÖVE2D in the &lt;a href=&#34;https://github.com/DeybisMelendez/game-tools/blob/90690b864e3d3b0ffeec66d04c1956198e383abf/lovepad.lua&#34; target=&#34;_blank&#34;&gt;game-tools repository&lt;/a&gt;:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2024-09-08-boredom-and-gamedev/lovepad.png&#34;
         alt=&#34;Figure 1: lovepad.lua&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 1: &lt;/span&gt;&lt;code&gt;lovepad.lua&lt;/code&gt;&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Still, I wanted this gamepad to be a bit more advanced, with analog stick imitation, and more buttons, so I ported it to Fennel first and then extended it with more features:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted class=&#34;uninvertable&#34;&gt;&lt;source src=&#34;https://andreyor.st/2024-09-08-boredom-and-gamedev/gamepad.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;img src=&#34;https://andreyor.st/2024-09-08-boredom-and-gamedev/gamepad.png&#34; title=&#34;Your browser does not support the &lt;video&gt; tag&#34;/&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;It has all of the buttons of a modern controller, so I could share the control scheme between the on-screen gamepad and a real gamepad.
I do understand that the on-screen gamepad should, ideally, be tailored around a game, but this will suffice for now.
It was fun to implement this too, and I found a small bug in the &lt;code&gt;lovepad.lua&lt;/code&gt; file, while I was porting it.&lt;/p&gt;
&lt;p&gt;Next, I added the &lt;a href=&#34;https://github.com/kikito/bump.lua&#34; target=&#34;_blank&#34;&gt;bump.lua&lt;/a&gt; library for basic physics (because I don&amp;rsquo;t want to deal with box2d yet), and made a simple player controller:&lt;/p&gt;
&lt;figure class=&#34;uninvertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2024-09-08-boredom-and-gamedev/player-controller.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;As you can see, I&amp;rsquo;m using Emacs on the phone, with the Google Keyboard set to PC QWERTY layout - a neat feature.
This is my phone setup for programming, and I&amp;rsquo;m actually using the same configuration as on my regular PC.&lt;/p&gt;
&lt;p&gt;After adding a &lt;a href=&#34;https://github.com/kikito/gamera&#34; target=&#34;_blank&#34;&gt;camera library&lt;/a&gt; from the author of &lt;code&gt;bump.lua&lt;/code&gt;, here&amp;rsquo;s what the player controller looks like at the moment:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted class=&#34;uninvertable&#34;&gt;&lt;source src=&#34;https://andreyor.st/2024-09-08-boredom-and-gamedev/player-controller.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;I want to tweak this player-controller a bit further, making it more fleshed out, but as you can see it already handles a few things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Direction facing is tracked based on horizontal velocity&lt;/li&gt;
&lt;li&gt;Jumping
&lt;ul&gt;
&lt;li&gt;Holding the jump button longer increases the jump height&lt;/li&gt;
&lt;li&gt;Bumping against a ceiling resets the vertical velocity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Crouching and crawling
&lt;ul&gt;
&lt;li&gt;When crouched, the player&amp;rsquo;s height is reduced, and when crawling the width is increased&lt;/li&gt;
&lt;li&gt;When crawling into a narrow space, the player changes to the crouched state if no direction input is given.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The camera follows the player
&lt;ul&gt;
&lt;li&gt;Camera pans in the direction of movement, showing more of the upcoming level&lt;/li&gt;
&lt;li&gt;Vertical position only changes when the player is grounded, or when the vertical position is lower than the original camera position&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I still need to tweak various speed values and add more movement options like dashing, sliding, etc., but it already feels &lt;em&gt;gameish&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Writing a player controller was the most challenging thing before when I &lt;a href=&#34;https://andreyor.st/posts/2023-07-17-game1-w34/&#34;&gt;made the first demo game&lt;/a&gt; in the marathon.
I made this one similar to the previous one, as can be seen in &lt;a href=&#34;http://andreyor.st/posts/2023-07-22-game1-w34-again/%20&#34; target=&#34;_blank&#34;&gt;further GAME1 demos&lt;/a&gt;, but it&amp;rsquo;s a complete rewrite, as I wanted to make it differently this time.
We&amp;rsquo;ll see how it evolves over time.&lt;/p&gt;
&lt;h3 id=&#34;drawing&#34;&gt;Drawing&lt;/h3&gt;
&lt;p&gt;While I didn&amp;rsquo;t draw anything for this game, I have a few updates on how I approach drawing on the phone.
In short, I ditched the &lt;a href=&#34;https://play.google.com/store/apps/details?id=com.PixelStudio&#34; target=&#34;_blank&#34;&gt;PixelStudio&lt;/a&gt; I&amp;rsquo;ve talked about in the &lt;a href=&#34;https://andreyor.st/posts/2023-06-30-game1/&#34;&gt;first post&lt;/a&gt; about GAME1 mainly because its UX doesn&amp;rsquo;t work for me personally.
It&amp;rsquo;s still a good app for pixel art, I just don&amp;rsquo;t like how it works, and it lacks some features I&amp;rsquo;d like to have.&lt;/p&gt;
&lt;p&gt;Fortunately, there exists a better option - &lt;a href=&#34;https://krita.org/en/&#34; target=&#34;_blank&#34;&gt;Krita&lt;/a&gt; which has a &lt;a href=&#34;https://play.google.com/store/apps/details?id=org.krita&amp;amp;hl=en_US&#34; target=&#34;_blank&#34;&gt;port for Android&lt;/a&gt; that doesn&amp;rsquo;t compromise any features, so you get a full Krita experience.
It&amp;rsquo;s probably better suited for Android tablets, but works well enough for me on the phone.
I&amp;rsquo;m slowly learning pixel art, and here&amp;rsquo;s a timelapse of me drawing a tree on my phone:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted width=&#34;50%&#34;&gt;&lt;source src=&#34;https://andreyor.st/2024-09-08-boredom-and-gamedev/krita.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the &lt;video&gt; tag&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;I made a few mistakes when using various tools, as I was not well accustomed to Krita&amp;rsquo;s toolset back then.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the final result after a bit of refinement:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2024-09-08-boredom-and-gamedev/pixelart.png&#34; width=&#34;100%&#34; height=&#34;auto&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;This isn&amp;rsquo;t a drawing for the game I&amp;rsquo;m making, just a sketch, following the principles outlined in this &lt;a href=&#34;https://www.youtube.com/watch?v=uFnL5X_GrmE&#34; target=&#34;_blank&#34;&gt;amazing video&lt;/a&gt; by Brandon James Greer.
But one thing that makes a difference when making games for LÖVE2D and not for TIC-80 is the unrestricted palette.
It&amp;rsquo;s still better to restrict the palette when making pixel art, but using only 16 colors for the entirety of game graphics is too restrictive for me.
Especially right now.&lt;/p&gt;
&lt;p&gt;One thing I haven&amp;rsquo;t tried yet is animating.
PixelStudio had a decent animation pipeline, and it was possible to export the animation as a sprite-sheet.
Still need to experience this in Krita - I know it has animation capabilities, but I&amp;rsquo;m not sure if they&amp;rsquo;ll be comfortable to use on the phone or not.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll be making more pixel art for this game I&amp;rsquo;m making in the future, so I&amp;rsquo;ll post actual images once I have anything more to share!&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Boredom and gamedev&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 08 Sep 2024 00:34:00 +0300</pubDate>
    </item><item>
      <title>Game4 and Autumn Lisp Game Jam</title>
      <link>https://andreyor.st/posts/2023-10-19-game4-and-autumn-lisp-game-jam/</link>
      <guid>https://andreyor.st/posts/2023-10-19-game4-and-autumn-lisp-game-jam/</guid>
      <description>&lt;p&gt;You might be wondering why there were no posts on the game development marathon I&amp;rsquo;ve been doing.
Maybe you&amp;rsquo;d thought that I gave up after the admittedly underwhelming game3 having no actual game just some basic movement.
And yeah, I felt burned up a lot, and considered skipping a month maybe - but then &lt;a href=&#34;https://itch.io/jam/autumn-lisp-game-jam-2023&#34; target=&#34;_blank&#34;&gt;this happened&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So I thought - well, I just make the game during the game jam instead, and rest up until the jam begins.
Yes, it means I will technically have less time to do this, but I did spend even less time on game dev last month, so it&amp;rsquo;s fine.
I also got an unplanned vacation, so I guess I&amp;rsquo;ll actually have free time too.&lt;/p&gt;
&lt;p&gt;Though, I lied a bit.
The other reason I didn&amp;rsquo;t do anything is also because the next genre I wanted to work in is a puzzle platformer.
And honestly, I don&amp;rsquo;t know what kind of puzzles to make.
None seem appealing.&lt;/p&gt;
&lt;p&gt;So after a bit of consideration, I&amp;rsquo;ve decided that can try to make something like a &lt;a href=&#34;https://en.wikipedia.org/wiki/Lode_Runner&#34; target=&#34;_blank&#34;&gt;Lode Runner&lt;/a&gt; type of game.
I already have the platformer engine from the very first game in this series, and originally I&amp;rsquo;ve planned that I would make a really simple 2D platformer, then in the subsequent game I will refine and improve it.
Similarly, with the top-down games - first make a simple dungeon crawler, then take the blueprint and make an adventure with it.
Unfortunately, the second game was a flop, and thus if I am to make the fifth game I&amp;rsquo;ll have to do everything from scratch.&lt;/p&gt;
&lt;p&gt;So I&amp;rsquo;ve been thinking how I should handle the game.
I guess I&amp;rsquo;m going to ditch the camera here, so the level fits the screen.
It will make it a bit easier to reason about, and I guess I can always add camera back later if I really need to.&lt;/p&gt;
&lt;p&gt;AI would be an issue though - I&amp;rsquo;ll need to implement some kind of path-finding for the 2D grid with gravity in mind.
In other words, enemies should understand that they can jump down from cliffs if it will bring them on the same elevation with the player.
Additionally, enemies shouldn&amp;rsquo;t just follow the shortest path to the player, as it will make them very predictable.&lt;/p&gt;
&lt;p&gt;And if I have time, I can try putting on a twist to the formula.
Not sure what kind of twist yet, but we&amp;rsquo;ll see I guess.&lt;/p&gt;
&lt;p&gt;The jam starts in ~12 hours, which unfortunately means that it will begin while my work week isn&amp;rsquo;t yet ended.
So I will have one day less already.
Additionally, right now I&amp;rsquo;m in another city, and will lose another day on train to get back home.
So this leaves me with 8 days instead of 10.&lt;/p&gt;
&lt;p&gt;Hopefully it will not be an issue.
Wish me luck!&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game4 and Autumn Lisp Game Jam&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 19 Oct 2023 18:42:00 +0300</pubDate>
    </item><item>
      <title>Game3 - Results</title>
      <link>https://andreyor.st/posts/2023-10-01-game3-results/</link>
      <guid>https://andreyor.st/posts/2023-10-01-game3-results/</guid>
      <description>&lt;p&gt;I gave myself 1 extra day on this game because in total I was only able to work on this game for 5 days, two of which were on the train.
So this game is now done, although I couldn&amp;rsquo;t make any sounds for it.
Designing explosion and blaster sounds that sound good is hard.
The game isn&amp;rsquo;t really complete, and you get practically invincible once you get 3 power-ups.
As wasn&amp;rsquo;t able to do much this time, so a lot of sprites are left unused.
Anyhow, here&amp;rsquo;s the game:&lt;/p&gt;
&lt;iframe src=&#34;https://itch.io/embed-upload/8798744?color=3e3c57&#34;
        allowfullscreen=&#34;&#34;
        width=&#34;600&#34;
        height=&#34;320&#34;
        frameborder=&#34;0&#34;
        style=&#34;margin-left: auto; margin-right: auto; display: block;&#34;&gt;
  &lt;a href=&#34;https://andreyorst.itch.io/game3-shoot-em-up&#34;&gt;Play Game3 - Shoot &#39;Em Up on itch.io&lt;/a&gt;
&lt;/iframe&gt;
&lt;p&gt;Since the last post, I changed a lot.
First, &lt;code&gt;bump&lt;/code&gt; is back and all collisions are handled through it again.&lt;/p&gt;
&lt;p&gt;I made some more weapons, the default one has a rapid-fire rate, but low damage:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted class=&#34;pixelart&#34;&gt;&lt;source src=&#34;https://andreyor.st/2023-10-01-game3-results/game.webm&#34; type=&#34;video/webm&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;There are three more weapons - laser gun, magic gun, and rocket gun.
Each of these has different damage values.
Originally I planned to implement the overheat mechanic, but ran out of time and passion to do that.&lt;/p&gt;
&lt;p&gt;It was fun implementing the flame that appears when the ship is taken down.
It is done as a particle effect, as the ship simply constantly emits flame particles when burning, and they get removed once their animation ends.
Similar to how the bullets interact with enemies.&lt;/p&gt;
&lt;p&gt;If you want to download this game, here&amp;rsquo;s the cartridge:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-10-01-game3-results/cart.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;The next game on my list is a puzzle platformer.
For now, I&amp;rsquo;m not sure if I will have time or passion to do it, and I honestly don&amp;rsquo;t know what types of puzzles should it have.
We&amp;rsquo;ll see.
I already have a pretty decent engine for a platforming game, so it&amp;rsquo;s a good time to refine it.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game3 - Results&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 01 Oct 2023 17:12:00 +0300</pubDate>
    </item><item>
      <title>Game3 w2/3</title>
      <link>https://andreyor.st/posts/2023-09-24-game3-w23/</link>
      <guid>https://andreyor.st/posts/2023-09-24-game3-w23/</guid>
      <description>&lt;p&gt;Another week passed, but I didn&amp;rsquo;t manage to squeeze out much spare time to make any significant progress with the game.
Not like I didn&amp;rsquo;t do anything, but the game is far from being playable.
This week I, unfortunately, could spend only a single day working on a game, because every day after work I had some personal stuff to take care of, which took all of my after-work hours.
But it doesn&amp;rsquo;t matter, the challenge is a challenge!
Hopefully, the next week will be a bit less busy.
Although the stuff happening right now is very exciting and very important, so if the next week is busy again - so be it.&lt;/p&gt;
&lt;p&gt;Anyway, here&amp;rsquo;s the progress so far:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted class=&#34;pixelart&#34;&gt;&lt;source src=&#34;https://andreyor.st/2023-09-24-game3-w23/game.webm&#34; type=&#34;video/webm&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a prototype.
I&amp;rsquo;m experimenting with enemy patterns, like a simple sine wave, or tracking enemies.
No collision has been implemented yet.
This is my plan for the next and final week.
As well as doing more animation, as the ship is just a cardboard right now, making weapons work, and not just fly with you, and implementing a scoring system.
Probably that&amp;rsquo;s the most I&amp;rsquo;ll be able to do.&lt;/p&gt;
&lt;p&gt;Another thing I want to look into is rotating sprites, as I want to spawn meteorites semi-randomly after some time passes in the game, so the game becomes harder.
These meteorites will shatter, and smaller parts will also damage the player, making it harder to maneuver.
But that&amp;rsquo;s probably the least prioritized thing as of this moment.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game3 w2/3&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 24 Sep 2023 20:55:00 +0300</pubDate>
    </item><item>
      <title>Game3 W?/4</title>
      <link>https://andreyor.st/posts/2023-09-16-game3-w4/</link>
      <guid>https://andreyor.st/posts/2023-09-16-game3-w4/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m working on the next game, although I gave myself an extended period of rest.
After failing to complete the last one I needed to distract myself a bit from this activity, so I worked a bit on Fennel stuff, played some games, and I think I&amp;rsquo;m back in business by now.
I have an interesting thing going on with my productivity - it comes in waves.
What I mean is that I can go onto programming frenzy for several months, and then once I feel burned out, I can just play games for another full month straight.
Though I get tired of games too, and if by that time I feel that I&amp;rsquo;m not ready for programming yet, I can read some technical books, or even just some manga if I still feel too tired to be productive.&lt;/p&gt;
&lt;p&gt;So this five month marathon is a bit hard for me, as I basically have to give up on long periods of rest, and juggle my free time to actually have some time to work on these projects.
While these games are nothing special, I feel like I&amp;rsquo;m still learning new stuff, and thus this is beneficial for me still.
Though, at some I actually thought of dropping the whole idea, and starting a more complex project that I was thinking about for a lot of time already.
But I decided to leave it for the next year, as I still need a lot to learn.
But, back on the topic.&lt;/p&gt;
&lt;p&gt;This post actually marks the end of only the second week of the current game.
How come, you might ask?
To put it simply, I miscalculated a bit, and in reality I had another week on the previous game by the time I dropped it.
So, technically, I could probably finish that game, but the burnout got me, so that&amp;rsquo;s that.&lt;/p&gt;
&lt;p&gt;As for this game, I have a little to show.
As it is a side-scrolling shooter, I designed a basic ship with some shooting modules, and some powerup icons.
I considered to not making any graphics for this one, and doing everything with just primitives, like triangles, circles and so on, but after trying to draw a ship like this I dropped the idea and returned to Pixel Studio.
Here are the results so far:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-09-16-game3-w4/sprites.png&#34; width=&#34;100%&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;The ship turned out to be a bit too big, but I decided that I can make a game with larger assets for a change.
So the enemy also uses 4 sprites, instead of just one, as in my previous games.&lt;/p&gt;
&lt;p&gt;And here are the enemies animated:&lt;/p&gt;
&lt;div class=&#34;grid-gallery&#34;&gt;
  &lt;div class=&#34;grid-gallery-row&#34; style=&#34;display: flex&#34;&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-09-16-game3-w4/roaming.gif&#34; width=&#34;40%&#34; height=&#34;auto&#34;/&gt;
&lt;/figure&gt;

&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-09-16-game3-w4/roaming-2.gif&#34; width=&#34;40%&#34; height=&#34;auto&#34;/&gt;
&lt;/figure&gt;

&lt;/div&gt;
&lt;figcaption&gt;
  &lt;p&gt;Movement animations&lt;/p&gt;
&lt;/figcaption&gt;
&lt;div class=&#34;grid-gallery-row&#34; style=&#34;display: flex&#34;&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-09-16-game3-w4/exploding.gif&#34; width=&#34;40%&#34; height=&#34;auto&#34;/&gt;
&lt;/figure&gt;

&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-09-16-game3-w4/explosion-2.gif&#34; width=&#34;40%&#34; height=&#34;auto&#34;/&gt;
&lt;/figure&gt;

&lt;/div&gt;
&lt;figcaption&gt;
  &lt;p&gt;Explosion animations&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/div&gt;
&lt;p&gt;Obviously, I need to add more enemy variety, with different patterns, but designing enemies is hard.
BTW, if you&amp;rsquo;re curious how I draw things on the phone, here&amp;rsquo;s a time-lapse:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop&gt;&lt;source src=&#34;https://andreyor.st/2023-09-16-game3-w4/timelapse.webm&#34; type=&#34;video/webm&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Though, I usually don&amp;rsquo;t do it in the landscape mode, portrait mode works better for me, especially with a stylus.
This process was recorded in landscape just for viewing convenience.&lt;/p&gt;
&lt;p&gt;On the technical side of things, I already implemented a basic movement with linear interpolation for the flying modules, and implemented some enemy patterns, but there&amp;rsquo;s no actual interactions yet.
I&amp;rsquo;m kinda torn on the idea of including &lt;code&gt;bump.lua&lt;/code&gt; again, as I feel like that this game can be done without any collision library.
At the same time, having a collision library may make things much simpler, so I&amp;rsquo;m still thinking how to approach this game.&lt;/p&gt;
&lt;p&gt;For the &lt;em&gt;record&lt;/em&gt;, I basically dropped the idea of making &lt;em&gt;any&lt;/em&gt; kind of music for these games because I just can&amp;rsquo;t get myself to work on it.
I do plan to take some courses on music composition for future projects, though.
Sound effects are challenging enough already by themselves.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for this week!
Hopefully, I&amp;rsquo;ll manage to finish the game this time, though I already lost one week.
Let&amp;rsquo;s say, this is week 1/3 instead of 2/4 shall we?
Feels less demotivating this way.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game3 W?/4&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sat, 16 Sep 2023 01:59:00 +0300</pubDate>
    </item><item>
      <title>Game2 W4/4</title>
      <link>https://andreyor.st/posts/2023-08-25-game2-w44/</link>
      <guid>https://andreyor.st/posts/2023-08-25-game2-w44/</guid>
      <description>&lt;p&gt;Well, It&amp;rsquo;s unfortunate, but I couldn&amp;rsquo;t make the game in these 4 weeks.
August is just too much of a pain in terms of the amount of different events - maybe even the busiest month in the whole year, for me personally.
Judging by the commit history, I was able to work only for 11 days out of the 28 days given to me by the challenge - and I tried to do at least some work every day and commit everything I did.
I&amp;rsquo;m saying 11 days, but maybe 5 of these were in this last week.&lt;/p&gt;
&lt;p&gt;This last week was all about level generation and, unfortunately, I failed at it.
I was trying to implement the &lt;a href=&#34;https://andreyor.st/posts/2022-05-10-wave-function-collapse-algorithm-in-clojurescript/&#34;&gt;Wave Function Collapse&lt;/a&gt; algorithm in Lua and for some weird reason, it didn&amp;rsquo;t work.
After three failed attempts, I decided to cheat.
My idea was to go and port my ClojureScript version to Fennel form by form and compile it to Lua after it works.
However, it didn&amp;rsquo;t work as well, no idea why.
For some reason, some branches in my code are just never visited at all, although I did everything the same way, and implemented missing pieces from Clojure&amp;rsquo;s standard library for this code to work.
At least it terminated, but instead generated a complete gibberish:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt; (wfc (gen_world 9 9) coast)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[[&amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟦&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟦&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟩&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟫&amp;#34;]]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is supposed to look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&amp;gt; (wfc (gen-world 9 9) coast)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[[&amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟩&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟦&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟫&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟩&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34; &amp;#34;🟦&amp;#34;]]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This reminded me of the importance of data structures and their properties I keep forgetting when programming in Clojure.
Because in Clojure it&amp;rsquo;s just the thing you have, so you don&amp;rsquo;t think much about it.&lt;/p&gt;
&lt;p&gt;You see, Clojure has 4 main data structures, baked up with literals: list &lt;code&gt;(a, b)&lt;/code&gt;, map &lt;code&gt;{k1 a, k2 b}&lt;/code&gt;, vector &lt;code&gt;[a, b]&lt;/code&gt;, and set &lt;code&gt;#{a, b}&lt;/code&gt;.
Each of these has its own set of properties, for example, lists are only fast to add elements at the front, and vectors are fast to add elements to the tail.
Maps are mostly like Lua&amp;rsquo;s tables, and sets are like maps in the way that they can only store unique elements, and are indexed like a map but iterated like a list.&lt;/p&gt;
&lt;p&gt;In my ClojureScript implementation of the WFC algorithm, I used all these data structures and relied on their behavior.
For example, the superposition for a cell after the world&amp;rsquo;s initialization is a set of all possible values for the cell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I used maps to store the recipe:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:up&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:down&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:left&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:right&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:up&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:down&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:left&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:right&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:up&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:down&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:left&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:right&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;}}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The map itself stores maps with sets that are later used in the algorithm.
Other data structures are at play for other parts of the whole process, but I&amp;rsquo;m not going to touch them here.&lt;/p&gt;
&lt;p&gt;Lua on the other hand has only one collection type - the table.
It can serve as a vector, to which you can add elements at the tail, and you can use them as hash tables, where there can only be a single instance of a given key.
Sets can also be represented if we just use a table where keys are elements and values are the same elements or something like &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; superposition = {[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is actually what the &amp;ldquo;Programming in Lua&amp;rdquo; book &lt;a href=&#34;http://www.lua.org/pil/11.5.html&#34; target=&#34;_blank&#34;&gt;suggests&lt;/a&gt;.
The recipe then looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- Sorry, not sorry for formatting - all these brackets on separate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- lines take a stupidly big amount of vertical space&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;]={up={[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         down={[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         left={[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         right={[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;}},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;]={up={[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         down={[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         left={[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         right={[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;}},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;]={up={[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         down={[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         left={[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         right={[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;}}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- also, the table syntax is just horrible - why square brackets are&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- needed around strings for keys? Why can&amp;#39;t we write {&amp;#34;foo bar&amp;#34;=&amp;#34;baz&amp;#34;}?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- And why can we write {foo=&amp;#34;bar&amp;#34;}? Why variable foo is not the same&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- foo when used in the table? Why foo is now a string?  The syntax is&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- too smart for its own good.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, here&amp;rsquo;s the problem - how do we tell apart sets from key-value tables?
We can write some predicates, like &lt;code&gt;is_set&lt;/code&gt; that either check that all values are &lt;code&gt;true&lt;/code&gt;, or create a constructor function that will add a hidden &lt;code&gt;__index&lt;/code&gt; metatable with a &lt;code&gt;is_set&lt;/code&gt; key set to true, but it&amp;rsquo;s all pretty janky, in my opinion at least.
A proper data structure should have its own syntax literal and a set of functions to check the type.
Lua doesn&amp;rsquo;t even give you the ability to distinguish sequential tables from associative ones&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.
I don&amp;rsquo;t think that Clojure&amp;rsquo;s choice of &lt;code&gt;#{}&lt;/code&gt; for sets is great, but it&amp;rsquo;s a lot better than nothing.&lt;/p&gt;
&lt;p&gt;But there&amp;rsquo;s also another issue with our implementation of sets - iteration support.
In Clojure, you can iterate over any type of data structure, and it will actually do it in a meaningful way.&lt;/p&gt;
&lt;p&gt;If you try to iterate over a list, vector, or set - it will just iterate over the elements:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map identity &lt;/span&gt;&amp;#39;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:b&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:c&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:b&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:c&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map identity &lt;/span&gt;[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:b&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:c&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:b&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:c&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map identity &lt;/span&gt;#{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:b&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:c&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:b&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:c&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the case of a set the order is not determined, so the order of results is arbitrary.
If you try to iterate over a map though, it&amp;rsquo;s a bit different:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map identity &lt;/span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;b&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:c&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;d&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:e&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;f&amp;#34;&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;([&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:c&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;d&amp;#34;&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;b&amp;#34;&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:e&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;f&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Same as for the set, the order is arbitrary, but you can see that the elements in the list are vectors.
That&amp;rsquo;s right, when we iterate over the map we get back vectors, containing the key and its value, which we can then use in the function that we iterate with.&lt;/p&gt;
&lt;p&gt;You may be thinking: &amp;ldquo;Well, that&amp;rsquo;s the same as what &lt;code&gt;pairs&lt;/code&gt; does in Lua&amp;rdquo; but it&amp;rsquo;s not.
Unlike what I have shown to you, &lt;code&gt;pairs&lt;/code&gt; will &lt;strong&gt;always&lt;/strong&gt; return the key and value, even for vectors.
Yes, in the case of a vector, the key will be an index, and we can pretty much ignore it most of the time, but what about our sets?
In the case of our set implementation, the key is actually the value we&amp;rsquo;re looking for, because the value is just &lt;code&gt;true&lt;/code&gt;.
So no, implementing sets as tables that store &lt;code&gt;true&lt;/code&gt; as a value is a no-go for most use cases, we have to store the value both as a key and a value in a set:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; superposition = {[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;, [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;]=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But I digress.&lt;/p&gt;
&lt;p&gt;Another, very important property of Clojure&amp;rsquo;s data structures is that they&amp;rsquo;re both immutable and persistent.
This means that whatever we do with the vector doesn&amp;rsquo;t actually change the vector - it returns a new vector that shares the unchanged part of the structure with the old one plus new stuff.
Clojure author went to great lengths to make this process fast and reliable.&lt;/p&gt;
&lt;p&gt;I used this heavily in the CLJS version of the algorithm.
Perhaps too heavily, but it&amp;rsquo;s a different topic.
What it gave me though is the ability to change the world without mutating the original world, so every step of the algorithm actually produced a new world, and I could trace it back to the very beginning if I wanted to.
It is not as fast as the mutation-based approach but is much more sane to work with and debug.&lt;/p&gt;
&lt;p&gt;My first implementation of the algorithm in Lua, however, was mutating the world.
Not only it is hard to debug, Lua makes it harder because you can&amp;rsquo;t view the data structure you&amp;rsquo;re working with.
You probably don&amp;rsquo;t remember it, but I made a &lt;a href=&#34;https://andreyor.st/posts/2021-01-09-pretty-printing-for-fennel-language/&#34;&gt;complete rewrite&lt;/a&gt; of the pretty printer for the Fennel language, and I did it mostly because the original one produced the representation that was hard to read due to indentation going all over the place.
Well, guess what, Lua doesn&amp;rsquo;t have its own pretty printer whatsoever.
You have to write your own or import some library that does it for you, which is not feasible with TIC-80, as its screen resolution is too small to comfortably read anything, especially huge tables that contain lots of elements, like the world I was trying to generate.
Can you feel my frustration?&lt;/p&gt;
&lt;p&gt;Then I made a hacky &lt;code&gt;deepcopy&lt;/code&gt; function (another part that lacks from Lua because &lt;em&gt;tables&lt;/em&gt;&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;) to at least get a copy-on-write type of immutability in Lua.
This slowed down things to the point that it was useless for the sizes of worlds I wanted to construct.
And it didn&amp;rsquo;t fix the problem, so it was somewhere else.
I wasn&amp;rsquo;t ready to re-implement the whole thing again, so I stopped here.&lt;/p&gt;
&lt;p&gt;Another thing I keep forgetting is how great Clojure&amp;rsquo;s standard library for manipulating collections is.
There are all sorts of operations on sets, you can transform maps, iterate on anything, rename keys, etc., etc.
Lua has a very rudimentary library for tables, that can&amp;rsquo;t do almost anything.
Sure, there are libraries like &lt;a href=&#34;https://github.com/lunarmodules/Penlight&#34; target=&#34;_blank&#34;&gt;Penlight&lt;/a&gt;&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;, and &lt;a href=&#34;https://github.com/lua-stdlib/lua-stdlib&#34; target=&#34;_blank&#34;&gt;lua-stdlib&lt;/a&gt; that could help with that, and I made a &lt;a href=&#34;https://gitlab.com/andreyorst/fennel-cljlib&#34; target=&#34;_blank&#34;&gt;port&lt;/a&gt; of Clojure&amp;rsquo;s core namespace to Fennel (and therefore Lua) but again - TIC-80 makes it hard to use these libraries.
So, no, Lua isn&amp;rsquo;t great at manipulating data structures, and porting Clojure code to it is a pain.
What did I expect?
Well, I&amp;rsquo;ve ported all the functions I used in my CLJS WFC implementation, things like &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;keep&lt;/code&gt;, &lt;code&gt;map-indexed&lt;/code&gt;, &lt;code&gt;get-in&lt;/code&gt;, &lt;code&gt;assoc-in&lt;/code&gt;, etc., but there were still problems with how to iterate over tables, as there is no sequence abstraction in Lua, and it&amp;rsquo;s hard to make it properly.
I tried multiple times before, and the best I got was my &lt;a href=&#34;https://gitlab.com/andreyorst/lazy-seq&#34; target=&#34;_blank&#34;&gt;lazy sequence&lt;/a&gt; library for Fennel, but even there I took some shortcuts regarding the situation with tables that have both associative and array parts.
Sorry Lua fans, but combined data structures like that are stupid.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m writing this a bit early, as there are clearly some more days until the end of this week, but then again, I won&amp;rsquo;t have time to do any work neither this evening, nor tomorrow, or the day after that.
It&amp;rsquo;s a shame though, I don&amp;rsquo;t want to abandon this roguelike idea, and maybe I&amp;rsquo;ll get back to it after the challenge ends.
Or maybe not, I don&amp;rsquo;t know.
I will have another chance to make a top-down game, but probably without an isometric projection.&lt;/p&gt;
&lt;p&gt;Looking back on the development process for this game I can see that choosing the isometric projection was probably the wrong decision.
First, I struggled with the projection itself, then with the projection of screen coordinates back to the world coordinates.
Halfway through I ditched the isometric projection and started drawing stuff without it, in hopes that I will just enable it back when the world generation is ready.
But then the world generation was a problem.
I didn&amp;rsquo;t even get to work on enemies, items, menus, and so on.
Well, a roguelike is a lot more involved than a simple platformer, so it is expected that it takes more time to do stuff, but I didn&amp;rsquo;t have that time unfortunately.&lt;/p&gt;
&lt;p&gt;Lua isn&amp;rsquo;t the one to blame for all these problems though.
While I did get some frustrations with its syntax, overall the experience wasn&amp;rsquo;t that bad.
However, I will not probably use it for upcoming projects.
The &lt;code&gt;lua-mode&lt;/code&gt; package for Emacs is in a rough shape - there is no pairing support for &lt;code&gt;do end&lt;/code&gt; keywords, like in &lt;code&gt;sh-mode&lt;/code&gt; or &lt;code&gt;ruby-mode&lt;/code&gt;.
Indentation is extremely slow and often unpredictable.&lt;/p&gt;
&lt;p&gt;The next game on the list is a Card game but I&amp;rsquo;m not in the mood for that at all, so I&amp;rsquo;m going to change this and make a side-scrolling shoot-em-up kind of game.
It should be much easier, and with all of the frustration built up over the last month, this is probably just what I need.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I know that the distinction isn&amp;rsquo;t possible because the data structure combines both sequential and associative parts in one package, but at least Lua could give us some predicates that would check if the associative part has any values and if the sequential part is not empty.
This way we would be able to detect if the table we&amp;rsquo;re looking at only has the array part, or only has the associative part which is much better than nothing.
It can be done in Lua but it is slow and often unreliable.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;It is hard to properly implement deep copying because of metatables.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;I keep forgetting its name and every single time I have to search for it as &amp;ldquo;lua batteries included&amp;rdquo; to only find a reddit post with a link to the repo that just lists lots of libraries for Lua.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game2 W4/4&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 25 Aug 2023 18:35:00 +0300</pubDate>
    </item><item>
      <title>Game2 W3/4</title>
      <link>https://andreyor.st/posts/2023-08-20-game2-w34/</link>
      <guid>https://andreyor.st/posts/2023-08-20-game2-w34/</guid>
      <description>&lt;p&gt;Why is it the third week that I finally gain any interest in actually working on the game?
Now, when I think of it, this may be the whole reason I couldn&amp;rsquo;t get into game dev during earlier attempts in the past years.
I consider myself an OK programmer and I know a bit of math that is required for making basic games, so I doubt it was due to a lack of knowledge.
Maybe it is that by the third week, there are some actual results that produce enough stimulation to my brain making it act as a feedback loop that amplifies the feeling until it burns out, and I just never stuck enough for that to trigger before.
Well, I experienced something like that during my first game jam, but not so much after when I made further attempts at this.
I guess forcing myself was the right decision.&lt;/p&gt;
&lt;p&gt;Anyways.
I mostly figured out the map problem I talked about in the previous post and the whole thing started moving, like, literally.
I ported the camera into this project and made a really basic way of moving in the world and it already feels like a game:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2023-08-20-game2-w34/camera.webm&#34; type=&#34;video/webm&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;This, however, didn&amp;rsquo;t go as smoothly, as the previous time.
I&amp;rsquo;m still figuring out the quirks, as my rendering pipeline is kinda weird.
You see, in the previous post, I made it so the tiles, used to build up a level, are baked into the cart&amp;rsquo;s map memory block.
This way I don&amp;rsquo;t have to recalculate projections of every floor tile on every tic and can do culling, drawing only what&amp;rsquo;s really is on screen, plus some extra boundary for smooth camera movement.
However, it means that when projecting to the level I need to account for the map offset, somehow.
This turned out to be a bit more challenging than I thought.&lt;/p&gt;
&lt;p&gt;For now, I put that problem aside, as I can always get back to it when I have more complex levels, and I needed to figure out the opposite of what I was doing in the previous post - project screen coordinates back to the world&amp;rsquo;s coordinates.
Because this game is meant to be a roguelike I&amp;rsquo;m going to use the mouse in this game for movement with some automatic path-finding.
Path-finding will have to wait though.&lt;/p&gt;
&lt;p&gt;After a bit of trial and error, I got it working:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-08-20-game2-w34/movement.gif&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;But again, this only works either for the static camera position, or a specific level geometry because of all the magic numbers spread through my code.
I didn&amp;rsquo;t have much time this week, only the first half, so I basically did nothing starting from Wednesday.
While it&amp;rsquo;s a shame, Starting next week I&amp;rsquo;m on vacation and hopefully will be able to spend much more time on the game and finish it in time.
Or at least get all of the mechanics working, and publish it as another demo.&lt;/p&gt;
&lt;p&gt;So, next up - world generation.
I looked at some interesting algorithms for dungeon generation in 2D roguelike games and while many of them are interesting in their own way, I don&amp;rsquo;t want to complicate things that much.
So instead, I turned to my older project - wave function collapse.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going a bit ahead of myself here as I haven&amp;rsquo;t started working on this yet, but I thought that it will be a nice and organic way to generate small, fixed-size levels.
But a plain WFC won&amp;rsquo;t work for me, so I made some adjustments.
The basic idea is to choose some points on the finite grid and assign them to specific elements.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a janky drawing with all of this in place:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-08-20-game2-w34/generation.jpg&#34; width=&#34;50%&#34; height=&#34;auto&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;These objects in the drawing are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Four rotations of room exits, connected to a floor tile, corridor tile, and two wall tiles;&lt;/li&gt;
&lt;li&gt;level entry and level exit, connected to 4 floor tiles at each side;&lt;/li&gt;
&lt;li&gt;spawn tile, also connected to 4 floor tiles.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To evenly distribute things in the level, I decided to divide the world into four sectors shown above as a gray grid.
Each sector can have only so many objects to hold, with the exception of entries and exits - these are shared across all segments and there can be only one of each.&lt;/p&gt;
&lt;p&gt;Once objects are in place, the actual WFC takes over and fills the world.
The blue walls on the image and black corridor paths will be generated by WFC, and because it will not pick empty tiles by itself, I suppose isolated rooms won&amp;rsquo;t appear.
The nice part is that the rules can be extremely simple, as there are basically 4 types of tiles used, unlike my previous project.
Of course, I can add variety later.
But that&amp;rsquo;s the topic for the next week.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game2 W3/4&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 20 Aug 2023 21:02:00 +0300</pubDate>
    </item><item>
      <title>Game2 W2/4</title>
      <link>https://andreyor.st/posts/2023-08-13-game2-w24/</link>
      <guid>https://andreyor.st/posts/2023-08-13-game2-w24/</guid>
      <description>&lt;p&gt;Didn&amp;rsquo;t have much progress on the Game2 this week.
Mostly worked on some additional assets, and rendering the world into an isometric grid.&lt;/p&gt;
&lt;p&gt;In the last post, I mentioned that it is very hard to come up with floor tiles that leave enough colors for things to be seen.
I didn&amp;rsquo;t mention it in the previous post, but here are the original tiles I drew for the game to represent the floor and walls:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-08-13-game2-w24/old-floor-wall-tiles.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;That&amp;rsquo;s right, I didn&amp;rsquo;t plan on using isometry originally.
However, this looked blunt and there wasn&amp;rsquo;t enough space to add any decoration.
I could, of course, bump the floor tile size to 4 tiles, but it started to look way too big.
Isometry, however, looks decent in my opinion:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-08-13-game2-w24/Screenshot_20230812_112859_Pixel%20Studio.jpg&#34; width=&#34;50%&#34; height=&#34;auto&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;The only problem though is how do I draw this?&lt;/p&gt;
&lt;p&gt;I created a sample level as a two-dimensional array and a simple projection function to project the world&amp;rsquo;s coordinates to screen coordinates:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; level = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {LW,RW,RW,RW,RW,RW,RW,RW,RW,RW},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {LW,F, F, F, F, F, F, F, F, F},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {LW,F, F, F, F, F, F, F, F, F},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {LW,F, F, F, F, F, F, F, F, F},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {LW,F, F, F, F, F, F, F, F, F},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {LW,F, F, F, LW,F, F, F, F, F},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {LW,F, F, F, RW,F, F, F, F, F},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {LW,F, F, F, F, F, F, F, F, F},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {LW,F, F, F, F, F, F, F, F, F},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {LW,F, F, F, F, F, F, F, F, F},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {LW,F, F, F, F, F, F, F, F, F},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;isometric_project&lt;/span&gt; (x, y, w, h)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; (x*8)+(y*-8), (x*4)+(y*4)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;LW&lt;/code&gt; is Left Wall, &lt;code&gt;RW&lt;/code&gt; is a right wall, and &lt;code&gt;F&lt;/code&gt; is floor.
All are objects with a single &lt;code&gt;draw&lt;/code&gt; method, that knows how to draw the tiles.&lt;/p&gt;
&lt;p&gt;I then drew this to the screen with a simple nested loop:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;load_level&lt;/span&gt; (level)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; ox,oy=x,y
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; offx,offy=120,8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; y=1,#level &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; x=1,#level[y] &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; t=level[y][x]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;table&amp;#34;&lt;/span&gt; == type(t) &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; mx,my=isometric_project(x-1,y-1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        t.draw(mx+ox+offx,my+offy+oy)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This gives me the correct result, albeit there&amp;rsquo;s no special code to draw this with composite tiles, so walls correctly intersect with ordinary tiles:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-08-13-game2-w24/wip-render.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;While this works, there&amp;rsquo;s a problem.
As can be seen in the &lt;code&gt;level&lt;/code&gt; array, there are only two kinds of walls - left and right ones.
Ultimately, I want to bake this layout into the map, so I can just call &lt;code&gt;map&lt;/code&gt; to render the whole level, and get camera culling as I did in the previous game.
And it isn&amp;rsquo;t easy to see the problem with the isometric grid from the app where I drew these tiles, so let me bring a non-isometric grid in the engine:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-08-13-game2-w24/wip-render-w-grid.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;There are some tiles that right now only take up half of a tile vertically, and some walls are drawn with two tiles and some with three tiles.
This means, that I can&amp;rsquo;t just bake this on a tile-by-tile basis into the map with &lt;code&gt;mset&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a closer look at the problem in case you didn&amp;rsquo;t see it:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-08-13-game2-w24/grid-problem.png&#34; width=&#34;50%&#34; height=&#34;auto&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;I, however, only used the two-tiled walls in this picture (marked with a red grid), so because of that I can&amp;rsquo;t bake this into a map, as the tiles I used don&amp;rsquo;t match the map grid.
Still thinking about how to approach this, as there&amp;rsquo;s also a second problem - entities should be able to stay behind the walls, so in reality I can&amp;rsquo;t bake this all to the map, probably only the floor tiles, and I will have to draw the walls separately.
Or via a second map call.
I mean, I &lt;em&gt;can&lt;/em&gt; draw it just like I do now, but this nested for loop bothers me way too much.
When I will add entities and have bigger levels I fear this will become really slow.&lt;/p&gt;
&lt;p&gt;There are probably ways of doing this easied than what I try to do, but this is just how I roll.&lt;/p&gt;
&lt;p&gt;Additionally, I drew even more items, and I decided that for every single-tile item I will draw a bigger one for the equipment menu:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-08-13-game2-w24/more-sprites.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Hopefully, I will figure out the isometry and have time to implement this.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game2 W2/4&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 13 Aug 2023 10:23:00 +0300</pubDate>
    </item><item>
      <title>Game2 W1/4</title>
      <link>https://andreyor.st/posts/2023-08-06-game2-w14/</link>
      <guid>https://andreyor.st/posts/2023-08-06-game2-w14/</guid>
      <description>&lt;p&gt;First week, second game!&lt;/p&gt;
&lt;p&gt;This time I opted to go with plain Lua.
Don&amp;rsquo;t get me wrong, I like Fennel, but I wanted to get a bit more authentic experience.
Apart from having a nicer standard library, Fennel doesn&amp;rsquo;t add anything to the &lt;em&gt;table&lt;/em&gt; in the case of the TIC-80 environment.
E.g. there&amp;rsquo;s no REPL that I can attach to from the editor and change code around, and there&amp;rsquo;s no real need for macros.&lt;/p&gt;
&lt;p&gt;Plus, I&amp;rsquo;d like to remind myself why I appreciate Fennel so much, as things like pattern matching, table comprehensions, and other Fennel-specific features are not available in Lua.
On the other hand, Lua is simpler, and the code being run is what you&amp;rsquo;d expect, not something that a compiler produced.
If you dared to look into the Lua version of the cart that I published at the end of the last post on the Game1 topic, you know that it looks horrific at times.&lt;/p&gt;
&lt;p&gt;So Lua it is.
TIC-80 actually provides even more languages, namely Ruby, JavaScript, MoonScript, Scheme, Squirrel, Wren, Janet, Python, and even plain WASM, I may try to use some of these.
I haven&amp;rsquo;t decided on future games yet though.&lt;/p&gt;
&lt;p&gt;Speaking of languages - why so many?
This is probably the single thing I dislike about TIC-80 and like more in PICO-8 - the latter is only programmable in a subset of Lua.
If I&amp;rsquo;m being honest, I would rather only leave Lua in TIC and ditched everything else - it&amp;rsquo;s much more authentic this way.
Even if that would mean losing direct Fennel support which, while a shame, is OK - we can always AOT.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve quickly gone through the development log, and it seems that the author is pretty generous with adding new languages to the project.
MoonScript was added first (probably), as far as I can see.
There&amp;rsquo;s a still &lt;a href=&#34;https://github.com/nesbox/TIC-80/issues/1471&#34; target=&#34;_blank&#34;&gt;open request&lt;/a&gt; for Nimscript, whatever it is.
Don&amp;rsquo;t get me wrong, the project is nothing less than amazing, I just think less is more when it comes to things like this.
But I digress.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve spent most of my first week thinking about the game and what would it evolve around.
After a bit of consideration, I decided to make a cyber-based roguelike, because there are already way too many traditional magic-based roguelikes.
So instead of a mighty artifact in my game, the character will search for the mighty neural chip that can do any kind of calculations instantly.
I can also try focusing on range battles, which should give a fresh spin on classic roguelikes too.&lt;/p&gt;
&lt;p&gt;I started working on graphics, but then life told me that I should not do anything this week and I had a power outage for quite some time.
Anyhow, this is what I got so far:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-08-06-game2-w14/sprites.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;I also tried making some floor tiles, and once again I feel the limitations of the palette - it&amp;rsquo;s so hard to come up with floor tiles that will make other sprites properly visible.
Maybe I&amp;rsquo;ll add outlines if I will not find a clever solution.&lt;/p&gt;
&lt;p&gt;One such solution might be to divide the palette into two smaller palettes.
In other words, the first 8 colors can be used for interactable objects, and the last 8 for the scenery.
Maybe I&amp;rsquo;ll try that too.
It&amp;rsquo;s even more restrictive, though.&lt;/p&gt;
&lt;p&gt;Unfortunately, I don&amp;rsquo;t think I followed my own word, and the first week went pretty unproductive regarding Game2.
And yes, I will name all of these games like that, sorry!
I did some work on my async library for Fennel, as I found some bugs in it though.
But I&amp;rsquo;ll bring the pace up the next week for sure!&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game2 W1/4&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 06 Aug 2023 23:04:00 +0300</pubDate>
    </item><item>
      <title>Game1 - Results</title>
      <link>https://andreyor.st/posts/2023-07-30-game1-results/</link>
      <guid>https://andreyor.st/posts/2023-07-30-game1-results/</guid>
      <description>&lt;p&gt;Well, this was fun!
A bit exhausting, actually.
The first of five months of the challenge has ended and here are the results:&lt;/p&gt;
&lt;iframe src=&#34;https://itch.io/embed-upload/8414750?color=3e3c57&#34;
        allowfullscreen=&#34;&#34;
        width=&#34;600&#34;
        height=&#34;320&#34;
        frameborder=&#34;0&#34;
        style=&#34;margin-left: auto; margin-right: auto; display: block;&#34;&gt;
  &lt;a href=&#34;https://andreyorst.itch.io/game1&#34;&gt;Play Game1 on itch.io&lt;/a&gt;
&lt;/iframe&gt;
&lt;p&gt;The game isn&amp;rsquo;t really complete, but I did my best to make it feel as complete as possible in the time constraints I had.
Technically, I have 1 day left, but given that I need to start working on the next game immediately I decided to give myself a day off.
It only features one level, and cuts out to the &amp;ldquo;you won&amp;rdquo; screen, but I still consider it a success.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the last bit of devlog for this particular game outlining some things I did since the last post in no particular order.&lt;/p&gt;
&lt;h2 id=&#34;graphic-overhaul&#34;&gt;Graphic overhaul&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve added parallax scrolling to the background, making the game happen inside a cave.
Well, at least, now the background is not that boring to look at, but it&amp;rsquo;s still plain.&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-30-game1-results/background.gif&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Then, I added a second layer and started experimenting with different colors:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-30-game1-results/background2.gif&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;The problem with limited colors is that I can&amp;rsquo;t find a way of having foreground and background properly separated without using outlines on sprites, which I wanted to avoid for this game at least.
Thus, slimes are now blue instead of green.
But I like it more this way because it pops from the green ground a bit better.
And now that the background is also green it&amp;rsquo;s a lot more sensible.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve spent some time drawing foliage, like mushrooms, trees, grass, water, and so on.
None of this is animated though - time is once again against me.&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-30-game1-results/foliage.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Also, added the menus, title screen, cover art, and some fade-in/out animations for smoother transitions:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-30-game1-results/transitions.gif&#34;/&gt;
&lt;/figure&gt;

&lt;h2 id=&#34;enemy-ai&#34;&gt;Enemy AI&lt;/h2&gt;
&lt;p&gt;While I wanted to add more enemy types to the game I simply ran out of time, so the game only features basic slimes.
Their AI is extremely simple too - just roam forward until there&amp;rsquo;s no more ground, a wall, or another entity, then turns around.&lt;/p&gt;
&lt;p&gt;Still, I had some trouble implementing this at first, as I tried to use the &lt;code&gt;world:check&lt;/code&gt; method to try and move the slime forward and below to check if there&amp;rsquo;s ground to traverse on.
But this didn&amp;rsquo;t work for some reason, so I opted for advanced bump API &lt;code&gt;world:queryRect&lt;/code&gt; and queried the rectangle below the slime instead.
It worked nicely, and perhaps I&amp;rsquo;ll use this to make a more robust AI in future games.&lt;/p&gt;
&lt;p&gt;I was toying for a little bit with flying enemies, but it&amp;rsquo;s hard to make them work right with the environment.
I didn&amp;rsquo;t want something like Medusa heads from Castlevania games, but that&amp;rsquo;s exactly what I got during testing.&lt;/p&gt;
&lt;p&gt;I also finally added the death mechanic, as previously the game lacked it completely.
Death doesn&amp;rsquo;t take away your score, as the game turned out to be hard, and there are not enough coins in the only level to get 100 of them and earn an extra life.&lt;/p&gt;
&lt;h2 id=&#34;level-design&#34;&gt;Level design&lt;/h2&gt;
&lt;p&gt;Probably shouldn&amp;rsquo;t have left this to the last possible moment, but designing interesting levels turned out to be a lot harder than I thought initially.
I think I&amp;rsquo;ve managed to at least do a somewhat challenging one, but you&amp;rsquo;re the judge here.
Probably most enemies and traps are cheap.&lt;/p&gt;
&lt;p&gt;As I mentioned previously, I&amp;rsquo;ve used the map editor to construct the level:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-30-game1-results/level.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;It&amp;rsquo;s a shame though that &lt;a href=&#34;https://www.mapeditor.org/&#34; target=&#34;_blank&#34;&gt;Tiled&lt;/a&gt;, a tilemap editor, doesn&amp;rsquo;t support TIC&amp;rsquo;s maps.
Well, there&amp;rsquo;s a converter but it didn&amp;rsquo;t work for me.
Map editor in TIC isn&amp;rsquo;t bad, but it isn&amp;rsquo;t as good as something like Tiled.
For example, Tiled has randomization from a selected set of tiles when you paint with them, which makes things like ground feel less repetitive.
In TIC I had to do it by hand, and I may have forgotten to do it somewhere in the game, so excuse me if you&amp;rsquo;ll see something like that.&lt;/p&gt;
&lt;p&gt;I used the bottom of the map to draw menus, backgrounds, transitions, and so on, as can be seen here:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-30-game1-results/map.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;My initial idea was to implement the first few levels like this, one below another, and then switch the memory bank, draw a new set of tiles, and make more levels.
But not only I ran out of time, I also ran out of ideas.
Maybe next time.&lt;/p&gt;
&lt;p&gt;Overall, I&amp;rsquo;d say making levels isn&amp;rsquo;t my least favorite thing so far but it&amp;rsquo;s close.
I&amp;rsquo;ve played in a fair bit of games with level editors and even published some online, but it never grew on me.
I guess I&amp;rsquo;m not a level designer at heart.&lt;/p&gt;
&lt;h2 id=&#34;music-and-sfx&#34;&gt;Music and SFX&lt;/h2&gt;
&lt;p&gt;This was probably the hardest part.
I can&amp;rsquo;t compose music and TIC&amp;rsquo;s tracker is alien to me. Sound design is a bit easier, but I don&amp;rsquo;t know a lot of tricks, so sounds in this game are far and few between.
Still was worth a shot.&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-30-game1-results/coin-sound.png&#34;/&gt;
&lt;/figure&gt;

&lt;h2 id=&#34;up-next&#34;&gt;Up next&lt;/h2&gt;
&lt;p&gt;The next game in the challenge is a roguelike.
This kind of game poses different problems, like pathfinding, more complex enemy AI in general, randomization of levels, items, etc.
I kinda feel exhausted right now but I&amp;rsquo;ll still try not to repeat the mistake I made and not procrastinate too much in the first weeks.
Though the next month is packed with various life-related events, much more than this one, so we&amp;rsquo;ll see.&lt;/p&gt;
&lt;p&gt;As for this game, here&amp;rsquo;s the cartridge if you want to play it yourself:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-30-game1-results/game1.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Though, because the original code requires a more recent version of Fennel than the one TIC provides, the code in the cart above was AOT compiled to Lua and isn&amp;rsquo;t very readable.
Also note that the last stable release of TIC still contains the &lt;a href=&#34;https://github.com/nesbox/TIC-80/issues/1904&#34; target=&#34;_blank&#34;&gt;#1904&lt;/a&gt; bug, which means that my game will run ~10 times slower than it should.
So you either need to play the game on the itch.io page, as it features a more recent version, build a standalone version yourself, or use an older release with the Lua version above.
You can read the original source code at the itch.io page linked above, or in the &lt;a href=&#34;https://gitlab.com/andreyorst/game1/-/blob/main/cart.fnl&#34; target=&#34;_blank&#34;&gt;game repository&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game1 - Results&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 30 Jul 2023 15:29:00 +0300</pubDate>
    </item><item>
      <title>Game1 W4/4 progress</title>
      <link>https://andreyor.st/posts/2023-07-26-game1-w44-progress/</link>
      <guid>https://andreyor.st/posts/2023-07-26-game1-w44-progress/</guid>
      <description>&lt;p&gt;This post is midway through the last week I have to work on the game in a platforming genre.
And it&amp;rsquo;s a bit of a shame because currently, I&amp;rsquo;m having a blast - now that the physics and camera are in place the game already feels like a playable thing.
So I decided to boost this feel and make some graphics so the world won&amp;rsquo;t look too boring to traverse.&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t decided on what the world be like yet, but I&amp;rsquo;m running out of time, and also, I&amp;rsquo;m not that experienced in pixel art.
A few posts ago I wrote how I tried to do pixel art on the phone by using a stylus, and it worked pretty well for me.
So I took out the app again and started thinking about how would I use the colors that are still available to me.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve briefly considered changing the palette too.
The default TIC-80 palette is a bit weird for my taste, and it doesn&amp;rsquo;t include some colors that I&amp;rsquo;d like to have, e.g. brown.
I don&amp;rsquo;t know how, but every time I see some pixel art that uses this particular palette I swear it has brown, but upon closer inspection it&amp;rsquo;s an illusion caused by interplay with the other colors.
Unable to find a new palette that works, and also that doesn&amp;rsquo;t make every other sprite I drew up to this point use some weird colors, I gave up for now.
Maybe I&amp;rsquo;ll just look at what colors I don&amp;rsquo;t use at all or use too infrequently and replace them with the colors I need for my purposes.&lt;/p&gt;
&lt;p&gt;For now, I drew some grass on stone type of terrain (again, no brown for dirt!), and some construction site-type red bars:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-26-game1-w44-progress/tiles.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Note, these are tiles, e.g. what goes on the map, but there are some things that are not part of the map, for example, the coin, or the slime enemy.
I&amp;rsquo;ll explain why they&amp;rsquo;re here shortly.&lt;/p&gt;
&lt;p&gt;And here are the sprites:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-26-game1-w44-progress/sprites.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;As you can see, I&amp;rsquo;m storing these sprites mostly in rows, and tall sprites, like the player character look naturally in the editor.
Except for the ones in the third and fourth rows first half - these are horizontal sprites, but I still store them this way, because of how I do animations.
This reminds me that I haven&amp;rsquo;t explained anything regarding how my game works!
I guess I was too busy implementing it and didn&amp;rsquo;t have any spare time to write a proper post.&lt;/p&gt;
&lt;p&gt;So the animations are implemented in terms of sprites, obviously, but the way I set up them is a bit weird.
And I know, I definitively could save some space and re-use some sprites, because clearly there are doubles or even triples of the same sprite.
But it was easier this way, so I did it anyway.
I have this function, called &lt;code&gt;sprites&lt;/code&gt; that takes an id of the first sprite, the last sprite, and an optional &lt;code&gt;loop?&lt;/code&gt; parameter:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sprites&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;loop?&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sprites&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fcollect&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;id&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;from&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;from&lt;/span&gt;)] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;id&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;doto &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sprites&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;tset &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:n&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;length &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sprites&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;tset &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:loop?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;loop?&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The result of this function is a table, that simply holds a range of IDs for all the sprites in the animation.
Does the &lt;code&gt;n&lt;/code&gt; key hold the total count of sprites, and &lt;code&gt;loop?&lt;/code&gt;, well, we&amp;rsquo;ll get to it in a moment.&lt;/p&gt;
&lt;p&gt;The other component of animation is how I choose when to change the frame.
I&amp;rsquo;m sure there&amp;rsquo;s a different, and probably more robust way of doing this, but what I&amp;rsquo;ve settled on is this function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;next-frame&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;obj&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dt&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dt&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dt&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;obj.last-draw-time&lt;/span&gt; 0))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;&amp;gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dt&lt;/span&gt; 60)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sprites&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;obj&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:sprites&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m/floor&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dt&lt;/span&gt; 60))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;obj.last-draw-time&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;obj.frame&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sprites.n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sprites.loop?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:number&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;type &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      (&lt;span style=&#34;font-weight:bold&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;obj.frame&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      (&lt;span style=&#34;font-weight:bold&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;obj.frame&lt;/span&gt; 1)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;font-weight:bold&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;obj.frame&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clamp&lt;/span&gt; 1 (&lt;span style=&#34;font-weight:bold&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;obj.frame&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold&#34;&gt;length &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sprites&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;obj.last-draw-time&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dt&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, this function receives an object &lt;code&gt;obj&lt;/code&gt; and a delta time &lt;code&gt;dt&lt;/code&gt;.
The object stores its own draw time, and when the sum of &lt;code&gt;dt&lt;/code&gt; and this time is greater than &lt;code&gt;60&lt;/code&gt; I change the frame.
The &lt;code&gt;loop?&lt;/code&gt; field is used in a special way - when the next frame exceeds the total sprite count, we check if the animation should loop.
If the field is &lt;code&gt;true&lt;/code&gt; the animation loops from the first frame.
However, if the field is a number, we restart the animation from that number.
This way the animation can have a set of frames that act as preparation or transition, and then loop only the necessary part.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how I draw coins:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;coin-sprites&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sprites&lt;/span&gt; 330 335 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:loop&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;coin-collect-sprites&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sprites&lt;/span&gt; 346 351))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-coin&lt;/span&gt; [{&lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;frame&lt;/span&gt; &amp;amp;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt;} {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam-x&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam-y&lt;/span&gt;}]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;match &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:sprites&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;coin-sprites&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;s&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;or &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;coin-sprites&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;frame&lt;/span&gt;) 511)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;spr&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;s&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam-x&lt;/span&gt; -120 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam-y&lt;/span&gt; -64 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;) 0 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;next-frame&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dt&lt;/span&gt; 2)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;coin-collect-sprites&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;s&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;or &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;coin-collect-sprites&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;frame&lt;/span&gt;) 511)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;spr&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;s&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam-x&lt;/span&gt; -120 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam-y&lt;/span&gt; -64 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;) 0 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;next-frame&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dt&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;frame&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;collect-sprites.n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;tset &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;coins&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are some wonky numbers in here to adjust to the center of the screen and camera position in the world, but the code should be straightforward.
The &lt;code&gt;(self:sprites)&lt;/code&gt; call simply returns the object&amp;rsquo;s current set of sprites, which I change in other functions depending on the situation.
E.g. if the coin was collected, the object&amp;rsquo;s sprite is changed to the &lt;code&gt;coin-collect-sprites&lt;/code&gt; which doesn&amp;rsquo;t loop, and the last sprite of that animation is invisible.
The coin itself is deleted from the world once the last &lt;code&gt;frame&lt;/code&gt; of the animation was played out.&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted class=&#34;pixelart&#34;&gt;&lt;source src=&#34;https://andreyor.st/2023-07-26-game1-w44-progress/coin-animation.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;This is the basis for all animation in the game.
Each object has it&amp;rsquo;s &lt;code&gt;:draw&lt;/code&gt; method, and each such method calls to &lt;code&gt;next-frame&lt;/code&gt; to understand what to display next time.&lt;/p&gt;
&lt;p&gt;Interaction with entities is done similarly - each entity has an &lt;code&gt;:interact&lt;/code&gt; method that decides what to do when a collision is detected.
For example, for the slime enemy, the method accepts the &lt;code&gt;y&lt;/code&gt; normal of the collision, and if it is not negative 1, which means that the collision happened from the side or from below, the player is damaged.
Otherwise, the slime sprite set is replaced with the stomp animation, and the object is deleted from the world:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted class=&#34;pixelart&#34;&gt;&lt;source src=&#34;https://andreyor.st/2023-07-26-game1-w44-progress/slime.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;By the way, I haven&amp;rsquo;t talked about how I structure the world yet.
You may know, that TIC has an inbuilt map editor:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-26-game1-w44-progress/map-editor.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;This is basically a level designer for me because I&amp;rsquo;ve implemented a small function that upon loading the cart walks through each tile on the map and populates the world based on it.
I still use &lt;code&gt;map&lt;/code&gt; for drawing the level, but before that, all entity tiles are removed from the map, like in the image above coins and slimes, and the player&amp;rsquo;s head, which acts as a spawn point.
This way I can simply put objects in the map editor, and re-run the game, getting an updated world, complete with collectibles, power-ups, enemies, etc.:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted class=&#34;pixelart&#34;&gt;&lt;source src=&#34;https://andreyor.st/2023-07-26-game1-w44-progress/level.webm&#34; type=&#34;video/webm&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Here I&amp;rsquo;m obviously testing things out, but the game feels complete enough to actually start designing some actual levels.
I&amp;rsquo;m running out of time though, so perhaps I&amp;rsquo;ll just make a single course to complete, and that&amp;rsquo;s it.
But it&amp;rsquo;s already more than I&amp;rsquo;ve anticipated at the beginning!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve also started working on the menu, but there&amp;rsquo;s nothing to show yet.&lt;/p&gt;
&lt;p&gt;From now, I&amp;rsquo;ll probably stop doing any in-game stuff, and concentrate on the level itself and I also need some audio to play when the player collects coins, takes damage, jumps, and so on.
Maybe I&amp;rsquo;ll even include some music if I&amp;rsquo;ll manage to compose something not too annoying to listen to.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game1 W4/4 progress&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Wed, 26 Jul 2023 20:09:00 +0300</pubDate>
    </item><item>
      <title>Game1 W3/4 (again)</title>
      <link>https://andreyor.st/posts/2023-07-22-game1-w34-again/</link>
      <guid>https://andreyor.st/posts/2023-07-22-game1-w34-again/</guid>
      <description>&lt;p&gt;Who knew that writing a post about how I&amp;rsquo;ve procrastinated for two whole weeks instead of following my own challenge would be so motivating?
Immediately after I posted the previous post on Monday, I regained interest and started working on physics integration.
Well, making a platformer without experience turned out to be harder than I thought, though I got stuck on things that are not platformer specific.&lt;/p&gt;
&lt;p&gt;For the first half of the week, I&amp;rsquo;ve been trying to implement collision resolution myself.
This&amp;hellip; didn&amp;rsquo;t go well, as can be seen here:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-22-game1-w34-again/custom-collisions.gif&#34;
         alt=&#34;Figure 1: The green rectangles depict the area in which I check for possible collisions, and red rectangles mark tiles that collided with the player&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 1: &lt;/span&gt;The green rectangles depict the area in which I check for possible collisions, and red rectangles mark tiles that collided with the player&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I&amp;rsquo;ve read some tutorials on &lt;a href=&#34;https://github.com/nesbox/TIC-80/wiki/tutorials&#34; target=&#34;_blank&#34;&gt;TIC&amp;rsquo;s wiki&lt;/a&gt;, mainly &lt;a href=&#34;https://medium.com/@btco_code/writing-a-platformer-for-the-tic-80-virtual-console-6fa737abe476&#34; target=&#34;_blank&#34;&gt;this&lt;/a&gt; one.
It mentions how to track collisions by checking nearby squarest cells on the map grid.
That was exactly my idea, but it didn&amp;rsquo;t work well, as was shown in the GIF above.&lt;/p&gt;
&lt;p&gt;I suspect the main reason for that is that the player object moves at irregular intervals because the distance is determined by velocity, and not constant as in the tutorial.
Thus, the object often overshoots or undershoots the wall and the floor, which led to the player stuck in walls, or going completely through them.
It reminded me of problems I had with my &lt;a href=&#34;https://andreyorst.itch.io/brick-game-with-a-twist&#34; target=&#34;_blank&#34;&gt;previous game&lt;/a&gt;, where the ball often got through the platform and bricks, so after failing to do physics again I decided to use a library.&lt;/p&gt;
&lt;p&gt;Using a library in a TIC game means that the library has to be included in the game cart because there&amp;rsquo;s no other way of shipping games for this platform - a cart is a self-contained program without external dependencies.
TIC&amp;rsquo;s carts also have limited capacity so the amount of code I can include is also limited.
Fortunately, there&amp;rsquo;s a small enough library called &lt;a href=&#34;https://github.com/kikito/bump.lua&#34; target=&#34;_blank&#34;&gt;bump.lua&lt;/a&gt; that does AABB collision detection, which is exactly what I need for this type of game.
TIC games are tile-based, so axis-aligned rectangles are exactly what I need to handle.
With some trickery, it is even possible to implement slopes by using special kinds of boxes that define a slope offset based on the X coordinate.&lt;/p&gt;
&lt;p&gt;There was a problem though.
&lt;code&gt;bump.lua&lt;/code&gt; is a Lua library, and while TIC supports Lua, I&amp;rsquo;m doing this game in Fennel.
Usually, it&amp;rsquo;s not a problem, because projects written in Fennel can use Lua libraries without any issues, and technically I could have used &lt;code&gt;bump.lua&lt;/code&gt; as a library from TIC-80 too.
But, as I mentioned, TIC carts must be self-contained, and thus can&amp;rsquo;t load an external library.
So I had to decide - either I port &lt;code&gt;bump.lua&lt;/code&gt; to Fennel, or compile my Fennel code to Lua and continue the development this way.
I also considered re-implementing a smaller subset of &lt;code&gt;bump.lua&lt;/code&gt; specifically for using it in TIC with map tiles, which would probably make the library smaller and easier to handle, but I decided that I want to actually see some results of my work at the end of this month.&lt;/p&gt;
&lt;p&gt;There was another compelling way of handling this situation though.
I could have used Fennel&amp;rsquo;s &lt;code&gt;-require-as-include&lt;/code&gt; compile flag to, well, include &lt;code&gt;bump.lua&lt;/code&gt; as an embedded dependency, and after the development is finished compile the cart to Lua right before shipping.
This would be the easiest way of doing things, as it would mean that I can do a completely normal development and use any libraries I want, but the downside is that the cart will be a hot mess of obfuscated Lua code, and I wanted the cart to actually contain something readable.
Maybe I&amp;rsquo;ll try this in the future, who knows?&lt;/p&gt;
&lt;p&gt;So, after some consideration of continuing in Lua and just copying &lt;code&gt;bump.fnl&lt;/code&gt; code into the cart, I decided to translate &lt;code&gt;bump.lua&lt;/code&gt; to Fennel.
As much as I like Lua, Fennel is more pleasant to work with.
It wasn&amp;rsquo;t that hard to do, given that there&amp;rsquo;s an &lt;a href=&#34;https://fennel-lang.org/see&#34; target=&#34;_blank&#34;&gt;excellent Lua-to-Fennel decompiler&lt;/a&gt;, that did most of the job.
It does generate weird code here and there, calling &lt;code&gt;set-forcibly!&lt;/code&gt; every now and then, and inserting &lt;code&gt;(lua &amp;quot;return &amp;quot;)&lt;/code&gt;  in places where Lua code had a sole &lt;code&gt;return&lt;/code&gt;, or doing things like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- original Lua code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sortByTiAndDistance&lt;/span&gt;(a,b)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; a.ti == b.ti &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; ir, ar, br = a.itemRect, a.otherRect, b.otherRect
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; ad = rect_getSquareDistance(ir.x,ir.y,ir.w,ir.h, ar.x,ar.y,ar.w,ar.h)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; bd = rect_getSquareDistance(ir.x,ir.y,ir.w,ir.h, br.x,br.y,br.w,br.h)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; ad &amp;lt; bd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; a.ti &amp;lt; b.ti
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; Lua decompiler result&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sort-by-ti-and-distance&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a.ti&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b.ti&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ar&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;br&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold&#34;&gt;values &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a.itemRect&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a.otherRect&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b.otherRect&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rect-get-square-distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.w&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.h&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ar.x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ar.y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ar.w&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ar.h&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rect-get-square-distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.w&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.h&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;br.x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;br.y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;br.w&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;br.h&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;___antifnl_rtn_1___&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ad&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bd&lt;/span&gt;)] (&lt;span style=&#34;font-weight:bold&#34;&gt;lua &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;return ___antifnl_rtn_1___&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a.ti&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b.ti&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; cleaned version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sort-by-ti-and-distance&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a.ti&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b.ti&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a.itemRect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ar&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a.otherRect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;br&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b.otherRect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ad&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rect-get-square-distance&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.w&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.h&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ar.x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ar.y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ar.w&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ar.h&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bd&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rect-get-square-distance&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.w&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ir.h&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;br.x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;br.y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;br.w&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;br.h&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ad&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bd&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a.ti&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b.ti&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;Code Snippet 1:&lt;/span&gt;
  e.g. here, the decompiler transformed a single-branch &lt;code&gt;if&lt;/code&gt; into &lt;code&gt;when&lt;/code&gt; and generated an explicit return, but a smarter decompiler could transform this into two branched &lt;code&gt;if&lt;/code&gt; without any early returns. Conceptually these two variants are the same, except one is more like the guard-return style and another is more like actual lisp-style.
&lt;/div&gt;
&lt;p&gt;So I took some extra time to clean all &lt;code&gt;set-forcibly!&lt;/code&gt; calls, restored the original comments which were lost during translation, and removed all instances of explicit early returns, by converting the code to use branches instead.
After compiling the library back to Lua, I tested it with some demos listed in the library&amp;rsquo;s readme and it worked fine, so I hope I didn&amp;rsquo;t introduce any new bugs during the cleanup state.
The next thing was to integrate it into the game.&lt;/p&gt;
&lt;p&gt;It wasn&amp;rsquo;t that hard to do, as I just copied the whole library code into the cart, but I was worried if it will be able to handle &lt;em&gt;lots&lt;/em&gt; of squares.
My idea was to iterate over every map cell, check if it is solid or not, and if so add it to the world.
Thus, each non-empty tile on the map exists in the world and acts as a collideable object.
As a result, I can use the map editor basically as a level editor, as adding a tile basically is like adding a world object.&lt;/p&gt;
&lt;p&gt;The resulting performance seems to be fine on my PC, though I&amp;rsquo;m unsure about the browser which I&amp;rsquo;ll target to make the game playable on my itch.io web page.
I&amp;rsquo;m still exploring the idea of using special tile flags to make rooms longer than they seem on the map, as described in the platformer tutorial that I&amp;rsquo;ve mentioned.
But this probably requires special handling when it comes to integrating it with the bump library.
For now, the result (with some debug info) looks like this:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-22-game1-w34-again/bump.gif&#34;
         alt=&#34;Figure 2: bump.lua in TIC-80 with some debug visualisations of collisions&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 2: &lt;/span&gt;bump.lua in TIC-80 with some debug visualisations of collisions&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The next thing to do was the camera.
Now, since each object in the world has the same coordinate as the map, the only thing I need to do is implement the translation of world coordinates to screen coordinates based on player position with some slight interpolation.
Fortunately enough, there&amp;rsquo;s a handy &lt;a href=&#34;https://github.com/nesbox/TIC-80/wiki/Camera-tutorial&#34; target=&#34;_blank&#34;&gt;tutorial&lt;/a&gt; on camera movement, and while I&amp;rsquo;d like to try and implement this myself, I decided to rely on external source of wisdom.&lt;/p&gt;
&lt;p&gt;Unfortunately, for some weird reason, the camera described in this tutorial worked differently for me.
For some reason, the player sprite was drawn in the top left corner of the screen, and the camera was also positioned there.
I mean, it moves correctly but is unplayable in this state.
After I&amp;rsquo;ve &lt;em&gt;experimented&lt;/em&gt; with some random numbers I&amp;rsquo;ve managed to get it to work:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-22-game1-w34-again/camera.gif&#34;
         alt=&#34;Figure 3: The camera moves with a slight delay to add a bit more dynamic feel, but I didn&amp;amp;rsquo;t go for a more proper camera implementation that tries to show more in the direction of movement yet. Also, what&amp;amp;rsquo;s up with these GIFs generated by TIC, their size is around 10MB each, so I had to heavily compress them myself, yet they look entirely the same afterwards.&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 3: &lt;/span&gt;The camera moves with a slight delay to add a bit more dynamic feel, but I didn&amp;rsquo;t go for a more proper camera implementation that tries to show more in the direction of movement yet. Also, what&amp;rsquo;s up with these GIFs generated by TIC, their size is around 10MB each, so I had to heavily compress them myself, yet they look entirely the same afterwards.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;With that in place, now I need to design some levels and add more graphics, and sounds.
As well, as implement actual environment interactions, such as roaming and collideable enemies, stationary hazards like spikes, health, score, and respawn systems, and maybe some other intractable objects, like coins to collect.
Not sure what I&amp;rsquo;ll do first, probably the latter, as it will teach me how to add collideable items to the world that should not be treated as platforms.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game1 W3/4 (again)&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sat, 22 Jul 2023 21:03:00 +0300</pubDate>
    </item><item>
      <title>Game1 W3/4</title>
      <link>https://andreyor.st/posts/2023-07-17-game1-w34/</link>
      <guid>https://andreyor.st/posts/2023-07-17-game1-w34/</guid>
      <description>&lt;p&gt;Long story short, no progress so far.
I&amp;rsquo;m starting to think that the way I&amp;rsquo;ve set this challenge up actually mostly demotivates me to continue rather than encourages me to press forward.
To say that I&amp;rsquo;ve been working on Game1 will be both a lie to myself and to you.
Well, I did, but in a tinkerer&amp;rsquo;s fashion - rewriting one piece of code til I&amp;rsquo;m satisfied (except I never am).&lt;/p&gt;
&lt;p&gt;So far I&amp;rsquo;ve managed to put sprites into the TIC-80 engine and created a simple controller, that actually doesn&amp;rsquo;t work how I expected it to, and that&amp;rsquo;s it:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-07-17-game1-w34/player-controller.gif&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Mostly because for the past two weeks I was either distracted by work or by working on a new Emacs window manager described in the last post (that, probably, no one needs, even me).&lt;/p&gt;
&lt;p&gt;I have two weeks left (including this one), and I don&amp;rsquo;t think I&amp;rsquo;ll be able to finish this one in time, at least in its full shape.
Maybe I&amp;rsquo;ll settle on a simpler thing, like a demo in which I just explore how to write a platformer, it&amp;rsquo;ll still be a good start.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game1 W3/4&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Mon, 17 Jul 2023 23:07:00 +0300</pubDate>
    </item><item>
      <title>Game1</title>
      <link>https://andreyor.st/posts/2023-06-30-game1/</link>
      <guid>https://andreyor.st/posts/2023-06-30-game1/</guid>
      <description>&lt;p&gt;As I stated a month ago, I&amp;rsquo;m going to force myself into game development with a &lt;em&gt;personal game dev marathon&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/em&gt; that will span over the next five months.
Technically, nothing prevents me from jumping off at any point, so I do want this to go as smoothly as possible, so I won&amp;rsquo;t burn out until I get out at least two games.
Well, we&amp;rsquo;ll see, of course - life often has its own plans for me, so&amp;hellip; yeah.&lt;/p&gt;
&lt;p&gt;The first game on my list is a platformer, which I wanted to be as simple as possible, e.g. basically run and jump.
I have no prior experience in making platformers, so this will be an exciting thing to try!
I&amp;rsquo;ve decided to go with &lt;a href=&#34;https://tic80.com/&#34; target=&#34;_blank&#34;&gt;TIC-80&lt;/a&gt; for this one, to further reduce friction, as this game engine/fantasy console has everything I need to design a game.&lt;/p&gt;
&lt;p&gt;In the previous post, I also mentioned that I was traveling, and while I wasn&amp;rsquo;t able to get to my laptop at all, I&amp;rsquo;ve decided that I will allow myself to draw some sprites for the upcoming game in advance.
The only problem was that I had to do it on my phone, which is a challenge on its own, and I don&amp;rsquo;t know what software to use.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve tried a bunch of options, and settled with &lt;a href=&#34;https://play.google.com/store/apps/details?id=com.PixelStudio&#34; target=&#34;_blank&#34;&gt;PixelStudio&lt;/a&gt; by &lt;a href=&#34;https://github.com/hippogamesunity&#34; target=&#34;_blank&#34;&gt;hippogamesunity&lt;/a&gt;.
Sadly, it&amp;rsquo;s not open source, but it is common for a lot of software for pixel art, and art in general.
The only open-source free software pixel art app I know is &lt;a href=&#34;https://libresprite.github.io/#!/&#34; target=&#34;_blank&#34;&gt;LibreSprtie&lt;/a&gt;, which itself is a fork of &lt;a href=&#34;https://www.aseprite.org/&#34; target=&#34;_blank&#34;&gt;Aseprite&lt;/a&gt; which changed its license some years ago and is no longer FOSS.
Since I was considering paying for either of those, I decided to go with PixelStudio because my phone has a stylus (S-Pen) that is supported by the app, and drawing on the screen seemed nicer.
I can always bring LibreSprite on my laptop in case I need more, and TIC also has a sprite editor.
TIC is also available on the phone, but unlike TIC, PixelStudio gives me the ability to do animations, which is what I was mainly looking for.
If not for animations, I would probably stick with the phone version of TIC until I&amp;rsquo;ve returned.&lt;/p&gt;
&lt;p&gt;So I went on and started working on characters for my &lt;code&gt;Game1&lt;/code&gt; project.
&lt;code&gt;Game1&lt;/code&gt; is, of course, a work-in-progress title, but it&amp;rsquo;s not far from the truth, as this will probably be the first thing that I will consider something like a real game made by me.
Anyway, this is how the app in which I drew my character looks:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2023-06-30-game1/pixelstudio.jpg&#34; width=&#34;35%&#34; height=&#34;auto&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;The interface is a bit cluttered, but I find it useful enough if the screen is big enough, which is my case.
But, back on character animations, here&amp;rsquo;s what I&amp;rsquo;ve got so far:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-06-30-game1/moveset.gif&#34; width=&#34;100%&#34; height=&#34;auto&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;This is just a mockup, testing around how animations would look in-game.
The blue fireball was added to show the damage animation, I&amp;rsquo;m not even sure if the projectiles will be in the game.
And starting from tomorrow I will actually start putting things together in the TIC.
I&amp;rsquo;m now realizing that by using too much color in the character sprite, I kinda limited myself on the number of colors that I can use for the background, and terrain because the default palette in TIC is quite limited on colors:&lt;/p&gt;
&lt;figure class=&#34;pixelart&#34;&gt;&lt;img src=&#34;https://andreyor.st/2023-06-30-game1/sweetie-16.png&#34; width=&#34;100%&#34; height=&#34;auto&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;So I may need to do a bit of redesign on the character part.
Actually, I&amp;rsquo;ve always liked pixel art for its limiting nature - the ability to express a lot of ideas and small details in such a low amount of pixels and colors always fascinated me.
I don&amp;rsquo;t know much about pixel art, and it probably shows, but hey, this marathon is to learn new stuff, so give me some time!
But, right now I&amp;rsquo;m not even sure how do I program such animations, so I&amp;rsquo;ll probably start with just drawing a rectangle for the player, enemies, and platforms.&lt;/p&gt;
&lt;p&gt;I will be posting updates as soon as I get more progress, so expect this as a kind of dev-log, but honestly, it is mostly for me, as I find this kind of activity encouraging to keep on.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;You&amp;rsquo;re welcome to join, of course, but I&amp;rsquo;m not going to organize an actual event&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Game1&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 30 Jun 2023 22:46:00 +0300</pubDate>
    </item><item>
      <title>Fennel Game Jam 2022</title>
      <link>https://andreyor.st/posts/2022-06-12-fennel-game-jam-2022/</link>
      <guid>https://andreyor.st/posts/2022-06-12-fennel-game-jam-2022/</guid>
      <description>&lt;p&gt;Quite recently a Fennel game jam happened on &lt;a href=&#34;https://itch.io/&#34; target=&#34;_blank&#34;&gt;itch.io&lt;/a&gt; and I&amp;rsquo;ve decided to participate.
I&amp;rsquo;ve been part of the Fennel community for some years, and every once in a while a lot of people from this community participated in a lisp game jam, but I&amp;rsquo;ve never made a game before, so I&amp;rsquo;ve skipped these events.
However, when the Fennel-specific game jam was announced I decided that I must finally put myself together and participate.&lt;/p&gt;
&lt;p&gt;The rules of the jam were quite relaxed - you basically had to use fennel for game programming, and release the game under an &lt;a href=&#34;https://opensource.org/licenses&#34; target=&#34;_blank&#34;&gt;OSI approved license&lt;/a&gt;.
No theme, no engine restrictions, no size requirement - an ideal situation for a programmer like me, who doesn&amp;rsquo;t know how to make a game, at all.
When I was young, and I mean, like almost 20 years ago, I only toyed with &lt;a href=&#34;https://en.wikipedia.org/wiki/Adobe_Flash#Macromedia&#34; target=&#34;_blank&#34;&gt;Macromedia Flash&lt;/a&gt; and ActionScript 2.0 at my school computer class, making interactive cartoons, which can hardly be considered games.
It&amp;rsquo;s not like I&amp;rsquo;m a complete stranger to game programming though, we had a very brief introduction to game programming at the university, except we never actually programmed games during these courses.
So, for example, I know what delta time is, how it should be used, or how to do vector math needed for basic movement, but this doesn&amp;rsquo;t count as experience.
If you read my blog, you may remember my small projects like &lt;a href=&#34;https://andreyor.st/posts/2020-06-04-simple-ray-casting-with-clojurescript/&#34;&gt;raycasting&lt;/a&gt; and &lt;a href=&#34;https://andreyor.st/posts/2020-10-15-raymarching-with-fennel-and-love/&#34;&gt;raymarching&lt;/a&gt;, which feature movement, camera programming, basic collision detection, and a basic game-loop.
So actually I felt prepared when I decided to enter the jam.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve already tried LÖVE2D in the mentioned raymarching example, so I&amp;rsquo;ve decided to change things up a bit since I&amp;rsquo;ve wanted to explore another project - &lt;a href=&#34;https://tic80.com/&#34; target=&#34;_blank&#34;&gt;TIC-80&lt;/a&gt;.
The change from LÖVE2D to TIC-80 actually made it easier for me, since I could do the sprite-work and sound effects inside tic&amp;rsquo;s inbuilt editors.
So I&amp;rsquo;ve begun to work on it.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll try to structure this post as a series of days based on the notes I made during the event.
There probably will not be any code though, as I have no early versions, since I&amp;rsquo;ve opted out of using version control systems for this project, to keep the retro vibe of the fantasy computer.&lt;/p&gt;
&lt;h2 id=&#34;day-1&#34;&gt;Day 1&lt;/h2&gt;
&lt;p&gt;The hardest day in my opinion because it is the day when I &lt;strong&gt;have&lt;/strong&gt; to start working on a project I haven&amp;rsquo;t had any thoughts about beforehand.
I&amp;rsquo;ve sat down and thought about what kind of game I &lt;em&gt;can&lt;/em&gt; make in the limited time of the event which was going from May 25 to Jun 1st.
Given 5 days and almost no game development experience, I&amp;rsquo;ve decided to play it safe and make a Breakout-like game.
Though a plain breakout clone would be a bit boring, so I&amp;rsquo;ve decided that I&amp;rsquo;ll put a small twist once you destroy the final block which would shake things a bit and hopefully be a welcome surprise.&lt;/p&gt;
&lt;p&gt;Now, since the theme was chosen I at least knew what I needed to start - a ball, a platform, and a box to bounce the ball to prevent it from flying away to infinity.
But I didn&amp;rsquo;t know how to do anything in tic, so I&amp;rsquo;ve opened up a &lt;a href=&#34;https://tic80.com/learn&#34; target=&#34;_blank&#34;&gt;manual&lt;/a&gt;.
The manual is minimalist, to say the least, and doesn&amp;rsquo;t provide a lot of info beyond essential things.
So I&amp;rsquo;ve picked up the &lt;code&gt;circ&lt;/code&gt; &lt;code&gt;rect&lt;/code&gt; and &lt;code&gt;rectb&lt;/code&gt; functions and started working.
This was my first result:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2022-06-12-fennel-game-jam-2022/day1.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;This has very basic hard-coded physics, meaning that I&amp;rsquo;ve literally defined a vector of all ball velocities and just cycled through it when the ball collided with any world object.
But it already has some interesting stuff done, which I haven&amp;rsquo;t changed much afterward.&lt;/p&gt;
&lt;p&gt;The first thing is that It has a proper world to screen coordinate transformation, which I&amp;rsquo;ve kinda never done before.
It&amp;rsquo;s a simple thing, I just have a world X and Y offsets that made the game world, e.g. the box rest, not in the top left corner but 10 pixels to the right and down.
All game physics was calculated with the top left corner in &lt;code&gt;0,0&lt;/code&gt; and then translated before drawing.&lt;/p&gt;
&lt;p&gt;The platform tracks its position and makes sure not to go outside the world boundaries.
And the ball is checked for collisions with everything but the lower boundary.
There, instead of a collision a basic &lt;code&gt;game-over?&lt;/code&gt; flag is set to interrupt the game loop.&lt;/p&gt;
&lt;p&gt;I was pretty satisfied for day one, especially since it wasn&amp;rsquo;t really a full day of me programming this, but only 3 hours after work.
The jam started at 10:00 AM in my time zone, and my work day also starts at the same time, so I had to begin working on a game 9 hours after the start of the jam.
I&amp;rsquo;m sure this is a common situation for most other participants, though perhaps they have had time before work too.&lt;/p&gt;
&lt;h2 id=&#34;day-2&#34;&gt;Day 2&lt;/h2&gt;
&lt;p&gt;I knew that I&amp;rsquo;ll not be able to move forward with the current physics system I&amp;rsquo;ve added to the game, so I spent most of the second day fighting with the collision system.
This was the result I got:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2022-06-12-fennel-game-jam-2022/day2.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;This had really wonky surface normal calculations, and you can see that the ball isn&amp;rsquo;t particularly happy with the results, as it just decides to leave the game.
I wasn&amp;rsquo;t happy with it either, but it was a move in the right direction.&lt;/p&gt;
&lt;p&gt;In addition to &lt;em&gt;improved&lt;/em&gt; physics, I&amp;rsquo;ve added destructible bricks with a random amount of health represented by a color.
The color was an accident, as I used brick health in place of the brick color when bricks were drawn on the screen, but I actually liked it.
The health was distributed randomly, but I&amp;rsquo;ve been focused on physics, so I&amp;rsquo;ve left it as is.&lt;/p&gt;
&lt;p&gt;There were two main problems.
First, I&amp;rsquo;ve re-used some linear algebra code from my raymarching project, mainly the calculation of the distance to the box and the calculation of the normal.
However, the calculation of a normal was done for a 3D world and wasn&amp;rsquo;t as meaningful for 2D space.
I&amp;rsquo;m not sure whether I&amp;rsquo;ll be able to explain the general method, but the idea is that I&amp;rsquo;ve found an intersection point, and picked two more points one below the surface and to the left and another above the surface and to the right.
Then I used some vector math to find a normal based on distance estimation from these points to the intersection point.
This works quite well for 3D, given that all reflections in the raymarching demo were correct, but in 2D it resulted in weird unexpected reflections (not in the video).&lt;/p&gt;
&lt;p&gt;Unfortunately, I have this kind of problem that once I&amp;rsquo;ve fixated on some solution I can&amp;rsquo;t see another one until I step away from the problem for a bit.
So I&amp;rsquo;ve kept the current physics and ended the day 2 session.&lt;/p&gt;
&lt;h2 id=&#34;day-3&#34;&gt;Day 3&lt;/h2&gt;
&lt;p&gt;This day was mostly spent polishing and rewriting the collision system.
I&amp;rsquo;ve almost fully fixed bugs with unexpected angles, but the ball still managed to find its way inside the platform.
I couldn&amp;rsquo;t spend too much time on it, so I&amp;rsquo;ve decided to leave it as is, and maybe fix it after everything else is done.&lt;/p&gt;
&lt;p&gt;In addition to that, I&amp;rsquo;ve made it such that the block health depends on the row it was spawned at.
So the lower blocks had 1 health, the next row above it had 2 health, and so on.
This can be seen with this nice color transition from purple to orange.&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2022-06-12-fennel-game-jam-2022/day3.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve also done some basic point systems that added 100 points when you destroy a brick, and 10 points upon collision.
There are now lives, so you can lose the ball several times before the &amp;ldquo;game over&amp;rdquo;.
Satisfied with that I&amp;rsquo;ve ended the third day, realizing that theirs not that much time left, but also not too far til the game will be complete.&lt;/p&gt;
&lt;p&gt;For the next two days, I was planning to add graphics and a small twist that will hopefully make the game a bit more interesting.&lt;/p&gt;
&lt;h2 id=&#34;day-4&#34;&gt;Day 4&lt;/h2&gt;
&lt;p&gt;Up until this day I&amp;rsquo;ve drawn everything with basic rectangles and this wasn&amp;rsquo;t going to cut for the jam in my opinion.
So for the fourth day, I&amp;rsquo;ve decided to focus on some graphics and sounds.&lt;/p&gt;
&lt;p&gt;The inbuilt sprite editor is quite good, actually.
I&amp;rsquo;ve only tried the &lt;a href=&#34;https://github.com/LibreSprite/LibreSprite&#34; target=&#34;_blank&#34;&gt;LibreSprite&lt;/a&gt;, an open-source fork of aseprite sprite editor, and it was a bit sluggish, perhaps because it was using a software cursor, which felt unresponsive.
But with TIC&amp;rsquo;s sprite editor it wasn&amp;rsquo;t a problem and I quickly drew basic sprites for bricks, the platform, and the ball:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2022-06-12-fennel-game-jam-2022/sprites.gif&#34;
         alt=&#34;Figure 1: Sprites&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 1: &lt;/span&gt;Sprites&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Then I decided to add power-ups.&lt;/p&gt;
&lt;p&gt;There are three classic power-ups that affect the size of the ball or the platform - the big ball, the long platform, and the short platform.
All these powers are timer-based, with a small exception for the big ball - if you lose the ball while it&amp;rsquo;s big, the power-up is also lost.
In addition to that, there are two speed-related power-ups, one that increases the ball&amp;rsquo;s speed, and one that decreases it.&lt;/p&gt;
&lt;p&gt;Speaking of speed, I&amp;rsquo;ve also made it so that the speed of the ball gradually grows during the game up to twice the initial speed.
And there&amp;rsquo;s a mentioned power-up to increase and decrease the value by a quarter.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a demonstration of various power-ups:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2022-06-12-fennel-game-jam-2022/day4.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;As can be seen, the ball still can act weirdly, almost spinning around the platform, but I&amp;rsquo;ve already spent most of my time on graphics and sounds, so I&amp;rsquo;ve decided to left it for the last day.&lt;/p&gt;
&lt;h2 id=&#34;day-5&#34;&gt;Day 5&lt;/h2&gt;
&lt;p&gt;The last day of the jam!
I&amp;rsquo;ve added more graphics, as I wasn&amp;rsquo;t able to figure out how to measure things in seconds, as the values of the &lt;code&gt;time&lt;/code&gt; function were kinda &lt;em&gt;weird&lt;/em&gt;.
So I&amp;rsquo;ve opted out of colored bars that gradually decrease in length.
I&amp;rsquo;ve also decided to add some effects, like screen shake when the ball is big.
Here&amp;rsquo;s how it looks:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2022-06-12-fennel-game-jam-2022/day5.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;At this point, I&amp;rsquo;ve started working on the &lt;em&gt;twist&lt;/em&gt; and polishing things out.
For the twist I&amp;rsquo;ve decided to do a boss battle at the end of the game, essentially turning the Breakout game into Pong when the last brick is destroyed:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay loop muted&gt;&lt;source src=&#34;https://andreyor.st/2022-06-12-fennel-game-jam-2022/boss-battle.mp4&#34; type=&#34;video/mp4&#34;&gt;
Your browser does not support the video tag.&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;The boss has a fixed amount of health, and each hit with the ball removes some amount of it.
If the big ball power-up is active the ball deals twice the damage.
I&amp;rsquo;ve actually made it that this damage multiplier also affects bricks, so bricks are destroyed a bit faster now too.
And if you score the boss, it&amp;rsquo;ll lose 5 times hp of a single hit, although it&amp;rsquo;s almost impossible, unless you picked a lot of speed power-ups.&lt;/p&gt;
&lt;p&gt;Boss&amp;rsquo; health is represented with another bar that changes color depending on the health range, going from green at full to red near the end.
To win the game you must defeat the boss, which is actually a bit tricky and I can&amp;rsquo;t do it consistently myself either.
Speaking of power-ups, there&amp;rsquo;s a random chance to spawn a power-up in a random location during the boss battle.
The chance of spawning is very low though.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve uploaded the game to itch as a web build, and noticed a weird problem.
All power-ups were wearing off too fast!
I couldn&amp;rsquo;t understand what the problem is, because to my knowledge I did a proper way of handling power-up times - I obtained the current game-time with the call to the &lt;code&gt;time&lt;/code&gt; function, added a fixed amount to it, and checked on each frame if the value returned by &lt;code&gt;time&lt;/code&gt; surpassed it.
To simplify, upon activation of a timer based power-up, I did this &lt;code&gt;end = time() + powerup_duration&lt;/code&gt;, and checked for &lt;code&gt;end &amp;lt; time()&lt;/code&gt; to disable the power-up.
Given that it is based on &lt;code&gt;time&lt;/code&gt; and not on some ticking mechanism, I&amp;rsquo;ve thought that it should work equally well regardless of frames per second.
Even more weird was that the ball speed was the same as on the desktop.
So in short - power-ups ended a lot faster, yet the rest of the speed was the same.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve decided to do it &amp;ldquo;properly&amp;rdquo; and calculated the delta time.
Then I multiplied ball movement by newly calculated &lt;code&gt;dt&lt;/code&gt; and reworked power-ups to work based on ticks, meaning they weren&amp;rsquo;t tied to &lt;code&gt;time&lt;/code&gt; directly.
Checked that all works well on my desktop I&amp;rsquo;ve made a fresh web build, uploaded it to itch, and it was way too fast!
The ball speed now was superfast, power-ups ended almost immediately.
After a ton of debugging, and trying to make any sense out of the phrase that the main &lt;code&gt;TIC&lt;/code&gt; function is called 60 times per second, when it &lt;em&gt;clearly&lt;/em&gt; wasn&amp;rsquo;t, as the game speed was different between the web and Linux builds.
Then I made a Windows build, and it worked with the same speed as the web build, and I thought that maybe it was a bug in the Linux build.
I&amp;rsquo;ve checked what value of &lt;code&gt;dt&lt;/code&gt; was calculated on each platform, and the Linux build had a 10-fold difference from other platforms:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2022-06-12-fennel-game-jam-2022/tic-bug.png&#34;
         alt=&#34;Figure 2: Delta time differences between platforms&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 2: &lt;/span&gt;Delta time differences between platforms&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The Linux build had a delta time value of approximately &lt;code&gt;0.001&lt;/code&gt; while the web and Windows build had &lt;code&gt;0.02&lt;/code&gt;.
I&amp;rsquo;ve tried an older version of TIC, and it had no such issue but didn&amp;rsquo;t support the Fennel version I was using for the game.
So I had to distribute the game only as a web build until the &lt;a href=&#34;https://github.com/nesbox/TIC-80/issues/1904&#34; target=&#34;_blank&#34;&gt;issue&lt;/a&gt; is fixed.
I&amp;rsquo;ve tweaked the speed by adding a &lt;code&gt;game_speed&lt;/code&gt; parameter that I could tweak around inside the web build to make the speed feel right.
After that, I pushed a final web build with these tweaks and submitted the game.&lt;/p&gt;
&lt;h2 id=&#34;jam-results&#34;&gt;Jam results&lt;/h2&gt;
&lt;p&gt;Because of my time zone, I was the first who submitted a game, but I couldn&amp;rsquo;t do any more work because the last hours of the jam were at nighttime here.
Out of 21 participants, only seven games were submitted, which actually a pretty great result, in my opinion, it&amp;rsquo;s a solid third!
Funnily enough, we have about 60 people in our &lt;code&gt;#fennel&lt;/code&gt; IRC channel on &lt;a href=&#34;https://libera.chat/&#34; target=&#34;_blank&#34;&gt;Libera.Chat&lt;/a&gt;, so 21 people is a third too.
The results can be viewed &lt;a href=&#34;https://itch.io/jam/fennel-game-jam-1/results&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;, and I suggest you try all games, as there are pretty cool entries!&lt;/p&gt;
&lt;p&gt;I managed to score third place, which actually surprised me a bit, given how simple the concept of my game was.
But I&amp;rsquo;m glad, and I think it&amp;rsquo;s a solid result for the first game.&lt;/p&gt;
&lt;p&gt;In retrospect, I think I could do some things better, especially in the user interface department.
Adding a proper menu, maybe an intro, making the interface look more like an arcade cabinet, which I&amp;rsquo;ve originally attempted, but my pixel-art skills are not that great yet.
But I still like the result, I feel that for a first game it turned out pretty great.
And the process was quite fun, which is the most important thing for me.&lt;/p&gt;
&lt;p&gt;I hope I&amp;rsquo;ll participate in more lisp-themed jams, maybe in a lisp game jam or the next Fennel jam.
I&amp;rsquo;ve always wanted to make games, and I had some ideas about the game I want to make in the Metroidvania genre.
Game jams are perfect for experiments, and you can learn a lot by doing things you never did before.
I&amp;rsquo;m not going to make a whole game during the jam as I want it to be a more complete thing, but the jam can help me to flesh out some main mechanics, be it the movement, or world-building practice.
So I&amp;rsquo;m looking forward to the upcoming events!&lt;/p&gt;
&lt;p&gt;This was a lot of fun, and I hope more people will join next time!
Thanks to everyone who participated, &lt;a href=&#34;https://www.mattroelle.com/&#34; target=&#34;_blank&#34;&gt;Matt Roelle&lt;/a&gt; for organizing the Jam, and everyone involved in Fennel and TIC-80 development.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Fennel Game Jam 2022&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 12 Jun 2022 12:37:00 +0300</pubDate>
    </item><item>
      <title>Wave Function Collapse Algorithm in ClojureScript</title>
      <link>https://andreyor.st/posts/2022-05-10-wave-function-collapse-algorithm-in-clojurescript/</link>
      <guid>https://andreyor.st/posts/2022-05-10-wave-function-collapse-algorithm-in-clojurescript/</guid>
      <description>&lt;p&gt;The last time I touched ClojureScript was &lt;a href=&#34;https://andreyor.st/posts/2020-06-04-simple-ray-casting-with-clojurescript/&#34;&gt;almost two years ago&lt;/a&gt;.
It was a really fun experience, and actually, it was a bit special to me personally.
Prior to that post, I only learned lisp&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; via books and mostly used it only for configuring Emacs, and while I&amp;rsquo;ve liked the idea of code as data and other lisp aspects, I never did anything more with the language.
So this was the first thing that I&amp;rsquo;ve done in lisp from start to finish, the first thing done in Clojure, the first interactive thing with some sort of visualizations.
And this is pretty much the reason I fell in love with Clojure and not with another dialect - I&amp;rsquo;ve used it for something &lt;em&gt;real&lt;/em&gt;, not just an exercise for the book, and I liked the syntax, the data structures, immutability, laziness, and other features.
Since that post I&amp;rsquo;ve got a job in Clojure, so now it&amp;rsquo;s my primary programming language and I love it still.
However, I have a lot less experience with ClojureScript, mainly because I mostly do backend development, and we have a separate team working on the frontend part.&lt;/p&gt;
&lt;p&gt;I like games, but I&amp;rsquo;ve never actually done anything more than simple demos of various game algorithms and techniques&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.
And I mostly did it in Fennel, because it&amp;rsquo;s also a very nice lisp-like language with a very similar syntax to Clojure.
I wanted to do more, but I wanted these experiments to be a bit more reachable, and possibly viewed directly in my blog, as it was with the raycasting example.
So I knew that I wanted to do something with ClojureScript instead of Fennel, which became my main language for this type of thing.
Another reason is that I&amp;rsquo;m thinking about doing some frontend programming in ClojureScript in the upcoming years.&lt;/p&gt;
&lt;p&gt;Luckily for me, not so long ago I found a really neat algorithm for generating worlds.
The algorithm is called Wave Function Collapse, and it actually has nothing to do with quantum physics.
In this post, I&amp;rsquo;ll try to walk you thru the algorithm, and explain how I&amp;rsquo;ve approached this problem.&lt;/p&gt;
&lt;h2 id=&#34;the-algorithm&#34;&gt;The algorithm&lt;/h2&gt;
&lt;p&gt;What makes this algorithm different from most procedural generation algorithms I&amp;rsquo;ve read about is that it is &lt;em&gt;extremely simple&lt;/em&gt;.
It can generate images based on a small sample of data, as shown below:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2022-05-10-wave-function-collapse-algorithm-in-clojurescript/coast.png&#34;
         alt=&#34;Figure 1: Example Input&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 1: &lt;/span&gt;Example Input&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2022-05-10-wave-function-collapse-algorithm-in-clojurescript/result.png&#34;
         alt=&#34;Figure 2: Generation result&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 2: &lt;/span&gt;Generation result&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;However, just implementing the algorithm from some description isn&amp;rsquo;t fun.
What I like to do, and this is a general approach I use for all my projects, is to get some assumptions about the thing I want to implement, and then do everything based on these assumptions only&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;.
So instead of learning how the algorithm is implemented, I&amp;rsquo;ve just observed its behavior with simple input.&lt;/p&gt;
&lt;p&gt;For example, let&amp;rsquo;s look again at the input sample, but let&amp;rsquo;s split it into tiles with a grid:&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--example&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2022-05-10-wave-function-collapse-algorithm-in-clojurescript/example.png&#34;
         alt=&#34;Figure 3: Sample&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 3: &lt;/span&gt;Sample&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;This sample specifies that for each tile on this image there are only so many possible neighbors.
For example, this tile in the middle can only have one unique neighbor on each of its sides:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2022-05-10-wave-function-collapse-algorithm-in-clojurescript/neighbors.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Other tiles may have two or more unique neighbors, and the job of the algorithm is to analyze each tile on the image, and track what neighboring cells it has, storing it into a ruleset.
And an image is then generated based on these adjacency rules only.&lt;/p&gt;
&lt;p&gt;This is basically what I knew about the algorithm when I started implementing it.
Of course, it&amp;rsquo;s not &lt;em&gt;that&lt;/em&gt; simple, but it&amp;rsquo;s still easy to grasp, and some nuances become apparent when you actually start working on it.
I&amp;rsquo;ll give the algorithm a more comprehensive explanation a bit later, as we&amp;rsquo;ll encounter problems.&lt;/p&gt;
&lt;h2 id=&#34;text-version-of-the-algorithm&#34;&gt;Text version of the algorithm&lt;/h2&gt;
&lt;p&gt;For this project, I once again picked shadow-cljs, so the project can be created with &lt;code&gt;npx create-cljs-project wave-function-collapse&lt;/code&gt;.
But before actually working with images we can begin with a bit simpler to debug version of it which deals with an ordinary text.
This can be done in plain Clojure, but since we&amp;rsquo;ll later plug it into our page, let&amp;rsquo;s use &lt;code&gt;.cljs&lt;/code&gt; file.
We start by implementing our algorithm in the file &lt;code&gt;wfc.cljs&lt;/code&gt;, &lt;code&gt;wfc&lt;/code&gt; being short for wave function collapse.&lt;/p&gt;
&lt;p&gt;As I&amp;rsquo;ve explained in the previous section, we start by transforming an input into a set of rules for the algorithm.
Our input will be a two-dimensional matrix, in this case, an array of arrays of strings.
Let&amp;rsquo;s start with a similar sample to that I&amp;rsquo;ve shown in the &lt;a href=&#34;#figure--example&#34;&gt;previous example&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;coast&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;]])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s even simpler, as it doesn&amp;rsquo;t have tiles that represent corners.
The first thing we need to do is to define a function, that gets all neighboring cells in all cardinal directions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-neighbors&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:up&lt;/span&gt; [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:down&lt;/span&gt; [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;inc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:left&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:right&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;inc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;)]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;into &lt;/span&gt;{}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;keep&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dir&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;when-some&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                       [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dir&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:cell&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;}]))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This function gets only those cells inside our matrix and discards those that are outside of its boundaries.
With this function we can write a function that builds a recipe from the input sample:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; add [clojure.set :as set] to :require&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;build-recipe&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;map-indexed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;map-indexed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;neigbors&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;into &lt;/span&gt;{}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dir&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;]}]] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dir&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;}]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-neighbors&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               {&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;neigbors&lt;/span&gt;})) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;flatten&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;apply merge-with &lt;/span&gt;#(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;merge-with &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set/union&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%2&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m using &lt;code&gt;map-indexed&lt;/code&gt; because we need to get neighbors for each cell, and this is what our &lt;code&gt;get-neighbors&lt;/code&gt; function accepts.
Calling this function on the &lt;code&gt;coast&lt;/code&gt; recipe yields the following map:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:up&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:down&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:left&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:right&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:up&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:down&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:left&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:right&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟫&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:up&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:down&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:left&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:right&lt;/span&gt; #{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟦&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;🟩&amp;#34;&lt;/span&gt;}}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we have a proper illustration of the adjacency rules we&amp;rsquo;ve talked about before.
With that, we can start implementing the algorithm itself.&lt;/p&gt;
&lt;h2 id=&#34;collapsing-cells&#34;&gt;Collapsing cells&lt;/h2&gt;
&lt;p&gt;In order to collapse anything, we need a world in which we&amp;rsquo;ll do our work.
The beauty of this algorithm lies in the fact that it can work with a partially filled world, but generally, the world starts in a so-called superposition.
To get this superposition, we need to analyze the input sample once again:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-superposition&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;into &lt;/span&gt;#{} (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;flatten&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This gives us all possible variants for a single cell.
To define a world we can just generate a new &amp;ldquo;empty&amp;rdquo; matrix that we&amp;rsquo;ll later populate with a cell superposition state.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gen-world&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-y&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mapv&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;for &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;range &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-x&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;for &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;range &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-y&lt;/span&gt;)] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;populate-world&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;superpos&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-superposition&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mapv&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mapv&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;nil? &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;superpos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As the last preparation step, we need a way of checking if the world is fully built.
This can be done by checking if any of the cells is still a hash-set and not a concrete value:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;done?&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;some &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set?&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;flatten&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A more optimal way would be to track how many cells were fully collapsed and compare it with the world size to avoid walking the whole world repeatedly on each step, but for now, this will do.
The last preparation step we need to do is to write a function that chooses which cell to collapse next.
The first cell can be selected at random, but the following must be selected more carefully, or we&amp;rsquo;ll corner ourselves pretty quickly.
To do that we need to measure world entropy and select a cell with the lowest one.
Since every cell can only contain a set of unique elements, we can measure the entropy by counting the number of elements in a cell.
Thus, a function that returns the lowest entropy cell can be defined as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lowest-entropy-cell&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;enthropies&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;map-indexed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;keep-indexed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                              (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;count &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;) [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;]])) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;apply &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;concat&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shuffle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;sort-by &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;first&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;if-some&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;first &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;enthropies&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;second &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      [0 0])))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will produce uniform distribution, so we might want to change it a bit later, but for now, it&amp;rsquo;ll do.&lt;/p&gt;
&lt;p&gt;Now to the meat and bones of the algorithm.
To actually collapse a cell we need a function that can choose a random element of a cell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;collapse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;val&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;coll?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;val&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= &lt;/span&gt;1 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;count &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;val&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;assoc-in&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;first &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;val&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;assoc-in&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;val&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After the cell is collapsed, we need to constrain its neighbors, so their superposition only contained possible elements that can be connected to this cell.
This is a bit harder part of the algorithm, as it involves waling a grid of cells recursively and constraining every cell that is a set and skipping others that are not.
If a cell itself is a set, its content should be treated as a series of cells that also affect how the surrounding cells should be constrained:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;collapse-neighbors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recipe&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;neighbors&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-neighbors&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;neighboring-cells&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shuffle&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;vals &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;neighbors&lt;/span&gt;))) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;; ❶&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;&amp;#39; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;reduce&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dir&lt;/span&gt; {[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt;] &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt;}]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt;) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;; ❷&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;variants&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set/intersection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;coll?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;) #{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;apply &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set/union&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;#(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recipe&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dir&lt;/span&gt;]) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recipe&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dir&lt;/span&gt;])))] &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;; ❸&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;seq &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;variants&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;collapse&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;variants&lt;/span&gt;) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;; ❹&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;neighbors&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;reduce &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;collapse-neighbors&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recipe&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;neighboring-cells&lt;/span&gt;)))) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;; ❺&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This function is the heart of the algorithm, as it does all of the heavy liftings on constraining cells, so let&amp;rsquo;s break it down.
First, we get all neighbors and extract a sequence of cells that we&amp;rsquo;re going to constrain (❶).
We then iterate over these neighbors inside &lt;code&gt;reduce&lt;/code&gt;, getting the current world state for this cell (❷).
For this cell, we need to compute all remaining variants.
This is done by intersecting this cell&amp;rsquo;s state with variants from a neighbor in a given direction.
And if the cell itself is a set, this is done for each element in a set (❸).
Finally, a cell is collapsed (❹), except when it was a set and the variant list wasn&amp;rsquo;t empty.&lt;/p&gt;
&lt;p&gt;After that process is done for all four neighbors, we need to repeat it for each of the neighbors&amp;rsquo; neighbors.
So we check if our last run actually produced any change in the world, and if it is, we recursively walk through these neighbors (❺), otherwise, we return current world state.
This may actually cause a stack overflow error if there are too many neighbors to collapse, which depends both on the world size and how general the recipe is.
To avoid that, this function can be turned into iterative, but it still will maintain the stack of neighbors to collapse, which will grow in memory, instead of on a stack.
I&amp;rsquo;ve decided to go with recursion, as it&amp;rsquo;s a bit easier to understand in the context of the post.&lt;/p&gt;
&lt;p&gt;The last bit needed is a loop that will repeat this process until the whole world is collapsed.
The process is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pick a cell with the lowest entropy, first one is random&lt;/li&gt;
&lt;li&gt;collapse it&lt;/li&gt;
&lt;li&gt;constrain neighbors&lt;/li&gt;
&lt;li&gt;check if not done
&lt;ul&gt;
&lt;li&gt;repeat&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;rsquo;s the code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recipe&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;build-recipe&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;populate-world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rand-int &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;count &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;first &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rand-int &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;count &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;))]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;if-not &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;done?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;collapse&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rand-nth&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;collapse-neighbors&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recipe&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lowest-entropy-cell&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we can actually try it!
Let&amp;rsquo;s create some helpers, that will print the resulting world, and the input recipe:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; add [clojure.string :as str] to :require&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;print-sample&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;str/join&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;str/join&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;println&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;print-world&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;print-world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sep&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;#(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;?&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;#(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;str/join&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sep&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;str/join&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;println&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;print-result&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;println &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;sample:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;print-sample&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;println &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;gen:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;print-world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, if we use our &lt;code&gt;coast&lt;/code&gt; recipe, we should see this in our REPL:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wfc.wfc&amp;gt; (print-result coast (wfc (gen-world 16 16) coast))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sample:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟩🟩🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟩🟦🟦🟩
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟦🟦🟦🟦
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟦🟦🟦🟦
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gen:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟫🟫🟫🟫🟩🟫🟫🟫🟫🟫🟫🟫🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟫🟫🟫🟩🟦🟩🟫🟫🟫🟫🟫🟫🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟫🟫🟩🟦🟦🟦🟩🟫🟫🟫🟫🟫🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟫🟩🟦🟦🟦🟦🟦🟩🟩🟫🟫🟫🟫
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟫🟩🟦🟦🟦🟦🟦🟦🟦🟦🟩🟫🟩🟩
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟫🟫🟩🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟩🟦🟦
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟩🟩🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can try with a bit more interesting examples, like these trees:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;snowy-trees&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;╱&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;╲&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;╱&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;v&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;v&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;╲&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;╱&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;v&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;v&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;v&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;v&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;╲&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;]])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wfc.wfc&amp;gt; (print-result snowy-trees (wfc (gen-world 16 60) snowy-trees))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sample:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*    *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  *╱╲ *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* ╱vv╲
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ╱vvvv╲
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gen:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; *  *  *   *   *      *   *     *    *   *  * *    * *  *  *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   *  *  *    * * * *   *  * *    *    *     *  * * *  *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; *      *      *              *  *       * *   *   *  * * *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  * * *   *   * * *  * *  *     *    * *  *   * *      * *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; *   *   *   * *   *  *  *  * *  *  *   *  * * * *        *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   *    *  *      *       *  *  *  *  *  *    * * *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; *        * * *  *  *  * *     *  * *     * *      * * * * *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  *  *  *    *  * *  *     *  *  * *  *  * *    *   *   * *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         * *   * * *      *    *  *     * *  * *  ╱╲  *  *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   *  * * *   *       *  *    *      *        * *╱vv╲  *   *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*   *  *   * *     * * *   *     *  *  * *  *  *╱vvvv╲
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  *   *   * *   * *     *   *   *  *    * *  * ╱vvvvvv╲
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; *  *   *     *   ╱╲ *    *   *   *  ╱╲  *  * ╱vvvvvvvv╲ *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         *     * ╱vv╲ *  *  ╱╲ * * *╱vv╲   * ╱vvvvvvvvvv╲ *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; *   *     *    ╱vvvv╲  * *╱vv╲ * *╱vvvv╲ * ╱vvvvvvvvvvvv╲
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*  ╱╲ *  ╱╲  * ╱vvvvvv╲   ╱vvvv╲ *╱vvvvvv╲ ╱vvvvvvvvvvvvvv╲
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Noticeable, the spread is too uniform.
This is because we pick a random choice, and the choices have equal distribution.
Instead, it&amp;rsquo;d be nicer if we had a bit more control over what elements are more present and what is less present.&lt;/p&gt;
&lt;p&gt;To do that, we need to replace our random choice picking with weighted random.
First, we need to calculate the weights:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample-weights&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;frequencies&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;apply concat &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will do - the more times a certain tile appears in a recipe, the higher its weight is.
Now we need a weighted random:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weighted-random&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;elements&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;variants&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;reduce &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;k&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;k&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;k&lt;/span&gt;))) {} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;elements&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;reductions&lt;/span&gt; #(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;vals &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;variants&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rnd&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rand-int &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;last &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;nth &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;keys &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;variants&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;count &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;take-while &lt;/span&gt;#(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rnd&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now, that we have weights, we can upgrade our &lt;code&gt;lowest-entropy-cell&lt;/code&gt; function to take weights into account when calculating the entropy.
We also use a better entropy calculation algorithm, based on &lt;a href=&#34;https://en.wikipedia.org/wiki/Entropy_%28information_theory%29&#34; target=&#34;_blank&#34;&gt;Shannon entropy:&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell-enthropy&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weight-sum&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;reduce + &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;#(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;log-weight-sum&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;reduce + &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;#(&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weight&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                         (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weight&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/log&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;double &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weight&lt;/span&gt;)))) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/log&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weight-sum&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;log-weight-sum&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weight-sum&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lowest-entropy-cell&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;enthropies&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;map-indexed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;keep-indexed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                              (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                [(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell-enthropy&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt;) [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;]])) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;reduce into &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sorted-map&lt;/span&gt;)))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;if-some&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;first &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;enthropies&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      [0 0])))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The last change needed is in the &lt;code&gt;wfc&lt;/code&gt; function - we need to use &lt;code&gt;weighted-random&lt;/code&gt; when we &lt;code&gt;collapse&lt;/code&gt; a cell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recipe&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;build-recipe&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample-weights&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;populate-world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rand-int &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;count &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;first &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rand-int &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;count &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;))]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;if-not &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;done?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;collapse&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weighted-random&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;collapse-neighbors&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recipe&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lowest-entropy-cell&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;weights&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the algorithm is done, and we can see that the &lt;code&gt;snowy-trees&lt;/code&gt; example has a bit less snow now:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wfc.wfc&amp;gt; (print-result snowy-trees (wfc (gen-world 16 60) snowy-trees))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sample:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*    *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  *╱╲ *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* ╱vv╲
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ╱vvvv╲
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gen:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   *    *    *   *  *       *      *           * *         *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  *        *    *         *     *       *       * *   * *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       *      *        *   *         *    *   *    *   *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   *                *        *     *  *    *     *   *   *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*             *  * *      *          *       *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           *           *   *    *       * *             *  *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              *  *    *            *   *      *      *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    *     *  *     * *     *    *    *     *           * *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   * *     *          * *   *  *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          *    *       *  *       *   * *   *     *  * *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  * *       * *    * *   *     *   * * *            *   *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       *   *    *                 *      *        ╱╲ *     *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      *      *        * *            *      *  * ╱vv╲
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     * ╱╲            *    * *          *  *     ╱vvvv╲
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ╱vv╲   ╱╲  *       *      *        *  *  ╱vvvvvv╲
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  *  ╱vvvv╲ ╱vv╲   ╱╲  *  * *           * *  *╱vvvvvvvv╲  *╱
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;working-with-images&#34;&gt;Working with images&lt;/h2&gt;
&lt;p&gt;At the beginning of this article, I&amp;rsquo;ve shown you an image of a coast.
This image is generated by the code above, but right now it can&amp;rsquo;t handle images, only text.
This isn&amp;rsquo;t a problem, really, because the text is just used in place of unique identifiers, so we can plug in anything, and then use the resulting world as a recipe to paint it on a canvas.
Let&amp;rsquo;s do exactly that, but before we can do it, we need to be able to upload an image and splice it into tiles.&lt;/p&gt;
&lt;p&gt;To do that, we&amp;rsquo;ll need an &lt;code&gt;index.html&lt;/code&gt; file in our &lt;code&gt;public/&lt;/code&gt; directory, and a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; tag in it with an appropriate &lt;code&gt;id&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;canvas id=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;sample_view&amp;#34;&lt;/span&gt; width=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;512&amp;#34;&lt;/span&gt; height=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;512&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/canvas&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;input type=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt; id=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;sample_input&amp;#34;&lt;/span&gt; accept=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;image/*&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/input&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;script type=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt; src=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;/js/main.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt;.onload = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wfc.core.init();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m also adding an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; tag, to open an image.
Additionally to that, there should be the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag that loads our &lt;code&gt;core&lt;/code&gt; module and runs the &lt;code&gt;init&lt;/code&gt; function.
With this in place, we can add an event listener to the button, and load the image to canvas.
In &lt;code&gt;core.cljs&lt;/code&gt; add:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc.core&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:require&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc.sample&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;^&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:export&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;init&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample-input&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;sample_input&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample-input&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;change&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample/upload&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And in &lt;code&gt;sample.cljs&lt;/code&gt; create the &lt;code&gt;upload&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defonce &lt;/span&gt;^&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:dynamic&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*image*&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:image&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:width&lt;/span&gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:height&lt;/span&gt; 0})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;viewer&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;sample_view&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;image&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/Image.&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getContext&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;viewer&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;2d&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;handler&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;image&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;image&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*image*&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:image&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                     &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                     &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;viewer&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;viewer&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.clearRect&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; 0 0 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;viewer&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;viewer&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.drawImage&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;image&lt;/span&gt; 0 0)))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;image&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;load&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;handler&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-src&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;image&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-target&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-result&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;upload&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;files&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-target&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-files&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;reader&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/FileReader.&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;reader&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;load&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.readAsDataURL&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;reader&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;aget &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;files&lt;/span&gt; 0)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should allow us to upload an image.
Now we need to split it into tiles.
To do that, let&amp;rsquo;s add another button to our &lt;code&gt;index.html&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;button type=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;button&amp;#34;&lt;/span&gt; id=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;split_to_tiles&amp;#34;&lt;/span&gt;&amp;gt;Split to tiles&amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In &lt;code&gt;core.cljs&lt;/code&gt; we add another event listener:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc.core&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:require&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc.sample&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;^&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:export&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;init&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample-input&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;sample_input&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample-input&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;change&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample/upload&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tile-size&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;split_to_tiles&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tile-size&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample/split-to-tiles&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render-button&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;render&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render-button&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render/render&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And define the function that does the work:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defonce &lt;/span&gt;^&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:dynamic&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*sample*&lt;/span&gt; [])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defonce &lt;/span&gt;^&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:dynamic&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*tiles*&lt;/span&gt; {})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;split-to-tiles&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:image&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*image*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.createElement&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;canvas&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*image*&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*image*&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getContext&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;2d&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.drawImage&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:image&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*image*&lt;/span&gt;) 0 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hashes-imgs&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;for &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;range &lt;/span&gt;0 (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*image*&lt;/span&gt;) 32)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;for &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;range &lt;/span&gt;0 (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*image*&lt;/span&gt;) 32)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;img&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getImageData&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; 32 32)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            [(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hash&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;img.data&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;img&lt;/span&gt;])))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*sample*&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mapv&lt;/span&gt; #(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mapv&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;first &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hashes-imgs&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*tiles*&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;into &lt;/span&gt;{} (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;apply concat &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hashes-imgs&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/alert&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Please upload an image first&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We do basic error checking, that an image was uploaded by checking &lt;code&gt;*image*&lt;/code&gt; to have anything under the &lt;code&gt;:image&lt;/code&gt; key.
If there&amp;rsquo;s an image, we create a canvas, that we draw this image on, and then iterate thru it row by row, tile by tile, with a fixed tile size of &lt;code&gt;32&lt;/code&gt;.
In this loop, we get an array of pixels, representing the given tile, and we calculate its hash, which we will use in our wave function collapse algorithm.&lt;/p&gt;
&lt;p&gt;Now we can upload an image, and split it into tiles, the only thing left is to actually draw the result!&lt;/p&gt;
&lt;h2 id=&#34;drawing-the-result&#34;&gt;Drawing the result&lt;/h2&gt;
&lt;p&gt;We need yet another canvas for that.
Actually, we need only one canvas for all of this, as we have the input button that takes care of image loading, and another button for splitting.
But I still like to see what sample is loaded, as it gives a better understanding of what the resulting image was constructed from.
So let&amp;rsquo;s add another canvas and a button:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;canvas id=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;render_view&amp;#34;&lt;/span&gt; width=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;512&amp;#34;&lt;/span&gt; height=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;512&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/canvas&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;button type=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;button&amp;#34;&lt;/span&gt; id=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;render&amp;#34;&lt;/span&gt;&amp;gt;Generate&amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once again, let&amp;rsquo;s add a handler to this button in &lt;code&gt;core.cljs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc.core&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:require&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc.sample&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc.render&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;^&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:export&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;init&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample-input&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;sample_input&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample-input&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;change&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample/upload&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tile-size&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;split_to_tiles&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tile-size&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample/split-to-tiles&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render-button&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;render&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render-button&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render/render&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And in &lt;code&gt;render.cljs&lt;/code&gt; we need to define the &lt;code&gt;render&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc.render&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:require&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc.sample&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc.wfc&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:image&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample/*image*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;renderer&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;render_view&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getContext&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;renderer&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;2d&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;renderer&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;renderer&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.clearRect&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; 0 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;solve&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/alert&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Please upload an image&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nothing too complicated, just a handler that clears the canvas and calls &lt;code&gt;solve&lt;/code&gt;.
Now, &lt;code&gt;solve&lt;/code&gt; is where the work is done:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;solve&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;seq &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample/*sample*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tiles&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample/*tiles*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;size&lt;/span&gt; 32]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc/wfc&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfc/gen-world&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;size&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;size&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sample/*sample*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; 0]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;row&lt;/span&gt; &amp;amp; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rows&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;world&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;row&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;row&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; 0]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt; &amp;amp; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cells&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;row&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tiles&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cell&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;size&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cells&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;size&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rows&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;size&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/alert&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Please split image to tiles&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First, we compute the result with &lt;code&gt;wfc&lt;/code&gt; call, and then we iterate over it calling &lt;code&gt;draw&lt;/code&gt; for each cell.
The tile is retrieved from the &lt;code&gt;*tiles*&lt;/code&gt; variable, we&amp;rsquo;ve set in &lt;code&gt;sample.cljs&lt;/code&gt; when we split the image.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;draw&lt;/code&gt; function is simple - it accepts an image, coordinates where we need to draw it, the size, and the canvas&amp;rsquo; context.
Then it just draws the image:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;image&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;size&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arr&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/Uint8ClampedArray.&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;image.data&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;place&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.getImageData&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;size&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;size&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.set&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.-data&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;place&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arr&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.putImageData&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;place&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The result will probably look a bit different, but the general idea is the same:&lt;/p&gt;
&lt;p&gt;&lt;canvas id=&#34;sample_view&#34; width=&#34;192&#34; height=&#34;160&#34; style=&#34;background-color: #888&#34;&gt;&lt;/canvas&gt;
&lt;br&gt;
&lt;input type=&#34;file&#34; id=&#34;sample_input&#34; accept=&#34;image/*&#34;&gt;&lt;/input&gt;
&lt;br&gt;
&lt;button type=&#34;button&#34; id=&#34;split_to_tiles&#34;&gt;Split to tiles&lt;/button&gt;
&lt;br&gt;
&lt;br&gt;
&lt;canvas id=&#34;render_view&#34; width=&#34;256&#34; height=&#34;256&#34; style=&#34;background-color: #888&#34;&gt;&lt;/canvas&gt;
&lt;br&gt;
&lt;br&gt;
&lt;button type=&#34;button&#34; id=&#34;render&#34;&gt;Generate&lt;/button&gt;&lt;/p&gt;
&lt;script type=&#34;text/javascript&#34; src=&#34;https://andreyor.st/2022-05-10-wave-function-collapse-algorithm-in-clojurescript/js/main.js&#34;&gt;&lt;/script&gt;
&lt;script&gt;
  window.onload = function() {
    wfc.core.init();
  }
&lt;/script&gt;
&lt;p&gt;You can use this image to try the whole process:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2022-05-10-wave-function-collapse-algorithm-in-clojurescript/coast.png&#34;
         alt=&#34;Figure 4: coast&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 4: &lt;/span&gt;coast&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Alternatively, you can try other samples, just beware that the tile size is fixed to 32x32 pixels.&lt;/p&gt;
&lt;h2 id=&#34;a-proper-demo&#34;&gt;A proper demo&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve actually omitted some more things on the JS side, as the post already got a bit to long even after we&amp;rsquo;ve finished the algorithm.
Things like configurable tile size, and custom world sizes, better error handling can be added, it&amp;rsquo;s just mostly the same stuff we already did for other buttons, and thus can get repetitive pretty quickly.
So instead I&amp;rsquo;ve set up a separate page with a better visuals, tile picker, editor, some additional examples to try, and more robust error handling.
You can try it &lt;a href=&#34;https://andreyor.st/wave-function-collapse/&#34;&gt;here&lt;/a&gt;.
And a bit more polished code can be found in the &lt;a href=&#34;https://gitlab.com/andreyorst/wave-function-collapse&#34; target=&#34;_blank&#34;&gt;repo&lt;/a&gt; for that demo page.&lt;/p&gt;
&lt;p&gt;I know that this isn&amp;rsquo;t how ClojureScript is used in production, but it&amp;rsquo;s still nice that you can build such pages pretty quickly, using your favorite language.
In the future I&amp;rsquo;ll probably learn some proper frontend related stuff, like Lumen or re-frame, but this is a thing for another time.
Hope this was an interesting read!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I&amp;rsquo;m saying lisp as in the language not as in concrete implementation.
To be clear, I&amp;rsquo;ve worked my way thru SICP, and mostly used Racked or GNU Guile, not Common Lisp, so I&amp;rsquo;m not biased on what is lisp, and I accept Clojure as a valid dialect, even if some may disagree.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;This includes &lt;a href=&#34;https://github.com/andreyorst/love-fabrik&#34; target=&#34;_blank&#34;&gt;LÖVE Fabrik&lt;/a&gt;, &lt;a href=&#34;https://andreyor.st/posts/2020-10-15-raymarching-with-fennel-and-love/&#34;&gt;raymarching&lt;/a&gt;, &lt;a href=&#34;https://andreyor.st/posts/2020-06-04-simple-ray-casting-with-clojurescript/&#34;&gt;raycasting&lt;/a&gt;.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;This is the approach I&amp;rsquo;ve taken when I&amp;rsquo;ve implemented my first Scheme-like language, condition-system, a library for asynchronous programming, raymarching algorithm, and many other projects.
I think I find this approach fascinating because when the thing finally works, and I go and look how it should be done, and see that I&amp;rsquo;ve got some things right, it gives me a lot of joy.
This also trains to think outside of the box, and solve problems that you don&amp;rsquo;t exactly know how to solve.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Wave Function Collapse Algorithm in ClojureScript&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Tue, 10 May 2022 08:20:00 +0300</pubDate>
    </item><item>
      <title>Raymarching with Fennel and LÖVE</title>
      <link>https://andreyor.st/posts/2020-10-15-raymarching-with-fennel-and-love/</link>
      <guid>https://andreyor.st/posts/2020-10-15-raymarching-with-fennel-and-love/</guid>
      <description>&lt;p&gt;Previously I decided to implement a rather basic &lt;a href=&#34;https://andreyor.st/posts/2020-06-04-simple-ray-casting-with-clojurescript/&#34;&gt;raycasting engine in ClojureScript&lt;/a&gt;.
It was a lot of fun, an interesting experience, and ClojureScript was awesome.
I&amp;rsquo;ve implemented a small &lt;a href=&#34;https://andreyor.st/posts/2020-06-04-simple-ray-casting-with-clojurescript/#labyrinth-game&#34;&gt;labyrinth game&lt;/a&gt; and thought about adding more features to the engine, such as camera shake, and wall height change.
But when I started working on these, I quickly understood, that I&amp;rsquo;d like to move on to something more interesting, like a real 3D rendering engine, that also uses rays.
&amp;lt;!&amp;ndash;more&amp;ndash;&amp;gt;
Obviously, my first thought was about writing a ray-tracer&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.
This technique is widely known and gained a lot of traction recently.
With native hardware support for ray tracing, a lot of games are using it, and there are a lot of tutorials teaching how to implement one&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.
In short, we cast a bunch of rays in 3D space, and calculate their trajectories, looking for what ray will hit and bounce off.
Different materials have different bounce properties, and by tracing rays from the camera to the source of light, we can imitate illumination.
There are also a lot of different approaches how to calculating bouncing, e.g. for global illumination, and ambient light, but I&amp;rsquo;ve felt that it is a rather complicated task, for a weekend post.
And unlike raycasting, most ray-tracers require polygonal information in order to work, whereas raycasting only needs to know wall start and end points.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve wanted a similar approach for 3D rendering, where we specify an object in terms of its mathematical representation.
Like for a sphere, we&amp;rsquo;ll just specify coordinates of a center, and a radius, and our rays will find intersection points with it, providing us sufficient data to draw this sphere on screen.
And recently, I&amp;rsquo;ve read about a similar technique, that uses rays for drawing on the screen, but instead of casting infinite rays as in raycasting, it marches a ray in terms of steps.
And it also uses a special trick, to make this process very optimized, therefore we can use it for rendering real 3D objects.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve decided to structure this post similarly to the one about raycasting, so this will be another long-read, often more about Fennel rather than raymarching, but at the end, I promise that we&amp;rsquo;ll get something that looks like this:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/end-result.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;So, just as in raycasting, first we need to do is to understand how the raymarching engine works &lt;em&gt;on paper&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&#34;raymarching-basics&#34;&gt;Raymarching basics&lt;/h2&gt;
&lt;p&gt;Raymarching can be illustrated similarly to raycaster, except it requires more steps until we could render our image.
First, we need a camera, and an object to look at:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/camera-and-circle.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Our first step would be to cast a ray, however, unlike with raycasting, we&amp;rsquo;ll cast a portion of a ray:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/camera-and-circle-short-ray.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;We then check if the ray intersects with the sphere.
It&amp;rsquo;s not, so we do one more step:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/camera-and-circle-two-steps.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;It&amp;rsquo;s not intersecting yet, so we repeat again:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/camera-and-circle-ray-overshoot.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Oops, the ray overshot and is now inside the sphere.
This is not really good option for us, as we want our rays to end directly at the object&amp;rsquo;s surface, without calculating the intersection point with the object itself.
We can fix this by casting a shorter ray:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/camera-and-circle-small-rays.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;However, this is very inefficient!
And besides, if we&amp;rsquo;ll change the angle a bit or move the camera, we will overshoot again.
This means that we&amp;rsquo;ll either have an incorrect result or require a very small step size, which will blow up the computation process.
How we can fix this?&lt;/p&gt;
&lt;h3 id=&#34;distance-estimation&#34;&gt;Distance estimation&lt;/h3&gt;
&lt;p&gt;The solution to this is a signed distance function or a so-called Distance Estimator.
Imagine if we knew how far we are from the object at any point in time?
This would mean that we can shoot a ray of this length in any direction and still don&amp;rsquo;t hit anything.
Let&amp;rsquo;s add another object to the scene:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/scene-with-two-objects.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Now, let&amp;rsquo;s draw two circles, which will represent distances from the objects to the point from where we&amp;rsquo;ll cast rays:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/distances.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;We can see, that there are two circles, and one is bigger than another.
This means, that if we choose the shortest safe distance, we can safely cast rays in any direction and not overshoot anything.
For example, let&amp;rsquo;s cast a ray towards the square:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/ray-in-safe-zone.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;We can see, that we haven&amp;rsquo;t reached the square, but more importantly, we did not overshoot it.
Now we need to march the ray again, but what distance should it cover?
To answer this question, we need to take another distance estimation from the ray end to the objects in the scene:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/second-safe-march.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Once again we choose a shorter distance, and march towards the square, then get the distance again, and repeat the whole process:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/another-safe-match.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;You can see that with each step the distance to the object becomes smaller, and thus we will never overshoot the object.
However, this also means, that we will take a lot of really small steps until we finally fully hit the object if we ever do.
This is not a good idea, because it is even more inefficient than using fixed distance, and produces too accurate results, which we don&amp;rsquo;t really need.
So instead of marching up until we exactly hit the object, we will march &lt;em&gt;enough&lt;/em&gt; times.
E.g., until the distance to the object is small enough, then there&amp;rsquo;s no real point to continue marching, as it is clear that we will hit the object soon.
But this also means, that if the ray goes near the edge of an object, we do a lot of expensive steps of computing distance estimations.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a ray that is parallel to the side of the square, and marches towards the circle:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/expensive-marching.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;We do a lot of seemingly pointless measurements, and if a ray was closer to the square&amp;rsquo;s side, we would do even more steps.
However, this also means, that we can use this data (since we&amp;rsquo;re already computed it) to render such things as glow, or ambient occlusion.
But more on this later.&lt;/p&gt;
&lt;p&gt;Once a ray hit an object we have all the data we need.
Ray represents a point on the screen, and the more rays we cast the higher resolution of our image will be.
And since we&amp;rsquo;re not using triangles to represent objects, our spheres will always be smooth, no matter how close we are to them, because there are no polygons involved.&lt;/p&gt;
&lt;p&gt;This is basically it.
Ray marching is a quite simple concept, just like raycaster, although it&amp;rsquo;s a bit more complicated, as we do have to compute things in 3D space now.
So let&amp;rsquo;s begin implementing it by installing the required tools, and setting up the project.&lt;/p&gt;
&lt;h2 id=&#34;project-structure&#34;&gt;Project structure&lt;/h2&gt;
&lt;p&gt;As you know from the title we will use two main tools to create ray-marcher, which are &lt;a href=&#34;https://love2d.org/&#34; target=&#34;_blank&#34;&gt;LÖVE&lt;/a&gt;, a free game engine, and &lt;a href=&#34;https://fennel-lang.org/&#34; target=&#34;_blank&#34;&gt;Fennel&lt;/a&gt; the programming language.
I&amp;rsquo;ve chosen Fennel, because it is a Lisp-like language, that compiles to Lua, and I&amp;rsquo;m quite a fan of Lisps.
But we also needed to draw somewhere, and I know no GUI toolkit for Lua.
But there is LÖVE - a game engine that runs Lua code, which is capable of running on all systems, thus a perfect candidate for our task.&lt;/p&gt;
&lt;p&gt;Installation steps may differ per operating system, so please refer to manuals&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;sup&gt;, &lt;/sup&gt;&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;.
At the time of writing this post, I&amp;rsquo;m using Fedora GNU/Linux, so for me it means:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sudo dnf install love luarocks readline-devel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ luarocks install --local fennel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ luarocks install --local readline &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;# requires readline-devel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;PATH&lt;/span&gt;=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;$PATH&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;$HOME&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;/.luarocks/bin&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s better to permanently add &lt;code&gt;$HOME/luarocks/bin&lt;/code&gt; (or another path, if your installation differs) to the &lt;code&gt;PATH&lt;/code&gt; variable in your shell, in order to be able to use installed utilities without specifying the full path every time.
You can test if everything is installed correctly, by running &lt;code&gt;fennel&lt;/code&gt; in your command line.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ fennel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Welcome to Fennel 0.5.0 on Lua 5.3!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Use (doc something) to view documentation.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt; (+ 1 2 3)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For other distributions, installation steps may vary, and for Windows, I think it&amp;rsquo;s safe to skip the &lt;code&gt;readline&lt;/code&gt; part, which is fully optional but makes editing in a REPL a bit more comfortable.&lt;/p&gt;
&lt;p&gt;Once everything is installed, let&amp;rsquo;s create the project directory and the &lt;code&gt;main.fnl&lt;/code&gt; file, where we will write our code.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ mkdir love_raymarching
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;cd&lt;/span&gt; love_raymarching
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ touch main.fnl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that&amp;rsquo;s it!
We can test if everything works by adding this code to &lt;code&gt;main.fnl&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.draw&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.graphics.print&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;It works!&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can compile it with &lt;code&gt;fennel --compile main.fnl &amp;gt; main.lua&lt;/code&gt;, thus producing the &lt;code&gt;main.lua&lt;/code&gt; file, and run &lt;code&gt;love .&lt;/code&gt; (dot is intentional, it indicates current directory).&lt;/p&gt;
&lt;p&gt;A window should appear, with white text &lt;code&gt;It works!&lt;/code&gt; in the upper left corner:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/love-works.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Now we can begin implementing our ray marcher.&lt;/p&gt;
&lt;h2 id=&#34;scene-setup&#34;&gt;Scene setup&lt;/h2&gt;
&lt;p&gt;Just as in raycaster, we need a camera that will shoot rays, and some objects to look at.
Let&amp;rsquo;s begin by creating a camera object, that will store coordinates and rotation information.
We can do so, by using &lt;code&gt;var&lt;/code&gt; to declare a variable that is local to our file, and that we can later change with &lt;code&gt;set&lt;/code&gt;&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;code-snippet--camera-unit&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [0.0 0.0 0.0]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x-rotate&lt;/span&gt; 0.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:z-rotate&lt;/span&gt; 0.0})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;For those unfamiliar with Lisps, and especially Clojure, let me quickly explain what this syntax is.
If you know this stuff, feel free to &lt;a href=&#34;#org-target--end-of-syntax-explanation&#34;&gt;skip this part&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We start by using a &lt;code&gt;var&lt;/code&gt; special form, that binds a value to a name like this: &lt;code&gt;(var name value)&lt;/code&gt;.
So if we start the REPL, using the &lt;code&gt;fennel&lt;/code&gt; command in the shell, and write &lt;code&gt;(var a 40)&lt;/code&gt;, a new variable &lt;code&gt;a&lt;/code&gt; will be created.
We then can check, that it has the desired value by typing &lt;code&gt;a&lt;/code&gt;, and pressing return:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 40)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;40
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can then alter the contents of this variable by using &lt;code&gt;set&lt;/code&gt; special form, which works like this &lt;code&gt;(set name new-value)&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 2))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;42
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now to curly and square brackets.
Everything enclosed in curly braces is a hashmap.
We can use any Lua value as our key, and the most common choice is a string, but Fennel has additional syntax for defining keys - a colon followed by a word: &lt;code&gt;:a&lt;/code&gt;.
This is called a keyword, and in Fennel, it is essentially the same as &lt;code&gt;&amp;quot;a&amp;quot;&lt;/code&gt;, but we don&amp;rsquo;t need to write a pair of quotes.
However, keywords can&amp;rsquo;t contain spaces and some other symbols.&lt;/p&gt;
&lt;p&gt;So writing this &lt;code&gt;{:a 0 :b 2 :c :hello}&lt;/code&gt; in the REPL will make a new table, that holds three key-value pairs, which we can later get with another syntax - the dot &lt;code&gt;.&lt;/code&gt;.
Combining it with &lt;code&gt;var&lt;/code&gt;, we can see that it works:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:b&lt;/span&gt; 2 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:c&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:hello&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:b&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There&amp;rsquo;s also a shorthand for this syntax, that is, we can type &lt;code&gt;m.b&lt;/code&gt; and access the &lt;code&gt;:b&lt;/code&gt; key&amp;rsquo;s value:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m.b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m.c&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice that even though we&amp;rsquo;ve specified the value for &lt;code&gt;:c&lt;/code&gt; as &lt;code&gt;:hello&lt;/code&gt;, the REPL printed it to us as &lt;code&gt;&amp;quot;hello&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re left with square brackets now, and this is a plain simple vector.
It can grow and shrink, and store any Lua values in it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; [0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;b c&amp;#34;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;a&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;b c&amp;#34;&lt;/span&gt; #&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;function&lt;/span&gt;&lt;span style=&#34;&#34;&gt;:&lt;/span&gt; 0&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x56482230e090&amp;gt;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However Lua doesn&amp;rsquo;t really have vectors or arrays, and it utilizes tables for this, where keys are simply indexes.
So the code above is equivalent to this Fennel expression &lt;code&gt;{1 0 2 &amp;quot;a&amp;quot; 3 &amp;quot;b c&amp;quot; 4 (fn [x] x)}&lt;/code&gt;, but we can use square brackets for convenience.&lt;/p&gt;
&lt;p&gt;Note, that we can combine indexed tables (vectors) and ordinary tables (hashmaps) together.
We can do it as shown above, by specifying indexes as keys, or defining a vector var and &lt;code&gt;set&lt;/code&gt; a key in it to some value:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v&lt;/span&gt; [0 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v.a&lt;/span&gt; 3)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt; 3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 1 0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 2 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 3 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;a&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;span class=&#34;org-target&#34; id=&#34;org-target--end-of-syntax-explanation&#34;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So camera is essentially a &lt;a href=&#34;https://www.lua.org/pil/2.5.html&#34; target=&#34;_blank&#34;&gt;Lua table&lt;/a&gt;, that stores keys &lt;code&gt;:pos&lt;/code&gt;, &lt;code&gt;:x-rotate&lt;/code&gt;, and &lt;code&gt;:y-rotate&lt;/code&gt;, each storing a respective value.
We use a vector as our position, and two floats as our rotation angles.
Now we can make objects, but before that, we need a scene to store those objects:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt; [])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yep, that&amp;rsquo;s our scene.
Nothing fancy, simply an empty vector to which we will later add objects.&lt;/p&gt;
&lt;p&gt;Now we can create these objects, so let&amp;rsquo;s start with perhaps the simplest one - a sphere.
And I&amp;rsquo;ll also briefly explain what makes raymarching different from other methods of creating 3D graphics.&lt;/p&gt;
&lt;h3 id=&#34;creating-objects&#34;&gt;Creating objects&lt;/h3&gt;
&lt;p&gt;What is a sphere?
That depends on the domain, we&amp;rsquo;re working in.
Let&amp;rsquo;s open up &lt;a href=&#34;https://www.blender.org/&#34; target=&#34;_blank&#34;&gt;Blender&lt;/a&gt;, remove the default cube, and create sphere with &lt;kbd&gt;Shift+a&lt;/kbd&gt;, Mesh, UV Sphere:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/blender-uv-sphere.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;To me, this looks nothing like a sphere, because it consists of rectangles.
However, if we subdivide the surface, we can get a more correct representation:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/blender-uv-sphere-subdivided.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;This looks more like a sphere, but this is still just an approximation.
Theoretically, if we move very close to it, we will see the edges and corners, especially with flat shading.
Also, each subdivision adds more points, and it gets more and more expensive to compute:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/subdivisions.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;We have to make these trade-offs because we don&amp;rsquo;t need very accurate spheres when we need real-time processing.
But raymarching doesn&amp;rsquo;t have this limitation, because the sphere in raymarching is defined by the point and radius length.
Which we can then work with by using the signed distance function.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s create a function, that will produce a sphere:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;radius&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;] &lt;span style=&#34;&#34;&gt;➊&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;] &lt;span style=&#34;&#34;&gt;➋&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt; [0 0 0])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; [1 1 1])]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:radius&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;radius&lt;/span&gt; 5)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; 0) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; 0) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt; 0)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:color&lt;/span&gt; [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt; 0) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g&lt;/span&gt; 0) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt; 0)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:sdf&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere-distance&lt;/span&gt; &lt;span style=&#34;&#34;&gt;➌&lt;/span&gt;}))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There&amp;rsquo;s a lot of stuff going on, so let&amp;rsquo;s dive into it.&lt;/p&gt;
&lt;p&gt;This is a so-called constructor - a function, that takes some parameters and constructs an object with these parameters applied, then returns it.
In most typed languages we would define a class, or structure to represent this object, however, in Fennel (and hence in Lua) we can just use a table.
And this is my favorite part of such languages.&lt;/p&gt;
&lt;p&gt;So we used &lt;code&gt;fn&lt;/code&gt; special form to create a function named &lt;code&gt;sphere&lt;/code&gt;, that takes three parameters: &lt;code&gt;radius&lt;/code&gt;, position in space &lt;code&gt;pos&lt;/code&gt;, and &lt;code&gt;color&lt;/code&gt; ➊.
Then we see another special form &lt;code&gt;let&lt;/code&gt;.
It is used to introduce locally scoped variables and has another nice property - destructuring ➋.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Let&amp;rsquo;s quickly understand how &lt;code&gt;let&lt;/code&gt; works in this case.
If you know how destructuring works, you can &lt;a href=&#34;#org-target--end-of-let-breakdown&#34;&gt;skip this part&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a simple example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt; 2]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;ve introduced two local variables &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, which hold values &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;2&lt;/code&gt; respectively.
Then we computed their sum and returned it as a result.&lt;/p&gt;
&lt;p&gt;This is good, but what if we wanted to compute a sum of three vector elements multiplied by &lt;code&gt;b&lt;/code&gt;?
Let&amp;rsquo;s put a vector into &lt;code&gt;a&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; [1 2 3]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt; 2]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;???&amp;gt;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are many ways to do this, such as &lt;code&gt;reduce&lt;/code&gt; over a vector with a function that sums elements, or getting values from the vector in a loop and putting those into some local variable.
However, in the case of our project, we always know exactly how many elements there will be, so we can just take these out by indexes without any kind of loop:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; [1 2 3]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt; 2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a1&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a2&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a3&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 3)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a3&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;12
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yet, this is very verbose, and not really good.
We can make it a bit less verbose by skipping local variable definitions and using values directly in the sum:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; [1 2 3]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt; 2]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;print &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;.. &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;value of the second element is &amp;#34;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 2)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 1) (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 2) (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 3)) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;second &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;element&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;is&lt;/span&gt; 2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;12
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, again, this isn&amp;rsquo;t really great, as we have to repeat the same syntax three times, and what if we want to use the second value from the vector in several places?
Like here, I&amp;rsquo;ve added &lt;code&gt;print&lt;/code&gt; since I particularly about the second element&amp;rsquo;s value, and want to see it in the log, but I have to repeat myself and get the second element twice.
We could use a local binding for this, but we don&amp;rsquo;t want to do this manually.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s where destructuring comes in handy, and trust me, it is a very handy thing.
We can specify a pattern, that is applied to our data, and binds variables for us like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a3&lt;/span&gt;] [1 2 3]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt; 2]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;print &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;.. &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;value of the second element is &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a3&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;second &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;element&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;is&lt;/span&gt; 2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;12
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works somewhat like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[1  2  3]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ↓  ↓  ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[a1 a2 a3]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is much shorter than any of the previous examples and allows us to use any vector values in several places.&lt;/p&gt;
&lt;p&gt;We can also destructure maps like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a-key&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:b-key&lt;/span&gt; 2})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a-key&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:b-key&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And this also has a shorthand for when the name of the key and the name of desired local binding will match:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:a&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:b&lt;/span&gt; 2})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[{&lt;span style=&#34;&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which is even shorter.&lt;/p&gt;
&lt;p&gt;All this essentially boils down to this kind of Lua code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- vector destructuring&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- (let [[a b] [1 2]] (+ a b))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; _0_ = {1, 2}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; a = _0_[1]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; b = _0_[2]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; (a + b)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- hashmap destructuring&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- (let [{: a : b} {:a 1 :b 2}] (+ a b))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; _0_ = {a = 1, b = 2}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; a = _0_[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;a&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; b = _0_[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;b&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; (a + b)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is nothing special really, but this example still shows the power of Lisp&amp;rsquo;s macro system, in which destructuring is implemented.
But it gets really cool when we use this in function forms, as we will see later.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span class=&#34;org-target&#34; id=&#34;org-target--end-of-let-breakdown&#34;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If we were to call &lt;code&gt;(sphere)&lt;/code&gt; now, we would get an error, because we specified a value ➌ for a key &lt;code&gt;:sdf&lt;/code&gt;, that doesn&amp;rsquo;t yet exist.
SDF stands for &lt;a href=&#34;https://en.wikipedia.org/wiki/Signed_distance_function&#34; target=&#34;_blank&#34;&gt;Signed Distance Function&lt;/a&gt;.
That is a function, that will return the distance from a given point to an object.
The distance is positive when the point is outside of the object and negative when the point is inside the object.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s define an SDF for a sphere.
What&amp;rsquo;s great about spheres, is that to compute the distance to the sphere&amp;rsquo;s surface, we only need to compute the distance to the center of the sphere, and subtract the sphere&amp;rsquo;s radius from this distance.&lt;/p&gt;
&lt;img src=&#34;https://andreyor.st/ltximg/2020-10-15-raymarching-with-fennel-and-love_9184447246721f1ac8fa15ea8fc4c62e5817d1d9.svg&#34; alt=&#34;\[d(P,S)=\sqrt{(S_x-P_x)^2+(S_y-P_y)^2+(S_z-P_z)^2}-S_r\]&#34; class=&#34;org-svg&#34; /&gt;
&lt;p&gt;Let&amp;rsquo;s implement this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sqrt&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;math.sqrt&lt;/span&gt;) &lt;span style=&#34;&#34;&gt;➊&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere-distance&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sy&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sz&lt;/span&gt;] &lt;span style=&#34;&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;radius&lt;/span&gt;} [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;]] &lt;span style=&#34;&#34;&gt;➋&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sqrt&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;(^ (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;) 2) (^ (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sy&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;) 2) (^ (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sz&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;) 2)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;radius&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For &lt;a href=&#34;https://www.lua.org/gems/sample.pdf&#34; target=&#34;_blank&#34;&gt;performance reasons&lt;/a&gt; we declare &lt;code&gt;math.sqrt&lt;/code&gt; as a &lt;code&gt;local&lt;/code&gt; variable &lt;code&gt;sqrt&lt;/code&gt;, that holds function value, to avoid repeated table lookup.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As was later pointed out, Luajit does optimize such calls, and there is no repeated lookup for method calls.
This is still true for plain Lua, so I&amp;rsquo;m going to keep this as is, but you can skip all these local definitions if you want and use methods directly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And at ➋ we again see destructuring, however not in the &lt;code&gt;let&lt;/code&gt; block, but in the function argument list.
What essentially happens here is this - function takes two parameters, the first of which is a hashmap, which must have a &lt;code&gt;:pos&lt;/code&gt; keyword associated with a vector of three numbers, and a &lt;code&gt;:radius&lt;/code&gt; keyword with a value.
The second parameter is simply a vector of three numbers.
We immediately destructured these parameters into a set of variables local to the function body.
Hashmap is being destructured into sphere position vector, which is immediately destructured to &lt;code&gt;sx&lt;/code&gt;, &lt;code&gt;sy&lt;/code&gt;, and &lt;code&gt;sz&lt;/code&gt;, and a &lt;code&gt;radius&lt;/code&gt; variable storing sphere&amp;rsquo;s radius.
Second parameter is destructured to &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, and &lt;code&gt;z&lt;/code&gt;.
We then compute the resulting value by using the formula above.
However, Fennel and Lua only understand definitions in the order from the top to the bottom, so we need to define &lt;code&gt;sphere-distance&lt;/code&gt; before &lt;code&gt;sphere&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s test our function by passing several points and a sphere of radius 5:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere-distance&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere&lt;/span&gt; 5) [5 0 0])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;0.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere-distance&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere&lt;/span&gt; 5) [0 15 0])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;10.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere-distance&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere&lt;/span&gt; 5) [0 0 0])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-5.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Great!
First, we check if we&amp;rsquo;re on the sphere&amp;rsquo;s surface, because the radius of our sphere is &lt;code&gt;5&lt;/code&gt;, and we&amp;rsquo;ve set &lt;code&gt;x&lt;/code&gt; coordinate to &lt;code&gt;5&lt;/code&gt; as well.
Next, we check if we&amp;rsquo;re &lt;code&gt;10&lt;/code&gt; something away from the sphere, and lastly, we check that we&amp;rsquo;re &lt;em&gt;inside&lt;/em&gt; the sphere because the sphere&amp;rsquo;s center and our point both are at the origin.&lt;/p&gt;
&lt;p&gt;But we also can call this function as a method with &lt;code&gt;:&lt;/code&gt; syntax:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;s&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;s&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:sdf&lt;/span&gt; [0 0 0])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works because methods in Lua are syntactic sugar.
When we write &lt;code&gt;(s:sdf p)&lt;/code&gt; it is essentially equal to &lt;code&gt;(s.sdf s p)&lt;/code&gt;, and our distance function takes sphere as its first parameter, which allows us to utilize method syntax.&lt;/p&gt;
&lt;p&gt;Now we need a distance estimator - a function that will compute distances to all objects and will return the shortest one, so we could then safely extend our ray by this amount.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;DRAW-DISTANCE&lt;/span&gt; 1000)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance-estimator&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;min &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;DRAW-DISTANCE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; [0 0 0])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;each&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;object&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ipairs&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;object&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:sdf&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;min&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set min &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;object&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:color&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;values&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;min &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This function will compute the distance to &lt;code&gt;each&lt;/code&gt; object in the &lt;code&gt;scene&lt;/code&gt; from given &lt;code&gt;point&lt;/code&gt;, using our signed distance functions, and will choose the minimum distance and the color of this ray.
Even though it makes little sense to return color from the distance-estimator, we&amp;rsquo;re doing this here because we don&amp;rsquo;t want to compute this whole process again just to get the color of the endpoint.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s check if this function works:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance-estimator&lt;/span&gt; [5 4 0] [(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere&lt;/span&gt; 2 [5 7 0] [0 1 0])])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.0     [0 1 0]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It works, we obtained the distance to the second sphere, and its color because the point we specified was closer to this sphere than to the other.&lt;/p&gt;
&lt;p&gt;With the camera, object, a scene, and this function we have all we need to start shooting rays and rendering this on screen.&lt;/p&gt;
&lt;h2 id=&#34;marching-ray&#34;&gt;Marching ray&lt;/h2&gt;
&lt;p&gt;Just as in raycaster, we cast rays from the camera, but now we do it in 3D space.
In raycasting, our horizontal resolution was specified by a number of rays, and our vertical resolution was basically infinite.
For 3D this is not an option, so our resolution now depends on the 2D matrix of rays, instead of the 1D matrix.&lt;/p&gt;
&lt;p&gt;Quick math.
How many rays we&amp;rsquo;ll need to cast in order to fill up 512 by 448 pixels?
The answer is simple - multiply width and height and here&amp;rsquo;s the amount of rays you&amp;rsquo;ll need:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;512 448)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;229376
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A stunning &lt;code&gt;229376&lt;/code&gt; rays to march.
And each ray has to do many distance estimations as it marches away from the point.
Suddenly, all that micro-optimizations, like locals for functions do not feel that unnecessary.
Let&amp;rsquo;s hope for the best and that LÖVE will handle real-time rendering.
We can begin by creating a function that marches a single ray in the direction our camera looks.
But first, we need to define what we would use to specify coordinates, directions, and so on in our 3D space.&lt;/p&gt;
&lt;p&gt;My first attempt was to use &lt;a href=&#34;https://en.wikipedia.org/wiki/Spherical_coordinate_system&#34; target=&#34;_blank&#34;&gt;spherical coordinates&lt;/a&gt; to define ray direction and move points in 3D space relative to the camera.
However, it had a lot of problems, especially when looking at objects at angles different from 90 degrees.
Like here&amp;rsquo;s a screenshot of me looking at the sphere from the &amp;ldquo;front&amp;rdquo;:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/spherical-ok.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;And here&amp;rsquo;s when looking from &amp;ldquo;above&amp;rdquo;:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/spherical-not-ok.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;And when I added the cube object, I noticed a &lt;em&gt;slight&lt;/em&gt; fish-eye distortion effect:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/spherical-distortion.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Which was not great at all.
So I&amp;rsquo;ve decided that I would remake everything with vectors, and make a proper camera, with a &amp;ldquo;look-at&amp;rdquo; point, will compute projection plane, and so on.&lt;/p&gt;
&lt;p&gt;And to do this we need to be able to work with vectors - add those, multiply, normalize, e.t.c.
I&amp;rsquo;ve wanted to refresh my knowledge on this topic, and decided not to use any existing library for vectors, and implement everything from scratch.
It&amp;rsquo;s not that hard.
Especially when we already have vectors in the language, and can destructure it to variables with ease.&lt;/p&gt;
&lt;p&gt;So we need these basic functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;vec3&lt;/code&gt; - a constructor with some handy semantics,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vec-length&lt;/code&gt; - function that computes magnitude of vector,&lt;/li&gt;
&lt;li&gt;arithmetic functions, such as &lt;code&gt;vec-sub&lt;/code&gt;, &lt;code&gt;vec-add&lt;/code&gt;, and &lt;code&gt;vec-mul&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;and other unit vector functions, mainly &lt;code&gt;normalize&lt;/code&gt;, &lt;code&gt;dot-product&lt;/code&gt;, and &lt;code&gt;cross-product&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;rsquo;s the source code of each of these functions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;) [0 0 0]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;)) [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt; 0)]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-length&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sqrt&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;(^ &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; 2) (^ &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; 2) (^ &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt; 2))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-sub&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z0&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;)])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-add&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z0&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;)])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-mul&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z0&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;)])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;norm&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;len&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-length&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;len&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;len&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;len&lt;/span&gt;)]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dot&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z0&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cross&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z0&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt;))])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since we already know how destructuring works, it&amp;rsquo;s not hard to see what these functions do.
&lt;code&gt;vec3&lt;/code&gt;, however, has some logic in it, and you can notice that &lt;code&gt;if&lt;/code&gt; has three outcomes.
&lt;code&gt;if&lt;/code&gt; in Fennel is more like &lt;code&gt;cond&lt;/code&gt; in other lisps, which means that we can specify as many &lt;code&gt;else if&lt;/code&gt; as we want.&lt;/p&gt;
&lt;p&gt;Therefore, calling it without arguments produces a zero-length vector &lt;code&gt;[0 0 0]&lt;/code&gt;.
If called with one argument, it returns a vector where each coordinate is set to this argument: &lt;code&gt;(vec 3)&lt;/code&gt; will produce &lt;code&gt;[3 3 3]&lt;/code&gt;.
In other cases we either specified or not specified &lt;code&gt;z&lt;/code&gt;, so we can simply create a vector with &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, and either &lt;code&gt;0&lt;/code&gt; or &lt;code&gt;z&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You may wonder, why this is defined as functions, and why I didn&amp;rsquo;t implement operator overloading, so we could simply use &lt;code&gt;+&lt;/code&gt; or &lt;code&gt;*&lt;/code&gt; to compute values?
I&amp;rsquo;ve tried this, however, this is extremely slow, since on each operation we have to do a lookup in meta-table, and this is like really slow.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a quick benchmark:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;macro&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;time &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;body&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  `(&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clock#&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;os.clock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;start#&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clock#&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;res#&lt;/span&gt; ,&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;body&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;end#&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clock#&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;print &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;.. &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Elapsed &amp;#34;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;1000 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;end#&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;start#&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; ms&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;res#&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; operator overloading&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;vector &lt;/span&gt;{})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vector.__index&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vector&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3-meta&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;setmetatable&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vector&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vector.__add&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z2&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3-meta&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z2&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v0&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3-meta&lt;/span&gt; 1 1 1))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;time &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;for &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 0 1000000] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v0&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; basic functions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vector-add&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z2&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z2&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v1&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; 1 1 1))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;time &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;for &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 0 1000000] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vector-add&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vector-add&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vector-add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v1&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v1&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v1&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we run it with &lt;code&gt;lua&lt;/code&gt; interpreter, we&amp;rsquo;ll see the difference:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ fennel --compile test.fnl | lua
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Elapsed 1667.58 ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Elapsed 1316.078 ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Testing this with &lt;code&gt;luajit&lt;/code&gt; claims that this way is actually faster, &lt;strong&gt;however&lt;/strong&gt;, I&amp;rsquo;ve experienced a major slowdown in the renderer - everything ran about 70% slower, according to the frame per second count.
So functions are okay, even though are much more verbose.&lt;/p&gt;
&lt;p&gt;Now we can define a &lt;code&gt;march-ray&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-point&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dir&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;] &lt;span style=&#34;&#34;&gt;➊&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-mul&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dir&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;MARCH-DELTA&lt;/span&gt; 0.0001)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;MAX-STEPS&lt;/span&gt; 500)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;march-ray&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;origin&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;direction&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;steps&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;not-done?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;true&lt;/span&gt;) &lt;span style=&#34;&#34;&gt;➋&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;not-done?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;&#34;&gt;➍&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;new-distance&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;new-color&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;origin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                             (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;direction&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                             (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance-estimator&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;new-distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;MARCH-DELTA&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;DRAW-DISTANCE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;steps&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;MAX-STEPS&lt;/span&gt;) &lt;span style=&#34;&#34;&gt;➌&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;not-done?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;false&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;new-distance&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;new-color&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;steps&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;steps&lt;/span&gt; 1))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;values&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;steps&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Not much, but we have some things to discuss.&lt;/p&gt;
&lt;p&gt;First, we define a function to move points in 3D space ➊.
It accepts a &lt;code&gt;point&lt;/code&gt;, which is a three-dimensional vector, a direction vector &lt;code&gt;dir&lt;/code&gt;, which must be normalized, and a &lt;code&gt;distance&lt;/code&gt;.
We then multiply the direction vector by a vector that consists of our distances and add it to the point.
Simple and easy.&lt;/p&gt;
&lt;p&gt;Next, we define several constants, and the &lt;code&gt;march-ray&lt;/code&gt; function itself.
It Defines some local vars, that hold initial values, and uses a &lt;code&gt;while&lt;/code&gt; loop to march a given ray enough times.
You can notice, that at ➋ we created a &lt;code&gt;not-done?&lt;/code&gt; var, that holds &lt;code&gt;true&lt;/code&gt; value, and then use it in the &lt;code&gt;while&lt;/code&gt; loop as our test.
And you also can notice that at ➌ we have a test, in case of which we &lt;code&gt;set&lt;/code&gt; &lt;code&gt;not-done?&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; and exit the loop.
So you may wonder, why not use &lt;code&gt;for&lt;/code&gt; loop instead?
Lua supports index-based &lt;code&gt;for&lt;/code&gt; loops.
Fennel also has support for these.
So why use &lt;code&gt;while&lt;/code&gt; with a &lt;code&gt;variable&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Because Fennel has no &lt;code&gt;break&lt;/code&gt; special form for some reason.&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;org-target&#34; id=&#34;org-target--break-rant&#34;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&amp;rsquo;s a little rant.
You &lt;a href=&#34;#org-target--end-of-break-rant&#34;&gt;can skip it&lt;/a&gt; if you&amp;rsquo;re not interested in me making unconfirmed inferences about Fennel :).&lt;/p&gt;
&lt;p&gt;I think that Fennel doesn&amp;rsquo;t support &lt;code&gt;break&lt;/code&gt; because Fennel is influenced by Clojure (correct me if I&amp;rsquo;m wrong), and Clojure doesn&amp;rsquo;t have &lt;code&gt;break&lt;/code&gt; either.
However, looping in Clojure is a bit more controllable, as we &lt;em&gt;choose&lt;/em&gt; when we want to go to the next iteration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 0]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; do stuff&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 10)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 1))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which means that &lt;code&gt;when&lt;/code&gt; &lt;code&gt;i&lt;/code&gt; is less then &lt;code&gt;10&lt;/code&gt; I want you to perform another iteration.&lt;/p&gt;
&lt;p&gt;In Fennel, however, the concept isn&amp;rsquo;t quite like this, because we have to define a &lt;code&gt;var&lt;/code&gt; explicitly, and put it into the &lt;code&gt;while&lt;/code&gt; test position:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 10)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; do stuff&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 1)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You may not see the difference, but I do.
This also can be trivially expressed as a &lt;code&gt;for&lt;/code&gt; loop: &lt;code&gt;(for [i 0 10] (do-stuff))&lt;/code&gt;.
However, not every construct can be defined as &lt;code&gt;for&lt;/code&gt; loop, when we don&amp;rsquo;t have &lt;code&gt;break&lt;/code&gt;.
And in Clojure we don&amp;rsquo;t have to declare a variable outside the loop, since &lt;code&gt;loop&lt;/code&gt; does it for us, but the biggest difference is here:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 0]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 100)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;some-foo&lt;/span&gt;) 1000))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;inc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice, that we&amp;rsquo;re looping until &lt;code&gt;i&lt;/code&gt; reaches &lt;code&gt;100&lt;/code&gt;, &lt;strong&gt;or&lt;/strong&gt; until &lt;code&gt;some-foo&lt;/code&gt; returns something greater than 1000.
We can easily express this as &lt;code&gt;for&lt;/code&gt; loop in Lua:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; i = 0, 100 &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; some_foo() &amp;gt; 1000 &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, we can&amp;rsquo;t do the same in Fennel, because there&amp;rsquo;s no &lt;code&gt;break&lt;/code&gt;.
In this case we could define &lt;code&gt;i&lt;/code&gt; var, put &lt;code&gt;some_foo() &amp;lt; 1000&lt;/code&gt; to the &lt;code&gt;while&lt;/code&gt; loop test, and then use break when &lt;code&gt;i&lt;/code&gt; reaches &lt;code&gt;100&lt;/code&gt;, like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 100)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;some-foo&lt;/span&gt;) 1000))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 1)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is almost like the Clojure example, and you may wonder why I complain, but in the case of &lt;code&gt;march-ray&lt;/code&gt; function, we can&amp;rsquo;t do this either!
Because the function we call returns multiple values, we need to destructure ➍ to be able to test those.
Or in some loops, such a function may depend on the context of the loop, so it has to be inside the loop, not in the test.&lt;/p&gt;
&lt;p&gt;So not having &lt;code&gt;break&lt;/code&gt;, or the ability to control when to go to the next iteration is a serious disadvantage.
Yes, Clojure&amp;rsquo;s &lt;code&gt;recur&lt;/code&gt; is also limited, since it must be in the tail position, so you can&amp;rsquo;t use it as &lt;code&gt;continue&lt;/code&gt; or something like that.
But it&amp;rsquo;s still a bit more powerful construct.
I&amp;rsquo;ve actually thought about writing a &lt;code&gt;loop&lt;/code&gt; macro, but it seems that it&amp;rsquo;s not as easy to do in Fennel, as in Clojure, because Fennel lacks some inbuilt functions to manipulate sequences.
I mean it&amp;rsquo;s totally doable, but requires way too much work compared to defining a Boolean &lt;code&gt;var&lt;/code&gt; and setting it in the loop.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span class=&#34;org-target&#34; id=&#34;org-target--end-of-break-rant&#34;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;At ➍ we see the syntax that I didn&amp;rsquo;t cover before: &lt;code&gt;(let [(a b) (foo)] ...)&lt;/code&gt;.
Many of us, who are familiar with Lisp and especially Racket may be confused.
You see, in Racket, and other Scheme implementations (that allow using different kinds of parentheses) &lt;code&gt;let&lt;/code&gt; has this kind of syntax:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-racket&#34; data-lang=&#34;racket&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;let&lt;/span&gt; [(a 1)   &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; In Scheme square brackets around bindings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (b 41)] &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; are replaced with parentheses&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; a b))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or more generally, &lt;code&gt;(let ((name1 value1) (name2 value2) ...) body)&lt;/code&gt;.
However, in the case of the &lt;code&gt;march-ray&lt;/code&gt; function, we see a similar form, except the second element has no value specified.
This is again a valid syntax in some lisps (Common Lisp, for example), as we can make a binding that holds &lt;em&gt;nothing&lt;/em&gt; and later &lt;code&gt;set&lt;/code&gt; it, but this is not what happens in this code, as we don&amp;rsquo;t use &lt;code&gt;foo&lt;/code&gt; at all:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;foo&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And, since in Fennel we don&amp;rsquo;t need parentheses, and simply specify bindings as a vector &lt;code&gt;[name1 value1 name2 value2 ...]&lt;/code&gt;, another possible confusion may happen.
You may think that &lt;code&gt;(a b)&lt;/code&gt; is a function call that returns a &lt;code&gt;name&lt;/code&gt;, and &lt;code&gt;(foo)&lt;/code&gt; is a function call that produces a &lt;code&gt;value&lt;/code&gt;.
But then we &lt;strong&gt;somehow&lt;/strong&gt; use &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;.
What is happening here?&lt;/p&gt;
&lt;p&gt;But this is just another kind of destructuring available in Fennel.&lt;/p&gt;
&lt;p&gt;Lua has 1 universal data type, called a table.
However Lua doesn&amp;rsquo;t have any special syntax for destructuring, so when a function needs to return several values, you have two options.
First, you can return a table:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;returns_table&lt;/span&gt;(a, b)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; {a, b}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But the user of such function will have to get values out of the table themselves:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; res = returns_table(1, 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; a, b = unpack(res) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- or use indexes, e.g. local a = res[1]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;a: &amp;#34;&lt;/span&gt; .. a .. &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;, b: &amp;#34;&lt;/span&gt; .. b)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- a: 1, b: 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But this is extra work, and it ties values together into a data structure, which may not be really good for you.
So Lua has a shorthand for this - you can return multiple values:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;returns_values&lt;/span&gt;(a, b)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; a, b
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; a, b = returns_values(1, 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;a: &amp;#34;&lt;/span&gt; .. a .. &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;, b: &amp;#34;&lt;/span&gt; .. b)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- a: 1, b: 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is shorter and more concise.
Fennel also support this multivalue return with &lt;code&gt;values&lt;/code&gt; special form:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;returns-values&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;values&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is equivalent to the previous code, but how do we use these values?
All binding forms in Fennel support destructuring, so we can write this as:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;returns-values&lt;/span&gt; 1 2))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;print &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;.. &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;a: &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;, b: &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; a: 1, b: 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Same can be done with vectors or maps when defining, &lt;code&gt;local&lt;/code&gt;, &lt;code&gt;var&lt;/code&gt;, or &lt;code&gt;global&lt;/code&gt; variables:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;returns-vector&lt;/span&gt;)) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; returns [1 2 3]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:z&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;} (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;returns-map&lt;/span&gt;)) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; returns {:x 1 :y 2 :z 3}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;global&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bar&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;baz&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;returns-values&lt;/span&gt;)) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; returns (values 1 2)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And all of this works in &lt;code&gt;let&lt;/code&gt; or when defining a function!&lt;/p&gt;
&lt;p&gt;OK.
We&amp;rsquo;ve defined a function that marches a ray, now we need to shoot some!&lt;/p&gt;
&lt;h2 id=&#34;shooting-rays&#34;&gt;Shooting rays&lt;/h2&gt;
&lt;p&gt;As with math functions, let&amp;rsquo;s define some local definitions somewhere at the top of the file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-points&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.graphics.points&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-dimensions&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.graphics.getDimensions&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-set-color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.graphics.setColor&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-key-pressed?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.keyboard.isDown&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-get-joysticks&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.joystick.getJoysticks&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is pretty much all we&amp;rsquo;ll need from LÖVE - two functions to draw colored pixels, one function to get the resolution of the window, and input handling functions for the keyboard and gamepad.
We&amp;rsquo;ll also define some functions in &lt;code&gt;love&lt;/code&gt; &lt;em&gt;namespace table&lt;/em&gt; (IDK how it is called properly in Lua, because it is a table that acts like a namespace) - &lt;code&gt;love.load&lt;/code&gt;, &lt;code&gt;love.draw&lt;/code&gt;, and others along the way.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s begin by initializing our window:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-width&lt;/span&gt; 512)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-height&lt;/span&gt; 448)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-flags&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:resizable&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:vsync&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;false&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:minwidth&lt;/span&gt; 256 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:minheight&lt;/span&gt; 224})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.load&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.window.setTitle&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;LÖVE Raymarching&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.window.setMode&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-flags&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will set our window&amp;rsquo;s default width and height to &lt;code&gt;512&lt;/code&gt; by &lt;code&gt;448&lt;/code&gt; pixels and set the minimum width and height to &lt;code&gt;256&lt;/code&gt; by &lt;code&gt;224&lt;/code&gt; pixels respectively.
We also add title &lt;code&gt;&amp;quot;LÖVE Raymarching&amp;quot;&lt;/code&gt; to our window, but it is fully optional.&lt;/p&gt;
&lt;p&gt;Now we can set &lt;code&gt;love.draw&lt;/code&gt; function, which will shoot 1 ray per pixel, and draw that pixel with the appropriate color.
However, we need a way of saying in which direction we want to shoot our ray.
To define the direction we will first need a projection plane and a look-at point.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s create a look-at point as a simple zero vector &lt;code&gt;[0 0 0]&lt;/code&gt; for now:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lookat&lt;/span&gt; [0 0 0])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we need to understand how we define our projection plane.
In our case, a projection plane is a plane that is our screen, and our camera is some distance away from the screen.
We also want to be able to change our field of view, or FOV for short, so we need a way of computing the distance to projection, since the closer we are to the projection plane, the wider our field of view:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/distances-to-projection-plane.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;We can easily compute the distance if we have an angle, which we also can define as a &lt;code&gt;var&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov&lt;/span&gt; 60)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can compute our projection distance (PD), by using this formula:&lt;/p&gt;
&lt;img src=&#34;https://andreyor.st/ltximg/2020-10-15-raymarching-with-fennel-and-love_32b13e61133b5f79cc4ee40a35afa13e72a8e735.svg&#34; alt=&#34;\[PD=\frac{1}{\tan{(fov/2)}}\]&#34; class=&#34;org-svg&#34; /&gt;
&lt;p&gt;Where &lt;code&gt;fov&lt;/code&gt; is in Radians.
And to compute radians we&amp;rsquo;ll need this constant:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;RAD&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;math.pi&lt;/span&gt; 180.0))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can transform any angle into radians by multiplying it by this value.&lt;/p&gt;
&lt;p&gt;At this point, we know what is the distance to our projection plane, but we don&amp;rsquo;t know its size and position.
First, we need a ray origin (&lt;code&gt;RO&lt;/code&gt;), and we already have it as our camera, so our &lt;code&gt;ro&lt;/code&gt; will be equal to the current value of &lt;code&gt;camera.pos&lt;/code&gt;.
Next, we need a look-at point, and we have it as a &lt;code&gt;lookat&lt;/code&gt; variable, which is set to &lt;code&gt;[0 0 0]&lt;/code&gt;.
Now we can define a direction vector, that will specify our &lt;em&gt;forward direction&lt;/em&gt;:&lt;/p&gt;
&lt;img src=&#34;https://andreyor.st/ltximg/2020-10-15-raymarching-with-fennel-and-love_ff94fdb25712c79044bfb62102c21558e710b0cc.svg&#34; alt=&#34;\[\overrightarrow{F}=normalize(\overrightarrow{lookat}-\overrightarrow{ro})\]&#34; class=&#34;org-svg&#34; /&gt;
&lt;p&gt;And with this vector &lt;code&gt;F&lt;/code&gt; if we move our point the distance that we&amp;rsquo;ve computed previously, we&amp;rsquo;ll navigate the center of our projection plane, which we can call &lt;code&gt;C&lt;/code&gt;:&lt;/p&gt;
&lt;img src=&#34;https://andreyor.st/ltximg/2020-10-15-raymarching-with-fennel-and-love_c12545f0f21b7028183e58e928fa64ce358535e6.svg&#34; alt=&#34;\[\overrightarrow{C}=\overrightarrow{RO}+\overrightarrow{F}\cdot{PD}\]&#34; class=&#34;org-svg&#34; /&gt;
&lt;p&gt;The last thing we need to know, in order to get our orientation in space, is where is &lt;em&gt;up&lt;/em&gt; and &lt;em&gt;right&lt;/em&gt;.
We can compute this by specifying an upward vector and taking a cross product of it and our forward vector, thus producing a vector that is perpendicular to both of these vectors, and pointing to the right.
To do this we need an up vector, which we define like this &lt;code&gt;[0 0 -1]&lt;/code&gt;.
You may wonder why it is defined with the z-axis negative, but this is done so positive z values actually go up as we look from the camera, and the right is to the right.
We then compute the right vector as follows:&lt;/p&gt;
&lt;img src=&#34;https://andreyor.st/ltximg/2020-10-15-raymarching-with-fennel-and-love_bb975b5a9462d9d4d29cb464c294a9c493a095d2.svg&#34; alt=&#34;\[\overrightarrow{R}=normalize(cross(\overrightarrow{F},\begin{bmatrix}0&amp;amp;amp;0&amp;amp;amp;-1\end{bmatrix}))\]&#34; class=&#34;org-svg&#34; /&gt;
&lt;p&gt;And the up vector &lt;code&gt;U&lt;/code&gt; is a cross product of &lt;code&gt;R&lt;/code&gt; and &lt;code&gt;F&lt;/code&gt;. Let&amp;rsquo;s write this down as in &lt;code&gt;love.draw&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.draw&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-dimensions&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;projection-distance&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;1 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tan&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov&lt;/span&gt; 2) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;RAD&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ro&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.pos&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;norm&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-sub&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lookat&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ro&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ro&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-mul&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;projection-distance&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;norm&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cross&lt;/span&gt; [0 0 -1] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;u&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cross&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;)) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; TBD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Currently, we only compute these values but do not use those, hence the &lt;code&gt;nil&lt;/code&gt; at the end of the &lt;code&gt;let&lt;/code&gt;.
But now, as we know where our projection plane is, and where our right and up are, we can compute the intersection point, where at given &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinates of a plane in unit vector coordinates, thus defining a direction vector.&lt;/p&gt;
&lt;p&gt;So, &lt;code&gt;for&lt;/code&gt; each &lt;code&gt;x&lt;/code&gt; from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;width&lt;/code&gt; and each &lt;code&gt;y&lt;/code&gt; from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;height&lt;/code&gt; we will compute a &lt;code&gt;uv-x&lt;/code&gt; and &lt;code&gt;uv-y&lt;/code&gt; coordinates, and find the direction vector &lt;code&gt;rd&lt;/code&gt;.
To find the &lt;code&gt;uv-x&lt;/code&gt; we need to make sure it is between &lt;code&gt;-1&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; by dividing current &lt;code&gt;x&lt;/code&gt; by &lt;code&gt;width&lt;/code&gt; and subtracting &lt;code&gt;0.5&lt;/code&gt; from it, then multiplying by &lt;code&gt;x/width&lt;/code&gt;.
For &lt;code&gt;uv-y&lt;/code&gt; we only need to divide current &lt;code&gt;y&lt;/code&gt; by height, and subtract &lt;code&gt;0.5&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;for &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;for &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;uv-x&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt;) 0.5) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;uv-y&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;) 0.5)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;))) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; TBD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now as we have &lt;code&gt;uv-x&lt;/code&gt; and &lt;code&gt;uv-y&lt;/code&gt;, we can compute intersection point &lt;code&gt;i&lt;/code&gt;, by using the up and right vectors and the center of the plane:&lt;/p&gt;
&lt;img src=&#34;https://andreyor.st/ltximg/2020-10-15-raymarching-with-fennel-and-love_a69b83ebed3bcf5eca644e7d65e9b0d62504bb41.svg&#34; alt=&#34;\[\overrightarrow{I}=\overrightarrow{C}\cdot(\overrightarrow{R}\cdot{X_{UV}}+\overrightarrow{U}\cdot{Y_{UV}})\]&#34; class=&#34;org-svg&#34; /&gt;
&lt;p&gt;And finally, compute our direction vector &lt;code&gt;RD&lt;/code&gt;:&lt;/p&gt;
&lt;img src=&#34;https://andreyor.st/ltximg/2020-10-15-raymarching-with-fennel-and-love_e500d651acc2ee6f01323734028400ea32660648.svg&#34; alt=&#34;\[\overrightarrow{RD}=normalize(\overrightarrow{I}-\overrightarrow{RO})\]&#34; class=&#34;org-svg&#34; /&gt;
&lt;p&gt;And now we can use our &lt;code&gt;march-ray&lt;/code&gt; procedure to compute the distance and color of the pixel.
Let&amp;rsquo;s wrap everything up:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tan&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;math.tan&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.draw&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;projection-distance&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;1 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tan&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov&lt;/span&gt; 2) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;RAD&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ro&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.pos&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;norm&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-sub&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lookat&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ro&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ro&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-mul&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;projection-distance&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;norm&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cross&lt;/span&gt; [0 0 -1] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;u&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cross&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-dimensions&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;for &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;for &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;uv-x&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt;) 0.5) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;uv-y&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;) 0.5)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-add&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-mul&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;uv-x&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-mul&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;u&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;uv-y&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rd&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;norm&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-sub&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ro&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;march-ray&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ro&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rd&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;DRAW-DISTANCE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-set-color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-set-color&lt;/span&gt; 0 0 0))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-points&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, if we set the &lt;code&gt;scene&lt;/code&gt; to contain a default &lt;code&gt;sphere&lt;/code&gt;, and place our camera at &lt;code&gt;[20 0 0]&lt;/code&gt;, we should see this:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/results-so-far.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;This is correct because our default sphere has white as the default color.&lt;/p&gt;
&lt;p&gt;You can notice, that we compute &lt;code&gt;distance&lt;/code&gt; and &lt;code&gt;color&lt;/code&gt; by calling &lt;code&gt;(march-ray ro rd scene)&lt;/code&gt;, and then check if &lt;code&gt;distance&lt;/code&gt; is less than &lt;code&gt;DRAW-DISTANCE&lt;/code&gt;.
If this is the case, we set the pixel&amp;rsquo;s color to the &lt;code&gt;color&lt;/code&gt; found by &lt;code&gt;march-ray&lt;/code&gt; function, otherwise, we set it to black.
Lastly, we draw the pixel to the screen and repeat the whole process for the next intersection point, thus the next pixel.&lt;/p&gt;
&lt;p&gt;But we don&amp;rsquo;t have to draw black pixels if we didn&amp;rsquo;t hit anything!
Remember, that in the beginning, I&amp;rsquo;ve written, that if we go past the object, we do many steps, and we can use this data to render glow.
So if we modify &lt;code&gt;love.draw&lt;/code&gt; function a bit, we will be able to see the glow around our sphere.
And the closer the gay got to the sphere, the stronger the glow will be:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; rest of love.draw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[ &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; rest of love.draw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;steps&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;march-ray&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ro&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rd&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;DRAW-DISTANCE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-set-color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-set-color&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;steps&lt;/span&gt; 100))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-points&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; rest of love.draw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here, I&amp;rsquo;m setting the color to the number of steps divided by &lt;code&gt;100&lt;/code&gt;, which results in this glow effect:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/glow.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Similarly to this glow effect, we can create a fake ambient occlusion - the more steps we did before hitting the surface, the more complex it is, hence less ambient light should be able to pass.
Unfortunately, the only object we have at this moment is a sphere, so there&amp;rsquo;s no way of showing this trick on it, as its surface isn&amp;rsquo;t very complex.&lt;/p&gt;
&lt;p&gt;All this may seem expensive, and it actually is.
Unfortunately, Lua doesn&amp;rsquo;t have real multithreading to speed this up, and the &lt;a href=&#34;https://love2d.org/wiki/love.thread&#34; target=&#34;_blank&#34;&gt;threads&lt;/a&gt; feature, provided by LÖVE results in even worse performance than computing everything in a single thread.
Well, at least the way I&amp;rsquo;ve tried it.
There&amp;rsquo;s a &lt;a href=&#34;https://love2d.org/wiki/Shader&#34; target=&#34;_blank&#34;&gt;shader DSL&lt;/a&gt; in LÖVE, which could be used to compute this stuff on GPU, but this is currently out of the scope of this project, as I wanted to implement this in Fennel.&lt;/p&gt;
&lt;p&gt;Speaking of shaders, now, that we can draw pixels on the screen, we also can shade those, and compute lighting and reflections!&lt;/p&gt;
&lt;h2 id=&#34;lighting-and-reflections&#34;&gt;Lighting and reflections&lt;/h2&gt;
&lt;p&gt;Before we begin implementing lighting, let&amp;rsquo;s add two more objects - a ground plane, and an arbitrary box.
Much like a sphere object, we first define the signed distance function, and then the constructor for the object:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;abs&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;math.abs&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box-distance&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box-x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box-y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box-z&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:dimensions&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x-side&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y-side&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z-side&lt;/span&gt;]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sqrt&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;(^ (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;max &lt;/span&gt;0 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;abs&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box-x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;)) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x-side&lt;/span&gt; 2))) 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (^ (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;max &lt;/span&gt;0 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;abs&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box-y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;)) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y-side&lt;/span&gt; 2))) 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (^ (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;max &lt;/span&gt;0 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;abs&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box-z&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;)) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z-side&lt;/span&gt; 2))) 2))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sides&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt; [0 0 0])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x-side&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y-side&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z-side&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sides&lt;/span&gt; [10 10 10])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; [1 1 1])]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:dimensions&lt;/span&gt; [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x-side&lt;/span&gt; 10)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y-side&lt;/span&gt; 10)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z-side&lt;/span&gt; 10)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; 0) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; 0) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt; 0)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:color&lt;/span&gt; [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt; 0) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g&lt;/span&gt; 0) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt; 0)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:sdf&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box-distance&lt;/span&gt;}))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ground-plane&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; [1 1 1])]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:z&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:color&lt;/span&gt; [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt; 0) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g&lt;/span&gt; 0) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt; 0)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:sdf&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;plane&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;]] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;plane.z&lt;/span&gt;))}))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In case of &lt;code&gt;ground-plane&lt;/code&gt; we incorporate &lt;code&gt;:sdf&lt;/code&gt; as a anonymous function, because it is a simple one-liner.&lt;/p&gt;
&lt;p&gt;Now, as we have more objects, let&amp;rsquo;s add those to the scene and see if those work:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [20.0 50.0 0.0]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x-rotate&lt;/span&gt; 0.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:z-rotate&lt;/span&gt; 0.0})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt; [(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt; [-6 0 0] [1 0 0])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt; [6 0 0] [0 1 0])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ground-plane&lt;/span&gt; -10 [0 0 1])])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With this &lt;code&gt;scene&lt;/code&gt; and &lt;code&gt;camera&lt;/code&gt; we should see this:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/more-objects.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;It&amp;rsquo;s a bit sadistic in the eyes, but we can at least be sure that everything works correctly.
Now we can implement lighting.&lt;/p&gt;
&lt;p&gt;In order to calculate lighting, we&amp;rsquo;ll need to know a normal to the surface at the point.
Let&amp;rsquo;s create &lt;code&gt;get-normal&lt;/code&gt; function, that receives the &lt;code&gt;point&lt;/code&gt;, and our &lt;code&gt;scene&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-normal&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;px&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;py&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pz&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;MARCH-DELTA&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;d&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance-estimator&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;px&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;py&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pz&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dx&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance-estimator&lt;/span&gt; [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;px&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;py&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pz&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dy&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance-estimator&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;px&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;py&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pz&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dz&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance-estimator&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;px&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;py&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pz&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;)] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;norm&lt;/span&gt; [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;d&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dx&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;d&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dy&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;d&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dz&lt;/span&gt;)])))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is a nice trick, since we create three more points around our original point, use the existing distance estimation function, and get a normalized vector of subtraction of each axis from the original point, with the distance to the new point.
Let&amp;rsquo;s use this function to get normal for each point, and use the normal as our color:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; rest of love.draw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;DRAW-DISTANCE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-set-color&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-normal&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ro&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rd&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-set-color&lt;/span&gt; 0 0 0))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; rest of love.draw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice that in order to get endpoint of our ray we &lt;code&gt;move-point&lt;/code&gt; &lt;code&gt;ro&lt;/code&gt; along the direction &lt;code&gt;rd&lt;/code&gt; using the computed &lt;code&gt;distance&lt;/code&gt;.
We then pass the resulting point into &lt;code&gt;get-normal&lt;/code&gt;, and our &lt;code&gt;scene&lt;/code&gt;, thus computing the normal vector, which we then pass to &lt;code&gt;love-set-color&lt;/code&gt;, and it gives us this result:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/colored-normals.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;You can see that the &lt;code&gt;ground-plane&lt;/code&gt; remained blue, and this isn&amp;rsquo;t an error.
Blue in our case is &lt;code&gt;[0 0 1]&lt;/code&gt;, and since in our world, positive &lt;code&gt;z&lt;/code&gt; coordinates indicate &lt;em&gt;up&lt;/em&gt;, we can see it directly in the resulting color of the plane.
The top of the cube and the sphere are also blue, and the front side is green, which means that our normals are correct.&lt;/p&gt;
&lt;p&gt;Now we can compute basic lighting.
For that we&amp;rsquo;ll need a light object:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light&lt;/span&gt; [70 40 100])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s create a &lt;code&gt;shade-point&lt;/code&gt; function, that will accept a &lt;code&gt;point&lt;/code&gt;, point &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;light&lt;/code&gt; position, and a &lt;code&gt;scene&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shade-point&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-mul&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point-lightness&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It may seem that this function&amp;rsquo;s only purpose is to call &lt;code&gt;point-lightness&lt;/code&gt;, which we will define a bit later, and return a new color.
And this is true, at least for now.
Let&amp;rsquo;s create &lt;code&gt;point-lightness&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clamp&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;t&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;t&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;t&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;above-surface-point&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;normal&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-mul&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;normal&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;MARCH-DELTA&lt;/span&gt; 2)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point-lightness&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;normal&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-normal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;) &lt;span style=&#34;&#34;&gt;➊&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light-vec&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;norm&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-sub&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;march-ray&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;above-surface-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;normal&lt;/span&gt;) &lt;span style=&#34;&#34;&gt;➋&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light-vec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lightness&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clamp&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dot&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light-vec&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;normal&lt;/span&gt;) 0 1)] &lt;span style=&#34;&#34;&gt;➌&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;DRAW-DISTANCE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lightness&lt;/span&gt; 0.5)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lightness&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What this function does, is simple.
We compute the &lt;code&gt;normal&lt;/code&gt; ➊ for given &lt;code&gt;point&lt;/code&gt;, then we find a point that is just above the surface, using &lt;code&gt;above-surface-point&lt;/code&gt; function ➋.
And we use this point as our new ray origin to march towards the &lt;code&gt;light&lt;/code&gt;.
We then get the &lt;code&gt;distance&lt;/code&gt; from the &lt;code&gt;march-ray&lt;/code&gt; function and check if we&amp;rsquo;ve gone all the way to the max distance or not.
If not, this means that there was a hit, and we divide total &lt;code&gt;lightness&lt;/code&gt; by 2 thus creating a shadow.
In the other case, we return &lt;code&gt;lightness&lt;/code&gt; as is.
And &lt;code&gt;lightness&lt;/code&gt; is a dot product between &lt;code&gt;light-vec&lt;/code&gt; and &lt;code&gt;normal&lt;/code&gt; to the surface ➌, where &lt;code&gt;light-vec&lt;/code&gt; is a normalized vector from the &lt;code&gt;point&lt;/code&gt; to the &lt;code&gt;light&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we again modify our &lt;code&gt;love.draw&lt;/code&gt; function like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; rest of love.draw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;DRAW-DISTANCE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ro&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rd&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-set-color&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shade-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-set-color&lt;/span&gt; 0 0 0))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; rest of love.draw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We should see the shadows:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/shadows.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;This already looks like real 3D, and it is.
But we can do a bit more, so let&amp;rsquo;s add reflections.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s create a &lt;code&gt;reflection-color&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;reflection-count&lt;/span&gt; 3)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;reflection-color&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;direction&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;d&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;direction&lt;/span&gt; 0 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-normal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;)]) &lt;span style=&#34;&#34;&gt;➊&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;not-done?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;reflection-count&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;not-done?&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-sub&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;d&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-mul&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-mul&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dot&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;d&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;) [2 2 2])) &lt;span style=&#34;&#34;&gt;➋&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;new-color&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;march-ray&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;above-surface-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;)] &lt;span style=&#34;&#34;&gt;➌&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;DRAW-DISTANCE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold&#34;&gt;do &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;p&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-normal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;d&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r&lt;/span&gt;) &lt;span style=&#34;&#34;&gt;➍&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g0&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b0&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b1&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;new-color&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point-lightness&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light&lt;/span&gt;) 2)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r0&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l&lt;/span&gt;)) 0.66)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g0&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l&lt;/span&gt;)) 0.66)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b0&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l&lt;/span&gt;)) 0.66)]) &lt;span style=&#34;&#34;&gt;➎&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;not-done?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;false&lt;/span&gt;) &lt;span style=&#34;&#34;&gt;➏&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;i&lt;/span&gt; 1)) &lt;span style=&#34;&#34;&gt;➐&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is quite a big function, so let&amp;rsquo;s look at it piece by piece.&lt;/p&gt;
&lt;p&gt;First, we use destructuring to define several &lt;code&gt;vars&lt;/code&gt; ➊, which we will be able to change using &lt;code&gt;set&lt;/code&gt; later in the function.
Next, we go into the &lt;code&gt;while&lt;/code&gt; loop, which checks both for maximum reflections reached, and if the ray went to infinity.
The first thing we do in the loop, computes the reflection vector &lt;code&gt;r&lt;/code&gt; ➋, by using this formula:&lt;/p&gt;
&lt;img src=&#34;https://andreyor.st/ltximg/2020-10-15-raymarching-with-fennel-and-love_dc97ecd084b47c4884333ad30190962c2093b2a7.svg&#34; alt=&#34;\[\overrightarrow{R}=\overrightarrow{D}-\overrightarrow{N}\cdot{dotproduct}(\overrightarrow{D},\overrightarrow{N})\cdot{2}\]&#34; class=&#34;org-svg&#34; /&gt;
&lt;p&gt;This is our new direction, which we will march from new &lt;code&gt;above-surface-point&lt;/code&gt; ➌.
If we&amp;rsquo;ve hit something, and our &lt;code&gt;distance&lt;/code&gt; will be less than &lt;code&gt;DRAW-DISTANCE&lt;/code&gt;, we&amp;rsquo;ll &lt;code&gt;set&lt;/code&gt; our point &lt;code&gt;p&lt;/code&gt; to new point, compute new normal &lt;code&gt;n&lt;/code&gt;, and set direction &lt;code&gt;d&lt;/code&gt; to previous direction, which was reflection vector &lt;code&gt;r&lt;/code&gt; ➍.
Next, we compute the resulting color.
I&amp;rsquo;m doing a simple color addition here, which is not an entirely correct way of doing it, but for now, I&amp;rsquo;m fine with that.
We also compute &lt;code&gt;lightness&lt;/code&gt; of the reflection point, and divide it by &lt;code&gt;2&lt;/code&gt;, so our reflections appear slightly darker.
Then we add each channel and make sure it is not greater than &lt;code&gt;1&lt;/code&gt;, by multiplying it by &lt;code&gt;0.66&lt;/code&gt; ➎.
The trick here is that maximum &lt;code&gt;lightness&lt;/code&gt; we can get is &lt;code&gt;0.5&lt;/code&gt;, so if we add two values, one of which is multiplied by &lt;code&gt;0.5&lt;/code&gt; overall result can be averaged by multiplying by &lt;code&gt;0.66&lt;/code&gt;.
This way we do not lose brightness all the way and the reflection color blends with the original color nicely.&lt;/p&gt;
&lt;p&gt;In case we don&amp;rsquo;t hit anything, it means that this is the final reflection, therefore we can end ➏ the &lt;code&gt;while&lt;/code&gt; loop on this iteration.
Lastly, since I&amp;rsquo;ve &lt;a href=&#34;#org-target--break-rant&#34;&gt;already ranted&lt;/a&gt; on the absence of &lt;code&gt;break&lt;/code&gt; in Fennel, we have to increase the loop counter manually ➐ at the end of the loop.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s change &lt;code&gt;shade-point&lt;/code&gt; so it will pass color into this function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shade-point&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;direction&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-mul&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec3&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point-lightness&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;reflection-color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;direction&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can notice that I&amp;rsquo;ve added the &lt;code&gt;direction&lt;/code&gt; parameter, as we need it for computing reflections, so we also have to change the call to &lt;code&gt;shade-point&lt;/code&gt; in &lt;code&gt;love.draw&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; rest of love.draw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;DRAW-DISTANCE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ro&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rd&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-set-color&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shade-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rd&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;light&lt;/span&gt;))) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; rd is our initial direction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-set-color&lt;/span&gt; 0 0 0))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; rest of love.draw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s try this out (I&amp;rsquo;ve brought &lt;code&gt;ground-plane&lt;/code&gt; a bit closer to objects so we could better see reflections):&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/reflections.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;We can see reflections, and reflections of reflections in reflections, because previously we&amp;rsquo;ve set &lt;code&gt;reflection-count&lt;/code&gt; to &lt;code&gt;3&lt;/code&gt;.
Currently, our reflections are pure mirrors, as we reflect everything at a perfect angle, and shapes appear just as real objects.
This can be changed by introducing materials, that have different qualities like roughness, and by using better reflection algorithms like &lt;a href=&#34;https://en.wikipedia.org/wiki/Phong_reflection_model&#34; target=&#34;_blank&#34;&gt;Phong shading&lt;/a&gt;, but maybe next time.
Refractions also kinda need materials, as refraction angles can be different, depending on what kind of material it goes through.
E.g. glass and still pool of water should have different refraction angles.
And some surfaces should reflect rays at certain angles, and let them go through at other angles, which will also require certain modifications in the reflection algorithm.&lt;/p&gt;
&lt;p&gt;Now, if we would set our &lt;code&gt;camera&lt;/code&gt;, &lt;code&gt;lookat&lt;/code&gt;, and &lt;code&gt;light&lt;/code&gt; to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lookat&lt;/span&gt; [19.75 49 19.74])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [20 50 20]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x-rotate&lt;/span&gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:z-rotate&lt;/span&gt; 0})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scene&lt;/span&gt; [(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box&lt;/span&gt; [5 5 5] [-2.7 -2 2.5] [0.79 0.69 0.59])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box&lt;/span&gt; [5 5 5] [2.7 2 2.5] [0.75 0.08 0.66])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;box&lt;/span&gt; [5 5 5] [0 0 7.5] [0.33 0.73 0.42])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere&lt;/span&gt; 2.5 [-2.7 2.5 2.5] [0.56 0.11 0.05])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sphere&lt;/span&gt; 10 [6 -20 10] [0.97 0.71 0.17])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ground-plane&lt;/span&gt; 0 [0.97 0.27 0.35])])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We would see an image from the beginning of this post:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-10-15-raymarching-with-lua-and-love/end-result.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;For now, I&amp;rsquo;m pretty happy with the current result, so lastly let&amp;rsquo;s make it possible to move into our 3D space.&lt;/p&gt;
&lt;h2 id=&#34;user-input&#34;&gt;User input&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ll be doing two different ways of moving in our scene - with keyboard and gamepad.
The difference mostly is in the fact, that gamepads can give us floating point values, so we can move slower or faster depending on how we move the analogs.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve already specified needed functions from LÖVE as our locals, but to recap, we&amp;rsquo;ll need only two:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-key-pressed?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.keyboard.isDown&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-get-joysticks&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.joystick.getJoysticks&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But first, we&amp;rsquo;ll need to make changes to our &lt;code&gt;camera&lt;/code&gt;, as currently, it can only look at the origin.&lt;/p&gt;
&lt;p&gt;How will we compute the look-at point for our camera so we will be able to move it around in a meaningful way?
I&amp;rsquo;ve decided that a good way will be to &amp;ldquo;move&amp;rdquo; the camera forward a certain amount, and then rotate this point around the camera by using some angles.
Luckily for us, we&amp;rsquo;ve already specified that our &lt;code&gt;camera&lt;/code&gt; has two angles &lt;code&gt;:x-rotate&lt;/code&gt;, and &lt;code&gt;z-rotate&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [20 50 20]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x-rotate&lt;/span&gt; 255
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:z-rotate&lt;/span&gt; 15})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And it is also declared as a &lt;code&gt;var&lt;/code&gt;, which means that we can &lt;code&gt;set&lt;/code&gt; new values into it.
Let&amp;rsquo;s write a function that will compute a new &lt;code&gt;lookat&lt;/code&gt; point for current &lt;code&gt;camera&lt;/code&gt; position and rotation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;math.cos&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sin&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;math.sin&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rotate-point&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ax&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ay&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;az&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x-angle&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z-angle&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ax&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ay&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;az&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x-angle&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x-angle&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;RAD&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z-angle&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z-angle&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;RAD&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cos-x&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x-angle&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sin-x&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sin&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x-angle&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cos-z&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z-angle&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sin-z&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sin&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z-angle&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cos-x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cos-z&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sin-x&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cos-x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sin-z&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ax&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sin-x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cos-z&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cos-x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sin-x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sin-z&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ay&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sin-z&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cos-z&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;az&lt;/span&gt;)]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;forward-vec&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.pos&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rotate-point&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt; [1 0 0]) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.x-rotate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.z-rotate&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The first function &lt;code&gt;rotate-point&lt;/code&gt; will rotate one point around another point by using two degrees.
It is based on &lt;a href=&#34;https://en.wikipedia.org/wiki/Aircraft_principal_axes&#34; target=&#34;_blank&#34;&gt;aircraft principal axes&lt;/a&gt;, but we only have two axes, so we do not need to &amp;ldquo;roll&amp;rdquo;, hence we do little fewer computations here.&lt;/p&gt;
&lt;p&gt;Next is the &lt;code&gt;forward-vec&lt;/code&gt; function, that computes current &amp;ldquo;forward&amp;rdquo; vector for &lt;code&gt;camera&lt;/code&gt;.
Forward, in this case, means the direction camera is &amp;ldquo;facing&amp;rdquo;, which is based on two angles we specify in the &lt;code&gt;camera&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With this function we can implement basic movement and rotation functions for the camera:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-forward&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dir&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;norm&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-sub&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;forward-vec&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.pos&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.pos&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.pos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dir&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-elevate&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.pos&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vec-add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.pos&lt;/span&gt; [0 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;])))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-rotate-x&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.x-rotate&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.x-rotate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;) 360)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-rotate-z&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.z-rotate&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clamp&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.z-rotate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z&lt;/span&gt;) -89.9 89.9)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-strafe&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z-rotate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.z-rotate&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.z-rotate&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-rotate-x&lt;/span&gt; 90)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-forward&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-rotate-x&lt;/span&gt; -90)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera.z-rotate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;z-rotate&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And if we modify our &lt;code&gt;love.draw&lt;/code&gt; again, we&amp;rsquo;ll be able to use our computed look-at point as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.draw&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; rest of love.draw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lookat&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;forward-vec&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; rest of love.draw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we don&amp;rsquo;t need a global &lt;code&gt;lookat&lt;/code&gt; variable, and it is actually enough for us to compute new &lt;code&gt;lookat&lt;/code&gt; every frame.&lt;/p&gt;
&lt;p&gt;As for movement, let&amp;rsquo;s implement a simple keyboard handler:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;handle-keyboard-input&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-key-pressed?&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;w&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-forward&lt;/span&gt; 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-key-pressed?&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;s&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-forward&lt;/span&gt; -1))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-key-pressed?&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;d&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-key-pressed?&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;lshift&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-strafe&lt;/span&gt; 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-rotate-x&lt;/span&gt; 1))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-key-pressed?&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;a&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-key-pressed?&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;lshift&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-strafe&lt;/span&gt; -1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-rotate-x&lt;/span&gt; -1)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-key-pressed?&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;q&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-rotate-z&lt;/span&gt; 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-key-pressed?&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;e&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-rotate-z&lt;/span&gt; -1))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-key-pressed?&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;r&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-elevate&lt;/span&gt; 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love-key-pressed?&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;f&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-elevate&lt;/span&gt; -1)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Similarly, we can implement controller support:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;handle-controller&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gamepad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lstick-x&lt;/span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gamepad&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:getGamepadAxis&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;leftx&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lstick-y&lt;/span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gamepad&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:getGamepadAxis&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;lefty&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l2&lt;/span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gamepad&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:getGamepadAxis&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;triggerleft&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rstick-x&lt;/span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gamepad&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:getGamepadAxis&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rightx&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rstick-y&lt;/span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gamepad&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:getGamepadAxis&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;righty&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r2&lt;/span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gamepad&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:getGamepadAxis&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;triggerright&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lstick-y&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lstick-y&lt;/span&gt; -0.2) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lstick-y&lt;/span&gt; 0.2)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-forward&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;2 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lstick-y&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lstick-x&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lstick-x&lt;/span&gt; -0.2) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lstick-x&lt;/span&gt; 0.2)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-strafe&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;2 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lstick-x&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rstick-x&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rstick-x&lt;/span&gt; -0.2) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rstick-x&lt;/span&gt; 0.2)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-rotate-x&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;4 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rstick-x&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rstick-y&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rstick-y&lt;/span&gt; -0.2) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rstick-y&lt;/span&gt; 0.2)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-rotate-z&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;4 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rstick-y&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r2&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r2&lt;/span&gt; -0.8))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-elevate&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;1 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;r2&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l2&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l2&lt;/span&gt; -0.8))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera-elevate&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;1 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l2&lt;/span&gt;)))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Only for a controller, we make sure that our &lt;code&gt;l2&lt;/code&gt; and &lt;code&gt;r2&lt;/code&gt; axes are from 0 to 2, since by default these axes are from &lt;code&gt;-1&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;, which isn&amp;rsquo;t going to work for us.
Similarly to this, we can add the ability to change the field of view or reflection count, but I&amp;rsquo;ll leave this out for those who are interested in trying it themselves.
It&amp;rsquo;s not hard.&lt;/p&gt;
&lt;p&gt;As a final piece, we need to detect if the controller was inserted and handle keys somewhere.
So let&amp;rsquo;s add these two final functions that we need for everything to work:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gamepad&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.joystickadded&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;set &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gamepad&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;love.update&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dt&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;handle-keyboard-input&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;handle-controller&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;love.joystickadded&lt;/code&gt; will take care of watching for new controllers, and &lt;code&gt;love.update&lt;/code&gt; will ask for new input every now and then.&lt;/p&gt;
&lt;p&gt;By this moment we should have a working raymarching 3D renderer with basic lighting and reflections!&lt;/p&gt;
&lt;h2 id=&#34;final-thoughts&#34;&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve decided to write this post because I was interested in three topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fennel, a Lisp-like language, which is a lot like Clojure syntax-wise, and has great interop with Lua (because it IS Lua)&lt;/li&gt;
&lt;li&gt;LÖVE, is a nice game engine I&amp;rsquo;ve been watching for a long time already and played some games written with it, which were quite awesome,&lt;/li&gt;
&lt;li&gt;and Lua itself, a nice, fast scripting language, with the cool idea that everything is a table.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Although I didn&amp;rsquo;t use much of Lua here, I&amp;rsquo;ve actually tinkered with it a lot during the whole process, testing different things, reading Fennel&amp;rsquo;s compiler output, and benchmarking various constructs, like field access, or unpacking numeric tables versus multiple return values.
Lua has some really cool semantics of defining modules as tables and incorporating special meaning to tables via &lt;code&gt;setmetatable&lt;/code&gt;, which is really easy to understand in my opinion.&lt;/p&gt;
&lt;p&gt;Fennel is a great choice if you don&amp;rsquo;t want to learn Lua syntax (which is small, but, you know, it &lt;em&gt;exists&lt;/em&gt;).
For me, Fennel is a great language, because I don&amp;rsquo;t have to deal with Lua syntax AND because I can write macros.
And even though I didn&amp;rsquo;t write any macro for this project, because everything is already presented in Fennel itself, the possibility of doing this is worth something.
Also, during benchmarking various features, I&amp;rsquo;ve used self-written &lt;code&gt;time&lt;/code&gt; macro:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;macro&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;time &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;body&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  `(&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clock#&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;os.clock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;start#&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clock#&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;res#&lt;/span&gt; ,&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;body&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;end#&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clock#&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;print &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;.. &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Elapsed: &amp;#34;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;1000 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;end#&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;start#&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; ms&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;res#&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So the ability to define such things is a good thing.&lt;/p&gt;
&lt;p&gt;LÖVE is a great engine, and although I&amp;rsquo;ve used a very little bit of it, I still think that this is a really cool project, because there is so much more in it.
Maybe someday I&amp;rsquo;ll make a game that will realize LÖVE&amp;rsquo;s full potential.&lt;/p&gt;
&lt;p&gt;On a downside note&amp;hellip;
The resulting raymarching is &lt;strong&gt;very slow&lt;/strong&gt;.
I&amp;rsquo;ve managed to get around 25 FPS for a single object in the scene, and a 256 by 224 pixel resolution.
Yes, this is because it runs in a single thread, and does a lot of expensive computations.
Lua itself isn&amp;rsquo;t a very fast language, and even though LÖVE uses Luajit - a just-in-time compiler that emits machine code, it&amp;rsquo;s still not fast enough for certain operations, or techniques.
For example, if we implement operator overloading for vectors we&amp;rsquo;ll lose a lot of performance for constant table lookups.
This is an existing problem in Lua, since it does its best of being small and embeddable, so it could work nearly on anything, therefore it doesn&amp;rsquo;t do a lot of caching and optimizations.&lt;/p&gt;
&lt;p&gt;But hey, this is a raymarching in ~350 lines of code with some cool tricks like destructuring!
I&amp;rsquo;m fine with the results.
A slightly more polished version of the code from this article is available at &lt;a href=&#34;https://gitlab.com/andreyorst/love-raymarching&#34; target=&#34;_blank&#34;&gt;this repository&lt;/a&gt;, so if anything doesn&amp;rsquo;t work in the code above, or you got lost and just want to play with the final result, you know where to go :)&lt;/p&gt;
&lt;p&gt;Till next time, and thanks for reading!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Ray_tracing_%28graphics%29&#34; target=&#34;_blank&#34;&gt;https://en.wikipedia.org/wiki/Ray_tracing_(graphics)&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/ssloy/tinyraytracer&#34; target=&#34;_blank&#34;&gt;https://github.com/ssloy/tinyraytracer&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://fennel-lang.org/setup&#34; target=&#34;_blank&#34;&gt;https://fennel-lang.org/setup&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://love2d.org/wiki/Getting_Started&#34; target=&#34;_blank&#34;&gt;https://love2d.org/wiki/Getting_Started&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;
&lt;p&gt;there&amp;rsquo;s no need to declare a variable as &lt;code&gt;var&lt;/code&gt; if it is a table and we&amp;rsquo;re only going to change the values stored inside the table, not the table itself.&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Raymarching with Fennel and LÖVE&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 15 Oct 2020 20:33:00 +0300</pubDate>
    </item><item>
      <title>Simple Ray Casting with ClojureScript</title>
      <link>https://andreyor.st/posts/2020-06-04-simple-ray-casting-with-clojurescript/</link>
      <guid>https://andreyor.st/posts/2020-06-04-simple-ray-casting-with-clojurescript/</guid>
      <description>&lt;p&gt;Ray casting is quite an old technique, that was heavily used in the early days of game development in a lot of games to create an illusion of 3D space.
The most known example, and perhaps the first widely successful game that used this technique, was Wolfenstein 3D, made by ID Software in 1992.
There were a lot of other games for all kinds of platforms, that used ray casting, for example, I remember playing the labyrinth game on Siemens C35 in around 2001:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/labyrinth-game-on-siemens-c35.jpg&#34;/&gt;
&lt;/figure&gt;

&lt;center&gt;Yup, this phone is still alive, and still has this labyrinth game&lt;/center&gt;
&lt;br&gt;
&lt;p&gt;There&amp;rsquo;s probably no reason to use ray casting for rendering pseudo-3D environments today, since this technique is very limited, and modern hardware is heavily optimized for working with triangles, which allows us to create very complex geometry that is impossible to model with ray casting.
But I think that ray casting is a kinda cool idea, a simple concept, and definitively was a very smart move in the nineties game development.
Additionally, ray casting has a lot more use cases than a simple rendering engine.
Also, &lt;em&gt;raycasting&lt;/em&gt; seems not to be a real word, but I&amp;rsquo;m going to refer to this technique like that further on, because it is convenient, and the engine itself can be referred to as &lt;em&gt;raycaster&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For this project, I&amp;rsquo;ve chosen ClojureScript because I want to get into it, and into Clojure as well.
Although my experience with Lisps is not very rich, the main usage right now is for writing functions in Emacs Lisp, but those are rather basic.
I&amp;rsquo;m also going through &lt;a href=&#34;https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book.html&#34; target=&#34;_blank&#34;&gt;SICP&lt;/a&gt; with GNU Guile and Racket, and though exercises in this book are sometimes brutal, this is not real programming experience.
So the real goal of this post is rather not to implement a basic raycaster, but learn some Clojure.
What, you thought we&amp;rsquo;re here for games?
Just kidding, we&amp;rsquo;ll make a simple maze game too, which will be playable on this page.&lt;/p&gt;
&lt;p&gt;But first, let&amp;rsquo;s understand what raycasting is, by going through some basic examples.&lt;/p&gt;
&lt;h2 id=&#34;ray-casting-basics&#34;&gt;Ray casting basics&lt;/h2&gt;
&lt;p&gt;The general idea behind this technique is that we can imitate a 3D environment based only on 2D information.
This is done by casting rays from the point, where the camera stands, and measuring the length of each ray until it hits any of the line segments, that represent walls on a 2D plane.
I&amp;rsquo;ve prepared some pictures to illustrate this idea:&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--example-stage&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/two-lines-and-a-camera.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;We can look at this as a top-down view of our scene.
But how would we convert it to a first-person pseudo-3D view?
The answer, &lt;em&gt;as you might expect&lt;/em&gt;, is rays.
Our camera will shoot a certain amount of rays in front of it, and we will see which rays have intersection points with our red and green walls.
Let&amp;rsquo;s shoot 6 rays:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/rays.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Now we can find intersections with our walls.
I&amp;rsquo;ve cut those rays, and calculated their lengths - this is the only information we need to make this 2D plane into a pseudo-3D scene.
Going from left to right, lengths are roughly &lt;code&gt;23.7&lt;/code&gt;, &lt;code&gt;24.2&lt;/code&gt;, &lt;code&gt;inf&lt;/code&gt;, &lt;code&gt;34.8&lt;/code&gt;, &lt;code&gt;30.3&lt;/code&gt;, &lt;code&gt;27.5&lt;/code&gt; pixels each:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/rays-intersected.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;So, in order to make a 3D scene out of these lengths we, first, have to create an empty scene.
Let&amp;rsquo;s make it &lt;code&gt;256&lt;/code&gt; by &lt;code&gt;224&lt;/code&gt; pixels.
We then divide this scene&amp;rsquo;s width by amount of rays, to compute the width of each ray, and fill this scene with rectangles of this width, which gives us roughly &lt;code&gt;42.7&lt;/code&gt; pixels wide rectangles:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/rectangles.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;This doesn&amp;rsquo;t look like 3D yet, and you can notice that there are only 5 out of the total 6 rectangles presented.
This is due to the fact that one ray had infinity length, since it did not intersect with anything, so we don&amp;rsquo;t draw anything there.
And to make it look 3D we need to change the height of each rectangle accordingly to the length of each ray.
General rule &amp;ndash; the shorter the ray, the bigger the height:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/rectangles-adjusted.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Now, this looks more like a 3D scene, isn&amp;rsquo;t it?
But the walls don&amp;rsquo;t exactly look like walls, more like a set of rectangles.
We can fix this by increasing our resolution, which we do by casting more rays.
Also, let&amp;rsquo;s add background and remove rectangle outlines:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/16-rays.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;We can also change the field of view, by keeping the same amount of rays but changing the angle between those:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/16-rays-fov.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Which is more convincing, but still not as smooth as it could be.
But, we can think about rays as our resolution, so if we would cast 256 rays, one ray for each pixel of image width, we would get something like this:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/256-rays.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;More advanced raycasting engines can produce various perspective corrections for such rectangles, making things appear at different heights.
This is often used to imitate a camera shake while walking.
Textures can be mapped to walls and the floor, and very basic lighting can be achieved by changing texture brightness depending on the distance.
Even more advanced engines allow changing the vertical angle of the camera to imitate looking up and down.
But we will implement pretty basic untextured raycasting, extending it further can be an interesting task, but I don&amp;rsquo;t feel like doing it with canvas.
Maybe later, with WebGL.&lt;/p&gt;
&lt;h2 id=&#34;project-structure&#34;&gt;Project structure&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ll be using &lt;a href=&#34;https://github.com/thheller/shadow-cljs&#34; target=&#34;_blank&#34;&gt;shadow-cljs&lt;/a&gt; to manage my project.
I&amp;rsquo;ve found this one very straightforward and simple to set up with &lt;a href=&#34;https://leiningen.org/&#34; target=&#34;_blank&#34;&gt;Leiningen&lt;/a&gt;.
To create &lt;code&gt;cljs&lt;/code&gt; project via &lt;code&gt;lein&lt;/code&gt; type this in the command line (I&amp;rsquo;m using Linux, so) some details on project setup may vary for different operating systems:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ lein new shadow-cljs raycasting
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As a result, it should create the following file structure for us:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;raycasting/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── package.json
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── public
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── css
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │   └── style.css
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── index.html
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── README.md
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── shadow-cljs.edn
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── src
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── raycasting
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── core.cljs
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s look at &lt;code&gt;shadow-cljs.edn&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; shadow-cljs configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:source-paths&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:dependencies&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;binaryage/devtools&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;0.9.7&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;reagent&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;0.8.0-alpha2&amp;#34;&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; set a nrepl port for connection to a REPL.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:nrepl&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:port&lt;/span&gt; 8777}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:builds&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:app&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:target&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:browser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:output-dir&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;public/js/compiled&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:asset-path&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;/js/compiled&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:modules&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:main&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:entries&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&lt;/span&gt;]}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:devtools&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;; before live-reloading, any code calls this function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:before-load&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core/stop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; after live-reloading finishes call this function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:after-load&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core/start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; serve the public directory over http at port 8700&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:http-root&lt;/span&gt;    &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;public&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:http-port&lt;/span&gt;    8700
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:preloads&lt;/span&gt;     [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;devtools.preload&lt;/span&gt;]}}}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Probably you won&amp;rsquo;t need to change much here, but I&amp;rsquo;ve removed &lt;code&gt;reagent&lt;/code&gt; dependency, because I don&amp;rsquo;t need it, so my &lt;code&gt;shadow-cljs.edn&lt;/code&gt; looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:source-paths&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:dependencies&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;binaryage/devtools&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;0.9.7&amp;#34;&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:nrepl&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:port&lt;/span&gt; 8777}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:builds&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:app&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:target&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:browser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:output-dir&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;public/js/compiled&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:asset-path&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;/js/compiled&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:compiler-options&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:optimizations&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:advanced&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:modules&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:entries&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&lt;/span&gt;]}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:devtools&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:http-root&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;public&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:http-port&lt;/span&gt; 8700
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:preloads&lt;/span&gt;  [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;devtools.preload&lt;/span&gt;]}}}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve also added &lt;code&gt;:compiler-options {:optimizations :advanced}&lt;/code&gt; to produce smaller &lt;code&gt;js&lt;/code&gt; file, and removed &lt;code&gt;:before-load&lt;/code&gt; and &lt;code&gt;:after-load&lt;/code&gt; functions, because I don&amp;rsquo;t think we need those, and script initialization on page load is sufficient enough.&lt;/p&gt;
&lt;p&gt;One last thing - we need a test page to see the results of our code, so let&amp;rsquo;s create &lt;code&gt;public/index.html&lt;/code&gt; file, where we will add our canvas, and other elements as we go.&lt;/p&gt;
&lt;p&gt;With the project setup and ready we now can begin working on ray casting by creating a camera.&lt;/p&gt;
&lt;h2 id=&#34;creating-a-camera&#34;&gt;Creating a camera&lt;/h2&gt;
&lt;p&gt;Since we&amp;rsquo;re going to cast rays out from the camera, we need a camera in the first place.
Camera will be represented as a single point on the plane with &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinates, and &lt;code&gt;degree&lt;/code&gt; parameter.
Let&amp;rsquo;s create a file &lt;code&gt;src/raycasting/camera.cljs&lt;/code&gt; and define camera by using &lt;code&gt;atom&lt;/code&gt; so we could later update it:&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;code-snippet--camera.cljs&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.camera&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;atom&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 0.0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 0.0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 0.0}))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;&lt;a href=&#34;#code-snippet--camera.cljs&#34;&gt;Code Snippet 1&lt;/a&gt;:&lt;/span&gt;
  Contents of &lt;code&gt;src/raycasting/camera.cljs&lt;/code&gt;
&lt;/div&gt;
&lt;p&gt;Our &lt;code&gt;camera&lt;/code&gt; is a hash map with three key-value pairs for each of its parameters.
We can later access these parameters by calling keys on this map like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.camera&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; @&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;0.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is quite handy, and we can update our map with &lt;code&gt;assoc&lt;/code&gt; procedure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.camera&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;@&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 45.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 0.0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 0.0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 45.0}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or use &lt;code&gt;merge-with&lt;/code&gt; procedure to change the value currently stored in the map, by using some procedure, which is &lt;code&gt;+&lt;/code&gt; in our case:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.camera&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;merge-with + &lt;/span&gt;@&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 90.0})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 0.0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 0.0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 90.0}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can notice that while I&amp;rsquo;ve used &lt;code&gt;assoc&lt;/code&gt; to change my &lt;code&gt;:degree&lt;/code&gt; to &lt;code&gt;45.0&lt;/code&gt; and then used &lt;code&gt;merge-with&lt;/code&gt; with &lt;code&gt;+&lt;/code&gt; to add &lt;code&gt;90.0&lt;/code&gt; degrees to current &lt;code&gt;:degree&lt;/code&gt;, I&amp;rsquo;ve still got &lt;code&gt;90.0&lt;/code&gt; as the result, and not the expected &lt;code&gt;135.0&lt;/code&gt;.
This is because &lt;code&gt;camera&lt;/code&gt; is a &lt;em&gt;value&lt;/em&gt;, and can&amp;rsquo;t really change, and instead we&amp;rsquo;re producing a new value based on old one.
And since our old value never changed, it still had &lt;code&gt;0.0&lt;/code&gt; as &lt;code&gt;:degree&lt;/code&gt;.
To understand how this works we need to understand what is considered a value and why.
You can &lt;a href=&#34;#moving-the-camera&#34;&gt;skip&lt;/a&gt; explanations of this if you want, since it mostly has nothing to do with raycasting itself, but this still may explain certain things that we will see later in the code.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In Clojure, we mostly work with values, and there are no &lt;em&gt;variables&lt;/em&gt; as presented in other languages.
To make it more clear, let&amp;rsquo;s talk about what is considered a value.
For example, in Rust &lt;code&gt;42&lt;/code&gt; is a value, that we can assign to a variable like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;mut&lt;/span&gt; a = 42;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;ve created a mutable variable &lt;code&gt;a&lt;/code&gt;, and put &lt;code&gt;42&lt;/code&gt; into it.
We can later &lt;em&gt;mutate&lt;/em&gt; &lt;code&gt;a&lt;/code&gt; to hold another value:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a -= 15;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The key here is &lt;em&gt;mutate&lt;/em&gt; - we&amp;rsquo;re not magically transforming &lt;code&gt;42&lt;/code&gt; itself into &lt;code&gt;27&lt;/code&gt;, we&amp;rsquo;re changing the contents of &lt;code&gt;a&lt;/code&gt;.
So &lt;code&gt;a&lt;/code&gt; is like a box that contains a value.
You can&amp;rsquo;t really do anything to &lt;code&gt;42&lt;/code&gt; itself &amp;ndash; it is and always will be &lt;code&gt;42&lt;/code&gt;, that&amp;rsquo;s why it is a value.
So when we did &lt;code&gt;a -= 15&lt;/code&gt;, we&amp;rsquo;ve produced a new value based on the old one, and put it into &lt;code&gt;a&lt;/code&gt;.
So values &lt;strong&gt;never change&lt;/strong&gt;, only variables that hold these values change what they are holding.&lt;/p&gt;
&lt;p&gt;As an example of something that is not a value in Rust, we can look at the Vector collection:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;mut&lt;/span&gt; b = vec![1, 2, 3];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a dynamic array, that holds three elements.
And we can actually change this array by using different methods that it provides, like &lt;code&gt;push&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;b.push(4); &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// now collection holds these four elements [1, 2, 3, 4]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After this &lt;code&gt;push&lt;/code&gt;, whenever we refer to &lt;code&gt;b&lt;/code&gt; it will hold four elements.
We&amp;rsquo;ve declared &lt;code&gt;b&lt;/code&gt; as &lt;code&gt;mut&lt;/code&gt;, but we&amp;rsquo;re not mutating &lt;code&gt;b&lt;/code&gt; itself, but the collection that &lt;code&gt;b&lt;/code&gt; holds - and because of that this is not a value.
&lt;code&gt;mut&lt;/code&gt; keyword only specifies that we can mutate collection.
But even if we were to drop the &lt;code&gt;mut&lt;/code&gt; keyword in both examples, e.g. &lt;code&gt;let a = 42&lt;/code&gt;, &lt;code&gt;let b = vec![1, 2, 3]&lt;/code&gt;, we would not be able to mutate both of these, but it still would not turn &lt;code&gt;[1, 2, 3]&lt;/code&gt; into a value, although we can treat it as a value, underlying semantics of a collection has not changed.&lt;/p&gt;
&lt;p&gt;(Semi-)real-world example - I give you an apple, and ask you to give me back half of it.
You slice the apple and give me back one half.
This apple is not a value, because you&amp;rsquo;ve literally changed it by slicing, and now the original apple is no longer available for both of us.
You now hold half of the apple, and I hold another half.
This is what happens when you modify a vector or any other collection.&lt;/p&gt;
&lt;p&gt;Then I give you an apple made out of a material that &lt;a href=&#34;https://en.wikipedia.org/wiki/Adamantium#History_and_properties&#34; target=&#34;_blank&#34;&gt;once cast, can&amp;rsquo;t be destroyed&lt;/a&gt;, and ask you to give me half of it.
You can&amp;rsquo;t slice it, or do anything to it at all, so you take very precise measures of this apple, cast a new piece out of the same material, and give it back to me.
We now have the original apple and an apple slice.
Then you can throw this apple in the garbage because you can&amp;rsquo;t really do anything with it.
This is what essentially happens when you do math with numbers - you can&amp;rsquo;t change &lt;code&gt;42&lt;/code&gt;, you can take the measure (&lt;code&gt;15&lt;/code&gt;) and produce &lt;code&gt;27&lt;/code&gt; by subtraction.
And this is what makes such an apple to be a value.&lt;/p&gt;
&lt;p&gt;So in Clojure, we work with such type of data, and all Clojure collections are immutable.
But the other major aspect of Clojure&amp;rsquo;s collections is persistence.
The apple I&amp;rsquo;ve described isn&amp;rsquo;t really persistent, because once you&amp;rsquo;ve made a new slice, nothing really tells me what its past state was - was it a whole apple or 3/4 of an apple?
So in order to make things persistent, we must provide additional information with apple, like a serial number for example.
When you cast a new slice, you create a new serial number, that contains information about the old serial number.
This way we can look at our piece, and determine what apple was used as a reference.&lt;/p&gt;
&lt;p&gt;Now, whenever we create new copies, we encode the previous serial number into the current serial number, and from any point, we are able to trace back to the original state of the apple.&lt;/p&gt;
&lt;p&gt;You can argue, that this can be done with an ordinary apple just as with an indestructible one, but the difference is, that an ordinary apple can be changed.
Imagine that you&amp;rsquo;ve made a new apple based on it, added a serial number, that encodes that it was derived from the original apple, and then someone bit off a piece of the original apple.
Then any holder of your copy of apple will try to refer to the original one and will find out not what they expected.
Or maybe what they expected, since the apple could have been bitten before and you&amp;rsquo;ve restored the original form of an apple when made it.
There&amp;rsquo;s no way to tell and preserve correct history.
So even though we can enforce mutation restrictions in Rust, this does not make the vector into a value.&lt;/p&gt;
&lt;p&gt;This is kinda what Clojure does with its collections.
But instead of using identifiers, Clojure uses path copying for sharing structure between states.
So newer state refers to some point in the old state.
There are many different ways to maintain persistence, which are nicely described on this Wikipedia &lt;a href=&#34;https://en.wikipedia.org/wiki/Persistent_data_structure&#34; target=&#34;_blank&#34;&gt;page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A very simple example of persistent collection we can refer to is a single linked list, that grows at the front.
Let&amp;rsquo;s start with a list of these three items &lt;code&gt;(1 2 3)&lt;/code&gt;.
This can be represented as boxes that hold values, and have pointers to what should be the next value:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/single-linked-list.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;So &lt;code&gt;1&lt;/code&gt; refers to &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt; refers to &lt;code&gt;3&lt;/code&gt;, and &lt;code&gt;3&lt;/code&gt; refers to nothing, which indicates end of the list.
Now we add another element to it at the front, which produces a new list &lt;code&gt;(0 1 2 3)&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/new-single-linked-list.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;You can see that all we did is created a box to hold &lt;code&gt;0&lt;/code&gt; and told it to point to a box that holds &lt;code&gt;1&lt;/code&gt;.
The rest thing is our old list, marked with green boxes, and we did not copy anything from it.
And old list did not change at all, only a new node was added to it at the front, but the old list knows nothing about it.
So if we stored our original list somewhere, and added &lt;code&gt;0&lt;/code&gt; to it, our original list was not changed.&lt;/p&gt;
&lt;p&gt;Furthermore, if we check the identity of our new list without its first element, it will be the same as in the original list:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user=&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;identical? &lt;/span&gt;&amp;#39;(1 2 3) &amp;#39;(1 2 3))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user=&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &amp;#39;(1 2 3))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user=&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;identical? &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rest &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;conj &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 0)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First &lt;code&gt;identical?&lt;/code&gt; test gives us &lt;code&gt;false&lt;/code&gt; because these are two different &lt;em&gt;objects&lt;/em&gt;, even though their &lt;em&gt;values&lt;/em&gt; are the same.
The second &lt;code&gt;identical?&lt;/code&gt; test gives us &lt;code&gt;true&lt;/code&gt;, because, as I&amp;rsquo;ve said, by adding a new value to the list, and then removing it, we get back the original list.&lt;/p&gt;
&lt;p&gt;And all of the collections in Clojure work this way, with a promise of fast change and low memory cost.
Although such collections are not as fast as mutable non-persistence collections, they are much more reliable, especially when it comes to concurrent programming, and reliability is much more important than speed most of the time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But in our raycasting we will have to really change camera position, so how do we do it if collections can&amp;rsquo;t be changed, and we&amp;rsquo;re using a hash map to hold camera coordinates and angle?&lt;/p&gt;
&lt;h2 id=&#34;moving-the-camera&#34;&gt;Moving the camera&lt;/h2&gt;
&lt;p&gt;When we&amp;rsquo;ve created &lt;code&gt;camera&lt;/code&gt; we&amp;rsquo;ve used the &lt;code&gt;atom&lt;/code&gt; procedure to produce a reference type that can be later atomically swapped to hold another value, and the swapping mechanism is concurrently safe.
So, in order to update our map, all we need to do is to call &lt;code&gt;swap!&lt;/code&gt; procedure, and pass our atom and a procedure that will update the value:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.camera&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 45.0)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 0.0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 0.0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 45.0}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, when we dereference &lt;code&gt;camera&lt;/code&gt; with &lt;code&gt;@&lt;/code&gt;, we can actually see the updated value:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.camera&amp;gt;&lt;/span&gt; @&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 0.0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 0.0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 45.0}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using swap with anonymous procedures is kinda tedious, so instead, let&amp;rsquo;s create a set of procedures that we will use to move the camera around:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;radian&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/PI&lt;/span&gt; 180.0)) &lt;span style=&#34;&#34;&gt;➊&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-point&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;] &lt;span style=&#34;&#34;&gt;➋&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;angle&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;radian&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m/three-decimal&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/sin&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;angle&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m/three-decimal&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/cos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;angle&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;)))]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-forward&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Move `camera` forward given `amount` respecting the `degree`.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-forward&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; 1))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt;} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;&#34;&gt;➌&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-point&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This procedure will move our camera &lt;em&gt;forward&lt;/em&gt; relatively to where the camera is pointed at.
We compute ➊ only once, to later convert degrees to radians by multiplication.
The &lt;code&gt;move-point&lt;/code&gt; ➋ procedure will later be used in several places of our program, so it is good to have it as a separate procedure, while &lt;code&gt;move-forward&lt;/code&gt; is used exclusively for camera movement.
And inside we have weird construction ➌ which is called &lt;a href=&#34;https://clojure.org/guides/destructuring#_associative_destructuring&#34; target=&#34;_blank&#34;&gt;Associative Destructuring&lt;/a&gt;.
We essentially bind &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, and &lt;code&gt;degree&lt;/code&gt; within our &lt;code&gt;let&lt;/code&gt; block, to the values contained in &lt;code&gt;camera&lt;/code&gt;.
Now let&amp;rsquo;s try to move our camera around:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-forward&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;@&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 0.0) 10)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 10, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 0}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-forward&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;@&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 90.0) 10)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 10, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 6.123233995736766&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;e-16&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 90}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Uh oh.
Moving forward with 0 degrees was fine, but when we&amp;rsquo;ve turned 90 degree, we&amp;rsquo;ve got &lt;code&gt;6.123233995736766e-16&lt;/code&gt; as our &lt;code&gt;y&lt;/code&gt; coordinate.
This value is very close to &lt;code&gt;0&lt;/code&gt;, but we don&amp;rsquo;t really need such precision, and there are some problems with such small values in JavaScript.
Let&amp;rsquo;s write a macro, that will truncate it to three decimal places, which would be more than enough for our needs:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defmacro &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;three-decimal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Truncate `double` to three decimal places.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;num&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  `(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;int &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;1000 ~&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;num&lt;/span&gt;)) 1000.0))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-forward&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Move `camera` forward given `amount` respecting the `degree`.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-forward&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; 1))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rad&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/PI&lt;/span&gt; 180.0))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;merge-with + &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;three-decimal&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/sin&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rad&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;three-decimal&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/cos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rad&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;))}))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will not work though.
The problem is, that we can&amp;rsquo;t just define a macro in the same file that we&amp;rsquo;ve declared procedure.
This is a &lt;a href=&#34;https://clojurescript.org/about/differences#_macros&#34; target=&#34;_blank&#34;&gt;difference&lt;/a&gt; between Clojure and ClojureScript, so we have to create new file &lt;code&gt;src/raycasting/macros.cljc&lt;/code&gt;, and use &lt;code&gt;:require-macros&lt;/code&gt; in our namespace definition for &lt;a href=&#34;#code-snippet--camera.cljs&#34;&gt;camera.cljs&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.camera&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:require-macros&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.macros&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can update &lt;code&gt;move-forward&lt;/code&gt; to refer to macro:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-forward&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Move `camera` forward given `amount` respecting the `degree`.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-forward&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; 1))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rad&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/PI&lt;/span&gt; 180.0))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;merge-with + &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m/three-decimal&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/sin&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rad&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                             &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m/three-decimal&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/cos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rad&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;))}))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s try it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-forward&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;@&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 0.0) 10)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 10, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 0}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-forward&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;@&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 90.0) 10)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 10, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 90}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nice.
Now, we can do the same thing to rotate the camera:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rotate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Rotate `camera` by a `degree`.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rotate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; 0.5))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mod&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt;) 360.0))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And if we call this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rotate&lt;/span&gt; @&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; 420)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 0.0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 0.0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 60.0}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The rotate procedure ensures that our &lt;code&gt;:degree&lt;/code&gt; stays inside 360 degrees, so when we specify a turn that is more than 360 degrees, we wrap around.
These are two main procedures we will later use.&lt;/p&gt;
&lt;h2 id=&#34;drawing&#34;&gt;Drawing&lt;/h2&gt;
&lt;p&gt;Now we can draw our camera on &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;.
Let&amp;rsquo;s add this to our &lt;code&gt;index.html&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;html lang=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;en-US&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;meta charset=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;script src=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;js/compiled/main.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;canvas id=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;raycaster&amp;#34;&lt;/span&gt; width=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;512&amp;#34;&lt;/span&gt; height=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;224&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/canvas&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt;.onload = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        raycasting.core.init();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;ve added our &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; and gave it an &lt;code&gt;id&lt;/code&gt;.
We will later be able to refer to this canvas via this &lt;code&gt;id&lt;/code&gt;, so let&amp;rsquo;s create two vars to hold the canvas object, and its context:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:require&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defonce &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defonce &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;^&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:export&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;init&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;raycaster&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-getContext&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getContext&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;2d&amp;#34;&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We use &lt;code&gt;defonce&lt;/code&gt; here, so when we save file, and shadow-cljs hot reloads the code, we will not redefine our &lt;code&gt;*canvas*&lt;/code&gt; and &lt;code&gt;*ctx*&lt;/code&gt; to &lt;code&gt;nil&lt;/code&gt;.
And &lt;code&gt;init&lt;/code&gt; procedure will run on &lt;code&gt;onload&lt;/code&gt; event, and set our &lt;code&gt;*canvas*&lt;/code&gt; and &lt;code&gt;*ctx*&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s create &lt;code&gt;draw-camera&lt;/code&gt; procedure, that will take current &lt;code&gt;camera&lt;/code&gt; state, and draw it to canvas:&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;code-snippet--draw-camera&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-line&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;] &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-strokeStyle&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;doto &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.beginPath&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.moveTo&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.lineTo&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.stroke&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-camera&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt;] [(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pointer&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) 7)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; 5]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-line&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pointer&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-fillStyle&lt;/span&gt;) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fillRect&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; 2)) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; 2)) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, if we write this to the REPL:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-camera&lt;/span&gt; @&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We should see our camera:&lt;/p&gt;
&lt;div style=&#34;text-align: center&#34;&gt;
  &lt;canvas id=&#34;example1&#34; width=&#34;256&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;p&gt;Now let&amp;rsquo;s add some walls to look at.&lt;/p&gt;
&lt;h2 id=&#34;creating-walls&#34;&gt;Creating walls&lt;/h2&gt;
&lt;p&gt;I need to mention, that many raycasting engines define stages in terms of squares on the grid.
This is useful because we can check intersections a lot faster since we only need to perform checks along the ray in fixed points of space.
While this is quite fast, I want arbitrarily placed walls in my raycaster.
Because of this, our algorithm will not be as optimal, but we will be able to handle more complex wall placement.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s create new file &lt;code&gt;src/raycasting/stage.cljs&lt;/code&gt;.
In this file, we will define our stages.
Each stage is a vector, with line segments, that have three components - beginning coordinate, endpoint, and color.
Let&amp;rsquo;s define stage, as on our &lt;a href=&#34;#figure--example-stage&#34;&gt;example picture&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.stage&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;example-stage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [ &lt;span style=&#34;&#34;&gt;➊&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   [ &lt;span style=&#34;&#34;&gt;➋&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [23.468 126.290] &lt;span style=&#34;&#34;&gt;➌&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [106.189 87.527] &lt;span style=&#34;&#34;&gt;➍&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#89a02c&amp;#34;&lt;/span&gt;] &lt;span style=&#34;&#34;&gt;➎&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   [[124.947 40.268] [166.507 95.415] &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#916f6f&amp;#34;&lt;/span&gt;] &lt;span style=&#34;&#34;&gt;➏&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So what we&amp;rsquo;re doing here is, we begin by creating a vector ➊.
This vector will hold all lines that our stage uses.
We define another vector ➋, that will hold beginning point ➌, ending point ➍, and wall color ➎.
Lastly, we specify another line ➏, and this process can continue on and on.
Bigger stages will require a lot of walls, and this can be a performance hit, but we&amp;rsquo;re not aiming for the best efficiency.&lt;/p&gt;
&lt;p&gt;Now we can implement wall drawing with our &lt;code&gt;draw-line&lt;/code&gt; procedure, that we&amp;rsquo;ve already used in &lt;a href=&#34;#code-snippet--draw-camera&#34;&gt;&lt;code&gt;draw-camera&lt;/code&gt; procedure&lt;/a&gt;.
Let&amp;rsquo;s create &lt;code&gt;draw-stage&lt;/code&gt; procedure, that will walk through our vector of walls and draw each on the canvas:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-stage&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;doseq &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;line&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;apply &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-line&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;line&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;doseq&lt;/code&gt; is a great way to iterate on a collection for producing side effects, such as drawing on the screen.
Let&amp;rsquo;s move our camera to the position &lt;code&gt;119.5,180&lt;/code&gt;, and rotate it to 180 so it is placed as on our example.
Now if we call this procedure, we should see our stage:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; #(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 119.5 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 180 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 180))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 119.5 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 180 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 180}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-stage&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage/example-stage&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style=&#34;text-align: center&#34;&gt;
  &lt;canvas id=&#34;example2&#34; width=&#34;256&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;p&gt;While we are at this, notice how awkward we&amp;rsquo;ve been setting our position for &lt;code&gt;camera&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; #(&lt;span style=&#34;&#34;&gt;➊&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;&lt;span style=&#34;&#34;&gt;➋&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;&#34;&gt;➌&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 119.5 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 180 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 180))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;➊ &lt;code&gt;#()&lt;/code&gt; is a shorthand for creating an anonymous procedure.
This procedure will call &lt;code&gt;assoc&lt;/code&gt; ➋, and &lt;code&gt;%&lt;/code&gt; ➌ will be our &lt;code&gt;cam/camera&lt;/code&gt;.
A more elaborate way to write the same code would be &lt;code&gt;(fn [camera] (assoc camera …))&lt;/code&gt;.
We could simplify this by using &lt;code&gt;reset!&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;reset!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 119.5 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 180 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 180})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which is much simpler, but still very error-prone, because we&amp;rsquo;ll have to remember what keys should be in the map.
This is not an issue for three key-value pair maps, but for huge maps, it will be better to create some kind of initialization procedure.
Let&amp;rsquo;s create one in &lt;code&gt;raycasting.camera&lt;/code&gt; namespace:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set-position&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Set position of the `camera` to a certain `x`, `y`, and `degree`.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;&#34;&gt;➊&lt;/span&gt; ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set-position&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; 0 0 0))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;&#34;&gt;➋&lt;/span&gt; ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set-position&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; 0))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;&#34;&gt;➌&lt;/span&gt; ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mod&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; 360.0)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is called &lt;a href=&#34;https://clojure.org/guides/learn/functions#_multi_arity_functions&#34; target=&#34;_blank&#34;&gt;Multi-arity function&lt;/a&gt;, we&amp;rsquo;ve been using it before, but I&amp;rsquo;ve never explained what it is.
In Clojure and ClojureScript it is possible to define procedure overloading based on the number of given arguments.
In this example we create three possible ways to call our procedure: ➊ - we only pass our &lt;code&gt;camera&lt;/code&gt; parameter, and it resets its position to &lt;code&gt;0,0&lt;/code&gt; coordinates, and set&amp;rsquo;s &lt;code&gt;0&lt;/code&gt; degree angle, ➋ - we specify coordinates, but we don&amp;rsquo;t care about our angle, so we reset it, and ➌ - we provide all needed parameters, and set those accordingly with &lt;code&gt;assoc&lt;/code&gt;.
The beauty of multi-arity procedures is that it can call itself with another amount of arguments, so in this case, there&amp;rsquo;s only one real body, that does the work (➌), and others (➊, ➋) are only calling it with all needed parameters.
With this procedure we can quickly set the desired position for our camera:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/set-position&lt;/span&gt;) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; reset&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 0}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/set-position&lt;/span&gt; 10 20) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; set coordinates&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 10 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 20 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 0}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/set-position&lt;/span&gt; 10 20 90) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; fully specify position&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; 10 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; 20 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 90}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can use this later when we initialize our stages in the game.&lt;/p&gt;
&lt;h2 id=&#34;casting-rays&#34;&gt;Casting rays&lt;/h2&gt;
&lt;p&gt;Now, when we have our camera and walls, we can finally cast some rays.
Although, we&amp;rsquo;re not casting rays, but really long line segments because our algorithm will check for intersections between line segments of stage walls, and our rays.&lt;/p&gt;
&lt;p&gt;First, we need some linear algebra.
In particular, we need to check if two line segments intersect or not.
This is done by three procedures.
First one checks if a point lies on the line segment:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;on-segment?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Checks if point `[ax ay]` lies on segment defined by two points `[b
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;  c]`, where each point is defined as a vector `[x y]`.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ax&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ay&lt;/span&gt;] [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;by&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cy&lt;/span&gt;]]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ax&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;max &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cx&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ax&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;min &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cx&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ay&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;max &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;by&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cy&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ay&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;min &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;by&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cy&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This procedure accepts a point, and a line segment defined as two points and checks whenever the point lies on that line segment.
We will need this procedure because when we will check for intersections, we need to ensure, that we&amp;rsquo;re staying inside line segments.&lt;/p&gt;
&lt;p&gt;Next bit is &lt;code&gt;orientation&lt;/code&gt; procedure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orientation&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ax&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ay&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;by&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cy&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orientation&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;by&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ay&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bx&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ax&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cy&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;by&lt;/span&gt;)))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;cond &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orientation&lt;/span&gt; 0) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:cw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orientation&lt;/span&gt; 0) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:cc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:else&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:colinear&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This procedure checks the relationship of point &lt;code&gt;a&lt;/code&gt;, and points &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;c&lt;/code&gt;.
These relationships can be &lt;code&gt;:cw&lt;/code&gt; (for clockwise), &lt;code&gt;:cc&lt;/code&gt; (for counter clockwise), and &lt;code&gt;:colinear&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/orientation.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Now we can check for the intersection itself:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersect?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Checks if two line segments intersect. Line segments are defined as
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;  vector of two points `[a1 a2]`, and each point is a vector of two
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;  coordinates `[x y]`.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a2&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b2&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;o1&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orientation&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;o2&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orientation&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;o3&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orientation&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;o4&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orientation&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a2&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;o1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;o2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;o3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;o4&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;o1&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:colinear&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;on-segment?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b1&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a2&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;o2&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:colinear&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;on-segment?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b2&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a2&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;o3&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:colinear&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;on-segment?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a1&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b2&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;o4&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:colinear&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;on-segment?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a2&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b2&lt;/span&gt;])))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To find the point of the intersection itself, we need to calculate these two formulas:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://andreyor.st/ltximg/2020-06-04-simple-ray-casting-with-clojurescript_2b9facc8d9bb825db7236d3992da31243e3b576b.svg&#34; alt=&#34;\[x=\frac{(x_1\cdot{y_2}-y_1\cdot{x_2})\cdot(x_3-x_4)-(x_1-x_2)\cdot(x_3\cdot{y_4}-y_3\cdot{x_4})}
{(x_1-x_2)\cdot(y_3-y_4)-(y_1-y_2)\cdot(x_3-x_4)}\]&#34; class=&#34;org-svg&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://andreyor.st/ltximg/2020-06-04-simple-ray-casting-with-clojurescript_390fe82895e7837d319616f6718408f327ed848e.svg&#34; alt=&#34;\[y=\frac{(x_1\cdot{y_2}-y_1\cdot{x_2})\cdot(y_3-y_4)-(y_1-y_2)\cdot(x_3\cdot{y_4}-y_3\cdot{x_4})}
{(x_1-x_2)\cdot(y_3-y_4)-(y_1-y_2)\cdot(x_3-x_4)}\]&#34; class=&#34;org-svg&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s write those as &lt;code&gt;intersection&lt;/code&gt; procedure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;intersection &lt;/span&gt;[[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;] &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt;] [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y3&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x4&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y4&lt;/span&gt;] &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt;)) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x4&lt;/span&gt;)) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y4&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x4&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y4&lt;/span&gt;)) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x4&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt;)) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y4&lt;/span&gt;)) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y4&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x4&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y4&lt;/span&gt;)) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x4&lt;/span&gt;))))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve added &lt;code&gt;:as ray&lt;/code&gt; and &lt;code&gt;:as wall&lt;/code&gt; to make it more clear what these points are related to.
The order doesn&amp;rsquo;t really matter, since we&amp;rsquo;re computing a point, but I think it gives a slight idea of what this procedure expects.&lt;/p&gt;
&lt;p&gt;As a final piece, we need a procedure, that will find all intersections for our ray, and return those in some form, that will be usable for us later.
I&amp;rsquo;ve created this procedure, that takes our stage, and two points as &lt;code&gt;ray&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;find-intersections&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;origin&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;&#34;&gt;➊&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersect?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;font-weight:bold&#34;&gt;new &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;intersection &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  [(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;origin&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;new&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;new&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                [10000000 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;end&lt;/span&gt;])))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;into &lt;/span&gt;{})))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here we&amp;rsquo;re using &lt;a href=&#34;https://clojure.org/guides/threading_macros#thread-last&#34; target=&#34;_blank&#34;&gt;thread last macro&lt;/a&gt; ➊, which essentially takes the result of our expression, and puts it in the last position in the next expression.
We then map with an anonymous procedure, that takes &lt;code&gt;wall&lt;/code&gt;, from our &lt;code&gt;stage&lt;/code&gt;, and checks if it &lt;code&gt;intersects?&lt;/code&gt; with our &lt;code&gt;ray&lt;/code&gt;.
If it does, we calculate &lt;code&gt;new&lt;/code&gt; intersection point, and return a vector of the distance between ray origin and intersection point, and this new point.
When map finishes, it produces this kind of list &lt;code&gt;([10 [0 15]] [11 [4.2 22.8]] … [length [x y]])&lt;/code&gt;.
We then convert it into a hash map, where a length will be our key, and a set of coordinates will be our value.
The distance procedure is defined as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m/three-decimal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/sqrt&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/pow&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt;) 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/pow&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;) 2)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we finally can cast our rays.
First, let&amp;rsquo;s cast a set of rays and draw those without truncation at the intersection point:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cast-rays&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-count&lt;/span&gt; 16
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;step&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; [(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;)]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/rotate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov&lt;/span&gt; 2.0))))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; 5000)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-line&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#ffe680&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;step&lt;/span&gt;)))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now if we call our procedures for drawing rays, camera, and stage like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-stage&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stages/example-stage&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cast-rays&lt;/span&gt; @&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.core&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-camera&lt;/span&gt; @&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We should see this result:&lt;/p&gt;
&lt;div style=&#34;text-align: center&#34;&gt;
  &lt;canvas id=&#34;example3&#34; width=&#34;556&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;p&gt;Now let&amp;rsquo;s change this procedure, so it will find ray ends before drawing:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cast-rays&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;step&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rayCount&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; [(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;)]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rayCount&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/rotate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov&lt;/span&gt; 2.0))))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; 5000)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;&#34;&gt;➊&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersections&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;find-intersections&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;&#34;&gt;➋&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shortest-ray&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;apply min &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;keys &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersections&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;&#34;&gt;➌&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersections&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shortest-ray&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-line&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#ffe680&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;step&lt;/span&gt;)))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First, we compute a map of intersections ➊, then find the shortest intersection length from the map by applying the &lt;code&gt;min&lt;/code&gt; procedure to the list of keys in the map ➋, and lastly get the closest endpoint for given ray ➌.&lt;/p&gt;
&lt;p&gt;This way we can find all intersections of the given ray with all walls, but we will draw only the shortest one, like this:&lt;/p&gt;
&lt;div style=&#34;text-align: center&#34;&gt;
  &lt;canvas id=&#34;example4&#34; width=&#34;556&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;p&gt;To illustrate this a bit better, let&amp;rsquo;s create simple animation by making our camera rotate:&lt;/p&gt;
&lt;div style=&#34;text-align: center&#34;&gt;
  &lt;canvas id=&#34;example5&#34; width=&#34;556&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;p&gt;Now we can use the &lt;code&gt;cast-rays&lt;/code&gt; procedure to make our pseudo-3D image.&lt;/p&gt;
&lt;h2 id=&#34;making-a-3d-view-of-our-scene&#34;&gt;Making a 3D view of our scene&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ll need to modify our &lt;code&gt;cast-rays&lt;/code&gt; procedure, so it would return a list of rays instead of drawing it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;&#34;&gt;➊&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;angle-between&lt;/span&gt; [[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;]] [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y3&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x4&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y4&lt;/span&gt;]]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;theta1&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/atan2&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;theta2&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/atan2&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y4&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x4&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;diff&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/abs&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;theta1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;theta2&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;min &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;diff&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/abs&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;180 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;diff&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cast-rays&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;step&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rayCount&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; [(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;)]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;&#34;&gt;➋&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;central-ray&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) 100)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rayCount&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/rotate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov&lt;/span&gt; 2.0))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt; ()]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; 5000)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersections&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;find-intersections&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shortest-ray&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;apply min &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;keys &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersections&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersections&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shortest-ray&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;&#34;&gt;➌&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-angle&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;angle-between&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;central-ray&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;step&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               &lt;span style=&#34;&#34;&gt;➍&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;conj &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shortest-ray&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-angle&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;]))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;&#34;&gt;➎&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-rays&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt; [(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;)]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;doseq &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-line&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#ffe680&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First, we&amp;rsquo;ve defined an &lt;code&gt;angle-between&lt;/code&gt; ➊ procedure, which takes two line segments and computes the angle between those in radians.
We then added one extra computation before we cast rays - we compute &lt;code&gt;central-ray&lt;/code&gt; ➋, a direction where the camera is looking.
Then, we compute the angle between the current ray we&amp;rsquo;re casting and the central ray ➌.
After that we&amp;rsquo;re &lt;code&gt;conj&lt;/code&gt;ing ➍ vector with endpoint, shortest length, angle, and ray number to a list of rays.
Finally, we return a list of rays ➎ to the caller.
&lt;code&gt;draw-rays&lt;/code&gt; will later use these rays afterward and draw each one ray by ray.&lt;/p&gt;
&lt;p&gt;Now, whenever we call this procedure, we get all the useful information that we will later need to produce an image.
First, let&amp;rsquo;s create another procedure, that will render all our elements on screen in a sequence:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-width&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; @&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cast-rays&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clearRect&lt;/span&gt; 0 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-rays&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-stage&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;&#34;&gt;➊&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;requestAnimationFrame&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a skeleton, not a fully realized procedure.
Note that at ➊, we request another frame to be drawn on our canvas.
So this is more like a game loop, though not quite.
We will use it as our game loop though.&lt;/p&gt;
&lt;p&gt;So, what we do here, is we create a set of bindings on each frame, and we dereference our &lt;code&gt;cam/camera&lt;/code&gt; to get its position and angle, and then cast rays from the camera on our stage.
Later we clear canvas and call &lt;code&gt;draw-rays&lt;/code&gt;, &lt;code&gt;draw-camera&lt;/code&gt;, and &lt;code&gt;draw-stage&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Calling this procedure should initiate an animation sequence, so if we add &lt;code&gt;(swap! cam/camera cam/rotate 1)&lt;/code&gt;, at some point we will have an animation of the rotating camera.
Now let&amp;rsquo;s create a 3D view:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-3d-stage&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-width&lt;/span&gt;) 2) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rayCount&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-width&lt;/span&gt;) 2)])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;&#34;&gt;➊&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-fillStyle&lt;/span&gt;) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#333&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fillRect&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; 2))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-fillStyle&lt;/span&gt;) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#666&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fillRect&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; 2) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; 2))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;&#34;&gt;➋&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;empty?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;first &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;&#34;&gt;➌&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;&#34;&gt;➍&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-fillStyle&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rgb(&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-color&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-color&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-color&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;&#34;&gt;➎&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ctx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fillRect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-width&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; 2) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; 2))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-width&lt;/span&gt; 1) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; extra pixel for border&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rest &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This procedure first fills background ➊, then, we &lt;code&gt;loop&lt;/code&gt; through each ray, we calculate wall height by simply subtracting canvas height and distance to the wall ➌, and since our canvas is 256 pixels high, we use this value as our color as well ➍.
Not really a pretty solution, but will do it for now.
Then we fill a rectangle of this height, and width, with an offset of half of the canvas width plus the number of the ray, times its width.
Calling this procedure in our &lt;code&gt;render&lt;/code&gt; procedure gives us such a view:&lt;/p&gt;
&lt;div style=&#34;text-align: center&#34;&gt;
  &lt;canvas id=&#34;example6&#34; width=&#34;512&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;p&gt;Sure this gives us the desired 3d view, but something is not right.
When we look at our walls we can see that we get some kind of fish eye effect, which we can see in its full form if we look directly at the wall:&lt;/p&gt;
&lt;div style=&#34;text-align: center&#34;&gt;
  &lt;canvas id=&#34;example7&#34; width=&#34;512&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;p&gt;There&amp;rsquo;s a good reason for this, which we can fix, although it requires a few additional calculations.&lt;/p&gt;
&lt;h2 id=&#34;fisheye-compensation&#34;&gt;Fisheye compensation&lt;/h2&gt;
&lt;p&gt;The reason for this effect is the method we&amp;rsquo;re using to calculate wall heights.
Here&amp;rsquo;s how we currently view our would:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/fish-eye.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;This curve is our screen, so if we were to display this on a non-flat screen with the opposite curve, our image would look natural.
However our screens are flat, so we need to compensate for this.
In order to do this, we need to compute distances while taking into account the number of degrees between camera direction and the ray we currently casting.&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s declare &lt;code&gt;angle-between&lt;/code&gt; procedure, that will return the angle between two line segments, one of which will be the direction where the camera is facing, and the other one is the ray we currently casting:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;angle-between&lt;/span&gt; [[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;]] [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y3&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x4&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y4&lt;/span&gt;]]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;theta1&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/atan2&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y2&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;theta2&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/atan2&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y4&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x3&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x4&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;diff&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/abs&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;theta1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;theta2&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;min &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;diff&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/abs&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;180 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;diff&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can use it in our &lt;code&gt;cast-rays&lt;/code&gt; procedure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cast-rays&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;step&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; [(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;central-ray&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) 100)]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/rotate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt; 2.0))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt; ()]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;do &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; 5000)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersections&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;find-intersections&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shortest-ray&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;apply min &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;keys &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersections&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersections&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shortest-ray&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;&#34;&gt;➊&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-angle&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*compensate-fisheye*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;angle-between&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;central-ray&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                              0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;step&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;&#34;&gt;➋&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;conj &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shortest-ray&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-angle&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;]))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We store calculated angle ➊, and then add it to our ray and &lt;code&gt;conj&lt;/code&gt; it to our &lt;code&gt;rays&lt;/code&gt; collection.
This vector already is quite big, so it would be better to use some associative collection instead.
Let&amp;rsquo;s change it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;conj &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:end&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:length&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shortest-ray&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:angle&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-angle&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:n&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, that &lt;code&gt;cast-rays&lt;/code&gt; returns a list of hash maps, we need to update our other procedures that expected a list of vectors.
I&amp;rsquo;ll omit these steps, as it ain&amp;rsquo;t much different from what I&amp;rsquo;ve previously described, and this post is already way longer than I&amp;rsquo;ve thought, but using hash maps will prove more usable when we will need to incorporate other information into our ray, such as color.&lt;/p&gt;
&lt;p&gt;Now we can use angles in &lt;code&gt;draw-3d-scene&lt;/code&gt; procedure.
We&amp;rsquo;ll change our &lt;code&gt;distance&lt;/code&gt; computation to use &lt;code&gt;Math/cos&lt;/code&gt; procedure, to compute corrected distance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m/three-decimal&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/cos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-degree&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should give us the such result:&lt;/p&gt;
&lt;div style=&#34;text-align: center&#34;&gt;
  &lt;canvas id=&#34;example8-1&#34; width=&#34;512&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;p&gt;This looks correct when we face the wall at a 90-degree angle.
But if we&amp;rsquo;re aligned with the wall, we get this:&lt;/p&gt;
&lt;div style=&#34;text-align: center&#34;&gt;
  &lt;canvas id=&#34;example8-2&#34; width=&#34;512&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;p&gt;Which is not right.
Wall is curved for some reason.&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: To be completely honest, up to this point I did everything without using existing raycasting tutorials.
But when I applied a seemingly correct fisheye compensation, and it has gone away only partially, I got stuck for a while.
So in order to find a correct way to compensate for this fisheye effect, I&amp;rsquo;ve read &lt;a href=&#34;https://www.permadi.com/tutorial/raycast/rayc5.html&#34; target=&#34;_blank&#34;&gt;this one&lt;/a&gt;, but for some reason the formula there didn&amp;rsquo;t work for me, so I&amp;rsquo;ve altered it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;So it seems that we&amp;rsquo;re missing the projection plane.
Let&amp;rsquo;s create one:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;projection-distance&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m/three-decimal&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt; 2) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/atan&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt; 2) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/radian&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is better to compute this once, but since we can change the ray count, we have to recompute this.&lt;/p&gt;
&lt;p&gt;With this distance we can add computation in our &lt;code&gt;wall-height&lt;/code&gt; computation process:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-3d-stage-example9&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-width&lt;/span&gt;) 2) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-width&lt;/span&gt;) 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;projection-distance&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;projection-distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-fillStyle&lt;/span&gt;) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#333&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fillRect&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; 2))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-fillStyle&lt;/span&gt;) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#999&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fillRect&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; 2) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; 2))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;sort &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l1&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:length&lt;/span&gt;} {&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l2&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:length&lt;/span&gt;}] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l2&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;first &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:length&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:angle&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:n&lt;/span&gt;} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;angle-step&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*compensate-fisheye*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m/three-decimal&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/cos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-degree&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;projection-distance&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt; 4))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-color&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; 10)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-fillStyle&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rgb(&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-color&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-color&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-color&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fillRect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-width&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; 2) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; 2))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-width&lt;/span&gt; 1) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; extra pixel for border&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rest &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This looks much better in both examples:&lt;/p&gt;
&lt;div style=&#34;text-align: center&#34;&gt;
  &lt;canvas id=&#34;example9-1&#34; width=&#34;512&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
  &lt;canvas id=&#34;example9-2&#34; width=&#34;512&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;p&gt;Although walls now appear further.
I&amp;rsquo;ve tried to make up constants that will play nice to make the wall occupy the whole height when we near the wall, so I&amp;rsquo;ll keep it this way.
I&amp;rsquo;m sure I have some misunderstanding of the algorithm, but it works, so I&amp;rsquo;m ok with that.&lt;/p&gt;
&lt;h2 id=&#34;handling-input-and-focus&#34;&gt;Handling input and focus&lt;/h2&gt;
&lt;p&gt;Now, when we have our camera working, we can make it move by pressing arrow keys.
We already have needed procedures for handling camera position and rotation, so the only thing we really need is input handlers, and a way to focus our canvas, so pressing arrows would not scroll the page.&lt;/p&gt;
&lt;p&gt;There are some libraries for handling keyboard input, but I&amp;rsquo;m a purist, so we&amp;rsquo;ll implement this without dependencies.
All we need is two procedures, that check if a key is pressed, and that it is released.
Let&amp;rsquo;s create &lt;code&gt;raycasting/input.cljs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;raycasting.input&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defonce &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key-states&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;atom&lt;/span&gt; {}))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defonce &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;focus&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We start by defining another atom for our key states.
It will hold a map of keys and their states, like this &lt;code&gt;{&amp;quot;Up&amp;quot; false, &amp;quot;Down&amp;quot; true}&lt;/code&gt;, which means that currently the &lt;kbd&gt;Down&lt;/kbd&gt; key is pressed down.
Another one is &lt;code&gt;focus&lt;/code&gt; which we will use to determine whether should we handle input or not.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s add these three procedures:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;valid-key?&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= key &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Escape&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= key &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Shift&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= key &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;ArrowLeft&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= key &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;ArrowUp&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= key &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;ArrowRight&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= key &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;ArrowDown&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;on-key-press&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;focus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-event&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;key &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-key&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;valid-key?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;preventDefault&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key-states&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc key &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;true&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;on-key-release&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;focus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-event&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;key &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-key&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;valid-key?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key-states&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc key &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;preventDefault&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;ll get our keys as strings, and check if this is one of the keys we need.
If it is, and we&amp;rsquo;re focused, we &lt;code&gt;swap!&lt;/code&gt; our &lt;code&gt;key&lt;/code&gt; state with either &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;, so our &lt;code&gt;key-states&lt;/code&gt; atom always holds most recent state.
Now we need to assign these procedures to events:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-onkeyup&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;on-key-release&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-onkeydown&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;on-key-press&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We also have these procedures to handle focus:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;on-click&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;focus&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;true&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;release-focus&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;focus&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;false&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But we set these in the initialization code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;^&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:export&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;init&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;raycaster&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;mousedown&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;input/on-click&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/set-position&lt;/span&gt; 10 10 45)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-getContext&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getContext&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;2d&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The final step would be to poll our keys on each frame in our &lt;code&gt;render&lt;/code&gt; procedure.
For this, we create another procedure, but in &lt;code&gt;raycasting.core&lt;/code&gt; this time:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-camera&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key-states&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;} @&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key-states&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Escape&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;input/release-focus&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;reset!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;input/key-states&lt;/span&gt; {}))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key-states&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;ArrowRight&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key-states&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Shift&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt;} (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/strafe&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; -1.5)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;detect-collision&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;&amp;#39;]]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/strafe&lt;/span&gt; -1)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/rotate&lt;/span&gt; -1.5)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key-states&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;ArrowLeft&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key-states&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Shift&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt;} (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/strafe&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; 1.5)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;detect-collision&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;&amp;#39;]]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/strafe&lt;/span&gt; 1)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/rotate&lt;/span&gt; 1.5)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key-states&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;ArrowUp&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt;} (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-forward&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; 1.5)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;detect-collision&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;&amp;#39;]]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-forward&lt;/span&gt; 1.5))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;key-states&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;ArrowDown&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt;} (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-forward&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; -1.5)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;detect-collision&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;&amp;#39;]]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-forward&lt;/span&gt; -1.5))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We then, call this procedure each frame as early as possible.
You can notice that we&amp;rsquo;re calling another procedure &lt;code&gt;detect-collision&lt;/code&gt;, it is much like our intersection finding stuff, but it calculates the end position of our camera, and checks if the path intersects with any of our walls.
Not very optimal, but works well.&lt;/p&gt;
&lt;p&gt;The last thing I want to add is a way to control the amount of rays, and field of view, as well as a fisheye compensation toggle.
For that we&amp;rsquo;ll need these &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; tags:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;input type=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;range&amp;#34;&lt;/span&gt; id=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rayCountSlider&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         min=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;10&amp;#34;&lt;/span&gt; max=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;256&amp;#34;&lt;/span&gt; step=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/input&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;label for=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rayCountSlider&amp;#34;&lt;/span&gt;&amp;gt;Ray Count: &amp;lt;/label&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;output name=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rayCountValue&amp;#34;&lt;/span&gt; id=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rayCountOutput&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/output&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;input type=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;range&amp;#34;&lt;/span&gt; id=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;fovSlider&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         min=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;10&amp;#34;&lt;/span&gt; max=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;360&amp;#34;&lt;/span&gt; step=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/input&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;label for=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;fovSlider&amp;#34;&lt;/span&gt;&amp;gt;Field of View: &amp;lt;/label&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;output name=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;fovSliderValue&amp;#34;&lt;/span&gt; id=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;fovSliderOutput&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/output&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;input type=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;checkbox&amp;#34;&lt;/span&gt; id=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;fishEyeCompensation&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/input&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;label for=&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;fishEyeCompensation&amp;#34;&lt;/span&gt;&amp;gt; FishEye compensation&amp;lt;/label&amp;gt;&amp;lt;br&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And we need a way to control those.
For this, let&amp;rsquo;s add these procedures:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-fov&lt;/span&gt; 360)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-compensated-fov&lt;/span&gt; 180)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;update-ray-count&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;.. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-target&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-value&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/parseInt&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;output&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rayCountOutput&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;output&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-innerHTML&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;update-fov&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;.. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-target&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-value&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/parseInt&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;output&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;fovSliderOutput&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;output&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-innerHTML&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;update-fish-eye-compensation&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;.. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-target&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-checked&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*compensate-fisheye*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov-slider&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;fovSlider&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov-slider&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-max&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-compensated-fov&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-fov&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-compensated-fov&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-compensated-fov&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov-slider&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-value&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-compensated-fov&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov-output&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;fovSliderOutput&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov-output&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-innerHTML&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt;))))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;init-inputs&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-count-slider&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rayCountSlider&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-count-slider&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-value&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-count-slider&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;update-ray-count&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-count-output&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rayCountOutput&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-count-output&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-innerHTML&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov-slider&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;fovSlider&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov-slider&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;update-fov&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov-slider&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-max&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*compensate-fisheye*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-compensated-fov&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;max-fov&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fov-slider&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-value&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-count-output&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;fovSliderOutput&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-count-output&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-innerHTML&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;compensate&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/document&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getElementById&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;fishEyeCompensation&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;compensate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;addEventListener&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;update-fish-eye-compensation&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;compensate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-value&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*compensate-fisheye*&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In short, these are event handlers, which are called when we&amp;rsquo;re interacting with these inputs.
We&amp;rsquo;re setting initial values as well, as the handlers in &lt;code&gt;init-input&lt;/code&gt; procedure.&lt;/p&gt;
&lt;h2 id=&#34;coloring-walls&#34;&gt;Coloring walls&lt;/h2&gt;
&lt;p&gt;Up until now, we were creating gray walls, which are fine, but boring.
And you could notice that we&amp;rsquo;re drawing our lines in color, so walls have color information.
Let&amp;rsquo;s update our &lt;code&gt;find-intersections&lt;/code&gt; procedure to include color information, and use it to color our walls:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;find-intersections&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;origin&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersect?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;font-weight:bold&#34;&gt;new &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;intersection &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  [(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;origin&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;new&lt;/span&gt;) {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:end&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;new &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:color&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#eeeeee&amp;#34;&lt;/span&gt;)}])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                [10000000 {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:end&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:color&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt;}])))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;into &lt;/span&gt;{})))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we return a map that has length as its key, and another map, which holds endpoint and wall color as a value.
We need to update our &lt;code&gt;cast-rays&lt;/code&gt; procedure to use this information:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cast-rays&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;step&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; [(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;central-ray&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;) 100)]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/rotate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt; 2.0))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt; ()]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;do &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-point&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; 5000)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersections&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;find-intersections&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shortest-ray&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;apply min &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;keys &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersections&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;&#34;&gt;➊&lt;/span&gt; {&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:end&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:color&lt;/span&gt;} (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersections&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shortest-ray&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-angle&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*compensate-fisheye*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;angle-between&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;central-ray&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                              0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;step&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;conj &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:end&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-end&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:length&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;shortest-ray&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:angle&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-angle&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:n&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;}))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We destructure our map ➊, and then use its values when we &lt;code&gt;conj&lt;/code&gt; rays.
If we use this color in our &lt;code&gt;draw-3d-stage&lt;/code&gt; procedure, we&amp;rsquo;ll finally get results similar to what I showed in the very beginning:&lt;/p&gt;
&lt;div style=&#34;text-align: center&#34;&gt;
  &lt;canvas id=&#34;example10&#34; width=&#34;512&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;p&gt;But it would be nice if we keep the effect that more distant walls appear darker.
To do that we&amp;rsquo;ll have to parse color, and dim it by some factor:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dim&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dim-factor&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/pow&lt;/span&gt; 1.1 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;inc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;amount&lt;/span&gt;) 7))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;int &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dim-factor&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; 25)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      25
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dim-color&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;red&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/parseInt&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;0x&amp;#34;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;subs &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; 1 3)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;green&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/parseInt&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;0x&amp;#34;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;subs &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; 3 5)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;blue&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/parseInt&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;0x&amp;#34;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;subs &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; 5)))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rgb(&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dim&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;red&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dim&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;green&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dim&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;blue&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These two procedures will dim colors encoded as six-digit hex colors, or &lt;code&gt;#ffffff&lt;/code&gt;.
We use our distance as the dim factor with some computations to make it look nice.
Now we can use it in our &lt;code&gt;draw-3d-stage&lt;/code&gt; procedure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-3d-stage&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-width&lt;/span&gt;) 2) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-width&lt;/span&gt;) 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;projection-distance&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;projection-distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gradient&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;createLinearGradient&lt;/span&gt; 0 0 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;doto &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gradient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.addColorStop&lt;/span&gt; 0 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#424242&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.addColorStop&lt;/span&gt; 0.5 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#111111&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.addColorStop&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#e2e2e2&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-fillStyle&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;gradient&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fillRect&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;sort &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l1&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:length&lt;/span&gt;} {&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l2&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:length&lt;/span&gt;}] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l1&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;l2&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;first &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:length&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-degree&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:angle&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:n&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:color&lt;/span&gt;} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;angle-step&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*compensate-fisheye*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;m/three-decimal&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Math/cos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-degree&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ray-count*&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;projection-distance&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*fov*&lt;/span&gt; 4))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dim-color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;distance&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set!&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-fillStyle&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;color&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fillRect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;canvas-width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;* &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-width&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; 2) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;/ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt; 2))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ray-width&lt;/span&gt; 1) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; extra pixel for border&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall-height&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rest &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve also added a bit more nice gradient for our background color there.
This will be our final version of this procedure.&lt;/p&gt;
&lt;h2 id=&#34;labyrinth-game&#34;&gt;Labyrinth game&lt;/h2&gt;
&lt;p&gt;Now we can create a small labyrinth game, but we need a way to determine if the goal was reached.
But first, we need a stage to play on, as our current one isn&amp;rsquo;t really a good one.
I&amp;rsquo;ve come up with this:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/labyrinth.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Our goal is to reach that colored corridor.
To check if we succeeded we&amp;rsquo;ll simply check if our camera is inside the square.
To check that we&amp;rsquo;ll use our raycasting facilities.
The algorithm is pretty easy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We cast rays from our point to the right,&lt;/li&gt;
&lt;li&gt;We count with how many walls of a given square we intersect with,&lt;/li&gt;
&lt;li&gt;If the amount of intersections is odd then we&amp;rsquo;re inside.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can see that this works for us:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/inside.svg&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Of course, there are special cases, like when a point lies on either of the rectangle sides, but we can&amp;rsquo;t intersect with walls, because we detect collisions, so we&amp;rsquo;ll be fine.
Here&amp;rsquo;s the code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;inside-rectangle&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ax&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ay&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;by&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cy&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dy&lt;/span&gt;]]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;walls&lt;/span&gt; [[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ax&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ay&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;by&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;by&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cy&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cy&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dy&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dx&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;dy&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ax&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ay&lt;/span&gt;]]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt;} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt;} (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/move-forward&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:y&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:degree&lt;/span&gt; 90} 1000)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;walls&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;intersect?&lt;/span&gt; [[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;&amp;#39; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;y&lt;/span&gt;&amp;#39;]] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wall&lt;/span&gt;) 1 0)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;reduce + &lt;/span&gt;0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;odd?&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We receive four points that define our goal and move the camera 90 degrees right to some amount.
Then we map &lt;code&gt;intersect?&lt;/code&gt; procedure across our walls, returning either &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;0&lt;/code&gt; depending on collision detection, and &lt;code&gt;reduce&lt;/code&gt; results with &lt;code&gt;+&lt;/code&gt;, to finally check if the result is &lt;code&gt;odd?&lt;/code&gt; or not.&lt;/p&gt;
&lt;p&gt;Though we need some way to extract goals from our stage, I&amp;rsquo;ll just define it as a constant because I don&amp;rsquo;t want to make stage code even more complex than it is now, and we&amp;rsquo;re not going to change stages.
So when we&amp;rsquo;ve reached our goal, we&amp;rsquo;ll just teleport the camera back to starting point:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;move-camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt; @&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;input/key-states&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;inside-rectangle&lt;/span&gt; @&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage/goal&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/set-position&lt;/span&gt; 12 195 180))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*canvas*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-width&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; @&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cam/camera&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cast-rays&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*ctx*&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clearRect&lt;/span&gt; 0 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-rays&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-camera&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;camera&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-stage&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;stage&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;draw-3d-stage&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rays&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;. &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;js/window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;requestAnimationFrame&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;render&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Combining all this stuff should give us this small game:&lt;/p&gt;
&lt;div style=&#34;text-align: center&#34;&gt;
  &lt;canvas id=&#34;raycaster&#34; width=&#34;512&#34; height=&#34;224&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;input type=&#34;range&#34; id=&#34;rayCountSlider&#34;
         min=&#34;10&#34; max=&#34;256&#34; step=&#34;1&#34;&gt;&lt;/input&gt;
  &lt;label for=&#34;rayCountSlider&#34;&gt;Ray Count: &lt;/label&gt;
  &lt;output name=&#34;rayCountValue&#34; id=&#34;rayCountOutput&#34;&gt;&lt;/output&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;input type=&#34;range&#34; id=&#34;fovSlider&#34;
         min=&#34;10&#34; max=&#34;360&#34; step=&#34;1&#34;&gt;&lt;/input&gt;
  &lt;label for=&#34;fovSlider&#34;&gt;Field of View: &lt;/label&gt;
  &lt;output name=&#34;fovSliderValue&#34; id=&#34;fovSliderOutput&#34;&gt;&lt;/output&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;input type=&#34;checkbox&#34; id=&#34;fishEyeCompensation&#34;&gt;&lt;/input&gt;
  &lt;label for=&#34;fishEyeCompensation&#34;&gt; FishEye compensation&lt;/label&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;You can click on this canvas, and use &lt;kbd&gt;Up&lt;/kbd&gt;, &lt;kbd&gt;Down&lt;/kbd&gt;, &lt;kbd&gt;Left&lt;/kbd&gt;, &lt;kbd&gt;Right&lt;/kbd&gt; to move, you also can strafe to the side while holding &lt;kbd&gt;Shift&lt;/kbd&gt;, and pressing &lt;kbd&gt;Esc&lt;/kbd&gt; will return focus to the page so you could scroll it with arrow keys as usual.&lt;/p&gt;
&lt;h2 id=&#34;what-i-ve-learned&#34;&gt;What I&amp;rsquo;ve learned&lt;/h2&gt;
&lt;p&gt;This project was extremely fun to do in ClojureScript, and Clojure itself is quite an awesome language, although those have some differences.
If you&amp;rsquo;re learning Clojure, I highly recommend &lt;a href=&#34;https://www.braveclojure.com/&#34; target=&#34;_blank&#34;&gt;Clojure for the Brave and True&lt;/a&gt; book, and although I didn&amp;rsquo;t finish it yet, I&amp;rsquo;ve borrowed a lot of ideas from there, like using these little Unicode circles (➊) to mark stuff for further explanations.
This book has a &lt;a href=&#34;https://www.braveclojure.com/functional-programming/#Peg_Thing&#34; target=&#34;_blank&#34;&gt;&amp;ldquo;Peg Thing&amp;rdquo; game example&lt;/a&gt;, which got me thinking about trying something a bit more complex and real-time with Clojure, but I wasn&amp;rsquo;t sure how to draw graphics with Java stuff, so I&amp;rsquo;ve chosen ClojureScript because the canvas was very easy to reach.&lt;/p&gt;
&lt;p&gt;After implementing this, I think that while you don&amp;rsquo;t really need all these class objects like &lt;code&gt;point&lt;/code&gt;, &lt;code&gt;line&lt;/code&gt;, e.t.c.
as long as you&amp;rsquo;re passing those in meaningful contexts, which I didn&amp;rsquo;t really do through this post, and I expect that this code will be really hard to read after some point in time.
But certainly, maps provide most of what you need from a class or object and are more generic than objects.&lt;/p&gt;
&lt;p&gt;The cleaned-up source code for this project can be found &lt;a href=&#34;https://gitlab.com/andreyorst/raycasting-with-clojurescript&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt; if you&amp;rsquo;re interested in looking more closely.
I hope you&amp;rsquo;ve enjoyed the read, and got interested in Clojure or Lisp in particular if you&amp;rsquo;re not a Lisp hacker already.&lt;/p&gt;
&lt;script type=&#34;text/javascript&#34; src=&#34;https://andreyor.st/2020-06-04-simple-ray-casting-with-clojurescript/js/main.js&#34;&gt;&lt;/script&gt;
&lt;script&gt;
  window.onload = function() {
    raycasting.core.init();
  }
&lt;/script&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Simple Ray Casting with ClojureScript&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 04 Jun 2020 13:49:00 +0300</pubDate>
    </item>
  </channel>
</rss>
