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!