Palix: tiles
A tilemap is rectangular grid of tiles, where each tile is a square made of pixels. The square is either 16 × 16 ("jumbo" tiles typically used for game levels) or 8 × 8 (typically used by fonts). The tile pictures come from a tileset, which is a collection of numbered tile images. For example, a video game forest might use a tile 7 for each bush, a tile 13 for a vertical segment of a dirt road, etc. As another example, the Hybrix text console is a tilemap where each tile is a text character (letter or number or punctuation mark or graphical glyph). In this case, the tileset represents a typeface font.
Note: The Hybrix framework defines two "tilemap" classes
tilemapandio_tilemap. Thetilemapclass is used for designer art resources, whereasio_tilemapdescribes the hardware interface for rendering. Thetile_layerclass preparesio_tilemapusing data fromtilemapandtileset.
Screen dimensions
Here's a handy reference for measuring screen dimensions as tiles:
| Screen size | Units |
|---|---|
| 320 × 224 | pixels |
| 40 × 28 | regular tiles (8 × 8) |
| 20 × 14 | jumbo tiles (16 × 16) |
Rendering
A tilemap is a two dimensional grid of cells, arranged in left-to-right rows, starting from the top row. The rows increase downwards like the Y axis, and columns increase rightwards like the X axis. Each cell contains a 16-bit pair called a tile code, whose binary bits encode three pieces of information for that cell:
| Tile code bits | Values | Encoded field |
|---|---|---|
| 0…9 | 0 – 1023 | tile index: indicates which tile to show from the tileset |
| 10…14 | 0 – 31 | theme index: the color palette theme used in this cell |
| 15 | 0 or 1 | matte coloring: if 1, then the io::matte_color is applied in this cell |
If enabled, matte coloring replaces any transparent pixels with the globally specified io::matte_color. The HASCII {mat} mode makes use of this feature to add a solid background for text fonts.
The io_tilemap.x and io_tilemap.y fields position the entire tilemap on the screen. The coordinate origin is in the upper-left corner of the screen, with the Y axis pointing downwards and the X axis pointing to the right.
The tileset data is an array of up to 1,024 tile images. io::tileset_a_addresses defines the tileset for io::tileset_a and so forth. The actual array size is indicated by io_tilemap.tile_count, which is important to prevent oversized index values from causing memory faults.
Each array element of io::tileset_a_addresses stores the memory address of that tile's bitmap pixels, one byte per pixel, in left-to-right rows, starting from the top row. For regular 8 × 8 tiles, there will be 256 pixels. For "jumbo" 16 × 16 tiles, there will be 1,024 pixels. The first byte is the upper-left pixel of that tile.
Tilemap A always appears in front of Tilemap B, which always appears in front of Tilemap C. See display priority for sprite interaction with the tilemap.
Palix-sized tilemaps
The io_tilemap::col_count and io_tilemap::row_count locations must have one of these dimensions:
16, 32, 64, 128, or 256
If any other number is used, it is considered an error—Palix will not display that tilemap at all.
The Hybrix designer warns you if a tilemap's dimensions are not Palix-sized. Why allow non-Palix sizes at all? This can be useful for tilemaps that will not be rendered directly by io_tilemap. The idea is to configure io_tilemap with a separate tilemap buffer that is Palix-sized, and then the non-Palix tilemaps get copied into this buffer. For example, the framework's console sets up a kernel::console_grid buffer for font text. You could make a tilemap that is a dialog box with a non-Palix size, and then at runtime your program could copy it onto the screen. Another common example is an infinite scrolling plane (io_tilemap::edge_mode = 0), where the program generates the tiles interactively as they scroll onto the screen.
I/O definitions
class io_tilemap # size 16
# Screen coordinates of upper-left corner of tilemap
var x: pair, y: pair
# Possible values: 16, 32, 64, 128, 256
var col_count: pair, row_count: pair
# A pointer to a grid of tile codes arranged in left-to-right rows,
# starting from the top row. the array index is row*col_count+col.
# Each tile code is a 16-bit pair:
# bits 0..9 encode the tile index (0..1023) from the tileset
# bits 10..14 encode the theme index (0..31) into io::themes
# bit 15 if set, io::matte_color replaces any clear pixels in this tile
var tile_codes_address: int
# 0 = wrap: the map wraps around, repeating infinitely in every direction
# 1 = clip: cells outside the map bounds are transparent
var edge_mode: byte
# ------------------
# Tileset properties
# 0 = tiles are 8 x 8 pixels
# 1 = tiles are 16 x 16 pixels
var jumbo: byte
# 0 < tile_count <= 1024
var tile_count: pair
end class
module io
. . .
inset tilemap_a: io_tilemap located at $d0_0310 # ..$d0_031f
inset tilemap_b: io_tilemap located at $d0_0320 # ..$d0_032f
inset tilemap_c: io_tilemap located at $d0_0330 # ..$d0_033f
. . .
inset tileset_a_addresses: int[size 1024] located at $d0_1000 # ..$d0_1fff
inset tileset_b_addresses: int[size 1024] located at $d0_2000 # ..$d0_2fff
inset tileset_c_addresses: int[size 1024] located at $d0_3000 # ..$d0_3fff
end module