11.3 セッションへの参加
11.3.1 検索で得られたセッションに入る
Find() メソッドを使ってネットワーク上の接続可能なセッションを検索し、AvailableNetworkSession オブジェクトを得ることができれば、対象のセッションに Join() メソッドで参加できます。
public static NetworkSession Join ( AvailableNetworkSession availableSession )
availableSession パラメータには、Find() メソッドの結果から得られた接続先となる AvailableNetworkSession オブジェクトを指定します。メソッドは、接続先となる NetworkSession オブジェクトを返します。
ここで得られる NetworkSession オブジェクトは、Create() メソッドで生成した NetworkSession オブジェクトとは異なり、ホスト権限はないことに注意してください。後述するゲームの開始や終了といった、ホスト権限が必要な操作を行うと例外が発生してしまいます。
NetworkSession オブジェクトがホストであるかどうかは IsHost プロパティから調べられます。
public bool IsHost { get; }
このプロパティは、セッションがホストである場合は true を、そうでなければ false を返します。
セッションに参加しているゲーマーは AllGamers プロパティから取得できます。ここから、セッションに参加している人数や、参加ゲーマーのゲーマータグなどを取得できます。
public GamerCollection<NetworkGamer> AllGamers { get; }
このプロパティは、セッションに参加しているゲーマーのコレクションとなる GamerCollection オブジェクトを返します。このコレクションは、ネットワーク上のゲーマーを表す Microsoft.Xna.Framework.Net.NetworkGamer クラスのオブジェクトを提供します。
public class NetworkGamer : Gamer
このクラスは Gamer クラスを継承し、ネットワークで繋がっているゲーマーを表します。このクラスのオブジェクトから、セッションに参加している他のゲーマーの状態を取得できます。
例えば、対象のゲーマーがホストであるかどうかは IsHost プロパティから得られます。
public bool IsHost { get; }
ゲーマーがセッションのホストである場合は true が、そうでなければ false が返されます。
また、AllGamers プロパティが返したゲーマーのコレクションには、自分自身も含まれています。得られた NetworkGamer がローカルマシンにサインインしているゲーマーなのか、リモートのゲーマーなのかを把握するには IsLocal プロパティを使います。
public bool IsLocal { get; }
ローカルマシンにサインインしているゲーマーであれば true が、そうでなければ false が返されます。
ホストの場合は、Create() メソッドで生成した NetworkSession オブジェクトから他のプレイヤーと繋がり、それ以外のプレイヤーは Join() メソッドが返した NetworkSession オブジェクトから他のプレイヤーと繋がります。ホストも参加者も、接続後は NetworkSession オブジェクトを介してセッションに参加しているゲーマーと通信するという点は同じです。
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Net; public class Test : Game { public static void Main(string[] args) { using (Game game = new Test()) game.Run(); } private GraphicsDeviceManager graphicsDeviceManager; private NetworkSession session; private AvailableNetworkSessionCollection sessions; private SpriteBatch sprite; private SpriteFont font; private string text; public Test() { graphicsDeviceManager = new GraphicsDeviceManager(this); Components.Add(new GamerServicesComponent(this)); } protected override void LoadContent() { sprite = new SpriteBatch(GraphicsDevice); font = Content.Load<SpriteFont>("Content/TestFont"); base.LoadContent(); } protected override void Update(GameTime gameTime) { GamePadState state = GamePad.GetState(PlayerIndex.One); if (state.Buttons.Back == ButtonState.Pressed) Exit(); SignedInGamer gamer = Gamer.SignedInGamers[PlayerIndex.One]; if (gamer == null) { text = "Please sign in as player one."; if (!Guide.IsVisible) Guide.ShowSignIn(1, true); } else { if (session != null) UpdateSession(state); else if (sessions != null) UpdateFindSession(state); else UpdateMenu(state); } base.Update(gameTime); } private void UpdateMenu(GamePadState state) { text = "A BUTTON: Create a network session\n"; text += "X BUTTON: Find a network session\n\n"; if (state.Buttons.A == ButtonState.Pressed) session = NetworkSession.Create(NetworkSessionType.SystemLink, 1, 16); else if (state.Buttons.X == ButtonState.Pressed) sessions = NetworkSession.Find(NetworkSessionType.SystemLink, 1, null); } private void UpdateSession(GamePadState state) { text = "Network session is available\n"; text += "B BUTTON: Dispose a network session\n\n"; session.Update(); foreach (NetworkGamer gamer in session.AllGamers) text += gamer.Gamertag + (gamer.IsHost ? ", HOST" : "") + (gamer.IsLocal ? ", LOCAL" : "") + "\n"; if (state.Buttons.B == ButtonState.Pressed) { session.Dispose(); session = null; } } private void UpdateFindSession(GamePadState state) { text = "Network session search results\n"; text += "B BUTTON: Return to menu\n\n"; if (state.Buttons.B == ButtonState.Pressed) sessions = null; else if (sessions.Count == 0) text += "Session not found"; else { session = NetworkSession.Join(sessions[0]); sessions = null; } } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.White); sprite.Begin(); sprite.DrawString(font, text, Vector2.Zero, Color.Black); sprite.End(); base.Draw(gameTime); } }
コード1は、ゲームを起動するとセッションを作成してホストとなるか、セッションを検索して参加するかを選択します。セッションを作成するか、セッションに参加することで得られた NetworkSession から、同じセッションに参加しているゲーマーを AllGamers プロパティから取得して表示します。
UpdateMenu() メソッドは、セッションの作成や検索を行うための処理を行います。UpdateSession() メソッドでセッションに参加している状態の処理を実行し、UpdateFindSession() メソッドでセッションの検索結果を表示する処理を実行します。Update() メソッドでは session フィールドが null でなければ有効なセッションに参加していると判断し UpdateSession() メソッドを呼び出します。そうでなければ sessions フィールドが null かどうかを調べ、null でなければ UpdateFindSession() メソッドを呼び出して検索結果の処理を実行します。
検索結果をリストとして表示し、プレイヤーにどのセッションに参加するかを選択させる流れも考えられますが、このプログラムでは検索結果から得られた最初のセッションに自動的に参加するように処理しています。