Info Guide
#12
31 декабря 2017 |
|
Код - Посекторный движок для 3D-шутера от Destr.
Посекторный движок Посекторный движок для ЗD-шутера Destr Основная идея двига - это движок, опи─ санный в "Adventurer #13: Обмен опытом - Как написать 3D игру типа DOOM". (http://zxpress.ru/article.php?id=10028) Но мне не удалось переделать их код под свои представления, поэтому изложу просто общие принципы. Основное отличие - это не заливать стенки. Т.е. имеем мир, устроеный из выпуклых секторов и отображем только пол и потолок. Всё это для ускорения (хочется ведь побо─ льше фреймов). Итак, берется сектор - например, такой: Камера находится в точке 0, "взгляд" направлен по стрелке. Надо спроецировать все точки сектора в перспективу и обрезать ПО ГРАНИЦАМ ЭКРАНА. Как именно проецировать - решать каждому, но очевидно,что перспективная проекция тут наиболее приемлема,т.е. "вверх" на рисунке - это Z ("вглубь" экрана). Получим что-то типа того: Красный прямоугольник - это экран, т.е. всё, что снаружи, - уже невидимо. "Пол" у нас есть :) Теперь, если мы хотим высоту пола и по─ толка во всех секторах одинаковыми (а это даст прирост кадров в секунду,т.е. потолок не надо проецировать отдельно), то "пото─ лок" можно получить простым отражением "пола" вверх ногами. Если разные высоты потолка всё таки хо─ чется, а тратить время на проекцию потолка всё равно жалко, то можно пойти на компро─ мисс - печатать потолок не с серединным отражением, а со смещением. Это если смещение вниз, эффект другой высоты есть, хотя и небезупречный. Если хочется выше, то и смещение должно быть вверх. Но, как видно на рисунке, придётся ещё раз клипировать по верхней границе. Это не идёт на пользу в плане скорости. Теперь осталось соединить углы (те, что видны на экране)- и вид "в комнату" готов. Чтобы визуальный эффект объёма был ощу─ тимей - надо бы залить пол и потолок. На Speccy для этого достаточно заливки "через строчку" (опять же, для скорости). Итак мы получили залитый пол, потолок и голые стенки. Накладывать на них текстуру - долго, а у нас ставка на скорость. Для шутера вполне пойдёт,если все стенки будут белыми,- главное атмосфера. Теперь о связи между секторами. Для то─ го, чтоб из одного сектора видеть содержи─ мое других,надо пробежаться обработчиком и по соседним. Какой из них видим полностью или частично, выяснить нетрудно, а вот с отображением есть нюансы. Сперва надо построить самый дальний ви─ димый сектор,потом тот,что поближе - и так по мере приближения к камере. Но! Построе─ ние идёт после ПОЛНОЙ обработки всех сек─ торов, что ближе к камере,- и вот почему. Допустим, мы хотим расширить наш мини-мир на один сектор, например, так: Зелёным цветом показана "спайка" между секторами. Проецируем: Разворачиваем "потолок" Здесь синим цветом выделены ГРАНИЦЫ КЛИПИРОВАНИЯ для "дальнего" сектора. Если из него видно что-то ещё более далёкое,оно будет клипироватся уже по следующему ребру "спайки" (или границе экрана, если ребро за него вылазит). Здесь выигрыш в скорости в том, что эти границы - всегда строго вертикальны,а зна─ чит,математика получается не сильно затра─ тная. Потолки рисуются последовательно, и, соответственно, их стыки не будут даже ви─ дны (ведь заливать всё это можно побайтно, а то и по паре байт). Если оставлять одинаковую высоту пола/ потолка для всех секторов, то можно их не заливать и получить движок, который будет довольно шустрым, но примитивным. По слож─ ности он будет как классический квадратный рейкастовый двиг, но с возможностью любых углов, зато без текстур. Если делать возможность разных высот потолка, то можно делать не просто коридо─ ры-комнаты, но и межкомнатные двери (и они даже смогут раздвигаться, открывая взору, что там за ними), но скорость расчётов и отрисовки так упадёт, что шутер уже не по─ строишь,а красивую бродилку-лабиринт можно сделать и на движке 3D Construction Kit... Для всего этого (даже для самого прос─ того варианта,без заливок) нужна математи─ ка хорошая (8.8 как минимум) и быстрая.Где такую взять, мне неизвестно,а то,что я сам наизобретал, показывать крайне не рекомен─ дуется. Наверняка можно адаптировать Адвенчур─ ный #13 двиг из статьи (которыйDUKEmain), но сперва придётся разложить его по пол─ кам, что у меня, опять же, не вышло. Однако если всё-таки удастся сделать проволочную бегалку, то встаёт в полный рост вопрос,что там делать.Нужны ведь вра─ ги, нужно оружие, а выводить это всё тоже очень долго. Скрепя сердце, можно выводить оружие развёрнутыми (и,следовательно,боль─ шими по объёму памяти) процедурами, но с масштабированными врагами такое, наверное, не получится. Также довольно остро стоит вопрос о пе─ ремещениях внутри сектора и "упирания" в стенку. Тут могут помочь заранее просчи─ таные массивы всех стенок для всех секто─ ров, но даже в этом случае довольно много времени после КАЖДОГО шага игрока будет тратиться на проверку "не пытаемся ли мы лезть на стену", чтобы если это так,то пе─ ремещения не делать. В таких случаях поло─ жено "скользить" вдоль стены, а это тоже непростая задача. Правда,можно хранить ка─ ждый сектор не только как массив координат описывающих точек,но и ещё как набор неких "векторов", тогда достаточно будет склады─ вать их направление с направлением текуще─ го взгляда и делать шаг в результирующем направлении. Но это в теории, на практике неизвестно, получится ли. Есть мысль, что можно скрестить сектор─ ную организацию с рейкастингом. Например, не обсчитывать все сектора, а только те, которые попадаюся на глаза в текущей пози─ ции. Это можно сделать, подготовив сперва массив, который будет заполняться номерами секторов, которые зацепляет испускаемый из камеры веер. Конечно, он (веер) не будет слишком частым (далеко не на каждый пик─ сель). Возможно,это ускорит расчёты,а воз─ можно, и наоборот... * * * Ред.: Смотрите демоверсию в приложении. Чтобы быстрее заливать пол и потолок серым цветом,лучше использовать чересстро─ чную сеточку, например, 25-процентную. (Предполагается, что экран изначально очищен значением#ff,линии нарисованы но─ ликами.) Идём сверху каждого столбца экрана до середины, изначальноc=#ff: ld a,c and (hl);накапливаем нолики в столбце inc h and (hl);накапливаем нолики в столбце ld c,a ;c=маска, какие биты в этом байте надо ;затекстурить (единички), напр. %11111000 ;(hl)=линии, которые надо наложить (нолики ;на фоне единичек), напр. %11111001 and d;e;строка текстуры,напр.%10111011 ;a=%10111000 cpl ;a=%01000111 and c ;a=%01000000 xor (hl) cpl ld (hl),a;%10111001 inc h или (Предполагается, что экран изначально очищен значением #00, линии нарисованы единичками,c=#00.) ld a,c or (hl);накапливаем единички в столбце inc h or (hl);накапливаем единички в столбце ld c,a ;c=маска, какие биты в этом байте надо ;затекстурить (нолики), напр. %00000111 ;(hl)=линии, которые надо наложить (1 ;на фоне 0), напр. %00000110 or d;e;строка текстуры, напр.%01000100 ;a=%01000111 cpl ;a=%10111000 or c cpl ;a=%01000000 or (hl) ld (hl),a;%01000110 inc h Аналогично заливаем пол - идём снизу каждого столбца экрана до середины. Оба варианта занимают 50 тактов на 2 байта, но работают прямо в экране. Если работаем в буфере, а штриховки на─ кладываются целыми знакоместными столбца─ ми,то можно залить столбец через xor (hl):ld (hl),a:inc l (18 тактов на байт), а потом перебросить на экран с текстурой через pop bc ld a,c:and e:ld (hl),a:inc h ld a,b:and d:ld (hl),a:inc h (24 такта на байт). Итого 42. Это при сплошной текстуре. При чересстрочной убирается каждый вто─ рой ld (hl),a в заливке и каждый второй ld a,b:and d:ld (hl),a (с возможной заме─ нойinc h:inc hнаld h,N) в текстуриро─ вании, остаётся 20(19) тактов на байт. Чтобы сэкономить скорость,можно помнить для каждого знакоместного столбца экрана, какая у него сейчас высота (минимально по всем линиям, попавшим в этот стоблец,кроме вертикальных). И текстурить только на эту высоту.
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября