So last time, I was updating the demo to use the new graphics format, and along with that format came the ability to apply operations to the new buffer – including modifying it in real time.
Before trying that, I wanted to get the level into a single “bitmap” instead of an array of 32×32 tiles. This would simplify adding/removing stuff as I wouldn’t have to apply the same operation to multiple tiles – making it a quarter the speed.
Now that there was enough memory, this was a fairly simple process and just meant making a tile of 320×200 and drawing the single tile. As an added benefit, I could also draw this each game cycle now, as it was the 2D loop that was slow – not the single call to draw it.
The only “gotcha” with doing this, was having to load in the bitmap in chunks, as the Z80 BASIC doesn’t have to space to load it all in at once. So now I have to swap from the fast oscli(“LOAD”) to reading in a byte at a time, as the oscli one doesn’t support block loading – just loading of it all.
Here you can see we now need to use BGET to read in a single byte, but aside from that we simply build a buffer then create the bitmap from it.
With that now loaded into a single bitmap, applying anything to it, is now a single operation which makes life much simpler. The first thing to do is to was to somehow modify the background to see if this will even work…
Time passes….
After much faffing, I finally managed to write some bytes into the bitmap, so it it looked like this should work. I was considering writing a black sprite into the background, then someone pointed to the fact that you could AND buffers – that’s ideal. I mean… it’s basically the same thing, as I’ll AND 0 or 255, which is like writing black – but this feels nicer.
So I needed to make a mask that I could loop around, and after (again), much faffing, I was able to loop through an array and send that to the VDP and get it to mask onto the background.
To get this working, I added a new bitmap to the tool and write some code to generate a mask from it.
The C# program scans for a non-pink pixel, then reads the bitmap inside it, building a 0 or 255 bitmap from it. We then invert that making a byte-per-pixel bitmap much like this.
We can then use this with out buffer, AND-ing it with the background.
This VDU command is pretty powerful and can apply many operations to the buffer – seen here from the document on github.
In this case, we’re going to AND this mask with the background using the loop above, which will give us this image below….
Now comes the annoying and tricky part…. updating the bitmask array we use for collision testing. Since the bitmap is held on the VDP we can’t just read that for collision testing, so we need to keep the bitmask for allowing the z80 to do the testing.
In order to remove something from the background, we also need to remove it from the bitmask, and this requires us AND-ing a 1bit mask to collision map. This is a pain, but the only way to do it.
So, next in the tool… is we need to generate 8 1bit bitmaps for each pixel in a byte as we rotate the mask. Basically we pre-rotate the 1bit mask so BASIC only has to loop and AND, and doesn’t have to shift anything.
With this array of shapes, all we need to do now, is get the number of shifts required, and use that as an index in to the mask array. We do that by simply taking the X coordinate and AND-ing with 7 like so…
xshift% = x% and 7
Lastly, we loop over the mask and AND it with the collision mask like so…
Now that we have everything masking, we can see the effect this has on our walking Lemmings….
The only clean up to do is to make a structure we can add more masks to, so that in theory we put in basher and diggers etc. We need to do this because BBC Basic doesn’t allow us to pass in arrays to functions, so we need to use a global array, and as such, we also need to put everything in one array.
But that’s not terrible, we can put lookup tables at the start if we need to, so that’s fairly simple.
I think the next thing I really want to do, is try and get this same thing working in C, as the Agon has a C compiler. It would be interesting to see how many Lemmings the C version could do, as I suspect BASIC is the limiting factor. So I might tinker with that next.
The latest version is now up on github for everyone to tinker with. I’d love to see someone else play with it, and add more features/skills.