问题

在你可以连接另一个玩家前,首先需要使用一个账号登录或创建一个新的账号。如果所有玩家都在相同的网络,这可以是一个离线账号,或者当你想通过Internet连接时也可以是一个在线Live账号。

在你可以访问XNA的网络功能前必须登录,它也允许其他玩家看到你的姓名和你可能提供其他信息。

注意:登录在Zune不需要。在Zune上的XNA游戏由一个SignedInPlayer开始,这个SignedInPlayer拥有你分配给Zune设备的名称。

解决方案

使用你的账号登录非常简单。你要做的就是调用Guide.ShowSignIn方法,这个方法允许用户选择一个已存在的账号或创建一个新的。

工作原理

在你可以使用XNA的网络功能前,你必须在游戏中添加GamerServicesComponent。

添加GamerServicesComponent

这个GameComponent (可参见教程1-7)保证整个网络引擎在背后以不变的时间间隔进行更新。对任何一个GameComponent,都要求在Game构造函数中加载:

public Game1()
...{
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";
    Components.Add(new GamerServicesComponent(this));
}
显示登录界面

简单的程序会在定义的两个状态中切换:SignIn和SignedIn。只要程序在SignIn状态中,登录界面就会显示给用户直到用户选择或创建一个账号。一旦选择了正确的账号,程序就会移动到SignedIn状态。

首先声明两个状态:

public enum GameState 
...{
    SignIn, 
    SignedIn
}

然后声明一个变量保存当前状态:

GameState currentGameState = GameState.SignIn;

这会让程序开始时处于SignIn状态。在更新循环中,你将检测程序位于哪个状态。如果处于SignIn状态,你想让用户选择一个账号。但是,因为用户可以选择一个账号自动登录,可能在开始GamerServicesComponent时一个账号已经登录。所以,你想检查当前登录是否还没有账号:

if (Gamer.SignedInGamers.Count < 1)
...{
    Guide.ShowSignIn(1, false);
    log.Add("Opened User SignIn Interface");
}
else
...{
    currentGameState = GameState.SignedIn;
    log.Add(Gamer.SignedInGamers[0].Gamertag + " logged in - proceed to SignedIn");
}

如果没有账号被记录,你激活登录界面,让用户可以选择或创建一个账号。一旦选择了一个账号,Gamer.SignedInGamers.Count不为0。在下一个更新过程中,当前状态会被设置为SignedIn,包含玩家名称的信息会被添加到日志中。

注意:日志的内容会在Draw方法中输出到屏幕上,可参见教程3-5学习如何将文字显示在屏幕上。

Guide.ShowSignIn方法需要两个参数。第一个参数显示可以登录多少个玩家。在Xbox 360平台上,同时最多可有4个用户,在Windows平台上被限制为只有1个。第二个参数指定是否只允许在线Live账户登录,这在使用Live服务时很有用。

注意:记住用户可以取消Guide界面,这会导致没有账号被选择。

因为同一时间无法打开Guide界面两次,在调用Guide.ShowSignIn方法前你必须检查当前Guide是否已关闭,这可以通过检查Game的IsActive属性做到,当游戏窗口是active状态,没有被最小化,Guide没有显示时这个属性才为true。

代码

整个Update过程如下所示。先检查IsActive属性,之后如果还没有用账号登录就调用Guide.SignIn方法,一旦登录为正确的账号, 状态变为SignedIn。

protected override void Update(GameTime gameTime)
...{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
        this.Exit();

    if (this.IsActive)
...    {
        switch (currentGameState)
...        {
            case GameState.SignIn:
...            {
                if (Gamer.SignedInGamers.Count < 1)
...                {
                    Guide.ShowSignIn(1, false);
                    log.Add("Opened User SignIn Interface");
                }
                else
...                {
                    currentGameState = GameState.SignedIn;
                    log.Add(Gamer.SignedInGamers[0].Gamertag + " logged in - proceed to SignedIn");
                 }
            }
            break;
            case GameState.SignedIn:
        ...    {
            }
            break;
        }
    }
    base.Update(gameTime);
}