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

User Tag List

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

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

  1. #1
    Veteran
    Регистрация
    01.03.2005
    Адрес
    Новосибирск
    Сообщений
    1,979
    Спасибо Благодарностей отдано 
    69
    Спасибо Благодарностей получено 
    261
    Поблагодарили
    99 сообщений
    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,800
    Спасибо Благодарностей отдано 
    249
    Спасибо Благодарностей получено 
    112
    Поблагодарили
    86 сообщений
    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,254
    Спасибо Благодарностей отдано 
    9
    Спасибо Благодарностей получено 
    80
    Поблагодарили
    34 сообщений
    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,800
    Спасибо Благодарностей отдано 
    249
    Спасибо Благодарностей получено 
    112
    Поблагодарили
    86 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

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

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

    По умолчанию

    Цитата Сообщение от Destr Посмотреть сообщение
    Говоря языком человеков = под каждый конкретный размер спрайта - своя процедура вывода.
    Это мне не подходит, такой способ эффективен для попиксельных сдвигов анимированных спрайтов. У меня эта задача тоже в другом месте будет решаться. Городить же кучу кода для вывода локаций — жалко памяти. Там и без этого до пяти слоёв у локации насчитывется, и бог его знает что по ходу придумается ещё.

    Сейчас задача стоит написать небольшую, но эффективную процедуру вывода.

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

    Цитата Сообщение от krt17 Посмотреть сообщение
    Если такты не жмут но все нормально. Немного странно что ldi в call'ах, но не критично. Если все плохо то я бы изначально попробовал под ld RP,data push RP.
    Это процедура вывода локаций из моей игры, стек нельзя использовать категорически. Все стековые выводы подвижной графики только в прерываниях. Суть вызова LDI массива через CALL очевидна. Да, это 27 лишних тактов на строку. Далее, эти массивы будут разные: для вывода OR/AND/XOR, отражения и сдвига на полубайт. При инициализации заданному циклу вывода будет указываться заданная процедура вывода строки. Но это позже.

    Второе это отрисовка атрибутов, как видно из кода там есть заготовка для расчета адреса атрибута. Как её толком использовать пока не придумал, но это явно эффективнее чем рисовать атрибуты отдельным циклом.

    Хранить атрибуты в начале спрайта или в конце тоже не эффективно. Надо ещё и расчитывать адрес атрибутов при выходе за верхнюю или нижнюю границу экрана (ведь в тогда в конце вывода HL указывает не на спрайт, а на массив атрибутов), а это альтернативные регистры для передачи данных на вывод (конструкции типа PUSH HL:EXX:POP HL) и ещё одно умножение как минимум. В общем не вариант.
    Последний раз редактировалось drbars; 30.12.2012 в 19:59.

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

    По умолчанию

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

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

    По умолчанию

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

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

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

    По умолчанию

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

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

Страница 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

Ваши права

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