Demo or Die #02
31 июля 1999

Demo-строение - древний эффект под хитрым названием Moving Shit.

__________________________________________

    (C) Devil of eTc/Scene'99
     ..... Moving Shit .....

   Данная  статья описывает древний эффект
под хитрым названием Moving Shit. Я уверен
что  многие наши читатели давно его знают,
однако  для  начинающего  програмиста  она
окажется, я надеюсь, интересной.
   Попутно мы рассмотрим множество проблем
возникающих   при  опимизации  алгоритмов,
таких как:
   -   переброска   спрайта   на  экран  с
исполизованием стека,
   - рациональное использование таблиц для
расчета  адреса  экрана,  адреса  линии  в
спрайте и т.д. и т.п.

  Для начала суть алгоритма.

   К  примеру  мы имеем таблицу синусов, а
так   же  две  переменные  характеризующие
смещение в данной таблице.
   Для определенности, пусть таблица у нас
будет  длинной  256 байт и будет принимать
значения от 0 до 64. Так же, для ускорения
кода, расположим ее по кратному адресу.
   Переменные смещения примем 8-ми битными
и  пусть  они  находится  соответствено  в
переменных A и B.
   Теперь  нам надо создать спрайт в каком
либо редакторе. При этом спрат может иметь
произвольную ширину (в разумных пределах),
но  длинна  должна  быть  равна удвоенному
муксимальному   значению  нешей  синусоиды
т.е.  64*2=128.  В спрайте может находится
все  что угодно: круги теугольники и т.д.,
в общем все зависит от вашей фантазии (для
примера  я  создал два разных спрайта и Вы
можете сразу увидеть разницу в эффекте).


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

  NumLin:=(SIN[A+n]+SIN[B+n]);
  AddrLine:=AddrSpr+NumLin*len;

где   NumLin  -  номер  выводимой  линии;
      n    -     берется из счетка цикла;
      AddrSpr -  ну тут все ясно это ад-
                 рес спрайта в памяти;
      len - ширина спрайта в знакоместах;

После  того  как  мы получили адрес линии,
смело  выводим  ее  на экран и переходим к
расчету следующей.
   После того как мы построили спрайт надо
изменть переменные A и B по формуле типа:
  A:=A+Step1;
  B:=B+Step2;
{Step1 не равно Step2}

   Вот и все. Если вы все понели то дальше
можете  не  читать,  а  для  сомневающихся
привожу   пример  исходника  с  подробными
пояснениями.


        ORG #7000

Y_S     EQU 129     ;длинна спрайта

        CALL INIT_P ;Инициализируем все
                    ;таблицы и кидетели
                    ;подробнее в самой
                    ;процедуре
START   LD A,#7F    ;проверяем на нажатие
        IN A,(#FE)  ;пробела и выходим
        RRA
        RET NC

        EI
        XOR A
        OUT (#FE),A
        HALT        ;ждем INT'а
        LD A,1
        OUT (#FE),A
        DI


        LD D,SINTAB[ ;заносим в D и H
        LD H,D       ;старший адрес табл.
                     ;синусов
POS1    LD A,0       ;INC'аем переменную
.1      INC A        ;A (см. выше)
        LD (POS1+1),A
        LD E,A
POS2    LD A,0       ;DEC'аем переменную
.4      DEC A        ;B (см. выше)
        LD (POS2+1),A
        LD L,A
;в принципе INC или DEC подбирайте сами по
;вкусу,    главное,    чтобы    прирошение
;переменных A  и  B  было  как можно более
;разным

        EXX
        LD H,TBLADD[ ;заносим в H',старший
        EXX          ;байт таблицы по ко-
                     ;торой мы считаем
                     ;AddrLine, подставляя
                     ;в L', NumLin

        LD (SPBUF),SP
        LD SP,BUFADR ;в SP,таблица адресов
                     ;линий в раскрытом
                     ;кидателе  спрайта

GETAD   INC E,L   
        LD A,(DE)
        ADD A,(HL)
        EXX
        ADD A,A      ;набодим NumLin
        LD H,TBLADD[ 
        LD L,A       ;L=NumLin
        POP DE       ;DE,адрес в кидателе
                     ;спрайта
        LDI          ;заносим AddrLin
        LDI          ;в раскрытый кидатель
        EXX          ;спрайта
ENDGET
        DS (ENDGET-GETAD)*Y_S
;В  этом  буфере  у  нас  повтруен 129 раз
;участок кода  от  GETAD  до  ENDGET,  для
;ускорения

        LD SP,(SPBUF)

        CALL PUTSP ;собственно кидаем на
                   ;экран спрайт

        JP START   ;на начало

DOWN_HL INC H
        LD A,H
        AND 7
        RET NZ
        LD A,L
        ADD A,32
        LD L,A
        RET C
        LD A,H
        SUB 8
        LD H,A
        RET

;Процедура INIT_P генерирует кидатель
;спрайта с применением стека

INIT_P
        LD HL,PUTLIN
        LD DE,ENDPUTL
        LD BC,(ENDPUTL-PUTLIN)*(Y_S-1)
        LDIR
        EX DE,HL
        LD (HL),#ED
        INC HL
        LD (HL),#7B
        INC HL
        LD (HL),SPBUF]
        INC HL
        LD (HL),SPBUF[
        INC HL
        LD (HL),#C9

;далее идет процедура которая генерит
;процедуру расчета таблицы адресов линий

        LD HL,GETAD
        LD DE,ENDGET
        LD BC,(ENDGET-GETAD)*(Y_S-1)
        LDIR

        LD B,Y_S
        LD HL,#4010
        LD IX,ADRSCR+1
        LD DE,ENDPUTL-PUTLIN
INIT1   LD (IX),L
        LD (IX+1),H
        ADD IX,DE
        CALL DOWN_HL
        DJNZ INIT1

        LD B,Y_S
        LD DE,ENDPUTL-PUTLIN
        LD IX,BUFADR
        LD HL,PUTLIN+1
INIT2   LD (IX),L
        LD (IX+1),H
        INC IX
        INC IX
        ADD HL,DE
        DJNZ INIT2

        LD B,Y_S
        LD HL,0
        LD DE,SPRAIT
        LD IX,TBLADD
INIT3   LD C,L
.4      ADD HL,HL
        ADD HL,DE
        LD (IX),L
        INC IX
        LD (IX),H
        INC IX
        LD H,0
        LD L,C
        INC L
        DJNZ INIT3
        RET

;SPRAIT  INCB "SHIT_SP1"
SPRAIT  INCB "SHIT_SP2"

SPBUF   DW 0
BUFADR  DS Y_S*2

        ORG (($-1)[+1)*256
SINTAB  INCB "STAB"

        ORG (($-1)[+1)*256
TBLADD  DS Y_S*2


PUTSP   LD (SPBUF),SP;20
PUTLIN  LD SP,0;      10
        EXX ;          4
        POP HL;       10
        POP DE;       10
        POP BC;       10
        POP AF;       10
        EXX ;          4
        POP DE;       10
        POP BC;       10
        POP HL;       10
        POP IY;       10
ADRSCR  LD SP,0;       6
        PUSH IY;      11
        PUSH HL;      11
        PUSH BC;      11
        PUSH DE;      11
        EXX ;          4
        PUSH AF;      11
        PUSH BC;      11
        PUSH DE;      11
        PUSH HL;      11
        EXX ;          4
ENDPUTL  ;итого: 222 такта
         ;т.е. 13,87 такта на байт
         ;что не так уж и плохо...

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

Вопросы шлите на адрес:
to: Sergey Movchan 2:4635/100.128@FidoNet
__________________________________________

 



Другие статьи номера:

Deathmatch Quake v. 2.00 - Кpаткое пособие по методам лишения жизни себе подобных.

Demo party - оффициальные результаты Chaos Construction 999 для PC.

Demo party - оффициальные результаты Chaos Construction 999 для ZX Spectrum.

Demo party - оффициальные результаты Paradox'99 для PC.

Demo party - оффициальные результаты Paradox'99 для ZX Spectrum.

Demo-строение - Phong Shading.

Demo-строение - Radial blur, эффект размывки по кругу битмапа.

Demo-строение - Генератор таблицы квадратов.

Demo-строение - древний эффект под хитрым названием Moving Shit.

Demo-строение - о некоторых методах сортировки.

Demo-строение - Процедура печати чанков.

Demo-строение - Реализация плазмы pазмеpом 2x2.

NeOS FAQ - Часто задаваемые вопpосы по операционной системе для ZX Spectrum - NeOS.

Интервью - Интервью с Деннисом Ричи (Dennis M. Ritchie) создателем языка программирования "С".

Интервью - интервью с известным coder'ом, одним из основателей M&U Sinclair Club, а позже и eTc group - Lazy.

Интервью - Интервью с кодером и железячником LD/X-Trade.

Критика - картика на первый номеp жypнала Demo or Die.

От редакции - Интерфейс.

От редакции - Эпилог.

Приложение - упаковщик экранных файлов LazyPack 2.0.

Реклама - Реклама и обьявления.


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

Похожие статьи:
For Coderz - Маленькие программерские хитрости.
Вечный думатель - Что значит "Ф"?
Чёрный Ворон - примерный план действий для прохождения некоторых уровней игры Черный Ворон.

В этот день...   21 июля