General Category > Programming

CPCRetrodev 2021 : Fitzroy Dives Deep

(1/6) > >>

Fitzroy Dives Deep
As per the ongoing tradition I wrote another Fitzroy game for CPCRetroDev.
The game disk and instructions can be found here:
I have also attached the recent binary (v1.2) to the end of this post.

I also tried to use images in attachments but could not figure out how to add them inline so imgur it is.
Feel free to give me feedback and report some bugs as I am sure there are things to fix that I don’t know about. It seemed like every time I added a new level I found a bunch of bugs.
If you don’t want to read my long post just grab the disk file and play it (you have been warned that this post might go on for a while  :P ).

Fitzroy Dives Deep is unquestionably my most successful game with seventh place :D (last year was my least successful but I won’t dwell on it too much).
This clearly means I did a lot more things right or less things wrong (whichever way you wish to look at it).

Rather than asking a bunch of questions (like I have some years) that no one seems to answer I will describe a bit more of my process as well as lessons learned.
I will try to add some screenshots because Gryzor said he likes having those.

A few things I learnt from the last few years for this game were:
1. Base the idea on a gameplay idea rather than a subject matter. When I decided to use sea mines I had no idea what the game was and spent a whole lot of time doing research without having a good idea on what sort of game I wanted to make. What I ended up was somewhat accurate to the idea but the core game was not that compelling.

2. Make sure the game is approachable, having some instructions is fine but avoid something really complicated.
Fitzroy in the Dark can be a little bit hard to understand how to use the inventory, but Fitzroy goes Sweeping is really hard to understand without instructions (Which I forgot to include in the submission arghh.).

3. Be careful not to make the levels barren or bare. Fitzroy in the dark has these big levels for you to explore but they aren’t particularly distinct (at least not when its dark) and there isn’t enough stuff or enemies to make them memorable.
I also effectively created a game that required you to make a map but I doubt many people have the patience for that.

4. Get the movement and controls right early on. Fitzroy in the dark was rather clunky initially with the selecting a square and then moving.
Fitzroy Dives Deep originally had up to jump which was OK originally but having a dedicated jump button made for a better experience. It also allowed me to use the jump key when in the water which made the water movement more interesting and faster.

That isn’t to say my game is bug free. I haven’t ever released a game without any bugs (like most people I expect) even if cpc-power only lists them for some games.

There are three bugs I know of that are intermittent.
1. A tile is sometimes drawn randomly on the screen, this is usually near the right edge but does not affect gameplay. (I very carefully made a video where this did not happen.)
I suspect it could be related to my backbuffer but I didn't really look into it. I haven’t seen this happen when using wincpctelera.
There is a spot on the valves level where it is consistent, but I never got around to looking into it.

2. One of the snail’s spawns in the wrong spot on the first level, I thought using memset on the enemy array before initialising would fix this, but it still sometimes happens. The memset fixed the game from crashing every time you reload a level though.

3. The game completely crashes at random (game breaking); I have no idea what causes this one as at other times it will be perfect playthrough which makes it hard to reproduce unless you happen to snapshot at the right time. I would have spent more time on this, but I didn’t have much time and it was intermittent.
I am reasonably certain it is related to enemy initialisation issues. Intermittent CPC only bugs are always the hardest to figure out.

Not so intermittent bugs (workarounds exist)
1. When you boost upwards it doesn't always go to the right to top, I partially fixed this, but it does not work in all circumstances. Instead of Fitzroy going to the top of the screen he will be one pixel off. The workaround is that when the player boosts in water up to a solid block they also press up to get all the way to the top.
I feel this is a little bit inconvenient and adds a bit of an artificial difficulty to the game. It hopefully shouldn’t be too hard to fix, I also assume no one would want me to keep this for the added difficulty?

2. On the last level there is a spot you change rooms where can you end up one pixel into a tile and seem stuck until you press up or left (can't remember which).
I considered this insignificant so haven’t had a look at all why this happens.

A few things I learnt for this game:
1. How to use Arkos Tracker 2 (Thanks Arnaud and Targhan for their help), it is nice to finally have a game with sound and music.
Technically last years game had one sound but that doesn’t count for much. Arkos 2 is also way better to use than Arkos 1.

2. How to use a backbuffer. Previously I have saved the video memory of an actor (player or enemy) as they move and then redraw it later. This time I used a backbuffer which was more reliable. However instead of sacrificing 16KB for the whole screen I used a backbuffer that was 4 tiles big (256 bytes).
This worked reasonably well and saved me some memory but there is a bit of slowdown because of the backbuffer.
Perhaps there is a better strategy of populating the backbuffer from the map where the actor was and drawing it at the actor’s previous position and then doing the same thing at the actor’s new position.
I suspect I have not got it completely right but at least there are no leftovers on the screen.

3. Limit adding new features near the end of the development time. I tried to avoid adding features in October.
This also applies to graphics where it worked out much better finalising the graphics and palette sooner (as usual I make sure to support the green screen even if I am the only person who ever uses this option).
I did spend more times on graphics this year which means they are better, but they remain fairly simple.
The more practice I have at making graphics the better I will get. I still managed to change the main character sprite and one of the interactable objects at the last minute, but I mostly stuck to this.

4. Try not to spend too much time on tools (more on that later).

More on the original idea
Back to the original game idea. The original idea was to build a game based around an underground cave system.
Some of it will be underwater and some of it will be dry. I specifically drew inspiration from Caves of Doom (A Mastertronic game that isn’t that significant except that I got it with my 464)

and Scubaventure (Not a CPC game but I played a lot of apogee platformers which is why I know this game).

I had thought of a game where you do the levels once without water and then come back a second time with them filled with water.
The idea was that you would have to navigate differently the second time because the environment changed.
I ended up building levels where bits of the level were empty and other parts were filled instead which was much easier to design.

I feel that drawing inspiration from some games that weren’t considered classics means you can easily learn from deficiencies in those games and avoid ending up building an inferior clone of some other game.
My biggest gripe with Caves of Doom (besides it being impossible to play with the keyboard) is that it requires pixel perfect movement and just about everything you touch instantly kills you.
You get a lot of lives, but it isn’t enough unless you have a lot of practice or modify the level with the in-game editor (this is a super neat feature of the game actually).
With my game I tried to make sure you didn’t have to have pixel perfect movement but instead there is something you can use to line yourself up with.
If you want to have pixel perfect movement you can probably play the game a bit faster but that’s up to you.

Overall, I am happy with how the game works and the progression through the levels but it has been suggested that the game is a little bit too hard. I have some ideas around adding a little bit more health and giving a way to replenish lives, but I’m open to ideas for this.

The challenge with difficulty is that I don’t want the game to be too easy (Xyphoe commented on his stream that a lot of the games were a bit too easy) but I also want the game to be hard enough to give players a challenge without making it unapproachable or impossible for most people.
I feel that because the CPC has a lot of very hard games there are people who are very good at hard games but not everyone wants a near impossible challenge.

Now we get to a bit more on my process. Each year I create a map editor to design my game levels (Except for Fitzroy and the Infestation which had autogenerated levels.).
I have noticed that my editors are very iterative in that I build a very similar editor thus writing similar (improved but similar) code each year for the same thing.
In response to this I decided back in April to write a library for my editor so that the bulk of the functionality could be contained in the library, and I wouldn’t have to rewrite it every year for each game editor.
This certainly helped reduce the amount of time I spent on the editor however I still spent a fair amount of time because it was not complete when I started work on the game in July.
Next year it will be even better as the library is far more complete then when I started using it.

This of course raises the question why don’t I just use Tiled and save the effort of writing my own? Part of it is that I enjoy writing the editor, I also don’t write much C++, so this is a good opportunity to do so.
The editor also fits into my process really well (or my process fits around my editor, not sure if it makes a difference).

This is what my editor looks like (we can see most of the test level in this screenshot). The level is made up of 3x3 Mode 0 screens.
Generally, how a level is designed is that I draw in major level features and then I fill in each individual screen with content until the level is completely filled in.

I then play the level and find its completely unplayable but that is simply how the process works out.
Sometimes I will test screens individually (this is what I did for later levels) rather than waiting for the whole level to be complete.
This is useful when I’m not sure if what I am trying to do is possible.
This is what one of my levels looked like early on:

The part of my process that the editor really helps with is how I design the graphics. I do all my graphics in Retro Game Asset Studio (RGAS).
The format it uses is a JSON file and as pointed out by someone on the forum (don’t remember who) you can read the file for your own automation purposes.

Here we have the tiles RGAS file open in RGAS.

From the editor I can select any of the graphics I have created in RGAS from the tile menu.

I can then plop them into the editor as I see fit.

This year I extensively used it to try the graphics out as I was designing them as the colours match what you will see in the CPC reasonably closely.

Here is me trying out some metal tile designs to work out which look best.Here is me trying out some metal tile designs to work out which look best.

I feel I can’t mention my process without mentioning Arnaud’s Wincpctelera.
This continues to be fantastic and makes it easy to quickly debug my game C code without having to drop down to the assembly.
It doesn’t solve all the problems as some things don’t happen that happen for the CPC version but it covers most things.

The wincpctelera version looks very similar as you can but it does play a bit faster which is both good and bad so you have to make sure it works on the CPC.

What’s next
Looks like we made it almost to the end (or you skipped all the “boring stuff” to look at the what’s next).
For next I would like to fix any bugs that I didn’t fix in the initial development. Particularly the intermittent bugs which can result in the game crashing. I would also like to address the game difficulty which I think is a little bit too hard but without compromising the game thus making it too easy.
Also, there was one extra level I had hoped to make. If you look in the source code, you will find my test map that I showed earlier big1.c which is filling the space for a tenth level in the game. This might be a v1.2 but I plan to finish this map and add it to the game.

One final thought
While the editor works great for me to build levels in the game its even more interesting to see what other people can do with it. User generated content is often the best kind of content.
If people are interested, I can provide the editor and the RGAS graphics files and let people try build some levels.
If I had some complete levels, I could create a cpcwiki version of the game with a new set of levels, this would be something like an expansion or addon version of the game.
The only concern is that to really test the level you need to be able to compile the game which might be a bit of a barrier to entry.
An option would be to try extend the wincpctelera version of the game to read in my json map files but it does play a bit faster which while a reasonable way to test a level is possible it isn't perfect. Often a level is actually easier on the CPC version because it plays a bit slower.
Let me know if this is an interesting idea, graphics could possibly be enhanced this way to (I hope I can keep my green screen support though).

Change Log
v1.1 (Build 525)

* Fixed memory corruption crash from stopping Arkos sound outside an interrupt.
* Make sure you cannot go above top of screen.
* Combined shoot and use to a single control.
* Moved spike near top left entrance of middle right room to make room transition easier on second level.
* Expanded the right most wall in the centre middle room to make room boundary clearer on second level.
* Removed spike near bottom right room entrance on the intro level to make room change easier.
* Made centre middle exit more obvious on the intro level to make room change easier.
* Entrance to bottom mid room is now normal water on valves level to prevent instant death.
* Fixed clipping through solid blocks underwater.
* Added additional health to the game to make it slightly easier to play.
* Fixed water boosting just off block bug.
* Improved boost pixel off bug fix when water at top of screen.
* Fixed bug where a tile can be drawn seemingly randomly on screen due to a futureYTile value of 255 (-1).
* Fixed bug where a valve could be used multiple times to cheat valve objective action count.v1.2 (Build 578)
* Removed yellow pixels from the U character in the font.
* Removed an unnecessary pipe from collect and place pipes level ( level 9 ).
* Add a dialog to allow the player to accept whether they want to restore from checkpoint or restart the level at the beginning.
* Play switch sound effect when activating checkpoint.
* Moved checkpoint in health water level ( level 8 ) so that it is not above a spike.
* Changed oxygen cylinders to oxygen water in health water level ( level 8 ) to make sure the level is possible when loading from checkpoint.
* Reduced the length of Player.c function logicPlayer() by splitting the function into several smaller functions. This was to make it easier to compile the game on low memory systems. This also provided a significant memory saving (when the right code was moved out).
* Reduced number of points that can be gained on the first level.
* Reduced number of points that can be gained on the second level.
* Extra lives for points can only be awarded on easy and normal difficulties.
* On the end of each level if the player has accumulated about 30K points an extra life will be awarded.
* Added brutal difficulty (previously was hard).
* Normal difficulty becomes hard difficulty (same as normal but no checkpoints).
* Checkpoints can now only be used in easy and normal difficulty.
* Replaced cpct_getScreenPtr with cpctm_screenPtr when used with constants to save memory.
* Replaced cpct_px2byteM0 with cpctm_px2byteM0 when used with constants to save memory.
* Display pipe count in collect and place pipes objective level.
* Added collect and place pipes map to game as level 9.
* Added checkpoints to game levels.
* Draw an active checkpoint graphic onscreen if the player has activated it. (Only one checkpoint can be active at a time)
* Created graphics for checkpoints (both active and inactive).
* Added a checkpoint interactable that the player can activate to save their place within a level. If they die after a checkpoint has been saved it will start the player at the checkpoint location instead of the start of the level. (The state of the level and the player items will remain the same.)
* Implemented activating a linked interactable when placing pipe.

I wish I could give you more than one Like for that fantastic post.
Congratulations on finishing a very good game, and on your most successful game yet.
It's very encouraging to watch your games getting better each year.
Well done!!!

Congratulation once again for your 7th place, here small ideas or improvements :


* Avoid when changing rooms direct walking on trap / monster or death.
* Better identification of exits or add walls to the places where you can't get out the room.
* Remove some traps in the underwater areas, managing the limited oxygen is already complicated.
* Add a small life bonus on some objects.
* When we die, restart in the current room.
* I think the Use key can be removed, the Shoot key can be used instead (and not shot if in front of interactive object).

* Add a small animation for the movements.
* Mirror enemy sprite according its direction.
* Make a little change of palette on interruption to make a visual effect of water.
If you make a sequel  ;D, I would have liked a game like Antiriad (or Metroid) where you unlock zones (and go back) as you acquire (and keep) equipment.

Congratulations! I think it is the best of your games so far!

Thats for all the kind words and suggestions. :)

I have a fix for the tile that randomly drew on the screen (usually to the right edge).

Turns out that because I was not setting futureYTileTop = 0 in Player.c as below that futureYTileTop would be 255 when processCell was called on the next line.
This would obviously get the wrong cell, in the first level where this happened you would jump and end up with the oxygen as well as the tile being drawn when it shouldn't be.

--- Code: ---
if (futureYTileTop == 255)
   // Check that the last cell in the room above is empty.
   if (processCellInRoom(occupiedXTileLeft, SCREEN_TILES_Y - 1, currentRoomX, currentRoomY - 1) == CELL_EMPTY &&
      processCellInRoom(occupiedXTileRight, SCREEN_TILES_Y - 1, currentRoomX, currentRoomY - 1) == CELL_EMPTY)
      // Set the position to the maximum position so you can scrape right against the top of the screen when jumping.
      player.object.position.y = 0;

      // Solid above the player so set velocity to 0 so they start falling.
      player.object.velocity.y = 0;

      // Reset futureYTile for the top of the screen.
      // Otherwise processCell will have a 255 which will get
      // the wrong cell and cause it to draw the wrong tiles on screen.
      futureYTileTop = 0;

// Process the content of the future cells and perform collision detection.
occupiedXFutureYTopLeft = processCell(occupiedXTileLeft, futureYTileTop);
occupiedXFutureYTopRight = processCell(occupiedXTileRight, futureYTileTop);

--- End code ---

--- Quote from: Arnaud on 16:05, 14 November 21 ---Gameplay:
Avoid when changing rooms direct walking on trap / monster or death.

--- End quote ---
There shouldn't be any monsters when you walk into a room, I thought I avoided that.
I would have said there wasn't anywhere you could die instantly when changing rooms but you showed me otherwise yesterday.
Every trap should be avoidable as long as you know its there, I tried to avoid being unfair but I might not have succeeded every time.
I was probably particularly unforgiving in the last level.

--- Quote ---Better identification of exits or add walls to the places where you can't get out the room.

--- End quote ---
Are you meaning places like this where you can't see where to go.
Perhaps that was a bit harsh for in the first level in this case.

I do have space for a few more tile sprites, would an arrow be helpful or is there a more subtle way to do it?
I probably should have put the strawberry right next to it.

--- Quote ---Remove some traps in the underwater areas, managing the limited oxygen is already complicated.
Add a small life bonus on some objects.

--- End quote ---
There is a health item, I have clearly been a bit stingy in using it.
I will have a look to add it in more than just two levels.

--- Quote ---When we die, restart in the current room.

--- End quote ---
The trouble is I don't know what is a safe position.
I suppose I could save the position as soon as you change room though and then restore you to that position (but could that position still be safe).
While I have avoided putting enemies next to entrances it is perfectly possible to create levels that do that.
I was thinking more along the lines of letting you replenish your lives by getting sufficient score but I'm not quite sure how much and I don't think there is an equal amount of points available in each level.
Alternatively I decide that one item (such as the circuit board) gives you an extra life. I think Jazz Jackrabbit does that but I might be wrong there.

--- Quote ---I think the Use key can be removed, the Shoot key can be used instead (and not shot if in front of interactive object).

--- End quote ---
At the moment I can't think of a time where you want to shoot when you're right next to a switch or something.
Even if there was it would probably be an acceptable difficulty for the player to manage.
Crystal Caves does a similar thing with using the shoot key for use as well with no noticeable down sides.
This would make the game playable with a two button joystick which would be nice (even if I don't have one).

--- Quote from: Arnaud on 16:05, 14 November 21 ---Visual:
Add a small animation for the movements.

--- End quote ---
I've never done animation in my games, it is something I should figure out.

--- Quote ---Mirror enemy sprite according its direction.

--- End quote ---
Making enemies that are recognisable like snails means this is a bit obvious.
I thought about flipping a little but not enough to do anything about it (time running out and such).
I didn't want to store the sprite for every enemy as that is 15*64 bytes which seemed like too big a sacrifice.

I could have a temporary enemy variable (only 64 bytes) which I memcopy the enemy sprite into and flip the temporary variable before drawing it (depending on direction of the enemy).
I thought this might be slow but I didn't try it.

The other option I noticed was cpct_drawSpriteHFlip_at but that requires 256 bytes for the flip table but I didn't actually get around to trying it.

--- Quote ---Make a little change of palette on interruption to make a visual effect of water.

--- End quote ---
Is it still a little change if I have to change many of the graphics though? I did something like this for Fitzroy in the dark but how many of my 16 colours would I have to sacrifice for this to work?

--- Quote ---If you make a sequel  , I would have liked a game like Antiriad (or Metroid) where you unlock zones (and go back) as you acquire (and keep) equipment.
--- End quote ---

I've never made a direct sequel to one of my games. I do have an idea for a Fitzroy in the Dark sequel but I might have a completely different idea by the time July comes around next year.
In this game having not implemented carrying inventory items across levels I decided it allowed for more interesting level design when you had to go find items every level.
Haven't played Antiriad or Metroid but doing a game with zones that you come back to could be interesting. Not sure what you need to do in order to make the zones interesting the second time unless they are partly locked because you don't have sufficient items or the hoards of enemies are too challenging the first time.
It could always be your next game .


[0] Message Index

[#] Next page

Go to full version
Powered by SMFPacks Reactions Mod
Powered by SMFPacks Alerts Pro Mod
Powered by SMFPacks Mentions Pro Mod