ZXNet эхоконференция «code.zx»


тема: Обрезание спрайта на краю экрана.



от: Slavik Tretiak
кому: All
дата: 21 Feb 2006
Hello, Sinus

и ещё. с твоими требованиями фреймово ты полюбому не сделаешь.
так что особо заморачиваться по поводу скорости и выигрывать каждый такт нет
смысла.

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

(или ты не игру делаешь?)

от: Slavik Tretiak
кому: All
дата: 21 Feb 2006
Hello, moroz1999

размеры спрайта какие? все спрайты разных размеров или одинаковых?
если не очень большие и одинаковые, то можно (читать нужно) раздекрянчить
смещая по X и создать несколько процедур вывода (кстати выводя "змейкой" особо
не ускоришь).

допустим есть max размер по X в знакоместах будет 4, то создаёшь следующие
процедуры для вывода

X <= (-4*8) : нафуй
X > (-4*8) && X < (-3*8) : proc_m1

X>=0 && X<255 : proc_normal

X>255 && X<(255+8) : proc_p1

вот.
оч. быстро ;)
но не оптимально по памяти.

-+----

или так: есть 3 процедуры, спрайты покрянчены

1) спрайт залазит влево
2) спрайт полностью на экране
3) спрайт залазит вправо

если спрайт на экране, то всё очевидно.

допустим, спрайт залазит вправо.

если вывод 2х строк такой:
┌─- code ───

line_1:
ld a,(bc)
inc с
ld d,a
dup max_width-1
ld a,(de)
and (hl)
inc hl
or (hl)
inc hl
ld (de),a
inc e
edup
ld a,(de)
and (hl)
inc hl
or (hl)
inc hl
ld (de),a
ret

line_2:
ld a,(bc)
inc с
ld d,a
ld a,
add a,l
ld l,a
dup max_width-1
ld a,(de)
and (hl)
inc hl
or (hl)
inc hl
ld (de),a
dec e
edup
ld a,(de)
and (hl)
inc hl
or (hl)
inc hl
ld (de),a
ret

└── code ───
то можно просчитать где поставить нужный ret (чтоб лишнего не выводить),
замодифицировать line_1 и line_2 для этих целей, так же пропишем


обрежем по Y и далее
┌─- code ───

; b - кол-во 2x линий для вывода
; hl' - указывает на нужное место спрайта
; e' - колонка в экране
; c' - номер линии в экране
; b' - адрес таблички адресов
ld hl,retaddr
push hl
ld hl,line_2
ld de,line_1
lp0:
push hl
push de
djnz lp0
ret

retaddr:
....

└── code ───
! код работать не будет !
тут есть проёб с тем что выводится "змейкой"- тогда не получится так просто
доставать адреса из таблички.
лучше без змейки. и из таблички надо доставать не только старшую часть адреса
(в данном случае D) но и младшую (E) и добавлять к ней смещение

в общем идея думаю ясна.

от: Slavik Tretiak
кому: All
дата: 21 Feb 2006
Hello, moroz1999

спрайт хранится правильно (маска - спр.)
а вот что покрянчить не можешь это плохо...
а зачем кил 8 на табличку?
┌─- code ───

RRtab:
DB %00000000,%00000000 ; %00000000
DB %00000000,%10000000 ; %00000001
DB %00000001,%00000000 ; %00000010
.... 256 раз


└── code ───
около 4 кил получается.

кстати можешь прооптимизировать вывод спрайта если смещение==0, но думаю смысла
не имеет.

а "змейку" ты так выводишь?
┌─- code ───

.... вывод 1 линии ....
CALL DOWN_DE
.... вывод 2 линии ....
CALL DOWN_DE

└── code ───
если да, то замени DOWN_DE на выборку из таблички, но тогда со змейкой туго
будет ;)

от: moroz1999
кому: All
дата: 21 Feb 2006
Hello, All

Я достаточно мало знаю теории по этому вопросу, может быть кто-то подскажет
какие-то хитрые решения по следующему вопросу:

Имеется процедура вывода спрайтов на экран со следующими параметрами:
координаты вывода - попиксельные,
X-размеры спрайта кратны 8 пикселям, Y-размеры кратны 2 пикселям.

вывод на экран ведется т.н. "змейкой", т.е нечетные выводятся слева направо,
четные для скорости справа налево.

вывод ведется напрямую в видеообласть памяти.

вопрос: как в теории проще/быстрее/хитрее/оптимальнее обрезать спрайт,
заступающий за край экрана?

от: moroz1999
кому: All
дата: 21 Feb 2006
Hello, Sinus

спасибо за инфу.
извиняюсь, мой прокол - не все требования выложил.

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

раздекрянчить спрайты не могу - их очень много. для обретения приемлимой
скорости используется таблица килобайт на 8, содержащая все варианты смещенных
байтов.
спрайты хранятся в таком виде:
байт маски, байт спрайта, байт маски, байт спрайта..., естественно для змейки.

кстати, на крайний случай от змейки отказаться несложно.

от: Slavik Tretiak
кому: All
дата: 21 Feb 2006
Hello, Wlodek

Wlodek: это если по вертикали спрайт вылазит, то можно в ПЗУ позапихивать ;)

а если по горизонтали?
или ты предлагаешь каждый байт из таблички доставать? это ж тормозно.

от: Wladimir Bulchukey
кому: All
дата: 21 Feb 2006
Hello, Sinus

Общая идея такова: использовать для вывода спрайта таблицу (или две таблицы :)
) адресов видеопамяти и в каждой из них предусмотреть несколько байт или слов
холостых адресов за пределами экрана, в зависимости от максимального размера
спрайта. Ещё в 1989 году я это успешно использовал в "Приключении в метро" :) .

от: Wladimir Bulchukey
кому: All
дата: 21 Feb 2006
Hello, Sinus

По горизонтали можно представить, что экран представляет из себя не 32, а 33,
34 и т.д. знакоместа (в зависимости от реального максимального размера
спрайта). По вертикали же - верно, сколько "лишних" строк, столько и "лишних"
ссылок из таблиц адресов. Говорю, реально просто и элементарно. Процедура
вывода спрайтов даже не задумывается над тем, что она на самом деле ряд
пиксельных элементов выводит не на экран, а, например, в область адресов ПЗУ.
Hикаких переходов по "если", никаких ветвлений. Говорю, я это использовал и
доволен ;) . А таблица адресов в памяти - ну, так нынче минимум 128К! А я в
1989 году всё в 48К упихнул и без проблем ;) . Всего 41К, со всеми таблицами,
образами спрайтов, графикой и, конечно, кодом программы. Сейчас всё намного
комфортнее ;) .

от: Slavik Tretiak
кому: All
дата: 21 Feb 2006
Hello, Wlodek

По горизонтали можно представить, что экран представляет из себя не 32, а 33,
34 и т.д. знакоместа

это то понятно, как говорится не в первый раз замужем.
я вот люблю цитировать себя же в таких случаях:

> или ты предлагаешь каждый байт из таблички доставать? это ж тормозно.
>

т.е. ты на каждый выводимый байт берёшь адрес из таблички.
а я говорю, что это ТОРМОЗHО! ;)

от: Slavik Tretiak
кому: All
дата: 21 Feb 2006
Hello, axor

axo> Можно сделать экран не во всю ширину, а по краям поставить атрибуты
axo> (ширина этой полоски зависит от max ширины спрайта), у которых
axo> совпадает ink и paper.
axo>
axo> Т.е. печатаем как обычно, а пользователь видит, что спрайт ушел
axo> вправо/влево. Hу а выход за реальные размеры экрана отрабатывать уж
axo> как придется.

да, такое делалось в некоторых демках и игрушках.
но имхо не лучший выход.
тем более что не всегда применимо- допустим если игра не во весь экран, а в
"рамочке". там уж атрибуты особо не расставишь

от: Александр Шушков
кому: All
дата: 21 Feb 2006
Hello, Wlodek

Можно сделать экран не во всю ширину, а по краям поставить атрибуты (ширина
этой полоски зависит от max ширины спрайта), у которых совпадает ink и paper.

Т.е. печатаем как обычно, а пользователь видит, что спрайт ушел вправо/влево.
Hу а выход за реальные размеры экрана отрабатывать уж как придется.

от: Владимир Кладов
кому: All
дата: 21 Feb 2006
Hello, Sinus

двойная маска. т.е. к маске которую имеет сам спрайт, добавлять еще одну маску.
Если спрайт ширины 2 или 3 байта - вполне эту маску можно перед выводом спрайта
грузануть в регистры со штрихом, и там и держать, для небольшого ускорения.
Если не нравится замедление - сделать 2 варианта процедуры вывода, вариант с
дополнительной маской работает только для спрайтов, которые "выехали" за край.
Идея ясна?

от: Александр Шушков
кому: All
дата: 22 Feb 2006
Hello, Sinus

Sin> да, такое делалось в некоторых демках и игрушках.
Sin> но имхо не лучший выход.
Sin> тем более что не всегда применимо- допустим если игра не во весь
Sin> экран, а в "рамочке". там уж атрибуты особо не расставишь

Hо зато самый простой способ :)

от: Slavik Tretiak
кому: All
дата: 22 Feb 2006
Hello, acidrain

acidrain ну во-первых это не я такое решение предложил (кста можно и не в ПЗУ,
а в любое свободное место ОЗУ), а во-вторых, если там страничка озу, то надо
каким-нибудь битом в каком-нибудь порте запрещать туда запись.

;) или отключалку делать ;)

от: Slavik Tretiak
кому: All
дата: 22 Feb 2006
Hello, moroz1999

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

а если большие, так это какие ж поля надо будет чёрными (читать INK=PAPER)
оставлять ???

от: acidrain
кому: All
дата: 22 Feb 2006
Hello, Sinus

Sin> то можно в ПЗУ позапихивать

А вдруг там атм и страница ОЗУ вместо спекПЗУ и запоришь ось нафих? %)

от: moroz1999
кому: All
дата: 22 Feb 2006
Hello, Sinus

Sin> да, такое делалось в некоторых демках и игрушках.
Sin> но имхо не лучший выход.
Sin> тем более что не всегда применимо- допустим если игра не во весь
Sin> экран, а в "рамочке". там уж атрибуты особо не расставишь

выход отличный, сам на данный момент держу в голове как вариант. пофиг до
рамочки, главное - геймплэй :)

от: Гаврилов Виталий
кому: All
дата: 22 Feb 2006
Hello, axor

спрайт фиксированной ширины? если да, то можно написать набор подпроцедур типа:

;если влазит целиком
put_all:
dup N
ldi
edup
inc d
dec e
dup N
ldd
edup
inc d,e
ret

;если не влазит K знакомест справа
put_noK:
dup N-K
ldi
edup
inc d
dec e
dup K+K
inc hl
edup
dup N-K
ldd
edup
inc d,e
dup K+K
inc hl
edup
ret

естесно соптимизировать коррекцию адреса в HL

вывод будет состоять в вызове нужной процедуры.
плюс отсечение невидимых спрайтов. Итого имеем 1 процедуру полного вывода, N
процедур для вывода за правым краем и N процедур для вывода за левым краем.

зы: код можно переделать и под маску

от: moroz1999
кому: All
дата: 23 Feb 2006
Hello, Sinus

блин, и правда, торможу после работы :o

от: Slavik Tretiak
кому: All
дата: 23 Feb 2006
Hello, Soplik

1) тормозно
2) проще обрезать спрайт, чем высчитыват где запортился экран
3) тормозно ;)

от: Виктор Иванов
кому: All
дата: 23 Feb 2006
Hello, moroz1999

А если кинуть безо всяких проверок, а запорченный экран быстро-быстро забить
фоном?

от: moroz1999
кому: All
дата: 24 Feb 2006
Hello, Soplik

Sop> А если кинуть безо всяких проверок, а запорченный экран быстро-быстро
Sop> забить фоном?

может возникнуть ситуация, что помимо фона на той стороне спрайт будет.

от: Виктор Иванов
кому: All
дата: 24 Feb 2006
Hello, Sinus

Уже понял.
А обязательно все спрайты попиксельно выводить?

от: Slavik Tretiak
кому: All
дата: 24 Feb 2006
Hello, Vladimir Kladov

Vladimir Kladov: очень хорошее решение, но к сожалению фреймовости не добится.

хотя я вот (когда муль свой тестил) посмотрел пару старых игрулек (Hydson Hawk
тот же) - нифига не фреймово, но не менее играбельно

от: moroz1999
кому: All
дата: 24 Feb 2006
Hello, Sinus

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

от: Владимир Кладов
кому: All
дата: 24 Feb 2006
Hello, moroz1999

Есть еще такое решение: строить весь кадр в буфере с последовательной
организацией строк, и при этом строки делать шире, добавляя с обоих краев
нужное число байтов (по размеру максимального спрайта минус 1). При переброске
обрезать. Работает в том числе когда задействована вся ширина для игрового поля
и когда есть рамки и не только рамки ink=paper. И очень неплохо, когда игровое
поле уже (а например справа еще что-то типа как меню команд в лазер сквадроне).




Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Железо - ЦАП`ы и АЦП.
Пьянка - про Чапая.
Тусовка - О тусовакх в Москве.

В этот день...   14 октября