=======================================
Мой профиль на Pixeljoint: http://pixeljoint.com/p/35576.htm
=======================================
Мой профиль на ZXArt.ee: http://zxart.ee/rus/avtory/h/helcril/
=======================================
ZX Spectrum +2, ZX Evolution Rev. C
С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
Доброго дня! Пока изучаю основы, и мне нужно напечатать карту игрового поля. Допустим я нарисовал её в ZX-Paintbrush, размеры 15*15 знакомест. Данные по изображению есть в формате :
; line based output of pixel data:
defb 255......
; line based output of attribute data:
defb 38h....
Какой несложной процедурой её можно распечатать, учитывая что она будет в качестве фона, статична и всегда в одном и том же месте (начальная позиция 3,9 в знакоместах).
Тогда лучше подогнать пиксельные строки под структуру экрана Спектрума. Т.е.:
1-я пиксельная строка 1-й строки знакомест
1-я пиксельная строка 2-й строки знакомест
...
1-я пиксельная строка 8-й строки знакомест
2-я пиксельная строка 1-й строки знакомест
...
2-я пиксельная строка 8-й строки знакомест
...
8-я пиксельная строка 8-й строки знакомест
1-я пиксельная строка 9-й строки знакомест
...
и т.д.
А потом командой ldir всё копировать из памяти на экран (до нее задать hl=адрес памяти, de=первый адрес экрана, bc=количество копируемых байт).
А если карта состоит из повторяемых элементов, то пиксельные строки - это расточительство.
- - - Добавлено - - -
Еще вариант - оставить данные со строками как есть у тебя, а в цикле по количеству пиксельных строк устанавливать hl,de,bc нужными и командой ldir копировать каждую пиксельную строку.
Изначально, самой простой идеей было "загнать" каждый элемент карты в символ UDG и распечатывать игровое поле, как из кусочков. Но проблема в том что каждая "ячейка" карты имеет размер 3*3 знакоместа (это соотвественно 9 символов UDG), и "собирать" её становиться нелегко.
У тебя каждая клетка - спрайт. А карта состоит из однобайтовых ID спрайтов. Вот и оперируй ими.
Вот процедура вывода двумерной карты из спрайтов 2х2 знакоместа, взята из моего кросс-компилятора Паскаля:
Процедуру несложно переделать под спрайты 3х3, как ты хочешь (задание на дом ).Код:; вывод участка карты на экран, состоящей из спрайтов 2х2 знакоместа map_put ld a,(map_xmax_array) ld c,a ld b,0 ld a,(map_y) dec a ld e,a ld d,0 call mul ld a,(map_x) dec a ld e,a ld d,0 add hl,de ld de,(map_addr_array) add hl,de ld (map_addr_curr),hl ld hl,(map_xscr) ld (map_xscr_curr),hl ld a,(map_height_scr) ld b,a map_put_01 push bc ld a,(map_width_scr) ld b,a map_put_02 push bc ld hl,(map_addr_curr) ld a,(hl) and a ld hl,(map_addr_sprites) jp z,map_put_04 ld b,a ld de,36 map_put_03 add hl,de djnz map_put_03 map_put_04 call map_put_10 ld hl,(map_addr_curr) inc hl ld (map_addr_curr),hl ld hl,map_xscr_curr inc (hl) inc (hl) pop bc djnz map_put_02 ld hl,(map_addr_curr) ld a,(map_ymax_array) ld e,a ld d,0 add hl,de ld a,(map_width_scr) ld e,a and a sbc hl,de ld (map_addr_curr),hl ld hl,map_yscr_curr inc (hl) inc (hl) ld a,(map_xscr) ld (map_xscr_curr),a pop bc djnz map_put_01 ret map_put_10 ex de,hl ld bc,(map_xscr_curr) LD A,B RRCA RRCA RRCA LD L,A AND 31 OR 88 LD H,A LD A,L AND 252 OR C LD L,A ld a,(de) ld (hl),a inc de inc hl ld a,(de) ld (hl),a inc de ld bc,31 add hl,bc ld a,(de) ld (hl),a inc de inc hl ld a,(de) ld (hl),a inc de ld bc,(map_xscr_curr) LD A,B LD H,A RRCA RRCA RRCA AND A,224 ADD A,C LD L,A LD A,H AND 24 OR 64 LD H,A dup 7 ld a,(de) ld (hl),a inc de inc h edup ld a,(de) ld (hl),a inc de ld bc,#6ff and a sbc hl,bc dup 7 ld a,(de) ld (hl),a inc de inc h edup ld a,(de) ld (hl),a inc de ld bc,#6e1 and a sbc hl,bc dup 7 ld a,(de) ld (hl),a inc de inc h edup ld a,(de) ld (hl),a inc de ld bc,#6ff and a sbc hl,bc dup 7 ld a,(de) ld (hl),a inc de inc h edup ld a,(de) ld (hl),a ret map_addr_array defw 0 ; начальный адрес карты, состоящей из однобайтовых id спрайтов map_xmax_array defb 0 ; размер карты в байтах по горизонтали map_ymax_array defb 0 ; размер карты в байтах по вертикали map_addr_sprites defw 0 ; начальный адрес спрайтов карты map_xscr defb 0 ; столбец экрана, с которого выводить карту map_yscr defb 0 ; строка экрана, с которой выводить карту map_width_scr defb 0 ; количество выводимых клеток карты по горизонтали map_height_scr defb 0 ; количество выводимых клеток карты по вертикали map_x defb 0 ; горизонтальная координата клетки карты, с которой выводить map_y defb 0 ; вертикальная координата клетки карты, с которой выводить map_addr_curr defw 0 ; текущий адрес карты map_xscr_curr defb 0 ; текущий столбец экрана map_yscr_curr defb 0 ; текущая строка экрана ; функция беззнакового умножения 16-разрядных чисел ; (C) Kirill Frolov ; idea by Vasil Ivanov ; dehl=de*bc ~730t. mul ld a,d and a jp nz,mul_00 ld ix,mul_00 ld h,b ld l,c ld a,e jp mul_02 mul_00 ld a,b and a jp nz,mul_01 ld ix,mul_01 ld h,d ld l,e ld a,c jp mul_02 mul_01 ld hl, 0 ld a, c ld c, l ; 18 add a, a jr nc, $+4 add hl, de adc a, c ; 29 ; REPEAT 7 add hl, hl rla jr nc, $+4 add hl, de adc a, c ; 40*7 309 add hl, hl rla jr nc, $+4 add hl, de adc a, c add hl, hl rla jr nc, $+4 add hl, de adc a, c add hl, hl rla jr nc, $+4 add hl, de adc a, c add hl, hl rla jr nc, $+4 add hl, de adc a, c add hl, hl rla jr nc, $+4 add hl, de adc a, c add hl, hl rla jr nc, $+4 add hl, de adc a, c ; ENDR ld c, a push hl ; 0chl ld hl, 0 ld a, b ld b, l ; 33 add a, a jr nc, $+4 add hl, de add a, b ; 29 ; REPEAT 7 add hl, hl rla jr nc, $+4 add hl, de add a, b ; 40*7 309 add hl, hl rla jr nc, $+4 add hl, de add a, b add hl, hl rla jr nc, $+4 add hl, de add a, b add hl, hl rla jr nc, $+4 add hl, de add a, b add hl, hl rla jr nc, $+4 add hl, de add a, b add hl, hl rla jr nc, $+4 add hl, de add a, b add hl, hl rla jr nc, $+4 add hl, de add a, b ; ENDR ; ahl0 + 0cde = hlde pop de ld b, l ld l, h ld h, a ld a, d add a, b ld d, a ld b, 0 adc hl, bc ex de, hl ; 60 ret ; 729t. mul_02 and a jp z,mul_n0 cp 1 jp z,mul_n1 cp 2 jp z,mul_n2 cp 3 jp z,mul_n3 cp 4 jp z,mul_n4 cp 5 jp z,mul_n5 cp 8 jp z,mul_n8 cp 10 jp z,mul_n10 cp 15 jp z,mul_n15 cp 16 jp z,mul_n16 cp 20 jp z,mul_n20 cp 32 jp z,mul_n32 cp 50 jp z,mul_n50 cp 64 jp z,mul_n64 cp 100 jp z,mul_n100 cp 128 jp z,mul_n128 jp (ix) mul_n0 ld hl,0 ret mul_n1 ret mul_n2 add hl,hl ret mul_n3 ld d,h ld e,l add hl,hl add hl,de ret mul_n4 add hl,hl add hl,hl ret mul_n5 ld d,h ld e,l add hl,hl add hl,hl add hl,de ret mul_n8 add hl,hl add hl,hl add hl,hl ret mul_n10 add hl,hl ld d,h ld e,l add hl,hl add hl,hl add hl,de ret mul_n15 ld d,h ld e,l add hl,hl add hl,hl add hl,hl add hl,hl and a sbc hl,de ret mul_n16 add hl,hl add hl,hl add hl,hl add hl,hl ret mul_n20 add hl,hl add hl,hl ld d,h ld e,l add hl,hl add hl,hl add hl,de ret mul_n32 add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ret mul_n50 add hl,hl ld d,h ld e,l add hl,hl add hl,hl add hl,hl ld b,h ld c,l add hl,hl add hl,bc add hl,de ret mul_n64 add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ret mul_n100 add hl,hl add hl,hl ld d,h ld e,l add hl,hl add hl,hl add hl,hl ld b,h ld c,l add hl,hl add hl,bc add hl,de ret mul_n128 add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ret Спрайты карты Один спрайт занимает 2×2 знакоместа (в принятом формате – всегда 36 байт с атрибутами). Спрайты идут последовательно в памяти, согласно кодам элементов карты. Коды элементов карты должны быть последовательными от 0 до максимума, не более 255. Количество спрайтов должно строго соответствовать количеству кодов карты. Формат одного спрайта карты: NAME DEFB 3,3,3,3 DEFB 7,31,63,127,120,247,252,249 DEFB 192,240,248,252,124,62,62,62 DEFB 243,243,120,127,63,31,7,0 DEFB 62,62,60,252,248,240,192,0 NAME – метка начала спрайтов элементов карты, имя метки обязательно заглавными буквами. Метка ставится вначале всех спрайтов карты, всегда одна для всех спрайтов карты. DEFB 3,3,3,3 – атрибуты для каждого из 4-х знакомест спрайта, могут быть различными. Далее идет по 8 байт изображения для каждого из 4-х знакомест спрайта.
Последний раз редактировалось Andrew771; 14.01.2016 в 15:14.
И еще пару-тройку советов, если позволите. До них я допёр с помощью инета уже после прочтения книги "Как написать игру", в книгах для начинающих этого не пишут почему-то.
1. В вышеприведенной процедуре используется отдельная процедура mul умножения двух регистровых пар. Вообще-то, это занимает много времени, поэтому для улучшения быстродействия очень желательно делать индексы массивов (в данном случае размерность карты) кратным 2^n (два в степени n), т.е. 4,8,16,32,64,128 или 256 и т.д. Тогда процедура "честного" умножения mul выкидывается полностью, а умножение заменяется банальной последовательностью сложений рег.пары hl самой с собой. Например, умножение hl на 8:
add hl,hl
add hl,hl
add hl,hl
И вообще, в прогах по возможности нужно избегать умножений и делений на числа, не кратных 2. Для кратных 2 числам просто применяются команды сдвигов влево (для умножения) или вправо (для деления).
2. Вывод спрайтов в книге Капульцевичей производится с расчетом для каждого знакоместа адреса вывода на экран изображения и адреса вывода атрибутов. Это идиотизм, если знакоместа находятся рядом. Проще рассчитать адрес первого знакоместа, а остальные адреса получать смещением от начального - сложением текущего адреса hl и константы. Что я и сделал, см. код ниже с метки map_put_10. Сначала рассчитывается адрес экрана в области атрибутов, затем змейкой друг за другом от него выводятся все 4 атрибута знакомест сразу. Затем то же самое для изображений знакомест - змейкой. Если спрайт 3х3, то змейкой можно выводить сразу 9 знакомест.
3. Не экономь память в коде при выводе изображения, это повышает быстродействие. В книге Капульцевичей вывод 8 строк-байт одного знакоместа производится в цикле:
ld b,8
loop ld a,(de)
ld (hl),a
inc de
inc h
djnz loop
Перцы покруче раскрывают цикл и пишут подряд 8 раз:
ld a,(de)
ld (hl),a
inc de
inc h
ld a,(de)
ld (hl),a
inc de
inc h
ld a,(de)
ld (hl),a
inc de
inc h
...
Или, если написать это короче:
dup 8
ld a,(de)
ld (hl),a
inc de
inc h
edup
Это занимает больше памяти, зато процессору не надо выполнять лишние такты на djnz loop для каждого байта. А особенно если еще встречается в начале и конце цикла какое-нибудь push bc / pop bc, то выгода по тактам очень огромна.
А самые крутые перцы делают вообще через стек: сначала адрес стека SP устанавливают на адрес в экране, затем загоняют по два байта изображения из памяти в рег.пару, а потом выводят в стек-экран командой push. Это занимает еще меньше времени по тактам.
Какой тонкий юмор! Я бы даже сказал, утончённый садизм.
Заявив о медлительности индексной адресации, привести в качестве альтернативы одну значительно более медленную, а другую одинаковую по скорости процедуры. Да к тому же, в отличие от индексной адресации, требующих дополнительных регистров
LD r,(IX+n) занимает 19 тактов.
А вторая процедура, хоть, и 11, но требует загрузки рег.пары H, а это уже +10т. Итого: 21т., что медленнее, чем через индексные регистры.
Можно и за 8 тактов HL загрузить - тогда общее время будет 19т.
С уважением,
Gris / Red Triangle.
_____________________________________
ZX-EVO/TS-Labs config/NGS/HDD/SD-card
Amiga A1200/Blizzard 1230@50/32/60GB
Amiga A1200/Apollo 1260@66/32/60GB
UnAmiga (C5) AGA GM7123 VideoDAC
Всем привет!!! Потихоньку продвигаюсь в написании своей концептуальной игры. Уже нашКОДил примерно 40%.
Разобрался таки со скроллами окон. Если кто видел сообщение оно уже не актуально)
Последний раз редактировалось megozavr; 24.01.2016 в 20:01.
Подскажите, вот я работаю в zx-spin. Мне нужно понять сколько в кб "весит" мой текущий код. Нужно же знать сколько еще у меня запаса памяти на игру)
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)