Project A Part 2: The First Seven Days

This post is part of a series. Part one is here.

Work on Project A began 16 June. I used nguillaumin’s excellent slick2d-maven project to get off the ground in a hurry. I enjoy working with Slick2D. It’s opinionated, but not too much. It has its flaws, but none of them are enough to disparage its use for simple projects. The first commit was just committing the generated directory structure after generating it. From here, I tried to make my earlier goal a little more actionable:

My goal is to get as quickly as possible to a point where the player can interact with the game in a way that is fun. Everything else is secondary.

Sublime Text minimal of all the bugs I had filed against myself.

I had amassed a pretty big bug list working on my last project (see my Sublime Text minimap on the right). Some of it was actual bugs, logic issues, that sort of thing. The majority of it was pipe dreams about what I thought I might be able to create. What I wanted to do this time around was not get wrapped up in the future, but always focus on the next immediate thing which would get me to a playable game.

I just recently played golf for the first time in a long time. I remembered the rule that the player with the ball furthest from the hole plays next. I enacted a similar rule for my game’s facets. I would stop work on more sophisticated facets until the less finished ones caught up. It’s not foolproof—creating equally sized goals for each part of the game is hard—but it’s a good rule of thumb.

The first facet I chose is UI. My first three goals, referred to by letter, looked like this:

  1. A basic UI that can display text.
  2. Store previous displayed text in a ring buffer so that text panels can continuously add lines to it and older lines will fall off the screen.
  3. Display a map of the world.

Alongside it, I had the Worldgen facet. My first three goals looked like this:

  1. The initial world generation loop: one pre-pass, one pass, one post-pass.
  2. World generation parameters keyed to a random seed to guarantee consistency.
  3. Placing settlements of various sizes onto the world.

I first started working on the UI, which can be see in my earlier post. The first step was creating some abstractions. I wanted to hide the details of displaying characters and setting colors. I could then create text panels, add lines to them, and then display them in Slick2D’s update loop. I had finished up with this in about two days.

Once I reached this goal, I put UI aside, and started working on Worldgen. This was kind of cheating, since I pulled in a ton of useful source code from an old project to get off the ground faster. It provided the basic container classes, and a noise function to use as the elevation of the world.

To keep things moving along, I also pulled in a bunch of utilities that I had put together over the years. One of my favorites is the RandomGenerator class, an extension to java.util.Random that allows a handful of useful functions:

  • nextString(int length), which returns a random string of ASCII characters,
  • nextAvailable(List<T> list, Class<T> cls), which returns a random typed object from a list, as well as a variant for returning a random typed object from a collection like a Set.
  • roll(int qty, int sides) for D&D style dice rolls,
  • RandomEnum, which allows one to register an Enum in the generator and then ask for a random item, or any random item except a passed list of values.

This is part of the codebase I’d eventually like to get online and public. At that point, all one has to do is specify a seed to the RandomGenerator, and make sure the same one is used for all procedural generation steps. In this way one can have reproducible worlds based on a seed, similarly to Minecraft.

A test of generating random characters and colors.

When the (extreme) basics were in place to my satisfaction, I turned back to the UI. In this way, every part of the game keeps in step with the other parts. I am kept in check against rabbit-holing too deeply on any one aspect of the game’s engine. After one more test of my UI (seen on the left), I plugged in the world generation to the UI.

Finally getting to see my world in my UI.

This is always one of the best parts of game programming for me. The ability to see one’s results so clearly through your game’s UI. I just created that little world. It’s not going to survive for long, and the ‘elevation’ is just choosing a different color based on some internal value, but that’s a world, and I generated it.

To view the entire map, I created a subclass of my text panel which took a ‘renderable thing’, and allowed a cursor move atop it. The renderable thing in this case was just the world tiles, which I refer to as cells generally. Again, pulling out code from the past helped me a ton here. In countless games, I’ve written some variant of the following logic to track something on a map larger than the screen:

  if (cursorX < 0) cursorX = 0;
  if (cursorY < 0) cursorY = 0;

  if (cursorX >= tileRenderable.getWidth()) cursorX = tileRenderable.getWidth() - 1;
  if (cursorY >= tileRenderable.getHeight()) cursorY = tileRenderable.getHeight() - 1;
  if (viewport.getX() < 0) viewport.setX(0);
  if (viewport.getY() < 0) viewport.setY(0);
  if (viewport.getMaxX() > tileRenderable.getWidth())
    viewport.setX(tileRenderable.getWidth() - viewport.getWidth());
  if (viewport.getMaxY() > tileRenderable.getHeight())
    viewport.setY(tileRenderable.getHeight() - viewport.getHeight());

I let myself play with the UI just a little bit more, to create an input text panel so I can see and change the world seed. After that, it was back to worldgen. My next step was settlement generation. I decided to use YAML to store structure data. YAML is more susceptible to typos and malformed data than XML, but it is simpler and easier to write in a hurry. I needed a YAML parser, and after some research, settled on SnakeYAML.

SnakeYAML is more than just a YAML parser. It comes packed with all kinds of insane functionality. It can marshal YAML documents into custom types. It can use YAML tags as syntactic hints for parsing. It can create objects based on YAML strings which match custom regexes. An example (and one I shamelessly copied from the documentation) is the ability to create a document like the following:

id: small_house
name: small house
size: 2
  !r knowledge: 1d3
  !r water: 1d10
  !r food: 1d10
person_capacity: 4
rarity: 1d4

There’s a couple things at work here. Normally, this document would get stored as a HashMap. Adding the !structure tag tells SnakeYAML to store the document in a JavaBean-like class. Values specified like a D&D dice roll (e.g. 1d10) get parsed out into a Dice(int qty, int sides) object. Finally, the !r represents a specific Enum; in this case, a resource type. My Structure object has a Map<Resource, Dice> field called contains. SnakeYAML is smart enough to store the enum as the key, and the Die as the value. This is insanely powerful.

I used the rarity field of a structure as a kind of placement decision system. The above structure has a rarity of 1d4, so one out of every four buildings, on average, should be an old house. More rare buildings, like police offices, would be 1d30. Even more rare buildings, like museums, would be 1d100. I wanted to adhere to these rarities during world generation, so I used this quick and dirty method. When worldgen requested a building, I would iterate over all known buildings, and roll a die matching their rarity. Every building whose die roll came back one was added to a set. Finally, I chose a building at random from that set. This is not an efficient way of ensuring the distribution—and the distribution is most likely off—but it sufficed for my purposes.

The final part of settlement generation was the ability to generate “rare settlements”. Every once in a while the rarities of all the buildings were pulled inward on the number line towards their average. For example, say I only had two buildings in my database. One has a rarity of 1d4, and another has a rarity of 1d50. The average of 50 and four is 27, so 4 would become larger—to be closer to 27—and 50 would become smaller. These settlements had a higher than average amount of rare buildings. Generating these makes worldgen more interesting, and gives players something to look for.

With that, I the first week of writing code ended. I pulled in a lot of extant utilities I wrote from earlier projects. I relied on the knowledge I had picked up from ASCII UI libraries like libtcod. I’m not sure how long this would have taken me starting from scratch. In any event, now was the time to add more facets to the project. The next facet was NPCs, for which I’ll soon have a write-up.

The game UI with a world dotted with settlements, and a log on the right displaying the kind of buildings that were recently generated.

Building a Grid-based Dungeon Crawler

After reading CrookedB’s Wizardry 4 LP and playing Legend of Grimrock, I decided I wanted to fuck around with a simple first person dungeon crawler. I love the look of old crawlers in this genre: cobblestone, timber framed buildings, and fog renderers.

Lands of Lore

Started with Java as usual, and GDX because of the success I had migrating another project over from slick2d. GDX isn’t perfect but it’s incredibly powerful and easy to get off the ground.

Started off as most projects do, with some sanity tests for loading images and positioning. At this point I’m still using the built in GDX model builders.

First attempt.

Notice that the textures on some sides of the cubes aren’t rotated correctly. That would stick with me until I finally started understanding UV mapping, and manually assigning corner order for new meshes. For the time being, though, I just rotated every cube 90 degrees on the Z-axis and ignored it.

I grabbed some Minecraft textures, created a map of zeroes, ones and twos for different textures, and added colored fog, and directional light. Already it was looking pretty good. Didn’t learn anything special at this point, but it was good to play around.

Looking prettier: better textures, colored fog, and positioned light.

This is where I started learning about billboards: textures mapped to a simple plane that either always face the camera, or are always aligned with the camera’s normal. Or at least, I think that’s the distinction. The difference is clear (sprites here are from Dungeon Crawl: Stone Soup).

Comparing camera facing and camera aligned billboards.

On the left, the billboards are “turned” slightly to look at the player. On the right, the billboards all face the opposite of the camera’s normal. So there’s no distortion.

This was accomplished with GDX’s Decal class, but the class doesn’t have the same surface area as the rest of GDX’s 3D rendering pipeline, so I couldn’t give it awareness of the fog and lighting environment setup:

Standing out brightly.

Standing out pretty brightly, huh? This is where I had to start diving closer to OpenGL and understanding the state machine a little bit better. I ended up replacing the use of the Decal class with my own implantation, culled from sources online and experimentation. Getting the billboards to be rendered with the correct fog and lighting was the easier part. The more difficult part was making sure they were facing the correct direction. At many points during this I would end up with billboards that only were visible from one direction, or were flipped vertically when viewed from the opposite direction.

I created a tiny gradient of sky-like colors, and set a timer so that the environmental fog would select a color from the gradient to match the time of day. Simple effect but super cool:

Using fog coloring to simulate sky colors.

I’m not sure if I’m going to take this project further, but I’d like to someday.

Project A Part 1: Retrospective

I’ve started working on another game project. Before I dive into it I want to take a look back at how I got to this point.

I’ve been working for the past five years—in one way or another—on a post- apocalyptic game of some kind. Work on it started when I was still running Linux as a daily driver on my old HP Pavillion laptop. I wanted a Dwarf Fortress-like simulator in the style of text-based Roguelikes. The year before I started working on it, I had actually managed to “complete” my first game: a seven day challenge with items, randomly generated floors, enemies with localized body part damage, and a not that bad interface. It was called Towerkrieg.

Towerkrieg, my first real attempt at a game.

I was happy that I was able to pull enough SDL and C++ knowledge together to make it happen. It allowed me to check my perfectionism at the door and make something that a player could actually interact with. Five years later, and I only conceivably made one other thing that a player could conceivably enjoy. It was a Flash game with isometric tiles which I worked on with a member of the forums. I don’t remember why I chose this theme, but the player was a hackey sack making its way through an office building, shooting security guards who—being pinballs for some reason—would then bounce all over the walls at high speed while constantly firing at you. I called it Bearings and Loan.

Bearings and Loan, a Flash game I made for a game competition.

I drew all those sprites, and all the isometric tile pieces. I was incredibly proud of myself.

After all that, I decided I needed to take it a step further. I wanted to make a deeper roguelike, something with real skills, real loot, real monsters and something worthwhile and interesting.

Vagrant NG, written in Lisp using the libtcod library.

This is Vagrant NG, the first iteration of the game I tried to put together. It was in Lisp, and it used the libtcod library.

Vagrant was the project I worked on for five years. It took all kinds of forms, from a console game written in Lisp, to a 3D game written in Python, to a 2D top-down action RPG. At the end of five years, I didn’t have much to show for it. The game was never fully written, never released, never shared. The only thing I have is a bunch of half-finished codebases and a handful of lessons I’m applying to my next project.

My next hobby game, Project A, is hopefully going to show the effect of all of these learned lessons.

My goal is to get as quickly as possible to a point where the player can interact with the game in a way that is fun. Everything else is secondary.

Many times over the past five years I’ve gotten bogged down in the details of writing my own game engine, or trying to balance a half-finished procedural generation engine, instead of being happy with the results at a high level. The project was always incredibly ambitious, and the fact I never made consistent progress shouldn’t at all be surprising.

So here’s Project A. This is what it looked like a few weeks ago.

Starting over from scratch.

The simplest possible thing that could be possibly work, I started off with Slick2D and a fairly mundane Code Page 437 tileset off of the Dwarf Fortress wiki. I wanted to get something on the screen as quickly as possible, so I built a text panel which would display characters with a given foreground and background color, and which could be told to take up a rectangle on the screen.

With that, I’ve come all the way back around to a simple ASCII-style game UI.

I’ve made more progress than that in the past few weeks, but that’s a good place to stop for the time being. Hopefully this will put me in the right mindset to continue describing some of the work I’ve been doing.


The age of the blog is over. Has been for a long time. It’s kind of depressing, actually. But there’s not really much you can do about it. Everyone’s on their smart phones, reading 140 characters at a time through an app that sucks up 20% of your battery life after being on screen for 25 minutes.

We all spend our time “measuring engagement” now, even though we don’t really recognize it. We count how many likes and retweets and faves we get on each little piece of garbage we throw into the waters of the internet.

I mean, let’s be clear. This isn’t some “man with VR googles and introvenous Facebook drip political cartoon” commentary. We’re not addicted to this stuff. A good percentage of us have actually fulfilling lives outside of the web. We go rock climbing. We travel. We learn new languages, and learn to knit, and go to hacking spaces. The world is an enormous place, and a lot of us live our lives to the fullest.

Which is why the whole social media thing is even more depressing. It’s produced some amazing things, hilarious Twitter humor, social commentary, it’s inspired and changed the lives of countless people. So it’s frustrating to see all those channels of inspiration and originality get transformed into polluted wastebins for the sake of “buzz” for whatever piss-poor company runs them and gets to hoard all our creative output.

I think it sucks. I think it sucks that the internet is filled with garbage. I think it sucks that private companies own what amounts to modern public squares. I think it sucks that we keep trying to apply old rules to new forms of communication. I think the amount of anger and hatred and vitriol in social media sucks. I think the dumb, predictable, banal comments in every linkbait or unoriginal thread on the internet suck. I think we can do so, so much better.

And, to be honest, it makes me a little nihlistic. Someone, out there, will respond to a tweet or something we wrote, if we’re lucky. And that’s on a service with a reasonable amount of discoverability. So what happens to blogs? What happens to things that sit far outside that discoverability? Well, it’s as if they don’t exist. You have to go looking for them. And who has time for that? And who wants to deal with the mobile web? And it’s like you’re shouting into the void. No one will hear you. No matter what you have to say. Isn’t that a depressing thought? It’s as if you don’t exist. So why write those words at all? Why would you devote your time to a medium that doesn’t appear to give a shit about you? How is it that we have all these social media sites and all we do is aggregate content from other social media sites? How did that happen?

We sit in our little boxes and stare at our little screens and consume endless streams of garbage. So the internet has become a new form of television. A screen we interact with passively. And we’re bogged down in ancient things. Software was meant to be pliable, flexible. And we still wrap our lines of code at 80 characters. And we still type into terminal emulators that support hardware which no one makes anymore.

So all the traffic flows into social media. Or, god forbid, inane hot-take generators like Medium. Everything is divorced from context. Content is posted over and over again, in slight variations, or none at all, in the one place humans have created which has the ability to remember everything.

I’m getting older. I’m getting tired. I don’t feel like learning Snapchat or WhatsApp or whatever is the temporary exit strategy for a bunch of bored billionaires, another silo filled with our ideas, our prose, our photos, our thoughts, our dreams. You’re never getting any of it back.

And maybe that’s the point. Maybe we all want this ephemerality. God knows I’ve thought about wiping all of my hard drives, for good, and starting over from scratch. A digital tabula rasa. But here, again, is our desire to apply old ways of thought to new ways of being: in an era where we try desperately to preserve and understand the ancient past, what little fragments we have, languages we cannot decipher anymore… we take the closest thing to permanence we have and make it all impermanent. We are terrified that someone will be listening, and so we make sure everything we create gets disposed of. Or reshared into illegibility.

The internet could have been something amazing. Now it’s just another advertising vehicle. A global pissing match.

I might be too cynical for all of this anymore.

The last thing we need is another white engineer’s take on how to build a lasting thing on the web. Another simplified something that accretes mass as it tries to reach profitability. Another Another messaging app. Do you really think the people who still can’t fix HTML or CSS or JavaScript or security in the browser should be making social media websites? Give me a break.

Things like Vine are important. Whether you like it or not, giving people six seconds or whatever to make you laugh, cry, or reflect, is art, is advancing the conversation, is giving people a voice. This cynical, Warhol “famous for fifteen minutes” world view is insipid and passive-aggressive, a mewling attempt trying to ignore a world that is sick of monomyths and unrealistic heroes. What’s wrong with being famous? What’s wrong with being famous for only a little while? If it’s better to burn out than fade away, why not let people do that in a six second video?

So fuck blogs. Blogs may be dead, but writing isn’t dead. And I need to continue writing. It’s a restorative process for me. It’s a necessary one.

I’m far from the first person to think about this. Initiatives like IndieWebCamp, and the re-de-centralization of the web, are striking back against the hegemony of the corporate bullshit web. I’m not really a part of any of those movements. But I do get what they’re after. And I hope one day we’ll have a place we can call our own, again.

prev Page 2 / 8 next