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!