Monday, 28 June 2010

Working away....

We're still working through design ideas at the moment. Some of our key ideas revolve around how to fully use the 128k now available to us. Ideas for cut scenes and sub games are bouncing around as ways to help expand on Gloop Troops 2.

Also check out natami !
Could we be about to receive some new Amiga hardware?
Between this and the X1000 things are certainly getting interesting :-)

Like many programmer the Amiga was the first machine I learnt to program on. It would be fantastic to revisit the Amiga at some point and develop a new game. Amiga Gloop Troops perhaps?

Saturday, 26 June 2010

Compressing map data for the ZX Spectrum

Working on platforms with tight memory budgets like the ZX Spectrum requires some head scratching work on how to cram in as much data as possible into such a tiny amount of space.

One of the biggest potential uses of memory is storing map data. Whilst working on our ZX Spectrum project we had iterated through 3 different map formats! Below I work through these map formats, showing their pros and cons before describing the final format which we'll be using on Gloop Troops 2.

Format 1: No compression on tiles.

First of all we tried exporting data directly to see what kind of memory hit we would take. Our maps are 32 x 22 tiles in size, with each tile representing 8x8 pixels of screen space. This leaves a space 2 tiles blocks for the HUD at the top of the screen. Initially we stored all the tile data uncompressed but compressed all the tiles attributes using a simple form of run length encoding.

The way we stored attributes very simple. After all the tile data was written to the map file we'd write out all the attributes.. There is 1 attribute setting per tile block used in the map. We would start by writing out an attribute's value into the map file and then check to see if there were subsequent tiles which had a matching attribute value. If so we'd scan along the rest of the map counting the number of times this attribute occured without changing and write this number as a second byte after our written attribute value. If there were no matches ( so only 1 instance of this attribute before it changed ) then we'd set the FLASH bit of the attribute to ON. This is because we knew we'd never have any background tiles with the FLASH bit set as it tended to look ugly.

Example attribute data ( uncompressed ), 5 attribute tiles with the value 8 followed by one of 16, followed by 2 3's, and finally another 0x8:

0x8, 0x8, 0x8, 0x8, 0x8, 0x10, 0x3, 0x3, 0x8

Example of compressed attributes:
0x88, 0x5, 0x10, 0x83, 0x2, 0x8

So we've written out attribute our attribute 0x8 with the top bit ( the FLASH bit ) which changes the number to 0x88 ( 10001000 ). We've then written out the number 5, which is the number of times this attribute occurs, followed by attribute 16 ( 0x10 ) without the top bit set ( so the number stays as 0x10 ). We've then written attribute 0x3 with the top bit set ( becoming 0x83 - 10000011 ), followed by the number 2 ( as there were 2 instances of the number 0x3 in our uncompressed data ). Finally we have the number 0x8 as the last attribute, and there was only one instance of this in a row so no FLASH bit and counter byte set.

We also stored the width and height of each map at the top of the map file. This is because we'd envisioned having a variety of map sizes and could save some space.

The pseudo code for the map file was:
Width - 1 byte.
Height - 1 byte.
For tile_y = 0 to 21 do
For tile_x = 0 to 31 do
Tile_Id - 1 byte.
next tile_x
next tile_y
{ Attribute data }

The advantage with this method is each screen can look distinct as there are no rules regarding which tiles can be adjacent to another tile. But the big problem with this format is that whilst the attribute data compresses nicely the tile data still uses up 704 bytes, which is quite a bit of space on a machine with only 48k!

Format 2: Mixed - Tile brushes and custom tiles data.

This was the method used for Gloop Troops 1 and offered up a sizeable saving but still wasn't enough. We realised that a lot of the tile data tended to repeat throughout a map, so rather than storing each tile individually we could store a single "brush" which would store many tiles worth of data.

Example tile brush: This is a 3x2 Tile brush which stores 6 tiles worth of data.
[ 4 ][ 4 ][ 4 ]
[ 7 ][ 8 ][ 9 ]

We stored the tile brushes separately from the map data so that they could be used by several levels. Tile brushes were written out without attribute data and in the format:
Width - 1 byte.
Height - 1 byte.
For tile_y = 0 to brush_height do
For tile_x = 0 to brush_width do
Tile_Id - 1 byte.
next tile_x
next tile_y

Our map format changed to:

Width - 1 byte.
Height - 1 byte.
Num_Tile_Brushes_Used - 1 byte.
For tile_brush_id = 0 to Num_Tile_Brushes_Used
Tile_Brush_Id = 1 byte.
Tile_Brush_X_Pos - 1 byte.
Tile_Brush_Y_Pos - 1 byte.
Next tile_brush_id

For tile_y = 0 to 21 do
For tile_x = 0 to 31 do
if ( tile_is_not_part_of_tile_brush )
Tile_Id - 1 byte.
next tile_x
next tile_y
{ Attribute data }

This meant we'd write out all the tile brushes first, then for any parts of the map which weren't covered by a tile brush we'd write out the tile data. We also did a simpler compression to tile 0 as what we did with attributes. If we wrote a 0 as the tile ID then we'd write a second byte indicating how many tile 0's to write out. This is because tile 0 represented blank space on the map, and there would typically be many of these in a row.

The advantage of this method meant that we could cover most of the map with a few tile brushes and then touch up areas with a few individual tiles. The compression on this was a lot better but still not fantastic.

Format 3: Tile brushes only and flood fill attribute.

This is the method we'll be using on GT2 - we'll be ditching the concept of individual tiles and purely using tile brushes. By default our screen will be flood filled to a particular attribute ( and tile 0 ) and tile brushes will also now store attribute data. The attribute data will still be stored in a simple run length encoded method inside the tile brush data.

Width - 1 byte.
Height - 1 byte.
Default_Attribute - 1 byte.
Num_Tile_Brushes_Used - 1 byte.
For tile_brush_id = 0 to Num_Tile_Brushes_Used
Tile_Brush_Id = 1 byte.
Tile_Brush_X_Pos - 1 byte.
Tile_Brush_Y_Pos - 1 byte.
Next tile_brush_id

We found that this now gives a far superior compression for each screen for some sacrifice of flexibility ( which we found we'd hardly used ).

This should mean less space wasted on storing map data and more space dedicated to graphics, game-play and sound!

Thursday, 24 June 2010

Making music

Currently playing around with the new Arkos Tracker

Only had a brief play with it but so far it seems like a lovely piece of software! Hopefully we'll be able to use it to put together some tunes and sfx for Gloop Troops 2 :-) Now all we need are some musicians...

Tuesday, 22 June 2010

New Speccy Releases from Other Developers!

Trooper:Point 5!

Looks to be a pretty solid game that reminds me a lot of JetPac, I quite like the shadowy effect underneath the platforms.

Full info can be found at World of Spectrum

Monday, 21 June 2010

Gloop Troops 2 - The wish list.

Now Gloop Troops is out the door we can take the time to see where we can improve the original game! Below's a list of features we'd love to include in the sequel:

* 128k Spectrum - by targeting this machine we'll be massively increasing the amount of RAM we'll have to play with! There looks to be a bit of a learning curve on using memory pages effectively which hopefully won't throw us off too much.

* Music - we had problems getting music into the original game, targeting the 128 and getting some AY music in should solve this brilliantly.

* Bosses! We wanted to have an end boss originally but in the end dropped it. It'll be great to go back to this idea and maybe have a few bosses every few levels?

* Power ups - Always a blast to collect in any game and missing from the original. We'll have to think up something fun for these :-)

* Cut scenes - We had 2 levels in Gloop Troops where we displayed some text above the action. We'd love to work on this more and have some more personality to the characters!

* High score table - Missing from the original, we only displayed a single high score. Having a high score table will hopefully add to the competitive nature of the game.

* More enemy types - there were a few enemies dropped from the original due to time and memory restraints. That shouldn't be a problem any more :-)

First up for coding will be the music system...

Sunday, 20 June 2010

The making of Gloop Troops - Post mortem

What went right:

* We managed to finish a home brew project! :-) We all start lots of mini projects in our spare time, and very few of these ever reach completion. We were both very proud to have seen one through to the end.

* Re-playability - Once the scoring mechanic was in we found that it made each level playable in multiple ways. The player could rush to the end collecting all the starts, or plan how to keep as many enemies glooped as possible in order to maximise their score.

* Great art work - a big thank you to Andy who stuck with the project in all it's guises and delivered some fantastic artwork for the game. He was able to work with the limitations of tghe spectrum, colour clash and all and deliver something which is brilliantly styled and makes each level easy to read at a glance.

* Tools - having written our own tools for editing levels, compressing level data and converting images files to a Spectrum friendly format allowed us to maximise what we could do with the platform.

What went wrong:

* The difficulty curve was too gradual, most retro gaming players could easily get to around level 15 without breaking a sweat before hitting the tricky levels. Our initial play testers were all friends and family who perhaps in hind sight may not have been the best candidates for testing. The reason for this is Gloop Troops is a very hard core retro game at heart and should have been tested by a more hard core games playing audience.

* Sound & music - this was something we only added late in the day. We had not been playing other Spectrum games and missed that the audio bar was much higher than we remembered :-) Next time we may target the 128k Spectrum and make use of the AY sound chip.

* Scoring mechanic was missed by a lot of players. We were going to display sprites over glooped enemies to show the amount of score you'd earned by glooping them. However this information was lost to the players we found as as this feature didn't make it in and a lot of players missed the score in the top right flashing. Next time we'd like to focus more time and memory on highlighting the player's achievements.

* Writing the game in assembly was time consuming. This had been done to maximise performance out of the limited hardware, but instead we could have used a C compiler such as Z88DK and rolled our own sprite and collision routines in assembly.

* Continuous experiments - whilst beneficial to the overall quality of the game, each new feature we added took around a weekend to implement, test, tweak and then decide if it was worth keeping or not. For future projects we've chatted about the possibility of creating a PC version to test game-play ideas before finally porting them to the target platform.

Friday, 18 June 2010

The making of Gloop Troops - part 4

Other elements started to make their way into the game in order to provide a sufficient challenge for the player. A timer was added to the game, first set to 20 seconds, but that caused new players to the game to struggle completing even the starting screens. With only 20 seconds on the clock, most players ran out of time whilst still watching the enemy patterns and planning their route through the level. The idea of having a brief pause before the level starts, displaying "Get Ready!" over the screen was discussed. This would have allowed us to keep a tight time limit to complete a screen ( as the player could see the level ahead and plan their actions ), but was dropped due to complications. In a sequel this idea would hopefully be revisited and implemented correctly.

In the final version of the game we gave the players 30 seconds to complete each stage as a compromise between allowing them enough time to figure out what to do and to execute their plan.

Using the timer we decided to spawn a bonus points giving fruit pick-up ( inspired by Pac man ) every 10 seconds, giving a maximum of 2 pick ups per level. This tied in nicely with other games spawning a reward the player could grab, at the risk of leaving any safe zones of the screen they might have found. It would have been more ideal to have this tied to the player performing an action, such as having glooped all the enemies on screen.

An element that went late into the game was spiked platforms. Previously the player could freely jump up and down platforms, easily avoiding enemies. Spikes were added to create more threatening platform sections and channel the player through certain parts of the map. They also make the player feel more uncomfortable when jumping over gaps ( as failure now costs a life ) and add a sense of danger to the screens.

Invincible enemies were added around the same time as spikes to create moving obstacles for the player to avoid. These, unlike the spikes, would require the player to time their actions to avoid colliding with them. Originally these enemies were going to be a particular colour, but it was difficult to communicate their invulnerability to the player as we were using a range of colours for the enemies already. A neat solution was to cycle the colour used on invincible enemies. That way they stood out easily when the player glances at the screen, and separated them from other enemies.

Wednesday, 16 June 2010

The making of Gloop Troops - Part 3

When we stripped the game mechanics back to basics we decided to give the player a regular projectile to fire. This avoided us having to design screens with large areas of vertical space ( to all throwing of enemies such as in Stackies or to jump on enemies heads ). Pressing fire would spawn a projectile which would travel in the same direction as the player. For simplicity ( and a bit of a challenge ) we limited the player to only having one of these projectiles on screen at a time.

We went with the idea of a player having to collect all the pick-ups on a level in order to progress to the next one. We'd had some code for pick-up collection left over from the adventure game and it seemed a good fit. Having to collect all the pick-ups forces the player to fully explore the screen and plan a route past all the obstacles. We wanted to maximise the player's time per screen as we were keeping with only having one screen per level.

When the projectile went in we first had it so that enemies were killed on collision with it. However removing enemies from the screen made each screen get progressively easier! As you shot at enemies and removed them from the map, the number of obstacles the player faced would also reduce. We debated on some alternatives, in particular the idea of having enemy spawners in the level. This would have spawned in a replacement enemy whenever one was killed. But this also had knock on effects to the screen design :-( More screen space would have to go to these spawners, which may not be active for much of a level's duration. The additional problem of getting the new enemies into a position where they blocked the player's path also proved to be tricky.

However the surprisingly simple and elegant idea of stunning enemies, rather than killing them came up as a way around the problem and provided a good challenge for the player. This meant that enemies would only be temporarily out of the picture, long enough for the player to get by, before they'd wake up and continue on their way.

The screen above used to be the first level in the game and was used when testing out all the above mechanics. It later became screen 7 in the final game.

Tuesday, 15 June 2010

The making of Gloop Troops - part 2

Disheartened by our failed epic game we thought it best to try going back to basics. We'd both recently seen The King of Kong and loved the idea of creating a simpler, action orientated game, but one with a scoring mechanic which allows experienced players to re-play old levels and improve their score.

We stripped back all the excess code to leave a simple core which read the joystick ports, loaded the map screens and displayed sprites on the screen. All our game code was written in Z80 assembly language, which allowed us to maximise performance, but came with the cost of being more difficult to manage. It was our first assembly coded project and had got a little spaghetti like as features were added, tweaked and dropped as the game was pulled in different directions. This had make making changes to the code during the adventure game's development very costly in time.

We started on a new game initially nicknamed Stackies. The goal of which was to simply clear each level of enemies by picking up an enemy ( in the same style used in Super Mario Bros 2 ), and throw them at another enemy. If the enemies collided and matched colours then the thrown enemy would sit on top of the hit enemy. If the colours didn't match then the thrown enemy, the hit enemy, and any enemies stacked on top of that hit enemy would be destroyed.

The mechanic was solid, but didn't suit a single screened game ( particularly a retro one with a small resolution ). The problems we encountered were that you needed lots of empty screen space to allow an enemy to be thrown, else they just ended up hitting platforms.

We debated on whether to make each level multi-screened or the enemies thrown in a straight line rather than in an arc, but these didn't feel as satisfying a solution. We were still disappointed after our previous failing and wanted to get the core mechanic developed quickly, fitting within the confines of the tech we had developed and the spec of our game. To make a game with single screen levels and an interesting scoring mechanic.

Monday, 14 June 2010

The making of Gloop Troops - Part 1

Before delving into our new game I thought it best to chat about our previous efforts :-) Gloop Troops was released at the end of April this year for the 48k ZX Spectrum.

Gloop Troops started out as a very different project back in 2007. Andy and I had been sitting in the pub discussing the joys of retro gaming when the idea of creating a brand new game on the Spectrum came up as a fun side project! We spent the what little spare time we had designing a Dizzy style adventure game, with elements of Exile and Monty on the Run.

We worked on it on and off for over a year, but without a clear vision on what we wanted at the start we ended up pulling the game in many different directions. Finally in mid 2008 we called the game to a halt after many code and tool re-writes ( including a pc version ).

After surveying the code wreckage we took a step back and started to come up with a new plan...

Sunday, 13 June 2010

New blog

Here's the start of a new blog charting the development of our next title Gloop Troops 2! We're hoping to share lots of info on what goes into making a new game, post up in development screen shots, code snippets, and other assorted bits of retro gaming joy!