[翻译]XNA 3.0 Game Programming Recipes之fifty-four


PS:自己翻译的,转载请著明出处

                                                                8-2 创建一个网络会话
问题
                                你想要创建一个网络会话,这样别的Xbox360控制台,Zunes,或者PCs可以找到并且加入你的会话中。
解决方案
                                一台机器首先需要去开始一个网络会话,你可以非常容易的实现它,使用NetworkSession.Create方法。这台机器,它创建一个会话将会是主机的会话。
                                在这个绘画被创建,所有的机器连接到这个会话,包括主机,通过会话可以监听任何发生的事件,例如一个玩家加入或者离开这个会话。
它如何工作的
                                你需要去包括Microsoft.XNA.Framework.Net命名空间从这节在本章的结尾的地方。通过添加下面的代码行去实现,并把它放在你代码文件的上面:
1 using Microsoft.Xna.Framework.Net;
                                在本章中,你的程序将循环通过三个自身定义的状态。正如我们前面章节所讨论的,你将会开始在SignIn状态,在这种情况下用户被询问去选择一个帐号。前面章节的这个SingedIn状态通过CreateSession会话被取代,你创建一个新的网络会话并且监听它们的事件。最终,你结束这个InSession状态。
                                开始定义这些状态:
1 public enum GameState{SignIn,CreateSession,InSession}

                                SignIn状态已经在前面的章节中讨论过了。让我们开始编写CreateSession状态。

Creating a NetWwork Session(创建一个网络会话)
                                在这种状态下,你将会创建一个新的网络会话。通过添加这个变量到你的代码中:

1 NetworkSession networkSession;
                                你可以创建一个新的网络会话并保存它在这个你刚才定义的变量中,使用这个NetworkSession.Create方法,正如这里显示的:

 

1 networkSession=NetworkSession.Create(NetworkSessionType.SystemLink,4,8);
                               这行将导致这台机器主机一个新的会话到其他可以连接的玩家。正如你看见的,这个方法期待三个参数。
                               这个第一个参数指定它应该创建的会话类型。如果所有的玩家都被连接到一个同意个机器上时,一个NetworkSessionType.Local类型的会话应该被创建,例如,四个玩家可以有它们自己的控制器连接到同一台Xbox360控制台上。
                               如果一个或者更多的玩家在不同的机器上,它被连接到同样的网络中,你可以创建一个NetworkSessionType.SystemLink类型的会话。
NetworkSessionType.PlayerMatch类型与SystemLink类型以相同的方式工作,但是它将允许用户去连接会话在因特网上,产生有用的在线服务器。在此刻,虽然,为了使用这些服务,你需要去买一个Live Gold 会员为所有的多个Xbox360控制台。
注意:因为Zune可以创建网络连接到其他的Zunes,你可以使用唯一的NetworkSessionType.Local和NetworkSessionType.SystemLink会话
类型为这个Zune.
                              第二个参数指定是否多个玩家连接到网络上的同一台机器。如果不能,你应该指定,这里每台机器只能有一个玩家。如果你想这样,例如,开始一个本地会话,你应该允许更多玩家去连接到同一台机器。
注意:一个本地玩家是一个用户在这台机器上允许它的代码。现在,XNA3.0支持唯一的一个本地玩家在每一个Windows-based机器和Zune,同时让四个玩家可以连接到一个Xbox360控制台。通过其他三个玩家连接到同样的机器上,这台四个玩家之一的玩家机器被认为是本地机器(译者:主机)
                              最后一个参数指定它能连接会话中的最大玩家数量。因为你处理多人游戏,这个数量至少是2,同时它应该等于或者小于上限,那么PC的上限是31,Xbox360的是31,Zune设备的上限是8
                              NetworkSession.Create方法有一个重载版本,它接收两个以上的参数。第一个参数指定玩家的数量,它应该保持这个变量为你的朋友。这样,只有你标记为朋友的玩家将可以加入这个会话。最后一个参数允许你去标记你的会话用一个NetworkSessionProperties对象,这样其他可以很容易的找到它。参看8-3节的列子。
注意:如果机器根本没有连接任何的网络,这个NetworkSession.Create方法将会抛出一个错误,这样你希望封装它在try-catch结构中。
                              现在,我们开始一个新的会话,你可以设置一些它的属性。一个重要的属性定义为什么会发生,如果主机退出这个会话。你可以指定XNA应该自动选择客户/同行之一通过设置这个AllowHostMigration属性为true,去成为新的主机:
1 networkSession.AllowHostMigration=true;
2 networkSession.AllowJoinInProgress=false;

                              正如你所看见的,你同样可以指定客户是否被允许加入这个会话在游戏已经开始了。
注意:应该特别注意采取主机的移植。如果任何游戏数据被专门的保存在旧的主机上,当它退出这个会话,它是非常重要的使这些数据自动转换到新的主机上。你想使至关重要的数据复制到最新的两台机器上,这样如果主机退出了,你可以复制这个数据到新的主机上。
                              因为XNA3.0,当本地玩家离开这个游戏时,本地网络会话将不会结束。相反,这个会话将持续至少还有一个玩家在这个会话中。

Hooking to the Session Events
                              现在,你的机器主持一个网络会话(主机),它将会很容易知道当其他人加入了这个会话。你可以通过挂起一个自身-定义的方法到网络会话的GamerJoined事件来实现它。只要一个玩家加入这个会话,这个会话将自动触发这个GamerJoined事件。作为一个结果,所有的方法挂起到这个将会被调用的事件。

                              这行将导致本身-定义的GamerJoinedEventHandler方法被挂起到GamerJoined的事件:
1 networkSession.GamerJoined+=GamerJoinedEventHandler;
                              在这个GamerJoinedEventHandler方法,你可以放入所有代码,它可以被执行只要一个新玩家加入了这个会话。下面的样列将会导致文本行包含玩家的姓名被打印到屏幕上:
1 void GamerJoinedEventHandler(object sender,GamerJoinedEventArgs e)
2 {
3     log.Add(e.Gamer.Gamertag+"joined the current session");
4 }
                              如同所有的事件-处理方法,这个方法将接收对象,它放出事件(在这种情况下,网络会话),以及第二个参数包含指定的信息,它来自这种类型事件。在这种情况下,GamerJoinedEventArgs包含Gamer对象对应的玩家,它刚刚加入了这个会话。
                              这个网络会话可以唤醒别的事件,你可以监听它。这里包括GamerLeft事件和GameStarted和GameEnded事件,它表明当会话从大厅转换到游戏模式(参看8-7节),以及SessionEnded和HostChanged事件。
                              SessionEnded事件被激发,当主机退出这个会话,同时AllowHostMigration被设置为false或者当主机调用这个Dispose方法在网络会话上。这个HostChanged事件被触发当主机退出这个会话,同时AllowHostMigration被设置成true。
                              下面的代码将会坚听这个GamerJoined,GamerLeft,和HostChanged事件的激发通过网络会话,并且打印一个相应的行到屏幕上:
 1 void HookSessionEvents()
 2 {
 3     log.Add("Listening for session events"); 
 4     networkSession.GamerJoined+=GamerJoinedEventHandler;
 5     networkSession.GamerLeft+=GamerLeftEventHandler;
 6     networkSession.HostChanged+=HostChangedEventHandler;
 7 }
 8 void GamerJoinedEventHandler(object sender,GamerJoinedEventArgs e)
 9 {
10      log.Add(e.Gamer.Gamertag+"joined the current session");
11 }
12 void GamerLeftEventHandler(object sender,GamerLeftEventArgs e)
13 {
14      log.Add(e.Gamer.Gamertag+"left the current session");
15 }
16 void HostChangedEventHandler(object sender,HostChangedEventArgs e)
17 {
18      log.Add("Host migration detected");
19      NetworkSession eventRaisingSession=(NetworkSession)sender;
20      if(eventRaisingSession.IsHost)
21           log.Add("This machine has become the new Host!");
22 }
                               在主机的移动的情况下,发送对象(它是你知道的一个网络会话)是首先转化为NetworkSession对象,这样你可以询问它的属性。这它们其中之一是IsHost属性,你可以使用它去检测这台机器是否成为这个会话新的主机。
                               确保你直接调用这个HookSessionEvents方法在你已经创建你的会话之后。这就是CreateSession状态在Update方法应该看起来象这样:
1 case GameState.CreateSession:
2 {
3    networkSession=NetworkSession.Create(NetworkSessionType.SystemLink,4,8);
4    networkSession.AllowHostMigration=true;
5    networkSession.AllowJoinInProgress=false;
6    log.Add("New session created");
7    HookSessionEvents();
8    currentGameState=GameState.InSession;
9 }

                               这个会话被创建,AllowHostMigration和AllowJoinInProgress值被设置,并且程序正在监听每个触发的事件通过这个会话。

Updateing the Network Session(更新网络会话)
                               一旦你连接了一个会话,你应该更新它在定期的时间内。一个明显的地方要做到这个是在你的游戏的更新循环中。现在,这是唯一的事情,它被完成在InSession状态时期:

1 case GameState.InSession:
2 {
3     newworkSession.Update();
4 }
5 break;

 

代码
                                在这里,你可以找到最终的Update方法。这个程序将开始于SignIn状态,在一个会话被创建在CreateSession状态中。程序结束在InSession状态。
 1 protected override void Update(GameTime gameTime)
 2 {
 3      if(GamePad.GetState(PlayerIndex.One).Buttons.Back==ButtonState.Pressed)
 4            this.Exit();
 5      if(this.IsActive)
 6      {
 7          switch(currentGameState)
 8          {
 9              case GameState.SignIn:
10              {
11                  if(Gamer.SignedInGamers.Count<1)
12                  {
13                         Guide.ShowSignIn(1,false);
14                         log.Add("Opened User SignIn Interface");
15                  }
16                  else
17                  {
18                         currentGameState=GameState.CreateSession;
19                         log.Add(Gamer.SignedInGamers[0].Gamertag+"logged in -proceed to CreateSession");
20                  }
21              }
22              break;
23              case GameState.CreateSession:
24              {
25                         networkSession=NetworkSession.Create(NetworkSessionType.SystemLink,4,8);
26                         networkSession.AllowHostMigration=true;
27                         networkSession.AllowJoinInProgress=false;
28                         log.Add("New session created");
29                         HookSessionEvents();
30                         currentGameState=GameState.InSession;
31              }
32              break;
33              case GameState.InSession:
34              {
35                         networkSession.Update();
36              }
37              break;
38          }
39      }
40      base.Update(gameTime);
41 }
42 
源代码:http://shiba.hpe.cn/jiaoyanzu/WULI/soft/xna.aspx?classId=4
(完)

posted on 2009-09-05 15:24  一盘散沙  阅读(216)  评论(0编辑  收藏  举报

导航