Введение.
При создании HUD в игре на Sega Genesis, у вас есть 2 пути:
- Использовать WINDOW слой
- Использовать спрайты
WINDOW слой откусывает кусок BG_A, это значит что HUD не получится сделать прозрачным. Тогда как, спрайтовый HUD лишен этих недостатков.
Что мы знаем о спрайтах:
- Sega Genesis поддерживает спрайты от 8×8 px до 32×32 px (реальные спрайты).
- Спрайты побольше, достигаются за счет одновременного использования нескольких спрайтов (программные спрайты).
- У спрайтов есть лимит на скан-линию в 20 спрайтов. Т.е. 20 спрайтов могут пересекать горизонтальную линию поперек экрана, иначе они багуют.
- Максимальное количество спрайтов — 80.
Так вот, почему-бы не использовать доступное пространство внутри спрайта — эффективно. Т.е. редактировать тайлы внутри спрайта, что-бы уменьшить вероятность влезть в лимиты на скан-линию.
Сперва, скачайте проект с github, затем откройте main.c в папке src. Разберем его.
Меняем тайл спрайта.
TileSet tempTileset;
tempTileset.tiles = MEM_alloc(sizeof(u32)*img_1.tileset->numTile);
unpackTileSet(img_1.tileset, &tempTileset);
VDP_loadTileSet(&tempTileset, sonic_obj->attribut & TILE_INDEX_MASK, CPU);
Этими строками, я создал тайлсет и аллоцировал под массив тайлов нужное количество байтов.
TileSet tempTileset;
tempTileset.tiles = MEM_alloc(sizeof(u32)*img_1.tileset->numTile);
img_1 — является Image ресурсом, внутри которого есть указатель на tileset, из которого, я достал количество тайлов.
Далее, с помощью функции unpackTileset, я распаковал тайлсет img_1 и записал в переменную tempTileset.
unpackTileSet(img_1.tileset, &tempTileset);
При распаковке, выделилась память под тайлсет, не забудьте очистить её (MEM_free) когда уже не будет нужна (при смене уровня например).
Тайлсет получен, осталось записать его в VDP, для этого используется VDP_loadTileSet. У которого следующий синтаксис:
VDP_loadTileSet(откуда_брать_тайлсет, куда_в_VDP_писать, способ_передачи);
где:
- откуда_брать_тайлсет — это указатель на переменную типа Tileset
- куда_в_VDP_писать — номер тайла в VDP, куда будем писать.
- способ_передачи — может быть CPU, DMA, DMA_QUEUE, DMA_QUEUE_COPY, самый стабильный CPU, а также, самый медленный.
VDP_loadTileSet(&tempTileset, sonic_obj->attribut & TILE_INDEX_MASK, CPU);
Данная строка:
sonic_obj->attribut & TILE_INDEX_MASK
Возвращает номер начального тайла в VDP, который использует спрайт.
Все разобрал, остальное либо копипаст, либо обсуждалось в предыдущих уроках. В итоге получили следующее.
А еще, вы можете отредактировать тайл под себя, вот так:
unpackTileSet(img_1.tileset, &tempTileset);
tempTileset.tiles[0] = 0xFFFFFFFF;
tempTileset.tiles[1] = 0xFFFFFFFF;
Каждый символ после 0x, отвечает за индекс цвета в палитре. Таким образом, вы можете менять пиксели тайла.
Генерируем свой тайл, и подставляем в спрайт.
Вы также, можете заменить тайл спрайта сгенерированным тайлом, примерно так:
const u32 sprite_tileset[16] =
{
0x000FF000,
0x00FFFF00,
0x0FFFFFF0,
0xFFFFFFFF,
0xFFFFFFFF,
0x0FFFFFF0,
0x00FFFF00,
0x000FF000,
0x000EE000, 0x00EEEE00, 0x0EEEEEE0, 0xEEEEEEEE, 0xEEEEEEEE, 0x0EEEEEE0, 0x00EEEE00, 0x000EE000
};
PAL_setPalette(PAL3, spr_sonic.palette->data, DMA);
sonic_obj = SPR_addSprite(&spr_sonic, x, y, TILE_ATTR(PAL3, 0, FALSE, FALSE));
SPR_update();
SYS_doVBlankProcess();
VDP_loadTileData(sprite_tileset, sonic_obj->attribut & TILE_INDEX_MASK, 2, СPU);
Здесь, sprite_tileset представляет из себя данные тайлов спрайта. В примере видно, что каждое число после 0x, задает цвет (от 0 до F, или от 0 до 15).
И, функцией VDP_loadTileData, записываем тайл в VRAM по такому синтаксису.
VDP_loadTileData(тайлсет, номер_тайла_в_VDP, количество_загруженных_тайлов, способ_передачи);
В итоге, получили следующее:
Конвертируем тайлсет в код.
Можно сконвертировать картинку в код, подобного типа:
const u32 sprite_tileset[16] =
{
0x000FF000,
0x00FFFF00,
0x0FFFFFF0,
0xFFFFFFFF,
0xFFFFFFFF,
0x0FFFFFF0,
0x00FFFF00,
0x000FF000,
};
Делается это с помощью Python скрипта написанного Greg Gallardo, скачайте его в отдельную папку.
В папке со скриптом, добавьте картинку с вашими тайлами, и переименуйте в ground_tiles.png, и запустите скрипт. Код, отобразится в консоли.