<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Hyperlink Your Heart - pixelart</title><link href="https://blog.hyperlinkyourheart.com/" rel="alternate"></link><link href="https://blog.hyperlinkyourheart.com/feeds/tag.pixelart.atom.xml" rel="self"></link><id>https://blog.hyperlinkyourheart.com/</id><updated>2025-07-08T11:59:00+02:00</updated><subtitle>Until there's nothing left.</subtitle><entry><title>Coming Down</title><link href="https://blog.hyperlinkyourheart.com/coming-down.html" rel="alternate"></link><published>2025-07-08T11:59:00+02:00</published><updated>2025-07-08T11:59:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2025-07-08:/coming-down.html</id><summary type="html">&lt;p&gt;A pixel art portrait of a woman, loosely inspired by the Chemical Brothers&amp;#8217; song &amp;#8220;Where Do I&amp;nbsp;Begin&amp;#8221;.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/coming-down.html"&gt;&lt;img alt="A pixel art painting of a woman's face, close up, in green hues. There are stars in the background to her right and a hint of some in her eye." src="https://blog.hyperlinkyourheart.com/images/coming-down/ComingDown1_x2.png" title="Coming Down"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Something I&amp;#8217;ve had in my mind for a while is to do something based on the Chemical Brothers&amp;#8217; song &amp;#8220;Where Do I Begin&amp;#8221;, which I think captures well the feeling of coming down after a trip; the mix of awe and confusion and the tenuous connection to your sense of&amp;nbsp;self.&lt;/p&gt;
&lt;p&gt;So I set out to do that, intending it to feature a woman with a coffee cup, like in the song&amp;#8230; and somehow got diverted into this close-up portrait. I think I had planned something like &lt;a href="https://blog.hyperlinkyourheart.com/cosmic-eye.html"&gt;Cosmic Eye&lt;/a&gt;, where she would have a universe visible in her pupil, but she wasn&amp;#8217;t really at the necessary scale for that to&amp;nbsp;work.&lt;/p&gt;
&lt;p&gt;I further intended to animate the colours, and shift between different palettes in a sort of pulsing manner, but that wasn&amp;#8217;t working out the way I planned, so I abandoned&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;I guess the most notable feature of this piece is the dithering style, which is sort of rough and incorporates various shapes. I&amp;#8217;ve never tried this style&amp;nbsp;before.&lt;/p&gt;
&lt;p&gt;I might need to try this again and stick closer to my original&amp;nbsp;vision&amp;#8230;&lt;/p&gt;
&lt;h2&gt;Timelapse&lt;/h2&gt;
&lt;p&gt;I used the recorder feature of &lt;a href="https://github.com/Orama-Interactive/Pixelorama" title="Pixelorama (Github)"&gt;Pixelorama&lt;/a&gt; to capture this timelapse, in the mode that only captures the canvas. I like that the result does not hop around erratically like my previous timelapse, but it does get a bit hard to follow what is actually being worked on at some points when it gets into the finer details, especially the&amp;nbsp;anti-aliasing.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=XP-Zx64bAqU"&gt;&lt;img alt="Coming Down Timelapse" src="https://img.youtube.com/vi/XP-Zx64bAqU/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="Art"></category><category term="pixelart"></category><category term="portrait"></category><category term="music"></category><category term="psychedelia"></category></entry><entry><title>Lovely, Dark and Deep</title><link href="https://blog.hyperlinkyourheart.com/lovely.html" rel="alternate"></link><published>2025-06-14T18:28:00+02:00</published><updated>2025-06-14T18:28:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2025-06-14:/lovely.html</id><summary type="html">&lt;p&gt;Post-mortem and results for my Ludum Dare 57&amp;nbsp;entry.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://hyperlinkyourheart.itch.io/lovely-dark-and-deep" title="itch.io page for the game"&gt;&lt;img alt="Pixel art of a forest with a man on a bicycle in the foreground, and the text &amp;quot;Lovely, Dark and Deep&amp;quot;" src="https://blog.hyperlinkyourheart.com/images/lovely-dark-and-deep/cover_image.png" title="Lovely, Dark and Deep"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Back in April I took part in Ludum Dare 57, which had the theme &amp;#8220;Depths&amp;#8221;. As usual I was eager to take &lt;a href="https://github.com/khoulihan/digression" title="Digression repository on GitHub"&gt;Digression&lt;/a&gt; for a spin and see how much it had improved since its last outing for &lt;a href="https://hyperlinkyourheart.itch.io/out-of-gas" title="Out of Gas on itch.io"&gt;Ludum Dare 48&lt;/a&gt;, and this time I managed to come up with something that allowed me to do that. Coincidentally, the theme for &lt;span class="caps"&gt;LD48&lt;/span&gt; was almost the same (&amp;#8220;Deeper and Deeper&amp;#8221;), and I ended up making a somewhat similar game in some&amp;nbsp;respects!&lt;/p&gt;
&lt;h2&gt;The&amp;nbsp;Concept&lt;/h2&gt;
&lt;p&gt;The initial concept was one I&amp;#8217;ve had kicking around for a while, of a post-apocalyptic trading game with two phases to the gameplay - one where you travel between outposts by car, possibly having to engage in combat or other encounters, and another at outposts where you have to trade and maintain your car. I think of it as terrestrial &lt;a href="https://en.wikipedia.org/wiki/Escape_Velocity_(video_game)" title="Wikipedia entry for the game Escape Velocity"&gt;Escape Velocity&lt;/a&gt;, though the travel would undoubtedly be much simplified for a jam&amp;nbsp;game.&lt;/p&gt;
&lt;p&gt;Of course none of the elements of that idea are set in stone. I usually think of it as being set in a desert (the ol&amp;#8217; Mad Max influence I suppose), but in this case I wasn&amp;#8217;t sure if deserts &lt;em&gt;have&lt;/em&gt; depths? So that was out. I considered setting it in deep space instead (some sort of &lt;em&gt;non-terrestrial&lt;/em&gt; Escape Velocity, I suppose? What a notion), but that seemed too close to the &lt;a href="https://hyperlinkyourheart.itch.io/out-of-gas" title="Out of Gas on itch.io"&gt;game I made for Ludum Dare 48&lt;/a&gt; already. And so it became deep forest, and then the car became a bicycle because that seemed more&amp;nbsp;foresty.&lt;/p&gt;
&lt;p&gt;Most of the rest of the originally envisioned gameplay mechanics fell away as I tried to scope it to the 72 hours available. The travelling became just an opportunity for a bit of dialogue, the vehicle maintenance became a simple stat alongside others for the player, and the trading disappeared entirely. In an effort to introduce some gameplay beyond just engaging in dialogue, I added in a hand of randomly drawn cards at each location and a limited number of action points for their use. I think I had in mind the dice rolls in &lt;a href="https://citizensleeper.com/" title="Website of the Citizen Sleeper series of games"&gt;Citizen Sleeper&lt;/a&gt; when I came up with this, but I couldn&amp;#8217;t really remember how they worked in that&amp;nbsp;game.&lt;/p&gt;
&lt;p&gt;Considering it has been several months since the jam I don&amp;#8217;t think I could give you a blow by blow even if I wanted to, so I&amp;#8217;m just going to talk a bit about what worked and what&amp;nbsp;didn&amp;#8217;t.&lt;/p&gt;
&lt;h2&gt;What&amp;nbsp;Worked&lt;/h2&gt;
&lt;h3&gt;Digression&lt;/h3&gt;
&lt;p&gt;Digression worked really well for the most part. I think I encountered one bug, but I was able to work around it. I was able to churn out dialogue really quickly for the encounters and travel, and it was relatively easy to implement changes to the game state during dialogue as well (giving items and buffs and the like) - though that aspect of it could have been better, as I discuss&amp;nbsp;below.&lt;/p&gt;
&lt;h3&gt;Use of&amp;nbsp;Resources&lt;/h3&gt;
&lt;p&gt;I used &lt;code&gt;Resource&lt;/code&gt; types for all the items, buffs, curses, character classes etc. Although they were a bit of a mess and included some stuff that didn&amp;#8217;t end up getting used, it really paid off to work with resources right from the beginning. Often in the past I would implement something like the player&amp;#8217;s gun, for example, as just a scene or part of a scene, with the intention to rework it later to allow different guns defined by resources. And of course in a jam that never happens as time runs out and I get fatigued - so there ends up being only one gun, one pickup&amp;nbsp;etc.&lt;/p&gt;
&lt;p&gt;Probably the most obvious effect this had in this game is the character class selection. It doesn&amp;#8217;t add all that much, but I think it is a neat thing to have in a jam game and it gives the impression of&amp;nbsp;depth.&lt;/p&gt;
&lt;p&gt;So, big thumbs up to doing things the right way from the&amp;nbsp;beginning.&lt;/p&gt;
&lt;h3&gt;Audio&lt;/h3&gt;
&lt;p&gt;I used old reliable &lt;a href="https://lmms.io/" title="Website of the LMMS DAW"&gt;&lt;span class="caps"&gt;LMMS&lt;/span&gt;&lt;/a&gt; for the music this time around. Last time I tried some new tools and had a really bad time. I&amp;#8217;m really proud of what I made for this game, it had the exact spooky, mysterious quality I was going for. I don&amp;#8217;t think &lt;a href="https://www.beepbox.co" title="Beepbox - an online chiptune music tool"&gt;beepbox&lt;/a&gt; would have cut it this&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;The game didn&amp;#8217;t call for many sound effects, but the ones that are there, aside from the &lt;span class="caps"&gt;UI&lt;/span&gt;, are foley - always fun to do that and I think they work pretty&amp;nbsp;well.&lt;/p&gt;
&lt;h3&gt;Art&lt;/h3&gt;
&lt;p&gt;What can I say, I think I did a good job on the art. That&amp;#8217;s always been my strength anyway so big&amp;nbsp;woop.&lt;/p&gt;
&lt;p&gt;I am still using &lt;a href="https://github.com/Orama-Interactive/Pixelorama" title="Pixelorama on GitHub"&gt;Pixelorama&lt;/a&gt; and there are still a few things about it that I find grating, but I have gotten used to it enough that it doesn&amp;#8217;t get in my way. It was better suited to this game than my last one because most of the art was large background pieces rather than&amp;nbsp;tiles.&lt;/p&gt;
&lt;p&gt;Something that&amp;#8217;s kinda new is that I did lot of animation using tweens. Little things like the the back and forth motion of the bicycle and how it enters and exits the screen, and the distribution and flipping of the cards, were entirely done with tweens. They took only minutes to implement and I think they look great, and add so much to the aesthetic of the game. I only had to actually animate one thing by hand, the&amp;nbsp;pedalling.&lt;/p&gt;
&lt;h3&gt;The Humour,&amp;nbsp;apparently&lt;/h3&gt;
&lt;p&gt;That Sully, what a&amp;nbsp;card.&lt;/p&gt;
&lt;h2&gt;What&amp;nbsp;Didn&amp;#8217;t&lt;/h2&gt;
&lt;h3&gt;Digression&lt;/h3&gt;
&lt;p&gt;Though it certainly didn&amp;#8217;t let me down, I definitely noticed a few pain points in actually using it for a&amp;nbsp;game.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It was originally a main-screen editor, and at some point I decided it should be in the bottom dock - probably because Godot didn&amp;#8217;t provide an official way to add a main screen plugin and you had to sort of hack it in. However it requires a lot of space to use properly, and having it in the bottom dock was an impediment to that. I have moved it back to the main screen since the&amp;nbsp;jam.&lt;/li&gt;
&lt;li&gt;Having to manually manage the size of dialogue nodes was a hassle. I have since updated them to be resizeable width-wise, but to grow with the text length-wise. Much nicer to&amp;nbsp;use.&lt;/li&gt;
&lt;li&gt;Similarly, it was kind of a pain scrolling up and down a node when there was a long section of text. I have since partially implemented a mechanism to allow the dialogue node to be &amp;#8220;maximised&amp;#8221; when you want to focus on editing, and I will be doing the same for the choice&amp;nbsp;node.&lt;/li&gt;
&lt;li&gt;The lack of an open graphs list made it a bit awkward to move back and forth between graphs, as I had to find them in a scene or the filesystem every time. I have since added an open graphs list, as well as an anchors list for navigating around a&amp;nbsp;graph.&lt;/li&gt;
&lt;li&gt;The two different signals for dialogue and choice dialogue struck me as a little awkward in retrospect. I will be consolidating them I&amp;nbsp;think.&lt;/li&gt;
&lt;li&gt;There are a few problems with the variable management system. One is that they lacked defaults - I have added these since. Another is that the variables didn&amp;#8217;t mesh well with the overall game, i.e. game state and dialogue state felt like two separate things that I had to bridge. I&amp;#8217;m not sure how I am going to address that&amp;nbsp;yet.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Gameplay&lt;/h3&gt;
&lt;p&gt;The gameplay was pretty awful. I clearly do not really know how card games work. Limiting the player&amp;#8217;s actions to a random selection of cards just resulted in frustration, especially when it was not obvious that some actions required items, and when their use of the cards was also constrained by action&amp;nbsp;points.&lt;/p&gt;
&lt;p&gt;The stats generally degraded too slowly as well and there were unclear interdependencies between them - your health doesn&amp;#8217;t degrade until you exhaust your food or water stats&amp;nbsp;completely.&lt;/p&gt;
&lt;p&gt;The encounters were fun, I thought, but there were too few of them and they were too random - you would see the same ones over and over sometimes. Too many of them had disappointing outcomes, and if you didn&amp;#8217;t get the right cards there was nothing to&amp;nbsp;do.&lt;/p&gt;
&lt;p&gt;I think the random encounters worked a bit better in &lt;a href="https://hyperlinkyourheart.itch.io/out-of-gas" title="Out of Gas on itch.io"&gt;Out of Gas&lt;/a&gt; for two reasons: most encounters involved combat, so that is just inherently more exciting - and the fact that you were fleeing something, and could be killed, was slightly more compelling than a set of depleting&amp;nbsp;stats.&lt;/p&gt;
&lt;p&gt;Overall, the randomness just left the player with little sense of agency. I would have been better off dropping the gameplay altogether and just making it a short visual novel, with agency expressed only through dialogue choices. Though I&amp;#8217;m not sure I could write a compelling story for a visual novel in such a short timespan&amp;nbsp;either&amp;#8230;&lt;/p&gt;
&lt;h3&gt;Bugs&lt;/h3&gt;
&lt;p&gt;I introduced a bug at the last minute that prevented the game from ending when your health or vehicle state reached zero lol,&amp;nbsp;lmao.&lt;/p&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;p&gt;&lt;img alt="Results table - 257th overall, 600th in Fun, 256th in Innovation, 446th in Theme, 80th in Graphics, 49th in Audio, 48th in Humour, 70th in Mood" src="https://blog.hyperlinkyourheart.com/images/lovely-dark-and-deep/results.png" title="Not too bad. Could be better."&gt;&lt;/p&gt;
&lt;p&gt;Much better than my last two outings, and some good ratings in several categories, but definitely let down overall by the gameplay. I&amp;#8217;m a bit disappointed by the mood rating as I felt I nailed that, but it is a very subjective one of course - and it&amp;#8217;s still pretty&amp;nbsp;good!&lt;/p&gt;
&lt;p&gt;Some&amp;nbsp;notables:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;My highest ever rating, and placing, in humour (please&amp;nbsp;clap).&lt;/li&gt;
&lt;li&gt;Highest ever audio rating (by a hair), and&amp;nbsp;placing.&lt;/li&gt;
&lt;li&gt;First time being in the top 100 in four categories as a solo&amp;nbsp;dev.&lt;/li&gt;
&lt;li&gt;First time being in the top 50 in two categories. Third time being in the top 50 in any&amp;nbsp;category.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Second lowest&lt;/em&gt; rating in fun - only my Ludum Dare 38 entry, which was only the opening scene of an adventure game and had no gameplay, was&amp;nbsp;lower!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt="Graph of audio placings" src="https://blog.hyperlinkyourheart.com/images/lovely-dark-and-deep/audioplacings.png"&gt;
&lt;img alt="Graph of humour ratings" src="https://blog.hyperlinkyourheart.com/images/lovely-dark-and-deep/humourratings.png"&gt;&lt;/p&gt;
&lt;h2&gt;Post-Jam&lt;/h2&gt;
&lt;p&gt;Nah.&lt;/p&gt;
&lt;h2&gt;Future&amp;nbsp;Developments&lt;/h2&gt;
&lt;p&gt;I was inspired to work on some sweeping improvements to Digression and have made a lot of progress, but there is also a lot of stuff broken and partially completed now. I will post about the changes in more depth when they are&amp;nbsp;done.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of dialogue and choice nodes in Digression" src="https://blog.hyperlinkyourheart.com/images/lovely-dark-and-deep/digressioncurrentstate.png" title="An example of some of the changes I've made"&gt;&lt;/p&gt;
&lt;p&gt;I also created a set of placeholder graphics to use in future jams. I used the default Godot robot sprite in this game, but it is not ideal in some ways because everything ends up looking the same, and when you put in the actual art you have to undo any scaling that was done to make the placeholder the correct&amp;nbsp;size.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of the game in early development, with the Godot logo everywhere" src="https://blog.hyperlinkyourheart.com/images/lovely-dark-and-deep/placeholders.png" title="Looks like Godot is already here"&gt;&lt;/p&gt;</content><category term="Game Development"></category><category term="ludum-dare"></category><category term="godot"></category><category term="godot4"></category><category term="pixelart"></category><category term="music"></category></entry><entry><title>Big Lick</title><link href="https://blog.hyperlinkyourheart.com/big-lick.html" rel="alternate"></link><published>2025-06-12T15:36:00+02:00</published><updated>2025-06-12T15:36:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2025-06-12:/big-lick.html</id><summary type="html">&lt;p&gt;A pixel art painting I did of my brother-in-law and one of my parent&amp;#8217;s dogs. Also some chat about why I haven&amp;#8217;t done any art in&amp;nbsp;ages.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/big-lick.html"&gt;&lt;img alt="A pixel art painting of a reclining man being licked on the nose by a small dog." src="https://blog.hyperlinkyourheart.com/images/big-lick/BigLick06_x3.png" title="Big Lick"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Oh boy, it&amp;#8217;s been &lt;em&gt;a while&lt;/em&gt; since I posted any art! I think I was put off the whole endeavour back when NFTs were the big thing and a lot of artists I respected were showing their ass over them. I had also started a piece that was maybe a bit too complex for me, and I started to dread working on it, and to feel guilty about not working on it, and then I started thinking that art for its own sake was just a distraction from what I had actually set out to do, which was to make a videogame. I started putting a lot more time into developing my dialogue graph editor for &lt;a href="https://godotengine.org/" title="Godot Engine"&gt;Godot&lt;/a&gt; instead (since given the name &lt;a href="https://github.com/khoulihan/digression" title="Digression Dialogue Graph Editor (Github)"&gt;&amp;#8220;Digression&amp;#8221;&lt;/a&gt;), and a tiny bit into the mechanics of the game, and just didn&amp;#8217;t think about art for a&amp;nbsp;while.&lt;/p&gt;
&lt;p&gt;Since then of course, NFTs seem to have basically disappeared from the zeitgeist, their promises of vast riches and libertarian copyright enforcement for artists unfulfilled, and all the artists have been replaced by machines that can pull, on command, statistically likely representations of anything you can imagine out of the aggregate of all visual media on the Internet. As if it wasn&amp;#8217;t bad enough that a huge chunk of it was already owned by giant corporations, capital is now grinding up our culture into a meaningless, commodified slurry and feeding it back to us. The pretense of having the interests of artists at heart has been replaced by a naked, shameless grasping. And with governments falling over each other to attract &lt;span class="caps"&gt;AI&lt;/span&gt; investment, it seems unlikely that there is going to be any recourse for individual creators any time&amp;nbsp;soon.&lt;/p&gt;
&lt;p&gt;So I&amp;#8217;d like to say, then, that the reason I did this piece was that I&amp;#8217;m an obstinate luddite who refuses to accept that the age of human creativity is over, and that I had to do my part to help preserve it. But actually I just needed to do something for my sister&amp;#8217;s birthday, and it occurred to me that I&amp;#8217;d never done any pixel art for her even though she is someone who would probably appreciate it. And isn&amp;#8217;t that a fine, &lt;em&gt;human&lt;/em&gt; motivation for getting back into&amp;nbsp;art?&lt;/p&gt;
&lt;p&gt;She did appreciate it, btw. I&amp;#8217;m not sure she would have if I had &lt;em&gt;engineered her a prompt&lt;/em&gt;&amp;nbsp;instead.&lt;/p&gt;
&lt;h2&gt;Tools and&amp;nbsp;Process&lt;/h2&gt;
&lt;p&gt;I used to use &lt;a href="https://pyxeledit.com/" title="Pyxel Edit"&gt;Pyxel Edit&lt;/a&gt; for all my art, but it is proprietary and Windows only and I couldn&amp;#8217;t get it running in Wine since I switched to Fedora. So I have switched to &lt;a href="https://github.com/Orama-Interactive/Pixelorama" title="Pixelorama (Github)"&gt;Pixelorama&lt;/a&gt; instead, an open source pixel art paint program developed in Godot. There are a few things that Pyxel Edit did better, but Pixelorama is a very decent substitute. I like that you can put different tools on your left and right mouse buttons, though it tripped me up a lot initially. One thing I really miss is the ability to update a colour globally from the palette. It was great to be able to completely change direction with the colours without having to repaint anything. That was something I used to do quite often and at any stage of the process, sometimes even when a piece was otherwise finished. Maybe I will look into contributing to the project, since I am somewhat familiar with&amp;nbsp;Godot&amp;#8230;&lt;/p&gt;
&lt;p&gt;When I tried adding the reference image it just automatically put it under the canvas, which I wasn&amp;#8217;t expecting, but since it did I decided to just trace a rough outline of the figures for&amp;nbsp;expediency.&lt;/p&gt;
&lt;p&gt;Unusually for me I did a lot of anti-aliasing in this one, and I really liked how that turned out, especially on the face. More of that in the&amp;nbsp;future.&lt;/p&gt;
&lt;p&gt;Also unusually I did not pay much attention at all to how many colours I was using. There is relatively little dithering as a result, and what is there is mostly for texture rather than giving the appearance of additional colours. I usually like the challenge of keeping colour counts low, but it was nice to be more relaxed about it for a change - I ended up using 64, and it&amp;#8217;s not as if the resulting palette is general&amp;nbsp;purpose!&lt;/p&gt;
&lt;h2&gt;Timelapse&lt;/h2&gt;
&lt;p&gt;The timelapse for this one is a bit of a mess. My previous method of capturing them doesn&amp;#8217;t work in Wayland, and I overlooked a feature in Pixelorama that would have allowed me to evaluate the canvas without having to zoom in and out constantly. I&amp;#8217;ve since discovered that it has a recorder feature that can save a copy of the canvas after every change, so I will likely try that for my next piece and the timelapse should have a &lt;em&gt;very&lt;/em&gt; different&amp;nbsp;look&amp;#8230;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=FPiJwkzLr0U"&gt;&lt;img alt="Big Lick Timelapse" src="https://img.youtube.com/vi/FPiJwkzLr0U/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="Art"></category><category term="pixelart"></category><category term="portrait"></category><category term="dogs"></category><category term="nfts"></category><category term="politics"></category><category term="foss"></category><category term="capitalism"></category><category term="genai"></category></entry><entry><title>From Hell’s Heart</title><link href="https://blog.hyperlinkyourheart.com/from-hells-heart.html" rel="alternate"></link><published>2024-05-14T22:46:00+02:00</published><updated>2024-05-14T22:46:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2024-05-14:/from-hells-heart.html</id><summary type="html">&lt;p&gt;A post-mortem of my Ludum Dare 55 entry, From Hell&amp;#8217;s Heart, a twin-stick&amp;nbsp;shooter.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Demon character from my game bound in a circle of protection" src="https://blog.hyperlinkyourheart.com/images/from-hells-heart/my_boy_scaled.png" title="What have they done to my boy??"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hyperlinkyourheart.itch.io/from-hells-heart" title="From Hell's Heart Itch Page"&gt;From Hell&amp;#8217;s Heart&lt;/a&gt; is my entry for Ludum Dare 55, the first Ludum Dare I have participated in since I made &lt;a href="https://hyperlinkyourheart.itch.io/out-of-gas" title="Out of Gas Itch Page"&gt;Out of Gas&lt;/a&gt; for Ludum Dare 48 in&amp;nbsp;2021.&lt;/p&gt;
&lt;p&gt;I was not thrilled with it overall (and neither was anybody else - but we&amp;#8217;ll get to that), but it was good to get into working on actual gameplay programming again after several years of only working on tooling, and it has inspired me to do a lot more gamedev work&amp;nbsp;since.&lt;/p&gt;
&lt;h2&gt;The&amp;nbsp;Concept&lt;/h2&gt;
&lt;p&gt;I was quite disappointed by the theme. I had an idea for the theme &amp;#8220;It Spreads&amp;#8221;, which was one of the final round themes, that I was very invested in. I was going to make a zombie shooter where the weapons were all spreadables like jam and nutella and so on, and I had a lot of fun art and gameplay ideas for&amp;nbsp;that.&lt;/p&gt;
&lt;p&gt;So when the theme of &amp;#8220;Summoning&amp;#8221; was announced I was disappointed. But, the theme is rarely the one I would prefer, so I got to brainstorming and came up with the idea of &amp;#8220;reverse-Doom&amp;#8221;, which evolved into something not explicitly Doom related, but where you play as a demon fighting soldiers nonetheless. For a brief moment I was even considering calling it &amp;#8220;What if Doom but you&amp;#8217;re the&amp;nbsp;Demon&amp;#8221;.&lt;/p&gt;
&lt;p&gt;The thing I liked about this concept was that it allowed me to address the theme in two ways - you are a demon who has been summoned, and you can summon other demons to help you. However, the fact that it is perfectly playable and beatable without ever summoning your demon friends diminishes this&amp;nbsp;somewhat!&lt;/p&gt;
&lt;p&gt;One of my hopes for this jam was to try out my dialogue graph editor, &lt;a href="https://github.com/khoulihan/digression" title="Digression GitHub Page"&gt;Digression&lt;/a&gt;, in another game, and unfortunately there was no place for it with this concept. I used it heavily in &lt;a href="https://hyperlinkyourheart.itch.io/out-of-gas" title="Out of Gas Itch Page"&gt;Out of Gas&lt;/a&gt; and &lt;a href="https://hyperlinkyourheart.itch.io/gophers" title="Gophers Itch Page"&gt;Gophers&lt;/a&gt; in the past, but it has been fleshed out significantly since then and is ready to be put through its paces. Oh&amp;nbsp;well.&lt;/p&gt;
&lt;h2&gt;Art&lt;/h2&gt;
&lt;p&gt;I couldn&amp;#8217;t get Pyxel Edit to run on my new computer when setting up for the jam (it is Windows only, and I have run it using Wine in the past), so I decided to branch out and try &lt;a href="https://github.com/Orama-Interactive/Pixelorama" title="Pixelorama GitHub Page"&gt;Pixelorama&lt;/a&gt; - a pixel art editor built in Godot. Although my muscle memory from Pyxel edit tripped me up constantly in minor ways it was a good experience overall and I think I will continue using it going forward, as I always prefer open-source and native applications when they are available. The only thing I really found lacking was the way it handles the grid/tiles. There are no tools for quickly copying and manipulating tiles, and the grid is specified in the global settings instead of being per-file, even though one grid is unlikely to suit different files even in the same&amp;nbsp;project.&lt;/p&gt;
&lt;p&gt;I also had to adapt the way I managed spritesheets, as Pyxel edit allows you to define multiple animations in a single file, with the frames being tiles, while Pixelorama will only animate the entire file as a single unit. As such, character sprites are spread across multiple files each. In Godot this means swapping the sprite texture for each animation, but that didn&amp;#8217;t seem to cause any&amp;nbsp;problems.&lt;/p&gt;
&lt;p&gt;I made some big mistakes with the level art early on, initially designing it at twice the appropriate resolution for the characters I had in mind. I was able to take the basic design ideas and downscale them into the final wall and floor tiles easily enough, but it still wasted a lot of time. I designed them for an auto-tiling approach which I developed a while ago, where a tool script populates the floor tiles when you update the&amp;nbsp;walls.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The initial oversized art I designed. The walls are about 5 times the height of the characters." src="https://blog.hyperlinkyourheart.com/images/from-hells-heart/humongowalls.png" title="Humongous walls, and some variants of the player character."&gt;&lt;/p&gt;
&lt;p&gt;I based the character shapes roughly on the design I came up with for &lt;a href="https://hyperlinkyourheart.itch.io/guerrilla-gardening" title="Guerrilla Gardening Itch Page"&gt;Guerrilla Gardening&lt;/a&gt; for Ludum Dare 41, which is very round and fun, and I&amp;#8217;ve found works really well for shooter games. It also features outlines for the characters which means there&amp;#8217;s less risk of ending up with characters that don&amp;#8217;t show up well against the&amp;nbsp;background!&lt;/p&gt;
&lt;p&gt;I was quite pleased with the art overall, though when I designed the wall and floor variants for the opening &amp;#8220;cutscene&amp;#8221; I realised that the game is far too red overall, as the characters looked much better against the bluer&amp;nbsp;background!&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of part of the opening scene, with blue-grey crates against blue-grey walls and floor" src="https://blog.hyperlinkyourheart.com/images/from-hells-heart/crates.png" title="The crates had much less contrast though."&gt;&lt;/p&gt;
&lt;p&gt;I am determined next time I do a jam solo to not do full animations for each character or game element, and instead use the animation features of Godot to bounce, squash and spin things to bring them to life. This will give me much more time to create a variety of characters and objects, which I think would contribute more to a jam game than full run-cycle animations. The only place I used this kind of technique in this game was for the spinning and pulsing of the portal, and I think it was quite effective. People do some great things with this kind of animation and I am missing&amp;nbsp;out.&lt;/p&gt;
&lt;h2&gt;Music&lt;/h2&gt;
&lt;p&gt;Music is an element of jam games that I am always trying to find a new and better approach to, as it is something that I enjoy a lot but am not particularly skilled at. In the past I have used &lt;a href="https://www.beepbox.co" title="Beepbox"&gt;beepbox&lt;/a&gt;, &lt;a href="https://lmms.io/" title="LMMS Website"&gt;&lt;span class="caps"&gt;LMMS&lt;/span&gt;&lt;/a&gt; and &lt;a href="https://boscaceoil.net/" title="Bosca Ceoil Website"&gt;Bosca Ceoil&lt;/a&gt; with different degrees of&amp;nbsp;success.&lt;/p&gt;
&lt;p&gt;In the week prior to the jam I came across an application called &lt;a href="https://helio.fm/" title="Helio Website"&gt;Helio&lt;/a&gt; which I thought looked incredibly promising. It looked like it might be as easy to use as Bosca Ceoil but with a wider variety of possible instruments, so I was excited to try it&amp;nbsp;out.&lt;/p&gt;
&lt;p&gt;Another type of tool that I am always looking to bring into the fold is modular synth emulators. I have tried &lt;a href="https://vcvrack.com/" title="VCV Rack Website"&gt;&lt;span class="caps"&gt;VCV&lt;/span&gt; rack&lt;/a&gt; in the past but never managed to use it for a game, and I recently came across a fork of it called &lt;a href="https://cardinal.kx.studio/" title="Cardinal Website"&gt;Cardinal&lt;/a&gt; and had been practicing with that. I discovered that I could use Cardinal as a plugin for Helio and create instruments in it to control using Helio, so I planned to either do that or create a patch to generate all the music for the game, depending on what idea I was working on. The concept for From Hell&amp;#8217;s Heart didn&amp;#8217;t really seem to call for techno or ambient music, so I ended up trying the&amp;nbsp;latter.&lt;/p&gt;
&lt;p&gt;Unfortunately, things did not go smoothly at all with creating the music. I found Helio to be lacking in some essential features, and with a confusing menu system. It crashed constantly, forgetting instrument settings each time and sometimes changing the volume of notes or moving them around arbitrarily. I think the interface with Cardinal may have been responsible for some of this, and ultimately abandoned trying to use it for any instruments in favor of a selection of sound fonts. There was no way to preview the sound fonts in Helio, and I ended up previewing them on the command line using &lt;code&gt;fluidsynth&lt;/code&gt;, but not all of the ones I found that I liked worked when loaded into instruments in Helio. It was just a frustrating mess all&amp;nbsp;around.&lt;/p&gt;
&lt;p&gt;Most bafflingly in terms of missing features in Helio, I couldn&amp;#8217;t find a way of creating more than one pattern for an instrument, so I ended up having to use multiple tracks of the same instrument when I wanted a different&amp;nbsp;pattern.&lt;/p&gt;
&lt;p&gt;It also lacks a central mixer where effects can be applied. Instead you can add effects on a per-instrument basis. I tried to do this in Cardinal as well, but again abandoned that as time dragged on and the application kept&amp;nbsp;crashing.&lt;/p&gt;
&lt;p&gt;So overall it was a bit of a nightmare, took five precious hours, and the track ended up being overly repetitive, with just one melody repeated over and over with the only variation being different instruments coming in and out. I hated it when I was done, but it grew on me a bit when I put it in the game. It did kind of have the mood I was aiming&amp;nbsp;for.&lt;/p&gt;
&lt;p&gt;Every time I try to make music in Linux I feel like I am missing out on some brilliant workflow that ties a variety of different applications together with their different specialities, but I am just failing to grasp how it all works, and this time was no different. Back to &lt;span class="caps"&gt;LMMS&lt;/span&gt; next time I&amp;nbsp;think&amp;#8230;&lt;/p&gt;
&lt;h2&gt;Sound&amp;nbsp;Effects&lt;/h2&gt;
&lt;p&gt;Somewhere that I did get to use Cardinal was for the sound effects! I mostly used the Audible Instruments synth modules with a variety of different setting, and used &lt;a href="https://www.audacityteam.org/" title="Audacity Website"&gt;Audacity&lt;/a&gt; to record different notes being played for variety. Some of the results I was really pleased with (the demon snarls), others much less so (the enemy voices, which sounded like robots saying random words), but overall it worked pretty well. I would have preferred to do some foley stuff but there wasn&amp;#8217;t time, and it was a step up from &lt;a href="http://www.drpetter.se/project_sfxr.html" title="SFXR Website"&gt;&lt;span class="caps"&gt;SFXR&lt;/span&gt;&lt;/a&gt; at&amp;nbsp;least.&lt;/p&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;p&gt;Since my long-time project, &lt;a href="https://gamejolt.com/games/just-a-robot/185852" title="Just a Robot GameJolt Page"&gt;Just a Robot&lt;/a&gt;, is a shooter, I had a fair bit of base code to plunder for this jam. I don&amp;#8217;t think I did or learned anything particularly interesting this time around, but the base code did include a technique for showing a character silhouette when they are obscured by a wall which is interesting enough, and some automatic configuration of floor and mask tilemaps to allow rooms to be banged out quickly with little possibility of&amp;nbsp;error.&lt;/p&gt;
&lt;p&gt;The trick to the silhouettes is to create a mask of the parts of the walls that should obscure game entities using a &lt;code&gt;BackBufferCopy&lt;/code&gt; node, and then check that mask in a shader on any sprite that should be obscured. Objects in the game do not need to be children of the &lt;code&gt;TileMap&lt;/code&gt;, and in fact there is a different &lt;code&gt;TileMap&lt;/code&gt; for walls and&amp;nbsp;floors.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of Godot editor scene tree showing mask TileMap and BackBufferCopy" src="https://blog.hyperlinkyourheart.com/images/from-hells-heart/backbuffer.png" title="Yes I used nodes as &amp;quot;folders&amp;quot; here, bad very bad."&gt;&lt;/p&gt;
&lt;p&gt;The mask &lt;code&gt;TileMap&lt;/code&gt; is populated automatically in the editor using a script like&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;tool&lt;/span&gt;
&lt;span class="k"&gt;extends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TileMap&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;copy_map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;NodePath&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;copy_from_layer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;copy_to_layer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;refresh_frequency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_copy_map_node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copy_map&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_editor_hint&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;_tool_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_tool_process&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;copy_map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;refresh_frequency&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;_copy_map_node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copy_map&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;current_ticks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_ticks_msec&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;current_ticks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;refresh_frequency&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;current_ticks&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;_copy_map&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_copy_map&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cells&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_copy_map_node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_used_cells&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copy_from_layer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copy_to_layer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_copy_map_node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_cell_source_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copy_from_layer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;copy_to_layer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;_copy_map_node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_cell_source_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copy_from_layer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;_copy_map_node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_cell_atlas_coords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copy_from_layer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;_copy_map_node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_cell_alternative_tile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copy_from_layer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fix_invalid_tiles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The mask tileset just has 100% red everywhere that should be obscured, so the shader just checks for red in the screen texture and displays a grey colour instead of the sprite&amp;#8217;s texture anywhere it finds it, leaving the alpha&amp;nbsp;intact:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;shader_type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;canvas_item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;uniform&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hide_when_occluded&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;uniform&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sampler2D&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SCREEN_TEXTURE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hint_screen_texture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;filter_linear_mipmap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fragment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;vec4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mask&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;textureLod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SCREEN_TEXTURE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SCREEN_UV&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hide_when_occluded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;COLOR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;COLOR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rgb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;vec3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m m-Double"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It turned out that people really hated the tight corridors and enemies being obscured though, so I probably won&amp;#8217;t be using this technique&amp;nbsp;again!&lt;/p&gt;
&lt;p&gt;A similar script to the one that populates the mask also populates a &lt;code&gt;TileMap&lt;/code&gt; with floor tiles based on the wall tiles. The floor tiles have a different size than the wall tiles however, so it is a bit longer and more involved. I think I would prefer to just put floor and wall tiles on different layers of the same &lt;code&gt;TileMap&lt;/code&gt; in the future, or as &lt;code&gt;TileMapLayers&lt;/code&gt; or whatever is being introduced in Godot&amp;nbsp;4.3&amp;#8230;&lt;/p&gt;
&lt;p&gt;Another neat thing I did in the editor was to have spawn points for portals and enemies draw a line to the thing they are associated with, or an obvious warning if they are not configured correctly. This helped me ensure that everything was set up properly when rushing through the room designs in the last few hours of the jam! I am trying to get into the habit of adding this sort of tooling to everything that might benefit from&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of Godot editor showing lines from spawn points to associated entities" src="https://blog.hyperlinkyourheart.com/images/from-hells-heart/spawnlines.png" title="Lines, lines, everywhere are lines"&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;tool&lt;/span&gt;
&lt;span class="k"&gt;extends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Marker2D&lt;/span&gt;


&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GameRoomSpawnPoint&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_editor_hint&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;_tool_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_tool_process&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;queue_redraw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_draw&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_editor_hint&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;null&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;_draw_to_destination&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;_draw_warning&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_draw_warning&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;draw_circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb nb-Type"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;15.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_draw_to_destination&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;draw_circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb nb-Type"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;15.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GREEN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;draw_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb nb-Type"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;global_position&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb nb-Type"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GREEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I also took from the base code a node-based state machine for enemy &lt;span class="caps"&gt;AI&lt;/span&gt;. This turned out to be a bit confusing and inflexible, and when I tried to introduce some new behaviour on the final day I ended up making the game crash constantly, and had to roll back. I&amp;#8217;m still unclear on exactly what went wrong there - I was getting null references due to the summoned allies despawning, even with null checks before referencing them. It was probably really obvious but I was exhausted by then. In any case there were other problems with the state machine I developed and I have started investigating the Godot plugin &lt;a href="https://github.com/bitbrain/beehave" title="Beehave GitHub Page"&gt;Beehave&lt;/a&gt; as an alternative for the&amp;nbsp;future.&lt;/p&gt;
&lt;p&gt;Something that did not work very well was the enemy navigation and avoidance. I completely misunderstood how the avoidance system was supposed to be used, so it was actually not in play at all. In experiments I&amp;#8217;ve done since the jam I got it working to some extent, but it seems like it does not work very well anyway, with agents just grinding to a halt in many circumstances even after avoiding an obstacle! The navigation itself would have worked much better with one small settings change of &lt;code&gt;path_postprocessing&lt;/code&gt; in the &lt;code&gt;NavigationAgent2D&lt;/code&gt; to &amp;#8220;edgecentered&amp;#8221;, as I discovered later. As I had it for the jam, navigation agents are always getting stuck on wall&amp;nbsp;corners&amp;#8230;&lt;/p&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;p&gt;My game got lots of nice commments, and also a lot of complaints about out-of-bounds glitches, enemies being obscured by the walls, and being too&amp;nbsp;easy.&lt;/p&gt;
&lt;p&gt;I was uninspired by the theme this time around and my skills were somewhat rusty in every area, and the game was generic and buggy as a result, so I was unsurprised by the negative comments. I did think it looked good and was reasonably juicy and sounded alright. I wasn&amp;#8217;t expecting great overall ratings, but I did think it would do ok in the graphics category at least. However, the ratings were quite bad across the board, at least compared to previous&amp;nbsp;jams!&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Category&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Rating&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Placing&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Percentile&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Overall&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.571&lt;/td&gt;
&lt;td style="text-align: right;"&gt;574&lt;/td&gt;
&lt;td style="text-align: right;"&gt;65th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Fun&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.63&lt;/td&gt;
&lt;td style="text-align: right;"&gt;418&lt;/td&gt;
&lt;td style="text-align: right;"&gt;75th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Theme&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.413&lt;/td&gt;
&lt;td style="text-align: right;"&gt;792&lt;/td&gt;
&lt;td style="text-align: right;"&gt;52nd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Innovation&lt;/td&gt;
&lt;td style="text-align: right;"&gt;2.739&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1080&lt;/td&gt;
&lt;td style="text-align: right;"&gt;35th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Humor&lt;/td&gt;
&lt;td style="text-align: right;"&gt;2.609&lt;/td&gt;
&lt;td style="text-align: right;"&gt;823&lt;/td&gt;
&lt;td style="text-align: right;"&gt;50th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Graphics&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.935&lt;/td&gt;
&lt;td style="text-align: right;"&gt;428&lt;/td&gt;
&lt;td style="text-align: right;"&gt;74th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Audio&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.619&lt;/td&gt;
&lt;td style="text-align: right;"&gt;343&lt;/td&gt;
&lt;td style="text-align: right;"&gt;79th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Mood&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.457&lt;/td&gt;
&lt;td style="text-align: right;"&gt;686&lt;/td&gt;
&lt;td style="text-align: right;"&gt;59th&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This game did worse in almost every category in percentile terms than my Ludum Dare 38 entry which I didn&amp;#8217;t even complete - it was just an opening scene with a short dialog and no gameplay. Quite a drop from my &amp;#8220;Gophers&amp;#8221;&amp;nbsp;peak!&lt;/p&gt;
&lt;p&gt;&lt;img alt="Ratings Graph" src="https://blog.hyperlinkyourheart.com/images/from-hells-heart/ratingsgraph.png"&gt;
&lt;img alt="Percentile Graph" src="https://blog.hyperlinkyourheart.com/images/from-hells-heart/percentilegraph.png"&gt;&lt;/p&gt;
&lt;h2&gt;Post-jam and&amp;nbsp;Take-away&lt;/h2&gt;
&lt;p&gt;I won&amp;#8217;t make my usual promise to work on a post-jam version of this game, both because it&amp;#8217;s not interesting enough to be worth it, and because I never keep that promise&amp;nbsp;anyway!&lt;/p&gt;
&lt;p&gt;Instead I have been inspired to start working on &lt;a href="https://gamejolt.com/games/just-a-robot/185852" title="Just a Robot GameJolt Page"&gt;Just a Robot&lt;/a&gt; again since the jam, trying to get combat and enemy behaviour working the way I have always envisioned them, to see if it would actually be fun. The idea is to make it a cover-based shooter where the enemies abilities are close to the player&amp;#8217;s, more or less, and combat feels weighty and dangerous in a way that is distinct from bullet-hell&amp;nbsp;shooters.&lt;/p&gt;
&lt;p&gt;I successfully implemented a cover system for the player, but when I went to enable the enemies to use it and switch to using Beehave for their &lt;span class="caps"&gt;AI&lt;/span&gt; I quickly discovered that the way I had built them so far was too centralised and inheritance based, so after watching a few tutorials and considering things a bit I decided to start again mostly from scratch with a more composition-based approach. This is working really well for the player so far and I&amp;#8217;m nearly back at the same point as I was&amp;nbsp;previously.&lt;/p&gt;
&lt;p&gt;I also thought about and experimented with tiling approaches a bit, creating both a very small scale autotiling tileset with multiple terrains, and a mockup of a more organic looking tileset with a wide variety of designs, angled walls and floor sections and the like. I am tired of creating boxy, uninteresting levels. I was initially inspired in my gamedev journey by the art and design of Hyper Light Drifter, and I want to get back to achieving something of that look and sense of verticality - maybe not in jam games, but in Just a&amp;nbsp;Robot.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Complex tiles mockup" src="https://blog.hyperlinkyourheart.com/images/from-hells-heart/HLD-like Room Experiment.png" title="Too bright for this game, but moving in the right direction I think"&gt;&lt;/p&gt;
&lt;p&gt;I started on a greybox version of the above to actually use in designing the game, but it&amp;#8217;s not quite finished&amp;nbsp;yet.&lt;/p&gt;</content><category term="Game Development"></category><category term="godot"></category><category term="godot4"></category><category term="gdscript"></category><category term="ludum-dare"></category><category term="music"></category><category term="pixelart"></category></entry><entry><title>Out of Road</title><link href="https://blog.hyperlinkyourheart.com/out-of-road.html" rel="alternate"></link><published>2021-08-11T17:10:00+02:00</published><updated>2021-08-11T17:10:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2021-08-11:/out-of-road.html</id><summary type="html">&lt;p&gt;Just a fancy car that took a wrong&amp;nbsp;turn.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/out-of-road.html"&gt;&lt;img alt="Out of Road" src="https://blog.hyperlinkyourheart.com/images/out-of-road/Denial02.png" title="Out of Road"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t remember where I got the inspiration for this one. I guess I&amp;#8217;ve been thinking a lot about climate change recently, what with the great crypto/&lt;span class="caps"&gt;NFT&lt;/span&gt; debates earlier in the year and recent extreme weather events and wildfires. It seems particularly timely given the recent &lt;a href="https://arstechnica.com/science/2021/08/new-ipcc-climate-report-is-the-clearest-guidebook-for-selecting-a-future/" title="IPCC report"&gt;&lt;span class="caps"&gt;IPCC&lt;/span&gt; report&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In terms of technique, I used a 3D render as a base, which is something I&amp;#8217;ve done before, but this time I used somebody else&amp;#8217;s &lt;span class="caps"&gt;CC&lt;/span&gt; licensed model because cars are kinda&amp;nbsp;complex.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://skfb.ly/6W8x8"&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Ford Mustang Mach 1&amp;#8221;&lt;/a&gt; by BaldGuyMartin is licensed under &lt;a href="http://creativecommons.org/licenses/by/4.0/"&gt;Creative Commons Attribution&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Timelapse&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=21VjoNfGcDc"&gt;&lt;img alt="Out of Road" src="https://img.youtube.com/vi/21VjoNfGcDc/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="Art"></category><category term="pixelart"></category><category term="politics"></category><category term="environmentalism"></category></entry><entry><title>Recent Art &amp; Portfolio</title><link href="https://blog.hyperlinkyourheart.com/recent-art.html" rel="alternate"></link><published>2021-06-08T00:20:00+02:00</published><updated>2021-06-08T00:20:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2021-06-08:/recent-art.html</id><summary type="html">&lt;p&gt;Belated art updates from the last 7&amp;nbsp;months.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Once again I have become neglectful of updating this blog with my artwork, so let&amp;#8217;s do a roundup of the last uh&amp;#8230; &lt;em&gt;7 months?!?!&lt;/em&gt; and maybe I&amp;#8217;ll try to get it back on track from here on. Though I do have a nice &lt;a href="https://portfolio.hyperlinkyourheart.com" title="Portfolio"&gt;portfolio site&lt;/a&gt; now that I have been keeping up to date, so if you really like my art you could be following that as well. More on that&amp;nbsp;below.&lt;/p&gt;
&lt;h2&gt;Socialist Revolutionaries Past &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Future&lt;/h2&gt;
&lt;p&gt;Last October I was trying to get back into the development of my game &lt;a href="https://gamejolt.com/games/just-a-robot/185852" title="Just a Robot"&gt;Just a Robot&lt;/a&gt;, and started as I always do by completely re-imagining its entire look. In this case I was inspired by the look of Soviet propaganda and Anarchist&amp;nbsp;woodcuts.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/rise.html"&gt;&lt;img alt="Robot Propaganda" src="https://blog.hyperlinkyourheart.com/images/recent-art/RobotPropaganda03_x1.png" title="Rise"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I followed that up in December with this tribute to the luxurious moustache of Irish revolutionary socialist James&amp;nbsp;Connolly.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/james-connolly.html"&gt;&lt;img alt="James Connolly" src="https://blog.hyperlinkyourheart.com/images/recent-art/JamesConnolly_x1.png" title="The Irish people will only be free, when they own everything from the plough to the stars"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Spaaaace&lt;/h2&gt;
&lt;p&gt;For the New Year I committed myself to working on more space and sci-fi themed stuff. I started with this depiction of a space station roughly based on the &lt;span class="caps"&gt;ISS&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/space-station.html"&gt;&lt;img alt="Space station" src="https://blog.hyperlinkyourheart.com/images/recent-art/SpaceStation_x1.png" title="Space Station"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also in January, a spaceship approaching Mercury, with some tricky&amp;nbsp;perspective.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/mercury-approach.html"&gt;&lt;img alt="Mercury approach" src="https://blog.hyperlinkyourheart.com/images/recent-art/MercuryApproach_169_x1.png" title="Getting warm"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In February I did another piece loosely inspired by Soviet propaganda, and a theme that seemed to be somewhat controversial - the idea of billionaires fleeing into space and leaving the rest of us to our fates. Some people took that as a literal prediction of future events, but I think of it in more allegorical terms - capital is ruining the natural and social environment without any sense of responsibility to the rest of us, while its masters can escape the consequences of their actions without &lt;em&gt;literally leaving the planet&lt;/em&gt; - depicting them doing so is just a good way of describing the situation, in my&amp;nbsp;opinion.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/flight.html"&gt;&lt;img alt="Flight of the Billionaires" src="https://blog.hyperlinkyourheart.com/images/recent-art/Flight02_x1.png" title="Pretty rockets though..."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In March I brought it back to Earth and explored the same theme from another perspective, more or&amp;nbsp;less.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/left-behind.html"&gt;&lt;img alt="Left Behind" src="https://blog.hyperlinkyourheart.com/images/recent-art/LeftBehind_x1.png" title="So long..."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I started a piece in April for Cosmonautics day, but I didn&amp;#8217;t get it finished until June - the capsule and final stage of Vostok 1 in orbit. I did a &lt;a href="https://blog.hyperlinkyourheart.com/out-of-gas-post-mortem.html" title="Out of Gas"&gt;game jam&lt;/a&gt; and an &lt;a href="https://twitter.com/http_your_heart/status/1393938661251690500" title="Diamond hill"&gt;oil painting&lt;/a&gt; in the meantime&amp;nbsp;though!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/vostok1.html"&gt;&lt;img alt="Vostok 1" src="https://blog.hyperlinkyourheart.com/images/recent-art/Vostok1_Final_x1.png" title="Vostok 1"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And that pretty much brings us up to&amp;nbsp;date!&lt;/p&gt;
&lt;h2&gt;Portfolio&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com" title="Portfolio"&gt;My portfolio site&lt;/a&gt;, which went live in July 2020, is another statically-generated site based on &lt;a href="https://blog.getpelican.com/" title="Pelican"&gt;Pelican&lt;/a&gt;, but focused on image galleries instead of blog entries (using the standard gallery plugin). I wanted a central place to put my art that wasn&amp;#8217;t a social media platform, and that would display it optimally. I&amp;#8217;ve linked to it a few times from here despite never actually mentioning&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;It is inspired by the ideas of Matej Jan on &lt;a href="https://medium.com/retronator-magazine/art-and-the-internet-a3281ba60a88" title="Art and the Internet"&gt;displaying art on the internet&lt;/a&gt;, and attempts to display my pieces at the best integer scaling to fit in the browser window, on a background with appropriate contrast, and with no&amp;nbsp;distractions.&lt;/p&gt;
&lt;p&gt;Of course, I also wanted to keep it as small and responsive as possible, so it does this with about 3kB of javascript, 11kB of &lt;span class="caps"&gt;CSS&lt;/span&gt;, and a selection of minimal &lt;span class="caps"&gt;SVG&lt;/span&gt; backgrounds. Because all the art is pixel art, transferring it at 1x resolution and resizing it in the browser (as discussed in &lt;a href="https://blog.hyperlinkyourheart.com/energy-usage-update.html" title="Energy Usage Update"&gt;recent&lt;/a&gt; &lt;a href="https://blog.hyperlinkyourheart.com/image-optimisation.html" title="Image Optimisation"&gt;posts&lt;/a&gt;) keeps things extremely compact, with the entire portfolio currently only amounting to 390kB. The portfolio does a lot better job of displaying the art than this blog does though, here the images are just resized to max width without attempting an integer&amp;nbsp;scaling.&lt;/p&gt;
&lt;p&gt;I think it looks real nice and that my art looks real nice on it, so &lt;a href="https://portfolio.hyperlinkyourheart.com" title="Portfolio"&gt;go check it&amp;nbsp;out!&lt;/a&gt;&lt;/p&gt;</content><category term="Art"></category><category term="pixelart"></category></entry><entry><title>Energy Usage Update</title><link href="https://blog.hyperlinkyourheart.com/energy-usage-update.html" rel="alternate"></link><published>2021-05-27T13:20:00+02:00</published><updated>2025-06-12T15:23:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2021-05-27:/energy-usage-update.html</id><summary type="html">&lt;p&gt;An update on the energy efficiency of this&amp;nbsp;blog.&lt;/p&gt;</summary><content type="html">&lt;p&gt;When I &lt;a href="https://blog.hyperlinkyourheart.com/remember-blogs.html"&gt;started this blog&lt;/a&gt;, one of my &lt;a href="https://blog.hyperlinkyourheart.com/embedding-svgs.html"&gt;goals&lt;/a&gt; was for it to be lean and efficient, both to improve the reader&amp;#8217;s experience and to reduce the power usage involved in serving&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been planning recently to write a post on a related topic - the energy efficiency of the Python language and how using it as the backend or &lt;span class="caps"&gt;API&lt;/span&gt; of a more dynamic website would fit with those same goals. In preparation for that, I thought to check in on this blog and whether it is still as lean as it was back when I was figuring out how to embed the &lt;span class="caps"&gt;SVG&lt;/span&gt; icons in&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;Unfortunately, it seems that it is not. Unlike one of my inspirations, &lt;a href="https://solar.lowtechmagazine.com/2018/09/how-to-build-a-lowtech-website.html"&gt;low-tech magazine&amp;#8217;s solar powered website&lt;/a&gt;, I never found a solution for reducing the size of image files. For my posts about &lt;span class="caps"&gt;TV&lt;/span&gt; shows and movies I use fairly low quality JPEGs. But for my art and game dev posts I have been unwilling to compromise, and, frankly, a bit lazy, and have just been throwing large PNGs and GIFs into my posts without thinking about their&amp;nbsp;size.&lt;/p&gt;
&lt;p&gt;As a result, loading the index of this site now transfers 1.&lt;span class="caps"&gt;7MB&lt;/span&gt; if nothing is already cached. The text content and &lt;span class="caps"&gt;CSS&lt;/span&gt; are in the tens of kilobytes, with the rest being images. This is comparable to the initial load of many corporate news sites and large blogs with all their tracking javascript and ads blocked - an improvement over the norm perhaps, since I&amp;#8217;m not doing any of the tracking or advertising that have become such a burden on the web, but not particularly notable. This site is now only in the &lt;a href="https://www.websitecarbon.com/website/blog-hyperlinkyourheart-com/"&gt;57th percentile according to websitecarbon.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For pixel art, one solution does present itself immediately. For my &lt;a href="https://portfolio.hyperlinkyourheart.com"&gt;portfolio site&lt;/a&gt;, all of the artwork is sent to the browser at 1x resolution and resized there by an integer factor by a small amount of javascript, and perhaps the same thing could be achieved with css. The index of that site is under 400kB despite including all of my artwork, and does not require specially resized image thumbnails or anything like that. I could do the same thing here instead of throwing manually resized art into&amp;nbsp;posts.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m less sure what to do about screenshots and screencaps. The solution used by low-tech magazine doesn&amp;#8217;t really work for me, I think it compromises the readability of the images too much and doesn&amp;#8217;t fit this site&amp;#8217;s aesthetic. I tried a number of different techniques for vectorising, posterising and dithering screencaps from &lt;span class="caps"&gt;TV&lt;/span&gt; shows and movies to reduce the number of colours, but they didn&amp;#8217;t result in significant savings. On the other hand, they did actually look kind of cool and&amp;nbsp;stylised!&lt;/p&gt;
&lt;p&gt;&lt;img alt="Vectorised Beth Harmon" src="https://blog.hyperlinkyourheart.com/images/energy-usage-update/parkchesscrowd_vector.jpg" title="Vectorised Beth Harmon"&gt;&lt;/p&gt;
&lt;p&gt;Something I should probably try is scaling such images down significantly and then back up to the required display size in &lt;span class="caps"&gt;CSS&lt;/span&gt;. Obviously this will degrade the quality, but it might be an acceptable&amp;nbsp;trade-off.&lt;/p&gt;
&lt;p&gt;Screenshots of things like a text-editor or &lt;span class="caps"&gt;IDE&lt;/span&gt; are even more problematic - if the quality is degraded there they are probably not useful. I will probably just have to try to keep that kind of thing to a minimum, and use tighter crops where&amp;nbsp;necessary.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s easy to become complacent about efficiency when computers are so powerful that a few tens or hundreds of kilobytes don&amp;#8217;t seem to cause them any strain, but when you have that mindset they can quickly add up to quite a significant waste of time and power. I think this is well demonstrated by &lt;a href="https://daringfireball.net/linked/2018/05/27/usa-today-gdpr"&gt;&lt;span class="caps"&gt;USA&lt;/span&gt; Today&amp;#8217;s pissy response to the &lt;span class="caps"&gt;GDPR&lt;/span&gt;&lt;/a&gt;, where instead of the usual 5.&lt;span class="caps"&gt;2MB&lt;/span&gt; bloated garbage site, readers from the &lt;span class="caps"&gt;EU&lt;/span&gt; were served a lean, content focused site that loaded almost instantly and didn&amp;#8217;t track&amp;nbsp;them.&lt;/p&gt;
&lt;p&gt;Nothing I do is going to have the kind of impact that a site like &lt;span class="caps"&gt;USA&lt;/span&gt; Today improving their efficiency would have, purely because of the scale of the traffic involved, but I still want to try to do&amp;nbsp;better.&lt;/p&gt;</content><category term="Meta"></category><category term="indieweb"></category><category term="blogging"></category><category term="pixelart"></category></entry><entry><title>Ludum Dare 48 Results</title><link href="https://blog.hyperlinkyourheart.com/out-of-gas-results.html" rel="alternate"></link><published>2021-05-27T11:11:00+02:00</published><updated>2021-05-27T11:11:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2021-05-27:/out-of-gas-results.html</id><summary type="html">&lt;p&gt;Results for Ludum Dare 48 are out, and I did less well than last&amp;nbsp;time!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Ludum Dare 48 results are out a while now, but I forgot to post about them. I did not do as well as last time, but since my &lt;a href="https://blog.hyperlinkyourheart.com/gophers-results.html"&gt;results for Gophers&lt;/a&gt; were exceptional for me, that was probably to be expected. This time I placed 433rd overall, with the stand-out category being graphics, where I just about broke the top 100, at 99th&amp;nbsp;place.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Category&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Rating&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Placing&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Percentile&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Overall&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.81&lt;/td&gt;
&lt;td style="text-align: right;"&gt;433&lt;/td&gt;
&lt;td style="text-align: right;"&gt;84th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Fun&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.259&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1044&lt;/td&gt;
&lt;td style="text-align: right;"&gt;61st&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Theme&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.672&lt;/td&gt;
&lt;td style="text-align: right;"&gt;873&lt;/td&gt;
&lt;td style="text-align: right;"&gt;67th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Innovation&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.345&lt;/td&gt;
&lt;td style="text-align: right;"&gt;754&lt;/td&gt;
&lt;td style="text-align: right;"&gt;72nd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Humor&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.596&lt;/td&gt;
&lt;td style="text-align: right;"&gt;277&lt;/td&gt;
&lt;td style="text-align: right;"&gt;89th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Graphics&lt;/td&gt;
&lt;td style="text-align: right;"&gt;4.466&lt;/td&gt;
&lt;td style="text-align: right;"&gt;99&lt;/td&gt;
&lt;td style="text-align: right;"&gt;96th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Audio&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.621&lt;/td&gt;
&lt;td style="text-align: right;"&gt;526&lt;/td&gt;
&lt;td style="text-align: right;"&gt;80th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Mood&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.846&lt;/td&gt;
&lt;td style="text-align: right;"&gt;460&lt;/td&gt;
&lt;td style="text-align: right;"&gt;83rd&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Graphs&lt;/h2&gt;
&lt;p&gt;A couple of graphs demonstrating my &lt;em&gt;trends&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Ratings Graph" src="https://blog.hyperlinkyourheart.com/images/out-of-gas-results/overall_graphics_ratings.png"&gt;
&lt;img alt="Placings Graph" src="https://blog.hyperlinkyourheart.com/images/out-of-gas-results/placings.png"&gt;&lt;/p&gt;
&lt;p&gt;Still haven&amp;#8217;t surpassed that Rattendorf peak, &lt;em&gt;sigh&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;More Out of&amp;nbsp;Gas&lt;/h2&gt;
&lt;p&gt;I am committed to working on a post-jam release of this game, as I think with a few tweaks and a bit more content it could be something quite special (more special than the ratings above suggest&amp;nbsp;anyway!)&lt;/p&gt;
&lt;p&gt;I will be posting here with development updates, and also over on the &lt;a href="https://hyperlinkyourheart.itch.io/out-of-gas"&gt;itch.io&lt;/a&gt; page, where you can also still play the jam version for&amp;nbsp;now.&lt;/p&gt;</content><category term="Game Development"></category><category term="ludum-dare"></category><category term="sci-fi"></category><category term="music"></category><category term="pixelart"></category><category term="godot"></category></entry><entry><title>Out of Gas</title><link href="https://blog.hyperlinkyourheart.com/out-of-gas-post-mortem.html" rel="alternate"></link><published>2021-05-04T10:41:00+02:00</published><updated>2021-05-29T22:52:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2021-05-04:/out-of-gas-post-mortem.html</id><summary type="html">&lt;p&gt;A post-mortem of my Ludum Dare 48 entry, Out of Gas - a space-road-trip themed narrative/clicker game about a couple of outlaws fleeing their cryptocurrency&amp;nbsp;debts.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://hyperlinkyourheart.itch.io/out-of-gas"&gt;&lt;img alt="Out of Gas" src="https://blog.hyperlinkyourheart.com/images/out-of-gas-post-mortem/OOG_itch_banner.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hyperlinkyourheart.itch.io/out-of-gas" title="Out of Gas"&gt;Out of Gas&lt;/a&gt; is my entry for the recent &lt;a href="https://ldjam.com/events/ludum-dare/48" title="Ludum Dare 48"&gt;Ludum Dare 48&lt;/a&gt; game jam. It was intended to be a blatant &lt;a href="https://subsetgames.com/ftl.html" title="FTL game"&gt;&lt;span class="caps"&gt;FTL&lt;/span&gt;&lt;/a&gt; rip-off, but in having much simplified clicker-like combat mechanics and an unusual cars-in-space aesthetic, I think it is sufficiently its own thing (I hope&amp;nbsp;anyway!)&lt;/p&gt;
&lt;h2&gt;Concept&lt;/h2&gt;
&lt;p&gt;My initial thought was more of a straight sci-fi concept of travelling into deep space, facing combat and resource management challenges similar to those which ended up in the game. The first thing that came to mind as a title for this was &amp;#8220;Out of Gas&amp;#8221;, after the &lt;a href="https://www.youtube.com/watch?v=-_heR2ekoxI" title="Out of gas. Out of road. Out of car I don't know how I'm gonna go."&gt;Modest Mouse song&lt;/a&gt; of the same&amp;nbsp;name.&lt;/p&gt;
&lt;p&gt;Thinking about that song got me thinking in another direction - essentially the same mechanics, but Earth-bound, set in a Modest Mouse world of highways and drifters, fleeing problems and starting over. The problem to flee in this case would obviously be debt - something that you can get deeper and deeper&amp;nbsp;into.&lt;/p&gt;
&lt;p&gt;As you can probably tell by now I ended up combining these two ideas! I didn&amp;#8217;t want to let either of them go, and I quickly fell in love with the idea of a universe where space combat meant winding down your window and firing a handgun at your&amp;nbsp;enemy.&lt;/p&gt;
&lt;p&gt;The combined concept suggested that a new, sci-fi twist on the debt problem was required, and that&amp;#8217;s where the idea of a constantly growing cryptocurrency debt came in. I&amp;#8217;ve been thinking about cryptocurrencies a lot lately since they&amp;#8217;re going through another hype cycle. One commonly touted feature of them (or some, like Bitcoin, at least), is that they&amp;#8217;re deflationary, so any debt denominated in them would constantly grow in value instead of decreasing in value like debts denominated in inflationary fiat currencies. This seemed like the perfect notion for the bizarre world of my game. It doesn&amp;#8217;t really have any impact on the gameplay, but I think it&amp;#8217;s a nice bit of narrative flavour, and it fits the theme&amp;nbsp;perfectly.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Late payment" src="https://blog.hyperlinkyourheart.com/images/out-of-gas-post-mortem/OOG-Late-Payment.jpg"&gt;&lt;/p&gt;
&lt;p&gt;The final piece of the conceptual puzzle was the characters. I couldn&amp;#8217;t very well have two anonymous nobodies riding along with the player on a trip like this! I turned to two characters I had vague notions of making a game about years ago, Haze &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Lee, a gun-toting, post-apocalyptic outlaw couple. Unfortunately I don&amp;#8217;t think their personalities really come across in the game due to time constraints, but at least they have&amp;nbsp;names!&lt;/p&gt;
&lt;h2&gt;Art&lt;/h2&gt;
&lt;p&gt;As usual, I did all the art in &lt;a href="https://www.pyxeledit.com/" title="Pyxel Edit"&gt;Pyxel Edit&lt;/a&gt;. I started off very rough with just pink boxes for the ships and a partial circle for the background, and moved immediately onto the gameplay with those placeholders. This is a somewhat unusual approach for me as I usually try to tie down the look of a game early&amp;nbsp;on.&lt;/p&gt;
&lt;p&gt;&lt;img alt="First mockup" src="https://blog.hyperlinkyourheart.com/images/out-of-gas-post-mortem/FirstMockup.png"&gt;&lt;/p&gt;
&lt;p&gt;The thing about rough mockups is that by the time I came back to the art a bunch of stuff in the game was already tied to the resolution and shape of the outlines. I wasn&amp;#8217;t even sure I had done the perspective correctly, but I was stuck with it anyway, and I guess it was close enough because nobody has&amp;nbsp;complained!&lt;/p&gt;
&lt;p&gt;&lt;img alt="First ships" src="https://blog.hyperlinkyourheart.com/images/out-of-gas-post-mortem/art_opt.jpg"&gt;&lt;/p&gt;
&lt;p&gt;I had planned to do some character portraits as well for the narrative side of the game, and express encounters as dialogues between characters, but unfortunately there wasn&amp;#8217;t time for&amp;nbsp;that.&lt;/p&gt;
&lt;p&gt;The map screen also didn&amp;#8217;t get much love, with the initial placeholder art surviving into the final&amp;nbsp;game.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Map screen" src="https://blog.hyperlinkyourheart.com/images/out-of-gas-post-mortem/OOG_Map_Trail.jpg"&gt;&lt;/p&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;p&gt;As for my last Ludum Dare entry, &lt;a href="https://blog.hyperlinkyourheart.com/gophers-post-mortem.html"&gt;Gophers&lt;/a&gt;, a &lt;a href="https://github.com/khoulihan/godot-cutscene-graph" title="Cutscene Graph Editor"&gt;cutscene graph editor plugin&lt;/a&gt; for &lt;a href="https://godotengine.org/" title="The game engine you waited for."&gt;Godot&lt;/a&gt; that I had previously developed was essential to getting this game done within the time constraints of the&amp;nbsp;jam.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Those darn teenagers!" src="https://blog.hyperlinkyourheart.com/images/out-of-gas-post-mortem/teenagers_dialogue.jpg"&gt;&lt;/p&gt;
&lt;p&gt;I had done a lot of work on this plugin in recent months, applying lessons learned from using it for Gophers to improve the workflow, functionality, and stability. This paid huge dividends, and I found almost no issues while churning out encounter cutscenes. The cutscene graphs created by this plugin power every encounter in the game up to and after&amp;nbsp;combat.&lt;/p&gt;
&lt;p&gt;My main task on the first day was to get the map screen working - it wouldn&amp;#8217;t be much of a game if you couldn&amp;#8217;t travel between systems. I implemented it as a graph defined by custom &lt;code&gt;MapSystem&lt;/code&gt; and &lt;code&gt;MapConnection&lt;/code&gt; control&amp;nbsp;nodes.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Map graph" src="https://blog.hyperlinkyourheart.com/images/out-of-gas-post-mortem/map_ui.jpg"&gt;&lt;/p&gt;
&lt;p&gt;The new fun thing about this for me was declaring the &lt;code&gt;MapConnection&lt;/code&gt; class to be a &amp;#8220;tool&amp;#8221; script, allowing the connections between systems to be drawn in the editor. This kind of custom tooling is important for the efficient design of systems in larger games, so it was fun to give it a try. Here, it mostly served to prevent me from getting confused about which &lt;code&gt;MapSystem&lt;/code&gt; nodes I had already connected to each other and which I&amp;nbsp;hadn&amp;#8217;t.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="n"&gt;_draw&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;usable&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;used&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;_can_draw_in_editor&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;_load_nodes_for_editor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;# TODO: Decide on proper colours for this&lt;/span&gt;
        &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gray&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;usable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hotpink&lt;/span&gt;
        &lt;span class="c1"&gt;# No idea why the offset is required&lt;/span&gt;
        &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;source_center&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_source_node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect_global_position&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;CENTER_OFFSET&lt;/span&gt;
        &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;target_center&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_target_node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect_global_position&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;CENTER_OFFSET&lt;/span&gt;
        &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source_center&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;target_center&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;source_center&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPACE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;finish&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target_center&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;source_center&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;target_center&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPACE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;draw_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;finish&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;LINE_THICKNESS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Implementing the combat was a lot tougher. The battle scene is almost entirely &lt;span class="caps"&gt;UI&lt;/span&gt; nodes, which was perhaps a mistake, and for some reason I struggled most of day two to even get player input to register properly. I don&amp;#8217;t really remember now what the obstacle was to this - maybe I was just&amp;nbsp;tired.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Battle UI" src="https://blog.hyperlinkyourheart.com/images/out-of-gas-post-mortem/encounter_ui.jpg"&gt;&lt;/p&gt;
&lt;h2&gt;Sound and&amp;nbsp;Music&lt;/h2&gt;
&lt;p&gt;There&amp;#8217;s nothing special about the sound this time around. Unlike for Gophers I didn&amp;#8217;t have time to do any foley work, and I figured I would probably have a hard time creating gunshot and explosion sounds anyway. Instead I fell back to &lt;span class="caps"&gt;SFXR&lt;/span&gt; (specifically, &lt;a href="https://sfxr.me/" title="jsfxr"&gt;jsfxr&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The music I put together in &lt;a href="https://beepbox.co" title="BeepBox"&gt;BeepBox&lt;/a&gt;, my favourite game jam tool for chiptune music these days due to its simplicity. I tend not to get as bogged down with it as I do with &lt;a href="https://lmms.io/" title="LMMS"&gt;&lt;span class="caps"&gt;LMMS&lt;/span&gt;&lt;/a&gt;. I initially wanted to try to create something in the style of Modest Mouse, given the game&amp;#8217;s inspiration, but it was hard to recreate a guitar sound. Instead I ended up with a simple arpeggiated chord progression over a bass drone that I hope feels kind of epic, kind of longing and lonesome, I&amp;nbsp;dunno.&lt;/p&gt;
&lt;p&gt;The battle music is a variation of the same tune but just swaps out one of the instruments, doubles up the drone, and compresses and spreads the arpeggios across more octaves for a more urgent and chaotic feeling. The two tracks play in sync throughout the game and just cut between each other as&amp;nbsp;necessary.&lt;/p&gt;
&lt;h2&gt;Abandoned&amp;nbsp;Ideas&lt;/h2&gt;
&lt;p&gt;As usual there were many ideas that I had to put aside due to time constraints. I had planned to include a small number of missiles which could be fired during combat with devastating effect, to allow the player to pull themselves back from the brink of defeat. I had also intended to have targetable/damageable systems on the ships, including injury to the characters, so that you could take out the enemy&amp;#8217;s weapon to gain a reprieve from being fired upon, or their engines and reduce their chance to dodge. You can see the proposed &lt;span class="caps"&gt;UI&lt;/span&gt; of these mechanics in the initial mockup above. Finally, I had planned a system of weapon upgrades which almost made it in, but not&amp;nbsp;quite.&lt;/p&gt;
&lt;p&gt;On the art side, I had wanted to include a number of different backgrounds to improve the sense of travelling between&amp;nbsp;systems.&lt;/p&gt;
&lt;p&gt;A big regret that I have is that I wasn&amp;#8217;t able to include the character portraits, and express the encounters primarily as dialogue between characters. I think this would have introduced a lot more personality to the narrative side of the game, as opposed to the third-person narration that I had to go&amp;nbsp;with.&lt;/p&gt;
&lt;h2&gt;Post-Jam&lt;/h2&gt;
&lt;p&gt;I like this game a lot, and I feel it is one that could be polished up and rounded out into a complete experience with relative ease, so I am determined to do a post-jam release with some of the missing features described above, and some of the problems with the jam release resolved (such as the &lt;span class="caps"&gt;RNG&lt;/span&gt; sometimes producing the same encounter multiple times in a row). I have already begun work on this, and I hope to have it completed in the next few months. I&amp;#8217;ll do another post about my progress on it so far, but for now here&amp;#8217;s a little sneak&amp;nbsp;peek:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hyperlinkyourheart.itch.io/out-of-gas"&gt;&lt;img alt="Haze speaks!" src="https://blog.hyperlinkyourheart.com/images/out-of-gas-post-mortem/HazeSpeaks.jpg"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="Game Development"></category><category term="ludum-dare"></category><category term="sci-fi"></category><category term="music"></category><category term="pixelart"></category><category term="godot"></category></entry><entry><title>Avocados</title><link href="https://blog.hyperlinkyourheart.com/avocados.html" rel="alternate"></link><published>2020-11-02T21:23:00+01:00</published><updated>2025-06-08T18:04:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2020-11-02:/avocados.html</id><summary type="html">&lt;p&gt;A couple of juicy&amp;nbsp;avocados.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/avocados.html"&gt;&lt;img alt="Avocados" src="https://blog.hyperlinkyourheart.com/images/avocados/Avocado02_x1.png" title="Avocados"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not very good at doing these art posts in a timely manner; I did this still-life of a couple of avocados for pixel dailies back in&amp;nbsp;September!&lt;/p&gt;
&lt;h2&gt;Timelapse&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=QP35xoMXE8U"&gt;&lt;img alt="Avocados" src="https://img.youtube.com/vi/QP35xoMXE8U/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="Art"></category><category term="pixelart"></category><category term="still-life"></category></entry><entry><title>Mine</title><link href="https://blog.hyperlinkyourheart.com/mine.html" rel="alternate"></link><published>2020-09-26T23:29:00+02:00</published><updated>2021-05-30T17:25:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2020-09-26:/mine.html</id><summary type="html">&lt;p&gt;A portrait of my friend&amp;nbsp;Mine.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/mine.html"&gt;&lt;img alt="Mine" src="https://blog.hyperlinkyourheart.com/images/mine/Mine_270x_x1.png" title="Mine"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A portrait I did of my friend &lt;a href="https://www.instagram.com/flamenclorca/"&gt;Mine&lt;/a&gt; a few weeks&amp;nbsp;ago.&lt;/p&gt;
&lt;h2&gt;Timelapse&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=rbd8nfxpNxY"&gt;&lt;img alt="Mine" src="https://img.youtube.com/vi/rbd8nfxpNxY/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="Art"></category><category term="pixelart"></category><category term="portrait"></category></entry><entry><title>Anticipation</title><link href="https://blog.hyperlinkyourheart.com/anticipation.html" rel="alternate"></link><published>2020-09-09T12:19:00+02:00</published><updated>2021-05-30T17:25:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2020-09-09:/anticipation.html</id><summary type="html">&lt;p&gt;A dog waiting for a very important&amp;nbsp;letter.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://portfolio.hyperlinkyourheart.com/anticipation.html"&gt;&lt;img alt="Anticipation" src="https://blog.hyperlinkyourheart.com/images/anticipation/AnticipationPortrait11Animated_x1_Optimised.gif" title="Anticipation"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I was inspired to create this when I won a postcard and sticker pack giveaway on twitter by my friend &lt;a href="https://twitter.com/moertel/"&gt;Stefanie&lt;/a&gt;, and I was eagerly waiting for it to arrive! I actually did this a while ago but I forgot to post it&amp;nbsp;here.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Postcard and stickers" src="https://blog.hyperlinkyourheart.com/images/anticipation/pack.jpg" title="Postcard and stickers"&gt;&lt;/p&gt;
&lt;p&gt;Go check out Stefanie&amp;#8217;s work, &lt;a href="https://moer.tel/"&gt;it&amp;#8217;s amazing&lt;/a&gt;. Thanks for the goodies&amp;nbsp;Stef!&lt;/p&gt;
&lt;h2&gt;Timelapse&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=IdL1mG59ApU"&gt;&lt;img alt="Anticipation" src="https://img.youtube.com/vi/IdL1mG59ApU/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="Art"></category><category term="pixelart"></category><category term="animation"></category></entry><entry><title>Observatory</title><link href="https://blog.hyperlinkyourheart.com/observatory.html" rel="alternate"></link><published>2020-07-02T18:48:00+02:00</published><updated>2021-05-30T17:25:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2020-07-02:/observatory.html</id><summary type="html">&lt;p&gt;An animation for Asteroid day&amp;nbsp;2020.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://www.redbubble.com/shop/ap/51580357"&gt;&lt;img alt="Observatory" src="https://blog.hyperlinkyourheart.com/images/observatory/ObservatoryComplete_x1_Optimised.gif" title="Observatory"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;An animation I made for &lt;a href="https://en.wikipedia.org/wiki/Asteroid_Day"&gt;Asteroid day&lt;/a&gt; to continue my space-themed art streak! Thanks to my friend &lt;a href="https://moer.tel/"&gt;Stefanie&lt;/a&gt; for the suggestion! Please click that link and check out her absolutely stunning art, you won&amp;#8217;t regret&amp;nbsp;it.&lt;/p&gt;
&lt;h2&gt;Prints&lt;/h2&gt;
&lt;p&gt;Prints are available through &lt;a href="https://www.redbubble.com/shop/ap/51580357"&gt;RedBubble&lt;/a&gt;, &lt;a href="https://www.inprnt.com/gallery/hyperlinkyourheart/pixel-art-observatory/"&gt;&lt;span class="caps"&gt;INPRNT&lt;/span&gt;&lt;/a&gt; and coming soon to&amp;nbsp;Displate.&lt;/p&gt;
&lt;h2&gt;Timelapse&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://youtu.be/Obh2zpAVn6k"&gt;&lt;img alt="Observatory Timelapse" src="https://img.youtube.com/vi/Obh2zpAVn6k/0.jpg" title="Pixel Art Timelapse - Observatory"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="Art"></category><category term="pixelart"></category><category term="space"></category><category term="animation"></category></entry><entry><title>Celestial</title><link href="https://blog.hyperlinkyourheart.com/celestial.html" rel="alternate"></link><published>2020-06-24T22:55:00+02:00</published><updated>2021-05-30T17:25:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2020-06-24:/celestial.html</id><summary type="html">&lt;p&gt;Several pieces inspired by the pixel dailies theme&amp;nbsp;&amp;#8220;Celestial&amp;#8221;.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://www.redbubble.com/shop/ap/50838959?asc=u"&gt;&lt;img alt="Celestial 1" src="https://blog.hyperlinkyourheart.com/images/celestial/celestial1.png" title="Celestial 1"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Only a few days after the last inspiring pixel dailies prompt, another one appeared that I couldn&amp;#8217;t resist - &amp;#8220;Celestial&amp;#8221;. I had three ideas for it immediately but I only had time to do the one above on the day. I&amp;#8217;m glad I spaced them out anyway because I think I achieved a lot with the extra&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.redbubble.com/shop/ap/50839684?asc=u"&gt;&lt;img alt="Flyby" src="https://blog.hyperlinkyourheart.com/images/celestial/flyby.gif" title="Flyby"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The second idea I worked on was originally only a planet-rise over some mountains, but it evolved quite a bit as I worked on it until it was about spaceships racing over a peaceful alien&amp;nbsp;village.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m quite pleased with the palette and animation on this&amp;nbsp;one.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.redbubble.com/shop/ap/50840685?asc=u"&gt;&lt;img alt="Celestial 2" src="https://blog.hyperlinkyourheart.com/images/celestial/celestial2.gif" title="Celestial 2"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The final concept I only completed yesterday, a view of the night sky through some&amp;nbsp;trees.&lt;/p&gt;
&lt;h2&gt;Prints&lt;/h2&gt;
&lt;p&gt;Prints are available through &lt;a href="https://randomhumanity.redbubble.com"&gt;RedBubble&lt;/a&gt; (linked individually above), and &lt;a href="https://displate.com/hyperlinkyourheart/celestial"&gt;Displate&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Timelapses&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=bn12CoFhqLc"&gt;&lt;img alt="Celestial 1" src="https://img.youtube.com/vi/bn12CoFhqLc/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=xrv-JyAFfXA"&gt;&lt;img alt="Flyby" src="https://img.youtube.com/vi/xrv-JyAFfXA/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Available from&amp;nbsp;2020-06-25:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Dn3sIkE6d3w"&gt;&lt;img alt="Celestial 2" src="https://img.youtube.com/vi/Dn3sIkE6d3w/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="Art"></category><category term="pixelart"></category><category term="pixeldailies"></category><category term="space"></category><category term="sci-fi"></category><category term="animation"></category></entry><entry><title>Cosmic Eye</title><link href="https://blog.hyperlinkyourheart.com/cosmic-eye.html" rel="alternate"></link><published>2020-06-06T21:44:00+02:00</published><updated>2021-05-30T17:25:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2020-06-06:/cosmic-eye.html</id><summary type="html">&lt;p&gt;A piece I did for pixel dailies on the theme&amp;nbsp;&amp;#8220;Eye&amp;#8221;.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Cosmic Eye" src="https://blog.hyperlinkyourheart.com/images/cosmic-eye/SpaceEye_216_01_x1.png" title="Cosmic Eye"&gt;&lt;/p&gt;
&lt;p&gt;I got back into the pixel dailies a couple of days this week. I&amp;#8217;ve never used them as an actual daily practice, but when I see a theme I like I jump in. This day, the theme was &amp;#8220;Eye&amp;#8221;, and I &lt;em&gt;really&lt;/em&gt; like&amp;nbsp;eyes.&lt;/p&gt;
&lt;p&gt;Unfortunately I was pushed for time that day so the result is a bit rough - however, I think it gets the idea across, which is &amp;#8220;eyes which are full of stars and made of stars and also stars were&amp;nbsp;there&amp;#8221;.&lt;/p&gt;
&lt;p&gt;I started this one out with my drawing tablet, which I don&amp;#8217;t usually use for pixel art and amn&amp;#8217;t very good with. I&amp;#8217;m trying to get away from using so many rigid straight lines, and treat pixel art more like regular painting. I had to switch to the mouse towards the end for the finer details, but it&amp;#8217;s a&amp;nbsp;start.&lt;/p&gt;
&lt;h2&gt;Timelapse&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=ZwnhLEPTCOM"&gt;&lt;img alt="Cosmic Eye" src="https://img.youtube.com/vi/ZwnhLEPTCOM/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="Art"></category><category term="pixelart"></category><category term="pixeldailies"></category><category term="surreal"></category><category term="space"></category></entry><entry><title>Ludum Dare 46 Results</title><link href="https://blog.hyperlinkyourheart.com/gophers-results.html" rel="alternate"></link><published>2020-05-13T22:34:00+02:00</published><updated>2020-05-13T23:58:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2020-05-13:/gophers-results.html</id><summary type="html">&lt;p&gt;Results for Ludum Dare 46 are out, and I did pretty&amp;nbsp;well!&lt;/p&gt;</summary><content type="html">&lt;p&gt;The Ludum Dare 46 results were published yesterday, and &lt;a href="https://hyperlinkyourheart.itch.io/gophers"&gt;my game&lt;/a&gt; did quite well, placing 109th overall and 14th in the &amp;#8220;Mood&amp;#8221; category, as well as 120th and 121st in graphics and audio respectively. In the largest ever Ludum Dare, those are pretty decent placings I think, despite not breaking the top&amp;nbsp;100.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Category&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Rating&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Placing&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Percentile&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Overall&lt;/td&gt;
&lt;td style="text-align: right;"&gt;4.136&lt;/td&gt;
&lt;td style="text-align: right;"&gt;109&lt;/td&gt;
&lt;td style="text-align: right;"&gt;96th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Fun&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.523&lt;/td&gt;
&lt;td style="text-align: right;"&gt;819&lt;/td&gt;
&lt;td style="text-align: right;"&gt;77th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Theme&lt;/td&gt;
&lt;td style="text-align: right;"&gt;4.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;279&lt;/td&gt;
&lt;td style="text-align: right;"&gt;92nd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Innovation&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.86&lt;/td&gt;
&lt;td style="text-align: right;"&gt;247&lt;/td&gt;
&lt;td style="text-align: right;"&gt;93rd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Humor&lt;/td&gt;
&lt;td style="text-align: right;"&gt;3.656&lt;/td&gt;
&lt;td style="text-align: right;"&gt;365&lt;/td&gt;
&lt;td style="text-align: right;"&gt;89th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Graphics&lt;/td&gt;
&lt;td style="text-align: right;"&gt;4.477&lt;/td&gt;
&lt;td style="text-align: right;"&gt;120&lt;/td&gt;
&lt;td style="text-align: right;"&gt;96th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Audio&lt;/td&gt;
&lt;td style="text-align: right;"&gt;4.102&lt;/td&gt;
&lt;td style="text-align: right;"&gt;121&lt;/td&gt;
&lt;td style="text-align: right;"&gt;96th&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Mood&lt;/td&gt;
&lt;td style="text-align: right;"&gt;4.523&lt;/td&gt;
&lt;td style="text-align: right;"&gt;14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;99th&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Graphs&lt;/h2&gt;
&lt;p&gt;I always feel that the real competition in the Ludum Dare is against myself - just trying to do a little bit better and learn a bit more each time. As such, here&amp;#8217;s some indication of my &lt;span class="caps"&gt;LD&lt;/span&gt; result trends over the&amp;nbsp;years.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Ratings Graph" src="https://blog.hyperlinkyourheart.com/images/gophers-results/ratings_ogm.png"&gt;
&lt;img alt="Placings Graph" src="https://blog.hyperlinkyourheart.com/images/gophers-results/placings_ogm.png"&gt;
&lt;img alt="Percentiles Graph" src="https://blog.hyperlinkyourheart.com/images/gophers-results/percentiles_ogm.png"&gt;&lt;/p&gt;
&lt;p&gt;Nice upward trends! Note that I was only responsible for the art for &amp;#8220;Claustrophobia&amp;#8221; and &amp;#8220;Rattendorf&amp;#8221;, so I can only take partial credit for the overall and mood ratings of&amp;nbsp;those.&lt;/p&gt;
&lt;p&gt;The real learning experience this time around was on the audio. I&amp;#8217;ve only done the audio for six of the nine Ludum Dares I&amp;#8217;ve entered, so I left it out of the graphs&amp;nbsp;above.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Ratings Graph" src="https://blog.hyperlinkyourheart.com/images/gophers-results/ratings_audio.png"&gt;&lt;/p&gt;
&lt;p&gt;Looks like I really cranked it up a notch this time after coasting for a long while.&amp;nbsp;Nice.&lt;/p&gt;
&lt;h2&gt;Moar&amp;nbsp;Gophers&lt;/h2&gt;
&lt;p&gt;I haven&amp;#8217;t decided yet if I&amp;#8217;m going to take the game further. I quite like the concept and I certainly have some ideas for it. I&amp;#8217;ll probably finish off my &lt;a href="https://github.com/khoulihan/gopher-render"&gt;gopher renderer&lt;/a&gt; and phlog generator before I decide, and then I can do a &lt;em&gt;devphlog&lt;/em&gt; for it&amp;nbsp;:D&lt;/p&gt;
&lt;p&gt;You can still play the &lt;a href="https://hyperlinkyourheart.itch.io/gophers"&gt;jam version&lt;/a&gt; for now, if you missed&amp;nbsp;it.&lt;/p&gt;</content><category term="Game Development"></category><category term="ludum-dare"></category><category term="gopher"></category><category term="sci-fi"></category><category term="music"></category><category term="pixelart"></category><category term="godot"></category></entry><entry><title>Gophers</title><link href="https://blog.hyperlinkyourheart.com/gophers-post-mortem.html" rel="alternate"></link><published>2020-04-25T17:24:00+02:00</published><updated>2021-05-30T17:25:00+02:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2020-04-25:/gophers-post-mortem.html</id><summary type="html">&lt;p&gt;A post-mortem of my Ludum Dare 46 entry, Gophers - a short adventure game about keeping a gopher network alive after some sort of nuclear event has destroyed&amp;nbsp;civilisation.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://hyperlinkyourheart.itch.io/gophers"&gt;&lt;img alt="Overlooking the city" src="https://blog.hyperlinkyourheart.com/images/gophers-post-mortem/Gophers_tower.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hyperlinkyourheart.itch.io/gophers" title="Gophers"&gt;Gophers&lt;/a&gt; is my entry for &lt;a href="https://ldjam.com/events/ludum-dare/46" title="Ludum Dare 46"&gt;Ludum Dare 46&lt;/a&gt;, the most recent of the bi-annual Ludum Dare game jams. It is a short adventure game about maintaining a &lt;a href="https://en.wikipedia.org/wiki/Gopher_(protocol)" title="Gopher Protocol"&gt;gopher&lt;/a&gt; network in a post-apocalyptic&amp;nbsp;world.&lt;/p&gt;
&lt;p&gt;The basic concept is one I&amp;#8217;ve been kicking around for a while as a sort of casual &lt;span class="caps"&gt;RPG&lt;/span&gt;/survival game about maintaining computer networks on scavenged technology, so it came to mind immediately when I saw the theme (&amp;#8220;Keep it&amp;nbsp;alive&amp;#8221;).&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been really interested lately in gopher and other low-overhead technologies, and what the internet would look like if the industries that sustain it collapsed. I&amp;#8217;d previously envisioned a relatively cheerful solarpunk game about connecting distant sustainable communities, but I think it took on a much darker tone because of recent&amp;nbsp;events.&lt;/p&gt;
&lt;h2&gt;Art&lt;/h2&gt;
&lt;p&gt;I did all the art in &lt;a href="https://www.pyxeledit.com/" title="Pyxel Edit"&gt;Pyxel Edit&lt;/a&gt; as usual. My goal was to keep everything abstract and as high-contrast and readable as possible while still allowing for a nice parallax cityscape. I started with a mock-up of the exterior scene, and then essentially flipped the background and foreground colours from that for the bunker scene. I only used 7 colours in the&amp;nbsp;end.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Bunker Scene" src="https://blog.hyperlinkyourheart.com/images/gophers-post-mortem/BunkerScreenie.jpg"&gt;&lt;/p&gt;
&lt;p&gt;I put together a timelapse of the art so you can see the whole&amp;nbsp;process:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=0jPLMCfSE0w"&gt;&lt;img alt="Gophers" src="https://img.youtube.com/vi/0jPLMCfSE0w/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;p&gt;The only reason why I considered this a viable idea was because I had previously developed a &lt;a href="https://github.com/khoulihan/godot-cutscene-graph" title="Cutscene Graph Editor"&gt;cutscene graph editor plugin&lt;/a&gt; for &lt;a href="https://godotengine.org/" title="The game engine you waited for."&gt;Godot&lt;/a&gt;. It was untested in any game but I thought it would give me enough of a leg up that I would have time for the art and&amp;nbsp;writing.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/khoulihan/godot-cutscene-graph" title="Cutscene Graph Editor"&gt;&lt;img alt="Graph editor" src="https://blog.hyperlinkyourheart.com/images/gophers-post-mortem/graph.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So in effect, the &amp;#8220;gopher network&amp;#8221; in the game is actually a dialogue&amp;nbsp;tree!&lt;/p&gt;
&lt;p&gt;Actually using the editor in a game did reveal some issues with it, but nothing significant enough to prevent me from finishing - and now I have some ideas on what needs work before I use it for another&amp;nbsp;game!&lt;/p&gt;
&lt;p&gt;I also took some code from a &lt;a href="https://hyperlinkyourheart.itch.io/people-poker" title="People Poker"&gt;previous game of mine&lt;/a&gt; for doing the menus and dealing with the settings. Every bit helps when you&amp;#8217;re entering the jam&amp;nbsp;solo.&lt;/p&gt;
&lt;p&gt;One thing that really came together for me in this jam was using coroutines to manage sequences of events. I&amp;#8217;ve always struggled to wrap my head around them previously for some reason, and would clumsily hook up signal handlers for every step. Using the &lt;code&gt;yield&lt;/code&gt; statement in &lt;a href="https://godotengine.org/" title="The game engine you waited for."&gt;Godot&lt;/a&gt; made handling interactions much easier and quicker to&amp;nbsp;write.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="n"&gt;_on_Terminal_clicked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;walk_target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;face_direction&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;_player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_destination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;walk_target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_player&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;arrived_at_destination&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;face_direction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;GameController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_spawn_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;bunker&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;terminal&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;GameController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_spawn_direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;bunker&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;right&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;FadeMask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fade_in&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FadeMask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;fade_in_complete&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Switch to the browser scene&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_tree&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;change_scene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;res://browser/Browser.tscn&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;FadeMask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fade_out&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FadeMask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;fade_out_complete&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Sound&amp;nbsp;Effects&lt;/h2&gt;
&lt;p&gt;The most exciting part of working on this game, for me, was doing the sound effects. I bought a fancy mic a while back (a &lt;a href="https://www.rode.com/microphones/nt-usb" title="Røde NT-USB"&gt;Røde &lt;span class="caps"&gt;NT&lt;/span&gt;-&lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/a&gt;) to do foley &lt;span class="caps"&gt;SFX&lt;/span&gt; rather than my usual &lt;span class="caps"&gt;SFXR&lt;/span&gt; beeps and boops, but this was the first chance I&amp;#8217;ve had to try it&amp;nbsp;out.&lt;/p&gt;
&lt;p&gt;&lt;img alt="My foley kit, or part of it at least" src="https://blog.hyperlinkyourheart.com/images/gophers-post-mortem/foley-kit.jpg"&gt;&lt;/p&gt;
&lt;p&gt;For the Geiger counter sounds I ran my finger over the teeth of a comb. For the bunker door, I rubbed a hammer and a spanner together in various ways. For the dripping sound in the bunker, I just used an eyedropper to drip drops into a glass of water. The footsteps are real footsteps that I recorded, and the cloth sounds when you&amp;#8217;re walking around the exterior are me crinkling a vinyl jacket. It was a lot of fun to record all these and I don&amp;#8217;t think I was even being all that creative. I couldn&amp;#8217;t figure out how to do buzzing or flickering sounds for the electric light within the time I had though,&amp;nbsp;unfortunately.&lt;/p&gt;
&lt;p&gt;One big problem I encountered was that my apartment is apparently incredibly noisy, as am I. It was a windy day and the shutters on my window were banging constantly, my neighbours were going about their noisy lives, oblivious, and my body stubbornly refused to go without oxygen during the recordings. Noise reduction in &lt;a href="https://www.audacityteam.org/" title="Audacity audio editor"&gt;Audacity&lt;/a&gt; helped a bit (make sure you record periods of &amp;#8220;silence&amp;#8221; to enable this), but there are definitely some extra environmental sounds in there. Thankfully I think they mostly just appear as mysterious underground reverb or get buried by other things. It&amp;#8217;s something I&amp;#8217;m definitely going to have to think about for next&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;I did a bunch of post-processing in &lt;a href="https://www.audacityteam.org/" title="Audacity audio editor"&gt;Audacity&lt;/a&gt; to pick the best bits out of the recordings, and make things sound better. I had to reduce the pitch on the bunker door sound to make it sound heavier, for&amp;nbsp;example.&lt;/p&gt;
&lt;h2&gt;Music&lt;/h2&gt;
&lt;p&gt;I was so proud of the sound effects that I almost wasn&amp;#8217;t going to do any music, but I&amp;#8217;m glad I did. I got to it in the last few hours of the jam, so I had to keep it very simple. It&amp;#8217;s mostly just the notes of a Dmin7 chord played in a few different arrangements on pad instruments, with some slow bass drums coming in and out. The title screen music layers a couple of different pads as well as a Rhodes doing sus4 arpeggios from each note of the&amp;nbsp;chord.&lt;/p&gt;
&lt;p&gt;I put everything together in &lt;a href="https://lmms.io/" title="LMMS"&gt;&lt;span class="caps"&gt;LMMS&lt;/span&gt;&lt;/a&gt;. I spent a good chunk of time experimenting with different instruments so even though it&amp;#8217;s really minimalistic it still took a&amp;nbsp;while!&lt;/p&gt;
&lt;h2&gt;Abandoned&amp;nbsp;Ideas&lt;/h2&gt;
&lt;p&gt;I had planned several other game elements, including the protagonist saying things to himself (or the player), and another type of interaction involving connecting cables and swapping out computer&amp;nbsp;components.&lt;/p&gt;
&lt;p&gt;A full game would probably have more complex survival elements instead of a simple timer, and would see you having to scavenge in the environment for computer equipment and other&amp;nbsp;supplies.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ll see if anything like that comes to fruition in the&amp;nbsp;future!&lt;/p&gt;</content><category term="Game Development"></category><category term="ludum-dare"></category><category term="gopher"></category><category term="sci-fi"></category><category term="music"></category><category term="pixelart"></category><category term="godot"></category></entry><entry><title>Catnip</title><link href="https://blog.hyperlinkyourheart.com/catnip.html" rel="alternate"></link><published>2020-01-23T15:52:00+01:00</published><updated>2020-01-23T16:24:00+01:00</updated><author><name>Kevin Houlihan</name></author><id>tag:blog.hyperlinkyourheart.com,2020-01-23:/catnip.html</id><summary type="html">&lt;p&gt;An animation of a cat hunting pixels on a 70&amp;#8217;s styled&amp;nbsp;computer.&lt;/p&gt;</summary><content type="html">&lt;p&gt;I put together an animation over the last few weeks of a cat trying to catch &lt;a href="https://en.wikipedia.org/wiki/Glider_(Conway%27s_Life)"&gt;gliders&lt;/a&gt; on a 70&amp;#8217;s styled computer. Check it out on&amp;nbsp;YouTube:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=2PqFIOkhUSk"&gt;&lt;img alt="Catnip" src="https://img.youtube.com/vi/2PqFIOkhUSk/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I actually only set out to draw the computer, and I&amp;#8217;m not sure at what point the cat entered the picture, but I&amp;#8217;m glad it did! My goal wasn&amp;#8217;t to depict any specific vintage computer, but to create a somewhat implausible one from imagination. I did look at a bunch of references for ideas on what to include, mostly from &lt;a href="http://oldcomputers.net/"&gt;oldcomputers.net&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Music&lt;/h2&gt;
&lt;p&gt;I had originally planned to create a patch in VCVRack to accompany the animation, but I struggled to create something that felt right for the animation. Several attempts to create something in &lt;span class="caps"&gt;LMMS&lt;/span&gt; also failed. I ended up putting something together in &lt;a href="https://beepbox.co/#8n51s6k0l00e0zt2mm0a7g0zj07i0r1o321440T1v2L4u25q1d5f7y0z8C0c0A5F4B0V1Q000dPc696E0018T1v1L4u63q1d5f7y1z7C1c0A1F1B4V1Q50b0Pea3bE0181T1v3L4u57q1d5f4y4z2C1c0A0F9B4V8Q0040P9900E0111T1v3L4ue1q3d7f7y2zbC0c0A0F0B7V1Q0000Pe600E0911T0v1L4ua7q3d6f8y4z1C0w0c1h0T3v1L4uf7q1d5f7y3z6C1SZIztrsrzrqiiiiibhkki4N8l0000018j4xkg4S00000g4x0j4xci4N0i41ci4Q00hkki4N8j4xci4N8j4xd5hm00000000004x8i4x8i4x800000000000000000018j4xci4M00000h4x4i000h4x4i4h800000p23GKrF-9isT7URQVH-p4U7CpKkVJvGBbXHKtSRnrARlLmrnZFdv_jvonQYPIyYLLKKYXZDvBCR-9jnUtc3onQYMcU_0rrupCh1KrhZGxqJQmVKfZ-PLMFKf-jTY3V2CnQUaD8S0sxdvVOILbOWrnUbYDcdvonVCmq_se_aKU_W-U_wuIXz_HW_TW_iL0arF-EvcBC8bwkRUwnFB0zhjhy9BV9EZELOjhOs25E5PYAmwk0"&gt;beepbox&lt;/a&gt;.&lt;/p&gt;</content><category term="Art"></category><category term="pixelart"></category><category term="animation"></category><category term="music"></category></entry></feed>