Wolfenstein 3D в EXCEL?
Wolfenstein 3D в EXCEL?
2424 показа
5.6K5.6K открытий

Привет,

молодец, хорошая статья вышла, но есть пара возражений по логике кода.
1.Функция определения положения игрока действительно странная. зачем 2 раза лопатить массив карты, чтобы найти сперва X-координату, а затем Y? Это все определяется за один проход, и не важно квадратная ячейка или нет (просто если хочется неквадратный мир - держим отдельно 2 переменных: cellSizeX и cellSizeY). Вобщем, не оправдано ни с т.з.быстродействия, ни с т.з. копактности кода.
2.Процедура рей-трейсера, конечно, достаточно короткая по коду, но жутко нерациональная. Как делать более рационально:
a) создаем переменные дистанции до пересечений луча с горизонтальными линиями сетки карты и текущих координат X и Y места их пересечения. Также создаем переменные шага дистанции и приростов по X и Y между двумя соседними пересечениями. То же самое - для вертикальных пересечений. Всего - 12 переменных (на деле, их немного больше, но это уже совсем детали).
б) вычисляем первое пересечение с горизонтальной и вертикальной линиями сетки (берем остатки от деления на размер клетки положения игрока по оси Х и Y и дальше с помощью синуса и косинуса получаем недостающие координаты, а потом вычисляем инициальные дистанции до этих пересечений) и заполняем соответствующие переменные. Потом, используя размер ячейки, заполняем переменные межклеточных приростов по X и Y и шаги дистанций между 2 соседними клетками по горизонтали и по вертикали.
То есть, фактически, у нас есть 2 луча - к горизонтальным линиям и к вертикальным. И приращивать мы их будем в одном цикле, на конкурентной основе (в каждую итерацию, сравнивая дистанции, пройденные лучами, мы приращиваем тот из них, который "короче", пока один из них не "упрется" в стенку). Чем такой путь лучше (ведь мы трассируем не 1 луч, а сразу 2)? Выигрыш будет в количестве итераций цикла (у меня количество итераций на карте 24х24 будет максимум 23*2 = 46, а в вышеуказанном рейкастере итераций ожидается до 64*20/0,05 =25600(!)). Плюс, учитывая эмпирический характер пересечений в таком рейкастере, на экране, несмотря на "микроскопические" приросты, может появится "гребенка" при приближении к стенам (особенно, если там таки появятся текстуры). Еще один, небольшой выигрыш: в моем случае для приращения позиции лучей мы используем сложения, а не умножения, что "дешевле" по времени.
3.В рендере:
а) "сглаживатель отрисовки" - это костыль, который "лечит" вышеуказанную проблему "гребенки" (причем - за счет снижения и без того низкого разрешения). Он не нужен.
б) использовать свойство .Interior.Color для изменения цветов ячеек - это очень "дорого" и не на всех версиях Экселя отработает без багов. Лучше создать пользовательскую палитру (ту, что из 56 цветов) при помощи ActiveWorkbook.Colors() и потом использовать свойство .Interior.ColorIndex для присвоения цвета по его индексу в палитре.
в) Очень специфический для Экселя "хинт": закрашивать ячейки поштучно через .Cells(,) гораздо медленнее, чем закрасить сразу весь столбец одним цветом через .Range(Cells(,),Cells(,))
г) Чтобы отрисовка шла быстро и плавно, перед началом отрисовки нужно отключать системный рендер экрана (Application.ScreenUpdating = False), а по завершении включать снова (Application.ScreenUpdating = True).

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

Удачи!
Я на itch.iohttps://davevsziggy.itch.io/dave-vs-ziggy

Ответить

Ааааа, я чувствовал, что этот день настанет! Я из-за Dave vs. Ziggy в т.ч. начал изучать VBA)

Спасибо за советы, вечером изучу вопрос)
P.S. По поводу Application.ScreenUpdating. Я его использовал, только решил не заострять на этом внимание в статье)

Ответить