SGDK. Анимируем тайлы.

Предисловие.

В этой статье вы узнаете как анимировать тайлы на слоях (BG_A, BG_B), что позволит вам, создавать анимированные фоны. Но сперва нужно определится где в VRAM, находятся тайлы которые будем анимировать.

В конце статьи сделаем анимированные часы.

Скачайте SGDK проект с github.

Как будем анимировать.

Слои BG_A, BG_B, используют тайлы из VRAM, все что нам нужно это заменить эти тайлы.

Как SGDK строит тайлсет вашей карты.

При создании ресурса TILESET, SGDK проходится по всем тайлам карты слева-направо, сверху-вниз, т.е. сначала проходит по первой строке тайлов, затем по строке ниже и так далее. Что дает нам возможность забить порядок тайлов тайлсета в первую строку тайлов карты. Так можно сделать, но не желательно, ведь есть способ получше. А именно, создание своего тайлсета карты.

Создание собственного тайлсета карты.

Создайте карту вашего уровня в Aseprite, или другом редакторе.

Определитесь, какую часть карты вы будете анимировать (в тайлах). В моем случае, я выбрал часы.

Карту в .res файле, импортируете таким образом:

Данные настройки максимально компактно уместят тайлы карты.

Теперь, создайте проект под свою карту, пример проекта можете взять в этой статье. И запустите его в эмуляторе Gens KMod.

Выберите CPU->Debug->Genesis->VDP, и нажмите Tiles to Bitmap, чтобы сохранить тайлсет.

Откройте этот тайлсет в Aseprite, и выделением, перекопируйте тайлсет на картинку карты, чтобы палитра тайлсета подстроилась под палитру карты. Данный прием, я объяснял в этой статье.

И меняйте порядок тайлов так, чтобы тайлы которые вы хотите анимировать шли слево-направо и сверху вниз. У меня получилось следующее.

И привязываем этот тайлсет (map_tileset.png) к карте:

Хотя, в данном случае редактирование тайлсета не потребовалось, у вас может случится что SGDK, оптимизирует тайлсет там где не надо, т.е. в области анимации. В этом случае, используйте данный метод.

Создание анимации.

Анимацию делаем отдельными кадрами, размер кадра, в моем случае 32×32 px (размер часов). Кадры должны быть в той же палитре, что и карта уровня.

В .res файл импортируем эти картинки как тайлсет, таким образом:

Т.е. импортируем как есть, без удаления дубликатов.

Подготовка завершена, теперь разберем код.

Разбор кода.

Разберем функцию main

int main()
{
	u16 vramIndex = TILE_USER_INDEX;
	PAL_setPalette(PAL0, pal_img.data, CPU);
	VDP_loadTileSet(&tileset_img, vramIndex, DMA); //Импортируем тайлсет карты 
	bga = MAP_create(&map_img, BG_A, TILE_ATTR_FULL(0, FALSE, FALSE, FALSE, vramIndex)); //Создаем карту
    vramIndex += tileset_img.numTile;
	MAP_scrollTo(bga, 0, 0); //Обновляем карту, чтобы она была нарисована с первого кадра
	s16 timer = 120; //таймер, задающий скорость анимации
	s16 cur_frame = 0; //текущей кадр анимации
	u16 baseTileIndex = bga->baseTile; //индекс тайла в VRAM куда будем вставлять тайлсет
        //Маcсив тайлсетов (кадров)
	TileSet** tile_anim[] = {&tileset_clock_anim1, &tileset_clock_anim2, &tileset_clock_anim3, &tileset_clock_anim4};
	while(1){
		handleInput();
		timer--;
		if(timer <= 0){ //если таймер истек
			VDP_loadTileSet(tile_anim[cur_frame], baseTileIndex, DMA); //Загружаем тайлсет 
			timer = 60; //Возобновляем таймер
			cur_frame++; //текущий кадр +1
			if(cur_frame > 3){ //зацикливаем текущий кадр
				cur_frame = 0;
			}
		}
		SYS_doVBlankProcess();
	}
    return (0);
}

Т.е. по кругу заменяем тайлсет часов следующим кадром.

В bga->baseTile хранится первый тайл тайлсета карты, и так уж вышло, что этот тайл принадлежит часам.

u16 baseTileIndex = bga->baseTile;

Остальное я объяснил в комментариях, либо это уже объяснял здесь.

По итогу, получили следующее.

Итоговый результат.

Пожалуйста отключи блокировщик рекламы, или внеси сайт в белый список!

Please disable your adblocker or whitelist this site!