Pull to refresh

Как сделать морской бой онлайн на Silverlight 4 (подробная статья)

Reading time 5 min
Views 4K
Добрый день! Этот текст является подробной статьей о том, как я делал морской бой на Silverlight 4. Вдохновили меня на написание статьи Ваши комментарии. Исходные коды можно взять здесь. Тестовый логин test@mail.ru, пароль 123456. Но есть ограничение на то, что игроки должны иметь разные логины. Поэтому кто-то один должен быть обязательно зарегистрирован, иначе возникнет ошибка, которая будет скоро устранена.
image

Итак, я являюсь сертифицированным специалистом в различных областях, но по WPF (то, на чем базируется Silverligh) у меня знаний было 0. Поэтому я решил изучить основы этой технологии на базе живого примера, которой и стал знакомый с детства морской бой. Приняв во внимание вышесказанное, эта статья не описывает оптимальных механизмов использования технологий, т.к., наверняка, существует более изящное решение.
В общем, что нам понадобится: Visual studio 2010 (у меня версия Ultimate, но, думаю, можно попробовать и на бесплатной Visual Web Developer 2010 Express версии), а также надо установить Silverlight 4 tools for VS 2010. После того, как все скачалось и поставилось, можно браться за дело! Для начала нам понадобится создать хост-приложение на ASP.NET (File-New Project – Web Application). Оно у меня уже было заранее создано, а также там должен быть настроен Membership (MS SQL). Подробнее об этом можете почитать здесь. Основным элементом membership'а будет являться таблица из базы Users, так как на нее опирается логика работы с пользователями. Также надо добавить, что используются профили. Для их настройки надо вставить в web.config следующие строки:
элемент profile enabled=«true» defaultProvider=«SqlProfileProvider», добавить в субэлемент properties элемент
add name=«NickName».

Теперь все готово для создания сильверлайт-приложения! Заходим в File-AddNewProject, выбираем Silverlight Application, указываем наше хост-приложение, а также на будущее поставьте галочку: Net RIA Services. Итак, наше приложение готово. При создании автоматически появится в хостинг-приложении тестовая страница для запуска сильверлайт-программы. Подкорректируем параметры для запуска приложения и добавим такую вот строку <asp:Literal ID=«LiteralParams» runat=«server»></asp:Literal> в элемент object. Такой литерал нам послужит параметрами, в которые мы передадим адрес нашего веб-сервиса (поскольку для локального тестирования он один, а на хостинге будет совсем другой):
StringBuilder SB = new StringBuilder();
SB.Append("треуг.скобкавлево param name=\"InitParams\" value=\"");

SB.Append("SFServiceUrl="+GetServiceUrl());

SB.Append("\" /треуг.скобкавправо");

LiteralParams.Text = SB.ToString();


Затем мы прочитаем эти параметры уже в сильверлайт-программе:
private void Application_Startup(object sender, StartupEventArgs e)
{
// Получаем адрес сервиса
ServiceUrl = e.InitParams["SFServiceUrl"];


Итак, дальше логичнее рассказать про внутреннюю кухню программы. Нам понадобится создать 5 таблиц в базе:
image
Связи устанавливать необязательно, т.к. в нашем ядре они пока что явно не используются. Обрезанные полоски идут к таблице Users, полю UserId. Затем надо будет создать контекст данных (Linq To SQl) и добавить эти таблицы в него. В дальнейшем контекст данных будет иметь имя класса SDC. Его следует разместить в отдельной сборке (скажем, SDataAccess). Как это делать я описывать не буду, т.к. это тема отдельной статьи. Видимо, чтобы использовать Domain services, лучше сделать контекст данных на базе LinqTo Entities, но я решил делать по-старинке.
В качестве ядра я использую библиотеку активностей Workflow (SWorkflows):
image

В нем создаем папку Activities/SeaFight. Ее содержимое есть в исходниках. Там зашита основная логика игры, как-то: создание, завершение, проверка ходов, получение данных об игроках, ведение чата, работа с координатами кораблей и т.д. Более подробно Вы можете ознакомиться с классами в исходниках, которые лежат в папке Activities\SeaFight. Там используются запросы Linq to Sql, а результаты запросов выдаются через Workflow service в наше Silverlight-приложение.
После того, как наша сборка с активностями успешно скомпилируется, можно смело приступать к созданию Workflow service. Для этого в нашем хост-приложении создадим ее: File-Add New Item – Workflow Service:
image
Затем надо открыть этот файл XAMLX и начать создавать сервис. В отличие от Workflow из .Net 3.5 здесь используется авторинг Workflow-first, что облегчает задачу создания интерфейса. Ранее нужно было сначала сделать интерфейс с атрибутами ServiceContract, OperationContract и т.д., а затем использовать его для создания воркфлоу, а теперь этот интерфейс генерируется автоматически на основе воркфлоу. Итак, для того чтобы наш сервис мог обрабатывать сразу несколько операций внутри одного Workflow, нам нужно в корень вставить Peek Activity, а затем в нее добавлять последовательно в отдельные Branch (ветви) Receive Activity и Receive-Send Activity. Внутрь Receive Activity нужно вставлять наши активности, которые мы сделали в отдельной сборке. Они будут автоматически доступны на вкладке Toolbox:
image
Теперь, последовательно создавая отдельные ветви, надо расположить активности на Workflow. Далее для нужных активностей добавить переменные (внизу слева вкладка variables), а затем все это связать (подробнее смотри исходники — SeaFightService.xamlx). У Receive activity надо задать интерфейс (ServiceContractName) и название операции, а также привязать входные параметры к переменным. Не забудьте поставить галку CanCreateInstance у каждой Receive Activity. Подробнее об этом читайте на сайте workflow.
Вот как получилось у меня:
image
Теперь, когда наша бизнес-логика готова для игры, мы добавляем Service Reference в наш Silverlight проект (Add Service reference, затем выбрать Discover):
image
Теперь остается только лишь сделать наш игровой интерфейс и использовать бизнес-логику посредством вызова прокси-объекта. Вот как использовал прокси-объект я:
var proxy = ProxyReference.GetProxy();
try
{
proxy.GetGameListCompleted += new EventHandler треуг.скобкавлево GetGameListCompletedEventArgs треуг.скобкавправо (proxy_GetGameListCompleted);
proxy.GetGameListAsync(proxy);
}
catch
{
proxy.Abort();
}



А вот метод, обрабатывающий ответ WCF сервиса:

// Обновляем список доступных игр
void proxy_GetGameListCompleted(object sender, GetGameListCompletedEventArgs e)
{
var games = e.Result;
dataGridGames.ItemsSource = games;
((SeaFightServiceClient)e.UserState).CloseAsync();
}



Проект имеет 5 окон: окно создания игры, окно ожидания второго игрока, окно расстановки кораблей, окно битвы и окно результатов. Соответственно, все они есть в исходниках, и Вы можете ознакомиться с их составом более подробно. В качестве игрового поля я использовал стандартный компонент – Grid, а позиции кораблей обозначены стандартными ToggleButton с измененным свойством Content. Опять-таки, чтобы узнать, как все сделано в деталях, смотрите исходники проекта SeaFight.
Для переключения окон используется элемент PageSwitcher, который хранит в своем корневом свойстве Content текущее окно. Для переключения между окнами я использую такой вот код:

if (this.Parent is PageSwitcher)
{
PageSwitcher ps = this.Parent as PageSwitcher;
ps.Navigate(new MainPage());
}


Одним из важнейших недостатков проекта является отсутствие дуплексного режима в сетевом сервисе. Поэтому для обновления состояния используется таймер System.Windows.Threading.DispatcherTimer. Из-за этого чувствуется задержка между получением сообщений и ходами в игре. В будущем все же планируется перейти на дуплексный режим, но это непростая задача для Silverlight. Вот так выглядит окно размещения кораблей:
image

Хотелось бы отметить, что есть еще 1 вспомогательный проект: SEntities, который содержит общие классы для ядра и сильверлайт-приложения. Правильнее на будущее использовать специальный тип сборки – Silverlight Library, а не обычный Library, который есть сейчас.
В общем, на этом я заканчиваю данную статью, так как основные моменты мной описаны, а на описание отдельных функций может уйти еще по одной такой статье на каждую функцию. Поэтому за более подробными деталями (как сделать размещение элементов на форме и т.д. можете обращаться в MSDN или ко мне). Если есть желающие помочь в развитии этого проекта – пишите: squalsoft{at}mail.ru.
Tags:
Hubs:
+22
Comments 10
Comments Comments 10

Articles