больше цвета!!!
(c) poisoned cyberjack//triebkraftne
пытаясь сделать что-нибудь впечатляющее для нашей демы weed, я даже и не ожидал, что получится так неплохо. многие подходили ко мне с вопросом - мультиколор или как? между тем все просто это всего на всего полноэкранная цветная анимация :) правда, неплохо запакованная, но все же...
буйство цвета, видимое на экране - результат не движка, а правильно сделанной оригинальной картинки. как это сделать, лучше спрашивать не у меня, а у g. d.//tbk//4d, который все это рендерил в lightwave 7.5 на пц. после чего я их конвертировал из avi'шников при помощи bmp2scr_1.75 by lcd. и лишь с полученными после этого спектрумовскими цветными экранами я работал...
вот в принципе и все, что мне требовалось вам рассказать :) но по поводу хорошего настроения я расскажу еще и об своем пакере...
в деме за небольшое время показывается 198 цветных полноэкранных скринов. все это занимает 1.368.576 байт в не пакованном виде и около 290к в zip'е (hrust примерно так же жмет). если запаковать laser compact'ом будет немного меньше, что не играет большой роли, так как все равно это очень и очень много. поэтому используется свой пакер, который сжал эти 198 экранов в 80к, то есть каждый экран в среднем занимает 400 байт!!! пускай и с потерей качества :)
идею подкинул diver//4d в далеком 2001 году - а почему бы не совместить hi-res и low-res, пиксельную графику и атрибуты в самом движке, получив много цвета и большую скорость. реализовать это до конца я не смог до сих пор (хотя не буду смешить народ, доказывая, что занимаюсь этим с ночи до утра).
а теперь немного истории... пару лет назад у diver'а созрела мысль сделать дему, абсолютно невиданную на спектруме. выжать из спектрума все, что можно - причем без мультиколора, все за счет различных извратов с совмещением low-res и hi-res, атрибутов и пикселов. ведь не забывайте, что именно в этом и заключена вся мощь спектрума - иначе он проиграл бы на старте другим компьютерам, которые вышли позже и по многим параметрам обставляли наш zx. из-за довольно высокого разрешения, цветного экрана и очень высокой скорости обновления экрана (пускай скорость не велика, но и объем-то небольшой) западные авторы и делали игры до середины 90х годов, хотя многие остальные домашние компьютеры были уже мертвы. а сейчас эта фишка практически не используется - либо работают только с пикселами (вектора, точки, чанки 4х4), либо с атрибутами, но опять же как с чанками (8х8, мультиколоры всяческие). реально же совмещение не используется практически никогда - слишком сложно все это кодится и слишком для специфических целей это можно использовать. но у diver'а голова варит неплохо, и он смог придумать много идей (правда из которых больше половины, на мой взгляд реализовать нельзя :). но дема у нас не заладилась, как из-за нашей занятости (harm demo, moorhuhn game), так и из-за того, что леха в данный момент находился в армии...
про идейки эти я не забывал, но руки никак не доходили довести все это до ума. и вспомнил об этом лишь в этом году, во время доделывания нашей весенней вещи detroyt. не хватало эффекта в середину - вернее идея была, но кодить было некогда, а на анимашку не хватало памяти. немного помучавшись, я поднял свой недописанный чанковый энжин, обрезал все замашки на реалтаймовый калькуляйтинг, пофиксил все баги, переделал под 2 цвета, и как результат - посмотрите часть с летающими шестеренками. для сведения - 230 экранов заняли 22.5к.
практически тогда же в апреле и родилась идея - сделать цветную анимашку. но возник ряд трудностей - энжин из detroyt'а под цвета переделывался неохотно, паковка получалась никакая, да и скорость распаковки упала ниже 5 фреймов (установленный нами порог). поэтому я плюнул слюной на все это мучение с распаковкой чанков, геморрой с c2p, и сделал все так просто, насколько можно - просто-напросто запаковал все экраны :) правда, для этого я все же воспользовался теми же чанками, поэтому нечто от того подхода осталось...
идея этого мифического чанкового движка в принципе проста, хотя и извратна до кучи. мы отстраиваем экран в чанковый буфер (то есть без всякой маеты с адресацией экрана и работы с битами) 1х1 или 2х2 (я выбрал этот вариант как более оптимальный по скорости и объему данных - chanky 2x2 roxx!!! ). но так как это сделать в чистом виде нельзя (почему не спрашивайте - и так все ясно), то пришлось извратиться - обрабатывать экран в два прохода. на первом проходе мы обсчитываем только цвета вершин сетку 33х25 знакомест. для крупных цветных вещей получится много (больше половины точно) знакомест, в которых все четыре вершины будут одного цвета. такие знакоместа c2p просто закрашивает этим цветом через установку нужных атрибутов и забывает про них. все же остальные надо детализировать обсчитывать ребра знакомест (в моем случае с шагом 2 пикселя), после этого находим нужный чанк (или спрайт - как вам проще для понимания), который и выводим в этом знакоместе на экране. с цветом сложнее - но я решил брать цвета первых двух вершин и не париться... вот так кратко изложена идея нового полноцветного чудо-движка, который не реализован до сих пор :)))
доделать все это до ума не хватило времени и желания (лень вечный отмаз :) единственное, что я сделал почти до конца - это нарисовал чанки (можно было бы и сгенерить, но наш принцип handmade :) основная проблема связана с вторичным проходом по чанковому экрану - слишком уж заумно все выходит :((( поэтому невиданным реалтаймом в наших последних демах и не пахнет просто очень крюютая паковка...
в detroyt'е сделано так: распаковывается сетка цветов для вершин знакомест. затем по четырем вершинам знакоместа определяется, какой тип спрайта надо рисовать. получается 16 типов спрайтов, причем сразу скажу, что два я не рисовал совсем (вместо них были черные знакоместа :), а два это просто-напросто знакоместа закрашенные paper=ink. осталось 12 видов спрайтов, для каждого из которых я руками нарисовал по 16 спрайтов. номер спрайта (4 бита) достается из пакованных данных. объяснять что, почему и как, пожалуй не буду :) прилагается экран, на котором эти спрайты нарисованы. кому очень уж интересно - обращайтесь ко мне.
в weed'е никакой сетки нет, никакого определения тоже нет. для каждого знакоместа после распаковки получаем цвет и, если надо, номер спрайта. спрайты рассчитывать или перерисовывать мне было немного непонятно как, поэтому были взяты спрайты из предыдущего продукта. именно поэтому их не 256, а 163 :) почему не 192? потому что некоторые из них слегка одинаковые (читай полностью), и я их со спокойной душой выкинул...
определение типа и номера спрайта на этапе паковки тоже упрощено. на цвета вершин вообще не обращается никакого внимания, все обсчитывается банальным перебором всех вариантов. спрайт, у которого минимальное количество несовпадающих пикселов, и считается нужным. в принципе это логично, но это машинная логика - человек бы выбрал хотя бы подходящий по форме...
в приложении вы сможете найти два исходника. my_batch - мой личный исходник, предназначенный для сборки демы. в таком виде он и использовался. что к чему - no comments, сделано все для своих нужд. colorfull - исходник, максимально приведенный к культурному виду (насколько это возможно). комментарии я писал уже сейчас, поэтому сильно не смейтесь. также не обращайте особого внимания на ужасающий код - работает, и это главное! не знал же я, в самом деле, что это кому-то понадобится :)
оба исходника в формате storm assembler by x-trade. как быть поклонникам других асмов я не знаю, так как конвертация практически невозможна. а я по-другому сейчас писать уже не могу :(((
пускай вас не смущает многократное повторение некоторых строк в некоторых местах :) раскрытие внутренних циклов плохо сказывается на объеме и модифицируемости кода, зато очень хорошо на скорости и читабельности, упрощает кодинг в конце концов - а иногда просто регистров не хватает...
перед упаковкой вызывается процедура check, которая приводит экран в нужный вид для пакера - все пустые знакоместа закрашивает ink=paper. в связи с особенностями пц-конвертора bmp2scr полностью залитые знакоместа не ищутся, ибо они не получаются никогда.
еще есть одна хитрость... в некоторых знакоместах могут находиться 1-2 пикселя. подходящие (разумно) спрайты находятся не всегда, в результате получаются различные глюки на экране. на момент пати-версии я обошел это добавлением в спрайтовый набор двух спрайтов - полностью пустого и полностью залитого, хотя это и не особо помогло - избранные товарищи, видевшие данное творение, это подтвердят. после пати же я написал нормальный оптимизатор, который такие знакоместа просто очищает. процедура optim - это все и делает. параметр p_min как раз и задает количество пикселов, меньше которого знакоместо очищается. так как проверка идет как в меньшую сторону, так и в большую (1-2 и 62-63 пикселя для p_min=2), то установка параметра равным 32 превратит всю картинку в чистые атрибуты. некоторым нравится :)))
check и optim делают немного пересекающуюся работу, но исправлять я уже не стал.
также применен простенький rle-пакер со странной логикой. блок пакованных данных представляет собой непрерывное битовое поле, в котором содержатся команды и их аргументы. команды 2хбитовые, соответственно их целых 4 штуки:
00 - новый цвет, 3b - код цвета 01 - спрайт, 8b - номер спрайта 10 - цепочка, 4b - длина цепочки 11 - одиночное залитое знакоместо
чуть подробнее... работа с цветом идет так - у нас есть два цвета, paper и ink. команда "новый цвет" задает новое значение ink, а paper становится равным старому ink. такая схема оказалась наиболее выгодной. спрайт... рисуется спрайт с нужным номером, цвет задается текущими цветами. одиночное залитое знакоместо - ink=paper_current, paper=paper_current, при этом текущие цвета не меняются. цепочка - последовательность залитых знакомест. длина задается четырьмя битами, это число подобрано опытным путем, более меньшую или большую разрядность оказалось использовать невыгодно.
алгоритм паковки я описал, распаковка аналогична. вся работа идет с данными, структура которых приведена выше. можно написать по-своему, ничуть не удивлюсь, если будет проще и быстрее, чем у меня. просто нас полностью устроило сие творение - скорость паковки невысока, но не каждые же пять минут надо что-нить запаковывать, а распаковка еще лучше - укладывается в 3 фрейма при нашей задержке в 5. а все знают, что лучшее враг хорошего :)
в приложении кроме вышеупомянутых исходников вы найдете несколько скринов для тестинга, а в качестве бонуса небольшую программку, демонстрирующую данный метод паковки/распаковки специально для тех, кто не видел нашей демы :)))
wbw, poisoned cyberjack//triebkraftne