iPhone - 在线多人游戏...了解机制

发布于 2025-01-08 07:34:45 字数 2622 浏览 3 评论 0原文

我正在开发一款在线多人游戏,但我在处理 Apple 文档方面遇到了困难。 (我已经尝试过 Ray Wenderlichs 第 1 部分第 2 部分< /a>,但它们不起作用(匹配永远不会开始,因为邀请设备从未收到匹配接受)。

时创建另一个问题。

由于这个主题很大,我将创建一个问题,然后在必要 创建一个在线多人游戏 用户邀请 1 到 3 人,因此,这将是一场 2 到 4 人的比赛。它是实时的,并且用户之间传输的数据最少。

允许 1

)我做的第一件事是创建一个通知

if (self.gameCenterAvailable) {
    NSNotificationCenter *nc = 
    [NSNotificationCenter defaultCenter];
    [nc addObserver:self 
           selector:@selector(authenticationChanged) 
               name:GKPlayerAuthenticationDidChangeNotificationName 
             object:nil];

}

,让我知道通知何时发生变化。当发生这种情况时,authenticationChanged 方法将触发...这是

- (void)authenticationChanged {    

GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) {
   // Insert application-specific code here to clean up any games in progress.
   if (acceptedInvite)
    {
        GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:acceptedInvite] autorelease];
        mmvc.matchmakerDelegate = self;
        [self presentModalViewController:mmvc animated:YES];
    }
    else if (playersToInvite)
    {
        GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
        request.minPlayers = 2;
        request.maxPlayers = 4;
        request.playersToInvite = playersToInvite;

        GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
        mmvc.matchmakerDelegate = self;
        [self presentModalViewController:mmvc animated:YES];
    }
};

}

我从 Apple 获取的代码。我的问题是这样的。如果苹果说在用户通过身份验证后运行此代码,为什么它要检查邀请或用户邀请?据我所知,用户还没有被邀请。除非当时代码没有执行,对吧?当邀请完成时,它只会坐在内存中等待被调用,对吗?

如果是这种情况,我现在创建一个匹配邀请,

[self dismissModalViewControllerAnimated:NO];
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease]; 
request.minPlayers = minPlayers;     
request.maxPlayers = maxPlayers;
request.playersToInvite = self.pendingPlayersToInvite;

GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];    
mmvc.matchmakerDelegate = self;

[self presentModalViewController:mmvc animated:YES];

我选择邀请的所有用户都会看到一个窗口。假设第一个点击邀请上的“接受”。我的应用程序将触发哪种方法,如何获取用户身份以及如何知道是否所有用户都接受?

谢谢。

I am developing an online multiplayer game, but I am struggling with Apple documentation. (I have tried these tutorials by Ray Wenderlichs Part 1 and part 2, but they are not working (match never starts because inviting device never receives the match acceptance).

As this topic is vast, I will be creating a single question, then moving to create another question on SO if necessary.

I want to create an online multiplayer game that will let a user to invite from 1 to 3 people. So, it would be a 2 to 4 people match. The game is not turned based. It is live and the data to be transferred between users is minimum.

Lets start with the basic stuff.

1) the first thing I do is create a notification

if (self.gameCenterAvailable) {
    NSNotificationCenter *nc = 
    [NSNotificationCenter defaultCenter];
    [nc addObserver:self 
           selector:@selector(authenticationChanged) 
               name:GKPlayerAuthenticationDidChangeNotificationName 
             object:nil];

}

to let me know when the notification changes. When this happens, authenticationChanged method will fire... here it is

- (void)authenticationChanged {    

GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) {
   // Insert application-specific code here to clean up any games in progress.
   if (acceptedInvite)
    {
        GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:acceptedInvite] autorelease];
        mmvc.matchmakerDelegate = self;
        [self presentModalViewController:mmvc animated:YES];
    }
    else if (playersToInvite)
    {
        GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
        request.minPlayers = 2;
        request.maxPlayers = 4;
        request.playersToInvite = playersToInvite;

        GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
        mmvc.matchmakerDelegate = self;
        [self presentModalViewController:mmvc animated:YES];
    }
};

}

I grabbed this code from Apple. My question here is this. If Apple say to run this code after the user is authenticated why it is checking for invitation or users to invite? As far as I see, users were not invited yet. Unless the code is not executed at that time, right? It will just sit in memory waiting to be called, WHEN the invitation is done, correct?

If this is the case, I now create an invitation for a match doing

[self dismissModalViewControllerAnimated:NO];
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease]; 
request.minPlayers = minPlayers;     
request.maxPlayers = maxPlayers;
request.playersToInvite = self.pendingPlayersToInvite;

GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];    
mmvc.matchmakerDelegate = self;

[self presentModalViewController:mmvc animated:YES];

A window will be present to all users I choose to invite. Suppose the first one taps ACCEPT on the invitation. Which method will be fired on my app, how do I get the user identity and how do I know if all users accepted?

thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

于我来说 2025-01-15 07:34:46

首先请注意,沙盒环境中的邀请往往会不稳定,因此我建议您首先让所有玩家搜索可用的比赛。代码如下:

GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = minPlayers;
request.maxPlayers = maxPlayers;

[[GKMatchmaker sharedMatchmaker] findMatchForRequest:request
                               withCompletionHandler:^(GKMatch *match, NSError *error) {
                                     if (error || !match) {
                                       // handle the error
                                     }
                                     else if (match != nil){
                                       // match found
                                     }}];
  }

然后您必须实现协议GKMatchDelegate。那里有一个方法,将为加入比赛的每个玩家以及与比赛断开连接的每个玩家调用(在这个方法中,您可以找到带有玩家 ID 的用户身份):

- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state {
    switch (state){
      case GKPlayerStateConnected: 
        if (match.expectedPlayerCount == 0) {
          // start the match
        }
        break;
      case GKPlayerStateDisconnected:
        // remove the player from the match, notify other players, etc
        break;
    } 
}

关于您的第一个问题,上的代码>authenticationChanged 仅注册这些方法的处理程序,这意味着通知到达时将调用的代码。

编辑:关于您评论中的问题,如果比赛是通过邀请开始的,则开始比赛的用户必须等到所有邀请都被接受,或者取消其中一些邀请,然后按开始比赛(或类似的操作)邀请屏幕。在这种情况下,一旦接受邀请的所有玩家都连接到比赛,就会满足 match.expectedPlayerCount == 0 条件。
如果比赛是由 AutoMatch 开始的,则 Game Center 会执行以下操作:一旦发现 minPlayers 等待开始比赛,它会将他们分配给一场比赛,然后再等待几秒钟,看看是否可以填充剩余的插槽。在某个时刻,它将以 minPlayers 和 maxPlayers 之间一定数量的玩家开始比赛。那么只有当所有玩家都有效加入比赛时,条件 match.expectedPlayerCount == 0 才会满足,但请注意,当决定开始比赛时,该比赛的预期玩家数量已经由游戏中心确定。

First of all please be aware that invitations on the Sandbox enviroment tend to work erratically, so I suggest you start by having all players search for an available match. The code would be something like this:

GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = minPlayers;
request.maxPlayers = maxPlayers;

[[GKMatchmaker sharedMatchmaker] findMatchForRequest:request
                               withCompletionHandler:^(GKMatch *match, NSError *error) {
                                     if (error || !match) {
                                       // handle the error
                                     }
                                     else if (match != nil){
                                       // match found
                                     }}];
  }

Then you have to implement the protocol GKMatchDelegate. There's a method there that will be invoked for each player that joins the match and for each player that gets disconnected from it (on this method you can find out the user identity with its playerID):

- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state {
    switch (state){
      case GKPlayerStateConnected: 
        if (match.expectedPlayerCount == 0) {
          // start the match
        }
        break;
      case GKPlayerStateDisconnected:
        // remove the player from the match, notify other players, etc
        break;
    } 
}

Regarding your first question, the code on authenticationChanged is only registering the handlers for those methods, meaning the code that will be invoked when the notifications arrive.

EDIT: Regarding the question on your comment, if the match was started by invitations, the user that started the match has to wait until all invitations are accepted, or cancel some of them and then press Start Match (or something like that) on the Invite Screen. In this scenario the match.expectedPlayerCount == 0 condition will be satisfied once all the players that accepted the invites are connected to the match.
If the match was started by AutoMatch then Game Center does the following: once it finds minPlayers waiting to start a match it will assign them to a match and then wait a few more seconds to see if it can fill the remaining slots. At some point it will start the match with a certain number of players between minPlayers and maxPlayers. Then the condition match.expectedPlayerCount == 0 will be satisfied only once all the players have effectively join the match, but note that when the decision was taken to start a match the number of players expected for that match is already determined by Game Center.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文