I get the feeling that having all the graphics modes in the PokittoLib makes it harder to maintain and make new modes. Instead, PokittoLib could provide a bare hardware abstraction, maybe just one graphics mode, and the other modes would be libs that built on top of that.
As for tile modes, API-wise, this is what I have in the lib used by Aquarium256:
void setTileImage( unsigned char id, const unsigned char *tile );
extern int cameraOffsetX, cameraOffsetY;
typedef int (*TileProvider)( int x, int y );
void setTileProvider( TileProvider tp );
First you use setTileImage to associate an id with a 16x16, 8-bit bitmap:
setTileImage( 0, bitmap ); // render bitmap for tile 0
To move the camera, simply set cameraOffsetX
and cameraOffsetY
.
A 15x12 grid of 16x16 tiles is managed automatically. When the camera moves, all the tiles are shifted within the grid and any missing tiles are requested from the tileProvider
. This makes it easy to stream map data from the SD card to RAM or generate tiles procedurally, and you can mask away other data before sending it to the renderer. If the camera moves one column to the right, the tileProvider is called for each tile on the rightmost column.
Say you use 8-bits per cell, where the lower 4 bits are the tile Id and the upper bits are for things like collision detection. You can define a tileProvider like this:
const unsigned char level1[][] = {...};
const unsigned char levelMask = 0x0F; // upper nibble for extra stuff
setTileProvider( []( int x, int y )->int{
return level1[ y ][ x ] & tileMask; // tile id at row Y, column X.
});
To create sprites and tiles, I drop a PNG and a PAL file into a converter.
Sprites can have any size and are rendered using the blit( x, y, sprite, BlitOp );
function. BlitOp can be NORMAL or FLIP_HORIZONTAL. I didn’t do FLIP_VERTICAL yet.
Since sprites are generally not square, I don’t store them as square bitmaps. This helps decrease space use and it’s faster to render because it does not have to do transparency tests.
/*
----------------
----------------
----------------
----------------
--------- ----
------- ----
-- --######----
- ##########--
- ###########-
-# ## ####--
------ #####----
------- #------
----------------
----------------
----------------
----------------
*/
const unsigned char fish8_sprite8[] = {
//width, height
16,16,
// 16x { offset, length }
0,0,7,3,6,4,6,4,7,3,7,3,6,5,5,7,5,7,4,8,4,7,4,7,7,3,7,3,8,1,0,0,
0x1d,0x1d,0x3e,
0x1d,0x1d,0x1d,0x1d,
0x1d,0x1d,0x1d,0x1d,
0x35,0x2a,0x3f,
0x2a,0x2a,0x2a,
0x2a,0x2a,0x2a,0x2a,0x1d,
0x1d,0x2a,0x2a,0x2a,0x1d,0x2a,0x1d,
0x1d,0x2a,0x2a,0x2a,0x1d,0x2a,0x1d,
0x1d,0x1d,0x2a,0x36,0x2b,0x1d,0x2a,0x46,
0x1d,0x1d,0x2b,0x2b,0x2b,0x2b,0x2b,
0x1d,0x1d,0x2b,0x2b,0x2b,0x2b,0x2b,
0x2b,0x2b,0x2b,
0x2b,0x2b,0x2b,
0x2b
};