Virtual Worlds #01
31 декабря 1999

Ассемблер - Круги на воде: Алгоритмы имитации эффекта известного на других платформах, под названием "круги на воде".

<b>Ассемблер</b> - Круги на воде: Алгоритмы имитации эффекта известного на других платформах, под названием
 ┌────────────────────────────┐
░▒▓▒▓█▓█ RIPPLES █▓█▓▒▓▒░░ └────────────────────────────┘

          (C) Reaper/ZX-MANIACS


  В  этой статье я решил описать
эффект,   известный   на  других
платформах как дождь на воде. Он
представляет  из  себя  расходя-
щиеся    концентрические   круги
(  как  след  на  воде от капель
дождя  ).  Этот  эффект особенно
похож  на воду, если под кругами
есть    какая-нибудь   картинка.
Впрочем,    данную   модификацию
эффекта   на  Спектруме  сделать
красиво  довольно сложно ( хотя,
например, в демке Emergency этот
эффект есть и смотрится он очень
даже неплохо ). Как бы то ни бы-
ло, я буду описывать обычный эф-
фект,  без  фоновой  картинки. В
конце,  я,  пожалуй,  скажу пару
слов об алгоритме работы с фоно-
вой  картинкой, но пример приво-
дить не буду.

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

  Итак, для создания эффекта Вам
понадобятся  два  буфера, равных
по  размеру  экрану. Так, напри-
мер, в примере используются чан-
ки. Выводятся они на 2/3 экрана,
так  что  размер  обоих  буферов
должен быть 64*32. Но здесь есть
одна тонкость. Желательно остав-
лять нетронутой ( постоянно рав-
ной  нулю ) полоску толщиной в 1
чанк  по всему периметру буфера.
Поэтому у меня в примере исполь-
зуются буфера размером 66*34, но
выводится на экран лишь внутрен-
няя  их  часть  размером  64*32.
Можно  оставить  буфера размером
64*32,   но  тогда  обрабатывать
следует  только  внутреннюю  об-
ласть  62*30 ( это, кстати, даст
увеличение скорости из-за умень-
шения  обрабатываемой  области и
из-за  упрощения  конвертации  в
формат 2 чанка на байт ( или ус-
корения  вывода  чанков, если вы
пользуетесь   процедурой  вывода
чанков   в  формате  1  чанк  на
байт ) ).

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


  1)  Выставляются  указатели  в
верхнюю  левую ячейку текущего и
предыдущего  буферов ( а лучше в
ячейку  на  1 строку ниже и на 1
столбец правее верхней левой, т.
к.  это даст возможность не зат-
рагивать  крайние строку и стол-
бец );

  2) Берем значения четырех яче-
ек вокруг текущей в 'предыдущем'
буфере и складываем их;

  3) Полученное число делим на 2
и  вычитаем из него значение те-
кущей ячейки в 'текущем' буфере;

  4)  Если  полученное  значение
меньше  нуля, приравниваем его к
нулю.  Обрубаем  его  также и по
максимуму ( в моем примере, мак-
симальное    значение,   которое
воспринимают чанки - 31, поэтому
полученное    число   обрубается
просто по AND 31 );

  5) Ну и теперь то, что получи-
лось,  кладем в текущую ячейку в
'текущем' буфере;

  6)  Переставляем  указатели на
следующие ячейки в обоих буферах
и  завершаем  циклы ( сначала по
столбцам, а потом по строкам );

  7)  Меняем  местами  текущий и
предыдущий буфера. Точнее, прос-
то переставляем указатели, и те-
перь  текущий  буфер  будет счи-
таться предыдущим и наоборот.

  Вот,  в общем-то, и весь внут-
ренний цикл эфекта. Теперь можно
зацикливаться на пункт 1. Если в
'предыдущий'   буфер   поставить
точку,  то она разойдется круга-
ми.

  Для большей наглядности приве-
ду  алгоритм в неком псевдокоде,
в  основном  смахивающем на Спе-
ковский Бейсик.

  Предположим,  что  у  нас есть
два    буфера:    COLD(M,N)    и
NEW(M,N).  Так  будет  выглядеть
процедура 'запуска кругов' в них
( для упрощения опущена проверка
значений на выход за пределы до-
пустимого диапазона ).

DO
X = INT(RND * (N - 1)) + 1
Y = INT(RND * (M - 1)) + 1
OLD (Y,X) = 15
FOR I = 2 TO M - 1
FOR J = 2 TO N - 1
A = OLD(I-1,J) + OLD(I+1,J) +
+ OLD (I,J-1) + OLD(I,J+1)
A = A/2 - NEW(I,J)
NEW(I,J) = A
NEXT J,I
NEW(M,N) -> SCREEN
SWAP OLD(M,N), NEW(M,N)
LOOP WHILE NOT KEYPRESSED


Здесь NEW(M,N) -> SCREEN - вывод
на экран ( в данном примере под-
разумеваются  чанки, принимающие
значения  от  0  до  15.  Именно
поэтому  в  'предыдущий' буфер в
качестве 'источника' кругов кла-
дется точка со значением 15 ). В
этом примере новый источник кру-
гов  ставится в буфер перед каж-
дым  внутреним  циклом. Это дает
очень  большое количество кругов
на экране и получается мельтеше-
ние...   но  все-равно  довольно
занимательно.

  У вас может возникнуть вопрос,
почему исходник работает со зна-
чениями  ячеек,  равными  0..31,
если  чанки  воспринимают только
значения  0..15 и приходится до-
полнительно  конвертировать. Все
дело  в  том,  что размер кругов
зависит   от   величины   числа-
источника.  Если  ставить  в ка-
честве  источника  число  15, то
круги получатся маленькими и не-
красивыми. Можно ставить даже 63
(  так,  имхо,  сделано  в демке
BlAME  ),  но  мне  больше всего
нравится  вариант  с источником,
равным 31.

  Вот, вроде, и все. Напоследок,
как и обещал, расскажу, как пус-
кать  круги поверх картинки. Для
этого  вам, естественно, понадо-
бится  буфер-картинка. Для прос-
тоты будем считать, что он равен
по    размеру    'текущему'    и
'предыдущему'  буферам  ( к тому
же, именно так обычно и бывает).

Алгоритм таков:

  1)  Проделываете  все  обычные
действия для создания кругов, но
не  выводите  'текущий' буфер на
экран;

  2) Теперь рассматриваются 'те-
кущий'  буфер  и буфер-картинка.
Для   каждого  элемента  буфера-
картинки   проводятся  следующие
действия:

  3)  Берется  значение из соот-
ветствующей ячейки из 'текущего'
буфера и из него вычитается зна-
чение   ячейки  справа  от  этой
(   все   так   же  в  'текущем'
буфере ). Получается смещение по
X;

  4)   Теперь  берется  значение
соответствующей  точки из 'теку-
щего' буфера и вычитается значе-
ние  точки на строку ниже. Полу-
чается смещение по Y;

  5) Оба смещения делятся на ка-
кое-нибудь  число.  На PC в 256-
цветном эффекте  лучше всего де-
лить  на 8. На  Спеке в  чанках,
наверно,  подойдет деление на 4,
хотя это все подбирается опытным
путем;

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

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

  Ну а теперь алгоритм в псевдо-
коде.   В   этом  алгоритме, для
упрощения,   нет   вышеуказанной
проверки  на  выход координат за
пределы буфера. Итак, NEW(M,N) -
'текущий'  буфер, SCR(M,N) - бу-
фер-картинка,  OUT(M,N) - буфер,
который  будет выводиться на эк-
ран.

FOR I = 2 TO M - 1
FOR J = 2 TO N - 1
XS = NEW(I,J) - NEW(I,J + 1)
YS = NEW(I,J) - NEW(I + 1,J)
XS = XS / 4
YS = YS / 4
X = J + XS
Y = I + YS
OUT(I,J) = SCR(Y,X)
NEXT J,I
OUT(M,N) -> SCREEN

  Как  несложно заметить, расчет
смещений очень смахивает на рас-
чет      псевдо-нормали        в
bumpmapping'е.  Так  что,  здесь
мы,  в  некотором смысле, делаем
бампоподобное  освещение картин-
ки.

  Алгоритм  всего эффекта кругов
поверх  картинки  в общих чертах
выглядит примерно так:

  1)  Ставится точка в 'предыду-
щий' буфер;
  2)  На  основе 'предыдущего' и
'текущего' буферов рассчитывает-
ся изображение в 'текущем' буфе-
ре;
  3) На основе 'текущего' буфера
и буфера-картинки рассчитывается
изображение в выходном буфере;
  4) Выходной буфер выводится на
экран;
  5)  И  опять на п.1 ( или п.2,
если  не нужно ставить новый ис-
точник кругов).

  Теперь совсем все. Надеюсь, вы
хоть  что-нибудь поняли из моего
параноидального  бреда. В прило-
жении  вы  можете найти исходник
данного  эффекта  на асме. В нем
вы   можете  управлять  курсором
клавишами 6/7/8/9 и пускать кру-
ги  клавишей 0. В исходнике есть
пояснения,  так  что  у  Вас еще
есть шанс разобраться на практи-
ке,  если  Вы  до сих пор не все
поняли.


P.S.: Приведенный исходник рабо-
тает очень медленно. Как сделать
быстрее  ,  а это можно сделать,
вам придется думать самим!







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

От редакции - история создания журнала.

Путеводитель - подробное содержание номера.

Описание оболочки - описание оболочки и методов ее правильной эксплуатации.

Авторы - об авторах.

Ассемблер - Z80 Flags: недокументированные комманды процессора Z80.

Ассемблер - Оверлеи для JC: Описание методов создания утилит работающих под управлением Jemmini_Commander 4.0T.

Ассемблер - Секреты TR-DOS: о методах пределения наличия дисководов.

Ассемблер - Круги на воде: Алгоритмы имитации эффекта известного на других платформах, под названием "круги на воде".

Ассемблер - Поиск пути. Решение задачи "статического" поиска наикратчайшего маршрута между двумя точками.

Отдохни - Механический эффект. История о том, что бывает, если использовать презервативы сомнительного происхождения.

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

Железо - Прерывания: Кое-что непонятное о прерываниях второго рода.

Техпомощь - Мысли вслух. Интересно письмо из конференции fido7.zx.spectrum на тему "К вопросу о стандартизации".

Техпомощь - File FAQ. Полный разбор форматов файлов, наиболее часто встечающихся в Интернет, и не только; а также способы их конвертации в "нормальный" вид.

Техпомощь - Dos Review: материал по формату дисковой операционной системы IS-DOS.

Техпомощь - Dos Review 2: материал по формату дисковых операционных систем ПК "АГАТ", Радио-86РК, SP-DOS, БК-0011М.

Техпомощь - Dos Review 3: материал по формату дисковых операционных систем CP/M, ASC SOUND MASTER, RT11, СМ ЭВМ РАФОС.

Техпомощь - Dos Review 4: материал по формату дисковой операционной системы от неизвестного автора.

DI:HALT:99 - Анализ DH:99. Наконец-то вся правда о прошедшей летом, в г.Дзержинске пати, от самих организаторов.

DI:HALT:99 - Hidden Parts. Жизнь дзержинских (и не только) спектрумистов в период проведения DI:HALT:99.

DI:HALT:99 - Результаты. После прошествия DH:99, чуть ли не каждая вторая газета, считала своим долгом придумать новый вариант результатов. Данная статья направле- на на то, чтобы окончательно поставить все точки над "И".

Программы - Alien: описание и прохождение игры по фильму "Чужой".

Программы - описание Universal AntiProtector 0.01 (программа для автоматического раскалывания ряда популярных защитных систем).

Программы - редактор игровых экранов "Белые Пятна".

Программы - Exhumator: программа для "эксгумации дисков".

Программы - чанковый графический редактор: Hard Core ver 3.01

Программы - Глаз Вопиющего: програмка позволяющая смотреть картинки, спрайты, слушая при этоммузыку.

Отдохни - Стих о Sysop'e. Поэзия однако...

Отдохни - Секс в Фидо. Юмористический расказ о том, как же на самом деле занимаются любовью заядлые фидошники.

Отдохни - Анекдоты. Подборка анекдотов с компьютерной тематикой.


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

Похожие статьи:
CMOS-часы - Микросхема CMOS-часов для компьютера (схема включения).
Есть такое мнение! - Кому она нужна, эта "Небьюла"?
Проходилка - Описание-проходилка игры: Занни и Бонни часть 1: Спасение.
Вопросы - Нужен ли на Speccy универсальный энциклопедический словарь?
Вступление - содержание номера.

В этот день...   18 апреля