After the model compiler comes the texture compiler. Decompressing a PNG file on Android is possible, but the loading code is simpler if the texture is already available in a format that we can feed directly to OpenGL. So I devised the GLT (GL Texture) format, and wrote a program called gltc to convert PNG files to GLT.
Having a level editor is a good start, but it’s not all. We need some kind of workflow to create models and textures and eventually get these to show up in the game. I started with the models.
Does a carpenter create his own hammers? Does a painter make his own brushes? Usually not, but a game developer often needs to build his own tools to get a particular job done. One of the most important tools to have is a level editor – you really don’t want to put all objects into a level by typing long lists of coordinates. Building the editor has kept me busy for the past few days.
I’ve decided to change course. Drastically. The fluid engine works nicely, and although it’s fun to play with, it’s not exactly a game just yet. I had this idea, which I alluded to in my previous post, of making it into a creative construction game. You’d be a beaver, and you’d have to use twigs and branches, floating in the water, to build a dam.
No truism is always true, not even this one. I recently clashed with two common conceptions in software engineering:
“All problems in computer science can be solved by another level of indirection.” – David Wheeler
“Some people, when confronted with a problem, think ‘I know, I’ll use regular expressions.’ Now they have two problems.” – Jamie Zawinski
The problem, in this case, is the heart of my little content management system, Utterson. As I discussed previously, I want all content to live in a Git repository, which is read and interpreted (later, also written) by the CMS. For example, I would create a blog using magic file extensions like this:
I’ve been doing more experimenting with the engine, trying to come up with a workable puzzle concept. Below are some videos and reasonings.
First off, the game objective. Assuming that it’ll have something to do with the fluid, one possibility is that the player has to make the fluid flow in a particular way or direction. We could represent this as having to “paint” particular objects with colours that are injected into the fluid. For example, in the video below, the player would have to paint the top box red and the bottom box green. (The opposite would make for a rather more difficult puzzle!) The boxes don’t yet react to paint in any way.
This week has been one of mostly refactoring. I’ve been streamlining the code to make it easier to add new objects and features later on. This will prove useful, because the gameplay clearly needs a lot more experimenting to get it right.
I had hoped that the editor would allow me to quickly test gameplay concepts by using “soft rules”: rules that are communicated to the tester verbally by me, instead of being enforced by the program. For example, I could say “Now try moving the orange ball into the blue rectangle, but only moving the green blocks.”
To be able to test different configurations, I had a rudimentary text-based file format to describe levels in. It was fairly simple and easy to edit, but still, hand-typing coordinates is not my idea of fun. It was time to build a graphical editor.
In the days of MS-DOS, things were simple. If you developed a game, you usually wrote it for one specific VGA or SVGA
resolution, such as 320x200 or 640x480. If someone’s video card did not support this resolution: tough luck.
This week I worked hard on getting the fluid solver in the style of Jos Stam working. The basics were easy enough, but Stam makes some simplifying assumptions, so the continuation was not quite trivial. But combined with what I learned in my earlier work on the free-surface simulator, I managed to put together a fast, stable, flexible and pretty fluid solver that I’m more than a little proud of.
From my previous posts, it must now be clear that free-surface fluid dynamics is hard. This is mainly caused by the free surface. Without that, it is possible to write a fluid-in-a-box in a little over 100 lines of C code, as Jos Stam did in his paper Real-Time Fluid Dynamics for Games. However, I could not go down that road. I needed the free surface. I wanted my game to have waves, droplets, splashes, sprays, fountains! How these would make a game, I would figure out after I got the simulation to work.
Work on this project has been standing still for some time while I was working on another project. But this week I picked up work where I left off: making the fluid simulation even faster. Since the SOR solver I was using lends itself well to parallelization, and video cards are good at running parallel programs, I tried to run the solver on the video card (GPU).
The fluid simulation was beginning to approach results of decent quality. However, it was still far too slow. Most of the screenshots I’ve shown so far were done on a 64x64 grid, which barely ran in real-time even on my fast Intel i7 machine. For a full-screen game, I’d need at least 128x128 and preferably 256x256. As I noted before, a doubling of the grid size requires about ten times as much computational power. Clearly, some optimizations were in order.
I’m a very visual type of guy. A picture really does say more than a thousand words. It should come as no surprise that my way of coding and debugging reflects this.
Last week, I wrote to my fluid dynamics professor for advice on the free surface fluid simulation. It was a positive surprise to see that I had run into exactly the same problems as he had in his research. I must have been doing something right then!
It’s been a busy week with little to show for it. As I wrote last time, I more or less gave up on the SPH particle-based method, and opted to fix my grid method instead. That turned out to be harder than I expected.
I realized that the problems I was having with the tracking of the water volume were not as easy to fix as I thought. It seemed that grid-based (Eulerian) methods are very suitable for a continuous fluid, but not so good when a sharp boundary between water and air is needed.