Отладка миссий
Пришлось разбираться с внутренней структурой ядра, и придумывать как работать с графом объектов ядра так, чтоб его можно было в любой момент удалить и восстановить из файла. Чтобы при этом корректно загружались все объекты других подсистем. Трудностей было очень много, и циклические ссылки, и реализация менеджера ресурсов. Попутно был составлен список используемых текстур, и каталог их хранящий, стал весить в два раза меньше. Из-за циклических ссылок например трупы не удалялись, а оставались лежать при перезагрузке уровня.
От идеи реализовать меню на движке пришлось отказаться. Во первых это было очень сложно, во вторых гуи движка выглядело мягко сказать непрезентабельно. За один день в делфи был набросан загрузчик, с красивой картинкой, настройками клавиш, звука, графики и физики, с возможностью загрузки/сохранения. Связь с основным exe файлом была реализована через текстовые файлы. А внешне всё работало даже неплохо.
Огромнейшая проблема была со стабильностью работы игры минут 30 играть можно было, а потом переполнялась память, начинался своп, время от времени просто всё падало от ненайденных ошибок. Быстро заткнуть эту дыру удалось сделав любую загрузку уровня/сохранённой игры через перезапуск exe файла.
Для "наведения лоска" написана система демонстрации комиксов, чтобы давать информацию игроку о событиях сценария игры, которые нам не удалось воплотить в жизнь. Это был один большой полигон с текстурой, и конфигурационный файл с последовательностью координат участка комикса, на который наводить камеру, какой текстом сообщения и именем звукового файла. Кто скажет, что комиксы выглядят убого - просто не видели первоначального варианта - сканов каракулей нарисованных ручкой от руки нашего инвестора, на уровне второго класса средней школы. Неподготовленные личности от их вида заражались положительной энергией и получали дополнительно 2-3 дня жизни от смеха. Озвучка, которую мы делали сами на пятидесятирублёвый микрофон встроенной звуковой карты - тоже обладала целебным эффектом. Остальные звуки были отличными, так как мы их позаимствовали из альфы второго халф-лайфа.
Так же быстро на коленке были реализованы скриптовые сценки. В персонажи добавлена анимация разговора, скрипт прерывал игровой процесс, сверху/снизу экрана дорисовывались черные полоски, "как в кино", все персонажи подходили на нужные места, и камера начинала поворачиваться вокруг "центра" дискуссии так, чтобы говорящий был виден со спины. Таким образом удалось обойтись без лицевой анимации.
Проблему представлял АИ NPC. Все телодвижения каждого персонажа на уровне вручную программировались в скрипте, и практически каждый раз предполагаемый сценарий нарушался, некоторые персонажи останавливались без дальнейшей программы действий, некоторые начинали тупить или делать очень смешные вещи в данной ситуации. Например напарник игрока после попадания в него пули, убегал как ошпаренный и доносился быстро удаляющийся голос - "я ранен, но я ещё могу идти!".
Как решение я прописал фиксированное количество простых программ с параметрами - стоять на место, следовать за кем либо, идти к точке, паниковать, и т.д. Были некоторые параметры, и очевидные автоматические переходы от одной программе к другой по внешним событиям. Скрипт стал использоваться только как принудительная установка программы поведения по определённым событиям в игре.
Тем временем на нас вышла Акелла. Как потом выяснилось, наш инвестор даже не сообщил об этом предыдущему издателю, а просто перестал отвечать на его письма и звонки.
С тем, что было мы поехали на очередной КРИ(2005). Как потом выяснилось, билеты на конференцию инвестор купил только себе, а мы туда прошли под видом посетителей/обслуживающего персонала(как получалось проскочить, так и проходили). Вся конференция прошла в сидении за стендом и демонстрации нашего продукта всем любопытным. Потом нас нашел предыдущий издатель и была занимательная сценка, как наш инвестор стеснялся и крутил пальчик в ладошке, а ему говорили, что же ты делаешь, почему не отвечаешь на письма и на звонки. Рядом был стенд лада рейсинг клаб, с продуктом уровня нашего, но денег у них было больше, даже хватило на огромный стенд и стриптиз для нищих.
Акелла - это был новый уровень, и соответственно новые требования. Стенсильные тени сразу были забракованы, был проведён бетатестинг того, что у нас называлось игрой и составлен список исправлений, от вида которого мне стало плохо. Но глаза боятся, а руки делают, начал переговоры напрямую с куратором проекта, стал объяснять что мы можем, а что нет. Некоторые вещи удалось урегулировать просто в обсуждении. Остальное начали исправлять.
Тени удалось реализовать на заготовке фонарика. Рендер в текстуру вместо картинки светового пятна, немного математики, и наш персонаж отбрасывает тень. Для стенсильной тени направление выбиралось как средний вектор ближайших источников. Но выглядело это коряво. Я решил попробовать отбрасывать тень от всех ближних источников. Но это просаживало производительность. В результате остановился на 3х тенях для игрока, и 1й тени от предметов и NPC. Подобрал подходящую функцию, от расстояния, чтоб тени появлялись и исчезали плавно, результат получился отличным. Но осталось две проблемы - тень на улице, и тени от источников под полом(находящиеся ниже игрока). Трассировку на источник было делать слишком накладно, да и многие источники были внутри предметов. Решено это было так - эмбиентная тень включалась только если игрок не пересекался с радиусом хоть одного источника, а все источники ниже игрока просто не учитывались.
Однажды, после добавления новых анимаций, модель игрока начала выделывать странные финты. Некоторые анимации превращали персонажей игры в нечто сайлентхилоподобное. Ошибку искали долго, сначала поняли что глюки начинаются после превышения определённого значения суммарной длиной анимаций модели. Потом оказалось что в реализации модели выделен фиксированный массив, без проверки переполнения, и анимации начиная с определённой длины читались/писались в свободную память.
С производительностью графики тоже было совсем тяжело. Из оптимизаций было только отсечение по фруструму, и то реализованное криво. При отрисовке всего уровня он рисовался примерно в 1~5 тысяч DIPов, по количеству листьев дерева, что выливалось в 4~5 фпс. Решено это было так, дерево было отсортировано специальным образом, что бы можно было отрисовывать узлы целиком, не спускаясь к листьям. Если узел почти полностью попадал в фруструм, то он отрисовывался полностью, без дальнейшей детализации. Таким образом удалось вернуть нормальный fps и уложится в 250 DIPов на всю отрисовываемую сцену. Но перекспортить графические модели уровней не удалось по банальной причине - максовские исходники части уровней были потеряны. Пришлось конвертировать всю сцену прямо во время загрузки ресурсов в игре. Самое интересное, что даже с этим общая загрузка получилась быстрее, чем в играх аналогах. Боюсь даже представить, что там у них делается.
Для улучшения картинки была добавлена система частиц и материалов. В движке уже была заготовка, сделанная ещё Глебом, но возможностей там было маловато. Пришлось всё сильно расширять, добавлять графическую трассировку для пуль, так как физическая модель часто отличалась и это вызывало визуальные глюки, как непростреливаемые невидимые стены, окна. Точно стали ложиться на поверхность отверстия от пуль, которые исчезают как и в остальных играх, но заметить этого невозможно из-за специально подобранной скорости нарастания прозрачности. Был сделан фиксированный набор материалов и составлено соответствие текстура-материал для каждой текстуры. Материал определял звук шагов, шум от физических ударов предметов друг об друга, модель дырки от пули, звук попадания пули, систему частиц, вызываемую по событию, и многое другое как во всех нормальных играх.
Огромную проблему представляла стабильность работы игры. Утечки памяти пришлось вылавливать вручную. Был реализован счётчик экземпляров классов, который считал статистику по всем создаваемым/удаляемым классам в игре. С локальными выделениями/удалениями памяти было сложнее, пришлось каждый случай отслеживать вручную. Больше всего запомнилась ошибка в синтаксическом анализаторе скрипт языка в ядре. При считывании лексемы не освобождалась память из под последнего символа. Казалось бы мелочь, а за час игры набегало 200 мегабайт. Когда все утечки были побороты, игра при нажатии кнопки выход стала выгружаться мгновенно после любой продолжительности работы, что было очевидной победой, так как до этого каждый выход из игры тормозил и сопровождался активным свопом.
В программе оставалось ещё много ошибок, из-за чего среднее время работы до падения составляло около получаса. Каждый раз сидеть играть и ждать падения для воспроизведения ошибки было непозволительной роскошью. Для автоматизации процесса был написан "автопилот". Игра при запуске с определённым параметром в командной строке начинала играть сама. В течении двух минут игрок бежал в случайном направлении, стрелял, прыгал, приседал, иногда сохранялся. По прошествии двух минут либо загружался новый уровень, либо сохранённая игра. И так в цикле. Программа запускалась на всех доступных компьютерах, работала около получаса и падала. Постепенно ошибки локализовывались и исправлялись. Время средней работы возросло до часа, потом до двух. После исправления последней ошибки игра на шести компьютерах параллельно проиграла сутки без падений и потерь памяти. Дело было сделано, временная заглушка с перезагрузкой при каждой смене уровня была отключена.
Мне стыдно в этом признаваться, но в физике не было реализовано ни одного примитива, только полигональные модели. За месяц до выхода игры на золото для ускорения трупов был добавлен примитив капсулы, вместо прямоугольных параллепипедов, которыми задавались части тела регдола.
В последние дни была заменена вся озвучка на студийную, и то, что раньше называлось комиксами - на нормальные рисунки художников.
Все эти работы делались параллельно с фиксингом многочисленных багрепортов. Нагрузка была нечеловеческая, но к вечеру 31 декабря 2005 года всё было сделано и игра ушла на золото.
Страницы:
1 2 3 4 5 6 Следующая »
7 января 2006
(Обновление: 23 дек 2012)