К счастью, Том оказался человеком слова. Через пару недель после нашей первой беседы он организовал для меня встречу с его знакомым – профессионалом в сфере управления финансами, который мог бы подтвердить навыки работы с программами на практике. Этот знакомый, Ричард, был человеком непростым, со скептическим взглядом на жизнь и крепким рукопожатием, говорящим о его опыте и характере. Мы встретились в его офисе – небольшом, но уютном кабинете с деревянными панелями и строгими стальными полками, уставленными бухгалтерскими книгами и финансовыми отчётами.
"Илон, верно? Ну что, покажешь мне эту программу, о которой Том всё уши прожужжал?" - ходу задал он мне вопрос.
Пришлось сесть за его старенький компьютер и, глубоко вдохнув, начать демонстрировать функционал нашего проекта. Программа на первый взгляд была простой, но каждый её компонент был продуман, и потому пытался объяснить, как это могло бы облегчить управление финансами для небольших компаний. Как только стал показывать автоматизацию сложных расчётов, Ричард замер, внимательно следя за действиями на экране.
"А теперь скажи мне, как ты это запрограммировал?" - он скрестил руки и с лёгким недоверием прищурился.
Так что пустился в объяснения, стараясь сдерживать волнение. Понимал, что от этой встречи многое зависит. С каждым новым пояснением Ричард становился чуть менее настороженным, и вскоре он уже наклонялся ближе к экрану, задавал вопросы, уточнял детали. Видимо, ему приглянулся – он наконец-то выпрямился и с удовлетворённой ухмылкой кивнул:
"Ладно, парень. Я тебе поверю. Тоже был молод, - его глаза чуть смягчились. - Программирование – это вещь полезная. Но ты знаешь, что одного только этого мало?
Естественно кивнул. Внутри всё трепетало от успеха, но сдержался, не став демонстрировать на публику свои реальные чувства.
"Поэтому ты будешь учиться дальше? - Он скептически посмотрел на меня. - Надеюсь, это в твоих планах?"
Это было как раз то, ради чего и взялся за подтверждение своих знаний. В голове уже прорабатывались маршруты: обдумывал дальнейшее поступление в университет. Ведь тоже прекрасно знал, что одним программированием большого успеха не добьёшься, нужны были связи, репутация и формальное подтверждение моего интеллектуального багажа. И так, впахивая в одиночку, команду не соберёшь, даже для создания игры, не говоря уж об остальном, что пока только в отдаленных планах.
Глава 4
Удобно так устроился в углу уютного торонтского кафе. Тихий уголок с видом на улицу позволял мне сосредоточиться, но при этом оставаться в курсе того, что происходит снаружи, – эта привычка сильно укрепилась с тех пор, как оказался в этом времени. Передо мной – тёплая булочка и дымящийся чай. Глотнув терпкого чая, вновь взглянул на экран. Да, почти всё заработанное на проекте с Томом потратил на местный вариант ноутбука. Не выдержал. Он не блистал характеристиками, зато давал возможность работать! Не когда было можно, а когда горело. Отрабатывать результат можно и потом, на нормальных машинах, когда к ним будет доступ, а пока так. Да и в целом, сейчас не такие уж и большие требования к графическому окружению программного обеспечения и много чего и на такой машинке можно писать полностью.
Для того чтобы игра могла функционировать на машинах нынешнего времени, придётся отбросить много "фишек" из будущего. Ускорители 3D-графики, как 3D-графические карты, ещё не появились на массовом рынке, и нужно было работать с тем, что есть. Следовательно, всё, что обычно обрабатывалось графическим оборудованием, теперь должно было выполняться центральным процессором со всеми вытекающими из этого последствиями. И основной идеей было задействовать возможности процессоров для построения псевдо-3D графики. Вдохновляясь подходами к рендерингу старых систем, стал думать над алгоритмом, который позволил бы симулировать трёхмерное пространство без полного построения сцены. Пальцы лихо побежали по клавишам, вводя очередные строчки кода:
```c
// Основная функция рендеринга
void RenderScene() {
for (int y = 0; y screenHeight; y++) {
for (int x = 0; x screenWidth; x++) {
// Перевод экрана в псевдо-3D координаты
int mapX = x 3;
int mapY = y 3;
int tileType = map[mapY][mapX];
// Проверка для текстурирования
if (tileType == WALL) {
DrawWall(x, y);
} else {
DrawFloor(x, y);
}
}
}
}
```
Суть этого подхода заключалась в том, чтобы проецировать 2D-карту на экран, таким образом создавая иллюзию 3D-пространства. Для эмуляции высоты использовались заранее подготовленные тайлы – кирпичики, полы, стены – которые накладывались друг на друга, как слои в фотографии. Эффект получался не совсем реальным, но в условиях отсутствия 3D-ускорителя он был весьма неплох. Тем боле пока потребители даже такого не вкусили толком. Ух они у меня устроят мочилово!
Так и продолжал возиться с рендерингом – в каждом шаге приходилось тщательно учитывать ограничения как потенциальных возможностей машин, на которых будут игру запускать, так и того, что мог мой ноут. "Так, без прямой поддержки 3D могу рассчитывать только на простые матричные преобразования и рисовать на основе значений тайлов. Ну, а свет? Ладно, с фальшивым светом подумаю позже...". На этом открыл блокнот, где предварительно набросал идеи для освещения:
1. **Имитировать световые зоны** – в зависимости от расстояния до источника света текстуры становились бы темнее или светлее.
2. **Простая градация** – чем дальше от игрока, тем темнее зона, создавая эффект глубины.
Ещё пара строк кода, и на экране в отдельном окне возникла сцена с характерным серым полом и тёмными стенами. Ощущение присутствия было сырым, но для первого эксперимента неплохо. Да что там, супер, сказал бы даже. Я молодец! Если себя сам не похвалишь, кто это ещё сделает, тем более никто и не знает, какую революцию тут замутил.
```c
void DrawWall(int x, int y) {
// Закрашиваем стену с оттенком серого
int shade = 255 - (distanceToPlayer(x, y) * 10);
shade = max(0, min(shade, 255)); // Ограничиваем значения
SetPixelColor(x, y, RGB(shade, shade, shade));
}
```
"Отлично, - пришла мысль, — это первый шаг. Простейшие стены готовы".
После чего сделал несколько быстрых глотков чая, поглядывая на экран. Несмотря на довольно простую задачу – отрисовку стен и пола, – процесс оказался гораздо более сложным, чем думал внвчале. Даже каждая мелочь, вроде изменения оттенков или расчета расстояний, съедала память и ресурсы процессора. Гадство…. Прибил бы этого Билла Гейтса с его шестнадцатью килобайтами оперативы, которой хватит на всё! Но одна идея крутится в голове, давая новый импульс: вместо полной симуляции каждого шага, можно ведь бы использовать метод **Raycasting**, в прямом переводе звучащий довольно бессмысленно, – метод, которым создавались игры вроде *Wolfenstein 3D* в ранние девяностые годы. Он не требовал 3D-ускорения, но позволял строить иллюзию трехмерного мира на основе двумерной карты.
Правда появился он куда как ранее, ещё в восьмидесятые, но это сейчас не важно, поскольку до нынешнего времени использовать его в практических приложения возможным не было, поскольку банально не хватало мощности компьютеров. Если сделаю игру и выпущу на рынок раньше, то будут упоминать меня, а не Кармака. Да и игра в которой его применили первой станет *DOOM*. В общем, тут можно сказать саму историю переписываю! А потому, сконцентрировавшись, начал накидывать основные принципы метода:
1. **Лучевая трассировка** - при каждом обновлении экрана будет высылаться множество «лучей», начиная с точки игрока и направленных в разные стороны. Эти лучи «натыкались» на стены, вычисляя расстояние до каждой из них.