Использование HTML5, веб-сокетов и немного C# для создания многопользовательской космической стрелялки
Сегодняшний проект посвящен многопользовательской игре вроде Asteroids, основанной на HTML5 и демонстрирующей некоторые простые способы взаимодействия холста HTML5 и веб-сокетов C#.
SpaceShoot – многопользовательскаяиграв HTML5
В последнее время возрос интерес в использовании HTML5 для создания великолепных кросс-платформенных игр. Технологии вроде WebSockets, Canvas и другие стали значительно стабильнее и безопаснее для использования веб-разработчиками. Правило остается прежним – продукты должны создаваться на основе технологий, которые станут доступными, когда продукт выйдет на рынок, а не когда продукт создается. Поэтому я считаю, что потребность в разработке продвинутых игр, использующих HTML5 вместе с CSS3 и JavaScript будет неуклонно расти на протяжении следующей пары лет.
Основы
Я всегда хотел написать отлично выглядящую многопользовательскую игру – но у меня никогда не было времени достичь поставленных целей во всех областях. Имел ли я надежный и быстрый многопользовательский код, или прекрасную идею для игры, или правильные методы отображения графики. С выходом HTML5 увеличился мир новых возможностей. Прежде всего, есть множество возможностей писать игры. Есть множество доступных видов игр. Некоторые браузеры даже включают (конечно, не как часть приближающегося стандарта HTML5) технологию WebGL. Некоторые браузеры, подобные Google Chrome, даже имеют так называемого естественного клиента. Все эти технологии делают возможным (ускоряют) 3D в браузере.
Сейчас большинство игр являются вариантами двухмерных социальных игр. Они следуют простым принципам и содержат прекрасную 2D-графику с интерфейсами в Facebook / Google+ / Twitter или другие социальные сети. Обычно вы играете в однопользовательском режиме, и как-то (обычно с помощью AJAX) соединены с базами данных больших сайтов, обеспечивающих вас обновлениями того, что делают другие или разными видами обратной связи и информацией. Однако есть технология, которая изменит всё это.
С появлением стандарта HTML5 будет стандартизироваться все больше и больше популярных технологий. Одна из них – WebSocket . Уже сейчас можно услышать множество рассуждений о node . js. ПО написано так, чтобы каждый мог писать на серверном (WebSocket-) коде на JavaScript. Этот код компилируется в машинный код (через движок с открытым кодом V8 компании Google) и управляет всеми запросами в форме обработки событий. Конечно, это дает преимущество, если вы хотите программировать серверный код на языке, подобном клиентскому, хотя нужно сказать, что node – совершенно другая технология (и, я полагаю, вы обнаружите это, использовав его всего лишь раз!)
Так как мне нравится C#, я захотел писать серверный код на C#. Основой серверного кода стал проект с открытым исходником Fleck . Он вызывает необходимые классы и методы.NET-Framework и поддерживает большинство текущих спецификаций протоколов. На клиентской стороне я решил использовать элемент <canvas>. Я не собираюсь представлять здесь всю игру: в то, что будет представлено здесь, можно играть (в многопользовательском режиме), и это будет достаточно забавно. Я сделал ее расширяемой. В нее можно включить ту функциональность, какую вы захотите. В проект включено всё, что нужно для этого.
Необходимо заметить, что возникает много проблем при попытке реализовать программу вроде игры в многопользовательском режиме. Подумайте о задержках. Какие типы сообщений отправляются и принимаются? Логика реализуется также и на клиенте, или только на сервере? Мой подход как будто прост в этом примере. Однако моей целью является представление этого подхода и демонстрация его преимуществ и недостатков, а также способов избавления от последних.
Каждый клиент будет посылать на сервер ввод с клавиатуры перед тем, как он будет обработан. Сервер затем распределяет входные данные другим клиентам. Так что все будут видеть одни и те же действия. Это имеет то преимущество, что игра практически не изменяется для одного игрока, за исключением того, что сообщения должны быть отправлены до реализации логики и того, что полученные сообщения могут приводить к дополнительной обработке логики. Однако есть несколько серьезных недостатков, а именно:
- Если один из игроков запаздывает, он будет получать логику слишком поздно и не сможет видеть действий оппонентов.
- Хуже того, если сообщения от такого клиента не размазаны по времени, то n сообщений от одного клиента не будут отправлены остальным. Так что другие клиенты увидят, возможно, одно сообщение – последнее из посланных. Вместо некоторых поворотов и выстрелов, лишь последнее действие будет выполнено, что приведет к рассинхронизации.
Чтобы предотвратить проблемы синхронизации, каждый космический корабль посылает серверу свой текущий жизненный статус и текущее положение. Затем эти данные рассылаются по другим клиентам. Такой подход также не лишен недостатков:
- Кто-то может сжульничать, изменив жизненную энергию и сведения о боеприпасах собственного корабля.
- Выстреливаемые частицы не включены, т. е. клавиатурные действия являются действительно решающими.
Большинство этих недостатков может быть исключено с помощью следующего подхода:
- Самая важная логика игры выполняется на сервере только в многопользовательском режиме.
- Не настолько важная логика (движение астероидов) выполняется на клиенте.
- Клиент отвечает лишь за прорисовку и отправку команд клавиатуры.
- Сервер собирает клавиатурные команды одного раунда – он не рассылает их, пока каждый не отправит данные клавиатуры.
- Цикл клиента по-прежнему составляет 40 мс, но связан лишь с посылкой клавиатурной информации (в многопользовательском режиме).
- Остальное выполняется, когда получены все команды клавиатуры. Таким образом, каждый остается с гарантией засинхронизованным.
У этого подхода есть ряд преимуществ. Первое, когда присоединяется новый игрок, сервер может выдать клиенту все требуемые объекты, включая координаты. Это возможно, поскольку сервер выполняет всю логику самостоятельно, зная все координаты. Также сервер просто выполняет один шаг по обработки логики после того, как получит все клавиатурные команды. Поэтому вместо того, чтобы основываться на всем времени (которое порой хорошо, но чаще всего плохо), он будет полагаться на синхронизированное время
...
Использованиекода
Чтобы использовать этот код, не требуется многого. Однако я должен различать однопользовательский и многопользовательский режимы. Однопользовательский режим должен работать в вашем браузере (если он не слишком устарел!) Я проверил игру в следующих браузерах (в однопользовательском режиме):
- Microsoft Internet Explorer 9+
- Opera 11.5+
- Google Chrome 16+
- Apple Safari 5+
- Mozilla Firefox 7+
Поскольку однопользовательский режим тривиален, давайте обратимся к многопользовательскому. Прежде всего, имейте ввиду, что для того, чтобы играть на веб-сервере, необходимо задать некоторые настройки у брандмауэра. Даже после их задания надо принять во внимание, что клиент может оказаться за брандмауэром (с точки зрения маршрутизатора, вашего компьютера, …) Таким образом, чтобы гарантировать соединение, нужно выбрать порт, а также аккуратно проверить методы. Или можно сделать следующее:
- Откройте представленное решение в Visual Studio 2010.
- Измените строку new WebSocketServer("ws://localhost:8081"); задайте порт, который вам нравится (вместо 8081).
- Откройте файл sockets.js.
- Измените строку new WebSocket('ws://localhost:8081'); заменив как порт, который вы хотите использовать (вместо 8081), так и IP-адрес или DNS-имя компьютера (т.е. замените localhostна 192.168.0.1 или example . com).
- Разместите файлы HTML/CSS и JavaScript либо на локальном сервере, либо в Интернете.
- Если серверная программа выполняется в локальной сети, то передача HTML-кода через интернет не имеет смысла – все по-прежнему будет работать, если выполнять страницы локально.
Два последних пункта не тривиальны. Почему требуется размещать страницу на сервере (т.е. на localhost) вместо размещения веб-сайта в файловой системе? Проблема с безопасностью. Большинство браузеров имеют установки безопасности, запрещающие исполнять код из локальной файловой системы. Google Chrome не выполняет запросов WebSocket для локальных веб-сайтов. Это справедливо и для большинства XHR-запросов и аналогичных (вроде WebWorkers). Некоторые браузеры предлагают опции, позволяющие регулировать эти настройки. Так как я не знаю, какой браузер вы используете, я просто предполагаю, что он совместим с WebSockets и предоставляет набор команд, которые гарантированно будут работать!
Вот фрагмент серверного решения:
Если вы задумываетесь о том, как использовать в вашей игре или на сайте веб-сокеты, это интересный пример, которому легко следовать…