Learning by playing

2021 February 24

Recently I experienced a cool first: a project of mine got a shoutout at a programming talk. The project was a small game, and it’s gotten me to reflect on how important making games has been to my development as a developer.

Educational gamedev

I didn’t set out for this to be the pattern, but it’s somewhat remarkable - over my career as a software developer, almost every foray into a new programming language has been done through trying to build a game. I suppose it’s simply my go-to move when exploring new ways to build software. Making these games not only familiarized me with the nuts and bolts of each of the new programming languages, it also helped introduce me to and familiarize me with generally-applicable software development concepts, the most important of which: I like making stuff that people use.

Learning Unison in 2020: 2048

When I left Tamr in late 2020, I wanted to spend my time studying languages and technologies I hadn’t yet been exposed to. Around that time a couple friends of mine (shoutouts to RJ and Ian) were getting involved in a new early-stage functional language called Unison. I figured it was a great opportunity to take a deeper dive into functional programming, as well as see how a language gets off the ground.

Initially, I wanted help the community by making a simple game, then building a set of docs around that game to help people learn the language. I chose 2048 because it was sufficiently simple, well-known to people (so they could focus on learning the language), single-player, and didn’t require complex UI interactions (since the only UI feasibly available to me in Unison was the terminal).

I haven’t gotten to the point of building the docs, but the game itself works! Unfortunately I don’t know of a way to host it online, so in order to play it you’ll have to download Unison… and learn a fair bit about how to use its codebase manager. If that’s no problem, here’s the repo!

Above is a screenshot of the important first I mentioned in the introduction: one of Unison’s cofounders Rúnar Bjarnason gave a shout out to this project at a talk he gave recently. It’s a small moment in the scope of a new language like Unison, but I was swelling with pride when I saw it. I need to mention though, in that video he demoes the trunk version that I hadn’t merged an animations update to — it looks better with animations.

What this introduced me to

  • Everything Unison has to offer, including…
    • Algebraic effects, though do I really understand these? Does anyone? Probably the Unison guys.
    • Content-addressed immutable term identifiers. The big thing in Unison. The set of ways you can break your program is getting smaller and smaller because really smart people are doing things like this.
    • Working with a codebase manager, as opposed to a big ol’ bag of text files like we’re used to.
  • A community built around an alpha programming language. I had never seen what goes into making the sausage before I got involved with Unison, and it’s been very rewarding.
  • ANSI escape sequences, for producing the visual interface in the terminal.
  • Language design based on Haskell. Trying Unison has coincided with me spending a lot of time learning Haskell, and cross-referencing the two has introduced me to just how influential Haskell is in the FP space.

Learning Elm in 2018: Rummikub

Sometime in 2018, my partner and I had her family over for a board game night. We decided to play Rummikub, which sounded fun and all. I had never played it, and I came to find out they had been playing Rummikub as a family for years. Needless to say they absolutely destroyed me…

My hurt pride demanded justice, so I wanted to do something to get more familiar with the rules and mechanics to be better prepared for the next encounter, and I figured building a Rummikub engine would be a nice project. I also wanted to build a solver for it, so that, as I joked to my partner, I could secretly pull it out next time we played Rummikub all together and wow everybody with my unbeatable skills (this never happened).

My friends (shoutouts to Aaron and RJ) were at the time diving into Elm, a new language to me in a yet-unexplored paradigm: “Functional Programming” (does that mean programming that works?). Riding my friends’ energies, I got to work on a Rummikub game engine written in Elm.

I lost steam on the project after only having made the engine, so it unfortunately doesn’t have a solver, a UI or anything screenshot-worthy. But it definitely let me sink my teeth into FP for the first time.

What this introduced me to

  • Functional programming! After a heavily OO-weighted education and career to this point, this was my very first foray into this different paradigm. (Spoiler alert, I very much favor it these days). Some concepts under this…
    • Algebraic data types. What would I do without them these days?
    • Pattern matching.
    • Automatic currying / the idea that all functions are unary.
  • Property / fuzz testing. Unfortunately, though, I didn’t really “get” it at the time. I don’t think I was yet primed enough on the importance of laws, properties and guarantees that FP focuses on.

Learning C++ in 2016: pyxl

This isn’t exactly a game, but it’s not exactly useful either, so I think it fits the category. I had touched C++ a few times in school, but who knows what sticks in those first few confused years of learning how to code. Having worked for the previous few years in Java and JavaScript, I was starting to hear from more experienced colleagues about the relative inefficiencies of Java vs. C++, about how C++ being “lower-level” meant it could be more performant. I figured I should learn about it, and feel what “lower-level” really meant.

I’m not sure exactly where I got the idea for a text file animation engine, but that’s what I built. Honestly, this wasn’t the last time I’d thought about game-like experiences that interact with real-world or not-meant-for-games data or contexts, like in this case arbitrary text files. Perhaps more to come on that…

Anyway, this was the first time I had touched C++ since college in 2014, and I haven’t touched it in the 5 years since. This project is certainly what I recall when thinking about C++ though. If you’d like to try it out you’ll have to pull down the source, build it, then run the binary in your terminal. Try mashing all of the commands at once, the animation engine can handle it :D.

What this introduced me to

This project didn’t introduce me to all that much, rather it helped solidify a lot of understanding through gaining a new perspective on fundamental, language-agnostic ideas.

  • Public interface vs. implementation, specifically in the header file vs. cpp file form that concept takes in C++.
  • Build configuration, specifically in the makefile form it takes in C++.
  • Complex terminal interactions. This project was my first exposure to ncurses, and getting experience here has helped me later, say, use ANSI escape codes to build the 2048 UI.

Learning JavaScript in 2013: Supervirus

It was the summer of 2013, and it was a slow week at my internship at Koa Labs. I was there to develop my skills as a software engineer, and, having almost no experience with it, I decided to try my hand at a small JavaScript project. Since I’m me, that project was a game.

Does anybody remember the old XGen Studios game Fishy?

Fishy Classic

I loved that game, so it’s no wonder what I ended up making was essentially a re-skin of it. Nevertheless, I was and still am very proud of what I had made in those couple weeks. I remember my mentor Kelsey would bet me a dollar each day for the rest of that summer that he could get a higher score than me in a single run. That type of encouragement was awesome, and really helped me understand just how fulfilling it is to have people use and enjoy the stuff I build.

If anybody would like to try Supervirus out, here it is! Fair warnings: there’s a (misspelled) expletive if you lose, and you “win” the game when you get so big your browser crashes trying to look for an off-screen place to spawn a new enemy.

What this introduced me to

  • Collision detection and resolution, which is a constant consideration in game development.
  • A return to trigonometry, for the math involved in getting the player character to sliding along the edge of the boundary.
  • The entity-component-system gamedev concept, through a JS game engine called craftyjs.
  • A truth about myself: I want to build things that people find delight in. There’s no feeling quite like that.

This also familiarized me with, you know, JavaScript, which proved to be one of the most useful hands-on skills I brought into my job the next year at Tamr. That foundation, and building on it over the course of the next few years, was essential to me becoming a technical leader in the UI there. It’s peculiar to think about how that somewhat frivolous use of two weeks has really fundamentally shaped my career.

Learning Java in 2011: LabyrinthAdventure

In the Spring of 2011 I had yet to touch the wonderful world of Computer Science. My friend Aaron had just taken CS 101 and was showing me the stuff he was doing. It looked like magic. I decided to take CS 101 as a summer course online at Southern Connecticut State University after my freshman year ended.

I distinctly remember the first time I saw “Hello, World!” printed to BlueJ’s console. Big feeling of magic. It sounds cheesy, but I think from that moment on it was pretty clear to me what I wanted to do with my life. I greatly appreciate that that feeling of magic hasn’t really gone away.

About a month in I made this little gem: LabyrinthAdventure. I can’t believe I found the source code actually, luckily I had emailed it to a friend asking for advice back in July 2011. This was the very first thing I made that wasn’t a class project. Opening the source code back up again was a powerful blast of nostalgia.

All you do in the game is click on the different directional buttons and see the different messages I put in each location until you get to the end and win. Super modest, but it was a big mountain to climb back then. I remember being so confused about how to work with Swing, and just wading blindly into the ocean of copy-pasting answers from the internet. But that’s an important part of learning programming, and maybe any skill - you can’t always gracefully derive actions from well-understood principles, sometimes (maybe, a lot of the time) you have to bang your head against the wall for hours (maybe, years). I developed a sense of accomplishment, and through that motivation, from simply making a thing work. I got to a finished product understanding little but being exposed to everything that went into it, which I think is an important, albeit frustrating, developmental stage.

What this introduced me to

  • Building stuff on my own. I can do it!
  • Java, and programming, in general. There’s so much to soak up one month into your programming education.
  • The concept of an IDE. After getting advice from a more experienced friend he recommended I use NetBeans. Was I ready for it? I’m not really sure, but it launched me into a big new experience for coding.

Increasingly complex Legos

Noticing this pattern has made me reflect on what building games offers as a learning mechanism. I think the biggest thing is how important it is to have the spirit of play in learning, especially for me. The fact that the project isn’t for some direct, useful, or external purpose leaves room for not feeling bad about not knowing what you’re doing. The frivolity of it all let’s you explore and try things in a low-stakes environment.

I think in general, not just in regards to learning, I always do my best work in an appropriately playful environment. I think part of the mission of delighting the user means that delight is involved for all those making the experience as well.

Another aspect is that the visual and interactive nature of games lets you create by reacting. I was first exposed to this idea by Bret Victor’s essential essay Learnable Programming, which I highly recommend. You change some code, you see your experience change, and you react to that change by tweaking more code. This loop of action and reaction leads to a lot of growth and understanding of what you’re doing.

Thank you for reading!