Info Guide
#07
31 мая 2005 |
|
Gamedev - 3D проецирование пола/трассы в играх.
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
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября