¡So much done!
Title Screen & Messages
As shown ’bove, a title screen, as well as a message screen that pops on ’pon starting the game, to say what you should do to beat the level, & 1 that appears ’pon beating the level.
Game States
In relation to this, a game state system, which can not only change states, but also “pop” & “push” states as a way to interrupt states & still be able to go back to them.
Since I’m terrible @ ’splaining what I’m doing—it’s mostly just me breathlessly talking ’bout something I did, as if by magic—here’s a much better explanation. In fact, I recommend reading most o’ those articles; they were an immense influence o’er the past year or so.
Pause Menu
Speaking o’ which, the latter is used in the pause screen I made, as well as the level-beginning aforementioned message. (Unlike the victory message, this message must pop up after the LevelState has already started so it can get info from its Goal—mo’ on that later).
Levels with Multiple Maps
The level class with submaps held by it, as well as fully-working warps that allow the player to move throughout the entire level.
Level Goals
Within the level class is also a goal class that determines how to beat the level (in addition to touching the goal block, which always completes the level). For this level, the goal is to collect 75 gems.
Palettes
A palette system. With so many things turning out easier than expected, this surprised me by how long it took to get right, simply due to my inability to decide how to organize the code. I finally elected to keep the actual palette file in the Graphics class, since it works directly with it. I then added a PaletteSet, which is just the name o’ the hue & the background # that can be used to create a palette, to GameState & Map. A GameState automatically creates a PaletteSet when created, & the Game engine automatically changes Graphics’s palette ’pon changing states & the Graphics automatically reloads graphics to apply the palette. This keeps the palette that’s applied in LevelState from continuing to any other states, other than the pause menu, which has its palette pushed to it in its constructor from the level state. Meanwhile, GameState also has a method that allows for changing its palette manually, which filters through to graphics with the same automation, which is used for map-switching (since that doesn’t actually change the game state).
It should be obvious that the palette system wasn’t created out o’ necessity or practicality, since SDL can easily load images with a full range o’ colors; I simply chose it for stylistic purposes. I don’t know: sometimes monochrome looks nice, specially when contrasted with other monochrome hues. Plus, Super-Game-Boy-like monochrome graphics is a form o’ retro callback that doesn’t seem to be o’erused yet, like most.
Text
A text system, which includes some frills, such as auto-aligning text lines & blinking text. This is not done by loading a font, since I actually find that that would add a bunch o’ complications that I don’t want to deal with, but just by using a graphic file & making a simple conversion map that outputs a frame # for a given character & functions for getting the x & y coordinates from that frame, which corresponds to the position o’ that character in the graphic file.
This reminds me that I didn’t go into much detail ’bout some o’ the things I’ve already done, ’specially the level construction, which is 1 o’ the most complex aspects.
1 programming pattern I’ve noticed a lot is breaking 2d grids into a single line o’ #s—what I usually call “frames.” For example, the text system I mentioned earlier did that, as well as the tilemaps for level maps (Tiled outputs 1d arrays). The best way to deal with that is with these 2 formulae that I’ve used countless times in programming:
1: x = n % width
2: y = floor( n / width )
“x” & “y” refer to their respective cardinal positions. For example, if one wants to find out where to place a block from the 28th ([27]) element in a 1d array for a 128-block-wide map, simply look for 27 % 128, while its vertical position is floor( 27 / 128 ). (Note: if this position is in pixels & not blocks, you’ll need to multiply the answer by the width & height respectively in pixels o’ blocks.
The 1st formula uses remainders, which, going up in #s, counts up the #s up to the 2nd # (the width, which is, logically, the maximum x position), & then back to 0 (the minimum x position), counting up ’gain & ’gain till the last block:
012345678 012345678 012345678 012345678
The y formula, meanwhile, stays @ the same # for every width # o’ blocks, & then rises 1 for ’nother width # blocks, & so on:
00000000 11111111 22222222 33333333
Looking @ these graphs, one can hopefully see how these formulae make sense, since I certainly can’t ’splain it logically.
I don’t know what I’ll do next. Maybe sleep.