This weekend was the third instalment of the Alakajam! game jam. I was really happy about the shortlist of potential themes, so I knew this was going to be a fun one. The winning theme, “Always growing”, was my second choice.
Last week,
I talked about a fairly sophisticated attempt at solving my
2D discrete physics problem,
which ultimately turned out to have unfixable flaws. But I need this problem
solved for my game, so I decided to relax my requirements for the time being.
As I previously wrote, I
recently fell in love with the Kotlin language. It’s been over four months
since that post, and my enthusiasm has not diminished. In this post, I’ll show
how I combined some of Kotlin’s best features to write some extremely readable
unit tests.
In the last
post, I
described my requirements for a 2D discrete physics system I’m working on. Now
that I’ve laid out what the system should do, let’s turn to the implementation.
For a new game I’m working on, I need some 2D “physics” that work in discrete
time and discrete space. In other words: every object consists of one or more
blocks aligned to a square grid, and time advances in turn-based steps. If
you’re thinking of Sokoban, you’ve got
the idea:
If you’re developing a game for mobile devices, chances are you have run into
the words “texture compression”. Texture compression helps to keep video memory
usage down, reduce download sizes and loading times, and may even reduce power
consumption. In this article, I take a comprehensive look at what the options
are.
Kotlin is a programming language developed by
JetBrains (the makers of IntelliJ IDEA), which compiles down to Java bytecode.
I got over my initial aversion for the ugly name, and decided to give it a try.
Now I never want to go back to Java. Here’s why.
Earlier this week, I added some variations to the procedural terrain in Dragon Attack.
Previously, the landscape was generated one segment at a time, forming a “chain” of rotated sprites. Each segment would have the same slope as the previous one, plus or minus a random number. To avoid going off the screen, the random number would be biased downwards near the top, and upwards near the bottom. This system worked great, but it made it pretty hard to implement variety in the terrain. For example, with just the previous height and slope as your “state”, how would you generate a mountain range?
In the past few years, I’ve done most of my game development in Java. It didn’t use to be that way. Before Android and libGDX came along, when C++11 was still C++0x, I used C++ almost exclusively. And recently, because of some performance-critical bits in Mystery Game No. 1, I got to use C++ again. And I loved it!
Update (14 September 2016): A month after I wrote this, RoboVM announced that they were winding down. I already had a (free) license, which is good until April 2017, but if you need a new one, you’re out of luck.
Update (14 September 2016): A month after I wrote this, RoboVM announced that they were winding down. I already had a (free) license, which is good until April 2017, but if you need a new one, you’re out of luck.
Any programmer worth their salt will have heard of the
DRY principle: Don’t
Repeat Yourself. The idea is that repetition is bad: it makes for more code to
read through, and it makes code harder and more error-prone to maintain because
you have to make the same change in multiple places.
== strings.properties ==
app_name=Confirmation App
confirmation=Are you sure?
== strings_en_UK.properties ==
confirmation=I'm terribly sorry to bother you, but would you please be so kind to confirm your certainty on this matter?
== strings_nl.properties ==
confirmation=Weet u het zeker?
Continue reading
Unfortunately, I can’t reveal too much about the game I’m currently working on,
but I can say that it’s like a board game. For the sake of this post, let’s
assume that the game is chess: there is a game board, there are some players,
and each player has a bunch of pieces that either have a position on the game
board, or have been captured. In this post, I’ll talk a bit about how to
architecture such a game in software.
Each field of programming presents its own challenges, and game programming is
no exception. In fact, I would say that a game is among the hardest things you
can program in general. Why? I can think of three main reasons, which are
closely related, as we will see.
Core to the idea of Bigcanvas is that it’s a shared space, where everyone can draw at the same time. Much as it would on a real canvas, this means people can interfere with each other. Properly handling this and making sure that everybody’s brush strokes made it onto the canvas turned out to be a fairly tricky problem.
How does one store the contents of an infinite canvas into a computer’s finite memory? One cheats. In this case, by taking advantage of the fact that the canvas may be infinite, but people’s drawings are quite finite. We simply don’t store the empty regions.
Setup: suppose you have a monochrome texture that contains a height map. A value of 1 is highest, and 0 is lowest. You want to use this texture as a ‘bump map’ to shade a 2D polygon via GLSL, computing light and shadow from the gradient of the height map at any given point. Let’s assume there is a single light source, infinitely far away (so the light rays are parallel). This is the setup we use in the game Aranami.
Ladies and gentlemen, Frozen Fractal presents… Bigcanvas! It’s an infinite online canvas that anyone can draw on. The ‘why’ is described within the app itself, so have a look! This blogpost focuses on the technical aspects, i.e. the ‘how’.
The JavaScript server code for Turtle Paint is becoming increasingly difficult to manage. People had warned me beforehand, but there’s no teacher like first-hand experience. The problems in a nutshell:
Game development can be a pain sometimes. Remember my writings on threading last week? This week has been more of the same kind of stuff: engine improvements, code cleanups, bugfixes, and only some small new features that are actually visible.
More work on performance this week. Things were getting a bit too slow for my tastes, meaning that they would likely be unplayable on medium-end phones. This work involved quite a bit of refactoring (which is jargon for “creating new problems to replace your old ones”), so I now have a bunch of screenshots of things… not working the way they should. Because this is a long and technical post, I will intersperse them for comic relief.
Although games vary wildly in appearance and mechanics, the structure of the underlying classes and objects is often similar. There is a “world” object, which contains everything else; there are multiple “entities” representing stuff in the world, there’s a “renderer” which tells each object to draw itself, etcetera. My game is no different, but still contains some interesting aspects that I would like to highlight.
After a week partly filled with lots of food and other Christmas celebrations, I’m back on track. I’ve done some polishing to make the game more game-like.
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.
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:
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.
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.
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.
To find the source of the instabilities, I pulled my code apart into more independent steps, that could individually be turned on or off. This did result in a speed hit, but allowed me to quickly trace the source of the problems to the advection routine. This is the part that moves the water along at its own speed.
Since no existing code fit my requirements, I started working on my own fluid simulator a few weeks ago. The idea was to try both a grid-based and a particle-based method, and see which worked better for my situation. I started with the grid-based version.