Возможно вы искали: 'Air Buccaneers HD'

May 12 2025 01:27:49
  • Как сделать 8Gamers.Ru домашней страницей?
  • Игры
    • База данных по играх
    • Игровые новости
    • Игровая индустрия
    • Обзоры на игры
    • Прохождения игр
    • Гайды к играм
    • Превью о играх
    • Игровые тизеры
    • Игровые арты
    • Игровые обои
    • Игровые скриншоты
    • Игровые обложки
    • Игровые трейлеры
    • Игровое видео
    • Вышедшие игры
    • Ближайшие релизы игр
  • Кино и ТВ
    • База данных по кино
    • Статьи о кино
    • Постеры
    • Кадры из кино
    • Кино трейлеры
    • Сегодня в кино
    • Скоро в кино
  • Комиксы и манга
    • Манга по алфавиту
    • База данных по комиксах
    • Читать онлайн комиксы
    • Читать онлайн манга
    • База персонажей
  • Читы и коды
    • Чит-коды для PC игр
    • Чит-коды для консольных игр
    • Трейнеры
    • Коды Game Genie
  • Моддинг
    • Модификации
    • Карты к играм
    • Программы для моддинга
    • Статьи о моддинге
  • Геймдев
    • Всё о создании игр
    • Список движков
    • Утилиты в помощь игроделу
    • Конструкторы игр
    • Игровые движки
    • Библиотеки разработки
    • 3D-модели
    • Спрайты и тайлы
    • Музыка и звуки
    • Текстуры и фоны
  • Рецензии
    • Игры
    • Кино
    • Аниме
    • Комиксы
    • Мангу
    • Саундтреки
  • Саундтреки
    • Лирика
  • Файлы
    • Патчи к играм
    • Русификаторы к играм
    • Сохранения к играм
    • Субтитры к кино
  • Медиа
    • Видео
    • Фото
    • Аудио
    • Фан-арты
    • Косплей
    • Фото с виставок
    • Девушки из игр
    • Рисунки
    • Рисуем онлайн
    • Фотохостинг
  • Юмор
    • Анекдоты
    • Афоризмы
    • Истории
    • Стишки и эпиграммы
    • Тосты
    • Цитаты
  • Флеш
    • Азартные
    • Аркады
    • Бродилки
    • Гонки
    • Для девочек
    • Для мальчиков
    • Драки
    • Квесты
    • Леталки
    • Логические
    • Мультфильмы
    • Открытки
    • Приколы
    • Разное
    • Спорт
    • Стратегии
    • Стрелялки
Статистика

Статей: 87772
Просмотров: 96030355
Игры
Injustice:  Gods Among Us
Injustice: Gods Among Us
...
Dark Souls 2
Dark Souls 2
Dark Souls II - вторая часть самой хардкорной ролевой игры 2011-2012 года, с новым героем, сюжето...
Battlefield 4
Battlefield 4
Battlefield 4 - продолжение венценосного мультиплеер-ориентированного шутера от первого ли...
Кино
Steins;Gate
Steins;Gate
Любители японской анимации уже давно поняли ,что аниме сериалы могут дать порой гораздо больше пи...
Ку! Кин-дза-дза
Ку! Кин-дза-дза
Начинающий диджей Толик и всемирно известный виолончелист Владимир Чижов встречают на шумной моск...
Обзоры на игры
• Обзор Ibara [PCB/PS2] 18346
• Обзор The Walking ... 18789
• Обзор DMC: Devil M... 19864
• Обзор на игру Valk... 15867
• Обзор на игру Stars! 17754
• Обзор на Far Cry 3 17935
• Обзор на Resident ... 16012
• Обзор на Chivalry:... 17495
• Обзор на игру Kerb... 17970
• Обзор игры 007: Fr... 16604
Превью о играх
• Превью к игре Comp... 17946
• Превью о игре Mage... 14451
• Превью Incredible ... 14706
• Превью Firefall 13462
• Превью Dead Space 3 16325
• Превью о игре SimC... 14717
• Превью к игре Fuse 15432
• Превью Red Orche... 15532
• Превью Gothic 3 16334
• Превью Black & W... 17345
Главная » Статьи » Всё о XNA » Сетевые игры

Сетевые игры

Эта лабораторная работа посвящена созданию сетевых игр с помощью XNA.

Цель работы

  • Научиться создавать сетевые многопользовательские игры

Задачи работы

  • Изучить модели сетевого взаимодействия игр
  • Познакомиться с поддержкой сервиса Microsoft LIVE для Windows-игр
  • Ознакомиться с объектами XNA, предназначенными для организации сетевого взаимодействия игр
  • Создать сетевую игру – клон игры Pong.


Модели сетевого взаимодействия компьютерных игр

Существуют две основные модели взаимодействия сетевых игр.

Первая модель – это Peer-to-peer – то есть, архитектура, основанная на взаимодействии равноправных программ. Такая модель взаимодействия предусматривает равноправие каждой из запущенных копий игры. При подобном способе взаимодействия каждая из запущенных копий игры равноправна, она обязана отслеживать состояние других копий, отправлять каждой из них сообщения. Такая модель взаимодействия подходит лишь для игр, предусматривающих небольшое количество игроков – при росте количества лавинообразно увеличивается поток сообщений, которыми они вынуждены обмениваться для поддержания игрового процесса. Фактически, каждая из копий игры связана с каждой из других копий. Схематически модель взаимодействия peer-to-peer вы можете видеть на рис. 12.1.


Рис. 12.1. Модель взаимодействия Peer-to-Peer

Как правило, в такой модели взаимодействия одна из игр назначается хостом – именно к ней должны обратиться новые игроки для того, чтобы принять участие в игре. Однако хост не управляет обменом сообщениями между играми

Вторая модель сетевого взаимодействия игр – это модель Client/Server (Клиент/Cервер). При таком взаимодействии выделяется два вида программ. Первая – это программа-сервер, на которую ложатся все заботы по организации игры и по взаимодействию с программами-клиентами. При таком подходе клиенты обмениваются сообщениями лишь с сервером, не взаимодействия друг с другом напрямую. Этот подход позволяет создавать игры, эффективно использующие пропускную способность каналов связи и поддерживающие одновременное участие в игре множества игроков. На рис. 12.2. вы можете видеть схематически изображенную модель взаимодействия Client/Server.


Рис. 12.2. Модель взаимодействия Client/Server

Каждая из игр одноранговой архитектуры является самостоятельной единицей, содержащей в себе все необходимое для полноценной организации игрового процесса. Фактически, каждая из копий игры работает самостоятельно, отсылая другим копиям информацию о своем состоянии и получая от других игр данные об их состоянии. При клиент-серверной схеме взаимодействия возможны несколько подходов. При первом каждый клиент является полноценной программой, которая выполнят все необходимые вычисления и отсылает серверу лишь их результаты. В итоге сервер превращается в инструмент для рассылки информации о состоянии игр между подключенными к нему клиентами. Второй подход заключается в большей нагруженности сервера – так, например, все игровые вычисления могут вестись на сервере, а клиенты используются лишь для приема ввода пользователя и отправки его на сервер, а так же для визуализации принятых от сервера данных.

Возможны и другие модели организации сетевого взаимодействия игр. Например – кольцевая система обмена сообщениями или модель, предусматривающая наличие нескольких игровых серверов.

Виды сетевых игр

Сетевые игры можно подразделить на два вида. Первый вид – это пошаговые игры (Turn Based Games). Яркий пример подобных игр – шахматы, шашки, компьютерные представления настольных игр. Игрок имеет определенное время на то, чтобы принять решение об очередном действии, ходе, а другие игроки вынуждены ждать своей очереди. Такие игры хорошо переносят проблемы сетевой связи – задержка прибытия сообщения на несколько секунд не слишком испортит впечатление от неторопливого шахматного турнира.

Второй вид игр – это игры реального времени (Real Time Games). К таким играм относится, например, популярная Counter Strike. Действия игроков происходят в реальном времени – даже небольшая проблема со связью способна очень сильно помешать игровому процессу.

Многие современные игры, не поддерживающие игру по сети, предусматривают хранение результатов игр на специальных интернет-сервисах фирм-производителей игр, позволяя игрокам соревноваться друг с другом «заочно».
XNA поддерживает различные способы организации сетевого взаимодействия игр.

Сетевые сервисы XNA

Мы отметим здесь два основных вида сетевого взаимодействия игр, которые поддерживает XNA.

Первый вид – это игры, которые используют для взаимодействия сервис Microsoft LIVE. Например – одна из моделей взаимодействия через LIVE организуется с помощью сессии типа NetworkSessionType.PlayerMatch. Для того, чтобы играть в такие игры, нужно подключение к Интернету, нужно получить учетную запись на сервере LIVE. Этот вид сетевых игр позволяет объединять игроков без учета их территориальной расположенности или других подобных ограничений.

Второй вид – это игры, которые могут взаимодействовать лишь в локальной сети. Эта модель взаимодействия реализуется с помощью сетевой сессии типа NetworkSessionType.SystemLink. Для организации игры не нужно подключение к Интернету, LIVE-аккаунт. Эта модель взаимодействия хорошо подходит для простых игр, однако, если вы хотите серьезно заниматься разработкой сетевых игр на платформе XNA – ориентируйтесь на LIVE-игры.

Рассмотрим последовательность создания сетевой составляющей компьютерной игры.

Особенности организации сетевой игры

Для того чтобы создать сетевую игру, нужно выполнить следующие шаги:

 

  • Создать учетную запись игрока, войти в систему
  • Создать сетевую сессию
  • Дождаться подключения игроков
  • Начать игру

В процессе игры вам придется обновлять состояние игровых объектов, следить за действиями игроков, проверять игру на выполнение критериев окончания, а так же – выполнять другие игровые задачи.

Рассмотрим создание сетевой SystemLink-игры, которая может работать в локальной сети.

Разработка сетевой игры

Разработаем сетевую версию клона популярной игры Pong. Реализуем в нашем примере базовую функциональность сетевой игры, которая, при практическом применении, должна быть дополнена.

Создадим новый игровой проект P12_1. На рис. 12.3. вы можете видеть окно Solution Explorer для этого проекта.


Рис. 12.3. Окно Solution Explorer для проекта P12_1

Здесь мы использовали уже знакомый вам набор текстур BallandBats, содержащий текстуры для клона игры в Pong. Основная функциональность сосредоточена в классе Game1. Классы Ball и Bat используются для представления соответствующих объектов в игре.

Алгоритм работы с программой выглядит так. Сразу после запуска она запускает интерфейс для создания учетной записи игрока, после того, как игрок войдет в систему, запускается игра. После запуска программа пытается автоматически найти сетевую сессию, созданную другой аналогичной программой. Если попытка поиска не увенчалась успехом, программа самостоятельно создает сессию и ждет подключения другой программы. После подключения начинается игра.

В листинге 12.1. вы можете найти код класса Ball. Этот класс используется для хранения атрибутов мяча, а так же – содержит код для вывода объекта на экран.

Листинг 12.1. Код класса Ball
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
 
namespace P12_1
{
    //Класс мяча
    //Обычный класс, содержащий данные о мяче и процедуру визуализации
    class Ball
    {
        //Текстура
        Texture2D sprTexture;
        //Прямоугольник, ограничивающий нужную текстуру
        public Rectangle sprRectangle;
        //Позиция на экране
        public Vector2 sprPosition;
        //Скорость перемещения
        public Vector2 sprSpeed;
        //Границы экрана
        public Rectangle scrBounds;
        //Конструктор - принимает на вход объект для загрузки 
        //контента и ссылку на игру
        public Ball(ContentManager content, Game game)
        {
            //Загрузим текстуру
            sprTexture = content.Load<Texture2D>("Ballandbats");
            //Установим прямоугольник
            sprRectangle = new Rectangle(16, 203, 17, 17);
            //Установим скорость
            sprSpeed = new Vector2(-1.5f, -2.7f);
            //Вычислим границы экрана
            scrBounds = new Rectangle(0, 0,
                game.Window.ClientBounds.Width,
                game.Window.ClientBounds.Height);
            //Установим мяч в центр экрана
            sprPosition = new Vector2(scrBounds.Width / 2, scrBounds.Height / 2);
        }
        //Процедура для рисования объекта
        //Принимает на вход объект SpriteBatch
        //Используется в основной игре внутри команд Begin и End
        //в цикле вывода изображений с помощью объекта типа SpriteBatch
        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(sprTexture, sprPosition, sprRectangle, Color.White);
        }
    }
}

 

В листинге 12.2. вы можете найти код класса Bat. Он почти так же прост, как и код мяча. Единственное существенное отличие – он включает в себя проверку на столкновение с верхней и нижней границами экрана. Эта проверка происходит каждый раз после вызова процедуры вывода объекта на экран.

Листинг 12.2. Код класса Bat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
 
namespace P12_1
{
    //Класс биты
    class Bat
    {
        //Текстура
        Texture2D sprTexture;
        //Прямоугольник, ограничивающий нужную текстуру
        public Rectangle sprRectangle;
        //Позиция
        public Vector2 sprPosition;
        //Границы экрана
        Rectangle scrBounds;
        //Конструктор - принимает на вход номер игрока, объект для загрузки 
        //контента и ссылку на игру
        public Bat(int PlIndex, ContentManager content, Game game)
        {
            //Загрузим текстуру
            sprTexture = content.Load<Texture2D>("Ballandbats");
            //Если номер игрока равен нулю (то есть - это хост)
            if (PlIndex == 0)
            {
                //Установим биту слева
                sprRectangle = new Rectangle(18, 9, 17, 88);
                sprPosition = new Vector2(0, 0);
            }
            //Если номер равен 1 (это - обычный игрок)
            if (PlIndex == 1)
            {
                //Установим биту справа
                sprRectangle = new Rectangle(17, 106, 17, 88);
                sprPosition = new Vector2(game.Window.ClientBounds.Width-sprRectangle .Width, 0);
            }
            //Границы экрана
            scrBounds = new Rectangle(0, 0,
                game.Window.ClientBounds.Width,
                game.Window.ClientBounds.Height);
        }
 
        //Процедура визуализации, которую вызываем из основной программы
        public void Draw(SpriteBatch spriteBatch)
        {
            //Перед визуализацие проверяем, не вышел ли объект за пределы экрана
            //Если вышел - исправляем
            if (sprPosition.Y < scrBounds.Y) sprPosition.Y = scrBounds.Y;
            if (sprPosition.Y + sprRectangle.Height > scrBounds.Height) sprPosition.Y = scrBounds.Height - sprRectangle.Height;
            //выводим объект на экран
            spriteBatch.Draw(sprTexture, sprPosition, sprRectangle, Color.White);
        }
    }
}

Теперь рассмотрим код главного класса нашей игры. В листинге 12.3. вы можете найти код класса Game1. Именно он реализует сетевую функциональность для нашей игры. При разработке этого класса мы пользовались справочными материалами Microsoft.

Листинг 12.3. Код класса Game1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
 
namespace P12_1
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        //Для управления графическим устройством
        GraphicsDeviceManager graphics;
        //Для вывода изображений
        SpriteBatch spriteBatch;
        //Для объекта-мяча
        Ball b;
        //Для обработки состояния клавиатуры
        KeyboardState Kb;
        //Для сетевой сессии
        NetworkSession networkSession;
        //Для записи и чтения пакетов данных
        PacketWriter packetWriter;
        PacketReader packetReader;
 
 
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            //Добавляем новый GamerServiceComponent
            Components.Add(new GamerServicesComponent(this));
        }
 
        protected override void Initialize()
        {
            //Объекты для заиси и чтения данных созданы
            //с конструкторами по умолчанию
            packetWriter = new PacketWriter();
            packetReader = new PacketReader();
            base.Initialize();
        }
 
        /// 
        protected override void LoadContent()
        {
 
            spriteBatch = new SpriteBatch(GraphicsDevice);
            //Создадим новый мяч
            b = new Ball(Content, this);
        }
 
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }
 
        protected override void Update(GameTime gameTime)
        {
            //Состояние клавиатуры
            Kb = Keyboard.GetState();
            //Если сетевая сессия не создана
            if (networkSession == null)
            {
                //Если окно приложения активно
                if (IsActive)
                {
                    //Если ни один игрок не вошел в систему
                    if (Gamer.SignedInGamers.Count == 0)
                    {
                       //Если окно регистрации не видно - отобразить его
                        if (!Guide.IsVisible)
                            Guide.ShowSignIn(2, false);
                    }
                    else
                        //Если пользователь вошел в систему
                        //Запустить процедуру, которая сначала пытается
                        //найти существующую сетевую сессию
                        //если не находит - создает новую
                        TryToJoinOrCreate();
                }
            }
            else
                //Если сетевая сессия создана
                //Перейти к процедуре обработки сессии
                WorkWithSession();
 
            base.Update(gameTime);
        }
 
        //Процедура, которая пытается подключиться к существующей сессии
        //или создать новую
        void TryToJoinOrCreate()
        {
            //Выводим сообщение в заголовок окна
            this.Window.Title = "Ищу доступную сессию";
            //Начинаем поиск новой сессии типа SystemLink - такая сессия
            //позволяет создавать игры для автономных, не подключенных к Интернету,
            //локальных сетей
            using (AvailableNetworkSessionCollection availNetSessions =
                NetworkSession.Find(NetworkSessionType.SystemLink,
                2, null))
            {
                //Если ни одной сессии нет
                if (availNetSessions.Count == 0)
                {
                    this.Window.Title = "Сессия не найдена - создаю новую сессию";
                    //Создаем новую сессию
                    networkSession = NetworkSession.Create(NetworkSessionType.SystemLink,
                        1, 2);
                    //Подключаем обработчики событий
                    JoinEventhandlers();
                    this.Window.Title = "Сессия создана";
                }
               //Иначе, если сессия найдена
                else
                {
                    this.Window.Title = "Сессия найдена, присоединяюсь";
                    //Присоединяемся к ней и так же подключаем обработчики
                    networkSession = NetworkSession.Join(availNetSessions[0]);
                    JoinEventhandlers();
 
                }
            }
 
        }
        //Подключение обработчиков событий
        void JoinEventhandlers()
        {
            //Объект типа NetworkSession имеет множество событий
            //В частности, они используются для того, чтобы показать, что к игре присоединился новый пользователь
            //что игра начата, закончен. Здесь мы подключили два события
            //Одно из них происходит, когда к игре присоединяется новый игрок, подключим соответствующий обработчик
            networkSession.GamerJoined += new EventHandler<GamerJoinedEventArgs>(networkSession_GamerJoined);
            //Второе происходит после закрытия сессии
            networkSession.SessionEnded += new EventHandler<NetworkSessionEndedEventArgs>(networkSession_SessionEnded);
        }
        //Обработчик события, происходящего при присоединении нового игрока
        void networkSession_GamerJoined(object sender, GamerJoinedEventArgs e)
        {
            //Получим номер игрока
            int plNumber = networkSession.AllGamers.IndexOf(e.Gamer);
            //Запишем в поле Tag игрока, которое имеет тип Object, то есть - способно
            //принимать любые объекты, новый объект Bat. Номер игрока, который мы передали
            //объекту, используется для его установки. В нашей игре могут участвовать лишь два игрока
            //поэтому номер 0 используется для установки биты в левой части экрана, а номер 1 - 
            //в правой. Игрок, создавший сессию, занимает левую часть экрана
            e.Gamer.Tag = new Bat(plNumber, Content, this);
        }
 
        //Обработчик события, происходящего при закрытии сессии
        void networkSession_SessionEnded(object sender, NetworkSessionEndedEventArgs e)
        {
            //уничтожим сессию
            networkSession.Dispose();
            networkSession = null;
        }
 
        //Процедура обработки событий в течение сессии
        void WorkWithSession()
        {
            //Вызвать процедуру, вычисляющую новое положение игрового объекта
            //для локального игрока - в нашем случае это один игрок с номером 0
            //и записывающей данные в сетевой поток
            CalcAndWrite(networkSession.LocalGamers[0]);
            //Обновить состояние сессии
 
            networkSession.Update();
            //Если сессия оказалась уничтоженной - выйти из процедуры
            if (networkSession == null) return;
            //Прочесть сетевые данные и модифицировать состояние объектов
            ReadAndImplement(networkSession.LocalGamers[0]);
        }
        //Вычисления и передача данных в сеть
        void CalcAndWrite(LocalNetworkGamer gamer)
        {
            //Рассматривать объект, записанный в Tag текущего игрока
            //как биту - Bat
            Bat bat = gamer.Tag as Bat;
            //Модифицировать координаты в соответствии с клавиатурными командами
            //Клавиша вверх перемещает биту вверх
            if (Kb.IsKeyDown(Keys.Up))
            {
                bat.sprPosition.Y -= 3;
            }
            //Клавиша вниз - вниз
            if (Kb.IsKeyDown(Keys.Down))
            {
                bat.sprPosition.Y += 3;
            }
            //Записать положение биты в сеть
            packetWriter.Write(bat.sprPosition);
            //Если текущий игрок - хост, то есть он создал
            //сетевую сессию, на него возложим обязанности
            //вычисления позиции мяча и обработки столкновений
            if (gamer.IsHost)
            {
                //Если к игре подключено 2 пользователя
                //То есть она началась
                if (networkSession.AllGamers.Count == 2)
                {
                    //Изменить позицию мяча в соответствии с его
                    //скоростью
                    b.sprPosition += b.sprSpeed;
                    //Если вышли за пределы верхней части игрового окна
                    if (b.sprPosition.Y < b.scrBounds.Y)
                    {
                        //Вернуть объект и инвертировать скорость по Y
                        b.sprPosition.Y = b.scrBounds.Y;
                        b.sprSpeed.Y *= -1;
                    }
                    //Если пересекли нижнюю границу окна
                    //Вернуть объект и инвертировать скорость по Y
                    if (b.sprPosition.Y + b.sprRectangle.Height > b.scrBounds.Height)
                    {
                        b.sprPosition.Y = b.scrBounds.Height - b.sprRectangle.Height;
                        b.sprSpeed.Y *= -1;
                    }
                    //Получить биту для игрока №0 - она расположена слева
                    //Берем этот объект из списка всех игроков
                    bat = networkSession.AllGamers[0].Tag as Bat;
                    //Если есть столкновение с битой
                    if (b.sprPosition.X + b.sprRectangle.Width > bat.sprPosition.X &&
                    b.sprPosition.X < bat.sprPosition.X + bat.sprRectangle.Width &&
                    b.sprPosition.Y + b.sprRectangle.Height > bat.sprPosition.Y &&
                    b.sprPosition.Y < bat.sprPosition.Y + bat.sprRectangle.Height)
                    {
                        //Вернем мяч и инвертируем скорость по X
                        b.sprPosition.X = bat.sprRectangle.Width;
                        b.sprSpeed.X *= -1;
                    }
                    //Получим биту для игрока №1 - она расположена справа
                    bat = networkSession.AllGamers[1].Tag as Bat;
                    //Если есть столкновение с ней
                    if (b.sprPosition.X + b.sprRectangle.Width > bat.sprPosition.X &&
                    b.sprPosition.X < bat.sprPosition.X + bat.sprRectangle.Width &&
                    b.sprPosition.Y + b.sprRectangle.Height > bat.sprPosition.Y &&
                    b.sprPosition.Y < bat.sprPosition.Y + bat.sprRectangle.Height)
                    {
                        //Вернем мяч и инвертируем скорость по X
                        b.sprPosition.X = b.scrBounds.Width - bat.sprRectangle.Width - b.sprRectangle.Width;
                        b.sprSpeed.X *= -1;
                    }
 
                }
                //Запишем позицию мяча в сетевой поток
                packetWriter.Write(b.sprPosition);
            }
            //Отправим данные другим игрокам
            gamer.SendData(packetWriter, SendDataOptions.InOrder);
        }
        //Процедура чтения и применения данных от других объектов
        void ReadAndImplement(LocalNetworkGamer gamer)
        {
            //До тех пор, пока есть данные для чтения
            while (gamer.IsDataAvailable)
            {
                //Новый объект sender типа NetworkGamer
                //Он бует использован для хранения ссылки на объект
                //который отправил данные
                NetworkGamer sender;
 
                // Прочесть данные
                gamer.ReceiveData(packetReader, out sender);
 
                //Если данные отправлены не локальным игроком - то есть - 
                //пришли к нам от одного из сетевых игроков (в нашем случае возможно наличие лишь одного
                //такого игрока
                if (!sender.IsLocal)
                {
 
                    //Получить объект bat из поля Tag игрока, отправившего данные
                    Bat bat = sender.Tag as Bat;
                    //Записать прочитанные данные в качестве позиции этого объекта
                    bat.sprPosition = packetReader.ReadVector2();
                    //Если отправитель данных - хост - дополнительно установить
                    //позицию мяча, прочитав данные из потока
                    //Таким образом хост всегда пишет в поток два фрагмента данных
                    //и если другой объект читает данные хоста - он так же
                    //воспринимает два фрагмента
                    if (sender.IsHost) b.sprPosition = packetReader.ReadVector2();
                }
            }
        }
 
        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
            //Начало вывода спрайтов
            spriteBatch.Begin();
            //Если создана сетевая сессия и количество игроков равно 2
            //То есть - выполнены условия для начала игры
            if (networkSession!=null && networkSession .AllGamers .Count==2)
            {
                //Для каждого игрока из всех игроков, имеющих отношение к данной сессии
                foreach (NetworkGamer gamer in networkSession.AllGamers)
                {
                    //Получить объект bat для текущего игрока
                    Bat bat = gamer.Tag as Bat;
 
                    //Вывести объект bat
                    bat.Draw(spriteBatch);
                    //Вывести мяч
                    b.Draw(spriteBatch);
                }
            }
            //Завершить вывод объектов
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

 

На рис. 12.4. вы можете видеть экран выбора игрока. Мы зарегистрировались как Player1.


Рис. 12.4. Выбор игрока

На рис. 12.5 вы можете видеть игровой экран после подключения программы к уже созданной сессии.


Рис. 12.5. Игровой экран проекта P12_1

Вопросы

1) Что характерно для сетевой архитектуры Per-To-Peer?

  • a. Выделенная программа, которая управляет игрой
  • b. Равноправие запущенных экземпляров игры – если текущий хост оказался неработоспособным – одна из запущенных копий сможет сыграть его роль
  • c. Невозможность работы в глобальных сетях
  • d. Невозможность работы в локальных сетях

2) Каков основной недостаток архитектуры Peer-To-Peer?

  • a. Невозможность работы в глобальных сетях
  • b. Невозможность работы в локальных сетях
  • c. Сложность реализации
  • d. Быстрый рост нагрузки на системные ресурсы при увеличении количества игроков

3) Какие функции выполняет программа-сервер в клиент-серверной архитектуре?

  • a. Она отвечает за загрузку графических ресурсов
  • b. Она отвечает за организацию игры, за взаимодействие с программами-клиентами
  • c. Она используется непосредственно для игры

4) Какие функции выполняет программа-клиент в клиент-серверной архитектуре

  • a. Она отвечает за загрузку графических ресурсов
  • b. Она отвечает за организацию игры, за взаимодействие с программами-клиентами
  • c. Она используется непосредственно для игры

5) Сетевая сессия типа NetworkSessionType.SystemLink позволяет создавать игры, в которые можно играть…

  • a. Через сервис Live
  • b. По локальной сети
  • c. Через Интернет, без использования сервиса Live
1690 Прочтений •  [Сетевые игры] [08.08.2012] [Комментариев: 0]
Добавил: Ukraine Vova
Ссылки
HTML: 
[BB Url]: 
Похожие статьи
Название Добавил Добавлено
• Сетевые игры Ukraine Vova 08.08.2012
Ни одного комментария? Будешь первым :).
Пожалуйста, авторизуйтесь для добавления комментария.

Проект входит в сеть сайтов «8Gamers Network»

Все права сохранены. 8Gamers.NET © 2011 - 2025

Статьи
Рецензия на Pressure
Рецензия на Pressure
Чтобы обратить на себя внимание, начинающие маленькие разработчики, как правило, уходят в жанры, ...
Рецензия на Lost Chronicles of Zerzura
Рецензия на Lost Chron...
Игры, сделанные без любви и старания, похожи на воздушный шар – оболочка есть, а внутри пусто. Lo...
Рецензия на The Bridge
Рецензия на The Bridge
«Верх» и «низ» в The Bridge — понятия относительные. Прогуливаясь под аркой, можно запросто перей...
Рецензия на SimCity
Рецензия на SimCity
Когда месяц назад состоялся релиз SimCity, по Сети прокатилось цунами народного гнева – глупые ош...
Рецензия на Strategy & Tactics: World War 2
Рецензия на Strategy &...
Название Strategy & Tactics: World War II вряд ли кому-то знакомо. Зато одного взгляда на ее скри...
Рецензия на игру Scribblenauts Unlimited
Рецензия на игру Scrib...
По сложившейся традиции в информационной карточке игры мы приводим в пример несколько похожих игр...
Рецензия на игру Walking Dead: Survival Instinct, The
Рецензия на игру Walki...
Зомби и продукция-по-лицензии — которые и сами по себе не лучшие представители игровой биосферы —...
Обратная связь | RSS | Донейт | Статистика | Команда | Техническая поддержка