rae.wtf

blog by rae

There But For The Hex of Gon Go I

10.05.2025   •   hexa


Hello! As I write this, it’s been just a couple of days since I launched HEXA on itch.io, for personal computers. If you’re reading this article, you’d probably like it!:

PLUG PLUG PLUG (Buy HEXA for personal computers)

…Or if you hate clicking links, I’ll sum it up: it’s a puzzle game, with triangles. You make hexagons, and try to conquer the universe. Simple!

Screenshot of HEXA running on a computer. In the center of the screen, there's a black, yellow, and white grid comprised of 19 individual triangles.

I launched the original game in late July of 2024, exclusively on the Playdate console. This was my second release for the platform, and above all else a real testament to the idea of the game jam: come up with a good idea, iterate ‘till you find something that’s “fun”, and polish it ‘till you can see your own reflection. I gave a whole talk about this!¹

The original Playdate version of HEXA, in Catalog

The initial game came together over the course of July — development started on the 4th, and it was released by the 30th. This was due in part to how fast I was able to iterate on the game and come up with something that I thought was really special, but also due to a lot of happenstance things that I just happened to get really lucky about. One could very convincingly argue that HEXA has been more trouble after it released than it ever was before! Hahaha, haha, haaa, ha.

But one thing has been on my mind for a while: this game would ROCK on computers. I don’t think it uses the crank in an imperative way (sorry hekhound), and it feels like it’s got better “legs” than a lot of other titles I’ve made for Playdate. I could technically have ported Cloudburst or something, but people aren’t really clamoring for a weather app on…their computers.

I actually went back through some DM history, and apparently the idea of porting HEXA over using LÖVE2D was in my head since…before HEXA even launched! Peep this:

DM message from user 'rae'. Attached is a screenshot of the HEXA game board grid running in a macOS window. It's captioned "STAND BACK IM GONNA BLOW THIS WHOLE THING WIDE OPEN"

Crazy, right?! Since then I’ve talked with a couple people and formatted the idea a couple different ways (shoutouts to the incredible Playbit library from Alex over at Games Right Meow, which aims to make this Playdate <=> LÖVE pipeline way easier with a single-repository approach!), but I figure I should talk a bit about the process of this final incarnation of the port, the one that you can pick up today.

I kinda just…started! I downloaded the LÖVE tools, fired open a new Nova project, and just…started running full-force into this new brick wall that’s been placed in front of me. It took me a solid hour to even figure out how to format a window, but by the end I had…something I wound up replacing with a better system that allowed for fullscreen/free resizing. Wooooo…!

Anyway, I started knowing that I was going to have a few hurdles going in. For one, a lot of my projects rely on specific aspects of the Playdate SDK that aren’t necessarily directly portable to LÖVE. Namely, things like OOP (object-oriented programming), game state-switching (which relies on the OOP itself), timers (in the animation sense, to allow for nice easings and delayed reactions), and sprites (Playdate has these as an easier way to manage compartmentalized logic, drawing order, etc. Plus, they also rely on the OOP library, within my workflow).

I soon found out that I was talking to the right people though, because legend icon superfunc basically immediately pointed me towards a library called HUMP². And this got me like… most of the way there! OOP, game states, timers; the only thing it didn’t really have a direct analog for was sprites, but I worked around that by…not using any sprites. Sustainable? Nope! But it works for now. 😁

The timers were also a bit of a kerfuffle to get working, as well — the HUMP library gave me a pretty close approximation, but I definitely had to rework some of my internal logic about how timers need to work. You can’t, for example, create an independent timer object and call for its standalone value. With HUMP, you need to have a pre-existing value, and pass it into the newly-created timer which it will then interpolate based on its settings. So instead of calling timers directly on the field, I’d have individual variables, and then the timers call the shots from the sidelines.

HUMP’s timers also lack functions like repeating, or reversing; so I bodged my way around that by creating more timers that, after a delay, would influence the initial timer performing the animation. So for example, you’d have a “tween” timer that moves a value from 0 to 1 over a second. Then, I’d set up a “every” timer that, every 1 second, would reset the “tween” timer — if the value it was editing was above 0.5, though, it would instead tween from 1 down to 0. Voila; looping, reversing timer! It’s an incredible hack, but it seems to work great.

From there, a lot of the hard work boiled down to three things: trying to jump the mental hurdle of having to crawl through my old code again; getting used to the idiosyncrasies of the LÖVE2D engine (specifically with reference to porting over other idiosyncrasies from the Playdate engine); and also creating a game in a PC environment (instead of one guaranteed platform, there’s an untold number of display resolutions, control methods, etc etc etc).

One simple thing that really screwed me over was losing Playdate’s arithmetic shorthands. For example, in Playdate’s version of Lua, you can do something like foo += 1 to increment a variable. Stock Lua, however, does not allow for this, and will get SUPREMELY mad at you if you try. So I had to do it the “long” way; for example foo = foo + 1. Not a bad change overall, but I definitely accidentally crashed the game quite a few times by just not remembering that I had to switch these over.

Two other big pain points were window resolutions (which I talked about a tiny bit before), and gamepad support. For the windows, I ended up landing on a solution where the game canvas is technically drawn in “the top left corner”, but is moved using translations and the “scissor” tool into the center of the window. The game will only ever scale on an integer level, because I A. did not want to implement a responsive design, and B. wanted to stay as true as I could to the look of the original game. You can even toggle off the color entirely, and play it near-exactly how it would look running on a Playdate!

The gamepad support is also really funny: I had already hooked up key bindings for each scene, and I didn’t feel like duplicating all of that function logic for the gamepads. So instead, I have a single global “gamepad pressed” function that interprets the button you’re pressing, spoofs a key on the keyboard, and tells the LÖVE engine that you “pressed” that “key”. So far, I haven’t heard about any bugs stemming from it!! 😬 (I also made it so that the on-screen button prompts react appropriately to the given control method you’re using. It’s a small touch, but I feel like it greatly improves the perceived polish level of the game!)

I also had the opportunity to add controller rumble, entirely on a whim — I was looking into adding support for the analog sticks on the controller (which I wound up not even supporting); and only in fumbling around through the LÖVE documentation was where I noticed the rumble function on supported controllers. I literally dropped everything to add that in in around ten minutes or so, and I’m really glad I did, because it adds so much in a way that I’ve never been able to toy around with before on Playdate. It’s so cool to experiment with even the subtle things like that which I just had no outlet for before now, and it makes me really stoked to keep working on stuff for the PC platform! If you haven’t already, try the game on a controller. It’s NICE.

On the topic of bespoke additions to the version for personal computers: obviously, color is a huge one. Here’s a fun fact: the game uses the Pico-8 stock color palette! Not for any particular reason, other than that I needed a palette, and it was the first one that I could think of with relative limitations. It was fun having the freedom of a full color suite, while still being limited in a way that necessitated the use of dithers for more advanced hues. I feel like it keeps the spirit of the Playdate original nicely despite much (read: infinitely) greater color fidelity.

At first, I was planning for a only single set of colors to the HEXAPLEX; the default set you see in the game today. After some tester feedback where players were mentioning that they weren’t sure if some of the tri colors were a bespoke value or just negative space on the game grid, I decided that I needed to change the colors. Problem was, I couldn’t decide which palette looked best…sooooo, I decided to add them all! In the final version, you unlock a new set of colors for your HEXAPLEX for every 1,000 on your top high score (up to 25,000). It’s a small bonus, but I really feel like it was a cool addition that helped underscore the insanity of getting to re-interpret a game that I’ve only ever envisioned in 1-bit, in color.

There were also some things that I added to the PC version, that I then backported into the Playdate original! So, this port was an entirely manual effort. I’m sure someone other than me would have written a batch script to convert function names, or asked one of their silly robots to do the job for them, or smartest of all designed the game to support both platforms in the first place. But for me, the only way I’d have been satisfied with the product was to manually vet all the code myself; staring at the Playdate script side-by-side with the new LÖVE code, and manually roping over logic and making engine conversions on the fly.

This process, start to finish, took about a week or two, but that’s also considering the time it took me to learn the fundamentals of LÖVE and figure out the transpositions for the Playdate-specific functions in the first place. One benefit(?) of doing the port this way, is that when you’re taking a very in-depth look through an entire codebase with a required focus on what it’s doing…you spot a lot of bugs you just kinda never noticed before! It’ll be hard to find the time to dive into a codebase that deep again (especially for a larger game), but it meant that I was also revising the Playdate version as I came across quirks and things I figured should be tweaked.

I did also tweak a couple of things just so that I could make things slightly easier on myself in the porting job, while keeping the visual parity up to code. (Nothing structural to the gameplay or logic, mainly just how a couple small things look). I also added a couple bonus features to the Playdate version; things that I was recommended to add to the PC version, but weren’t necessarily impossible to backport to the Playdate hardware. So, both versions now enjoy the benefits of a full Statistics menu, and granular volume controls rather than a static on/off toggle.

The final leap for me came in actually releasing the game. Bundling the versions for different platforms was and continues to be a pain — you can’t really edit a Windows executable without a Windows machine, so I’ve been unable to add fun metadata like icons (if anyone knows a way to do that from a Mac, get in touch!); and of course when creating an app that runs on computers, they are very very vigilant about virus protection. For extremely good reason, let’s face it!, but as someone who’s used to the ease of having someone sideload a Playdate title, the trust barrier of the computer actively being super reluctant to run some code I’ve compiled was a pretty crazy culture shock.

I released the game on itch.io on October 3rd, 2025; not knowing a single thing about the PC gaming market, or how a title like this would sell — I do have experience with itch’s backend (publishing jam titles for example), but am not too well-versed with maintaining a paid title on the platform. I decided to launch at $8 — the same current price as the Playdate version in Catalog — because I figured this would keep things simple. A couple of things are surprising me as someone who has majority experience selling in Playdate’s Catalog — namely, the lower default revenue share taken by itch.io (10%, compared to 25% in Playdate Catalog), and the addition of the ability to ‘tip’ above MSRP.

Catalog has no tips function, so as a developer I’ve subconsciously written it off in my mind just because I don’t have any experience with it; but I’m surprised that multiple people so far have opted to pay above my suggested price for the game! It’s super nice to see; of course if you’re out there, thank you to bits for your support.

And I think that brings us to…now! It was a super fun experience, and I’m definitely encouraged to make more games for personal computers. Just personally (ha), it was really fun being able to involve my friends who don’t own Playdates — I’ve been making games for a while, but seeing my friends testing and having fun with the things I can make is a magical feeling I didn’t realize I was missing. Once I get more time, I’d absolutely love to continue pursuits in LÖVE2D, and maybe even port some of my other Playdate titles with the same method. (I’ve been racking my brain trying to figure out how RowBot Rally could work without the crank…) If you’ve read this far, thanks! I hope this interested you. And, if you haven’t picked up the game, I hope you consider it! I know I didn’t talk much about what it’s actually like, but believe me: it’s heaps of fun.


¹I really should consider recording a cut of that for YouTube sometime — heaven knows I’ve already forgotten all my lines, and that it wasn’t that good of a talk anyway.

²I know, I know. Apparently a lot of LÖVE libraries are named like this. I don’t know why.