Пользователь под ником C Bel сделал собственный 3D-движок без использования макросов и VBA. C Bel был вдохновлен коридорами игры Doom, что и послужило на создание такого проекта, а ни как не отсутствием личной жизни…
Итак, что может данный 3D-движок:
- Создание бесконечных процедурно-генерируемых карт в виде лабиринта;
- В режиме реального времени возможно рассчитывание трассировка световых лучей;
- Просчет затемнения;
- Вычисление самых простых источники света.
Ниже вы можете скачать как обычную, так и HD-версию движка.
Эта статья посвящена тому, как я смог написать 3D-движок игры Doom только на формулах Excel. Я реализовал следующий функционал:
- бесконечная процедурно генерируемая карта лабиринта
- рендеринг трассировкой лучей в реальном времени
- вычисление окклюзии
- рендеринг простейшего освещения
- шейдер освещения и вычислений
- движок естественного движения
- в 3D-движке не используются макросы
* чтобы управлять игрой нажатием клавиш, нужны макросы, управляющие движением с помощью одной простой инструкции копирования.
Можете скачать файл и протестировать его самостоятельно!
Файлы
- Файл без vba: http://public.cbel.free.fr/?file=Doom.xlsx
- Файл с vba для перехвата нажатий клавиш: http://public.cbel.free.fr/?file=Doom.xls-v1.1.xlsm
- Файл с vba и высоким разрешением: http://public.cbel.free.fr/?file=Doom-HD.xls-v1.1.xlsm
- Файл с vba и кнопками вместо горячих клавиш: http://public.cbel.free.fr/downloads/?file=Doom.xls-Buttons-v1.1.xlsm
Контекст
Учитель информатики однажды сказал нам: «любые вычисления можно выполнить в любом языке программирования, даже через формулы электронной таблицы».
Поначалу, какой бы мудрой ни казалась эта фраза, упоминание в этом списке Excel выглядело глупо…
Затем, после изучения машины Тьюринга, фраза стала для нас полностью верной, хотя и не вполне реализуемой.
Получив многолетний опыт работы с Excel, мы уже поняли, что единственное ограничение формулы Excel — недостаток способов ввода-вывода.
Но множество задач, решаемых исключительно формулами, по-прежнему выглядит впечатляюще.
Как бы то ни было, эта работа — не просто какое-то хвастовство… У меня были для неё серьёзные причины.
Электронные таблицы — это мощный инструмент, которому должен научиться каждый, ведь его можно использовать почти в любых деловых задачах.
Однако когда большинство людей доходят до решения более сложных задач, они стремятся использовать язык VBA, даже не понимая толком, зачем.
А начав изучать его, они пытаются использовать его для решения любых видов задач, даже для простого поиска или визуализации.
Сегодня я преподаю Excel, поэтому постараюсь объяснить людям, почему написание макроса на VBA для решения любой задачи без хорошего знания программирования — это не только пустая трата времени, но и серьёзный риск снижения качества электронной таблицы.
При использовании в бизнесе формулы обладают следующими преимуществами перед макросами:
- Их быстрее писать для любого человека, если он не профессиональный программист-аналитик
- Их проще поддерживать любому человеку, а не только профессиональному программисту. (Чаще всего макросы становятся бесполезны после ухода их разработчика.)
- Гарантированное качество благодаря постоянной проверке значений. (Принудительное применение техники «разработка через тестирование»)
- Они более эффективны в долговременной перспективе благодаря процессу создания формул в стиле «думай, прежде чем писать».
- И они совершенно точно гораздо лучше интегрированы в сам инструмент создания электронных таблиц и следуют изначальному паттерну разработки электронных таблиц, в то время как макросы часто оказываются специфическими конструкциями, требующими в дальнейшем активной поддержки.
Примечание: эти пункты в основном относятся к процедурам, используемым как макросы; дополнительная функция, написанная на VBA, может увеличить эффективность, не снижая качества.
Вот так я пришёл к написанию своей игры: она стала наглядной демонстрацией того, что макросы обычно не нужны даже для решения самых сложных задач.
Если конкретнее, то я нашёл всего два случая, когда потребовался VBA:
- Добавление специфического ввода или вывода (как я сделал здесь для получения событий клавиш), потому что формула всегда ограничена изменениями в самой ячейке
- Некоторые сложные задачи (например, оптимизация), в которых вычисления занимают слишком много времени и/или пространства. Но такие задачи довольно редки в реальной жизни.
В оставшейся части этой статьи я расскажу как работают электронные таблицы в различных аспектах игры.
Карта
Моя электронная таблица должна была стать игрой в стиле Doom в лабиринте.
Можно было создать для неё постоянную, построенную вручную карту, возможно, зацикленную по краям, но она бы потребовала дополнительного места, поисков и изначальной разработки дизайна.
В то же время, гораздо более интересной целью мне казалась идея процедурно генерируемой бесконечной карты.
Для создания случайно генерируемой карты нам нужно быть последовательными, поэтому функцию rand() использовать нельзя, ведь мы не можем контролировать начальное состояние (seed) генератора случайных чисел.
Начальные состояния генератора случайных чисел должны быть позициями (x;y) на карте, чтобы мы могли получать разные значения для каждой позиции, и мы не можем получить результат предыдущего случайного числа как начальное состояние для следующего, или нам придётся хранить всю карту с самого начала.
Обычные хэш-функции, несмотря на обеспечение высокого качества случайных чисел, оказались слишком затратными, поэтому мне нужно было найти другое решение.
Эксперименты с фрактальным генератором тоже оказались довольно затратными и давали интересные результаты только для небольшой части карты.
Тогда я обнаружил метод средних квадратов (middle-square method), который на самом деле не очень «случаен», потому что в нём используются последовательные начальные состояния. Но он подсказал мне идею того, что можно брать десятичную часть любого другого вычисления.
Я выяснил, что если брать десятичные части sin(x)+cos(y), то наконец-то получаются красивые числа без какого-либо прослеживаемого паттерна, а время вычислений при этом на удивление малО.
Для получения десятичных частей математические функции mod() и floor() гораздо более эффективны по сравнению с текстовой функцией подстроки mid().
Я стремился сделать карту похожей на крысиный лабиринт, поэтому создавал блоки не сплошными, чтобы они походили не на пещеры (в стиле Minecraft), а на лабиринт.
То есть нам нужны тонкие стены с двумя возможными стенами для каждого квадрата. Тогда мы сможем брать два блока чисел вместе с тем же случайным значением.
Плотностью размещения стен управляют два параметра.
С учётом этих правил мы можем или отображать лабиринт, или тестировать любую стену с заданной позицией с помощью трассировки лучей.
Стоит заметить, что карта «плоская», без подъёмов и спусков. Можно было добавить рельеф с помощью генератора рельефа (подошёл бы алгоритм Diamond-Square, потому что его можно написать без рекурсивной функции), но весь последующий процесс сильно облегчило бы вырезание отверстий в полу и потолке с дополнительным значением уровня.
Трассировщик лучей
Трассировщик лучей должен определять для каждого пикселя экрана, какой первой поверхности касается луч, и получать от неё информацию (расстояние, угол падения света, цвет и т.д.).
Кроме того, трассировщику лучей требуется дополнительный луч, распространяющийся из этой точки (отражения, прозрачность), что напрямую увеличивает вычислительные затраты.
Окклюзия
Первым сложным моментом будет нахождение первого объекта на пути каждого луча.
Поскольку лабиринт на самом деле плоский с горизонтальными стенами, то ближайшая найденная стена будет одинаковой для всех пикселей одного столбца.
То есть процесс можно упростить до горизонтального «радара» в одном измерении.
Тогда у нас нет иного выбора, кроме как проверять луч на первой вероятной стене, потом на второй вероятной, и так далее, пока мы не найдём нужную.
Определение того, какую стену нужно проверять — это всего лишь тригонометрическая задача.
И поскольку у нас всего два типа стен, мы можем тестировать оба типа, а потом сохранять только ближайшую.
Одно из ограничений Excel заключается в отсутствии условного цикла и для экономии времени можно только пропускать тело цикла. Поэтому нам нужно ограничить максимальное расстояние проверки, считая, что если на этом расстоянии стена не найдена, то её нет.
Пол и потолок
Чтобы определить потолок и пол, нам достаточно определить, где заканчивается стена.
Отдельный лист изменяет расстояние до пола или потолка в зависимости от вертикального угла.
Затем для каждого пикселя мы определяем, дальше ли стена, чем потолок или пол, и соответствующим образом задаём цвет пикселя.
Эффективное сравнение реализовано использованием только проекции расстояния до стены и до пола/потолка по оси камеры. Конечное расстояние затем получается с помощью предварительно вычисленного коэффициента расстояния в шейдере расстояний. Постоянные предварительно вычисленные значения нужны для экономии ресурсов.
Освещение
Конечное освещение берётся из шейдера освещения, представляющего собой свет факела, в направлении камеры (и оружия).
Когда поверхность точно горизонтальна к лучу света, также добавляется отражение.
Стена может быть только горизонтальной (если добавить наклон, то он просто смещает окно экрана вверх и вниз, не поворачивая камеру)
Для каждого угла радара мы получаем угол между лучом и ближайшей найденной стеной.
Коэффициент отражения — это просто функция угла.
В конце концов освещение становится результатом функции коэффициента расстояния, потолка/пола или разрешения стен, коэффициента отражения и коэффициента шейдера освещения.
Экран дисплея
Эффективный дисплей реализуется с помощью условного форматирования — градиент цвета зависит от значения ячейки.
Сокрытие значения выполняется форматированием ячейки.
Коллизии со стенами
Игрок не должен проходить сквозь стены, иначе это разрушит весь смысл лабиринта.
Кроме того, игрок не должен прилипать к стене при контакте с ней. Он должен двигаться, скользя вдоль стены, пока не попадёт в угол.
Также необходимо соблюдать минимальное расстояние между стеной и игроком, чтобы избежать графических проблем и придать стенам толщину.
Оказалось, что довольно сложно обработать все возможные варианты стены и позиций игрока относительно этой стены.
Изучено 25 вариантов и к ним привязано три возможных исхода (для каждой оси смещения), чтобы получать результаты за как можно меньшее количество проверок.
Несмотря на то, что это казалось самой короткой частью игры, таблица смещений стала самой сложной в реализации. (В 10 раз больше, чем карта, в два раза больше кода распознавания стен.)
Враги
Графический рендеринг
Сложность с врагами заключалась в том, чтобы получить форму, которую легко можно располагать перед стеной, легко рендерить на любом расстоянии, и которая будет интереснее, чем простой куб.
Целый отдельный лист посвящён вычислению формы сфер с учётом горизонтального радиуса и вертикальной высоты овоида. Для анимирования существа используется соотношение высоты/ширины.
В рендеринге стен и потолка используется градиент только по одному цвету, однако Excel позволяет использовать два последовательных (не сливающихся) градиента. Поэтому врагов можно отображать другим цветом. Для этого градиента можно использовать диапазон значений ниже 0, при том, что значение 0 — это чёрный цвет.
Меняющуюся прозрачность реализовать оказалось не сложнее, чем плавный рендеринг поверхности сферы. Луч получает толщину сферы, делая пиксель более цветным.
На границе сферы низкая толщина сохраняет только значение цвета по умолчанию стены за ней с отрицательным коэффициентом для превращения его в цвет монстра. Фильтр цвета освещения обеспечивает прозрачность на границе сферы.
Здесь вычисления тоже производятся в горизонтальной плоскости, а максимальный объём вычислений подготавливается перед завершением 3D-вычислений для каждого пикселя.
Поведение врагов
Чтобы избежать реализации сложного и некачественного процедурного поведения, враги не будут реагировать на действия игрока. Их позиция определяется только временем, они движутся по сложной траектории, чтобы паттерн был не таким заметным.
Чтобы позиция, скорость и ускорение были непрерывными (для плавного движения), я сделал траекторию своего рода конечным фракталом большого круга с добавленными к нему небольшими круговыми вариациями. Коэффициент соотношения между кругами (и даже соотношение x/y) случаен и ненатурален, поэтому траектория никогда не самозацикливается. Чтобы получить хороший случайный генератор детерминированных траекторий, я создал отдельный лист, отображающий траекторию.
Так как траектории не могут учитывать стены, я был вынужден оставить монстрам возможность проходить сквозь них.
В каждый момент времени вычисляется несколько траекторий. Весь лабиринт населён одними и теми же десятью врагами, расположенными в сетке на значительном расстоянии, чтобы игрок не мог увидеть двух одинаковых монстров одновременно.
Можно уменьшать/увеличивать сетку повторов, чтобы повышать/снижать плотность расположения врагов. При этом следует внимательно следить за конечным смещением монстра, чтобы оно не было чрезмерным, и за скоростью, изменяющейся при масштабировании.
Создав ограниченное количество управляемых врагов, можно скопировать их по всему лабиринту.
Атаки врагов
Анимация врагов сделана с помощью соотношений их радиуса/высоты. Так как атака врага должна быть чётко заметна, но в то же время достаточно медленной, чтобы игрок смог отреагировать, враги просто увеличиваются в радиусе, когда замечают игрока. Рост соответствует экспоненциальной функции, симулирующей взрыв.
Область видимости каждого монстра вычисляется на вкладке радара с учётом расположения стен.
Игрок получает урон, когда он оказывается внутри радиуса врага. Если игрок специально забирается внутрь врага, происходит то же самое.
Это создаёт эффект наносимого игроку урона — простой эффект негативного цвета во весь экран.
Добавлен также ещё один эффект — отмена рендеринга всех остальных врагов при нанесении урона игроку.
Жизнь игрока указана как один из элементов его статуса, который обрабатывается поэтапно, как и его положение.
Атаки игрока
Каждый враг получает значение статуса, определяющее его оставшуюся жизнь и фазу атаки. При некоторых значения враги просто не отображаются, при некоторых других враги медленно регенерируют, а последнее заставляет врага взорваться.
Эта упрощённая модель позволяет игроку предотвратить атаку врага, снизив его жизнь до нуля.
Чтобы увеличить сложность, добавлена сложность прицеливания в маленьких врагов, которые остаются на дальнем расстоянии, а боеприпас через какое-то время требует перезарядки.
При убийстве враг просто переходит в состояние бездействия и медленной регенерации. Так как по всей карте повторяется несколько врагов, ни одного из них нельзя уничтожать полностью.
Смерть и перезапуск
Когда жизнь игрока снижается до нуля, бОльшая часть его действий приостанавливается и появляется экран конца игры.
Этот экран рендерится с помощью ещё одного шейдера освещения. К цвету применён эффект негатива, чтобы подчеркнуть нанесение урона.
Постепенное отображение сообщения «game over» реализовано с помощью небольшого коэффициента, увеличивающегося как степенная функция. Это позволяет будущим пикселям оставаться скрытыми до их появления, когда степень становится достаточно большой.
Сдвигание вниз — это простое смещение шейдера освещения, в который добавлены другие сообщения, например, рекорды (high score) и перезапуск игры.
Очки должны отрисовывается с помощью пикселей шрифтом очень низкого разрешения.
При перезапуске генерируется новый начальный параметр, а сам игрок отправляется в другую точку, чтобы не встретиться с теми же врагами.
источник
original
Abstract
This article is on how I could write a 3D engine using only excel formula, including following functionalities :
— infinite procedural generated maze map
— real time ray tracer rendering
— occlusion calculation
— basic illumination rendering
— illumination and compute shader
— natural displacement engine
— No macro at all used by the 3D engine,
* to enjoy the game using key press, some macro trigger the displacements, using just one simple copy instruction.
In-game screen capture
You can freely download the file and test it by yourself !
Files
- File without vba : http://public.cbel.free.fr/?file=Doom.xlsx
- File with vba for key press catch : http://public.cbel.free.fr/?file=Doom.xls-v1.1.xlsm
- File with vba, and high resolution : http://public.cbel.free.fr/?file=Doom-HD.xls-v1.1.xlsm
- File with vba, and buttons instead of key shortcuts :
http://public.cbel.free.fr/?file=Doom.xls-Buttons-v1.1.xlsm
Demonstration
Context
A computer science teacher once told us «a given computation can be achieved with any programming language, even spreadsheet formula».
At first, as wise at it could have been, including Excel in the comparison sounded definitively stupid …
Thereafter, while studying Turing machine, it then sounded correct, yet not very fulfilling.
Several years of experience with Excel, we will mostly remind Excel formula only are definitively limited with the lack of input/outputs.
But, the set of problems that can be simply solved with formula only remain impressive.
Anyway, this work is not just some kind of performance … There is was a good reason for me to do it.
Spreadsheet are a powerful tool that everyone has to learn to use for almost every business jobs.
Yet, when most people come to solve most complexes problems, they want to use VBA language, without even knowing why.
And once they started learning it, they try to use it for any kind of problem, even simple search or rendering.
Today, as an excel teacher, I’m trying to explain to these people why writing VBA macro for any problem while not being educated on computer programming is not only a real waste of time, but also a serious risk for their spreadsheet quality.
In a business environment, using formula rather than macro is :
- Faster to write for anyone but professional analyst programmer
- Easier to maintain for anyone but professional analyst programmer. (while macro are mostly unusable once the initial developer is gone)
- A guaranteed quality, due to permanent value checking. (a forced Test Driven Development method)
- More efficient in the long run, due to the «think before you write» process with formula design
- And definitively, much better integrated in the overall spreadsheet tool, following the initial design pattern of the spreadsheet, while macro often appear like specific developments requiring extensive maintenance afterwards.
Nota : these concerns mostly apply to procedure used as macro, while additional function written in VBA can increase the efficiency without lowering the quality.
This is how I came to write this game : an applied demonstration, that macro was not necessary at first, even for some of the most complex problems.
To be more precise, I found only 2 cases when VBA is required :
- Adding specifics input or output (as I did here to get key events), while formula is always limited to change on the cell itself
- Some complex problems (like optimization, try-and-check problems), those in which the computation time is too long, and/or taking too much space. But theses problems are quite rare in real business life.
This said, now, I’ll only focus on the rest of this article on how the spreadsheet actually works, for its different aspects.
The Map
The spreadsheet is meant to be a doom-like game, in a sort of maze environment.
It could have been a fixed, manually-constructed map, possibly looping on borders, but it would require storage, lookup, and an initial design.
In the meantime, using a procedural generated infinite map sounded much more worth of the effort.
To get a random generated map, we need it to be self-consistent over time, so rand() function could not be used, as we do not control the random seed.
The seeds for the random generator have to be the position (x;y) on the map, to get a different value for each position, and we cannot take the result of the previous random as seed for the next, or we would have to store all the map from the beginning.
While providing high quality random, usual hash functions are too expensive, so I needed to find an other one.
Trying to use fractal generator appeared to be also quite costly, and providing interesting result only for a small part of the map.
Then I found the middle-square method, which isn’t very «random» when consecutive seed are used, but gave me the idea of taking decimal of any other calculation.
I found out that taking decimals of sin(x)+cos(y) finally provided nice decimals, without any visible pattern, and a computation time surprisingly short.
To get decimals, mathematical function mod() and floor() are much more efficient compared to text function substring mid()
Trying to get the map looking like a rat maze, I didnt made block of solid block, otherwise it would have looked like a cavern (minecraft style) rather than a maze.
So we needed thin walls, with 2 possible walls for each square. We can then take 2 blocks of digits among the same random value.
2 parameters controlling the density of walls.
Given theses rules, we can either display the maze, or test any wall given it’s position for raytracing.
Note that the map is «flat», without any top/down. It would be possible to add relief using relief generator (diamond-square algorithm could apply, as it is possible to write it with a non-recursive function), but the solution of cutting holes in both ceiling and floor, with an additional level value would greatly ease the whole following process.
Ok, we’re definitively in hell
Raycaster
The raycaster solution imply to determine for each pixel which face the ray would touch first, and retrieve some information from it, (distance, angle with light, color …).
Raytracer also require additional ray to spread from this point (reflections, transparencies), with a direct massive increase on computation cost.
Occlusion
The first problematic will be to find the first object in the course of each ray.
Since the maze is actually flat, with horizontal walls, the nearest wall found will be the same for all pixels of a given column.
The process can then be simplified as an horizontal radar, on 1 dimension.
Then, there is no choice but testing for a wall on the first possible wall, then the second possible, until we find one.
It’s only a trigonometrical problem to determine which wall are to be tested.
And as we have 2 kind of walls, we have to test both of kinds, and then keep only the nearer.
One of the limit in excel is that condition loop does not exist, and the loop body can only be skipped to save time. So we should cut the maximum checking distance, assuming there is no wall at all if not found until then.
Floor and Ceiling
To represent floor and ceiling, we just have to find where wall does stop.
A dedicated sheet mesure the distance of the floor or ceiling depending of the vertical angle.
Then, for each pixel, we decide if the wall is further or not than the ceiling of the floor, and decide the pixel color accordingly.
The comparison is made efficiently by using only the projection of the distance of both wall and ceiling/floor on the camera axis. The final distance is then obtained using the pre-calculated distance factor in the distance shader. The fixed pre-calculated is mean to save resources.
Illumination
The final light is obtained from a light shader representing a torch light, in the direction of the camera (and weapon sight).
Some reflection is also added, when a surface is exactly horizontal to the light ray.
Only wall can be horizontal (if a pitch is added, it would only displace the screen pane up and down, not turning the camera)
For each angle of the radar, we get the angle between the ray and the nearest found wall.
Then, the reflection factor is a basic function of this angle.
In the end, the light is the product of a factor function of the distance, the ceiling/floor or wall resolution, the reflection factor, and the light shader factor.
Display
The effective display is made from conditional formatting — gradient of color based on the value of the cell.
Hiding the value is achieved by cell formatting.
Wall collision
The player is not supposed to move through wall, or it would defeat the idea of a maze.
Wall would not either stuck the player as he reach them. The movement should slip unless he reach a corner.
In addition, a minimum distance should be kept from the player to avoid graphical issues, and make wall have some width.
It appeared to be particularly tricky to manage all the possible cases of wall, and positions of the player compared to this wall.
The 2^5 possibilities were studied, and the 3 potentials outcome (for each displacement axis) where mapped to get the result within fewer possible tests.
While appearing one of the smaller, the displacement tab was one of the most complex to realize. (10 times more than the map, twice as much as the wall detection)
Enemies
The bad guy
Graphical rendering
The challenge for enemies was to obtain a shape that could be easily added before wall, easily rendered at any distance, and who would be more interesting than a simple cube.
A complete tab is dedicated to calculation of the shape of spheres, considering the horizontal radius, and vertical height of the ovoid. The height/width ratio is used to animate the creature.
The wall and ceiling rendering only used the gradient on 1 color, while excel allow 2 successive (not merged) gradient. Then, the enemies can be displayed in an other color. The value range bellow 0 can be used for this gradient, the value 0 being black.
The progressive transparency appeared to be not harder than the smooth rendering of a sphere surface. The ray is getting the thickness of the sphere, the thicker making the pixel more colored.
On the border of the sphere, the low thickness is only keeping the default value of the wall behind, with a negative factor to turn it on the color of monster. The light color filter providing a transparency on the border of the sphere.
Once again, calculation are made on the horizontal plane, and the maximum calculations are prepared before finalizing the 3d calculation for each pixel.
Enemies behavior
In order to avoid a complex and unsatisfying procedural behavior, enemies does not react to the player action. Their position is determined only by the time, on a complex trajectory designed to provide no explicit pattern.
To keep the position, speed, and all acceleration continuous (so the movement is fluid), the trajectory is a sort of finite fractal of a big circle, and small circular variations added on it. Ratio factor between circle (and even x/y ratio) are random an non-natural, so the trajectory never loop on itself. A separate sheet was made to display the trajectory to achieve a good random generator of deterministic trajectories.
Since the trajectories cannot take account of walls, the ability of monster to go through walls is forced.
Several trajectories are then computed at each instant. The entire maze is populated by the same 10 enemies repeated on a grid with a sufficient distance so the player cannot see 2 instances of the same enemy.
The repetition grid can be zoom in/zoom out to decrease/increase the enemy density. This should be made while taking great care of excessive resulting displacement of the monster, and effective speed due to scale.
Then, we have a limited number of enemies to manage, these being copied everywhere in the maze.
Enemies attacks
The animation of the enemies is made using the radius/height ratio. Since the attack of the enemy should be clearly visible, and yet, slow enough for the player to be able to react, enemies simply increase in radius wether they have the player in sight. The grow follow an exponential function to simulate an explosion.
Light of sight is calculated for each enemy in the radar tab, considering walls.
Then, the player simply get damage if it turn to be inside the radius of an enemy. It works the same is the player goes on purpose inside the enemy.
This make the damage effect on the player a simple effect of negative color on the entire screen.
An other effect is to cancel the rendering of any other enemy when the player get damaged.
The life of the player is one of the element of its status, which managed though steps like its position.
Player attacks
Each enemy get a status value, defining either its remaining life and attacking phase. For some values, enemies are simply not displayed, for some other, the enemy slowly regenerate, and the last one make the enemy explode.
This simplified model allow the player to prevent attack by decreasing the life of the enemy.
To increase the challenge, the player will have difficulties to aim a small enemy by staying at long range, and the ammunition will require reload action after a while.
On kill, the enemy simply turn into a slow regeneration state of inactivity. Since there are few enemies repeated everywhere, there cannot be a definitive elimination of one of them.
Death and rebi.. restart
Once the life of the player goes bellow 0, most of its actions are frozen, and the game-over screen appear.
This screen is rendered using an other light shader, and a negative effect is made on color to keep with the idea of damage.
The progressive display of the «game over» message is achieved with small factor, which are elevated with an exponential function. This allow future pixels to stay hidden before appearing once the exponent is big enough.
Then, the slide down is a simple displacement of the light shader, which include some other message, like high score and restart.
The score have to be written using pixels, with a very low resolution font.
The restart generate new starting parameter, and send the player elsewhere at an other instant to avoid the player to meet the same enemies.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Public Const Width = 78 | |
Public Const Height = 26 | |
Public Colors(36) | |
Sub spread_fire(x, y) | |
rand = Int(3 * Rnd) | |
randcool = Int(6 * Rnd) | |
xshift = x — rand + 1 | |
If xshift <= 0 Then xshift = x | |
If xshift > Width Then xshift = x | |
newValue = Cells(y + 1, xshift).Value — (randcool) | |
If newValue < 0 Then newValue = 0 | |
Cells(y, x).Value = newValue | |
Cells(y, x).Interior.Color = Colors(newValue) | |
End Sub | |
Sub do_fire() | |
For y = 1 To Height — 1 | |
For x = 1 To Width | |
Call spread_fire(x, y) | |
Next x | |
Next y | |
End Sub | |
Sub read_colors() | |
For x = 1 To 35 | |
Colors(x — 1) = Cells(28, x).DisplayFormat.Interior.Color | |
Next x | |
Colors(35) = RGB(255, 255, 255) | |
End Sub | |
Sub init_fire() | |
For y = 1 To Height — 1 | |
For x = 1 To Width | |
Cells(y, x).Interior.Color = RGB(0, 0, 0) | |
Cells(y, x).Value = 0 | |
Next x | |
Next y | |
For x = 1 To Width | |
Cells(26, x).Interior.Color = RGB(255, 255, 255) | |
Cells(26, x).Value = 35 | |
Next x | |
End Sub | |
Sub end_fire() | |
For x = 1 To Width | |
Cells(26, x).Interior.Color = RGB(0, 0, 0) | |
Cells(26, x).Value = 0 | |
Next x | |
End Sub | |
Sub doom_fire() | |
Randomize | |
Call read_colors | |
Call init_fire | |
For x = 1 To 100 | |
Call do_fire | |
Next x | |
Call end_fire | |
For x = 1 To 100 | |
Call do_fire | |
Next x | |
End Sub |
Программисту было скучно на работе и он написал игру подобную Doom на собственном трехмерном движке. Как сообщает автор, движок основан на стандартных макросах Excel. Игра может работать даже без использования встроенной в Office среды программирования VBA.
В аннотации автор рассказал, что используя только формулы в Excel, имитация Doom поддерживает следующий функциональные возможности:
— бесконечная генерируемая карта лабиринта
— рендеринг трассировки лучей в реальном времени
— обработка затемнений
— базовый рендеринг
— движок реалистичного перемещения
Подпишитесь на наш канал в Телеграме, чтобы читать только интересные новости высоких технологий
Разумеется, примитивная графика и геймплей это только пародия на бродилку. Попробовать поиграть можно по ссылке.
На самый важный вопрос «Зачем?» автор отвечает:
Электронные таблицы — это мощный инструмент, который каждый должен научиться использовать практически для любых бизнес-задач.
Тем не менее, когда большинство людей решают большинство сложных задач, они хотят использовать язык VBA, даже не зная, почему.
И как только они начали изучать это, они пытаются использовать это для любой проблемы, даже простого поиска или рендеринга.
Можно ли играть в игру в Excel?
Игры с Excel существуют уже давно, но, что более важно, все знают, что Excel — отличный инструмент для анализа данных. В игры Excel можно играть с использованием флэш-памяти или макросов. Из-за этого вам иногда может понадобиться активировать макросы, чтобы повеселиться с Excel.
Как я могу играть во флеш-игры в Excel?
Инструкции о том, как вставить флеш-игру в электронную таблицу Excel. Вы можете играть во флеш-игру бесплатно онлайн или использовать ту, которая у вас уже есть… Excel должен быть открыт, а затем должна быть выбрана кнопка выбора в верхнем левом углу. Чтобы отобразить вкладку разработчика, нажмите кнопку на ленте. Нажмите кнопку «Вставить», пока вы находитесь на вкладке «Разработчики». Создайте в электронной таблице раздел, идентичный по размеру окну, в котором вы сейчас работаете.
Можно ли анимировать в Excel?
Excel также предоставляет вам несколько встроенных анимаций, которые вы можете использовать в своих презентациях. Чтобы получить к ним доступ, выберите вкладку «Вставка», а затем щелкните раскрывающееся меню с надписью «Анимация». В этом разделе вы найдете широкий выбор анимаций, которые вы можете использовать для анимации элементов в своей книге, включая текстовые поля, фигуры и диаграммы, среди прочего.
В Excel скрыта игра?
В Microsoft Excel была спрятана мини-игра в стиле Doom, известная как «Зал замученных душ». Игра состояла из серии комнат, в которых были изображены имена и лица создателей программы.
играть в дум в экселе
Что самое сумасшедшее, что вы можете сделать с Excel?
Ниже приведены некоторые из наиболее инновационных способов использования Excel для создания интересных и занимательных проектов. Удивительное искусство AutoShape… Решатель и генератор судоку… Удивительное искусство AutoShape Включены клон тетриса, планетарная модель, традиционная головоломка со слайдами, рабочий симулятор полета и традиционная головоломка со слайдами.
У Excel все еще есть пасхальные яйца?
Пасхальные яйца Excel В рамках инициативы компании «Надежные вычисления» Microsoft официально прекратила практику включения пасхальных яиц в свои продукты в 2002 году.
Как я могу играть в тетрис в Excel?
Тетрис в Microsoft Excel Шаг 1: Включите макросы. Сначала откройте файл Excel, а затем выполните следующие действия, чтобы включить макросы: … Следующий шаг — элементы управления. Клавиатуры служат основой для элементов управления, и они уже настроены… Шаг 3: Ведение счета Количество завершенных строк определяет ваш счет. Шаг 4: Готово! Всплывающее сообщение будет появляться всякий раз, когда игра окончена.
Какие забавные вещи вы можете делать с Excel?
Вы можете попробовать одну из этих 15 творческих идей проекта Excel: Проект для записи и анализа посещаемости… Мониторинг ежедневных расходов… Список дел. … Потрясающее произведение искусства, которое было создано… Разработка игры в Excel. … Создание головоломок судоку. … Создание веб-игр. … Создание 3D маятника.
играть в дум в экселе
Какие забавные вещи вы можете делать с Excel?
Вы можете попробовать одну из этих 15 творческих идей проекта Excel: Проект для записи и анализа посещаемости… Мониторинг ежедневных расходов… Список дел. … Потрясающее произведение искусства, которое было создано… Разработка игры в Excel. … Создание головоломок судоку. … Создание веб-игр. … Создание 3D маятника.
Какие забавные вещи вы можете делать с Excel?
Вы можете попробовать одну из этих 15 творческих идей проекта Excel: Проект для записи и анализа посещаемости… Мониторинг ежедневных расходов… Список дел. … Потрясающее произведение искусства, которое было создано… Разработка игры в Excel. … Создание головоломок судоку. … Создание веб-игр. … Создание 3D маятника.
- Ваши Достижения 🔥
- История посещений
- Ваши заметки 🗒️
- Главная
- Каталог Статей
- Игровые статьи
DOOM в MS Excel – ЗАЧЕМ и КАК?
Культовый шутер от id Software запускали и на карманных приставках, и на калькуляторах, и на стиральных машинках, но сделать его в Microsoft Excel – это мощно, да. Впрочем, название очевидно кликбейтное. В творении пользователя C Bel от DOOM по сути лишь название файла и базовый концепт. Но от этого достижение товарища не становится менее значимым. И сейчас я отвечу на два хтонических, как лобковый волос мамонта, вопроса – КАК и ЗАЧЕМ он это сделал.
DOOM в MS Excel
С ЗАЧЕМ разобраться довольно просто. C Bel является, помимо разработчика игр, ещё и учителем Excel, и данным проектом он хотел показать, что даже в самых сложных задачах можно обойтись исключительно стандартными математическими формулами. Ведь в качестве альтернативы формулам обычно используется язык VBA, он же – Visual Basic for Application.
И в то время, как формулы Excel – это инструменты с довольно ограниченной областью применения, на VBA можно написать почти всё, что угодно. Хоть это и упрощённый, но всё же язык программирования. Целью C Bel было показать, НАСКОЛЬКО СИЛЬНО люди недооценивают возможность формул и почему им не стоит сорвя голову бежать изучать VBA, как только на горизонте замаячит задача посложнее расчёта, скажем, годовых затрат. И лично я считаю, что у него получилось.
Теперь вопрос – КАК? Поскольку C Bel владеет формулами Excel на уровне чёрной магии Дэвида Блэйна, я даже пытаться не буду понять, насколько он велик. Или велик. Или самокат. Или даже гироскутер – мы ж тут современные люди, правда? Я сделаю иначе – для начала расскажу, ЧТО именно ему удалось сделать. Итак, при помощи Excel и исключительно математических формул он реализовал:
- бесконечную процедурно-генерируемую карту
- трассировку лучей в реальном времени
- расчёт столкновений
- рендеринг света
- расчёт шейдеров
- и движок перемещения
Будучи разработчиком игр, автор попросту имел представление о том, как создать подобный лабиринт, используя программирование, а доскональное знание формул Excel позволило ему попросту интерпретировать программный код в математические формулы. Это звучит, как трансформер, состоящий из костыля на костыле, но впечатляющий вне всяких мер.
Лучшее время ознакомиться с классикой
У зрителей менее опытных возникнет вопрос – как вообще можно сделать игру настолько сложную, используя только формулы? Без текстур, без полноценного игрового движка, без анимаций и прочего? Расскажу секрет. По сути, при создании игры мы делаем упор либо на использование памяти компьютера, либо на использование ресурсов его процессора и видеокарты. То есть, та же самая текстура может либо храниться на жестком диске устройства, либо создаваться по формулам прямо на лету силами процессора.
Два самых экстримальных примера – No Man’s Sky с тремя гигабайтами на обозримую вселенную внутри игры, и малоизвестная нынче игра kkrieger. Её вы на скриншотах ниже сейчас и видите.
Хотите верьте, хотите нет, но она занимает 96 КИЛОБАЙТ. Кило-БАЙТ. На жестком диске. Меньше, чем картинка, которая стоит у вас на аватарке в фейсбуке. Это впечатляет, и лично меня впечатляет не меньше, чем без пяти минут DOOM в Microsoft Excel.
Комментарии:
Иногда симбиоз задатков программиста и геймера даёт небывалые результаты — пользователи мастерят интересные вещи из тех программ и их возможностей, которые ранее применялись совсем для других дел. Например, многие разработчики компьютерных игр используют Microsoft Excel как платформу для своих творений. Там есть все необходимые формулы и возможности, осталось только разобраться в документации и проявить фантазию. К примеру, в интернете можно скачать вполне играбельную Монополию для Excel.
Однако, разработчики дальше каких-то казуальных игр или недо-RPG не заходили. Всё же, это не игровой движок и создавать на нём сложные проекты довольно трудно. Пользователь с ником C Bell трудностей не боится — он смог создать на данной платформе полноценный шутер по мотивам DOOM.
Игра представляет из себя лабиринт, по которому вы путешествуете и находите врагов, их можно уничтожить лазером и пойти дальше. Самое невероятное в этой истории — графика объемная. Это настоящий 3D шутер с картой, противниками и стрельбой. Да, немного кособокий, привлечёт только фанатов программирования и разработки игр. С другой стороны, вы видели шутеры из раздела инди в Steam? Там ничем не лучше игры продаются.
Вся игра построена исключительно на формулах, весь виртуальный мир генерируется (а он именно генерируется, это не заранее нарисованная карта) исходя из данных, введённых в программу. Создатель проекта решил не использовать VBA-макросы и всё написал сам, с нуля. Естественно, играть в это вы не будете, но сам эксперимент очень даже интересный. Плюс, на просторах интернета уже нашлись фанаты, которые просят разработчика добавить возможность улучшения оружия и персонажа, чтобы была мотивация сражаться чаще.