Buzz Grid on the desktop

2012-08-20

I'm conflicted about this. On the one hand, I've spent the last two articles complaining about the difficulties of writing portable software. On the other hand, I've spent five days porting Buzz Grid to Pygame, and it came out better-looking that the original!

buzz grid desktop

This time, however, I was able to keep the gameplay unchanged.

I was doubtful about that, see. Square Shooter needed quite a few adjustments, and Buzz Grid has significantly more complex logic. It took me five days to complete the port; a rewrite would have doubled the time at the very least. As it is, capping the framerate at 20FPS did the trick, with the only downside being visible flickering.

On the plus side, Python's qualities have been even more evident with the harder task. A shuffle() function is standard; unique() became trivial. But the most interesting part was porting this bit of JS code:

	this.map = new Array(data.map.length);
	for (var i = 0; i < data.map.length; i++) {
		this.map[i] = new Array(4);
		for (var j = 0; j < 4; j++) {
			this.map[i][j] =
				data.map[i][j]
					* GridGame.resolution;
		}
	}

which on the first attempt became:

	self.map = []
	for i in range(len(data["map"])):
		self.map.append([0, 0, 0, 0])
		for j in range(4):
			self.map[i][j] = data["map"][i][j] * resolution

This works, but it's non-idiomatic and arguably even ugly. Luckily, the correct Python equivalent was a little thinking away:

	self.map = [[j * resolution for j in i] for i in data["map"]]

The graphics side was somewhat trickier.

First of all, Pygame surfaces don't support rotation or scaling of the coordinate system, nor transparency in drawing primitives. But I knew from the Java ME port that neither was an obstacle. The known, fixed resolution even made certain things easier. The hard part was doing the explosions.

See, the comic book-style "visible sound effects" in the original implementation were simply because I couldn't think of anything better back then. That they ended up giving the game personality was a happy accident. But for better or worse, they are completely impractical to do with Pygame's rigid text API. Worse, it turns out text rendering does impact performance after all; you can see it in the CPU usage.

So I was faced with a double problem: to come up with an interesting particle effect, and to implement it from scratch.

It was my recent foray into voxels that gave me the idea, even though Buzz Grid is purely 2D: the trick is to use the pixels in a bitmap in unusual ways, not just for direct blitting on the viewport. After a false start, I settled for 8x8 icons stored inline as a simple matrix of bytes, and drawn in an expanding pattern. I did my best to give them interesting shapes, because the random jitter was an afterthought; the shapes help either way. While at it, I did away with the visible countdowns, which the green explosions now obscured.

Last but not least, it's worth noting that even with the additions the Python code again ended up shorter than the original Javascript. The strong typing also contributed to making the job easier, even though having to remember where I used dictionaries versus objects was annoying. And did I mention the merits of an ample standard library? Clearly, this won't remain just a one-off experiment. Stay tuned.

Tags: , .