3D проецирование пола/трассы
В Wolf'2004 пола нет, а в существующих
на ZX гонках он хотя и есть, но нечестный
(по нему нельзя ездить поперёк трассы и в
обратном направлении). Настоящий пол нужно
получать перспективным проецированием на
экран картинки (трассы) достаточно большо─
го размера.
Newart>
Игровое окно занимает,допустим, 160 пи-
кселей, половину окна занимает спроеци-
рованный ландшафт, длина его, наверно, до
проецирования раза в 3 больше,чем видно на
экране после проецирования. Объясни, как
ты предлагаешь сделать без ротации...
Alone Coder>
Ротация будет, но в процессе переноса
графики в chunkmap. Т.е. 2 прохода:
1. rotate;
2. вывод чанков.
Newart>
А проецирование будет во время вывода
чанок?
Alone Coder>
Проецирование во время ротации.
Пусть высота земли = 80 пикселей ( 40
чанков). Расстояния,на которых видны выво─
димые горизонтальные линии, относятся друг
к другу как 40/40, 40/39, 40/38 и т.д.,по─
следняя линия - 40/1. Допустим, что карта
имеет размер, ну,хотя бы 256x512 пикселей.
Пусть 4 самых задних линии земли не видны
(серые), а видим мы на расстояние не более
1/3 карты (зависит от высоты наблюдателя).
Тогда при чанках 2x4 на самых ближних ли─
ниях будут различимы пиксели текстуры, но
получатся они размером не более 2 чанков,
если я не обсчитался. Т.е. ОЧЕHЬ ДАЖЕ тер-
пимо...
Внутри каждой горизонтальной линии эк─
рана мы движемся по текстуре равномерно,
равными приращениями. Перед выводом линии
нужно только рассчитать её начало на текс─
туре и вектор движения по текстуре (и то,и
другое можно высчитать по таблицам).
Математика тут ничего из себя не предс─
тавляет.
Обозначим координаты игрока через x0,
y0, а его угол поворота - через a. Условно
определим ось z от середины экрана вниз,
масштаб - любой.
Тогда расстояние по карте до точки, ко─
торую нужно вывести в середине горизонтали
z, равно: d(z)=k1/z, где k1 - некий коэф─
фициент (он зависит от высоты игрока над
поверхностью).
Координаты этой точки на карте, если их
отсчитывать от координат игрока, равны:
cx(z,a)=d(z)*cos(a); cy(z,a)=d(z)*sin(a).
Шаг,с которым мы будем проходить карту,
рисуя горизонталь z, равен: step(z)=k2/z,
где k2 - некий другой коэффициент (отноше─
ние k1/k2 определяет прямоугольную "вытя─
нутость" изображения).
Составляющие этого шага по x и y равны:
stepx(z,a)=step(z)*sin(a);
stepy(z,a)=-step(z)*cos(a).
Тогда понятно,что левая точка нашей ли─
нии z на карте будет иметь координаты:
leftx(z,a)=cx(z)-width*stepx(z,a);
lefty(z,a)=cy(z)-width*stepy(z,a).
То есть вместо математики может быть
просто таблица значений stepx,stepy,leftx,
lefty размером 36*64 (остальные 192 угла a
можно свести к этим 64 углам простыми об─
менами координат и сменами их знаков).Пос─
кольку эти числа 16-битные,то таблица зай─
мёт 18 килобайт (можно разложить по стра─
ничкам - особая скорость здесь не нужна).А
все вычисления "на лету" сведутся к прос─
тому прибавлению координат игрока (x0, y0)
к прочитанным из таблицы координатам.
Главное - разбиение карты на "знакомес─
та" (тайлы). Предположим, что тайл равен
16(Y)*8(X) текселей (текстурных элементов,
пикселей). Храниться они будут по адресам
%0110yyyyxxxttttt, где yyyy,xxxx - коорди-
наты внутри тайла, ttttt - номер тайла.
Тогда карта будет 16*128=2048(Y) на 8*256=
=2048(X).
Проецирование идёт в чанковый буфер
(потом можно будет накладывать спрайты).
width=24 ;CHRS
(DUP width)
ADD IX,DE ;Y
EXX
ADD HL,BC ;X
LD E,H ;X
LD D,HX ;Y
(set 7,d) ;чтобы не зашкал.за карту
LD A,(DE) ;номер тайла, стоящего в
;этом месте карты
XOR L ;мл.байт X (внутри тайла)
AND #1F
XOR L ;A=%xxxttttt
EXX
LD L,A
LD A,LX ;мл.байт Y (внутри тайла)
RRA
SCF
RRA
SCF
RRA
OR A
RRA ;A=%0110yyyy
LD H,A ;HL=адрес текселя в тайле
LD B,(HL) ;цвет чанка
;и ещё раз:
ADD IX,DE ;Y
EXX
ADD HL,BC ;X
LD E,H ;X
LD D,HX ;Y
(set 7,d) ;чтобы не зашкал.за карту
LD A,(DE) ;номер тайла, стоящего в
;этом месте карты
XOR L ;мл.байт X (внутри тайла)
AND #1F
XOR L ;A=%xxxttttt
EXX
LD L,A
LD A,LX ;мл.байт Y (внутри тайла)
RRA
SCF
RRA
SCF
RRA
OR A
RRA ;A=%0110yyyy
LD H,A ;HL=адрес текселя в тайле
LD C,(HL) ;цвет чанка
PUSH BC ;кладём 2 чанка в чанкмэп
(EDUP)
Точность расчётов = 1/8 текселя.
Вывод чанков на экран:
(DUP width)
POP HL ;цвета двух чанков:
;%1111aaa1,%1111bbb1
LD A,(HL)
LD (BC),A
LDD ;DE=BC+256 (или наоборот)
(EDUP)
Можно чередовать вывод чанков с проеци─
рованием после каждой строчки картинки -
но тогда без спрайтов на экране.Хотя можно
выводить их хитро, тоже по строчке.
Размер чанкмэпа (включая верхнюю поло─
вину, где карта не рисуется):
48(2*width)*80(hgt)=3840.
Памяти не осталось, поэтому можно испо─
льзовать 2-й экран,а можно уменьшить карту
по Y в два раза (до размера странички) -
добавить ещё SET 6,D. Вообще-то эти SET -
дело вкуса, можно просто не давать игроку
приближаться к границе карты.
A. Coder