Creating Monster Mash


Last week I entered PROCJAM 17, where the goal is to “make something that makes something”. It’s a very relaxed week where a lot of people develop games or systems capable of generating content procedurally.

For those interested, you can try out my entry here!

The Goal

Jade Cocoon was a monster RPG where you could capture and merge the minions to create hybrids.

For this jam I wanted to return to a mechanic that I’ve explored a lot, but put a procedural spin on it.

The Result

  • Completed procedural monster generation: All monsters shown in the game are generated and animated entirely with code.
  • Completed monster merging mechanic: You can select two monsters from the menu and combine them to create a hybrid.
  • Completed battle system:  A turn based battle system where the enemies are generated randomly, with a chance of fighting multiple enemies at the same time. The game’s difficulty also increases with your winstreak, generating tougher monsters.

Procedural Monster Generation

The process:

  • Select a species from data
  • Generate a mesh using the species parameters
    • A mesh is generated per body part
  • Generate a skeleton using the species parameters
  • Apply a bone weighting algorithm per body part

Select a Species from Data

The base data that the generator selects from is a species pool. The game has 9 unique “species” including creatures like “Dog”, “Dragon” and “Spider” among others.

A species is a collection of ranges of values for properties like limb length, thickness, curves to determine limb shape, as well as how many of each limb to generate.

The generator takes a species, and from this it can build up a list of body parts. With this the mesh and skeleton can now be generated.

Generate a Mesh using the Species parameters

With a species selected, body parts are generated using the species constraints. The body part data gives some key information for the mesh generation.

To generate a body part, I essentially sample an elliptic cylinder that has had its radii altered by AnimationCurves. I sample based on a NumSections and LOD property. The NumSections property tells me how many vertices rings I will get from the shape, while LOD tells me how many vertices there are per ring, joining the vertices up into triangles is then just a matter of mathematics.

This video shows how the AnimationCurves are used to alter the shape that’s formed for each body part.

To generate the skeleton, I just select the origin and end point of a body part, the challenge wasn’t so much generating the skeleton as it was applying the skeleton to the mesh.

Apply a Bone weighting algorithm per Body Part

Bone weighting was tricky at first, there are some excellent gamedev articles on bone weighting algorithms. In the end, I combined the naive approach of distance weighting with the fact that I already know which vertices belong to which body part, so I can perform the bone weighting per part instead of across the whole mesh like some of the algorithms I found.

The distance algorithm typically goes like this:

  • For each vertex:
    • Compare the distance between the vertex and each bone
    • Order the bones by distance
    • Select the 2-3 closest bones, these are the candidate bones
    • Assign their weights using a fraction determined using their distance in relation to the other candidate bones

The problem with this normally, is that you end up applying weights for vertices to bones that aren’t directly connected to them (e.g. Part of an arm gets weighted to a bone on the torso.) Since my mesh and skeleton is generated per body part, I automatically know which bones are relevant to which vertices, and can immediately ignore the bulk of the bones for any given vertex.

Here are two demonstrations, one shows the naive bone weighting, while the other shows the same approach but with the limited bone assumption applied:



Monster Merging Mechanic

Having produced a monster generator that is completely data-driven, creating the merging mechanic was just a matter of mixing the data.

Applying this mechanic to the generation process also allows far more interesting looking creatures to be produced, because the mixing stage will also mix values like limb orientation, creating bone structures that weren’t possible from the base species list alone.

Here is a demonstration of the merging in action: On the left are the two inputs, and on the right is the resulting merged creature.

Battle System

Having spent the first 7 days on the procedural portion of the game, I was left with the weekend to put together a turn-based battle system. Much like the procedural monsters, this was something I haven’t attempted before, but I did have a few ideas about how to achieve certain aspects.

Ultimately the battle system had the following:

  • Speed-based turns
  • Attack/defense-based damage calculation
  • Animated attacks with events at key moments
  • Dynamic difficulty scaling
  • Multiple opponents


To start with, I created a BattleCharacter object and a BattleContext object. The BattleCharacter object houses data about a character relevant to the fight, while the BattleContext object contains all the BattleCharacters, keeps track of who belongs to what team and who is actively in the battlefield. If any of my other systems want information about a BattleCharacter, they get it by querying the BattleContext.

Speed-based Turns

This was the first aspect I thought about. The main inspiration for this whole project was Jade Cocoon, and in that game it was possible for characters to take a second turn under some circumstance.

Another case study I used for this was Final Fantasy X, in which speed played a big role in determining the order of play, going so far as to offer a timeline of future turns on the side, the best way to see the impact of speed is to target somebody with ‘Haste’ and observe how their name suddenly appears on the timeline a lot more.

To achieve this, I created the TurnTicker object. Imagine that the characters are in some sort of race, the track length is equal to the sum of their speed values, the following rules apply:

  • In one tick, a character runs a distance equal to its speed.
  • When a character reaches or crosses the finish line, it is their turn.
  • When a character passes the finish line, move them backward by a distance equal to the track length, resume the race.

With this ruleset, characters trigger their turn when they reach the finish line, faster characters reach the finish line first, characters that are exceptionally faster than their opponent will often get two or more consecutive turns before their opponent can get an attack in.

I described this as a race, and talked about moving characters some distance over time. If you haven’t noticed yet, this means I can determine who goes first by solving a set of linear equations. We have:

speed*numTicks >= speedSum

Meaning that numTicks is calculated like so:

numTicks >= ceil(speedSum/speed)

I round up so that I only get the tick count for ‘crossing the line’ since that is when we guarantee that it is their turn.

Some more rules:

  • If two characters cross the finish line at the same time, the faster character goes first.
  • If two characters cross the finish line at the same time, the slower character is added to a queue.
  • When querying the TurnTicker for the next character’s turn, the TurnTicker will check and exhaust the queue before calculating any further turns.

Doing the turns in this way also means that I can recreate the FFX-style timeline and show the future lineup of turns at any given time, this was something I didn’t get to show in-game on release but it’s trivial to add at this stage.

Attack/Defense-based damage calculation

I didn’t do anything particularly innovative here, as before I observed how other turn-based battle games such as Pokemon, Jade Cocoon and Final Fantasy do their damage.

In its primitive jam state, my game contains stats for Attack, Defense and Speed. However the goal would have been to include elemental damage and a difference between physical and ‘special’ attacks, as well as modifiers and status effects.

These stats are contained in a BattleStats object, which belongs to the BattleCharacter in a couple of forms: base stats, and buff stats. Base stats are the character’s actual stats in and out of combat, while the buff stats are temporary figures applied through attacking or powers (which I also wasn’t able to implement in time).

I created an AttackList for the game, which contained a list of AttackData objects. AttackData contained stats to be added to the attacker’s damage stats, as well as stats to be “inflicted” upon the enemy (added to their buff stats).

If I come back to implementing those, I will include the details here.

Animated attacks with events at key moments

While this system was a result of my lackluster animation scripts, it has some key functionality that make it very useful when I come to redo those.

I returned to the AttackData object to add an AttackSequence object, this is a data-driven object that provides AnimationCurves for the character’s height in the arena, as well as an interpolation value that moves the character between their ‘home spot’ and their target.

The AttackSequence object also contains a map of timestamps to strings. When one of these timestamps is reached, an event is fired off with the corresponding string as a parameter. This allows me to display damage values on-screen at exactly the moment of impact.

When I come to implement an improved animation system for the characters themselves, this will also allow me to message the characters to tell them which animation they should play at important timestamps (e.g. jump, get hit, dodge, etc)

Dynamic difficulty scaling

This was very rudimentary, but it was a good basis for keeping the game interesting when I didn’t have time to add things like an overworld or story to provide more wild encounters.

The game has a difficulty setting, it starts at 0, increases by 1 with every win and falls by 1 with every loss. The difficulty value affects 3 things:

  • The likelihood of encountering more than 1 enemy in the same fight.
  • The base stats of an enemy.
  • How many times the enemy gets merged before being added to the fight.

I said before that merging is a mixture of data values, this includes the BattleStats data. The player is encouraged to merge their captures because it maximizes their combat stats, they are also encouraged to do this because the difficulty scale increasing the enemy merge count means that the enemies get strong quite quickly.

The player is given an advantage at the start by being given a ‘starter minion’ that has been merged 3 times, making it significantly stronger than the first encounter. If a player somehow loses their first encounter (and therefore loses their only minion), they are given another, much stronger minion that has been merged 6 times.

As I said, this was very rudimentary. There are obvious balance issues to be considered, such as the player losing on purpose to deliberately get a much stronger monster. It is all stuff I would like to return to now that I’m not feeling so constrained by the jam.

Multiple Opponents

The TurnTicker determines whose turn it is, it does this regardless of which side a character is on. Thanks to that, no special behaviour was required for adding extra characters into the mix, I can probably allow for the player to bring multiple characters in as well, I just didn’t sort out a good UI for that in time (some might argue that I didn’t sort out a good UI at all!)

Future Work

  • Add more species
  • Balance the stats
  • Implement elemental damage and status effects
  • Rework monster animations – provide a system that creates sensible animations based on type of body part and context (which other body parts are on the same creature), encapsulate all of this in an animation class for the creature that switches between idle, attack, dodge, death, etc, poses when appropriate.
  • Improve UI, merging and main navigation preferably done with mouse instead.
  • Music and SFX

Thanks for reading!


SFAS Days 4 & 5

So day 4 ended up being especially busy for me, I was only able to get back-end improvements done to the project. The code was restructured to better allow for multiple level appearances and characters, since currently I was editing the prefab’s inspector variables manually to see change.

Over both days, here’s what I got done:

  • Restructured code
  • Created some more character and environment sprites
  • Improved shader code
  • Rubble spawns from broken rocks, coins can also be obtained this way
  • Score counter
  • Game states are back, and it’s now possible to lose the game

There are a couple of things I was asked to go in to detail on, I’ll try to do so on a break, that’s all for now. Next goal is to implement a high-score and total-score counter in order to unlock the extra content.

~ Oli S-L

SFAS Day 3

I took a break yesterday, then got back to work in the evening to add coins and our character’s “super move” which bursts through all the obstacles. Despite not putting so much time in to the project yesterday, a lot of interesting things went on to make all of this happen.

Making it Rain

The coins themselves were easy to implement with what I already had, the sprite is animated using my SpriteAnimation script, and Unity’s collisions take care of collecting the coin, but having the coin just disappear on you is boring. I wanted the coins you collect to fly in to the top-left corner where the score counter is going to be.

There are two coin prefabs in use: one to be collected by the player, and one “post-collection” coin whose only purpose is to curve to its destination and then vanish.

To curve the coin I wrote a BezierCurve script, you set it up with the coin’s starting position, a destination and some random point to the right of the screen

A rough diagram to show what the Bezier Curve is doing, ‘u’ transitions from 0 to 1 .

So this worked, the next issue was when to remove the collected coin from the scene.  If you’re familiar with Unity you’ll notice that the coins in the gif used Trail Renderers to create the yellow streak that follows their path. Removing a GameObject that has a TrailRenderer component attached will remove the trail abruptly.

The cost of aesthetic.

So instead the collected coins has a configurable value for their ‘end lifespan’, when they reach the end of the path, they will go invisible for this amount of time giving the trail time to catch up and finish gracefully, at which point the GameObject is then removed.

Super Move

In addition to collecting the coins, I want for a special powerup to exist in the game, when collected it sends the player in to an over the top rainbow-charged frenzy that allows them to charge full speed through the game, destroying all the blocks in their path.

This was again done with the use of a TrailRenderer and ParticleSystem, probably the most challenging part of this for me was tackling shaders, something I’m not familiar with yet.

Unity’s standard shader (left), and then two of mine.

The Unlit/Cutout shader was my first test run with Unity shaders, since it was bugging me that I had to use a lit shader in order to preserve the transparency on my sprites. If you’re looking to get started quickly with shaders in Unity, Dan Moran’s video tutorial offers a very fast review of the basics, more than enough to get started (and then I’m sure there’s plenty of more advanced documentation of writing shaders out there)

The Unlit/RainbowPower shader was the result of plugging random numbers in and experimenting with the _Time and _Sin or _CosTime variables (Unity docs on built-in shader variables, a great resource)

I plan to experiment more with shaders as I’m starting to realise just how powerful they can be. One simple tweak I would like to make is having the rainbow shader transition through the colours more frequently.

All that was left with Super Move effect after this was to attach the shader to the trails, particles and player, then activate it at the right moment.

Breaking the Terrain

This was probably the toughest to get right, the approach is straightforward but it’s easy to make a mistake on some of the lower level parts.

  • We find the tiles surrounding the player
  • If they are solid, the Wave needs to be updated to set them to non-solid.
  • The TileMap for that Wave then needs to update the appropriate tiles to match the changes.

That last point is where a few attempts were made to get it right, remembering that I wrote the TileMap so that it would auto-tile: When a block is removed, the surrounding tiles must also be updated to no longer connect to it.


On to Day 4

I was actually up until 4am finishing off most of the stuff above, and I managed to optimise a few of the texture handling scripts while I was fixing the terrain breaking mechanic. That said I’m now ready to continue!

Today’s goals are to add rubble for when a block is destroyed, a get game states reimplemented (the skeleton project we were given to start us off has this set up already, but I disabled the original scripts while I got my concept to work.)

As always, you can direct your feedback or comments to my Twitter @Jindont.

~ Oli S-L





SFAS Day 2

View post on

After yesterday’s work, I ended the day with something playable! The level generator adds waves as the player progresses, and removes waves that have strayed off-screen. The player must tap to swap surfaces, avoiding all walls and future obstacles.

I’m going back to work today as I’m ahead of schedule with this project, so I expect to get less done this time, but my next two goals are 1) Make it look nicer, and 2) add obstacles and collectibles!


The Level Class

The Level class is responsible for managing the waves, and for retrieving tile data for the player. It iterates through the existing waves (which maxes out at 3 before they start getting removed) until it finds the wave that the player is on.

Waves have a width, height, starting X position and an array containing their collision data. So checking that the player is on a specific wave is as simple as making sure they’re between startX and startX+width. If the Player wants a tile, it calls level’s GetTileAt(x,y) function, which then calls the appropriate wave’s GetTileAt(x,y) function, and returns that result.

Currently, the player only requests 3 tiles from above or below its current position (depending on the direction it’s falling). If a resulting tile is solid, an AABB collision test occurs between two rectangles formed from the player and the tile positions and scales.


Frog Bro

The current protagonist!

Coming from a Flash background, I’m not a huge fan of Unity’s animation tools. I find it very slow and overkill when trying to animate a simple 2D sprite, I’m assuming it’s meant for bigger tasks than that but it remains a painful process for cases like this.

So I wrote an AnimatedSprite script, it takes a Texture in the form of a spritesheet like the one above, and an array of animation data (name, frames used, and speed of the animation). The object can then be called on to set its animation to whatever you gave it, it will select the appropriate frame from the spritesheet and draw that on to a Quad.

I’m quite pleased with the result of this script, and a change of parameters is all it takes to implement a new sprite. When I have more time I’ll probably polish it and release it here.


This is all I have time to write for now, later today I hope to make a start on collectibles but we’ll see how that goes. For queries and feedback, reach out to me on Twitter @Jindont!

~ Oli S-L

SFAS Day 1

My 2 weeks started yesterday for the second round of the Search for a Star competition. The competition is a nationwide programming challenge for students and graduates that attempts to mimic an application process.

The second round gives contestants 2 weeks to make a game in Unity and publish it to the Windows Phone store. Last year my project got me a ticket to the final round interview, which was a miracle in itself given how restricted I was working on a slow, near broken laptop. I even had to take it to lectures to make progress as it was the only way I’d have time to finish everything. It was also one of my first times really using Unity.

Not my best work, but for a 2 week time-limit I was more than pleased with it!

Upgrade Your Workflow

This year, my placement has afforded me a proper setup, complete with a high-end desktop and multiple monitors, in addition I’ve booked time off work to focus on the project for its duration!

Having a faster machine has also allowed me to spend time looking at workflow improvements before going ahead with implementation. In my first blog entry I was looking at creating Tilemaps out of meshes, and said that I’d like to create an editor to allow for user created tilemaps.

So that’s what I focused on for Day 1, I rewrote the tilemap scripts and scriptable objects infrastructure, then proceeded to write an EditorWindow with very basic functionality for creating a level (or “Wave” as it’s called in this project)

Draft 2D Level Editor

It’s no Tiled but it will certainly do.

So how is it used? First you set the dimensions of your wave, and the window will resize itself to accommodate a grid which fits your given size. Left-click dragging will create black ‘walls’, while right-click dragging will erase them. All that’s left then is to enter a name and click ‘Save Wave’, Unity then creates an asset out of your drawing.

The ‘Wave’ asset, the string property is an artifact from not having the level editor originally, you can change the level with this provided its length agrees with the width and height.

Under the hood, the window itself works by calling DrawRect() and referring to a 2D array of integers to determine which colour to use for each rectangle, the window automatically resizes as you change the dimensions of your level as well.

Since my tilemap script attempts to stitch edges and corners together algorithmically, I have no need for a tileset display or the ability to see what tile you’re placing in this version, though it wouldn’t be too tricky to implement and certainly something I would add before releasing any of it.

On to Day 2

Today’s work will involve getting a factory in place to generate the level, the level is made up of ‘Waves’ which my editor is used to create. A Wave is just a segment of the level, I’ll create a large pool of preset waves which the factory will then choose between when it comes to generate the level.

Level will be assembled from randomly selected presets, Player will ask Level if it’s colliding with any of the tiles in each Wave.

Having an editor allows me to ensure that the waves are surpassable, and also allows me to do things such as pick viable locations for collectibles such that they will never be unreachable.

Hopefully my post tomorrow will give more of an idea of the actual gameplay as I wrap up on this workflow business.

If you’re interested to see more about the Tilemap solution, see my previous blog post. If you have questions or feedback, feel free to reach out to me on Twitter @Jindont!

~ Oli S-L

Tile Maps in Unity

I’ve been experimenting with Unity a lot lately. I’ve usually worked with 3D prototypes but this weekend I wanted to investigate the work that was involved in getting something tile-based up and running.

I was going to do an introductory blog post first, but I’ve made some interesting developments with this so I thought I would document it all here now.

Tile-Based Anything in Unity

The main annoyance I’ve had with trying to do anything tile-based with Unity is that a lot of the documentation and tutorials I’ve read seem to steer you in the direction of using GameObjects for each individual tile. While this approach is simple and easy to follow, I don’t feel that it scales well, and I generally dislike approaches that clog up the Hierarchy this much (granted steps can be taken to organise it properly)

Fortunately, there are some techniques that can be learned to get around the use of GameObjects per tile, this fantastic tutorial series by quill18 introduces you to the concept of creating meshes programmatically, and even touches on extending the editor, a technique that I think is essential to getting the most out of Unity.

I followed enough of the series to get a basic understanding of the process, and set off to produce this:

What we have is a script component in which you specify your level’s dimensions in tiles, along with the scale of each tile in Unity units. The script will take this, generate a mesh and a texture to produce what you see on the left. quill18’s tutorial also shows you how you can add a custom element to the component’s inspector in the form of the ‘Rebuild’ button, which in my script allows you to generate a new level, the changes are also visible in edit mode.

The Process

The end goal with this was to produce something seamless with a very minimal tileset. Something like these which contain just enough information to construct what you see in the above screenshot:

These have of course been scaled up, each tile is 16×16, making each tileset 48×48.

The map is an array of 1’s and 0’s, where 0 is air and 1 is a solid block. Initially the mesh was only textured to show solid tiles, with no inclusion of the edge tiles. Below is a screenshot comparing this original look (foreground tileset) with the new, auto-tiled look (background) which gives all adjacent tiles a connected appearance:

Getting the auto-tiling to work was an interesting challenge on its own, and one that still needs some work before it will work with any tileset I give it.

Auto-Tiling Our Level

The first step in my approach was to assign numbers to each of the corner and edge tiles surrounding the center ‘wall’ tile, like so:

Then, for each tile in our level’s array, we compare its surrounding 8 tiles and add the corresponding number from the above image.

int getAdjacentTiles(int x, int y) {
    int value = 0;
    int center = 0; // have we reached the center tile yet?
    for (int i = 0; i < 8; i++) {
        int currentX = x + (i%3) - 1;
        int currentY = y + (i/3) - 1;
        if (currentX == x && currentY == y) {
            center = 1; // for offsetting i after the center tile.
            continue; // skip the center tile
        if (tileOutOfBounds(currentX, currentY) 
        ||  levelTiles[currentY,currentX] == 1) {
            value |= 1 << (i - center);
    return value;

After getting this value for a tile, you can determine which edges/corners need to be added by checking if the expression:

value & (1 << i)

is non-zero.

In Unity, stitching adjacent textures together on to a single tile was easier said than done, although I could be something crucial in Texture2D’s functionality. Traditionally, you can use Texture2D’s getPixels() and setPixels() to effectively combine portions of textures together. This is fine so long as you don’t intend for your pixels to overlap, but in my case this was not so, and as a result the transparent pixels would overlap the colour.

I got around this with a naive rewrite of the setPixels function, which attempts to ignore ‘transparent’ pixels so that only the non-transparent parts of an image are overlayed:

private void setPixels(ref Texture2D texture, int x, int y, int w, int h, Color[] p)
    for (int i = 0; i < w* h; i++)
        if (p[i].a != 0) // if the pixel to be written is solid
            texture.SetPixel(x + (i % w), y + (i / w), p[i]);
            // this was a hack to ensure that the image wouldn't
            // lose its transparency, like I said it needs work.
            Color c = texture.GetPixel(x + (i % w), y + (i / w));
            if (c == Color.white || c == Color.clear)
                texture.SetPixel(x + (i % w), y + (i / w), Color.clear);

This is something I will come back to, since I’m sure there’s going to be a better way to get around this then what I went with. That said, I’m very pleased with the end result. I have a script generating a mesh, a random level and auto-tiling the mesh according to that level’s data.

What’s Left?

The next step with this is that I want to extend the editor further to allow the user to draw the level on to the mesh themselves, at that point I may release what I’ve got so far for others to mess around with.

~ Oli S-L