Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Video Game in a Font (coderelay.io)
605 points by ghub-mmulet on March 19, 2021 | hide | past | favorite | 76 comments

I wrote a an article going into the technical details here: https://github.com/mmulet/code-relay/tree/main/markdown/HowI...

I also released the code for the game engine. Available here: https://github.com/mmulet/code-relay/tree/main/markdown/Tuto...

Amazing! I absolutely love projects like this, where you put a game in somewhere it clearly wasn't meant to be. I made a game you play in your file browser[0] before, and I have another idea planned using windows error dialogs.

0: https://wheybags.com/dungeons_and_directories/

A kindred spirit! Dungeons and directories is great! I've only played the beginning so far[Edit I've beat the game now and joined the secret club!], but I really laughed at the "You walk through the southern door, and straight into the chasm you saw earlier..." Picture : "you walking straight into the chasm with a smile on your face".

I ran into the same problems you did, any variable leads to an exponentially large state. Other than, "scoping" as you put (or branch merging as I put it), the most space-efficient way I found to keep state was to ask the player to remember a passcode. So the player can keep track of the state, but I don't have to (ie. exponential space savings!). Even when entering the password, you can keep the space small (n*2 rather than 2^n) see [0]. Players used to retro PC games will remember entering passwords found in their instruction manual, so it's an added nostalgic appeal.

Let me know when your error dialogs game is done. If you want to collaborate on some games, hit me up, I too love games where they shouldn't be.

0: https://github.com/mmulet/code-relay/blob/main/markdown/how/...

I had a similar "variables" problem when designing a choose-your-own-adventure book with my kids. I wanted your character to be able to reach the same pages but have state -- e.g. have a key or not have a key. I didn't want to have to duplicate pages with different state (which I kind of remember from old CYOA books -- there's be pages with almost the same thing, but now slightly different because you entered the room with a sword or whatever).

In the end, because it's a book and not a computer game, we could just ask the user: "If you have a key, turn to page 43..." and it just depends on the user being honest (or as honest as any reader of a CYOA book is, with nine fingers stuck between pages).

I assume there were similar books in the past that used the same mechanic -- maybe the Fighting Fantasy books? I forget.

Could you have used the key as a simple crypto-key? As in, give them the two digit number, and tell them "Turn to page 17+the number of the key".

Or if you wanted to make them work a little harder and maybe teach a little math, "17 times the number mod 47".

Of course they can still be dishonest, but it gives them an opportunity to have solved a simple puzzle. They get to the correct page because they "won".

Yup, could do that, that's a good idea.

The other thing we did, slightly simpler, was introduce a plethora of choices where only prior knowledge would get you (easily) to the page.

E.g. You can land on page A a number of different ways, but only from one path do you find out the suspect is in a certain city. Then from page A you're asked if you want to go to B, C, D, E or F. Without the prior knowledge there are too many choices.

This is exactly how the game Seventh Continent works, its just a collection of 1000 cards and if you have a symbol then you sometimes draw a different card for if you have key items.

Thanks! Just played through fontemon now (I think, the final battle is unbeatable right? I think I tried every move combo). Had a bit of trouble getting it to work in system programs, but on your site it worked just fine (in libreoffice it would just repeat the intro if I changed the font size, and gimp would shift things up and down depending on the highest pixel in the frame).

Overall, awesome stuff :D Ever since I read [0], I knew you could do some funky stuff with ligatures, but I never imagined you could take it this far :D

0: https://blog.janestreet.com/commas-in-big-numbers-everywhere...

Maybe my in game hints were too subtle. You can beat it, but spoilers

You have to keep going past the ending (GameOver) keep typing. You'll revive and beat the boss.

I beat it but at the end it said that I got the "bad ending". Is there really a good ending?

Amazing project BTW, had a lot of fun!

Thanks! There are 3 endings in fact. Checkout the secrets guide [0]

0: https://github.com/mmulet/code-relay/blob/main/markdown/Secr...

Yeah it still has a lot of quirks. On libre office, you have to change the font size to size 2px (and zoom in) or so to play the game all the way through without resetting. Same thing happened to me in gimp, it's annoying but playable.

You're following someone's footsteps and don't even know it.

This is years beyond the statute of limitations so I can finally talk about it - in my youth I broke into one of LANL's servers for kicks; some Lotus/IBM Domino machine, saw nothing of interest except for a project directory which even the admin didn't have access to... I didn't want to escalate privileges any further because it'd require permanent changes and would probably trip a flag - but then I found a bizarre folder.

Someone coded a series of directories within Domino and made a maze game, maybe a Zork 'lite'. I spent a few minutes exploring and got bored.

Sounds like the plot to WarGames! Be glad you didn't cause WW3!

Ha, interesting! Would you be interested in sharing more details? (How you got in, for exwmple)

Barely remember... I think it was some staff/user directory listed within robots.txt, which also happened to not verify edit credentials on the backend so I was able to 'borrow' a login from a backup admin :)

Plenty of similar stories about other better known orgs/corps but this isn't the venue for those :)

Adding to the theme of games where there shouldn't be: I had a bit of fun adding the Chrome dino game to DevTools a couple years ago: https://twitter.com/cjamcl/status/1143725364553764864?s=20

I love it! The dialog idea is genius too.

This week I stumbled upon John Robertson for the first time. He made an choice based Adventure game called The Dark Room, which (in its first iteration) was realized with YouTube Annotations, then performed live, and now he streams it on Twitch. It's an interesting combination of preparation and improvisation

Perhaps the most interesting consequence of this game design is that you can edit the past, changing a single decision while leaving your other choices in place.

For example, it's possible to go back to the beginning of the input box and edit your character selection while keeping the rest of your gameplay in place.

Seems like this could have a lot of potential as a puzzle game mechanic.

Best quote from the author's article explaining how it was done (even though by his own admission he didn't follow his own advice in the case):

"If you want to make a game, make a game. If you want to make a game engine, make a game engine. But never, ever, make a game engine to make your game!"

I spent a good five+ years working on my own game engine to make my own games with it. Never finished a single game, or the engine-- but it was a fun learning experience so there's that.

It's a much better quote than the annoyingly common, "Don't write a game engine!"

If you work in games or want to work in games, writing a game engine is a very valuable experience. Probably the best thing you can work on for personal growth.

That said, I think you get substantially more value out of the experience if you've already gotten your feet wet making games with a commercial engine.

Well, one day last week I wrote this game http://canonical.org/~kragen/sw/dev3/invaders without a game engine. Then I decided that it would be a lot better with a game engine, so I wrote a game engine for it http://canonical.org/~kragen/sw/dev3/qj2d.js and rewrote the game over the next couple of days with the engine http://canonical.org/~kragen/sw/dev3/qvaders. Then during the rest of the week I used the engine to write http://canonical.org/~kragen/sw/dev3/qabbits and http://canonical.org/~kragen/sw/dev3/offscreen † but both of which were a lot easier to write with the engine than they would have been without it, and for which I had to improve the engine, which also improved the Invaders game.

Now obviously QJ2D is not going to replace Godot or even LÖVE2D or TIC-80. It's a couple of days' worth of work, less than 200 lines of code; anyone could have done it. And nobody else is going to use it unless they have Greek letters on their keyboard. But not only did I learn a lot, it's also a substantial improvement for this kind of thing over the raw browser. I think I'll probably rewrite it differently for the next project, though...

I don't want to "work in games", but of course I enjoy writing games. I mean that's all computers are good for, really!


† not really games

> you have chosen... unwisely. This is the worst one.

Not only is this a brilliantly hilarious piece of tech, the humour in the game ain't bad either.

Great job!

This is crazy. I can feel the immense possibility from this. I especially like the "feature" of this game, where you can save, load, and even share the game progress just by copying the plain text.

Me too! One day I want to make a multiple game where you have to copy/paste text between two different fonts to solve puzzles!

I feel the immense possibility of security vulnerabilities from this, but I assume it’s just a font, so, I suppose anything that looks like scripting can’t access any outer API.

Wow! That's all I can muster to say. I always knew fonts and font rendering was tricky business....

(And you are making the rounds on gaming sites [0])

[0] https://www.rockpapershotgun.com/fontemon-is-a-pokemon-parod...

Thanks! There's a lot of room for unexplored creativity in fonts. Fonts are everywhere, but they are so complex so no one tries. And thanks again, for the link, I didn't see that!

I'm in shock and awe. I knew GSUB can computationally do such things, but didn't know there is no defined maximum substitution limit even in practice and it is only limited by the table size. Amazing!

this is a great abuse of GSUB tables

just van rossum’s rubik’s cube is another recent example of font layout gone too far: https://twitter.com/justvanrossum/status/1340960087750402048...

And that tweet led me down a rabbit hole, to this:


Sorry, waaay off-topic, but I've never seen such incredible D&D dice!

Very pretty and very expensive dice! Possibly a good present for a Tabletop RPG fan

That's sweet! Is it open source? I would love to take it apart and see what makes it tick!

I have a question regarding how you render "gray" pixels. You said that you use rectangles, because "dithered" pattern had low performance. But the rectangles cause "scanlines", which I presume are because of imprecise mapping to physical pixels.

Have you tried other shapes? Dividing the square by the diagonal should not have this problem, and you're even drawing a simpler shape (triangle vs rectangle).

I have tried other shapes at the pixel level, but not at the sprite level. Example: I draw from the top left pixel, draw the whole row of pixels (use the run length encoding), Then I draw the next row and so on. I haven't tried drawing the top left pixel and then drawing the to the bottom right corner, then moving up/down a diagonal row. You're right that might make it look a lot better, I will have to try it later. I stopped after I got it "good enough", because I wanted to finish the game.

I was specifically referring to the "sub-pixel" level: https://github.com/mmulet/code-relay/blob/main/markdown/HowI...

Oh yeah. In that case, I did try that, but for whatever reason it didn't perform well or I wasn't happy with the look. (It was probably performance). You can play around with the sprite rendering in the code. This [0] is the line for each individual pixel. And this[1] is where I generate the repeated pixel subroutines.

0: https://github.com/mmulet/font-game-engine/blob/e92a97ecbf8c...

1: https://github.com/mmulet/font-game-engine/blob/e92a97ecbf8c...

They could use the CPAL and COLR tables to turn each glyph / frame of the game into multiple RGBA layers.

Are CPAL and COLOR supported by chrome?

Chrome definitely supports them on Windows at least, I don't know if it supports them on other operating systems. Here's a test page for the various kinds of color font tables: https://yoksel.github.io/color-fonts-demo/

Sweet! I might make a FontKid Color!

Can I save my game by copy/pasting what I typed?

[Edit]: Yes, it seems. Very cool!

Great project! I love the idea of extending Blender to use it as a custom game engine.

So do I! It saved me a lot of work. I started making it as a web-based react component, and I got to the part where I was doing custom bezier curves and keyframe based animation, and I was like "ah, I'm reinventing the wheel here!" So I switched. The only (possible) downside is that the addon has to be GPL3. I always intended on licensing the engine as GPL3, so it wasn't a problem for me.

I just looked into that code relay thing, and it sounds really cool. Do you have any examples of contributions or things people accomplished with it yet? I'm finding it hard to imagine what could be accomplished in just 5 minutes a day.

For all intents and purposes, Code Relay literally just launched today, so I don't have any examples, yet. 5 minutes a day is a matter of scale.

If we can get 10% of programmers to devote 5 minutes to open source a day, we can help a lot of people (maintainers and the open source community as a whole).

Obviously, not everything can be broken down into 5 minute tasks. But, I believe there are enough things that can be broken down. That Code Relay is worth pursuing.

Maybe, it will only work for functional programming languages where there is a strict way to divide code into smaller and smaller functions.

Or maybe it will only work for crowdsourcing documentation. Most projects need better documentation, badly. So, this would be a worthwhile goal in and of itself.

The approach I'm taking now is to try everything and see what sticks.


This seems interesting and compelling, but I think encoding "this specific time at this specific timezone" into the foundation of the system will exclude a potentially significant number of people that may otherwise contribute to its success.

First of all, let's see how far away I am from PST... okay, 7AM PST is 1AM the next morning in AEST (in Australia). Imposing a globally-fixed time across the world, irrespective of timezone, falls on the suboptimal side of exclusive for a lot of people, since there are always going to be more people outside of any given timezone than within.

Secondly, I look at 7AM a bit deer-in-headlights: I'm incidentally temporarily using an offset sleep schedule at the moment while I rectify some environmental issues, so that time happens to be just about the mathematically least optimal moment in the day for me to approach a conveyor belt of unexpectedness with anything resembling interest. Most likely I would instead demonstrate the fastest possible method ever seen of permanently disassembling the conveyor belt, then go back to sleep :)

The above two points are my reasons why this approach would not be ideal for me. I suspect that a lot of other people would probably present unique anecdotes of their own with vaguely similar sentiment.

I would recommend a call waiting-like architecture instead. Have a giant queue of things on the server. Offer some small percentage of available tasks to a given user*, then hide those from everyone else. When the first user picks the thing(s) they want**, re-mark the unselected things as available. Do this for everyone at once.

* It will both be technically easier and socially more interesting for users to list their experience then get delivered a precomputed list of tasks, than simply go "ok here's _everything_". The 'everything' approach has terrible UX, with tasks disappearing as others "steal" them, but the precomputed ideology of "this list was calculated before you arrived" feels more like TV - the list of things the user can see is all there is. This architecture should age very well, too, allowing you to do all kinds of optimizations over time in terms of figuring out who visits and when and what tech they like and whatnot, then precalculate optimized views for each user before they arrive. You'd need a few hundred people before you'd be able to build that correctly though.

** Definitely let users pick more than one thing to add to their local queue. That way they can headscratch about (or get their brain into the zone for) complicated thing #2 while breezing through trivial thing #1. If someone queues a task they decide is actually too hard, make it feel like it's not at all the end of the world for the user to release the task back into the queue. This covers queuing up multiple things as well.

Also, make it possible for users to see all tasks they ever selected, including what they didn't complete or immediately released without starting - the user might have fat-fingered their mouse (or brain) and might want to go manually complete (or help completing) the task outside of the website. (Completely +1 avoiding the rabbithole of "wait, no, I actually wanted that task, yank it off of whoever is doing it")

In practice (from an architecture-design perspective) I reckon about 50 things and 3 or so users would probably look pretty similar to 1000 users and 150 things and 5000 users and 500 things.

In closing, even with the queue approach described here, I see the fundamental idea as very distinctly different from the asynchronicity and absolutely-unbounded-complexity of Stack Overflow. Here are 5 things. Which can you do **right now** in 15 minutes? That does not exist. It sounds awesome.

Also, SO's success, _despite_ the unboundedness issues, absolutely proves that there are people out there who will literally spend hours and hours figuring out other people's problems for free. The idea of making this process ADHD/anxiety-friendly, unintentionally or not, is why I initially said this was compelling. May you scale well :P

NB. Have you thought about supporting collaboration? That would be the next logical step for something like this - and it's so logical, it's unfortunately what everyone using the platform would likely clamor for. I recognize that it's extremely hard to even just collaboratively edit documentation etc, let alone work on solving open-ended problems with arbitrary tooling. Precisely figuring out and publishing your stance on this - eg, "nope, not interested", "sounds interesting, patches welcome", "sounds interesting, patches welcome if maintenance on offer", etc - from the start might be a good idea. (FWIW "patches welcome" can often come across as very unempathetic and ivory-towered, if you will, especially when it sticks around for a long time and gives the impression progress isn't happening. Articulation is hard, etc...)

(edit, typing into the box where the pictures happen is easy enough, it's just typing in the bottom box that is very awkward because of constantly scrolling back up to see tiny changes.) Sadly this is very difficult to play on mobile.

Loving some of the puns: Helvetikhan lol

Amazing project! Had fun in the web version, although I didn't manage to make the game font work on any of my available text editors on Mac. (I tried in Pages, TextEdit, Sketch, and I broke Sublime trying to use the font in there).

Uh, that code looks a lot like PostScript.

Call me crazy, but you would write a Z-Machine on that.

I believe it's a derivative of PostScript (mostly as subset), and as far as I know, it's not Turing complete.

That's sad :( But understandable.

Absolutely awesome! I'm impressed by the level of polish, this is waay beyond the usual POCs you see for hacks like this.

For me, the tl;dr from the technical explanation was this:

> Now, everything in fontemon is baked

Just reading that made me laugh out loud. It's so simple and so ridiculous, i love it.

I recommend reading the entire blog post btw, it's very thoroughly explained and it assumes no knowledge of either fonts or gamedev.

Thanks! For better or worse, I'm a perfectionist with deadlines (to steal django's slogan) . I tried to make everything as accessible as possible, because I know 12 year old me would want to make his own font-game. I spent a lot of time, adding guard rails to Blender so you can't get lost (I made it impossible to change the camera, to dismiss the side bar menu, I also made it so you never have to go into a sub-menu. Everything you need is available in one central location.)

I wasn't able to get it to run on Microsoft Word or Adobe Flash CS5, but finally got it running on paint.net, and have to say I am amazed!

I should build a list of places where it works or doesn't. Some places will work if you set the right options, enable the right ligatures. Which version of Word did you use?

I'm using Word Version 2102 Build 13801.20294, with Microsoft 365 Apps for Enterprise

This is really cool, I love these little tech experiments that keep the "hacker" in "hacker news" :)

Back in my day, all we had was a pixel.

(seriously, very fun!)

That was amazing, and I managed to get all three endings :D

Now I gotta try shoving it into various programs to see if it works.

Great job!!!

At least on work, they already blocked at least some Egyptian Hieroglyphs even in the standard fonts.

Somebody should do a speedrun of this game. Is copy pasting considered tool assist?

The copy paste exploit was banned in official speedruns by the committee. Macros are still allowed though and there is a lot of community backlash because of this being so similar to copy paste in practice.

Amazing! God Tier! I love it and thanks for the articles to go with it!

Is it just me or is the game unwinnable?

I couldn't figure out how to help missINGDINGno from that guide

After the seventh gym, when you get your gym badge, the meat. Look at the text. At some point you'll see a : that's when you enter the passcode

After you ybfr gb gur svany obff, lbh'er fhccbfrq gb xrrc glcvat naq gura lbh "jva" naq trg n uvag sbe fbzrguvat qvssrerag gb qb ng gur ortvaavat.

(However, I haven't figured out exactly what to do after that!)

I got the bad ending. But still trying to find out the place for abaa if thats actually what the key is.

You have the right key. Check out the secrets guide [0] if you get stuck.

0: https://github.com/mmulet/code-relay/blob/main/markdown/Secr...

~~I've tried a bunch of different things but I can't figure out where to enter the code. I looked at the hint too but it didn't help in my case.~~

Edit: Figured it out

Hello everyone! A lot of people are getting stuck, so I wrote a guide [0] to the game's secrets. I saw that this got posted to lobste.rs, can someone post this link there, too, I don't have an invite to that site.

0: https://github.com/mmulet/code-relay/blob/main/markdown/Secr...

Loved the Rochester shout-out!

Applications are open for YC Summer 2023

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact