По ссылке с HackerNews наткнулся на
рассказ Patrick Wyatt, одного из программистов Starcraft (того самого, классического, 1998 года выпуска) о том, как они эту игру писали. Прочитав, я чуть не прослезился сразу по нескольким причинам.
I. Во-первых, дежа вю и ностальгия. После университета я семь лет делал компьютерные игры и пошел заниматься этим не в последнюю очередь потому что искренне хотел делать хорошие игры. Такие, например, как Starcraft. Оказывается, те люди, которые его писали, испытывали примерно те же трудности, что и мы:
- они (и мы 20 лет назад тоже) фигачили просто как проклятые. После выхода моей первой игры я ради интереса разделил объем кода на потраченные человекомесяцы и узнал, что мы написали в среднем по 500 строк кода в день. Каждый. Это именно в финальном коде, не считая багфиксов и рефакторингов. Патрик описывает, что у них ведущий программист временами проводил за кодом по 40-48 часов подряд и остальные старались за ним тянуться, работая абсурдно много. Сходится.
- они (и мы в 2002 тоже) понятия не имели о практиках программирования, которые сейчас считаются очевидными и обязательными. Какой такой code review? Ведущий программист занимался тем, что принимал очень редкие высокоуровневые решения, распределял задачи, а дальше просто старался писать больше всех самого важного кода - он же ведущий!
- они боролись с C++ и стреляли себе в ноги. Например, правило "prefer aggregation over inheritance" ещё не было открыто, и юниты в игре находились в следующей иерархии классов: CUnit < CDoodad < CFlingy < CThingy (названия реальные!)
- класс CUnit, естественно, был мешаниной из пары тысяч строк, а его объявление было разнесено на несколько файлов
ну и т.п.
Главные проблемы были буквально одни и те же:
- низкоуровневые оптимизации и stateful-натура игрового кода делают его очень хрупким. Сейчас, мне кажется, подобных задач для программистов почти нигде и не осталось. Бывают области, где всё ещё нужны низкоуровневые оптимизации (какой-нибудь там инференс ML-кода, или embedded всякий), но все они по сути stateless. Бывают stateful-сервисы, но реакция любого современного программиста "ок, весь state сразу уносим в базу данных". А ситуаций как в старых игрушках, когда тебе нужно моделировать изменения довольно сложного "мира" и делать это как можно быстрее, кажется, нигде больше и нет (даже в игрушках). В Старкрафте главной проблемой, оказывается, были небезопасные связаные списки, в которые связывались все на свете объекты для быстрой итерации по ним, и многие сразу в несколько списков. Мы себе такую проблему, к счастью, не создали, зато я до сих пор с ужасом вспоминаю "автоматическое" управление памятью при помощи хитрых умных указателей. Ощущения в пересказе программиста Starcraft и в моих собственных воспоминаниях при этом очень похожи.
- довольно "тупой" код игровой логики, похожий на бизнес-логику в привычных сейчас IT-проектах, оказывается вовсе даже не тупым, когда его приходится писать по 500 строк в сутки. Наверное, больше всего это похоже на написание романа: каждое следующее слово просто берешь и пишешь, вроде бы. Но на больших масштабах слова или складываются в непротиворечивый работающий сюжет с интересными персонажами, или нет. И если просто графоманить, не придумав себе некоторые высокоуровневые принципы и некоторые инварианты, то точно не сложится. И тот факт, что вы уже умеете написать короткий рассказ, еще не означает, что вы научились писать.
- save-load на С++ это ад. Представьте себе какую-то систему из огромного количества взаимосвязанных и взаимодействующих объектов со своими свойствами (некоторые из которых только перечисляются в 2000 строк, см.выше). А теперь нам нужно её слепок в произвольный момент времени сохранить на диск и восстановить с него, и сделать это быстро. Баги, которые проявляются только после saveload-а, сделанного в момент со строго определенными свойствами - мои любимые. Конечно, написание этого кода нужно автоматизировать. Конечно, это плюс один уровень сложности поверх всего вышесказанного.
- pathfinding оказывается крайне недооцененной задачей, совсем не сводящейся к Dijkstra's algorithm и/или A*, требующей постоянных допиливаний и стреляющей багами вплоть до релиза (и это, черт подери, даже без всяких там "полностью разрушаемых окружений в 3d")
II. Во-вторых, чувство зря потраченных сил и времени. Судя, по крайней мере, по тексту Патрика, мы были программистами не просто не хуже близзардовских. Мы были лучше. Про Гулина даже не говорю, но и лично я сделал
какую-то RTS и её код был устроен в разы, если не на порядки лучше, чем то, что описывает человек из Близзард. Да, у Робокалипсиса были очень приличные рейтинги. И это, конечно, естественно, совсем не Starcraft. Почему у меня в геймдев-жизни так в итоге не было проекта, который был бы известен по всему земному шару и в который массово играли бы десятилетиями? Да потому что я работал не в том месте, которое как организация было бы на это способно, вот и всё.
Гораздо более интересный вопрос, а почему Blizzard или LucasArts способны были делать шедевры на десятилетия, а Nival или Vogster оказались не способны. Наверное, это серьезное упрощение, но всё же я свёл бы этот результат всего к двум факторам:
- в руководстве должны быть хорошие люди, которые искренне и в глубине души хотят делать хорошие игры (наверное, это можно распространить на соседние области "выпускать хорошие фильмы" и "делать качественные продукты"), а не просто заняться бизнесом и заработать денег. Вроде банально, но надо заметить, что в жизни всё не так-то просто: конечно же, все и всегда притворяются людьми первого рода, а не второго. Ситуации, когда нужно выбирать между первой целью и второй, редки и незаметны, отличия проявляются в скрытых ситуациях и в обсуждениях за закрытыми дверьми, в общем отношении к людям и их талантам. Представьте себе, что человек, единственной целью которого является заработать денег, рассказывает тебе, что разделяет твою мечту и предлагает вместе работать над её достижением; чем старше, умней и опытней слушатель, тем он лучше интуитивно чувствует подвох в подобных рассказах и тем хуже с ними мирится. Тим Шейфер до выпуска Full Throttle проработал в LucasArts 8 лет; сомневаюсь, что он протянул бы столько в -----. И ещё одно замечание: иногда (и даже часто) люди, которые хотят делать хорошие вещи, становятся богаче людей, которые хотят заработать денег, хотя казалось бы. С точки зрения теории оптимизации, видимо, первые не застревают в локальных оптимумах.
- как это ни банально, у компании должно быть хорошее и доступное финансирование, которое можно получить в том числе под обещание доделать многообещающий проект до идеального состояния. Невозможно (или очень сложно) сосредоточить все таланты у себя в студии, но есть множество вещей, которые хорошо аутсорсятся: музыка, видеоролики, значительная часть арта, middleware; да и вообще, "полировка" и упор на качество в режиме денежного голода невозможны. Как это ни банально, в странах первого мира получать стратегическое финансирование на хороших условиях куда проще, а в конце девяностых - начале двухтысячных особенно. Так устроен мир, такова жизнь.
Почти законченный Starcraft до того, как было принято решение влить в него ещё несколько миллионов долларов и всё переделать
III. Ну и, в-третьих, чувство безвозвратности. Что бы ни случилось дальше в моей жизни (а я надеюсь, случится ещё много хорошего и интересного), я уже вряд ли когда-нибудь буду делать компьютерные игры и в выпуске какого-нибудь нового шедевра не поучаствую. А в Starcraft (Brood War Remastered, конечно), может, и поиграю ещё.