Примерно год назад вышла моя статья, которую можно назвать первой частью" данной статьи. В первой части я насколько смог подробно разобрал тернистый путь разработчика-энтузиаста, который мне удалось когда-то самостоятельно пройти от начала и до конца. Результатом этих усилий стала игра жанра RTS "Земля онимодов" созданная мною в домашних условиях без движков, конструкторов и прочих современных средств разработки. Для проекта использовались C++ и Ассемблер, ну, и в качестве основного инструмента моя собственная голова. В этой статье я постараюсь рассказать о том, как я решил взять на себя роль "реаниматора" и попытаться "воскресить" этот проект. Много внимания будет уделено написанию собственного игрового сервера. Продолжение статьи: GUI Конец статьи: Сеть Короткое видео я прилагаю к статье, чтобы сразу было понятно о чем идет речь:
Вступление
Вся эта история уходит корнями в 1998 год, когда мир IT был совсем иным. Игра, естественно, изначально проектировалась на существующие в тот момент условия. В частности, я бы сейчас навряд ли стал использовать ассемблер для вывода графики, но в тот момент это мне казалось чуть ли ни единственным решением. Если кому-то интересно, как всё это работает (игровая механика, AI и прочее) и каким было российское "издательство" игр в конце прошлого века, отсылаю вас к первой части статьи. Также существует отдельное описание алгоритма поиска пути, который я когда-то разработал для своей RTS. Этой статье уже более 10 лет и писалась она, скорее, "для себя", но писалась достаточно подробно, чтобы я сам мог вспомнить как всё это работает. Использованное решение, на мой взгляд, обладает высокой эффективностью с точки зрения скорости работы и гарантированно строит путь до цели на клеточном поле с любой степенью сложности расположения препятствий. Ознакомиться с этим способом можно тут. Почему я решил продолжить всю эту "эпопею"? Мне всегда было больно осознавать, что работа такого масштаба была мною в своё время просто похоронена по экономическим причинам. И когда мне показалось, что есть хоть какой-то шанс дать этой игре вторую попытку, то я, естественно, попытался это сделать. Последний год своей жизни я почти полностью посвятил этому вопросу. Благодаря в основном поддержке читателей первой части статьи, игра прошла Greenlight, и я решил со свойственной мне целеустремленностью привести всё в порядок. И именно этой моей деятельности будет посвящена данная статья. В начале я думал описать подробно весь процесс, начиная с создания собственного GUI (графический интерфейс пользователя) и заканчивая написанием игрового сервера. Но, к сожалению, обнаружил, что этой информации получается слишком много. В результате я больше внимания уделил описанию сети, так как, мне показалось, что эта тема для многих более интересна. Я постарался дать объяснения в таком виде, чтобы это можно было как-то применить на практике. Однако у меня нет уверенности, что в результате статья не получилось слегка "тяжеловатой" для понимания."Оболочка" для игры или то, что можно скачать и посмотреть в исходном коде C++
Как ни странно, этот раздел, который находится в самом начале статьи, я написал в последнюю очередь. По ходу написания статьи я понял, что мне нужно хоть что-то показать "изнутри", иначе все мои объяснения не имеют большого практического смысла и на деле превращаются в словоблудие. А мне бы этого очень не хотелось. Поэтому дополнительно я снабдил статью примером, по которому желающие могут ознакомиться с некоторыми аспектами моего подхода к написанию больших проектов: Визуально этот пример мало похож на мою игру, но на деле игра использует именно этот код, только в ней применяется другая "оформляющая тема ". Настройка игрового сеанса выглядит в игре так: Также на всякий случай уточняю, что это не "кнопки Windows-а", как кто-то может подумать, а мои собственные компоненты, которые я сделал в том объеме, который требовала моя игра. Пример является не просто "формальным" примером, а содержит в себе оболочку, которую я создал, чтобы использовать её в составе игры. Названия сей продукт не имеет, но он создавался мною с учетом того, что возможно игре потребуется портирование на другую платформу. В настоящий момент в полностью работоспособном состоянии имеется только Windows-версия, однако все обращения к операционной системе выполнены через виртуальные функции, которые можно заменить. На практике мне это понадобилось, когда пришло время выкладывать игровой сервер на просторы Интернета. Для бесплатного тестирования мне был доступен только вариант сервера, которым управляла Unix-подобная ОС. В результате пришлось дописать в оболочку ветку для Unix-а. Сам сервер при этом я не менял вообще, только заменил функции, которые требовались серверу для взаимодействия с ОС. Я не особенно разбираюсь в API Unix-а, но у меня есть хороший знакомый программист (на данном ресурсе носящий кодовое имя @Komei), который прекрасно понимает в этой теме. С его помощью портирование сервера было выполнено в течение нескольких дней. Кроме того мой приятель любезно предоставил мне свой Unix-сервер для запуска и тестирования моего игрового Интернет-сервера, а это, как минимум, была приличная материальная помощь моему проекту, так как держать собственный выделенный сервер не такое уж и дешевое удовольствие. Пример в составе статьи мне понадобился по причине того, что вся вторая часть статьи посвящена устройству сетевой игры. И там я вынужден периодически переходить в объяснениях на код. А сами по себе отдельные куски кода представляются мне достаточно бессмысленными. Обнародовать исходный код игры я посчитал "перебором" , всё же это для меня коммерческий продукт, кроме того, относительно небольшой пример представляется мне гораздо более понятным. Поэтому я решил обнародовать исходный код оболочки снабдив её для понятности собственным примером. Пример показывает работу с моим GUI, проигрывает звук и демонстрирует сетевое взаимодействие. Т.е. пользователь может нажать кнопку "Включить сеть", потом кнопку "Создать" и будет создан игровой сеанс, к которому можно присоединиться из примера, запущенного на другом компьютере. Конфигурация игрока в сеансе сводится к возможности менять его цвет, но для демонстрации принципа этого вполне достаточно. Описывать подробно организацию GUI я уже не стал, так как я не уверен, что это сильно кому-то интересно, а статья и так получилась достаточно большой. В любом случае пример демонстрирует работу со всеми имеющимися в моем GUI компонентами. Я не возражаю против того, чтобы кто-то воспользовался моей работой в своих корыстных или бескорыстных целях. Но я не обещаю, что буду развивать этот проект или что я буду поддерживать совместимость с текущей версией. Также я уточняю, что GUI проектировался не для скорости, а для универсальности, что и требовалось в моем случае. Кроме того, у меня реализована ветка, которая работает только с 16-битным цветом, который нужен моей игре, однако никто не мешает дописать ветку кода, которая будет работать с 32-битными цветами, а также использовать аппаратное ускорение GPU там, где это возможно. Скачать этот проект можно здесь. Проект примера выполнен на Visual Studio 2008 и использует язык C++ и DirectX9.Проблемы, которые мне предстояло решить
Для начала вот список проблем, которые существовали в игре год назад:- Игра полноценно работала только под Windows XP. Под Windows 7 игра нормально запускалась, но локальная сеть не функционировала вообще. А Windows 8/10 просто отказывались запускать игру.
- Игра была намертво "прибита гвоздями" к платформе Windows. Активно использовался DirectX, а также MFC.
- Оформление меню было очень "стрёмным" даже на мой взгляд. Связано это было с тем, что я занимаюсь программированием и к рисованию имею весьма далекое отношение, а доделывал игру я уже в одиночку.
- Визуально с "иконками исследований" дело обстояло еще хуже, чем с меню.
- Голосовая озвучка оставляла, мягко говоря, желать лучшего.
- Не было интернет-сервера, который мне всегда хотелось иметь, так как я считаю, что самое интересное в RTS - это игра по сети.
С чего начать
Проект игры когда-то делался в Visual Studio C++ 6.0. Теперь же этот Visual Studio C++ 6.0 даже не пожелал работать в Windows 8. Поэтому первым делом, мне нужно было перенести проект в новую для него среду. С одной стороны всё должно быть просто, так как Visual Studio умеет конвертировать проекты из прошлых версий в собственный формат, однако не тут-то было. Дело в том, что я использовал ассемблер tasm32, который создавал мне obj-файл. Этот файл без проблем линковался с Visual Studio C++ 6.0, но совсем не хотел линковаться с Visual Studio 2008. Новой версии tasm32 на свете не оказалось, а другие ассемблеры типа masm почему-то пылали к синтаксису tasm32 лютой ненавистью и выдавали множество ошибок при попытке подсунуть им мой asm-файл. Поразмыслив, я решил, что не готов на данной стадии переписывать код ассемблера под другой синтаксис, так как по началу я вообще не был уверен, что я двигаюсь в правильном направлении. В результате я принял следующее решение: установил Windows XP, поставил в неё Visual Studio C++ 6.0, создал проект типа DLL, написал экспортируемые функции, которые просто вызывали через себя функции ассемблера и прилинковал к нему свой ассемблерный obj-файл, который в Windows XP прекрасно создавался через tasm32.exe. В результате я получил библиотеку asm.dll, которую я уже смог без проблем подключить к новому проекту в Visual Studio 2008. Такое решение заработало, практически, сразу и пока я решил остановится на нем. Я, естественно, понимаю, что это решение абсолютно не переносимо на другие платформы, но если уж действительно встанет вопрос о портировании, то можно "собрать волю в кулак " и перевести ассемблер в другой синтаксис. Пока же судьба этой игры для меня туманна, хотя определенно я её за последний год в прямом смысле реанимировал. В любом случае, я потратил на этот проект уже достаточно сил, чтобы наконец-то получить от вселенной четкий ответ по данному поводу. После того, как я смог запустить игру в Windows 8 с помощью Visual Studio 2008 у меня в руках на-конец -то появился отладчик. Для начала мне нужно было разобраться в причинах, по которым новые версии Windows не желали запускать игру. Я давно не занимался играми и не особенно следил за той эволюцией ограничений, которую Windows стала накладывать на работу старых программ. Лично для меня эта причина оказалась очень неожиданной. Я обнаружил, что из Windows 8/10 удален 16-битный цветовой режим, который использовался моей игрой. После нескольких "магических ритуалов" мне всё же удалось запустить игру и даже немного поиграть, но работало всё угрожающе медленно, а вместо ландшафта на основной части экрана был чистый и прекрасный черный цвет. Для себя я отметил, что 16-битный режим теперь эмулируется и имеет ограничения по использованию.Битва за 16-битный видеорежим
Как бороться с этой проблемой? Как минимум имеется 2 выхода:- Переделать всю графику в игре так, чтобы она могла работать в 24-битном разрешении. В моем случае этот вариант плох тем, что вся графика хранилась в сжатом виде и рисовалась ассемблером. Все функции ассемблера умели работать только с 16-битной графикой, самих функций было много и работали они достаточно быстро, предполагали много нюансов при рисовании и, главное, за эти годы я порядком забыл как всё это функционирует в деталях.
- Создать в ОЗУ собственную поверхность, которая для игры будет являться экранной памятью. Рисовать всё на этой поверхности, а потом копировать её на реальный экран. Этот вариант я и выбрал в качестве единственно верного. При таком решении также появлялся жирнейший плюс - мне теперь почти не нужен DirectX для работы с графикой, так как единственное что он теперь должен был делать - это копировать мою поверхность на экран. Но есть в таком решении и не сразу очевидный минус - DirectX позволял мне запросто выводить текст, и я, естественно, так и делал. А теперь получалось: "нет DirectX - нет текста".