Кодерам
----------------------------------------
Размышления о 3D
------------------
Николай Дворник /KilleRam/
В этой короткой статье я хочу
рассказать о моей идее на счет создания
универсального 3D движка на SPECCY для
написания игр соответствующего направле-
ния. Как мне кажется, наиболее удачно 3D
реализовано в следующих программах: DOOM
Ьу Digital Reality, Awaken Ьу Rage, Wolf
3D Ьу AlCo/i8, Stellar Game Ьу Brain-
wave. Реализации, конечно, отличные, но
до Delta Force'а и до Medal of Honor не
тянут:). Я в смысле реализации полного
ландшафта, а не тупого беганья по лаби-
ринту (Awaken не в рамках стиля).
Я предлагаю создать на SPECCY редак-
тор на котором можно будет писать прак-
тически любой 3d ActiOn. А точнее, чисто
редактить зоны (подгружаем текстуры,
создаем плоскости-обЪекты и "разрисо-
вываем" их текстурами).
Первое с чего я хочу начать - это
таблица высот. Эта таблица хранит данные
о высоте (z-координате), на которой бу-
дет впечатываться тот или иной снимок
(см. ниже). Длина этой таблицы 255 байт,
при чем уровень 0 принадлежит плоскости
ХУ, а квантование уровней идет в соот-
ветствии с наименьшей высотой плоскости
(см. ниже).
ПРИМЕР:
1байт: уровень наинизшего снимка (ХУ)
2байт: уровень более высшего
...
192байт: уровень наивысшего снимка,час-
тый случай которого - небо.
Снимок - ортогональная, горизонтальная
проекция уровня высоты.
Формат снимка таков:
Размер снимка (16х16 бит)
1линия массива снимка соответствует у=0
и хранит данные о впечатываемых плоскос-
тях (см. ниже), минимальная ширина плос-
кости 4pix (см. ниже).
Например:
Х | 0 | 4 | 8 | 12 | 16 | 20 | 24 |
---+---+----+----+----+----+----+----+
N | 1 | 2 | 3 | 4 | 1 | 3 | 4 |
Это соответствует такому представлению:
Х
+----------------------------------->
| +---------------------------------+
| |1234134 и т.д до Х(мах)/4 |
| | |
| | |
| | |
| | |
| | |
| | |
| +---------------------------------+
УС
И так для каждой линии до У (мах)
Хочу сказать, что максимальное количест-
во плоскостей 111, а максимальный номер,
роспознаваемый программой 255, при этом
коды от 0 до 31 - управляющие (например,
оповещают программу о впечатывании
спрайта вместо плоскости и т.д.) Коды от
32 до 143 говорят программе о том, что
плоскость с соответствующим номером впе-
чатывается параллельно оси Х, а если ко-
ды находятся в пределах от 144 до 255,
то параллельно оси У.
То есть, плоскость с номером 32 соот-
ветествует плоскости с номером 144. Код
31 соответствует пустоте (ничего не впе-
чатывается). Плоскость - массив содержа-
щий данные о впечатываемых текстурах и
их цвете. Максимальное количество
текстур 222 (коды от 0 до 31 - управляю-
щие). Размер текстуры 8x4pix, чтобы удо-
бнее было разрисовывать.
Пример формата
1байт - длина (ширина)
2байт - высота
3
|- размер в байтах
4/
далее идет
Sбайт - номер текстуры
ббайт - цвет
и т.д.
В памяти все хранится по порядку. В
процессе подготовки ландшафта он пол-
ностью преобразуется в координатную фор-
му (над ней легче производить преобразо-
вания), а потом в соответствии с полу-
ченными координатами впечатываются текс-
туры.
- - -
Свои мышления по-поводу этой идеи
шлите либо в редакцию, либо мне лично по
адресу:
ул.Суворова 22, г.Енакиево-19,
Донецкая обл., Украина, 86486
* * *
Простой вывод спрайта
-----------------------
Денис Токарчук /DWT/
Не знаю, возможно в каких-то источни-
ках и было написано о подобном приеме
вывода спрайта, но до него я дошел путем
экспериментов.
Как известно, спрайт в памяти компь-
ютера расположен последовательно -
строчка за строчкой. Однако спектрумов-
ский экран имеет свои особенности, о ко-
торых все прекрасно знают. Следователь-
но, сложность вывода спрайта на спектру-
мовский экран состоит в пересчете следу-
ющей линии по оси У в экранной памяти.
Существует множество способов выводить
спрайт на экран - от "грубовысчитывае-
мых" (но универсальных) до табличных и
стековых. Я же предлагаю некий гибрид
таблично-стековой выводилки спрайта.
Конструкция такой программых чрезвы-
чайно проста. Допустим, где-то в памяти
с адреса TABL находится таблица примерно
следующего вида: #4000, #4100, #4200,
#4300 . . . #4020, #4120, #4220, и т.д.
То есть адреса каждой последующей линии
экрана в памяти. А по адресу SPR_V на-
ходится программа непосредственно вывода
спрайта:
SPR_V LD (STACK),SP
LD HL,адрес спрайта
LD SP,TABL
DUP высота в пикселях
РОР DE
DUP ширина в знакоместах
LDI
EDUP
EDUP
LD SP,0
STACK EQU $-2
RET
Надеюсь, что комментарии к этому лис-
тингу излишни, так как все ясно: поме-
щаем в регистр DE из стека (который на-
ходится у нас на таблице адресов экрана)
значение текущей линии экрана, затем
командами LDI перекидываем одну линию
спрайта на экран (HL)->(DE), потом "сни-
маем" со стека следующую линию, и так до
конца. Элементарно, не правда ли?..
Однако по скорости выполнения эта
конструкция (я ее называю РОР DE-LDI) не
является самой оптимальной, хотя тоже
довольно шустрая. Например, спрайт в
10х20 знакомест она выводит примерно за
27250 тактов. По-моему, неплохо.
Другой вопрос - как бы ее сгенерить,
чтобы довольно увесистый кусок кода не
хранить эдаким балластом в программе.
Прежде всего, необходимо сгенериро-
вать таблицу адресов экрана (названную
нами TABL), что довольно-таки просто. А
затем нехитрой программкой создать собс-
твенно выводилку.
Ну а вот и пример:
TABL EQU #6000 ;адрес, куда раз-
;мещать таблицу
;адресов экрана
SPR_V EQU #8000 ;адрес, где будет
;находиться прог-
;рамма вывода сп-
;айта
ADR_SCR EQU #4000 ;адрес экрана,ку-
;да печатать спр-
;айт
SPR_НТ EQU 64 ;высота спрайта в
;пикселях
SPR_WT EQU 8 ;ширина спрайта в
;знакоместах
ORG #6200
;формируем таблицу адресов экрана:
МАКТАВ LD DE,TABL
PUSH DE
LD HL,ADR_SCR
LD В,SPR_НТ
МТ1 LD А,L
LD (DE),А
INC DE
LD А,Н
LD (DE),А
INC DE
INC Н
LD А,Н
AND 7
JR NZ,МТ2
LD А,L
ADD А,#20
LD L,А
JR С,МТ2
LD А,Н
SUB 8
LD Н,А
МТ2 DJNZ МТ1
;а вот и сама генерилка программы вывода
;спрайта:
МАКЕ_SV
;----------------------
LD HL,SPR_V ;Записываем по
LD (HL),#ED ;адресу SPR_V ко-
INC HL ;манду LD (..),SP
LD (HL),#73 ;Адрес, куда SP
INC HL,HL,HL ;запишется - вы-
;ясним позже
;----------------------
LD (HL),#31 ;Записываем по
INC HL ;следующему адре-
РОР DE ;су LD SP,TABL,
LD (HL),Е ;то есть помещаем
INC HL ;стек на адрес
LD (HL),D ;таблицы адресов
INC HL ;
;----------------------
LD С,SPR_НТ
MSV0 LD (HL),#D1 ;по следующему
;адресу помещаем
;РОР DE
INC HL
;----------------------
LD В,SPR_WT ;Записываем LDI
MSV1 LD (HL),#ED ;SPR_WT раз (то
INC HL ;есть ширина сп-
LD (HL),#А0 ;райта определяе-
INC HL ;тся количеством
DJNZ MSV1 ;LDI)
;----------------------
DEC С ;Повторяем всю
JR NZ,MSV0 ;конструкцию (РОР
;DE-LDI) SPR_НТ
;раз
LD (HL),#31 ;Записываем в по-
;следующий адрес
;LD SP,..
INC HL ;И сохраняем сле-
LD (SPR_V+2),HL ;дующий адрес
;в начало програ-
;ммы (куда сохра-
;нять стек)
INC HL,HL
LD (HL),#С9 ;Ну и в конце -
;RET
RET
После генерации программы вывода
спрайта, можно ее запустить, не забыв
перед CALL SPR_V записать в HL адрес
спрайта. Вот и все что я хотел сказать:)
- - -
Other articles: