Recent Posts


Post Types


Authors


Archives

Zzap - Maze bonus levels!
Author: HS_Dave
- Posted on: 05/09/2017
Post Type: Blog Entry


I should probably stop saying "I'll start blogging more regularly" as despite best intentions I never quite manage it! If perhaps I do not mention it then when I DO post more regular it will be a pleasant surprise :) This is not a personal blog post today but a development one - but for those who care and know any of the reasons I become very busy sometimes please know that my mum is indeed home and now receiving a proper care package at home at last.

Zzap! Wait, where's Drop? Drop is coming I PROMISE! But the user response to our LD39 gamejam project Zzap was SO positive we just had to continue it and polish it up in preparation for a real release. As the talented Tommy Brett is willingly working alongside me on this still I really would be a fool not to prioritise it at this time. Overall it's good for everything, more games for everyone!

Today I have been working on a maze generator for Zzap. My idea is to have maze levels as bonus levels the player can discover and get lot's of good treats from. The algo is a simple backtracking generator but it has been really effective for what I've wanted to generate this time. These levels are full of extra points to collect and can be very valuable - but like all levels in Zzap they CAN kill you if you are not paying attention to the path you are building!

Procedural generation is a particular passion of mine so it's great whenever I get to work on stuff like this. In the past I've worked on generating continents for an overworld and dungeons for rogues - you'll see a lot more procedural content in various upcoming projects!
LD39 Game Jam
Author: HS_Dave
- Posted on: 01/08/2017
Post Type: Blog Entry
Ludum Dare 39

I have tons of news about Drop Dimensions, new features and tweaks as the game finally nears completion. I would probably of been putting the finishing touches on some this weekend and writing the (much overdue) blog post about it last weekend.. except something else was happening that weekend.

Ludum Dare #39 - Global Game Jam!



This is the first time I've ever taken part in LD and, as an aside, also my first time working with the Unity engine. I had a complete blast working with my friend Tommy for a 72hr solid stint to see what we could make. The theme for the game jam was "running out of power" and our game is called Zzap.

In Zzap the level contents are randomly generated (for better and sometimes for worse.. but we only had 72hrs!) and the aim of the game is to connect power from the start node to the exit node. The game is played on a grid of sorts and powering each tile costs varying amounts of power. Sometimes getting to the level exit can be quite easy.. but collecting all the points and power nodes is a completely different matter.

The programming was split up between the pair of us fairly evenly. Tommy also went to town working on the music, sfx and UI and is responsible for the awesome power-beam code. I did my best to create our 3D assets, textures and related effects. Having someone who was experienced with Unity and able to answer questions as we worked was a serious boon and I doubt I would of been even half as productive if I had been alone without that!

Tools I personally used for this game were:

Unity 2017 (free)
Visual Studio 2015
Adobe Photoshop CS3
Blender
Notepad++

Tommy uses Reason as his music DAW of choice.

Special mention here for http://realtimeboard.com which was a really useful tool for collaborating remotely! Free for little guys like us too!

I learned a ton of stuff during this experience and I'm REALLY proud of the game we created. We will definitely be refining this game and seeing where we can take it next.

You can check out the project and, if you like, rate it at: Zzap @ LDJAM39

If you just want to see it at its best then you can grab the binary from: Zzap v2 @ googledrive which is a SLIGHTLY more polished version (has a few extra effects etc) that was sadly finished not quite in time for the deadline (I had to go to work on the last day mind!)

Or, finally, here is a youtube video for you.



Now I'm going to go escape screens for a couple of hours, catch some pokemon and find some lunch. Back to normal programming from this evening!
Birthday Shenanigans
Author: HS_Dave
- Posted on: 22/06/2017
Post Type: Blog Entry
Hi all, just a quick update!

Drop Dimensions is finally nearing a beta phase! In fact a few people already have it and the process of squashing the unexpected bugs has begun. For example I really did not see "game crashes if ran on Norwegian computers" one coming ;) I'll do a proper update about Drop (hopefully with some shiny new screenshots/vids) soon.

In other news its my birthday this weekend! My lovely wife has managed to collude with some friends and family to provide me with a new core for my dev workstation so there will be a tiny bit of down time whilst I upgrade to a new Ryzen 1700 core and reconfigure the dev environment - pretty excited about it though! I will also be attending a 3 day LAN party this weekend as a birthday treat so I'm not sure what work will get done but.. worth it ;)

See you on the flip side!
Loot Boxes!
Author: HS_Dave
- Posted on: 31/05/2017
Post Type: Blog Entry
It can be a challenge to find ways to add value to a game as conceptually simple as Drop Dimensions. On one hand you want to keep things simple, not bloat it out or spend too many dev hours on features that give back little and on the other hand you want to give your users everything you can.

One of the ways I've decided to add a little value to your play time in Drop Dimensions is with Loot Boxes. These are given freely to the player for completing certain daily (or weekly) challenges such as getting a score above some target amount. Then, when opened, they give back either in game currency of varying amounts or perhaps fully unlock a character or stage straight out. Got a duplicate? It gives you the in-game currency value of the item you got instead so you can buy something else from the in-game shop. The trick with designing this is trying to make sure the player feels like they are getting extra rewards as prizes rather than "you must earn loot boxes to progress". Until today loot boxes did not even exist in the game so I can assure you the game is designed to be played without them and is balanced in that way!

But it does open some interesting discussion about micro-transaction possibilities. It has been suggested to me that I allow people to purchase loot box packs for real life currency in app and it is again something to umm and ahh about. This game REALLY is NOT pay to win - rather it's play to win. Being able to purchase loot boxes will help you to collect all the unlockables faster it's true but that should give you no distinct advantage in game when it comes to the leaderboards etc. But I feel some people would see "in app purchases" and immediately make assumptions about what that means. Of course I want my apps to generate revenue and pay my bills etc but ultimately I want the players to feel valued and enjoy the experience.

Loot boxes are in! They are fun and free. I'm waiting on some real art to replace my programmer art for the boxes and interface but it's all there :) But should the player be able to purchase additional boxes for small in-app fees?

I'd say reply with your thoughts but I never got around to adding comments to my blog scripts :) However if you have an opinion on this why not drop me a line on twitter @HS_Dave and let me know what your opinion is!
Collision in Drop Dimensions
Author: HS_Dave
- Posted on: 06/05/2017
Post Type: Blog Entry
The past few dev days have been spent working on the collision in Drop Dimensions. The original Drop used a very simple tile based collision which functioned, sure, but was less than perfect. It was possible to skip over gaps in the floor by moving too fast for one thing which in a game where survival depends on you going DOWN was a big problem.

It quickly became an even bigger problem in Drop Dimensions because the player characters are larger (twice the size infact) and the inclusion of different characters of varying shapes really meant it was time to overhaul the system. What I needed was a pixel-perfect collision system so that is what I've written. Its feeling quite nice and I'm happy with the turn out! For the curious amongst you the rest of the blog post will be about how that works. I wont bloat out the post with code but give a quick overview of the system. I've put in pictures :)

The process can be split into three headings:
-Collecting Collision Data (init)
-Collision Detection
-Collision Response

Collecting Collision Data

The first step is gathering the pixel data for the character that has been selected. Most graphics libraries (I am using MonoGame for this project) provide some sort of method to read the pixel data from a texture. It's usually quite expensive on the CPU so it is something you only really want to do once if possible. I chose to grab the data when the level starts - if I had done it when the game first loads it would mean no delay to grab data in the future but the more HD characters I added the more ridiculous the memory requirements would of become. Here was where I hit my first snag: My character sprites are large, HD, animated sprite sheets. The game engine renders them at different size to the source image depending on what is going on. The character preview for example has a very large render and in game the character is scaled down to fit the world. That means the source pixel data is completely inappropriate for collision as its way too large!


(source image size versus scaled size [what the player sees])

The solution I went with was actually very simple. I created a render target (a special texture you can draw things to) that was the correct/final size the character would appear in the game world. I then iterate through the different frames of animation stored in the character sprite sheet(s) and draw them to the render target at their scaled resolution. I then grab the pixel data for the frame and add it to my scaled pixel data array for the current source sheet. At the end of this process I have a completely accurate array of scaled pixel data.

Collision Detection

When you have all that information to look up detecting collisions becomes fairly easy and not that different from tile collision. I still use tile-based lookups for the world itself as I know in this game every collidable object is the same size as one world tile so doing a pixel lookup on the world data would be a complete waste of time. So doing a pixel to tile collision detection becomes the simple case of:

Fetch pixel data for players current animation frame
for each pixel in the data..
-Is it transparent (alpha == 0)? If so, skip to next pixel, no collision
-else get the position of this pixel in the WORLD by adding the players world x/y position to the pixel x/y
-does the pixel world x/y exist inside a tile?
--if so collision detected
--else move on to next pixel, no collision here

The "fetch pixel data" stage has a lot of potential optimisation. The first thing to note is, fortunately, character sprites in in Drop Dimensions do not get rotated at runtime. That is a big saving in headaches! But they DO get flipped. If a sprite is flipped (mirrored on either x/y axis) then you simply have to read the pixel data backwards and job is done. Now you've got your data reading well the next step is to make sure you only read it when its needed. How many times will your collision routine be called per frame by different parts of the engine? Maybe once, but likely lots. Reading out the same pixel data every time is an expensive waste. I made sure to track what frame we last requested pixel data for and I store that pixel data in a persistent array named something like LastFramePixels. If another request for the data comes in and the player is still on the same frame as the last request then it simply returns LastFramePixels again without updating it at all.


(in this image the gray represents an area the algorithm is checking inside for collisions, the blue is world tiles that are within that area, the magenta is pixels in the player sprite which are transparent and the inner gray are player pixels which can collide)

Collision Response

How you respond to a collision when it has been detected will vary greatly game to game. In Drop Dimensions I've opted for a more handcrafted situational approach than a one size fits all routine. I chose this because the simple design of Drop means there are not many edge cases to catch and it allowed me to tweak the feel of the game to just "feel nice". One thing that became quickly apparent is sometimes pixel PERFECT collision felt.. not nice. One character, a panda who moves around the world by rolling, has two cute ears sticking out the top. But whenever she rolled onto her head the pixel perfect routine would push her up and then down again and then up... and then down. It started feeling jerky and unpleasant.

So maybe it was a waste of time and I should of stuck with tiles? Well no. Some of the humanoid characters are quite tall and thin and when they try to drop off the edge of ledge but can't unless a full tile width over despite "looking" like they are stood on thin air.. well thats bad.

Solution? I modified the collision detection method to take two new parameters that specified if the X and Y axis should, independently, use pixel or tile based collision. Because my collision response is situational this meant I could finely control how each situation behaved. For example when its trying to adjust your vertical/Y axis for floor collision it uses Tile based collision for the Y and pixel based for the X to give you a consistent "ground level" but pixel-perfect pass through for the width of the character.

A few more modifications were made that allowed me to specify WHERE to check for collisions (anywhere, to the left, below the player, etc) and this means when moving in a certain direction etc its only ever looking at things relevant to what is happening. This felt really nice to play.

Heres a GIF demonstrating it all in action. Purple = player collision area (sometimes tile based, sometimes pixel, etc), green = world tile that is worth "considering" for a collision. Red = this tile caused a collision.



And now you know what I've been up to lately and more than you'd want to know about how collision works in Drop Dimensions! :)
Drop Dimensions
Author: HS_Dave
- Posted on: 24/04/2017
Post Type: Blog Entry
So we're all familiar with "fall down" style games these days. You are usually some object thrust into a world that is forever scrolling upwards and you have to find your way down to prevent yourself being pushed off the top of the screen.

This formula did not really change at all when I created Drop for windows phone 7 several years ago. Thanks to the work of Elin the art was slightly more polished than most fall down games and a few additional features such as powerups (speed up, slow down, world freeze, etc) and persistent online leader boards made it slightly more interesting than your average fall down clone but not by a massive margin.

These games can be fun to play for a few minutes but there is not a lot to them and long sessions are probably going to begin to drag eventually. I started to wonder what could be done to make these games more engaging without significantly changing the nature of what they actually were. It's okay that the average play session isn't massively long as long as the time spent was enjoyed.

From this the design for Drop Dimensions was slowly crafted. It was (and still is) a constant battle of feature ideas and feature cuts to try and balance interest and simplicity. It's a slightly faster game than Drop was and coupled with the increased speed we've added columns that block the player from moving in a certain direction. Some columns can be bashed apart with a new dash move but some are indestructible. To balance the increased difficulty this presents the world now supports a wrap-around feature so if you move off the left of the screen you will appear on the right and vice versa.

You can still die fairly easily but you'll always see during your last moments that way you could of taken to escape. The levels themselves have a larger variety of powerups and obstacles ranging from bear traps to concussion mines. The whole idea has been to try and create a more interesting gaming experience without over complicating the simple formula or making it require a large investment of time to play in one sitting.

Another aspect that has been focused on is game setting. I wanted to prevent everything from becoming too "old" too quick and started toying around with the idea of levels with their own graphical themes. What I did NOT want was to interrupt the players game at any point with an "end of level" or similar event so what we eventually settled on was this concept that you were trying to survive in an unstable multiverse where dimensions would repeatedly collapse on you. Survive long enough on a specific level and the dimension you are in will start to fall apart until eventually it collapses and hurls you into a new dimension (level). The transition only takes a few seconds and helps to prevent things from becoming boring without interrupting your game.

Finally, it's not just levels/areas that belong to a specific dimension.. but playable characters too. I really wanted to add more in-game persistence beyond just the leader boards so you can feel you are achieving something even if just a short play session. At the end of each session your final score gets converted into in game currency which you can spend to unlock new characters to play as. This is NOT a real money transaction but just a way for you to convert your game time into new unlockables to enjoy.

Development on this game is very advanced already and I look forward to showing you media from the alpha build soon! I intend for it to be available on all major mobile devices and POSSIBLY PC. I play test it on PC and it certainly works well.. but I keep asking myself: does it belong here? :o
The last year (and a bit)
Author: HS_Dave
- Posted on: 19/04/2017
Post Type: Site Update
Well, it's about time I wrote this blog post.

Being a solo indie developer can be hard. If something else crops up in your life that requires your full focus then the dev WILL suffer, there is no team to carry it and no one to cover for you. The last few years have been some of the hardest in my life.

13th of Nov 2015 I received a phone call whilst at my day job (I am a orthotics technician) asking me to rush home and drive my father to hospital (my mother is disabled). The next day he was diagnosed with liver cancer. The next few months of my life were spent looking after mum and visiting dad as they assessed treatment options. At first it looked like they may be able to do a life saving operation which they EVENTUALLY (march) attempted after many ridiculous delays (such as surgery computers crashing, doctors strikes, etc) but they had found the cancer had spread and there was nothing they could do. He was still fairly strong and started a course of chemo which he was responding well to.

During May that year my mother went into hospital for a "routine operation with complications". That it to say my mother was a complex example of the situation but the operation itself should not pose too many risks. Sadly, during this operation there was an accident and part of her bowel was split. They performed an emergency repair, stitching the wound closed and transferring her to more long term care. That evening whilst she was laying in the ward the stitching came undone and NEARLY resulted in her death. She was moved to intensive care after another emergency operation and somehow made it back from the brink. Just. At one point we were told it was probably time to say our goodbyes. But slowly her condition improved and her strength slowly returned although she is still, to this day, bed bound at home unless carried to a special wheel chair. Prior to the surgical accident she had limited mobility using walking supports.

But as she grew stronger my dad sadly grew weaker. On the 28th of January '17 his story ended and we said goodbye. That is still a hard thing to write and has made me put off this post for several weeks.

As you can imagine, during this period I have not got an awful lot done. I can thankfully say it has not been a complete stand still! Work has been going on whenever I've found the mental strength. But the limit of my strength has mostly been reserved for looking after my family and myself.

On to more positive things then.

I love game programming. I love working on projects that I have designed. Even before 2015 hit I was not feeling satisfied with the level of time I had to work on these things. This year my wife and I decided it was time for me to go part-time at my day job so I could focus on my passion more "officially" rather than just in the evenings where I had some energy left. This is starting with just one day a week, an arrangement that began last month. Having an extra whole day where I am fresh to work and ALLOWED to work is liberating and making a massive difference to the amount that is getting done!

The discipline required is hard - absolutely. But VERY rewarding. You can expect to see more regular blogging and more progress updates from here on out.

There IS a slight shake up in the roadmap however. As I am now earning less money from my day job I need to try and make up at least some of that ASAP. Some small trickle funds. As such, Drop is getting a much more featured, more polished sequel which is nearly ready. I may be releasing a few other simple, but fun, mobile apps after depending on how the bank balance looks. But my more structured development time is allowing me to plan and prioritise coding tasks in a much more managed way so Dodeka STILL has it's slot and is probably coming sooner than you think.

In the mean time, welcome to the new website and hopefully a fresh breath of life for HS! It feels good to be back and finally moving forward.
Dodeka progress update
Author: HS_Dave
- Posted on: 03/11/2015
Post Type: Blog Entry
Wow, as usual long time between updates! 2015 has been a very busy year and a lot of the time it has been a choice between blogging about gamedev or actually doing the gamedev.

Actually that's nonsense, I could of found the time to blog more frequently if I had really tried. Slap my wrist!

The good news though is that I HAVE still been working. If you are one of the few people who follow me on twitter (@HS_Dave - tweet nearly as infrequently as I blog though.) then you may of caught wind of some sort of editor tool I have been working on.

It has been worth the time I am investing in it. It is a utility that allows me to create scripts/quests/npc's/etc etc for the Dodeka single player and is enabling the creation of much more dynamic content than I was originally providing.

To recap, the single player idea for Dodeka is procedural and quite random. Random missions in random location in a randomly generated continent. The continent generation I have had working for many months and I am very excited by it. Indeed, it even was successfully generating missions on the island though VERY random.

Too random.

I wanted some coherence and some idea of story. It was our lead artist, Elin, that soon came up with the idea's of "truths". A truth is exactly what it sounds like - something that is "true" about the story. For example there could be a truth named "Fred is Evil". Using the campaign editor I have been working on you can create a database of truths such as that. Then you can create a new quest and create (using point and click UI rather than typing) a script for that quest. The script can check wether a particular truth in the database is true or false and then act differently as needed.

When you start a new campaign the game will randomise the values of the truth table (unless a particular truth is setup to prevent this - such as a truth that may only change if the player does something specific) so even if you play the exact same campaign as last time it will now be very different.

As usual I have got carried away, disobeyed the KISS rule (keep it simple stupid!) and generated a lot of immediate work for myself. But as the tool nears its first usable build (it now performs full compilation of the scripts and campaign data for the game engine to load. It will even compile to assembly for debug purposes :P) I am actually glad I broke the rule this time as the content the alpha build is creating is already 200% better than the hard coded "random missions" from before. The ability to create quests which randomise themselves and can spawn other quests in certain conditions (making for potential quest chains with interesting conclusions) yet keeping the ability to assign random NPC's to the quests and all the other little things I added is really going to give some depth to the story I believe.

If I have my way this tool will be packaged with the game so anyone can create (and share!) their own campaigns. Now that I would REALLY enjoy to see.

So that is what I've been silently working on the past few months. I probably need to hire more help ;) Elin is still drawing away and amazing me as usual and we actually have a new website design waiting to be implemented which I think you'll all enjoy! Someone else is working on the new implementation on my behalf this time so hopefully it will be finished before the next ice age.

Thanks for reading!
C# Software Bitmap Utility
Author: HS_Dave
- Posted on: 17/04/2015
Post Type: Blog Entry
So I've been working on some procedural content for Dodeka (more details on that in next dev update!) and I needed a way to visualise it as I worked on it so I could see exactly what I was doing. Originally I output ASCII to a text file but that really was not ideal.

The obvious choice is to create an image then. The problem is that I needed to quickly create a LARGE (giant even) image which is a problem when dealing with XNA Texture2D objects because they are all stored on the graphics card which severely limits the maximum size. I did not have access to System.Drawing in this project and nor did I wish to add it.

Googling around a bit I found I was not alone in this problem however there were little in satisfactory solutions. So what I've done is knock up a very quick (*see foot note) software bitmap handler for C#. It relies on very little and does NOT use unsafe to do it's stuff.

It's not fast and it's not full featured - but it does allow you to very easily create bitmap images, edit them programmatically and then save them to disk in a proper format for your OS to open and display. As I found I was not alone in needing this I've decided to share it, so here it is:

HS_Bitmap.cs

Feel free to use/modify/whatever. It does not really have a real-time application as it's not fast - but as a utility it may be very useful. I have thrown in some basic inline documentation for your intellisense etc - if you'd like more details on the bitmap format then check wikipedia, it's where I got the info from!

As a bonus, here's a quick example of how you would copy an XNA Texture2D into the bitmap object if you wanted to do tile map representation:

First load your image data and create your objects:

    HS_Bitmap WorldBmp = new HS_Bitmap(WorldWidth * TileSize, WorldHeight * TileSize);
    HS_Bitmap WaterBmp = new HS_Bitmap(TileSize, TileSize);
    HS_Bitmap PlainsBmp = new HS_Bitmap(TileSize, TileSize);
    HS_Bitmap MountainBmp = new HS_Bitmap(TileSize, TileSize);

    Texture2D WaterImg = SystemVars.g_MainContentManager.Load<Texture2D>("DATA_2D\\Dodeka\\Water");
    Texture2D PlainsImg = SystemVars.g_MainContentManager.Load<Texture2D>("DATA_2D\\Dodeka\\Plains");
    Texture2D MountainImg = SystemVars.g_MainContentManager.Load<Texture2D>("DATA_2D\\Dodeka\\Mountain");
            
Create some arrays to hold colour data and copy the XNA Texture2D data into them:

    Color[] WaterPixels = new Color[TileSize * TileSize];
    Color[] PlainsPixels = new Color[TileSize * TileSize];
    Color[] MountainPixels = new Color[TileSize * TileSize];

    WaterImg.GetData<Color>(WaterPixels);
    PlainsImg.GetData<Color>(PlainsPixels);
    MountainImg.GetData<Color>(MountainPixels);

Set the HS_Bitmap pixel data to match the Texture2D Color data:

for (int x = 0; x < TileSize; x++ )
{
    for (int y = 0; y < TileSize; y++)
    {
        WaterBmp.SetPixel(x, y, WaterPixels[y * TileSize + x].R, WaterPixels[y * TileSize + x].G, WaterPixels[y * TileSize + x].B);
        PlainsBmp.SetPixel(x, y, PlainsPixels[y * TileSize + x].R, PlainsPixels[y * TileSize + x].G, PlainsPixels[y * TileSize + x].B);
        MountainBmp.SetPixel(x, y, MountainPixels[y * TileSize + x].R, MountainPixels[y * TileSize + x].G, MountainPixels[y * TileSize + x].B);
    }
}

Then you can draw to the WorldBmp bitmap using normal Tile Map methods. IE, draw a mountain tile:
WorldBmp.SetPixels(x * TileSize, y * TileSize, MountainBmp.GetPixels());

I hope this is useful to someone :)

*Footnote: This actually took me an entire evening to write. No matter what I did, windows picture viewer would always report the bitmap was corrupt. In the end it turned out I had accidently opened the destination file as a text document and was writing in ASCII instead of binary - it probably worked first time. I'll admit to raging a little after that one. Then laughing.
Dodeka - Huldra
Author: HS_Dave
- Posted on: 11/04/2015
Post Type: Blog Entry
As usual, sorry for the slow updates!

It's been a real busy time for me the past few months. But also productive - work on the Dodeka engine is continuing in earnest with lot's of time now being spent on crafting a worthy single player campaign.

Let's talk about art quickly. One of my favourite cards from Duodecad was always Huldra. It was one of the first cards drawn for the game and I was really happy when it was sent to me! Now several years later the card has been updated (re-imagined even!) for Dodeka and she looks better than ever.

Truth be told I have never heard of a Huldra until my artist introduced me to them. If you'd like to know more about the lore then check out the page on Wikipedia! She may end up quite relevant to the new single player...

Anyway, enough chat, here she is:



Elin, as always, has done an amazing job.

Now I need to get back to work, more updates soon!
Dev Article - Refactoring
Author: HS_Dave
- Posted on: 22/02/2015
Post Type: Blog Entry
TL;DR - Write better code and it'll save you time later. Pretty pictures in future blog posts.


This one is for the dev's. I want to shower you all in screenshots and visual media but I'm "not allowed" until it's "ready" says the artist. So instead I'm going to chat on about some of the work I've been doing codewise - what it entails and potentially how to avoid having to do it yourself if you are teaching yourself development right now.

The majority of the work at the moment falls roughly under the category of "Refactoring". This is where I take the code base and try to fix everything I did wrong 7 years ago. The ultimate goal is to end up with code that is a lot more concise, readable and maintainable.

So, why?

When I decided I wanted Dodeka to be more than just a pc port and that I wanted to add new features I immediately started hitting problems that were caused simply by how the old code was written. Even relatively simple things like face lifting the GUI was turning out to be a nightmare with everything hard-coded.

I decided that if I started "cleaning up" then I could save a lot of the game logic (which is actually pretty good, albeit untidy) and at the same time I could start altering code to prepare it for my new additions.

What about just rewriting it?

So that's the million dollar question. A friend of mine who works for a game studio in Canada actually recommended I just rewrote the game and I was umming and ahhing until I decided I actually wanted to save as much of it as possible. In hindsight I probably should of started from scratch.

One thing that has become clear during this process is that my programming is radically different from 7 years ago (as I should hope!). Not only do I tend to write tidier and quicker but I actually have a completely different style that becomes obvious when you compare blocks of old and new code in Dodeka.

On the plus side I have gained a good insight into my development as a game dev by doing it this way. If you are in a similar situation then ultimately you will have to answer this question yourself.

Some practicals then.

The State Machine of Doom

A lot of tutorials used to have a state machine style setup for controlling program flow. For example you would have a DrawGame() and Update() method and inside each you'd see a small switch() statement that would check engine state. For example your DrawGame method may of looked like:

switch(GameState)
{
case States.Menu:
     Menu_Drawing_Code;
        break;
        
    case States.InGame:
     Game_Drawing_Code;
        break;
}

Or something like that. When you are following a small tutorial that's fine. But when you start working on a large game and you just keep adding little tidbits to the state machine it quickly becomes disgustingly convoluted! This happened inside Duodecad with some case statements having additional switches inside, REALLY BAD idea.

State machines are a good thing. Filling case blocks with lots of game code is not. Get your case statements to call external methods which handle things - it will save you a lot of headache later on. If you use visual studio then you'll notice switches are not collapsible. There is also no "go to" quick bookmarking for them. When you get lost in a giant state machine of doom you really ARE on your own, so do not create them.

Extracting Code

Finding code that can be moved ("extracted") to an external method is a key part of refactoring and it does not just apply to state machines. It is very easy as you work on a project and add new features that you just "add a line of code" to an existing method. 7 months of development later and you've built a 650 line mega method one line at a time unless you've been doing frequent refactoring sweeps. Find groupings of code that can be moved to their own method and replace the original block with a single call to that method. Naming the method something in plain English (or your own native language of course) will doubly increase the readability of your parent method.

Taking an example from my own code again, I had ended up with a mega method called UpdateCards(); It's job was simple: Tell all the cards where they are positioned on the screen.

Originally there could be 2 places a card would appear: On the side of the screen or on the actual game board. The first thing that was added was Player 2 - their cards were in a different place. Then I added an effect that showed a card sliding off screen then back down to the board when it was placed. Then I changed scaling of a card if it was selected and then they had to be rotated if cards were hidden from a player and.. you get the point. It went on for ages.

Younger me had never heard of refactoring but would of benefited a lot from it. Most of that code could be extracted into smaller, readable methods. PositionBoardCards(); PositionCardsInHand(); UpdateCardMovement(); etc.

Because of this the main UpdateCards() function is now very easy to read, you can see exactly what it is doing where and if a bug turns up or a new feature is required its very easy to just go straight to the piece of code and get the job done.

Naming and Readability

Readable code is easy to work with code. You know where you are, what is happening and thus what WILL happen if you add or change something at any particular point. To that end the simplest refactor and one of the most useful is the rename. Do you have a variable called xt? That is not useful - what is it doing? It makes perfect sense to you right now but you'd be amazed how it wont if you come back to it in 5 years. Let alone if someone else comes to look at the code.

With the advent of super powerful IDE's (big Visual Studio fan here), incredible Intellisense and auto completion there is no need to use tiny short hand for everything. It saves you nothing. Perhaps you're a javascript developer and you're trying to save on filesize? A worthy aim but write good readable code and then minify your js using a tool later.

There are of course conventions that are completely fine. Everyone knows that N in a loop is a counter and X/Y/Z in iterative loops are self explanatory. But things become a bit vague when you write xs instead of XSpacing and cw instead of CardWidth.

I am also a big fan of keeping things in separate files. Each class, each enum etc I move to an external file with the same filename as the class or enum inside it. Visual Studio has good integration for this type of system too where if you rename a file in the Solution Explorer it will automatically rename the class inside and update references to it. It just means everything is always easy to find.



Refactoring is a giant topic and I could be writing on forever about it. There are several books you can buy and a plethora of videos on youtube that can help explain it all in more detail, I really recommend having a look. But if I had just been covering the 3 headings above when working on my original game the changes I'm making today might well be done already.

Look after your code and it will look after you :)
Dodeka Development #3
Author: HS_Dave
- Posted on: 04/02/2015
Post Type: Blog Entry
Well I managed to skip a whole month of blog updates, but better late than never right?

I may not have been blogging much but I *have* been working, I promise! The network back end for the Dodeka match making service has been really taking shape. I say the "Dodeka match making service" but as I suggested in the previous post the "Heavenly Software match making service" is more accurate as its designed to do the work for all games I make. At the moment it is going simply under the name HNET but I am open to suggestions :)

The service is currently providing game discovery and live chat for Dodeka as well as some essential services like NAT punch through. It also has a decent framework for providing Achievement like services which I'm umming and ahhing about adding - if you have an opinion on that then do drop me a line! There is also potential for things like competitions and ladders in the future but due to the work involved that would be considered AFTER a successful release if the game seemed popular enough to merit the investment.

So, pushing the boring network updates out the way let me move on to the game. Sadly it's almost as dull as network chat as most of the work over the past month has been on GUI features as I attempt to craft a system that is a lot more fluid and quick to navigate - I know one of the major failings of Duodecad is the GUI was quite clunky and not always clear. It's worth the time investment, I promise :)

I have also invested a fair chunk of extra time rewriting a lot of code to not depend on XNA so much anymore. Infact the ultimate goal is that the Dodeka engine does not actually know what XNA is despite the fact it uses it for all it's rendering etc. This move was made after I received a very welcome message from a fan on facebook who said they really enjoyed Duodecad and wanted to know if Dodeka would also be on Xbox. Now, I can't promise that it will be. But it did prompt me to start thinking about other platforms that people use and how I can bring the game to them.

Properly abstracting certain parts of the engine will make this "possible" but not guaranteed. But I *DO* want to bring Dodeka to as many platforms as possible (including mac, linux, consoles and tablets) so to make sure I have a good fighting chance of doing that I'm laying down the ground work now. However when it comes to the consoles there are additional licensing fees and usually dev kits required etc so just having code that "will probably work" does not mean I will manage to push to that specific platform!

As always, it's not only me that has been working. Elin is still drawing away - mostly concentrating on the GUI as that is where I have put the focus at the moment but also bringing new cards to me!

So as a little treat to make up for my lazy blogging habbits here is a look at the latest one I was sent:



and a link to the high resolution version: here

This is one of the new level 10 cards that you'll see in Dodeka. One of the new features the game will have is that any card can be potentially be found as a rare "foil" card - it's going to be interesting to see how these look on shiny backgrounds!

Let us know what you think through facebook or twitter. I'll try to blog a bit sooner next time!
Tis the season..
Author: HS_Dave
- Posted on: 14/12/2014
Post Type: Blog Entry
tra la la la laaaa.. etc.

Well already it's the busiest month of the year and I notice my blog entries have been slack! My wife came up with a fun idea for this years advent where hanging on the wall in our living room is a fabric advent calendar with pockets for each day and we have each placed cards alternately into each one and on each card is an activity that we will do together on that day. For example "Watch XYZ Christmas Movie" or "Visit the Christmas market in town" or "Make mince pies" etc.

It's somewhat part of a process where we are repairing and rediscovering our marriage after a very hard few years. In that sense, its great! But it also means less uninterrupted time for coding and less to blog about.

What I HAVE been working on however is a multiplayer lobby service, primarily for Dodeka but also built to support other games so I'm all good for the future. Multiplayer in Dodeka is fully working at the moment. You can host games, join games and play games. What you can't do however is "find" games. Originally this was provided by Xbox LIVE for Duodecad. On the PC there are some other alternatives, the most prevalent of which is probably steamworks provided by valve for steam games. However, being unable to guarantee I could release on steam (although I will certainly try) and wanting to provide for the future as well I've decided to roll my own. I have access to cloud services through Azure so hosting will not be a problem and this will be an interesting test of running a scalable networking service.

I have many plans for the future of it and hope to blog more details in the future but for now it's just a simple service for Dodeka and we'll see where it goes! It's been a helluva experience already and an opportunity to bury my head in white papers on scalable/distributed services such as IRC and Battle NET and learning where things have gone wrong for them in the past, what has gone right and perhaps what should be done differently or not at all. Not to say what I am building is ANY WHERE near the scale of something like Battle NET - just that the existence of those things provides an education in of itself.

More specifically to Dodeka then: Elin is still drawing away whenever she gets the chance. More GUI drafts have been appearing in my dropbox folder and the occasional new card image when she needs a break from dialog boxes. I have recently rewritten parts of the particle engine to be more efficient with quads (infact, due to the simplicity of particles in Dodeka, just one quad). This has completely eliminated the need for any quad pre-caching and halved loading times which I'm well happy about.

There is still more refactoring to be done and further development of the game rules logic I mentioned in my last post and then I think it will be time to move into adding some of the really new features that I hope will significantly set Dodeka apart from Duodecad. Watch this space!
Dodeka Development #2
Author: HS_Dave
- Posted on: 13/11/2014
Post Type: Blog Entry
What a month. I've been to hospital three times (twice for myself, once for my wife) and just when I thought it was all calming down I ended up with food poisoning. Still, despite all that I have managed to get some work done.

I have quite a few features I want to bring to Dodeka but in order to bring them into the engine there is a "lot" of prep work to be done because of the way it was originally written for Duodecad. This starts with a lot of re-factoring to make the old code simply readable, a lot of code extraction to new classes to properly encapsulate it all and in some places just straight up rewrites to more sensible or more extendable code to allow the new additions to take place later down the line.

One of the things I've added is a new Game Rules system. In Duodecad there were only two rules that affected the stats of cards on the game board (other rules, like plus, are basically triggers for additional capture attempts) and the checks for them were built into the main game loop (I release forgiveness to my past self for my coding crimes). That is fine on a purely functional level, the game works as the user expects. But when it comes to extending the game with new rules (or even making changes to existing rules) it's a really bad system that gets very ugly, very bloated and very unmaintainable very fast.

With the new system I can define game rules as classes that implement the GameRule interface. In simple terms the interface describes some core functions that allow a specific rule to process the current game state and output a result based off the end result - whether that output is a modification to the attack power of cards on the board or a new capture attempt etc is up to the specific rule. This has two immediate effects on the game engine:

1) The actual core logic loop has been trimmed right down with all rule code removed. It's very easy to read and basically summarises as "for each active rule: Rule.Process()". This makes for a much easier to maintain code base.

2) The engine has become highly extendable. To add new rules and behavior into the game the process is basically to add a new class for the rule that implements the GameRule interface, write the logic for the rule inside the class Process function and then let the game know the new rule exists by adding AvailiableGameRules.Add(MyNewRule); to the Init() function.

What bugs and issues I actually run into as I add new features and rules in the future remains to be seen, but already this type of system is a massive leap from what used to exist. It is a wonderful (and perhaps slightly uncommon) use for the powerful c# interface - something I did not even know existed when I first started writing Duodecad!

For those that are interested I'm going to finish this post with a link to a youtube video I was listening to the other day which I thought was pretty neat. It's a short talk on designing maintainable code by Eric LaForce and I was personally interested in his section on Anti Patterns which I don't hear much about. Basically things that are bad. I identified a few too many in my own code base ;) Have a watch:

https://www.youtube.com/watch?v=EOkyQCQkmXs
This week with Dodeka
Author: HS_Dave
- Posted on: 12/10/2014
Post Type: Blog Entry
When I started writing Duodecad I had a very vague idea of what I was doing. I had used c# for winform applications and had a basic grasp of the language but that was about it. All my previous experience was with C/C++ and old style to boot (IE, I never really used a class before, just a lot of functions).

Starting Duodecad I had a half idea that I was going to make a "simple game" that was "a bit like triple triad" and it would be a good experience to get used to using XNA and C# for game dev. 3 years later I actually finished and released my game.

In that time my knowledge and experience grew and changed a lot. That's great but it had some very negative effects on my code base. For example half of it is written using hungarian notation brought over from my C experience and later I ended up switching to simple Camel Case which was more common in C#. Good code design practices were something I had heard of and that is as far as it went - multiple classes in the same source file, random hacks in the middle of functions.. all sorts of little nasties.

So coming to port the game to the PC proved to be a complete nightmare when it should of been simple. Years later I have a good understanding of C#, proper code design and features like interfaces which were never touched in Duodecad and it gives me a bit of headache working out how (and when) to implement this knowledge in the engine.

Most of this week I have been looking at parts of the code base I will need to change for the new features I wish to add to Dodeka and deciding what to modify and what to rewrite. The card classes will need modification to allow for some new features (like foil cards with unlockable abilities). The network code has already been done (that I just deleted and wrote again from scratch - it is now based on Lidgren and a plug and play style interface system) but there are so many more areas that need a good think about to make sure I proceed in the most effective way. It is time consuming and a little frustrating in that it does not produce a visible "thing" to screen shot and show everyone but it is VERY necessary.

Art. One new thing that Dodeka will receive is a brand new GUI and theme. I've been head to head with Elin (who has joined me again to provide the art - woo!) and viewing new designs, hopefully this will be something physical to show you all soon. Just today I handed over a bunch of flow charts showing menu flow and the content of different screens, I really look forward to seeing what she brings back to me from it all!

Now I'm heading back to visual studio to decide what can be reworked and what just needs ctrl+a, delete...
A personal welcome to Heavenly Software
Author: HS_Dave
- Posted on: 05/10/2014
Post Type: Blog Entry
Welcome to the new Heavenly Software website and blog!

These blog entries will usually be very developer orientated and intended to showcase progress on the various projects I'll be working on over the years. This first post however will be a bit of an exception as I want to talk a little more personally about what's been happening since the release of Duodecad and also do a little bit of apologising.

If this sort of thing is of no interest to you then check back later for the more technical posts!

So, my name is Dave. I'm the lead programmer at Heavenly Software. During the day however I am an orthotics technician working in the UK. My true passion has always been software development with a special focus on games. I've always said I want my own studio one day and it was about a month ago I was talking with a work colleague when I was hit by a voice in my head saying "well, you have a company name, a (broken) website and have released a couple of games. You have a studio, you just don't look after it properly."

It was then that I realised that I was in danger of missing the dream by being so focused on it's end and missing the start. As soon as I got home I started making plans to remake the website, schedule in fixed working hours specifically for development that were realistic and took in to account my responsibilities as a husband with a day job and set out some realistic goals and mile stones. Up until now everything has been very freestyle and if I come home too tired I could too often decide "cba, I'm gonna sit on MMO's tonight" whereas with a proper time table I can make myself work properly but know I have time set aside for my own leisure as well.

The past few years have been very hard. A lot of struggles in my personal life have had to be faced which have been very distracting from my development work. That coupled with the fact that when I released Duodecad it was very well received, won an award or two and remains highly rated today - but as far as sales go it was a -complete- flop was very disheartening for a time but also led to some great learning opportunities that I may talk more about another time.

So what's next? Well it was largely decided that one of the reasons for Duodecad's failure was the 360 was not the best place for it at all and it was much more suited to the PC where there was a larger market for the genre and more options/openness about what I could do with it. So for the past year or so I have been slowly porting the game to the PC.

This has not been easy because quite frankly the original code I wrote is awful and full of hacks left right and centre as I grappled with the nuances of console programming. The largest task was the port of the networking code which relied 100% on the Xbox LIVE framework in its original form. That has now been replaced with a tidy interface system and I've written a new network handling system using Lidgren.

Whilst I was working on this people would point out little bits and bobs that could be improved. New ideas to add. Feature requests, game modes and slowly I realised I no longer had a port on my hands but a sequel. A much needed one too for there are some pretty big failures in the original game. Things such as improved GUI, a proper single player campaign, a tutorial mode etc - all were begging to be added to the original.

There's a whole bunch of other stuff that we'll be adding. Perhaps the most important thing is the name change. The original name people had trouble pronouncing and it really did the game no favours! Some time ago after getting feedback on social media and amongst my peers the new name for the PC project was decided: Dodeka.

So that is what you will be seeing next. I will bring regular blog updates about the progress of the game (none hopefully this long!) and the new features as they are implemented. After that I have some exciting projects sat in design documents ready to be made flesh and you may even see some glimpses of them before Dodeka is finished as I'm allowing myself Sundays as "prototype day" for playing with new ideas to keep myself interested and prevent burn out.

FINALLY, my apology:
This is for anyone who tried to use the Duodecad website and found it broken or even managed to get to the forum but never got replied to. I know some users came to the site and I can only apologise for the fact you would of been completely ignored. The old site was built on top of PHPBB 3 and it became INFESTED with spam bots. I enabled capcha and it did not seem to help anything. I then required administrator approval for posts and accounts. At it's height I was having about 800 spam accounts created every day and if any genuine users were amongst it all I would never of known. Coupled with the financial failure of Duo I quickly became very despondent and just stopped looking. 2 weeks later I received an email from my hosting provider saying my DB was exceeding the maximum allowed size (I'm on an unlimited account btw) and it was ALL from spam accounts and posts and I ended up locking down the whole thing.

What a mess. I am so sorry - part time indie or otherwise thats a terrible way to run things! This is why the new site has no forums but instead we're using facebook. I'm sure there will still be spam but hopefully a lot more manageable!

Okay, sorry for the long intro post but I felt I should get that all out there. See you soon for development updates!
New website!
Author: HS_Dave
- Posted on: 04/10/2014
Post Type: Site Update
It is way overdue but here it finally is - heavenlysoftware.co.uk 2.0!

The new website should offer a much better user experience for everyone and is now touch screen friendly.

We have dropped all the forums as although they were created to allow you to connect with us and the rest of the community they actually ended up preventing that when the spam became so great it was just not possible to administrate it. I have no idea how many people tried to connect via the HS forums or the duo-game.com forums but I am so sorry for the terrible user support you would of experienced!

To keep things more manageable we have opted to now use a facebook page as a means for you to chat with us and others. Feel free to connect with us straight away!

The final new addition to our site is this blog. I (Dave) hope to be able to bring development updates about projects I am working on rather than a couple of years of silence between each release. Let's see how that goes ;)