This is a bit of a bump - but I just released a full game on Itch: Daedalus Versus Minotaur by Orange Thief
And here's a gameplay vid: https://www.youtube.com/watch?v=6ftWvYCh8vo
There are a lot of changes compared to what I shared above, most notably the approach to drawing the first-person perspective got almost entirely re-thought and re-written. When I got my playdate and tested out the original project it ran terribly when in first-person, hitting maybe 3 fps. It was almost entirely unplayable! I realised I needed to drastically change my approach, but was a performant full screen first-person maze view even in the realms of possibility? What I needed to do was think up all the possible ways it might be possible in Pulp and do some performance testing.
Possible approaches for effective full screen draws:
- Brute force draws - just draw 375 tiles to cover the entire screen!
- While loop draws - still brute force, but in a while loop for code brevity
- 14 labels (1 per line) with embedded tiles - one label for each line, each label spanning the length of the screen, and using
{embed:tile name}
to embed tiles into the labels
- 14 labels (1 per line) with text tiles - as above, but without the embeds (we'll get back to that)
- 1 label (line wrapped) with text tiles - as above, but using line breaks
(3) sounded like it might be a clever solution in the event of label
being more performant than draw
. (4) you might wonder what the point is in comparing - but in a flash of inspiration it occurred to me that as the total number of tiles I need to draw the maze in first-person is small, and the font character table is editable, I might be able to edit the font directly. A very silly idea!
Results of testing effective full screen draws on every frame with different approaches:
- Brute force draws (375 draws) = 7 fps
- While loop draws (1 draw looped over all 375 coords) = 3 fps
- 14 labels (1 per line) with embedded tiles = 8 fps
- 14 labels (1 per line) with text tiles = 16/17 fps
- 1 label (line wrapped) with text tiles = 18 fps
(I had some test code wrapping these approaches so I could quickly cycle through them on device without loading a new build, but I assumed the overhead there to be minimal!)
There it was - the tantalising taste of performant full-screen updates! It might seem odd but editing the font to use text characters directly rather than embedding or drawing other tiles gives a huge increase in performance! There are maybe some other useful results there, like knowing while
should be avoided when drawing.
Anyway, my font ended up looking something like this:
Any text in the game would be limited to upper case characters, but I could live with that!
Of course I wasn't done with optimising. One big and obvious improvement was to separate out the calculation of what needs to be drawn from the actual drawing. The calculation itself is a very heavy piece of code and running it every frame is a complete waste of resources. I changed it so that the calculation of what to draw happens only when moving (or rotating) and this performed a lot better!
The drawing itself could also be improved. While the tests above are for a complete full-screen redraw, my maze layouts mean I don't actually need to label across the entire screen - especially at the top and bottom of the screen there is a lot of whitespace that always remains whitespace. There was a bit of balance here between the optimal labelling and having manageable code to generate it. I ended up with a somewhat convoluted middle ground where the central rows have the most calculation logic with full row labels with decreasing complexity as you get higher/lower (thanks to less overlapping coordinates in the view).
With all of those changes made I ended up with something actually performant! Not perfect (even by Pulp's 20 fps definition of perfect) but perfectly playable, which made me happy enough!
Please do check out the game - the demo/free edition includes the main versus multiplayer mode. I hope this dev post is interesting, especially as a conclusion to the year-old experimentation above back when I didn't even have my handheld!