Thursday, June 11, 2015

Developing Memory Matrix

Hello, my name is Lucas (not makapuf) and I wanted to walk you through my experience developing a game for the bitbox console.

Intro screen.  Prepare to memorize!

Let's get started!

I learned about the bitbox on Tindie, and got in touch with makapuf via e-mail. After checking out the SDK, downloading and testing a few games (the emulated versions), I liked just how easy it was to get started with development (on linux). I am delighted by the bitbox's open-source nature, and I liked the idea of making retro games (without cartridges, with modern code). So I set about making a game. To be honest, I wanted to make sure that the bitbox was capable of playing the games I would create, before I got one :D.

I wanted to code something simple, because it's good to start small. I had a pyglet version of Memory Matrix lying around, and realized this game would work very well with a tile-based engine. (In turn, I think I originally got the game idea from Lumosity's Memory Matrix, but mine is better since it has color ;).) I used bitbox-polar as a starting point, because that's a perfect simple example of a tile-engine for the bitbox, with an extra sprite that moves around. Perfect, that's exactly what we need to make a game about moving colored squares around!

Simple layout you have to memorize.

There's simplicity in developing for the bitbox. A lot of the hard work is done for you in makapuf's bitbox SDK. This means you can focus on the code of your game, as well as the art style. C is an interesting language (I'm more used to C++, and I'm told you can also code in C++ with the SDK), but the imperative programming style makes it easy to see what is going on. In a simple game, you have a few state variables (usually global), which allow you to control what happens in each game frame. I also made my own sprites/tiles and "music" for the game, using Gimp (with a wacom pad) and bitbox-chiptracker (from pulkomandy, but I modified it a bit for my own purposes). I did just a simple song, because I wanted to finish the game quickly, though I hope to make more music for the bitbox in the future. (I like writing electronic stuff, and if you like that genre, shameless plug: http://ible.bandcamp.com/.)

 As for the code: In each frame, the bitbox checks whether it needs to jumble the blocks or create a new set of blocks for the next level. These things are done in advance, hidden in a variable next_blocks, because it is important to randomize these things and make sure the difficulty is hard enough (but not too hard), based on your current score. Each frame the code might jumble the current set of blocks, check the jumble, create a new set of blocks, or check the new set of blocks. (Separating these out was an effort to avoid the bitbox hanging in some evil loop of bad jumbling.) It took a little coordination to get this working. At one point, the player was actually getting the score of the next board, which could be significantly higher than the current.

To jumble a matrix, the code makes sure to make a different one than you start with.

Deciding the score of the layout is quite important, since it's easy to grasp patterns with our minds, even if the board has lots of tiles. You start with a base score, based (roughly) on the number of possible boards with those colors, but then subtract points if the code spots patterns (like lots of colors next to each other). You also need to deal with an edge case: for a layout where each square has the same color, the base score is zero, because it is dumb to play the game with that layout.

Things are getting tough.

For more detail on the specific base score equation: Say you have N total blocks and C[i] blocks with color i (i=0 to 3, so that sum_i C[i] = N); the specific layout has been chosen randomly. You can find the edge case if C[i] = N for any i. In my original pyglet implementation, I used something like this to determine a rough idea of the total number of possible boards (factorials, yay!):
    N! / (C[0]! * C[1]! * C[2]! * C[3]!)
(I don't think that's exact, but I'm not a combinatorics major...). I wanted to simplify this for the bitbox, because I didn't want to have to deal with factorials. I decided on this:
    product_i [ C[i] * (N - C[i]) if (C[i] > 0) otherwise 1 ]
This also has the nice feature of giving zero if any C[i] = N. The max base score you can get has C[i] = N/4 for all i and N = 4*8 is the largest matrix in the code: in other words, 1358954496. That might not be as big as what the pyglet base score would be (99561092450391000), but it still motivates using 64 bit integers to store scores!

The largest matrix, with all possible colors... pure evil.  What just 20 seconds to memorize?!

Well, there are some other code details, like keeping track of what's the max possible incorrect you can get wrong, in order to make sure the blocks are jumbled enough -- though again my equation might be just a heuristic and not completely sound mathematically... (Oh, but it is a hint for how to memorize boards a bit easier.) Feel free to ask questions on the bitbox google mailing list (https://groups.google.com/forum/#!forum/bitbox-console) or raise issues on the github if you encounter errors/bugs in the game (https://github.com/lowagner/bitbox-mmat).

As for the future, I am thinking of adding some more sounds to the game, in case of losing or winning a level, but besides that I don't have any many other plans. The code could give you a better score for beating a level in a shorter time, but I didn't want the focus to be on time, but on careful precision. I do want to double check my "subtract points" algorithm, to make sure that a board that is half one color and half the other isn't that high of a score ;). Who knows, maybe the whole scoring system will become completely reworked. But at any rate, my eyes are looking to the next game...

So, after I did my developing, makapuf helped with some logistics (testing it on a real bitbox, advising good button press/unpress logic in the code). I think the story has a good ending, because soon I will be the happy owner of a bitbox console. Thanks makapuf for all your hard work! 

TL;DR: I really enjoyed developing a game for the bitbox; its openness, excellent examples, and simplicity makes it easy to be efficient and finish projects.

No comments:

Post a Comment