Важная информация

User Tag List

Страница 1 из 4 1234 ПоследняяПоследняя
Показано с 1 по 10 из 31

Тема: Выводим спрайт, с проверкой границ экрана

Комбинированный просмотр

Предыдущее сообщение Предыдущее сообщение   Следующее сообщение Следующее сообщение
  1. #1
    Veteran
    Регистрация
    01.03.2005
    Адрес
    Новосибирск
    Сообщений
    1,985
    Спасибо Благодарностей отдано 
    71
    Спасибо Благодарностей получено 
    266
    Поблагодарили
    102 сообщений
    Mentioned
    6 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию Выводим спрайт, с проверкой границ экрана

    Всех с наступившим 0x7DD годом! Продолжаю эксперименты над выводом спрайта с учётом границ экрана, перетряхнул процедуру и сделал вывод атрибутов.

    Сами атрибуты выводятся в основном цикле, с каждой 8ой строкой спрайта. На мой взгляд это намного быстрее, чем выводить строку отдельной итерацией и тем более быстрее вывода атрибутов отдельным циклом, с учётом специфики границ экрана. Если спрайт не заходит за границы экрана, то подготовка регистров для процедуры вывода (включая проверку границ, расчет фазы атрибутов и адреса экрана) занимает около 300 тактов. При нижней границе у нас отсекается высота спрайта (+16 тактов), а вот верхнюю границу можно немного оптимизировать.

    Процедура по-прежнему не использует стек

    Код:
    	DEVICE ZXSPECTRUM128
    
    	MODULE MAIN
    
    SPR_SIZE=#10
    
    	ORG #8000
    
    START:
            LD SP,#7FFF
            LD HL,#BE00
            LD A,H
            LD I,A
            IM 2
            LD BC,#00BF
            LD (HL),C
            INC HL
            DJNZ $-2
            LD (HL),C
            LD H,C
            LD L,C
            LD (HL),#C9
    
    ST_LOOP:
    	EI
    	HALT
    	LD A,#07
    	OUT (#FE),A
    	
    	LD HL,TEST_SPRITE
    CURS_Y	LD D,0			; D=Y
    CURS_X	LD E,0			; E=X
    	LD B,64			; B=HEIGHT
    	LD C,SPR_SIZE		; C=LEN
    	CALL SPRITE_OUT
    
    	SUB A
    	OUT (#FE),A
    	JP ST_LOOP
    
    
    SPRITE_OUT:
    ;-----------------------------------------------------
    ; Проверка левой и правой границ, расчет длинны строки
    	LD A,E
    	OR A
    	JP P,R_EDGE
    	NEG
    	LD (L_SKIP1),A 
    	LD (L_SKIP2),A
    	NEG
    	ADD A,C	
    	LD E,#00	; Начало левой границы по X
    	EXX
    	LD IY,SP_CL2	; Указатель на процедуру вывода коррекции слева
    	LD DE,PHASE2    ; Указатель на параметр фазы
    	JP LEN_CL
    R_EDGE	ADD A,C
    	SUB #20
    	JR C,NO_COR
    	LD (R_SKIP1),A
    	LD (R_SKIP2),A
    	NEG
    	ADD A,C
    	CP C		; Спрайт на всю ширину экрана?
    	EXX
    	LD IY,SP_CL3	; Процедура вывода коррекции справа
    	LD DE,PHASE3    ; Указатель на параметр фазы
    	JR NZ,LEN_CL
    	EXX
    NO_COR	LD A,C          ; Вывод без коррекции
    	EXX
    	LD IY,SP_CL1	; Указатель на процедуру вывода без коррекции
    	LD DE,PHASE1    ; Указатель на параметр фазы
    LEN_CL	OR A
    	RET M		; Выход, если спрайт целиком за левой или правой границей экрана
    	ADD A,A		; Тут расчитываем длину спрайта для текущего метода вывода
    	SUB #40
    	NEG
    	LD IX,L_OUT1	; Указатель на процедуру вывода LDI (HL-->DE)	
    	LD C,A		; C'=A
    	LD B,#00
    	ADD IX,BC
    	EXX
    ;--------------------------------
    ; Проверка верхней границы экрана
    	LD A,D
    	CP #C1		; Верхняя граница (-1..-63)
    	JR C,D_EDGE
    	NEG             ; A - кол-во пропускаемых строк сверху
    	CP B
    	RET P		; Выход, если спрайт целиком за верхней границей экрана
    	LD D,A
    	PUSH DE
    	RRCA		; Расчитываем сколько строк атрибутов ушло за верхнюю границу
    	RRCA
    	RRCA
    	AND #1F
    	ADD A,D		; Пропускам D/8 строк
    	LD E,A
    	LD D,#00
    	PUSH BC
    	LD A,B
    	EXX
    	INC A
    	AND #07
    	LD (DE),A	; Помещаем код фазы в выбранную процедуру
    	EXX
    	LD B,#06
    MULCYC	SRL C
    	JR NC,NO_ADD
    	ADD HL,DE
    NO_ADD	SLA E
    	RL D
    	DJNZ MULCYC
    	POP AF
    	POP DE
    	SUB D
    	LD B,A
    	LD D,#40	; Начало верхней границы на экране
    	JP (IY)
    ;-------------------------------
    ; Проверка нижней границы экрана
    D_EDGE	LD A,D
    	SUB #C0         ; Нижняя граница > 192 ?
    	RET NC          ; Выход, если спрайт целиком за нижней границей экрана
    	ADD A,B
    	JR NC,CLC_DE	; Не корректируем высоту спрайта
    	SUB B
    	NEG
    	LD B,A
    ;-----------------------------
    ; Расчет экранного адреса
    ; E=X (#00-#1F), D=Y (#00-#BF)
    CLC_DE	LD A,D 		
    	AND #38
    	RLCA
    	RLCA
    	OR E
    	LD E,A
    	LD A,D
    	AND #C0
    	RRA	 
    	SCF	 
    	RRA	 
    	RRCA	 
    	XOR D
    	AND #F8
    	XOR D
    	LD D,A
    ;---------------------------------------
    ; Расчет фазы атрибутов для цикла вывода
    	LD A,B
    	EXX
    	INC A
    	AND #07
    	LD (DE),A	; Помещаем код фазы в выбранную процедуру
    	EXX
    	JP (IY)
    ;---------------------------------------------------
    ; Расчет в DE адрес атрибута, вывод строки атрибутов
    AT_OUT	LD A,D          
    	RRCA
    	RRCA
    	RRCA
    	AND #0B
    	OR #50
    	LD D,A
    ;-----------------------------
    ; Вывод строки спрайта
    L_OUT   LD C,D
    	JP (IX)
    L_OUT1	DUP 32
    	LDI
    	EDUP
    	RET
    ;-----------------------------
    ; Расчет следующего знакоместа
    COR_DE	LD A,E
    	SUB #E0
    	LD E,A
    	SBC A,A
    	AND #F8
    	ADD A,D
    	LD D,A
    	JP (IY)
    ;-----------------------------------------------------
    ; Процедура вывода на экран с атрибутами без коррекции 
    LOOP1	INC D
    	LD A,D
    	AND #07
    	JR Z,COR_DE
    SP_CL1	LD A,E
    	CALL L_OUT
    	DEC DE		; Коррекция D, если Е > #FF
    	LD E,A
    	LD A,B
    	AND #07
    PHASE1  EQU $+1
    	XOR #00         
     	JR Z,A_OUT1    
    	DJNZ LOOP1    
    	RET
    A_OUT1	PUSH DE
    	CALL AT_OUT
    	POP DE
    	DJNZ LOOP1
    	RET
    ;----------------------------------------------------------
    ; Процедура вывода на экран с атрибутами с коррекцией слева
    LOOP2	INC D
    	LD A,D
    	AND #07
    	JR Z,COR_DE
    SP_CL2	LD A,B
    L_SKIP1	EQU $+1
    	LD BC,#0000	; Переменная отступа слева
    	ADD HL,BC
    	LD B,E
    	CALL L_OUT
    	LD E,B		; При сдвиге влево D можно не корректировать
    	LD B,A
    	AND #07
    PHASE2	EQU $+1
    	XOR #00
    	JR Z,A_OUT2
    	DJNZ LOOP2
    	RET
    A_OUT2	PUSH DE
    	LD A,B
    L_SKIP2 EQU $+1
    	LD BC,#0000
    	ADD HL,BC
    	LD B,A
    	CALL AT_OUT
    	POP DE
    	DJNZ LOOP2
    	RET
    ;-----------------------------------------------------------
    ; Процедура вывода на экран с атрибутами с коррекцией справа
    LOOP3	INC D
    	LD A,D
    	AND #07
    	JR Z,COR_DE
    SP_CL3	LD A,B
    	LD B,E
    	CALL L_OUT
    	DEC DE		; Коррекция D, если Е > #FF
    	LD E,B
    R_SKIP1	EQU $+1
    	LD BC,#0000	; Переменная отступа справа
    	ADD HL,BC
    	LD B,A
    	AND #07
    PHASE3	EQU $+1
    	XOR #00
    	JR Z,A_OUT3
    	DJNZ LOOP3
    	RET
    A_OUT3	PUSH DE
    	CALL AT_OUT
    	LD A,B
    R_SKIP2	EQU $+1
    	LD BC,#0000
    	ADD HL,BC
    	LD B,A
    	POP DE
    	DJNZ LOOP3
    	RET
    
    ;----------------
    ; Тестовый спрайт
    	ORG #C000,#00
    TEST_SPRITE:
    	DUP 3	
    
    	DUP 4
    	DS SPR_SIZE,#55
    	DS SPR_SIZE,#AA
    	EDUP
    	DB #41
    	DS SPR_SIZE-2,#01
    	DB #41
    
    	DUP 4
    	DS SPR_SIZE,#F0
    	EDUP
    	DUP 4
    	DS SPR_SIZE,#0F
    	EDUP
    	DB #42
    	DS SPR_SIZE-2,#02
    	DB #42
    
    	DUP 4
    	DS SPR_SIZE,#55
    	DS SPR_SIZE,#AA
    	EDUP
    	DB #43
    	DS SPR_SIZE-2,#03
    	DB #43
    
    	DUP 4
    	DS SPR_SIZE,#F0
    	EDUP
    	DUP 4
    	DS SPR_SIZE,#0F
    	EDUP
    	DB #44
    	DS SPR_SIZE-2,#04
    	DB #44
    
    	DUP 4
    	DS SPR_SIZE,#55
    	DS SPR_SIZE,#AA
    	EDUP
    	DB #45
    	DS SPR_SIZE-2,#05
    	DB #45
    
    	DUP 4
    	DS SPR_SIZE,#F0
    	EDUP
    	DUP 4
    	DS SPR_SIZE,#0F
    	EDUP
    	DB #46
    	DS SPR_SIZE-2,#06
    	DB #46
    
    	DUP 4
    	DS SPR_SIZE,#55
    	DS SPR_SIZE,#AA
    	EDUP
    	DB #07
    	DS SPR_SIZE-2,#47
    	DB #07
    
    	DUP 4
    	DS SPR_SIZE,#F0
    	EDUP
    	DUP 4
    	DS SPR_SIZE,#0F
    	EDUP
    	DB #41
    	DS SPR_SIZE-2,#01
    	DB #41
    
    
    	EDUP
    	PAGE #00
    	SAVESNA "test.sna",START
    	ENDMODULE
    ---

    Upd. во вложении пример использования этой процедуры для вывода спрайта в игре.
    Вложения Вложения
    Последний раз редактировалось drbars; 07.06.2014 в 02:39.

  2. #1
    С любовью к вам, Yandex.Direct
    Размещение рекламы на форуме способствует его дальнейшему развитию

  3. #2
    Super Moderator Аватар для Alex Rider
    Регистрация
    07.02.2008
    Адрес
    г. Рязань
    Сообщений
    2,908
    Спасибо Благодарностей отдано 
    29
    Спасибо Благодарностей получено 
    89
    Поблагодарили
    31 сообщений
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Я тоже после мероприятия, пока не в состоянии глубоко анализировать чужой код Сорри.

  4. #3
    Veteran Аватар для Destr
    Регистрация
    26.03.2008
    Адрес
    Питкяранта
    Сообщений
    1,802
    Спасибо Благодарностей отдано 
    249
    Спасибо Благодарностей получено 
    114
    Поблагодарили
    88 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Процедуру отсечки нужно гвоздями прибивать к размерности спрайта.
    Т.е. сама выводилка уже в себе несёт знание с чем ей работать.
    Говоря языком человеков = под каждый конкретный размер спрайта - своя процедура вывода.
    Тогда можно заточить выводилку так, что даже байтовая координата будет нести больше инфы, чем казалось могла-бы.
    (Ну к примеру не 256 значений в байте можно хранить, а все 258. именно из-за того что либо влево либо вправо спрайт вылазит (и отсекается).)
    Сумбурно описал, наверное, но суть думаю ясна.
    Сильно не бить, ламер я ещё тот
    Но работает такой подход!
    (в ранних спек-гамах, этого не делали, делали "закрытку" атрибутами слева и справа, отсекайка как-бы и ненужна, но мы-то хотим кодить под фулскрин, так что придётся колдовать
    Причем по тактам не так уж и много это занимает.

    ---------- Post added at 14:37 ---------- Previous post was at 14:32 ----------

    А, да!
    Совсем забыл.
    Некий jerri зело крут в таких вещах.
    Топикстартеру лучше всего с ним в асе (или ещё как) погутарить.
    Он всегда поможет быстрей и толковей чем весь форум вместе взятый.
    (форумчане хоть и дружелюбны, но ленивы, каждый надеется что кто-то другой сделает, а жерри - он оперативен, быстр и мудр)

  5. #4
    Vitamin C++ Аватар для Vitamin
    Регистрация
    14.01.2005
    Адрес
    Таганрог, Россия
    Сообщений
    4,259
    Спасибо Благодарностей отдано 
    9
    Спасибо Благодарностей получено 
    84
    Поблагодарили
    36 сообщений
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Капля оффтопа. Одно время вынашивал идею хранения спрайтов в больших картах шириной в 256 знакомест, кадрирование и вывод получаются весьма просто. Очевидные проблемы- жуткая фрагментация памяти. "Дырки" можно использовать под системные нужды. В некоем ограниченном виде даже применил.

  6. #5
    Guru
    Регистрация
    03.01.2006
    Адрес
    Рязань
    Сообщений
    2,935
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    1
    Поблагодарили
    1 сообщение
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Надо учесть, что обычно нужны спрайты шириной 1-4 знакоместа с точностью до 1-4 пикселей по горизонтали.

  7. #6
    Veteran Аватар для Destr
    Регистрация
    26.03.2008
    Адрес
    Питкяранта
    Сообщений
    1,802
    Спасибо Благодарностей отдано 
    249
    Спасибо Благодарностей получено 
    114
    Поблагодарили
    88 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от alone Посмотреть сообщение
    Надо учесть, что обычно нужны спрайты шириной 1-4 знакоместа с точностью до 1-4 пикселей по горизонтали.
    По-ходу тут пытаются (т.drbars) универсальную (или приближённо к идеалу) процедуру замутить, но пока ещё не осознал что спек (как структура) этого не допустит

  8. #7
    Veteran Аватар для Destr
    Регистрация
    26.03.2008
    Адрес
    Питкяранта
    Сообщений
    1,802
    Спасибо Благодарностей отдано 
    249
    Спасибо Благодарностей получено 
    114
    Поблагодарили
    88 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от drbars Посмотреть сообщение
    Проблема: Как быстро, и главное правильно, расчитать момент включения вывода строки атрибута при выходе за верхнюю или нижнюю границы экрана?
    Это и есть самый сволочизм zx-спек-строения.
    Грааль нашей 8-бит машинки.
    Сорри за оф (если что)

  9. #8
    Veteran
    Регистрация
    01.03.2005
    Адрес
    Новосибирск
    Сообщений
    1,985
    Спасибо Благодарностей отдано 
    71
    Спасибо Благодарностей получено 
    266
    Поблагодарили
    102 сообщений
    Mentioned
    6 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от Destr Посмотреть сообщение
    Это и есть самый сволочизм zx-спек-строения.
    Грааль нашей 8-бит машинки.
    Сорри за оф (если что)
    да ничё, я уже нижнюю границу запилил Злое какое-то шампанское было...
    Сам отношусь к чужому коду — проще написать свой, чем понимать.
    Всё гениальное — просто Втянул кодинг, после всяких 1С и Ораклов хорошо мозг проветривает

    13 лет ничего не писал, а тут раз чё-то сел и понеслось
    Последний раз редактировалось drbars; 30.12.2012 в 20:06.

  10. #9
    Veteran Аватар для Destr
    Регистрация
    26.03.2008
    Адрес
    Питкяранта
    Сообщений
    1,802
    Спасибо Благодарностей отдано 
    249
    Спасибо Благодарностей получено 
    114
    Поблагодарили
    88 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от drbars Посмотреть сообщение
    какое-то шампанское было...

    (бъем бокалы, не знаю как там смайл копирастиется)

  11. #10
    Veteran
    Регистрация
    01.03.2005
    Адрес
    Новосибирск
    Сообщений
    1,985
    Спасибо Благодарностей отдано 
    71
    Спасибо Благодарностей получено 
    266
    Поблагодарили
    102 сообщений
    Mentioned
    6 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    В общем сделал расчет атрибутов верх и низ, теперь лево-право думаю... Тока с атрибутами, высота спрайта должна быть кратна 8, иначе — видеоэффекты Фаза расчитывается исходя из высоты спрайта, а регистр B в цикле DJNZ используется как счетчик, чтобы не заводить лишний. Правда зачем некратная высота нужна с атрибутом?
    Последний раз редактировалось drbars; 01.01.2013 в 21:42.

Страница 1 из 4 1234 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. времянки экрана Pentagon'а
    от siril в разделе Программирование
    Ответов: 6
    Последнее: 10.08.2011, 00:09
  2. Времянки экрана БК
    от Sandro в разделе БК-0010/0011
    Ответов: 18
    Последнее: 19.12.2010, 19:36
  3. посоветуйте спрайт-едитор
    от boo_boo в разделе Софт
    Ответов: 11
    Последнее: 15.03.2007, 10:43
  4. Самый большой спрайт игрока
    от goodboy в разделе Игры
    Ответов: 17
    Последнее: 21.08.2006, 07:52
  5. Разрешение экрана.
    от CityAceE в разделе Форум
    Ответов: 19
    Последнее: 06.03.2005, 06:37

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •