I'm going to try and explain how I currently handle coins and breakable blocks.
I call coins and breakable blocks "special tiles".
Special Tile Data Format
In the simple case, level data is an array where each element is a VDP tile. As a reminder, the data per tile looks like:
Code: Select all
pccvhnnnnnnnnnnn
p = Priority flag
c = Palette select
v = Vertical flip
h = Horizontal flip
n = Pattern name
Because it's already formatted, I can simply copy a part of the level directly to the VDP. But with special tiles, it's not that simple anymore.
I needed to be able to identify a special tile from a regular one, so I chose the 11th bit. It reduces the number of regular tiles from 2k to 1k, but it opens up a few things for me.
Once a tile has it's 11th bit set, the tile data is parsed like this:
Code: Select all
AAAAABCCDDDDDDDD
AAAAA = pattern name (0 - 31)
B = special tile bit
CC = special tile type (0 - 3)
DDDDDDDD = index into a state table (0 - 255)
AAAAA is the index of the pattern to use, offset by a known location stored elsewhere. For example, the four tiles that make up a coin go from 0 to 3. The actual coin tiles are stored at a known location in memory. The AAAAA number is added to the known memory location to get the actual tile in memory.
B when the bit is set, it means it's a special tile.
C A value of 0 means a coin, 1 means a breakable block. I'm currently feeling pretty limited by this as there are only 4 values, so I might steal an extra bit from AAAAA since I don't think special tile patterns will be bigger than 4x4 tiles. The bits won't be contiguous so I'll have to do some bit gymnastics to get the 3 bits together. Annoying but doable.
DDDDDDDD is an index to state table of 256 values. Each type of special tile has a state table. The tiles that make up a coin or breakable block all point to the same element in the state table. If the element is 1 then the special tile is visible, if 0, then invisible. At the moment, I can have up to 256 instances of a type of special tile. This is a pretty good number.
Drawing Special Tiles
I draw the background by drawing rows or columns in the direction the screen is scrolling. A "strip of tiles" that make up a row or column is pre-computed into a buffer during gameplay and DMA'd into the VDP during vblank.
For each tile when building a strip of level data, if it's not a special tile then I simply copy its data to the strip. If it's a special tile, then I go through a procedure of:
1 - get the special tile type (0 - 3)
2 - get the index into the state array (0 - 255)
3 - if the state is 1, then compute the actual pattern name (offset + known memory location) and copy that into the strip of tiles, else return a known blank tile.
This will definitely change since the level data is currently stored uncompressed. Once I introduce compression, the building of tile strips will have to change.
Interacting With Special Tiles
When flying, the Goplanes continuously detects the tile it's currently on for collisions. The current collision algorithm goes like:
Code: Select all
- get the current tile
- if it's a regular tile:
- look up the tile with the tile collision type table. Each regular tile has a type (solid, transparent, etc)
- if it's solid, compute collision stuff.
- Else, do nothing.
- if it's a special tile:
- get it's type
- if it's a coin
- get the index into the coin state array
- check the coin state
- if the coin state is 1, add 1 coin to the coins counter, turn state to 0, erase the coin from the plane and play a sparkle effect.
- Else, do nothing.
- if it's a breakable block
- get the index into the breakable block state array
- check the breakable block state
- if the state is 1,
- if the plane is not in afterburner mode, then treat as regular tile collision.
- Else set the state to 0, erase the block from the plane and play an explosion effect.
Exporting Special Tiles
I use Tiled to build levels and have made my own exporter for Goplanes.
In Tiled you can use multiple tilesets in one map. In my latest map (which is seen in my last few youtube videos) I use three tilesets:
- a tileset that contains the regular background tiles
- a tileset named "coins" that contains the 16x16 pixel coin image, broken up into 8x8 tiles
- a tileset named "breakableblocks" that contains the 32x32 pixel breakable block image, broken up into 8x8 tiles
Building a map this way means I can reuse the coin and breakable block tilesets without having to add them to the regular background tiles.
When I export the level, for each tile:
- check which tileset it belongs to
- if it belongs to the regular tileset, save the tile in the regular VDP format
- if it belongs to a special tileset ("coins" or "breakableblocks"), save the tile in the special tile format
I also have to make sure that the 2x2 tiles that make up a coin or the 4x4 tiles that make up a breakable block all point to the same element in the state array.
Conclusion
That's it!