I'm possessed by Neo political correctness. It's block woman!
Aha! Good catch. Though, it's said she does identify as a man, and also doesn't mind much which pronouns she's referred to by
Background Brick TilesNew backgrounds! Block Man (aka Icy Girl) will be set within a crypt. So the art direction for the game will be 75% cute and 25% creepy
I needed backgrounds but didn't want to use a level editor, tile editor, or anything like that in order to save time. I just need something that looks nice and can be done in less than half a day and forever after forgotten.
I implemented as simple of a system for drawing backgrounds as I could think of. After studying Minish Cap background tiles, I noticed a clever way to tile bricks with only two basic patterns that must be applied in a checkerboard pattern. Since I've designed this game to have a screen similar to a Game Boy Advanced, I chose the game's internal screen dimensions to be 320x240 pixels, and tiles to be 16x16. This leaves a screen size of 20x15 tiles.
However, since the tiles are *not* odd dimensions it is impossible to perfectly tile bricks or squares within a single tile by dividing it in half, or any equidistant amount of pixels. Below is a picture showing an example of how it's not so easy to make tiles for an even number of pixels with just squares/rectangles, without big 2-pixel thick borders, or unevenly sized borders.
What I noticed in Minish Cap was the trick to simple leave one side of a tile without any brick borders. This offset bricks within one tile by one pixel... But the result looks great! And the tile pattern of zig-zag bricks is really nice to help give the background some variety and break up all the horizontal/vertical lines.
So this means there are two types of tiles, like a checkerboard. Ones with two horizontal bricks, and ones with two vertical bricks. That means I can hand-draw maps with two different elements like these (below), and easily render them.
array<array<string_t>> BackgroundMaps = {
{
"XXXX0000XXXX00000XXX",
"XXXX00000XXXXXX000XX",
"00XX0000000XXX000000",
"00000000000XXX0000XX",
"00XX000000000X00XXXX",
"00XXX000XX00XXX00XX0",
"00XXXX00XX0000000000",
"0000XX0000XX00XXX000",
"XXX0000XX0XX00XXX000",
"XXX0XX0XX000XXXX0000",
"XXXXXX0XX00XXXXX00XX",
"XXXX0X0XX00XXXXX00X0",
"XXX0000XX000XXX0000X",
"XXX00XXXX000XXX00XXX",
"XXX00XXXX000XXX00XX0",
},
{
"00000000000XXX0000XX",
"XXXX00000XXXXXX000XX",
"00XX0000000XXX000000",
"XXXX0X0XX00XXXXX00X0",
"00XX000000000X00XXXX",
"00XXX000XX00XXX00XX0",
"XXXX0000XXXX00000XXX",
"00XXXX00XX0000000000",
"0000XX0000XX00XXX000",
"XXX0000XX000XXX0000X",
"XXX0000XX0XX00XXX000",
"XXX0XX0XX000XXXX0000",
"XXXXXX0XX00XXXXX00XX",
"XXX00XXXX000XXX00XXX",
"XXX00XXXX000XXX00XX0",
},
};
Then I exported two arrays of tiles, one for each checkerboard spot. After doing a little bit of math, and using a seeded RNG generator, unique background tiles are selected for X and 0 based on the given map. Briefly: an X is picked as either a red/black checkerboard pattern based on its index, and then a random tile of that type is deterministically chosen to be drawn. Here's the function to initialize an array of brick sprites.
void InitBackgroundBricks(int seed)
{
rnd_t rnd = rnd_seed(seed);
int background_index = rnd_next_range(rnd, 0, BackgroundMaps.count() - 1);
background_bricks.clear();
for (int i = 0; i < 15; ++i) {
for (int j = 0; j < 20; ++j) {
string_t path;
if (BackgroundMaps[background_index][i][j] == 'X') {
if ((i & 1) ^ (j & 1)) {
path = BricksEven[rnd_next_range(rnd, 0, BricksEven.count() - 1)];
} else {
path = BricksOdd[rnd_next_range(rnd, 0, BricksOdd.count() - 1)];
}
} else {
path = "data/brick_empty.png";
}
sprite_t s = AddSprite(path);
s.transform.p = v2((float)(j * 16 + 8 - 320/2), (float)((15 - 1 - i) * 16 + 8 - 240/2));
background_bricks.add(s);
}
}
}
So now backgrounds can be easily added by modifying text arrays to pick where bricks are drawn, the brick image index is randomly chosen, but, the checkerboard pattern is preserved. Also since the RNG is deterministic, each level is assigned varied tile indices automatically!
All in all the code took about 25 minutes to write and integrate into the game! Yay, as simple as possible backgrounds achieved
Though there's no background walls... Yet.