Speccy, Vol 9: Attack of the RGBobots

April 17th, 2016

It's Ludum Dare time again, and I figured I might write a game for the zx spectrum (again) for the heck of it.

After waking up, I checked the theme which was "Shapeshift". I thought of several ideas - Ikaruga clone, a take on the lost vikings or fury of the furries where you'd just swap between characters in place.. like in trine, actually. Or how about a take on "hole in the wall" TV show. All possible, but would either take way too much time to make for the speccy. So I took a simpler idea, a twist on the ancient "robots" game.

In "robots" you have a bunch of robots that always move one step towards you on every turn - yes, it's turn based - and if two robots collide, they die. If they collide with you, you die. In some versions you can also teleport to a random location, possibly limited times, or with cooldown.

In my twist, the robots come in three colors, and you can change your color. Each color can 'eat' one color and be eaten by one other color. I didn't know whether it'd be fun or not, but it's a simple enough mechanic to write quickly.

Then I went out for a nature walk with my boy, went out to eat, came back home and (after talking it over with my wife) started working on the game.

Time between my "Trying to get a speccy game together" tweet and my "Here's my ludum dare entry" tweet is 9 hours. I also helped with dinner, ate dinner, took dogs for a walk, and performed the usual fatherly responsibilities like reading a bedtime story.

My original idea was that every color change you do is also a move, but this quickly turned out to make the game extremely difficult. Being able to choose your color freely made the game easier.. possibly too easy, but that's a better option, especially in Ludum Dare games.

For art, I used my image spectrumizer. The fact that stb_image loads photoshop's .psd files makes the art workflow really powerful. I'd draw in photoshop and have the same file open in spectrumizer on another monitor, and every time I save the file I'd see the spectrumized result instantly.

Being "robots", I only needed two sprites - a robot and the player. I tried to make the robots really angular and boxy and the player more round and smaller, but when we're talking 1-bit 16x16 sprites (and my skill level) the results may not be quite as good as I'd hoped. But I did think about it before doing the art, which is something I guess =).

Being turn based, I could have some longer sound effects. I used BeepFX player by Shiru again, this time being able to use it more properly.

Working off my speccy toolchain and various bits of routines and tools I had written for it. As an example, the sprite routines I used are total overkill for this game, as the sprites only move in 16x16 aligned positions. That also means there's 7 unused copies of the sprites (and masks) in the game. Yes, it's a waste.

Since I had all those routines to use and the turn baseness of the game meant I didn't need to care about hitting 50Hz, I didn't need to write a single line of z80 assembly to build the game.

After getting the game logic going and having the game over done and even the level progression written, I still needed to write the main menu. I started coding a window drawing routine to draw the menu on top of the game's graphics.. and then figured, this will take ages, and I have memory to spare. So I fired up photoshop again and just drew the main menu as a static image instead.

For packaging I used my Mackarel again. The game uses two full-screen images (the game background and main menu) which I told mackarel to load as a compressed low-memory block. This was much simpler than to turn the images into include files. This did lead to a slight complication, because the my default code offset is low enough that two uncompressed images didn't fit under it, so I needed to tweak it. Fortinately that didn't blow up anything, so I've apparently didn't have any (critical) hard coded addresses anywhere.

If I was really tight on memory space I could have stored the main menu in compressed form while running and decompress when it's actually needed, but at the moment the memory map shows 16k unused space.. (well, not totally unused: the non-const globals are allocated from there).

Mackarel 2.0 by Jari Komppa, http://iki.fi/sol
Progname set to "RGBobots  "

"crt0.ihx":
        Exec address : 40960 (0xa000)
        Image size   : 7550 bytes
        Compressed to: 4123 bytes (54.609%) by ZX7

"logo.scr"
        Image size   : 6912 bytes
        Compressed to: 1956 bytes (28.299%) by RCS

"lowblock.dat":
        LowBlock addr: 23296 (0x5b00)
        LowBlock size: 13824 bytes
        Compressed to: 4438 bytes (32.104%) by ZX7

Boot exec address: 56684 (0xdd6c)
BASIC part       : 51 bytes
Screen unpacker  : 122 bytes
App bootstrap    : 123 bytes (69 codec, 54 rest)
"rgbobots.tap" written: 10867 bytes
Estimated load time: 82 seconds (19 secs to loading screen).

Memory : 0       2       4       6       8       10      12      14      16
         |-------|-------|-------|-------|-------|-------|-------|-------|
On load: rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
         sssssssssssssssssssssssssss..b..................................
         ................................................................
         ..............................LLLLLLLLLLLLLLLLLLCCCCCCCCCCCCCCCC

On boot: rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
         sssssssssssssssssssssssssssLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
         LLLLLLLLLLLLLLLLL...............CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC..
         ................................................................

Key    : r)om s)creen b)asic L)ow block C)ode block
         H)igh block .)unused -)reserved```

One of the last things I did was the different input schemes. Keyboard routines were relatively simple (and the interface-2 joystick is also a "keyboard" device), but for some reason I had a lot of problems getting kempston support going. After struggling with that for an hour or so I figured it doesn't absolutely need to be there, so I edited the option out from the main menu picture and removed the option. The problem with the kempston (in this case) is that it's a separate port to read from, and the turn-baseness of this game was achieved through an ANYKEY() check.. which, for some reason, I couldn't get working with kempston. So I cut it out.

Based on the early comments on the Ludum Dare entry page people seem to be liking it. I don't think the game has any chance of getting to the top-10, though, and I think there'll be games that are way more deserving to be there.

You can grab the .tap image here, or try an online emulator here. The sources are in github along with the rest of my speccy stuff.

Someone asked for a windows port of the game. I considered this for a while, but that would probably take more effort than writing the game did, due to the way the control flow goes. It's better to just download an emulator and run the .tap through it.

Anyway, I hope you'll find it as fun as it was to write!