(бухай): программируй
148 subscribers
465 photos
96 videos
3 files
65 links
Мысли, дегустация и код
Download Telegram
Теперь хочу рассказать, как я это сделал.
Я придумал штуку, которую назвал Triple Block Raycasting, и ее точно уже придумали до меня.
Стандартный рейкастинг работает так: на каждый столбец экрана выпускается луч, который в какой-то момент встречается со стенкой. Записывается длина этого луча. Чем дальше стена, тем длиннее луч и, соответственно, высота стены будет меньше.
На Commodore 64 было бы очень сложно это воспроизвести (много вычислений и тригонометрии).
Поэтому я поместил в память таблицу, в которой для каждого луча (а их всего 64 при ширине экрана в 128, т.к. в режиме multicolor пиксель двойной ширины) указываются:
— номера блоков, с которым может столкнуться луч;
— высота линии, в случае, если луч столкнется с блоком;
— адрес таблицы увеличения текстур, которая позволяет обойтись без дорогого умножения и деления;
— координаты столбца текстуры.

Так как блоки на экране могут находиться только в заложенных местах, то и проверять для одного луча надо всего по три блока.
❤‍🔥1
А в плане памяти все осталось как есть.
Раньше таблица увеличения текстур занимала 2 килобайта (от 32 до 128 пикселей высоты с шагом 2). Теперь всего килобайт (от 32 до 128 с шагом 4).
Таблица для проверок лучей занимает чуть больше 1 Кб.
То есть в итоге я почти ничего не потерял, но зато получил нормальную картинку.

Осталось написать функцию для наложения текстур, присвоения цветов (с которыми будет тот еще геморрой, чувствую), ну и заняться творчеством. Планируется, что на одном уровне будет до 16 возможных текстур, и они будут подгружаться с дискеты при смене уровня.

Но для этого надо разобраться, как подгружать что-либо с дискеты=)
👍2
А вот и текстурки подъехали.
Но это все точно надо как-то оптимизировать, но пока не знаю как=(
🔥2
Сегодня сделал пару новых штук.
Во-первых, немного оптимизировал процесс отрисовки. Например, указал, что пустые пиксели закрашивать не надо.
Во-вторых, сделал прозрачные текстуры (и оптимизация полетела к чертям). То есть, если сквозь текстуру можно смотреть, то рисуются блоки позади.
Но пока что еще нет функции, которая определяет текстуру блока и раскрашивает пиксели в нужный цвет
❤‍🔥1
Ну и нарисовал депрессивные текстуры для русского жилища. Ковер присутствует =)
На один уровень будет по 16 уникальных текстур
3
Сегодня особо похвастаться нечем.
Я немного оптимизировал процесс отрисовки.
Для этого пришлось пожертвовать 1000 байт памяти. Если раньше у меня предрасчитанные значения индекса текстур лежали в одном байте попарно (от 0 до 15), то сейчас я их распределил по одному байту для каждого значения. Из-за этого теперь не приходится делать лишние операции сдвига.

Во-вторых, переписал функцию отрисовки пикселя на экране.
Раньше я брал первый блок строки и прибавлял к нему смещение по Y. Но сейчас я считаю блоки построчно, и к ним прибавляю индекс по Х. Получается без лишних 16 битных сложений.

Но все равно медленно!
❤‍🔥1
За эти выходные просто дофига новостей!

Во-первых, удалось увеличить скорость отрисовки почти на 50%.
И, внезапно, в этом мне помог Кирилл Лейфер. Благодаря ему я и Commodore купил, когда увидел видео про это на его YouTube канале.

Сейчас Кирилл сам делает игру про кота для C64:
https://t.me/paw_noir

Он посмотрел на мой код, кое-где оптимизировал, а потом я сам уже убрал возможность отрисовки "комнаты за комнатой".
Это сильно снижало скорость, а еще могли бы возникнуть конфликты цветов в одном знакоместе при коллоризации.
❤‍🔥1
Во-вторых, я написал собственно функцию для колоризации.

В текстуре один пиксель может принимать значения: 01, 10, 11, 00.
11 - это цвет из Color RAM (1000 байт в одном месте памяти). Он у меня везде одинаковый - тёмно-серый.
00 - это цвет фона - черный.
А вот 10 и 01 могут быть любыми цветами, которые я помещу в третье место (еще 1000 байт в другом месте в памяти).
То есть текстура - это лишь набор ссылок на другие регистры.

Цветовую палитру для каждой текстуры пришлось хранить отдельно от самих текстур. Но таким образом цвета можно менять налету
❤‍🔥1
И, в-третьих, я добавил буфер экрана. Это лишние 2Кб памяти, в которое сохраняется изображение перед выводом на экран.

Цель у этого всего одна - избавиться от того, что процесс отрисовки виден на экране в реальном времени. Как мне кажется, это довольно сильно раздражает
❤‍🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Сделал вчера игровую карту и функции перемещения (ну почти) и поворота.
При каждом изменении вызывается функция отрисовки экрана, а между этим экран очищается.
И вроде как это смотрится не так уж раздражающе медленно)

А еще в конце можно увидеть, что если зайти за пределы карты, то можно отправиться путешествовать по памяти компа)
👍3
Но как это путешествие работает, надо описать:

У игрока есть позиция Y и позиция X, а у каждой строки карты размером 24*24 байта есть свой адрес. Адреса забиты в таблицу указателей на адреса строк.

То есть позиция игрока высчитывается как текущий адрес строки из таблицы со смещением Y + смещение по X.

Если выйти за пределы карты, например позиция игрока станет не 24, а 40, то адрес строки будет равен "адрес начала таблицы + 40", а что хранится в этом месте неизвестно. Это может быть указатель хоть на самую первую страницу памяти.

Зато, если уйти за пределы карты вправо, то игрок перескочит на следующую строку в противоположном конце карты, и наоборот🙈

Думаю, это можно как-нибудь использовать для секретов, главное ничего не сломать:)
🤡1
This media is not supported in your browser
VIEW IN TELEGRAM
Немного доработал рендеринг. Теперь не требуется очищать полностью экран, а только экранный буфер.
Благодаря этому пропало раздражающее мерцание между кадрами
😱1
Media is too big
VIEW IN TELEGRAM
Видео-отчет за последние несколько дней безудержного веселья.
Нет, серьезно, мне уже снятся эти байты.
Вчера мне приснилось, что для того, чтобы проснуться, надо поменять значение будильника в регистре памяти.
Я во сне написал программу на ассемблере и спокойно проснулся под будильник🤦‍♂
😁2
А они все ждут своего часа ....
Когда-нибудь я напишу что-нибудь на ассемблере для МК-90, починю арифмометры.

Но Commodore, он постоянно где-то в тени и наблюдает за мной. Требует новых игр

Видимо, надо вызывать ведьмака
1😱1
Думаю, как реализовать триггеры.
Пока придумал такую штуку. Каждый триггер будет иметь такие параметры:
Позиция X и Y на карте;
Номер ключа (будет проверяться наличие ключа у игрока);
Флаги Single use и Available.
Первый флаг будет означать, что триггер срабатывает один/бесконечное количество раз и переключает флаг Available в ноль в первом случае.
Второй флаг будет означать, что в данный момент триггер можно/нельзя активировать.

Допустим, я хочу сделать триггер для двери. Так как я отказался от отрисовки "комнаты за комнатой", дверь будет обычным блоком. К этом блоку надо привязать два триггера. Первый будет телепортировать игрока в одну сторону, второй - в другую. К тому же каждый триггер будет Single use (то есть флаг Available будет выставляться в 0) и должен активировать противоположный триггер (флаг Available выставляется в 1).

Получится так:
00000001 - тип триггера "дверь".
00000011 - флаги выставлены в 1.
Два байта - позиция на карте.
Один байт - номер ключа.
Два байта - позиция для телепортации игрока.
Один байт - номер триггера, который нужно будет активировать после телепортации.

Пока что я предполагаю, что на 1 уровне будет как минимум 64 триггера. Один триггер занимает 8 байт, то есть в сумме 512 байт.
😱1
Планируются такие триггеры:
— Телепортация (односторонняя);
— Дверь (телепортация + активация другого триггера);
— Смена видимости блока (выставляем флаг Textured на блоке в 0 или 1);
— Смена коллизии блока (флаг Solid в 1 или 0);
— Смена текстуры блока (меняется номер текстуры блока от 0 до 15);
— Смена флага Single use триггера (пока не придумал конкретные ситуации, где это можно использовать);
— Смена флага Available триггера (таким образом можно активировать будущие сюжетные триггеры, которые в начале уровне не будут доступны);
— Вывод текста на экран (будет определяться адрес текста в памяти)
— Триггер для смены уровня (тут будет номер следующего уровня, на основе которого уже будут считываться нужные файлы с дискеты. Осталось разобраться, как эти файлы считывать).
Как вариант, можно сделать триггер на смену параметров другого триггера, но конкретные примеры я пока тоже не придумал.
Чувствую. что большинство триггеров я буду придумать по ходу создания уровней для конкретных ситуаций.
🤡1
Немного о том, как я создаю текстуры для игры=)

Сперва я их рисую в Multipaint - программа, в которой можно рисовать для большого количества старых компьютеров, включая Commodore 64, VIC-20, ZX Spectrum и Amstrad.

Потом я своими руками переношу данные текстур попиксельно в Excel, где уже с помощью формул СЦЕП и ДВ.В.ШЕСТН создаю нужное представление последовательности байт для ассемблера.
Но я уже устал так делать😂 Пора бы что-нибудь на питоне написать для облегчения жизни
❤‍🔥1
Media is too big
VIEW IN TELEGRAM
Ну и наконец видео-обновление. Перенес все текстуры в игру. Может быть потом еще придумаю, как это дело улучшить:)
🔥2