<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>sunbro.dev</title><link>https://sunbro.dev/</link><description>Recent content on sunbro.dev</description><generator>Hugo -- 0.131.0</generator><language>en</language><lastBuildDate>Mon, 26 Aug 2024 10:15:42 +0200</lastBuildDate><atom:link href="https://sunbro.dev/index.xml" rel="self" type="application/rss+xml"/><item><title>Cleaning up the RSS feed</title><link>https://sunbro.dev/posts/2024-08-11-fixing-rss-papermod/</link><pubDate>Sun, 11 Aug 2024 18:00:00 +0100</pubDate><guid>https://sunbro.dev/posts/2024-08-11-fixing-rss-papermod/</guid><description>Updating PaperMod&amp;rsquo;s RSS template to fit my needs</description><content:encoded><![CDATA[<h2 id="motivation">Motivation</h2>
<p>After a 4 year hiatus, I&rsquo;m finally coming back around to this blog and doing some cleaning before writing again.
Part of that cleaning includes making sure the 
<a href="/index.xml/" >RSS feed</a> works as expected.
To do so, it needs to check off the following:</p>
<ul>
<li><input checked="" disabled="" type="checkbox"> Provide valid RSS content</li>
<li><input disabled="" type="checkbox"> Include the posts&rsquo; contents so they can easily be read with RSS readers</li>
<li><input disabled="" type="checkbox"> Exclude pages that are not posts</li>
</ul>
<p>The first box is ticked by default thanks to Hugo&rsquo;s RSS generator</p>
<h2 id="task-1-including-the-posts-contents">Task 1: Including the post&rsquo;s contents</h2>
<p>Looking at PaperMod&rsquo;s RSS layout, I noticed the following code:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl">{{- if and site.Params.ShowFullTextinRSS .Content }}
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;content:encoded&gt;</span>{{ (printf &#34;<span class="cp">&lt;![CDATA[%s]]&gt;</span>&#34; .Content) | safeHTML }}<span class="nt">&lt;/content:encoded&gt;</span>
</span></span><span class="line"><span class="cl">{{- end }}
</span></span></code></pre></div><p>This might&rsquo;ve been added some time in the 4 years since I started this blog and seems to solve all of our problems.
One update to our site&rsquo;s config and voilà, the RSS feed&rsquo;s XML includes our posts&rsquo; content in it!</p>
<p>One task down, one to go!</p>
<h2 id="task-2-excluding-specific-pages">Task 2: Excluding specific pages</h2>
<h3 id="the-easy-way">The easy way</h3>
<p>As pointed out on 
<a href="https://discourse.gohugo.io/t/rss-feed-only-for-blog-posts/47558" target="_blank" >Hugo&rsquo;s Discourse</a> there is a straightforward way to generate an RSS feed only for blog posts:</p>
<ol>
<li>Update the <code>output</code> section of your site&rsquo;s config file so it does not include RSS</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="cl">[...]
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[output]
</span></span><span class="line"><span class="cl"><span class="gd">- home = [&#34;HTML&#34;, &#34;RSS&#34;, &#34;JSON&#34;]
</span></span></span><span class="line"><span class="cl"><span class="gd"></span><span class="gi">+ home = [&#34;HTML&#34;, &#34;JSON&#34;]
</span></span></span><span class="line"><span class="cl"><span class="gi"></span>
</span></span><span class="line"><span class="cl">[...]
</span></span></code></pre></div><ol start="2">
<li>Add an <code>_index.md</code> file to your <code>/posts</code> subfolder with the following front matter:</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="l">+++</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">title = &#34;Posts&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">outputs = [&#34;HTML&#34;, &#34;RSS&#34;]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">+++</span><span class="w">
</span></span></span></code></pre></div><ol start="3">
<li>We now have an RSS feed at <code>https://sunbro.dev/posts/index.xml</code>!</li>
</ol>
<p>&hellip; but there&rsquo;s one problem: this breaks the feed for anyone already subscribed to the current feed at <code>https://sunbro.dev/index.xml</code>. That URL now 404s.</p>
<h3 id="the-correct-way">The &ldquo;correct&rdquo; way</h3>
<style type="text/css">
     
    .notice {
        --title-color: #fff;
        --title-background-color: #6be;
        --content-color: #444;
        --content-background-color: #e7f2fa;
    }

    .notice.info {
        --title-background-color: #fb7;
        --content-background-color: #fec;
    }

    .notice.tip {
        --title-background-color: #5a5;
        --content-background-color: #efe;
    }

    .notice.warning {
        --title-background-color: #c33;
        --content-background-color: #fee;
    }

     
    @media (prefers-color-scheme:dark) {
        .notice {
            --title-color: #fff;
            --title-background-color: #069;
            --content-color: #ddd;
            --content-background-color: #023;
        }

        .notice.info {
            --title-background-color: #a50;
            --content-background-color: #420;
        }

        .notice.tip {
            --title-background-color: #363;
            --content-background-color: #121;
        }

        .notice.warning {
            --title-background-color: #800;
            --content-background-color: #400;
        }
    }

    body.dark .notice {
        --title-color: #fff;
        --title-background-color: #069;
        --content-color: #ddd;
        --content-background-color: #023;
    }

    body.dark .notice.info {
        --title-background-color: #a50;
        --content-background-color: #420;
    }

    body.dark .notice.tip {
        --title-background-color: #363;
        --content-background-color: #121;
    }

    body.dark .notice.warning {
        --title-background-color: #800;
        --content-background-color: #400;
    }

     
    .notice {
        padding: 18px;
        line-height: 24px;
        margin-bottom: 24px;
        border-radius: 4px;
        color: var(--content-color);
        background: var(--content-background-color);
    }

    .notice p:last-child {
        margin-bottom: 0
    }

     
    .notice-title {
        margin: -18px -18px 12px;
        padding: 4px 18px;
        border-radius: 4px 4px 0 0;
        font-weight: 700;
        color: var(--title-color);
        background: var(--title-background-color);
    }

     
    .icon-notice {
        display: inline-flex;
        align-self: center;
        margin-right: 8px;
    }

    .icon-notice img,
    .icon-notice svg {
        height: 1em;
        width: 1em;
        fill: currentColor;
    }

    .icon-notice img,
    .icon-notice.baseline svg {
        top: .125em;
        position: relative;
    }
</style><div class="notice info" >
    <p class="notice-title">
        <span class="icon-notice baseline">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="92 59.5 300 300">
  <path d="M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z"/>
</svg>

        </span>Info</p><p>This definitely not the only way to do this and there are certainly more &ldquo;Hugo-ist&rdquo; ways to do it.</p></div>

<p>Now that we know we want to preserve the current <code>/index.xml</code> let&rsquo;s give ourselves a way to exclude certain pages from it.
Let&rsquo;s add a new entry on to our pages&rsquo; config: <code>RSSExclude</code>. You should add it to all the pages you want to exclude from the RSS feed.</p>
<p>For example in my <code>projects.md</code> that I want to exclude I added:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="l">+++</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">title = &#34;Projects&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">[</span><span class="l">...]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">RSSExclude = true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">+++</span><span class="w">
</span></span></span></code></pre></div><p>Now, let&rsquo;s customise PaperMod&rsquo;s <code>index.xml</code> layout to take it into account.
Copy the theme&rsquo;s file into your <code>/layouts/_default/</code> and edit it as follows:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="cl"><span class="gd">- {{- if and (ne .Layout `search`) (ne .Layout `archives`) }}
</span></span></span><span class="line"><span class="cl"><span class="gd"></span><span class="gi">+ {{- if ne .Params.RssExclude true }}
</span></span></span><span class="line"><span class="cl"><span class="gi"></span>    &lt;item&gt;
</span></span><span class="line"><span class="cl">        [...]
</span></span><span class="line"><span class="cl">    &lt;/item&gt;
</span></span><span class="line"><span class="cl">{{- end }}
</span></span></code></pre></div><p>Instead of only excluding pages with the <code>search</code> or <code>archives</code> layouts we now exclude all pages where <code>RSSExclude</code> is <code>true</code>.</p>
<p>Task two, check!</p>
<h2 id="conclusion">Conclusion</h2>
<p>I&rsquo;m happy to see this was much easier than I thought.
Although I wish PaperMod natively supported excluding pages from the RSS feed, this has only motivated me to tweak the theme&rsquo;s layouts even further in the future.</p>
]]></content:encoded></item><item><title>Presenting Nocode: The future of programming</title><link>https://sunbro.dev/posts/2020-10-10-nocode-writeup/</link><pubDate>Sat, 10 Oct 2020 20:09:00 +0100</pubDate><guid>https://sunbro.dev/posts/2020-10-10-nocode-writeup/</guid><description>A simple way to write clean single-file code without taking up disk space</description><content:encoded><![CDATA[<h2 id="idea">Idea</h2>
<p>The initial idea comes from a discussion with friends over dinner a couple of
nights ago, when we realized <code>ar(1)</code> can read input from <code>STDIN</code>. While we were
wondering why that would be useful and what it could be used for, one of use
mentioned that <code>gcc(1)</code> can also read input from <code>STDIN</code>. From there, the
conversation derailed into how to &ldquo;misuse&rdquo; that feature in order to do something
completely over the top and useless.</p>
<p>Inspired by Kelsey Hightower&rsquo;s 
<a href="https://github.com/kelseyhightower/nocode" target="_blank" >nocode</a> idea, we wanted to
use <code>gcc(1)</code> to write our code directly on <code>STDIN</code>, compile it, and, if successful,
add and commit it to a git repo. Obviously doing all of this by hand wouldn&rsquo;t cut
it, so all of it had to be &ldquo;automated&rdquo; or neatly wrapped into a useable script.</p>
<p>Which then gave birth to <code>Nocode: A simple way to write clean single-file code without taking up disk space</code>.</p>
<h2 id="implementation">Implementation</h2>
<p><code>Nocode</code> is essentialy a bash script which wraps all of the useful steps.</p>
<p>It starts of by creating and filling a <code>.gitignore</code> file if none exist, as to
not create git clutter with the following steps.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> ! -f <span class="s2">&#34;.gitignore&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">    <span class="k">$(</span><span class="nb">echo</span> <span class="s2">&#34;a.out&#34;</span> &gt;&gt; <span class="s2">&#34;.gitignore&#34;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">$(</span><span class="nb">echo</span> -n <span class="s2">&#34;*.c&#34;</span> &gt;&gt; <span class="s2">&#34;.gitignore&#34;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span></code></pre></div><p>The script then goes on to read the code from <code>STDIN</code>, in order to compiling it.
Before passing the input to <code>gcc(1)</code> it is first given to <code>clang-format</code> in
order to apply the coding style the user wants. This is then input to <code>tee(1)</code> in
order to save it until it is committed to our git repository, and finally into
<code>gcc(1)</code> for compilation.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># &#34;$ARG&#34; is equal to the first argument given to Nocode</span>
</span></span><span class="line"><span class="cl"><span class="k">$(</span>clang-format <span class="p">|</span> tee <span class="s2">&#34;</span><span class="nv">$ARG</span><span class="s2">&#34;</span> <span class="p">|</span> gcc -x c -<span class="k">)</span>
</span></span></code></pre></div><p>The next step is to check if the script was called in a git repository, if not
the user is prompted to initialize one. If the user refuses, the script stops and
the generated C file is saved.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Check if we&#39;re it a git repository</span>
</span></span><span class="line"><span class="cl"><span class="k">$(</span>git status <span class="p">&amp;</span>&gt;/dev/null<span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="nv">$?</span><span class="s2">&#34;</span> -ne <span class="m">0</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">    <span class="nb">read</span> -p <span class="s2">&#34;Not a git repository, do you want to create one? [Y/n] &#34;</span> USERCREATEGITINPUT
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="nv">$USERCREATEGITINPUT</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s2">&#34;n&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        <span class="nb">echo</span> <span class="s2">&#34;nocode.sh: leaving file as is&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="nb">exit</span> <span class="m">0</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">$(</span>git init <span class="p">&amp;</span>&gt;/dev/null<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span></code></pre></div><p>To finish everything off, the file is added and committed to the repository before
finally being deleted.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Perform all git actions except push, left up to the user</span>
</span></span><span class="line"><span class="cl"><span class="k">$(</span>git add <span class="s2">&#34;</span><span class="nv">$ARG</span><span class="s2">&#34;</span> <span class="p">&amp;</span>&gt;/dev/null<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="k">$(</span>git commit -m <span class="s2">&#34;</span><span class="nv">$ARG</span><span class="s2">: update&#34;</span> <span class="p">&amp;</span>&gt;/dev/null<span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Remove file because we&#39;re #NoCodeCompliant</span>
</span></span><span class="line"><span class="cl"><span class="k">$(</span>rm <span class="s2">&#34;</span><span class="nv">$ARG</span><span class="s2">&#34;</span><span class="k">)</span>
</span></span></code></pre></div><p>Of course, not all of the boilerplate is presented here because it is not very
interesting. The scource code is available on 
<a href="https://github.com/quentin-dev/nocode" target="_blank" >GitHub</a>. Issues
and PRs are welcome!</p>
<h2 id="usage">Usage</h2>
<p>All you have to do to use <code>Nocode</code> is call it with the filename you want to
save, as follows:</p>
<p><code>./nocode.sh filename.c</code></p>
<p>Once you are done writing your code on <code>STDIN</code>, you can use <code>CTRL+D</code> to send
an <code>EOF</code> in order to tell <code>clang-format</code> that you are done typing.</p>
<p>Pushing the code to the repository&rsquo;s remote is left up to the user in order to
avoid dealing with git credentials.</p>
]]></content:encoded></item><item><title>Adding video support to the Hugo Terminal theme</title><link>https://sunbro.dev/posts/2020-05-20-adding-video-support-to-hugo-terminal/</link><pubDate>Sun, 17 May 2020 22:32:00 +0100</pubDate><guid>https://sunbro.dev/posts/2020-05-20-adding-video-support-to-hugo-terminal/</guid><description>Using Hugo shortcodes to adapt Hugo to my needs</description><content:encoded><![CDATA[<h2 id="problem">Problem</h2>
<p>At the time of writing this post, this website uses 
<a href="https://gohugo.io/" target="_blank" ><strong>Hugo</strong></a> and the

<a href="https://themes.gohugo.io/hugo-theme-terminal/" target="_blank" ><strong>Terminal</strong></a> theme by 
<a href="https://twitter.com/panr" target="_blank" ><strong>panr</strong></a>. I really like
the way this theme handles content and Markdown integration, but there is no
native support for videos. This is probably due to the fact that there currently
is no way to embed videos in Markdown files, unlike images for example.</p>
<p>This problem reared its head when I was writing my first Pokémon Emerald romhack

<a href="/posts/2020-05-08-making-a-simple-romhack/" ><strong>post</strong></a>. At the time, I planned to use GIFs to illustrate the
changes made to the game. However, I quickly realised that GIFs take up a lot
of memory and can take quite long to load for readers, contrary to videos, MP4
in our case, which are up to 10 times smaller !</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ du -h static/captures/birch_speech_original.gif
</span></span><span class="line"><span class="cl">3.1M static/captures/birch_speech_original.gif
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">$ du -h static/captures/birch_speech_original.mp4
</span></span><span class="line"><span class="cl">332K static/captures/birch_speech_original.mp4
</span></span></code></pre></div><h2 id="solution">Solution</h2>
<p>The answer to our solution comes in the form of Hugo &ldquo;shortcodes&rdquo;. Shortcodes are
a way to bridge the gap from Markdown to HTML. Therefore, we can use one to handle
integrating videos in our posts&rsquo; Markdown files.</p>
<p>To get started create a <code>shortcodes</code> sub-directory in your <code>layouts</code> folder. Once
that is done create a <code>video.html</code> file in <code>layouts/shortcodes/</code>. The shortcode&rsquo;s
code is as follows:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">video</span> <span class="na">autoplay</span> <span class="na">loop</span> <span class="na">muted</span> <span class="na">playsinline</span> <span class="na">aria-label</span><span class="o">=</span><span class="s">&#39;{{ .Get &#34;label&#34;}}&#39;</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;width: 100%; height: auto;&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    {{ with .Get &#34;mp4&#34; }}<span class="p">&lt;</span><span class="nt">source</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;{{ . }}&#34;</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;video/mp4&#34;</span><span class="p">&gt;</span>{{ end }}
</span></span><span class="line"><span class="cl">    {{ with .Get &#34;webm&#34; }}<span class="p">&lt;</span><span class="nt">source</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;{{ . }}&#34;</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;video/webm&#34;</span><span class="p">&gt;</span>{{ end }}
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span> Your browser does not support video. <span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">video</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>The syntax is explicit enough to get a basic grasp of how it works. Our shortcode
takes three possible parameters: <code>label</code>, <code>mp4</code>, and <code>webm</code>. If <code>label</code> is defined,
its contents become the <code>aria-label</code> of the video HTML element. If <code>mp4</code> or <code>webm</code>
is defined, their contents become the source for the video element.</p>
<p>The rest of the shortcode is plain HTML, with inlined style to make it &ldquo;responsive&rdquo;
and readable on mobile devices.</p>
<p>Using the shortcode in a post&rsquo;s Markdown file goes like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Markdown" data-lang="Markdown"><span class="line"><span class="cl">{{<span class="p">&lt;</span> <span class="nt">video</span> <span class="na">label</span><span class="o">=</span><span class="s">&#34;this is a label&#34;</span> <span class="na">mp4</span><span class="o">=</span><span class="s">&#34;/path/to/video.mp4&#34;</span> <span class="p">&gt;</span>}}
</span></span></code></pre></div><p>I hope this helps you if you encounter the same problem, good luck!</p>
]]></content:encoded></item><item><title>Making a simple Pokémon romhack - Editing a map</title><link>https://sunbro.dev/posts/2020-05-15-romhack-map-editing/</link><pubDate>Fri, 15 May 2020 12:54:00 +0100</pubDate><guid>https://sunbro.dev/posts/2020-05-15-romhack-map-editing/</guid><description>Editing the Littleroot Town map</description><content:encoded><![CDATA[<h2 id="current-state-of-affairs">Current state of affairs</h2>
<p>Here is where our romhack currently stands:</p>
<ol>
<li><input checked="" disabled="" type="checkbox"> Changing <strong>Professor Birch&rsquo;s speech</strong></li>
<li><input disabled="" type="checkbox"> Changing the <strong>Littleroot Town map</strong></li>
<li><input disabled="" type="checkbox"> Adding an <strong>interaction event in Littleroot Town</strong></li>
<li><input disabled="" type="checkbox"> Changing the <strong>starter Pokémons</strong></li>
<li><input disabled="" type="checkbox"> Changing the <strong>first trainer&rsquo;s team</strong></li>
<li><input disabled="" type="checkbox"> Modifying the <strong>first wild Pokémons</strong></li>
</ol>
<h2 id="goal">Goal</h2>
<p>The goal for this step is to modify the starting town&rsquo;s map, and add an object
we will later be able to interact with. This object will most likely be a
signpost, or npc, or one of both.</p>
<p>To make these changes, we are going to use <strong>Porymap</strong>, available 
<a href="https://github.com/huderlem/porymap" target="_blank" ><strong>here</strong></a>.</p>
<h2 id="using-porymap">Using Porymap</h2>
<p>Once you&rsquo;ve compiled and executed the <strong>Porymap</strong> binary and opened the relevant
project, our romhack in this case, you should an interface that is reminiscent
of the typical RPG Maker interface.</p>
<p>The leftmost panel should be a list of folders named <code>gMapGroup0</code> through <code>gMapGroup33</code> at
the time of writing. Here is what each map group contains:</p>
<ul>
<li><strong>gMapGroup0</strong>: all of the &ldquo;<em>outside</em>&rdquo; maps - town layouts and routes</li>
<li><strong>gMapGroup1</strong> to <strong>gMapGroup16</strong>: all of the &ldquo;<em>indoor</em>&rdquo; maps for the
towns, with some exceptions like the inside of the moving truck found
during the introduction in Littleroot Town</li>
<li><strong>gMapGroup17</strong>  to <strong>gMapGroup23</strong> and <strong>gMapGroup27</strong> to <strong>gMapGroup33</strong>: all of the
&ldquo;<em>indoor</em>&rdquo; maps for all of the routes</li>
<li><strong>gMapGroup24</strong> to <strong>gMapGroup26</strong>: all of the remaining &ldquo;<em>indoor</em>&rdquo; maps - Battle
Frontier, caves, the inside of the moving truck, ships, etc&hellip;</li>
</ul>
<p>Take a moment to unroll of the folders and take a look at all of the different maps
you can edit. Once you&rsquo;re done, open <code>gMapGroup0</code> and select <code>[0.09] LittlerootTown</code>.</p>
<p>You should now see the town map in the center of your screen, and the map&rsquo;s tiles
on the right. The rest of the interface is intuitive enough and I will let you
refer to the official 
<a href="https://huderlem.github.io/porymap/" target="_blank" ><strong>documentation</strong></a> to see exactly what
everything does.</p>
<h2 id="making-our-first-map-change">Making our first map change</h2>
<p>Littleroot Town currently looks like this:</p>
<p>


<img src="/images/pokeemerald/littleroot_town_original.png" alt="Littleroot Town&amp;rsquo;s original map" loading="lazy" width="641"
    height="643" style="max-width: 100%; height: auto;" /></p>
<p>Let&rsquo;s add a puddle, and a signpost in the center and save our changes:</p>
<p>


<img src="/images/pokeemerald/littleroot_town_puddle.png" alt="Littleroot Town with a puddle" loading="lazy" width="639"
    height="642" style="max-width: 100%; height: auto;" /></p>
<p>Congratulations, you&rsquo;ve just edited your first map! However, as you might realise,
if you compile the rom and play it, the player goes right through the signpost.</p>
<video autoplay loop muted playsinline aria-label='The player does not collide with the signpost' style="width: 100%; height: auto;">
    <source src="/captures/littleroot_puddle_no_collision.mp4" type="video/mp4">
    
    <p> Your browser does not support video. </p>
</video>
<p>We now have to add collisions. To do so, select the <code>Collision</code> tab on the right, and
make it so the player cannot walk through the signpost. The map&rsquo;s collision look like
this:</p>
<p>


<img src="/images/pokeemerald/littleroot_town_update_collisions.png" alt="Littleroot Town&amp;rsquo;s updated collisions" loading="lazy" width="640"
    height="641" style="max-width: 100%; height: auto;" /></p>
<p>Save the map, compile the game, and you will see that the player cannot walk
through the signpost anymore:</p>
<video autoplay loop muted playsinline aria-label='The player collides with the sign' style="width: 100%; height: auto;">
    <source src="/captures/littleroot_puddle_collision.mp4" type="video/mp4">
    
    <p> Your browser does not support video. </p>
</video>
<p>Congratulations once again, you&rsquo;ve successfully edited a map and adjusted the collisions!</p>
<h2 id="interacting-with-the-signpost">Interacting with the signpost</h2>
<p>Switch to the events tab in the central panel, select the dropdown menu on the
right, next to <code>New Object</code> and choose <code>New Sign</code>. A new sign event should appear
in the top left corner (0,0) of the map. Select the pointer and move the event to
the signpost in the middle of the puddle.</p>
<p>


<img src="/images/pokeemerald/littleroot_events.png" alt="Littleroot Town events" loading="lazy" width="638"
    height="640" style="max-width: 100%; height: auto;" /></p>
<p>Name the script <code>LittlerootTown_EventScript_PuddleSign</code> and click the <code>Open Map Scripts</code>
button. If nothing happens, open the <code>data/maps/LittlerootTown/scripts.inc</code> file with the
text editor of your choice.</p>
<p>Add this code at the end of the file:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-S" data-lang="S"><span class="line"><span class="cl"><span class="n">LittlerootTown_EventScript_PuddleSign</span><span class="o">::</span>
</span></span><span class="line"><span class="cl">	<span class="n">msgbox</span> <span class="n">LittlerootTown_Text_PuddleSign</span><span class="p">,</span> <span class="n">MSGBOX_SIGN</span>
</span></span><span class="line"><span class="cl">	<span class="n">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">LittlerootTown_Text_PuddleSign</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">	<span class="n">.string</span> <span class="s">&#34;Welcome to the world famous Littleroot\n&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="n">.string</span> <span class="s">&#34;Town puddle$&#34;</span>
</span></span></code></pre></div><p>As you can imagine, this code creates a procedure called <code>LittlerootTown_EventScript_PuddleSign</code>
which creates a message box containing the text after the <code>LittlerootTown_Text_PuddleSign</code> label.
Save the file, recompile the game, and you should now be able to interact with the signpost:</p>
<video autoplay loop muted playsinline aria-label='Interacting with the puddle signpost' style="width: 100%; height: auto;">
    <source src="/captures/littleroot_puddle_interaction.mp4" type="video/mp4">
    
    <p> Your browser does not support video. </p>
</video>
<p>Good job, you&rsquo;ve now added your first interactive event to game and made a more
complete romhack!</p>
<p>That&rsquo;s it for now, next time we will edit the game&rsquo;s starter pokémons.</p>
]]></content:encoded></item><item><title>Making a simple Pokémon romhack - Getting started</title><link>https://sunbro.dev/posts/2020-05-08-making-a-simple-romhack/</link><pubDate>Thu, 07 May 2020 00:25:00 +0100</pubDate><guid>https://sunbro.dev/posts/2020-05-08-making-a-simple-romhack/</guid><description>Starting out with Pokémon Emerald</description><content:encoded><![CDATA[<h2 id="goals">Goals</h2>
<p>The goal of this project is to create a Pokémon Emerald romhack. To do so,
we are going to use a dissassembled version of the rom as a starting point. Using
different tools, we are going to modify the parts we want to change. The changes
we are going to make are the following:</p>
<ol>
<li>Changing <strong>Professor Birch&rsquo;s speech</strong></li>
<li>Changing the <strong>Littleroot Town map</strong></li>
<li>Adding an <strong>interaction event in Littleroot Town</strong></li>
<li>Changing the <strong>starter Pokémons</strong></li>
<li>Changing the <strong>first trainer&rsquo;s team</strong></li>
<li>Modifying the <strong>first wild Pokémons</strong></li>
</ol>
<h2 id="tools">Tools</h2>
<p>Here is a list of the tools we are going to use:</p>
<p><strong>A Pokémon Emerald disassembly</strong></p>
<ul>
<li><em>pokeemerald</em> - 
<a href="https://github.com/pret/pokeemerald" target="_blank" ><strong>Github</strong></a></li>
</ul>
<p><strong>A map editor</strong></p>
<ul>
<li><em>Porymap</em> - 
<a href="https://github.com/huderlem/porymap" target="_blank" ><strong>GitHub</strong></a></li>
</ul>
<p><strong>A Gameboy Advance emulator</strong> <em>(any will do)</em></p>
<ul>
<li><em>Visual Boy Advance M</em> - 
<a href="https://github.com/visualboyadvance-m/visualboyadvance-m" target="_blank" ><strong>GitHub</strong></a></li>
</ul>
<p><strong>A text editor</strong> <em>(any will do)</em></p>
<ul>
<li><em>Visual Studio Code</em> - 
<a href="https://github.com/microsoft/vscode" target="_blank" ><strong>GitHub</strong></a></li>
</ul>
<p>Setting up each of these tools is well documented and can be done without too
much of a hassle. Personally, I am working on a 2019 Dell XPS 13 running Arch
Linux, and all of these tools are usable without issues.</p>
<h2 id="making-our-first-change">Making our first change</h2>
<p>Right now, when we start the game we get the usual speech from Prof. Birch:</p>
<video autoplay loop muted playsinline aria-label='Prof. Birch&#39;s regular speech' style="width: 100%; height: auto;">
    <source src="/captures/birch_speech_original.mp4" type="video/mp4">
    
    <p> Your browser does not support video. </p>
</video>
<p>Let&rsquo;s change his opening line</p>
<blockquote>
<p>Hi! Sorry to keep you waiting!</p>
</blockquote>
<p>to</p>
<blockquote>
<p>Hey all you cool cats and kittens!</p>
</blockquote>
<p>To do so, start up your text editor and open the <code>data/text/birch_speech.inc</code>
file in the <em>pokeemerald</em> repository. You should see this as the first 7 lines
of the file:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-S" data-lang="S"><span class="line"><span class="cl"><span class="n">gText_Birch_Welcome</span><span class="o">::</span> <span class="o">@</span> <span class="m">82</span><span class="n">C897B</span>
</span></span><span class="line"><span class="cl"> 	<span class="n">.string</span> <span class="s">&#34;Hi! Sorry to keep you waiting!\p&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="n">.string</span> <span class="s">&#34;Welcome to the world of POKéMON!\p&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="n">.string</span> <span class="s">&#34;My name is BIRCH.\p&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="n">.string</span> <span class="s">&#34;But everyone calls me the POKéMON\n&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="n">.string</span> <span class="s">&#34;PROFESSOR.\p&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="n">.string</span> <span class="s">&#34;$&#34;</span>
</span></span></code></pre></div><p>From this sample, we can determine that the <code>\p</code> character indicates
when user input, typically the A button, is needed to go to the next
line of dialogue, and that the <code>\n</code> simply indicates a line break in
the dialogue.</p>
<p>In our case all we have to do here is to change the second line to</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-S" data-lang="S"><span class="line"><span class="cl">    <span class="n">.string</span> <span class="s">&#34;Hey all you cool cats and kittens!\p&#34;</span>
</span></span></code></pre></div><p>Now save the file, compile the rom, start a new game in your emulator
and you should see:</p>
<video autoplay loop muted playsinline aria-label='Prof. Birch&#39;s modified speech' style="width: 100%; height: auto;">
    <source src="/captures/birch_speech_remix.mp4" type="video/mp4">
    
    <p> Your browser does not support video. </p>
</video>
<p>Congratulations, you&rsquo;ve just made your first romhack ! Take a look at the
other lines of dialogue in the file, try to find other files that contain
NPC dialogue, modify them and see what happens.</p>
<p>Next time, we will explore how to customize the Littleroot Town map !</p>
]]></content:encoded></item><item><title>Specific callbacks for each element of a RecyclerAdapter</title><link>https://sunbro.dev/posts/2020-04-27-kotlin-method-as-argument/</link><pubDate>Mon, 27 Apr 2020 21:55:45 +0100</pubDate><guid>https://sunbro.dev/posts/2020-04-27-kotlin-method-as-argument/</guid><description>Figuring out how to set a specific callback with RecyclerAdapters</description><content:encoded><![CDATA[<h1 id="premise">Premise</h1>
<p>An Android school project which uses different APIs to get a list of all
Pokémons and information about them. This specific piece of code relates
to a list of all pokémons, or a 
<a href="https://bulbapedia.bulbagarden.net/wiki/National_Pok%C3%A9dex" target="_blank" ><strong>Pokédex</strong></a>.</p>
<p>Specifically, a <code>RecyclerAdapter</code> which sets the <code>OnClickListener</code> for each
row to the same thing:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Kotlin" data-lang="Kotlin"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">PokedexRecyclerAdapter</span><span class="p">(</span><span class="k">val</span> <span class="py">context</span><span class="p">:</span> <span class="n">Context</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                             <span class="k">val</span> <span class="py">data</span><span class="p">:</span> <span class="n">MutableList</span><span class="p">&lt;</span><span class="n">PokedexEntry</span><span class="p">&gt;):</span>
</span></span><span class="line"><span class="cl">       <span class="nc">RecyclerView</span><span class="p">.</span><span class="n">Adapter</span><span class="p">&lt;</span><span class="nc">PokedexRecyclerAdapter</span><span class="p">.</span><span class="n">ViewHolder</span><span class="p">&gt;()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreateViewHolder</span><span class="p">(</span><span class="n">parent</span><span class="p">:</span> <span class="n">ViewGroup</span><span class="p">,</span> <span class="n">viewType</span><span class="p">:</span> <span class="n">Int</span><span class="p">):</span> <span class="n">ViewHolder</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="k">val</span> <span class="py">rowView</span> <span class="p">:</span> <span class="n">View</span> <span class="p">=</span> <span class="nc">LayoutInflater</span><span class="p">.</span><span class="n">from</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                             <span class="p">.</span><span class="n">inflate</span><span class="p">(</span><span class="nc">R</span><span class="p">.</span><span class="n">layout</span><span class="p">.</span><span class="n">pokedex_list_item</span><span class="p">,</span> <span class="n">parent</span><span class="p">,</span> <span class="k">false</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">rowView</span><span class="p">.</span><span class="n">setOnClickListener</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="n">context</span> <span class="k">as</span> <span class="n">MainActivity</span><span class="p">).</span><span class="n">onEntryListClicked</span><span class="p">(</span><span class="k">it</span><span class="p">.</span><span class="n">tag</span><span class="p">.</span><span class="n">toString</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">ViewHolder</span><span class="p">(</span><span class="n">rowView</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onBindViewHolder</span><span class="p">(</span><span class="n">holder</span><span class="p">:</span> <span class="n">ViewHolder</span><span class="p">,</span> <span class="n">position</span><span class="p">:</span> <span class="n">Int</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// [...]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h1 id="problem">Problem</h1>
<p>As each row of the <code>RecyclerView</code> is a different pokémon, in some specific
fragments I needed to change the callback to a specific method call for
each entry.</p>
<p>The method I needed to call looked as follows:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Kotlin" data-lang="Kotlin"><span class="line"><span class="cl">    <span class="k">private</span> <span class="k">fun</span> <span class="nf">setUpSelectedPokemon</span><span class="p">(</span><span class="k">data</span><span class="p">:</span> <span class="n">PokedexEntry</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">selectedPokemon</span> <span class="p">=</span> <span class="k">data</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// Clear second type if new pokémon only has one
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="n">resetSelectedPokemon</span><span class="p">(</span><span class="k">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">selectedPokemonNameTextView</span><span class="p">.</span><span class="n">text</span> <span class="p">=</span> <span class="k">data</span><span class="p">.</span><span class="n">name</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// [...] More code that configures the selected Pokémon layout elements
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="p">}</span>
</span></span></code></pre></div><h1 id="solution">Solution</h1>
<p>The first step to fix this is to pass the callback as an argument to the
<code>RecyclerAdapter</code> although the main fix comes from moving the assignment
of the callback from 
<a href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter#onCreateViewHolder%28android.view.ViewGroup,%20int%29" target="_blank" ><strong><code>onCreateViewHolder()</code></strong></a>
to 
<a href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter#onBindViewHolder%28VH,%20int%29" target="_blank" ><strong><code>onBindViewHolder()</code></strong></a> which has access to the
<code>ViewHolder</code> and the position of the element in the list.</p>
<p>So the <code>RecyclerAdapter</code> now looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Kotlin" data-lang="Kotlin"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">PokedexRecyclerAdapter</span><span class="p">(</span><span class="k">val</span> <span class="py">context</span><span class="p">:</span> <span class="n">Context</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                             <span class="k">val</span> <span class="py">data</span><span class="p">:</span> <span class="n">MutableList</span><span class="p">&lt;</span><span class="n">PokedexEntry</span><span class="p">&gt;,</span>
</span></span><span class="line"><span class="cl">                             <span class="k">val</span> <span class="py">callback</span><span class="p">:</span> <span class="p">((</span><span class="n">PokedexEntry</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Unit</span><span class="p">)?</span> <span class="p">=</span> <span class="k">null</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">       <span class="nc">RecyclerView</span><span class="p">.</span><span class="n">Adapter</span><span class="p">&lt;</span><span class="nc">PokedexRecyclerAdapter</span><span class="p">.</span><span class="n">ViewHolder</span><span class="p">&gt;()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreateViewHolder</span><span class="p">(</span><span class="n">parent</span><span class="p">:</span> <span class="n">ViewGroup</span><span class="p">,</span> <span class="n">viewType</span><span class="p">:</span> <span class="n">Int</span><span class="p">):</span> <span class="n">ViewHolder</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="k">val</span> <span class="py">rowView</span> <span class="p">:</span> <span class="n">View</span> <span class="p">=</span> <span class="nc">LayoutInflater</span><span class="p">.</span><span class="n">from</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                             <span class="p">.</span><span class="n">inflate</span><span class="p">(</span><span class="nc">R</span><span class="p">.</span><span class="n">layout</span><span class="p">.</span><span class="n">pokedex_list_item</span><span class="p">,</span> <span class="n">parent</span><span class="p">,</span> <span class="k">false</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">ViewHolder</span><span class="p">(</span><span class="n">rowView</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onBindViewHolder</span><span class="p">(</span><span class="n">holder</span><span class="p">:</span> <span class="n">ViewHolder</span><span class="p">,</span> <span class="n">position</span><span class="p">:</span> <span class="n">Int</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1">// [...]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">callback</span> <span class="o">!=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">holder</span><span class="p">.</span><span class="n">itemView</span><span class="p">.</span><span class="n">setOnClickListener</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">callback</span><span class="o">!!</span><span class="p">(</span><span class="k">data</span><span class="p">[</span><span class="n">position</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">holder</span><span class="p">.</span><span class="n">itemView</span><span class="p">.</span><span class="n">setOnClickListener</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="p">(</span><span class="n">context</span> <span class="k">as</span> <span class="n">MainActivity</span><span class="p">).</span><span class="n">onEntryListClicked</span><span class="p">(</span><span class="k">it</span><span class="p">.</span><span class="n">tag</span><span class="p">.</span><span class="n">toString</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Which can then be called like this from our <code>Fragment</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Kotlin" data-lang="Kotlin"><span class="line"><span class="cl"><span class="n">pokemonListRecyclerView</span><span class="p">.</span><span class="n">adapter</span> <span class="p">=</span> 
</span></span><span class="line"><span class="cl"><span class="n">PokedexRecyclerAdapter</span><span class="p">(</span><span class="n">activity</span> <span class="k">as</span> <span class="n">MainActivity</span><span class="p">,</span> <span class="k">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                          <span class="p">{</span> <span class="n">elt</span> <span class="o">-&gt;</span> <span class="n">setUpSelectedPokemon</span><span class="p">(</span><span class="n">elt</span><span class="p">)</span> <span class="p">}</span>
</span></span></code></pre></div>]]></content:encoded></item><item><title>Tetrua - Part 1</title><link>https://sunbro.dev/posts/2020-03-18-tetrua-part-1/</link><pubDate>Wed, 18 Mar 2020 00:05:00 +0100</pubDate><guid>https://sunbro.dev/posts/2020-03-18-tetrua-part-1/</guid><description>Presenting Tetrua</description><content:encoded><![CDATA[<h2 id="grec">GREC</h2>
<p>The idea behind G Rapidement Envie de Coder (GREC - I Wanna Code Quickly)
is to take the concept of a 
<a href="https://en.wikipedia.org/wiki/Game_jam" target="_blank" ><strong>game jam</strong></a> / 
<a href="https://en.wikipedia.org/wiki/Hackathon" target="_blank" ><strong>hackathon</strong></a>
and apply it a short project so third year computer science students can use
it to learn a new concept or language. The project should be able to be
completed in a weekend or 48 hours.</p>
<h2 id="tetrua">Tetrua</h2>
<p>For this project, the end goal is to create a tetris clone using 
<a href="https://www.lua.org/about.html" target="_blank" ><strong>Lua</strong></a> +

<a href="https://love2d.org/" target="_blank" ><strong>LÖVE</strong></a>.</p>
<h3 id="graphics">Graphics</h3>
<p>LÖVE makes it very easy to display sprites and images to screen. As such
my first step was to draw the different blocks needed for the different

<a href="https://tetris.fandom.com/wiki/Tetromino" target="_blank" ><strong>tetrominos</strong></a>. I started off by drawing each tetrimino with

<a href="https://www.aseprite.org/" target="_blank" ><strong>Aseprite</strong></a>:</p>
<p>


<img src="/images/tetromino_i.png" alt="The &amp;ldquo;I&amp;rdquo; tetromino" loading="lazy" width="16"
    height="64" style="max-width: 100%; height: auto;" /></p>
<p>After thinking about it a bit more, I realized drawing each different color
block separately would be easier to deal with in-game and maybe a little more
memory-efficient in the long run, although that is not the priority.</p>
<p>


<img src="/images/block_i.png" alt="The &amp;ldquo;I&amp;rdquo; block" loading="lazy" width="16"
    height="16" style="max-width: 100%; height: auto;" /></p>
<p>Loading and displaying an image in Lua with LÖVE looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Lua" data-lang="Lua"><span class="line"><span class="cl"><span class="c1">-- Load the image to a variable</span>
</span></span><span class="line"><span class="cl"><span class="n">sprite</span> <span class="o">=</span> <span class="n">love.graphics</span><span class="p">.</span><span class="n">newImage</span><span class="p">(</span><span class="s2">&#34;path/to/image&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1">-- Draw `sprite` to screen at (150, 150)</span>
</span></span><span class="line"><span class="cl"><span class="n">love.graphics</span><span class="p">.</span><span class="n">draw</span><span class="p">(</span><span class="n">sprite</span><span class="p">,</span> <span class="mi">150</span><span class="p">,</span> <span class="mi">150</span><span class="p">)</span>
</span></span></code></pre></div><h2 id="next-time">Next time</h2>
<p>That&rsquo;s it for now, the next article will likely be about how the game board
works. I hope you enjoyed reading this, see you next time!</p>
]]></content:encoded></item><item><title>Introduction</title><link>https://sunbro.dev/posts/2020-02-16-introduction/</link><pubDate>Sun, 16 Feb 2020 20:44:00 +0100</pubDate><guid>https://sunbro.dev/posts/2020-02-16-introduction/</guid><description>An introduction to this blog</description><content:encoded><![CDATA[<h1 id="welcome-">Welcome !</h1>
<p>Hello and welcome to my blog ! My goal with this website is to write about
what I find interesting in computer science and to share what I learn this
year. I plan to write one post per month, but that might change over time
as I gradually have more and more on my plate.</p>
<p>Thank you for getting this far, and see you next time !</p>
]]></content:encoded></item></channel></rss>