Game developer & web programmer
This is a brief, incomplete list of projects that I have worked on in my spare time, mostly for my own edification and amusement. The source code for most of them is visible in my various GitHub repositories.
World generator is a Unity project I made partly to learn about how the Unity Terrain asset works, but also to experiment with procedural terrain generation techniques. It randomly generates continents, surrounded by ocean and divided up into biomes. Here are some examples:
The terrain is randomly generated when you first load the application, but if you don't like what you see or become bored of exploring one world, you can click the "Regenerate" button in the top left to generate a new world.
You can click anywhere on the terrain to mark a location and bring up some information about the region / biome that the location is in, including its name, area, rainfall and temperature. More information about what those parameters mean and how they're generated is described in the Method section, below.
The "Minimap" below the Regenerate button cycles between three modes:
The first thing the generator does is to create a random heightmap that dictates the shape of the terrain. While figuring out how to approach this, I created an AbstractValueMap class that let me swap in various possible approaches for generating heightmaps. I experimented with a few different options:
The next step is to assign biomes like "Taiga" and "Desert" to the map, ideally in a consistent and broadly speaking realistic way. My implementation of biome generation is inspired by the ideas described in this article on Gamasutra , although my own implementation differs slightly. It is still, however, fundamentally based on Whittaker's biome type classification scheme and uses a combination of rainfall and temperature values to determine what biome a given area of the map should have.
Rainfall across the map is determined with a map of values produced by Perlin noise. In this scenario, the smooth, rounded blob shapes produced by Perlin noise actually work well, producing contiguous wet and dry areas that translate into biomes of a good variety of sizes.
The temperature value of a map tile is itself based on two values: its height above sea level and its latitude (effectively, its y and z co-ordinates). The precise calculation (visible here) is a weighted average of the two values after some tweaking to try to bring the coldest and hottest latitudes nearer the middle of the map so they have a better chance of being on dry land. This means that the North of the map should be colder and thus have snowier biomes than the jungled, tropical South, but that mountaintops should also be colder than land on the coast.
Each map tile is then assigned biome weights, based on where its temperature and rainfall values lie on this chart:
That chart is actually generated at runtime from values specified in this 10*10 array (hence the blocky shape of the biome definitions), with values that fall between those specified in the array determined by bilinear interpolation to give smooth transitions between neighbouring biomes. This means that a tile might fall at the intersection between biomes and be (say) part Taiga, part Snow and part Plains, with varying weights.
There is also a special biome which doesn't feature on this chart: Ocean. That gets applied on top of the temperature/latitude biomes based solely on the tile's height above sea level, meaning that anything underwater is entirely "Ocean" and that the coasts blend (rapidly) into the land biomes as the terrain rises above the waves.
The full calculation for the biome weights for a tile is visible here.
Each map tile is then assigned a "parent" biome, or region, by using a flood fill algorithm to group together neighbouring tiles with the same top-weighted biome type (my implementation of this can be viewed here). These regions are then given a name, based on their biome type and how big they are: a large Forest region will be called a "Forest", but a smaller one might be a "Copse" or a "Grove". The actual names given to regions are assembled randomly by combining vowels, consonant-vowel pairs and a predefined list of other pronounceable bigrams like "sh" and "nd".
Once all the biome information has been generated, it must actually be applied to the Unity Terrain object for the user to see. The terrain is painted with a collection of textures, one for each Biome type: mud for swamps, grass for plains, seabed for oceans and so on. These textures are blended using an alphamap (generated here) that describes with what opacity each biome's texture should appear at a given point. This is where preserving the weight values assigned to all biomes for every map tile is useful: we can say that a given tile on the edge of several biomes should appear to be fading between, say, grass, mud and leaves.
There's one additional texture that gets applied to the alphamap, as well as all the biome textures: a rocky "cliff" texture. That gets blended in on top of the relevant biome textures for tiles located on particularly steep areas of the map, which helps to give the impression of rocky mountainsides and coastal cliffs, even if the way that the heightmap works means that one can never have truly vertical cliffsides.
Finally, some trees get scattered onto the map. Unity's Terrain object handles all the rendering and LODing for the trees: all the generator needs to provide is a list of tree locations, types and scales. To build that (the code for which is here), it follows the frankly fairly inelegant method of just picking 50,000 randomly chosen locations on the map and, if it happens to be in a Forest, Taiga or Jungle biome, placing a tree there of the appropriate type (deciduous, pine or palm, respectively). Trees are scaled based on the biome weight, so trees at the edge of a forest should appear to be smaller than those in the middle.
Pretty much all art assets used by World Generator - the terrain textures, the trees, the water shader, the skybox - are from free packages on the Unity Asset Store.
The location icon (the one that appears when you click on something) came from the ever-dependable game-icons.net.
In the current implementation, the entire generation process takes place on the main thread, meaning that the entire game "freezes" until it completes (this usually takes less than 5 seconds on a typical PC). Obviously, that's not an ideal user experience (and would be unacceptable in a fully-produced game), so it'd be nice to arrange the code to perform the generation process on a separate thread, only writing the completed data to the terrain object after completion.
As I mentioned at the start, this project was at least partly intended to help me learn the features of the Unity Terrain object. It also served to teach me its limitations. In particular, it's based on the assumption of a 2-dimensional heightmap with vertices arranged in a regular grid. While it's therefore not feasible as a modification or extension of this project, in a future landscape generator, I'd like to experiment with more sophisticated models for terrain shapes, like the method of using Voronoi regions to place vertices discussed here, which would allow more irregular biome shapes with fewer vertices (and thus better performance). Still better (though still more complex) would be to use a voxel-based approach like Minecraft or No Man's Sky, allowing for caves, overhangs and bridges.
I'm particularly unhappy with the place names generated by the current implementation. If it were to be used in an actual game, I'd want much more flavourful place names - particularly if I were to add towns and cities to the map. One approach would be to assemble them from a predefined grammar using a system like Rant (or Phable!) to create names that would fit in a typically tropey fantasy story: Mount Shardfrost, The Greyleaf Forest, Chokemist Marsh. Alternatively, for names that are less hackneyed (and arguably less accessible), but still consistent, I could use a system like the one described here to generate a fictional "language" that is then used to name all the biomes and settlements.
Fuel Me Once is a game of triangulation*, wonky driving and oil extraction that I made in Unity in 72 hours for Ludum Dare 29, which ran from April 25th-28th 2014. It was both my first (non-tutorial) Unity project and my first Ludum Dare entry.
The aim of the game is to use detector beacons to locate oil deposits beneath the desert sands, so that you can plant a drill atop them and deliver the oil they extracts back to your central base to sell it.
* - Well. Strictly speaking, it's trilateration, not triangulation.
An Xbox 360 controller will probably improve your experience with Fuel Me Once, but it's not required.
Detectors will emit a "ping" if their scan pulse passes over an oil deposit, and the pulse will leave a green ring behind indicating the range of the deposit from the detector. By combining the information from multiple detectors, you can pinpoint exactly where to target your drill.
A drill that is dropped correctly onto an oil deposit will start to produce oil! Carry oil in your spare inventory slots back to the shop to sell it for cash. The price of oil generally increases over time, and drops slightly every time you sell some of your stocks, so pick your moment to get the best price.
You start with 3 detectors, 1 drill and $50. Detectors can be bought in packs of 3 for $5, but another drill will set you back $100. If you miss with your first drill, you'll not be able to afford another, so make sure you're certain before picking your first drill site.
Make as much cash as you can before the time runs out!
The inventory icons (ie. the only thing in the game that's obviously not programmer art) came from game-icons.net
Most sound effects were just noise produced by the ever-useful sfxr, though the cash register chime came from freesound.org.
In general, players have praised the concept of Fuel Me Once, although the process of using three or more detectors to pinpoint the location of oil deposits turned out to be much less intuitive than I expected.
The most obvious problem in Fuel Me Once was the controls. I decided early on to make the player character a vehicle, to save me having to animate any of my hastily-produced SketchUp models. I then got bogged down in the physics almost immediately, trying to find some values for Unity's Wheel collider that felt as fun to drive as the buggies in Renegade Ops. Although the final result is (mostly) fine after a little practice, I never quite found the sweet spot.
It's possible, however, that the reason people complain about the controls actually has more to do with the layout of the central platform, to which the mechanics demand that you return to shop for gear and sell your spoils. While driving up a ramp at full speed to leap into the air over the platform and sell all your oil is a genuinely satisfying interaction, navigating your vehicle with its large turning circle to the precariously-placed shop items in the corner of the platform is surprisingly fiddly and frustrating, especially when approaching the platform from the same side as the item you want.
During the jam, I did add a self-righting feature which, if you manage to flip your truck onto its back or side, should after a three second delay unceremoniously right your vehicle and fling it into the air. Even so, far too many playthroughs end with the truck stuck between the corners of the platform or bottomed-out on the lip of a ramp.
Phable is my attempt to port Kate Compton's Javascript procedural story-generation library Tracery into PHP. It takes a JSON file that specifies a "grammar" containing all the sentence fragments that are used to generate an entire story and generates random "traces" (paths) through that grammar. The result is a story (or a paragraph or a sentence) that's different every time.
I've written a few demonstrations of Phable in action: