TSconf: Sprites

А вот чё бы и не навалить поверх графики спрайтов-то, а?
Они-то у нас искаропки.

Дао говорит: Спрайт — это графический тайл размером от 8 до 64 точек, который может быть выведен в координаты 0-511 по X и Y, с возможностью отражения отображения по вертикали / горизонтали, и имеющий прозрачность.
Всего доступно 85 спрайтов для одного спрайтового слоя.


В общем, отработка спрайтов выглядит следующим образом:
  • Спрайт нужно разместить в памяти точно таким-же образом, как для тайлов (или на экране в режиме 16 цветов).
  • Палитра спрайта так-же должна быть загружена в общую палитру системы.
  • После этого — загружаем описание спрайта в систему и включаем отображение.
Спрайт становится виден.

Разберём по порядку:

Ну, во первых — сам спрайт.
Спрайт у нас может иметь размер кратный 8 точкам как по Х, так и по Y, от 8 до 64;
XS X Size. (0=8, 1=16,… 7=64 pixels)
YS Y Size. (0=8, 1=16,… 7=64 lines)
т.е. — 16х64 — пожалуйста, 48х8 — тоже, а вот 6х33 — увы, нет. Размер будет использован кратный 8 точкам.
Связано это с тем, что спрайты — это почти те-же тайлы.
Спрайт не умещается даже в размер 64 точки? Не проблема! Решим, но чуть попозже ;)
Так-же нужно учесть, что в TSconf для одного спрайта выделена одна палитра, которая включает в себя 15 цветов спрайта и прозрачный цвет. Прозрачность — это цвет с номером 0 в палитре, выбранной для спрайта. Палитру, естественно, загружаем в палитровую память, номер этой палитры отмечаем.

Спрайт нужно разместить в памяти. Для этого выбираем страницу, номер которой обязан быть кратным 8 (0, 8, 192, 240 и т.д.).
Данные спрайта должны лежать не линейным образом, а как на экране — т.е. следующая строчка спрайта соответствует следующей линии экрана.
Для этого стоит воспользоваться DMA и скопировать на страницу, используемую для хранения графики спрайта с учётом этих требований.
Хорошо, будем считать что спрайт правильно скопирован в память.

Что бы мы увидели спрайт, необходимо передать о нём информацию системе. Для работы спрайтов в системе есть отдельный блок памяти, отвечающий за хранение «дескрипторов» спрайтов — т.е. информации, описывающей спрайт, его размер, положение, прочее.
Дескриптор одного спрайта занимает 6 байт:

SFILE	Reg.16	7	6	5	4	        3    2    1        	0
0	R0L	Y[7:0]							
1	R0H	YF	LEAP	ACT	reserved	YS[2:0]			Y[8]
2	R1L	X[7:0]							
3	R1H	XF	-	-	reserved	XS[2:0]			X[8]
4	R2L	TNUM[7:0]							
5	R2H	SPAL[7:4]				TNUM[11:8]			

Описание:
X	X координата, байт + 1 бит (адрес может быть в пределах 0-511)						
Y	Y координата, байтом + 1 бит
XS	X размер. (0=8, 1=16, ... 7=64 pixels)
YS	Y размер. (0=8, 1=16, ... 7=64 lines)							
XF	Горизонтальное отражение спрайта при выводе. <em>Отмечаем себе, что спрайтов рисовать уже нужно в 2 раза меньше!</em>
YF	Вертикальное отражение спрайта при выводе
ACT	Отображение спрайта (вкл/выкл)
LEAP	Бит, определяющий переход на следующий слой для последующих спрайтов. Третий переход обозначает конец описателей спрайтов
TNUM	Номер первого тайла спрайта указанного размера. Биты 0-5 - X позиция тайла в странице графики спрайтов, биты 6-11 - позиция по Y.
SPAL	Выбор палитры. 4 бита - 16 палитр доступно.						


Давайте рассмотрим пример дескриптора:
Спрайт у нас будет размером 64х64 точки, палитра для него под номером 1, в памяти расположен с адреса #c000 — т.е. начало — тайл с номером 0:

sprite    	db 0    ; позиция по Y
		db %00111110    ; биты: 0 - поворот (flip, отражение) по Х выкл,  0 -переход на следующий слой спрайтов выкл, 
; 1 - спрайт будет отображаться,1 - резерв для будущего применения; три бита размера (111 - 64 точки) по Y, 
; и последний бит - 0 - старший бит позиции по  Y
		db Xpos_logo    ; позиция по Х
		db %00001110    ; 0 - поворот (flip) по Y выкл, дальше биты не юзаются до битов размера, 111 - 64 точки по Х; последний бит - это старший бит позиции по Х
		db 0            ; номер тайла на карте графики спрайта. отсчёт от левого верхнего угла, один тайл 8х8 точек.
		db %00010000    ; старшая тетрада - это номер палитры, младшая - старшие биты номера тайла
sprite_end


После того, как данные дескриптора будут отправлены в систему, выводим его на экран.

		ld hl,logo_spr
		call set_ports
; ...
logo_spr
		defb    #1a,low logo ; logo - все дескрипторы спрайтов, не забываем выравнивание адреса по 2
	        defb    #1b,high logo
		defb    #1c,2
	        defb    #1d,0
	        defb    #1e,2    ; отправляем в спрайтовую память
	        defb    #1f,0
	        defb    #26,(sprite_end-sprite)/2    ;длина транзакции
	        defb    #28,0
		db 	#27,#85    ; DMA_RAM_SFILE
		db #ff


Для этого необходимо сообщить системе, что спрайты будут использованы. Для этого устанавливаем бит, ответственный за включение отображения спрайтов при выводе в порте TSConfig, под названием S_EN (Sprite_ENable):

    		ld bc,TSCONFIG
		ld a,TSU_SEN     ; 7й бит
		out (c),a


Спрайт подготовлен и включен. Наблюдаем его на экране. Стоит нерушимо, собака!

Для того, что-бы он начал двигаться — меняем его положение на экране в дескрипторе — Х и Y.
Для того, что-бы спрайт выглядел спрайтом (менялись изображения спрайта) — меняем номер тайла в графике спрайта на нужный.
Не забываем отправлять изменённые данные в спрайтовую память пересылкой.

Итак, что-бы вывести спрайт больше чем 64 точки — используйте ДВА спрайта с нужными координатами ;)

Вопросы и ответы:
? Как спрятать спрайт?
! Выключите ему бит Act, спрайт не будет отображаться

? Как вывести спрайт из-за края экрана?
! Укажите координаты за пределами экрана: например, -32

? У меня спрайты закрываются тайлами, почему?
Потому что нужно использовать бит Leap для перехода на нужный слой. 2 раза — и спрайт лежит сверху всех слоёв.

Ну, я пошла! ;)

5 комментариев

avatar
Э, а где анимированная голая тетка в конце статьи?
avatar
Обещала вернуться!
avatar
avatar
А почему в анимации только половина спрайтов?
avatar
Vitamin , такое исходное изображение
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.