So, this is done:
And it’s had some wonderful reviews, from actual journalists! First, this piece on Eurogamer:
“I’ve been hypnotised by the Screen Explosion… it’s a joyous, mysterious, witty thing, a quick-change artist, one screensaver conjuring brutalist city layouts, another rendering streetcorners as buzzing pointillist swarms of lights, another taking you on a tour of the pylons of the world, seen from an endlessly cruising blacktop, colours changing, designs switching around as you travel without moving, the whole thing drawing me in until the pylons themselves start to look like mecha one minute and religious statues the next.
and also this piece on Rock Paper Shotgun:
“I enjoyed restarting screensavers to see them with new colours or new patterns. I really enjoyed that drive past international pylons. I enjoyed watching colours. I felt the childhood magic of screensavers again.”
Massive thanks to everyone who helped with testing, and to everyone who bought it. Pending any fatal bugs I’m now done with it, and moving onto a game, but before I do here’s some things I learned whilst dragging it from a nice little sketch to an actual product.
Writing your own engine is mostly a terrible idea but has some advantages
Perhaps it wasn’t necessary to write my own engine, but I wasn’t sure if I’d be able to write a screensaver any other way- Unity and Unreal are both a bit heavy, and you lose a lot of control over the low-level stuff like windowing and resolution. I didn’t entirely do it on my own- it’s all written on top of OpenFrameworks, which gets rid of a lot of the misery of the OpenGL API, but there’s large chunks of functionality I had to put together from scratch.
Fortunately the structure of the project meant that effort was just done as needed; the downside of that being that progress on producing things to actually look at was slower than I’d hoped, because I was having to muck about with the internals. Writing things that people won’t see gets demoralising, because despite any improvements you know you’ve made, none of it is evident to someone just looking at the screen.
One big advantage, however, is not having to find a way to express what you want to do within the confines of some larger structure. I was writing my own shaders directly; I could feed them the data I wanted. This makes some things a lot neater… but then again I’m nowhere near the fidelity of something like Unreal.
There’s a massive gap in expertise required to use C++ and JavaScript
I don’t think this is a surprise to anyone, but it really is a massive gap. Most of the work I’ve done for the last 10 or so years has been with JS and it’s various flavours, such as TypeScript. Before doing the Screen Explosion I’d not written any C++ since University, and picking it up again was essentially like learning a new language from scratch.
Now, there’s a lot of things that annoy me about open source JS projects- the stupid names, everything being “made with love”, even the most mundane shit having a logo- but they’re a hell of a lot easier to understand than the C++ ones. This is partly down to my familiarity, but also partly down to the language; aside from a few things like RXJS where the code is covered in decorators, nobody tries to overload operators or write macros or specify their own type of floating point number in JavaScript. But these turn up in C++ libraries pretty regularly, meaning you have to do a lot more reading to understand what’s going on, and even more if you get an error message.
An example of something I didn’t expect: Open GL redclares nearly every numeric data type with the prefix ‘GL’- GLint
, GLfloat
, GLdouble
, and so on. Now, given that OpenGL is liasing with the hardware and different operating systems running on different types of processor there’s a good reason for this- the library needs assurances that it will function in the same way regardless of each environment- but there’s no explanation for this anywhere in the documentation, and in TypeScript all of these except GLboolean
would just be number
. And the Windows API terrifying if you go into it cold; I can see why the O’Reilly books sell so well now.
Getting perfectionist about something isn’t always bad, unless you do it too early
Most of the time I was happy to get things to ‘good enough’ and move on, but there are a few things that spending time on really helped with. First, the fish:
I knew I wanted to do a flocking simulation because it was a relatively easy win, but making an interesting flocking simulation is actually a bit of a challenge. If you just apply the basic rules, the different actors will go off endlessly into the distance, or bunch up, or ignore each other, or go in a straight line until they hit a wall. To make them actually look like a school of fish, I had to do a lot of experimentation.
Here’s a few additional things over and above the usual boids algorithm that I added in.
- Containment. Having the fish swim off endlessly meant they need to be contained, but abrupt changes in direction when they get to the edges looks crap. As such, they’re encased in a sphere, with each fish gaining a force reflecting their velocity back into the sphere that ramps up from an inner boundary to the outer boundary.
- Homing. Having the fish swim around the edges of the ‘tank’ also looks boring- they’ll line up and flock, but only around the edges. To counter this there’s a periodic homing force that gets applied, guiding them back to the center. This ramps up and fades away over time, giving the impression that the fish actually want to do something other than simply mooch about.
- Current. There’s a subtle 3D noise field that gets added into the simulation that evolves over time, which mostly works to divert the lead fish in a school away from a linear path. This makes any chains that form flow into a more interesting pattern.
- Variable stupidity. Each fish has a number which says how much it will follow each of the above forces, varying between 0.9 and 1. That adds a bit of chaos to the system, and makes things a little less robotic.
If I hadn’t got a bit precious about getting this right it would have been shit; as it is, I’m extremely happy with the result.
The counterpoint to this is: shadow maps. I burnt an absolutely stupid amount of time trying to get shadows right for the pylons, before taking them out and realising I didn’t really need them in the first place. The pylons have a non-realistic rendering scheme where the brightness calcuation is mapped onto a palette of colours, and if anything it looks better when it’s allowed to be weird and shadows aren’t present.
I don’t think there’s any non-obvious lesson here- I suppose this could fall under the category of premature optimisation- but when you’re doing something on your own it can be hard to prioritise.
If you want to write a game-like thing, you also need to get good at editing videos and copywriting and 3D modelling and whatever you’ll need next week
Guess what: everyone wants a trailer these days. Perhaps that’s obvious but I hadn’t really thought about it before, and so I found myself learning how to use DaVinci Resolve. On top of that, while there’s some great free 3D models out there, if you’ve got something specific in mind you’ll need to either pay for it or make it yourself. The budget I had for this project was “as close to nothing as possible”, so I had to learn Blender. And then there’s the press releases, patch notes, and so on. None of this stuff is hard as such, and I got better the more I did, but it’s time-consuming work that I didn’t expect, and work you don’t expect is always the hardest to do. Which leads us on to…
Keep going even when you think it’s all shit (despite the fact that sometimes something is shit and you need to get rid of it)
Again, no big non-obvious lesson here, but I had a hundred opportunities to give up, and it took a lot of effort to will myself to keep going.
I had a lot of self-doubt when I was looking at something and hating it, and then wanting to change it… and sometimes I was completely right to hate it, and sometimes I just needed a break.
Pushing through nigh-incomprehensible C++ error messages was hard; pushing through more semantic bugs with the rendering, where nothing was appearing on screen but everything looked like it was correct, was even harder.
Finding that my Windows 11 upgrade had made the multi-screen video player stop working, and then deciding to cut it rather than spend an unknown amount of time fixing it, was also very difficult, as were the failed experiements that seemed great in my head but not on the screen.
Particularly hellish was when I did an initial release into Early Access… and then hardly anyone bought it, and nobody responded to my emails except to say “sorry, I just want to cover games on site of moderately high-profile games journalist
, I can’t imagine anyone would want to cover screensavers”.
But finishing it, and getting the press, and the positive user reviews, and now selling enough to at the very least get the app submission deposit back from Steam… that feels very good. Also knowing that I’ve learned a huge amount, and that I can do something like this, that’s a big thing to. Who knows if I’ll ever top it, but I’m going to try.