Skip to content

Part 2: texturing the walls

Dmitry V. Sokolov edited this page Feb 10, 2019 · 3 revisions

under construction

Этап 9: загрузка файла текстур

Настало время разбираться с текстурами. Мне лениво самостоятельно писать загрузчик изображений, поэтому я взял прекрасную библиотеку stb. Я подготовил файл с текстурами для стен, все текстуры квадратные и упакованы в изображение по горизонтали:

На этом этапе я просто гружу текстуры в память. Чтобы проверить работоспособность написанного кода, просто рисую как есть текстуру с индексом 5 в левом верхнем углу экрана:

Внесённые изменения можно посмотреть тут.

Open in Gitpod


Этап 10: рудиментарное использование текстур

Теперь я выкидываю случайно сгенерированные цвета и подкрашиваю мои стены, взяв левый верхний пиксель из соответствующей текстуры: Внесённые изменения можно посмотреть тут.

Open in Gitpod


Этап 11: текстурируем стены по-настоящему

А вот теперь настал долгожданный момент, когда мы наконец-то увидим кирпичные стены:

Основная идея очень простая: вот мы скользим вдоль текущего луча и останавливаемся в точке x,y. Давайте предположим, что мы остановились на "горизонтальной" стене, тогда y почти целочисленнен (не совсем, т.к. наш способ движения вдоль луча вносит небольшую ошибку). Давайте возьмём дробную часть от x и назовём её hitx. Дробная часть меньше единицы, следовательно, если мы умножим hitx на размер текстуры (у меня 64), то это нам даст столбец текстуры, который нужно нарисовать в этом месте. Осталось его растянуть до нужного размера и дело в шляпе:

В общем, идея крайне примитивная, но требует аккуратного исполнения, так как у нас есть ещё и "вертикальные" стены (те, у которых hitx будет близок к нулю [x целочисленный]). Для них столбец текстуры определяется hity, дробной частью от y. Внесённые изменения можно посмотреть тут.

Open in Gitpod


Этап 12: время рефакторить!

На этом этапе я ничего нового не стал делать, просто занялся генеральной уборкой. До сего момента у меня был один гигантский (185 строк!) файл, и в нём стало трудно работать. Поэтому я его разбил на тучу мелких, к сожалению, попутно почти удвоив размер кода (319 строк), не добавив никакой функциональности. Но зато стало гораздо удобнее пользоваться, например, чтобы сгенерировать анимацию, достаточно сделать вот такой цикл:
    for (size_t frame=0; frame<360; frame++) {
        std::stringstream ss;
        ss << std::setfill('0') << std::setw(5) << frame << ".ppm";
        player.a += 2*M_PI/360;

        render(fb, map, player, tex_walls);
        drop_ppm_image(ss.str(), fb.img, fb.w, fb.h);
    }

Ну а вот результат:

Внесённые изменения можно посмотреть тут.

Open in Gitpod

Продолжение следует... незамедлительно

На этой оптимистичной ноте я заканчиваю текущую половину моей простыни, вторая половина доступна тут. В ней мы добавим монстров и слинкуемся с SDL2, чтобы можно было погулять в нашем виртуальном мире.
Clone this wiki locally