游戏邦在:
杂志专栏:
gamerboom.com订阅到鲜果订阅到抓虾google reader订阅到有道订阅到QQ邮箱订阅到帮看

分享制作异步多人游戏的方法和经验(4)

发布时间:2013-12-28 12:06:41 Tags:,,,

作者:Ross Przybylski

多人游戏成功的关键在于拥有大量一起玩游戏的用户群。但如果一开始你并没有什么用户基础,又该如何集结大量玩家呢?移除“必须在线玩游戏”这个条件。异步匹配功能有助于促进玩家参与多人游戏,即使他们并不在线!随机匹配方式则可让玩家遇到新人并结识新友,邀请系统则有助于玩家发展这些友情,并创造传播游戏的热情。本文将说明如何使用游戏服务器和数据库来管理创造和加入多人游戏的过程。(请点击此处阅读本文第12、3篇

本文将说明:

1.如何创造一个直观的多人模式界面

2.如何设置随机玩家的异步多人模式匹配

3.如何设计异步游戏邀请系统

4.如何设计好友管理系统,以便玩家邀请对方参与游戏(即使对方并不在线)

要求

*必备知识

开发回合制游戏的经验

熟悉ActionScript 3.0

已经看过本系列第2、3篇文章

*必需产品

Flash Professional

Smart Fox Server Pro

MySQL Database

*用户级别

高级

创造直观的多人体验

用户体验是创造异步多人游戏最重要的部分。无论你的游戏有多棒,如果它不能立即清晰地让玩家知道如何设置游戏,那就一定会流失用户。

在《Hero Mages》最初的即时多人模式部署中,用户可以登录和立即进入聊天大厅,并同其他玩家交流、创造游戏,访问系统中的其他模块(例如积分排行榜和地图编辑器)。该系统模拟了类似《暗黑破坏神》、《星际争霸》等游戏的原版Battle.net的多人门户设计。硬核游戏玩家通常很熟悉这种设置,但许多休闲玩家却会对此不知所措。

学习案例

确定游戏界面如何运行,以及设计有效而直观的布局确实是个大挑战。最有效的方法之一就是探索其他游戏如何处理这个问题,然后在原先的部署基础上再进行优化和提升。

《Hero Academy》是一款拥有直观用户界面的成功异步多人游戏。多人模式会直接启动玩家的游戏列表,以便他们开始新的配对或者继续玩他们已经开始的游戏。为了联系其他玩家,你的游戏屏幕上要有三个选项:一个是通过搜索邀请玩家,一个是找到随机对手,一个是通过Facebook邀请好友。《Hero Academy》的社交媒体绑定是一个更便于邀请好友的重要功能。最后,《Hero Academy》的随机匹配屏幕也允许玩家去设置他们的团队并找到对手。注意要妥善设置“购买”按钮,以便何促销IAP内容。

注:本文并非旨在探讨如何绑定Facebook功能,但我会说明你设计自己的游戏内好友列表(针对那些并不使用Facebook的玩家)的过程。

HeroAcademy_Multiplayer(from indieflashblog)

《Hero Academy》的多人模式始于游戏列表(from indieflashblog)

HeroAcademy_NewGame(from indieflashblog)

在《Hero Academy》中创造一个新的多人游戏(from indieflashblog)

HeroAcademy_Purchase(from indieflashblog)

(from indieflashblog)

《Hero Mages》功能的多人模式界面具有一个直观的通道屏幕,允许玩家访问该应用所有可用的功能,其中包括创造新游戏、加载和继续玩当前游戏,查看积分排行榜,设计定制地图等功能。这其中还包含经典的在线聊天大厅界面,玩家可以从右上方的图标进入该界面。

 

《Hero Mages》支持即时多人和异步多人模式,它与设计一个支持玩家不同选项的新游戏创造屏幕密切相关。我在《Hero Academy》中添加了直接从英雄选择画购买扩展内容的功能。但这里存在一些微妙的不同之处。“购买”标签并不出现于各个角色之上,而是出现一个将你引 向具有不同产品的新扩展画面的“购买”按钮。这种设置的首要原因是角色需要成套购买。第二个原因是将英雄直接“锁定”在列表中,许多原来的玩家就会觉得自 己购买应用时没有“获得完整的游戏”。这种分离法能够更好地将新角色区分出来,让玩家看到新角色是扩展内容(而不是核心套件)。

HeroMages_Multiplayer(from indieflashblog)

《Hero Mages》中的多人模式门关(from indieflashblog)

HeroMages_NewGame(from indieflashblog)

在《Hero Mages》中创造新多人模式游戏(from indieflashblog)

HeroMages_Purchase(from indieflashblog)

在创建帮派的画面中添加购买角色扩展内容的功能(from indieflashblog)

最后,《Hero Mages》的邀请系统与《Hero Academy》不同,它需要独立的画面。玩家可以邀请多达7名的好友加入游戏。《Hero Academy》“搜索好友”功能的一个弱点在于,如果你的好友不在Facebook上,那你每次想邀请他们玩游戏时都需要输入对方的用户名。而《Hero Mages》则在你邀请好友加入游戏时创建了游戏内好友列表,从而改进了这一系统。我稍后会说明这个系统的运行方式。

 

HeroMages_InviteSetup(from indieflashblog)

你可以邀请多达7位好友加入《Hero Mages》(from indieflashblog)

HeroMages_Invite2(from indieflashblog)

HeroMages_Invite2(from indieflashblog)

(在邀请好友时,你可以从一个下拉菜单中选择好友,该菜单还提供了添加还不是好友的玩家选项)

如何加入游戏?

注意以上所示的两个界面风格都不包包含“加入游戏”按钮。随着游戏创造的推进,人们该如何联系上对方?答案就是由屏幕背后的服务器来处理人们加入游戏的问题。当玩家“创造”一个配对时,他们实际上是向服务器发送了与一名玩家联系的请求。服务器会根据其他玩家是否在等待的情况,将这一请求存储为新游戏记录或者以已在排队的现成游戏记录连接他们的游戏参数选择。系统不应令玩家为加入游戏的任务而操心,因为这会增加游戏体验的复杂性。除非你的游戏还支持实时多人模式,并且你也允许用户在游戏中途过程中加入。《Hero Mages》的玩家可以通过主聊天大厅,点击右侧列表的即时游戏即可加入。

值得注意的是,《Hero Mages》还会在轮到玩家的回合时,将异步玩家引进即时游戏回合中。如果此时玩家正在异步情况下通过游戏列表玩对手载入的游戏,那么他们就会自动加入即时游戏回合中。

总结有效的多人界面特点

正如上图所示,有效的多人游戏界面包含以下关键元素:

1.访问多人模式功能的门关屏幕

2.创造新游戏的明显而直观的方法

3.邀请好友的有效系统

设置一个随机的1v1配对

正如上文所述,有效的异步多人界面可以通过配对消除加入游戏的问题。创造两名玩家之间随机的1v1匹配模式的最基本方法就是在首次发出配对请求时创造一个新游戏纪录。之后,当玩家再次请求配对时,就以先存的会话将他们连接起来。

当玩家开始一个随机对手配对时,会有以下两者中的一种情况:

1.现成的配对不可行,所以服务器要创造一个新配对,并将其存储在数据库中。用户会进入一个“寻找玩家”的屏幕。他们可能会继续等待一位对手加入,或者取消等待。即使他们取消了等待,其请求仍然会保存在服务器中。这样,当有对手加入时,系统就会向其发送通知,他们就可以准备玩游戏了。

2.现成的配对是可行的,所以服务器完成了一个带有用户名参数的待定配对,并向他们发送游戏记录。服务器应分配“加入的”玩家开始第一回合。这样他们在游戏加载完成时就可以立即开始玩游戏。

HeroMages_FindingPlayer(from indieflashblog)

HeroMages_FindingPlayer(from indieflashblog)

(当玩家进入这一界面时,系统就创造了一个新的游戏记录。玩家可以等待与一名对手建立联系或者选择取消!)

HeroMages_SearchingForOpponentPrompt(from indieflashblog)

HeroMages_SearchingForOpponentPrompt(from indieflashblog)

(该系统会在数据库中建立配对请求,并在找到一名对手时通知玩家,这样他们就无需继续等待。)

HeroMages_SearchingForOpponent(from indieflashblog)

HeroMages_SearchingForOpponent(from indieflashblog)

(新记录出现在玩家游戏列表中,代表该系统正在搜索一名对手。)

如何运行

本文并不讨论《Hero Mages》编程随机配对模式的代码执行方法,但会完整地概括该流程的要点。使用本文所列要点、编写客户端的技术,以及前两篇文章中所提到的服务器端代码,将有助于你获得编写任何异步多人游戏的切入点。

1.当用户选择“随机匹配”按钮时,就会触发“sendMatchMakeCommand”,它会在客户端指导游戏创造类去创建一个新的游戏数据结构,并向服务器发送一个请求。

2.在服务器端,查看是否还有尚未配对的游戏正在排队等待。

A 如果当前没有尚未配对的游戏,在服务器创造一个拥有-1状态的新游戏记录,显示游戏正在等待一个对手。向客户端发回一个请求,显示未发现配对。

B 如果当前存在未配对游戏,载入该游戏记录的数据,并在回复中将其发回客户端。

3.在客户端

A 如果没找到配对,显示“寻找玩家”屏幕。如果玩家取消了,显示提示“配对就绪时我们会通知您”。

B 如果找到配对了,创造一个新游戏数据,整合玩家游戏参数(例如英雄选择)与配对玩家的当前游戏设置数据,并将响应发回到服务器。

4.在服务器端

A 为配对玩家更新具有新记录的游戏成绩表

B 更新具有新游戏设置数据的游戏记录

C 返回响应命令以载入游戏(就像第3篇文章中的载入游戏方式,只是这里会有一个额外的已包含配对游戏的标识)

5.在客户端

A 载入游戏数据并开始游戏。配对玩家可以立即开始玩游戏。

B 向服务器发送响应提示游戏已经配对

6.在服务器端,查看原来的配对创造者是否在线。如果在线,向其发送应用内部通知,告知配对已就绪。如果不在线,就发送推送通知或电子邮件。如果玩家仍然处于“寻找玩家”屏幕,我们就可以将他们与对手连接到即时游戏会话中。

随机异步游戏很适合1发配对,但如果你想同2人以上的玩家一起游戏又该如何呢?也许你可以设置一个更大的随机游戏,但这却存在可能对异步游戏产生危害的问题。例如,假如你玩随机的PvP游戏,而你的队友却打算退出游戏了该怎么办?此外还要考虑到越多玩家参与一款游戏,轮到每位玩家的时间就越长。如果是随机玩家,大家就无法联系对方,告诉他“嘿,轮到你了,让我们完成这个游戏吧!”这正是创造与好友绑定的游戏邀请系统的好处。这样你就知道和你一起玩的人可以看到游戏设置,以且能够一起完成游戏会话。

设计异步游戏邀请系统

1.游戏组织者启动一个新游戏创造屏幕,并且能够分配所有的游戏选项。这包括选择地图、游戏目标、组队以及增加电脑对手。游戏屏幕应该包括针对每位玩家(人类或者电脑)的可增加单元。

2.游戏主持人可以使用玩家选择下拉菜单并选择“邀请好友”来邀请玩家。这里的邀请仅局限于玩家好友,因为玩家不可以向那些无意玩多人游戏的随机玩家发送干扰性的邀请。

3.当所有的选项都设置和分配好时,游戏组织者可以点击“发送邀请”按钮。这可以向服务器发送包含游戏设置数据,以及所有参与玩家的ID这一信息。

4.在服务器端,使用本系列第2篇中介绍的相同功能创造一个新游戏记录,但这里有两个不同之处:

A 游戏状态存储为-2以指示游戏邀请接受情况仍然待定

B hm_gameresults表格应该进行调整以便纳入存储玩家邀请接受状态的新参数以及定制游戏参数。

5.当游戏数据中的服务器创造好游戏记录时,它就会像其他游戏一样出现在邀请玩家的游戏列表。但当玩家选择它时,它不会启动游戏,而是载入游戏当前参数返回游戏创造屏幕。此时玩家可以选择他们的英雄,并选择接受或拒绝邀请。

6.如果玩家拒绝邀请,游戏状态就会设置为-3,或者邀请被拒绝。游戏就会向所有被邀请玩家显示为完成状态,并且不再向其开放。

7.如果玩家接受邀请,系统就会呼叫服务器将该名玩家的接受状态设置为true。

8.在客户端,游戏记录界面应该破译被接受的响应,并在游戏记录绘制恰当的标记。例如,将那些已被邀请但并未回应的玩家显示为信封图标。而那些接受邀请者则显示为绿色的打勾符号,拒绝进显示为红色的打叉符号。

9.当最后一名玩家接受游戏邀请时,该服务器就会分配游戏数据以便合并所有的新玩家参数。如果接受邀请的玩家积极应战,它就会发送一个启动游戏的信号,让他们各自开始游戏。否则,它就会发送通知,指出哪位玩家先开局。

游戏成绩表的附件

回忆本系列第2篇中提到的hm_gamersulfts表格。这个表格用于存储与玩家相关的数据,其中包括玩家输赢结果,以及他们见证的最后一个游戏命令指数(用于查看游戏动画重播)。对于邀请系统来说,我们需要额外的数值来追踪邀请响应,以及任何用于定制玩家团队或角色选择的参数。

table 1(from indieflashblog)

table 1(from indieflashblog)

记住,游戏邀请只是简单地创造一个会出现在玩家游戏列表的新游戏记录。唯一的区别在于除非所有玩家都接受邀请,该游戏状态为-2,或者所有玩家的接受情况仍然待定。我们不想在游戏数据本身中存储玩家准备状态,因为两名玩家在同一时间接受邀请,就会覆盖另一者的接受状态。使用每位玩家各自的游戏成绩记录,就可以让每位玩家修改自己的状态。只有当最后一名玩家接受邀请时,我们才能重写游戏数据以纳入该玩家的所有游戏设置信息(类似于以上部分中提到的合并配对的随机玩家)。

更深的设计考虑

游戏邀请发送出去后,如果玩家不回应怎么办?

游戏邀请的响应方式与游戏记录一样。它们会与玩家正在玩的游戏或已经完成的游戏一样出现在游戏列表。其区别就在于,游戏邀请的状态标识是-2,在游戏列表中的标注是“邀请待定”。

HeroMages_PendingInvite(from indieflashblog)

HeroMages_PendingInvite(from indieflashblog)

(邀请待定的游戏记录使用符号来指示哪位玩家已经接受邀请)

注意这些图标是用于代表游戏邀请状态。那些已被邀请但并未回应的玩家显示为信封图标。而那些接受邀请者则显示为绿色的打勾符号,拒绝进显示为红色的打叉符号。

要注意保持游戏列表的整洁,以确保玩家返回应用时很看到清晰的“任务”集合。

之前文章的游戏列表分类算法运行方法如下:

1.玩家需要回应邀请的游戏处于最高优先权,因为游戏只有在所有玩家都接受的状态下才能开始。它们要在游戏列表中居首。

2.轮到玩家出击的游戏处于第二优先权,因为如果玩家不完成自己的回合,这些游戏就无法取得进展。这些记录要按照日期第二分类条件显示在列表中。

3.排在第三位的是正在进行中的游戏或者等待其他玩家接受邀请的游戏,它们同样依照记录中最后一次活动的时期/时间进行分类。

4.最后是已经完成的游戏和拒绝的邀请,同样以时间分类。

那些尚未得到响应的邀请仍会显示在玩家的游戏列表中,等待其他玩家的操作(类似于游戏等待对手的回合)。玩家可以选择“放弃”3天后仍未执行自己这一回合的对手。在游戏开始之前的任何时间,任何玩家都可以更改对游戏邀请的接受状态,例如将接受改为拒绝。这样会让游戏显示“邀请被拒绝”的状态。游戏就会显示为完成,并且不会再影响玩家状态。

当游戏准备开始时,谁先下手?

基于邀请的游戏参与玩家可能多达8人。这里不建议由最后进来的玩家先开始,而应该遵循最初游戏设置所计算出来找随机回合顺序。系统应该在游戏开始时向首个玩家发送执行操作的通知。当游戏开始时,游戏状态就会更改为“游戏正在进行中”,玩家就会看到游戏列表中的游戏记录更新。

什么机制可以阻止玩家发送不受欢迎的邀请?

玩家可能使用积分排行榜作为查看最高排名的玩家是谁,并向对方提交挑战请求,以期赢得更高的点数。但这有可能让热门玩家受到干扰,《Hero Mages》就要求玩家只能邀请好友,而不是任何玩家。这有助于杜绝不请自来的游戏邀请,保持游戏列表的整洁性。

与此同时,系统也不能限制玩家在游戏中发展友谊。为此,《Hero Mages》允许你通过游戏邀请来请求新好友。当添加一名新好友时,玩家就可以向其发送游戏邀请。如果该玩家接受游戏邀请,他们就会自动成为游戏组织者的好友。如果他们拒绝游戏邀请,这种友情状态仍会处于待定状态,直到他们接受或者取消邀请为者。我们将在下一个环节中介绍创造游戏内好友系统的过程。

创造游戏内好友系统

像Facebook这类社交网站是将玩家与现成的好友连接起来的优秀解决方法,但仅仅依赖这些网站却可能疏离那些并不使用社交媒体或者不喜欢让你的游戏获取其社交媒体帐号的用户。

推荐使用游戏内好友系统的原因如下:

1.你可以完全控制如何建立游戏内的友谊关系,它具有更高的灵活性,更便于在游戏内部社区中进行病毒扩散。

2.玩家的友谊独立于社交网络,所以无论你的用户是否在Facebook或其他社交网站上,你都可以创建玩家社区。

3.但仍然可以增加绑定社交媒体的选项,以便强化你的游戏社区。

这一部分描述的是设计游戏内好友系统,以及将其同游戏界面和邀请系统绑定,以便促进游戏玩家社区发展的过程。

好友表格

创造好友系统的第一步是创建一个新的数据库表格。以下就是《Hero Mages》的标准惯例,我使用的标识符是 “hm_friends”。该表格应该包括以下属性:

table 2(from indieflashblog)

table 2(from indieflashblog)

客户端好友列表UI

为了创造新的好友关系,客户端将需要一些额外的用户界面组件设置,以便向服务器发送一个新好友请求。一个重要的问题就是:“玩家如何在游戏中设置友情?”你的好友系统越直观,玩家就越有可能在游戏中建立友情,强化游戏的玩家社区和长期可行性。

《Hero Mages》中的玩家可以通过3种方式建立友情:

1.打开另一玩家的资料,选择“添加好友”按钮。玩玩可以通过在线聊天室获取对方资料、积分排行榜,并在游戏中的玩家列表中选择该玩家名称。

2.使用“好友管理”屏幕(通过多人模式门关进入)并寻找玩家的用户名。

3.当设置新游戏邀请时选择“添加好友”。可通过好友管理选项2执行这一操作,之后返回游戏邀请屏幕,允许玩家快速邀请新好友加入游戏。

HeroMages_StatCard(from indieflashblog)

玩家可以通过玩家统计卡添加好友(from indieflashblog)

HeroMages_FriendList(from indieflashblog)

可以通过好友管理屏幕添加和移除好友(from indieflashblog)

HeroMages_AddFriendViaInvite(from indieflashblog)

还可以在设置定制游戏邀请时添加好友(from indieflashblog)

添加好友

客户端将以既定的合适UI,向服务器发送一个好友请求,其中包含发送请求的成员ID,以及他们想添加的好友ID。

在服务器端会发生以下情况:

1.首先查看是否已存在好友关系。

sql = “SELECT * FROM hm_friends WHERE ID_MEMBER = “+params.hmId+” AND ID_FRIEND = “+params.fId;

2.根据查询是否回馈结果,创造一个新的友情记录或更新当前的友情记录状态。

A 如果查询没有结果,说明不存在好友关系,就要创造新记录:

sql = “INSERT into hm_friends (ID_MEMBER, ID_FRIEND, accepted) VALUES (“+params.hmId+”, “+params.fId+”, 1) , (“+params.fId+”, “+params.hmId+”, -1)”;

B 否则就是存在好友关系,更新好友关系的状态:

sql = “UPDATE hm_friends set accepted = 1 WHERE ID_MEMBER = “+params.hmId+” and ID_FRIEND = “+params.fId;

3.向客户端发送一个包含玩家更新好友列表的回复。该列表包括名称、ID、虚拟角色,以及玩家好友的友情状态。

值得注意的是,每个好友关系是由hm_friends表格中的两个记录所定义。在各个好友关系中,玩家将具有一个由ID_MEMBER存储他们自己ID的记录,以及另一个在ID_FRIEND中存储好友ID的记录。这两条记录都很重要,这样玩家就可以在无需创建/删除额外记录的情况下添加和移除好友。

遵循这一做法的原因有三:

1.保持追踪已存在的好友关系,确保玩家无法向不明确的对象发送好友请求。当对方拒绝好友请求时,“接受”属性就会设置为0,这样该用户就不会再出现额外的好友请求。只有在该玩家添加了最初发送请求者为好友时,两者才能建立好友关系。

2.保持追踪已存在的好友关系,以便程序查看“sentGameInvite”属性。这一属性存储了游戏是否向这名玩家发送了邀请的情况。如果这一数值标识为true,那么游戏就不允许玩家再向未接受邀请的用户发送干扰性的邀请信息。

3.最重要的是,确认好友关系生效需要这两条记录。可以将该系统想象成双方握手。发送邀请的玩家会自动将其“接受”标记为true,而获得邀请的玩家则将其“接受”标记为-1(未决定),直到他们决定接受或拒绝为止。

移除好友

以这一设置移除好友很容易:简单地将将玩家的“接受”状态更新为0以移除好友。这要使用到以下陈述:

sql =  “UPDATE hm_friends set accepted = 0 WHERE ID_MEMBER = “+params.hmId+” and ID_FRIEND = “+params.fId;

获取好友列表

好友系统会集合在一起,通过这种服务器端的MySAL陈述将好友列表返回客户端的玩家。以下是应部署于服务器端代码的 “getFriendsList”函数例子:

//CODE EXAMPLE FRIEND LIST
function getFriendsList(hmId){//PASS THE ID OF THE PLAYER WHOSE FRIEND LIST WE ARE RETURNING
//STEP 1: Generate friends list query results by joining tables with pertinent data together
sql = “SELECT * FROM (\r”;
sql +=  “SELECT s.memberName as friendName, avatar, m.ID_FRIEND as fId, f.accepted as friendAccept, m.accepted as myAccept, m.sentGameInvite as g FROM hm_friends m\r”
sql += “JOIN hm_friends f ON f.ID_MEMBER = m.ID_FRIEND AND m.ID_MEMBER = f.ID_FRIEND\r”
sql += “JOIN smf_members s on m.ID_FRIEND = s.ID_MEMBER\r”
sql += “WHERE m.ID_MEMBER = “+hmId+” and f.accepted != 0 and m.accepted != 0″;
sql += “) as x\r”;
sql += “ORDER BY myAccept, friendAccept, friendName”;

//STEP 2: Populate the results into an array of objects that can be populated into a list component by client
var queryRes = dbase.executeQuery(sql);
var friendsList = [];
for(var i = 0; i < queryRes.size(); i++){
var tempRow = queryRes.get(i)
var row = new Object()
row.n          = tempRow.getItem(“friendName”)
row.a          = tempRow.getItem(“avatar”);
row.fId        = tempRow.getItem(“fId”);
row.g          = tempRow.getItem(“g”);

//STEP 3: Set the status of the player based on query results
if(tempRow.getItem(“myAccept”) == -1){
row.s = -2;    //This player has requested me as a friend
}
else if(tempRow.getItem(“friendAccept”) == -1){
row.s = -1;    //I’ve requested this player as a friend and am waiting response
}
else{
row.s = 1;     //We’re friends
}
friendsList.push(row);
}
return friendsList;
}

处理客户端的服务器响应

同之前的例子一样,最后一步就是处理客户端的服务器响应。最佳做法是在一个普遍易用的位置存储好友列表数据。这样,数据就可以填充多种视图,例如位于好友管理系统的好友列表UI,或者游戏邀请系统中的下拉菜单。

总结

本文说明了如何设计一个高效异步多人界面,如何设置随机配对,如何设计游戏邀请系统,以及如何创造简单的好友列表等方法。本系列下篇文章将说明将完整的异步多人体验绑定在一起的最终必要元素。

原文发表于2012年7月22日,所涉事件及数据以当时为准。(本文为游戏邦/gamerboom.com编译,拒绝任何不保留版权的转载,如需转载请联系:游戏邦

How to Create an Asynchronous Multiplayer Game Part 4: Matchmaking

by Ross Przybylski

The key to a successful multiplayer game is having a critical mass of people to play with each other. But how do you amass players without an initial player base in the first place? Remove the requirement of “must-be-online-to-play”. Asynchronous matchmaking enables players to engage in multiplayer games, even if they’re not online! Random matchups allow players to meet new people and make new friends, and an invitation system enables them to grow these friendships and create a viral spread of enthusiasm for your game. This article will explain how to use your game server and database to manage the process of creating and joining multiplayer games.

This article will explain:

How to create an intuitive multiplayer interface

How to setup an asynchronous multiplayer match with a random player

How to design an asynchronous game invitation system

How to design a friends management system so players can invite each other to game even when their friends aren’t online

Requirements

Prerequisite knowledge

Experience developing turn based games

Familiarity with ActionScript 3.0

Has Read “Part 2: Saving the Game State to Online Database”

Has Read “Part 3: Loading Games from the Database”

Required products

Flash Professional (Download trial)

Smart Fox Server Pro (Download trial)

MySQL Database

User level

Advanced

Creating an Intuitive Multiplayer Experience

User experience is the most important part of creating an asynchronous multiplayer game. Regardless of how awesome your game may be, you will lose users if it’s not immediately clear to them how to setup multiplayer games.

In the original, real-time multiplayer implementation for Hero Mages, users would login and immediately enter a chat lobby where they can converse with other players, create games, and access other modules of the system such as the leaderboards and map editor. The system was modeled to mimic the design of popular multiplayer gateways like the original Battle.net for Diablo and Starcraft.

Hardcore gamers are generally familiar with this setup, but many casual gamers are completely lost and uncertain about what to do next.

Learn by Example

Defining, in clear terms, how the game interface should function and designing layouts that are effective and intuitive to users is a challenging process. One of the most effective ways to overcome this challenge is to explore how other games have handled the problem and then seek to improve upon existing implementations.

Hero Academy is a very successful asynchronous multiplayer game that has an intuitive user interface. Multiplayer launches directly to the player’s game list where they can start new matches or continue playing games they’ve already started. Creating a new game takes you to a screen with three options for connecting with friends: inviting a player via search, finding a random opponent, and inviting a friend via Facebook. Hero Academy’s social media integration is an important feature for making it easier to invite friends. Finally, Hero Academy’s random match screen allows player to setup their team and find an opponent. Note the well-placed “Buy” button here that helps promote In-App purchasing.

Note: I won’t be discussing how to integrate with Facebook in this article (perhaps in the future) but I will explain the process for designing your own in-game friends list for those players who don’t use Facebook.

Hero Academy’s multiplayer begins from the game list.

Creating a new multiplayer game in Hero Academy

The ability to buy character expansions has been added to the party builder screen.

The new multiplayer interface for Hero Mages features an intuitive gateway screen that allows players to access all available functions of the application, including the ability to create new games, load and continue playing existing games, view the leaderboard, design custom maps, and so forth. The classic live-chat lobby interface is included as well and can be accessed via the icon in the upper left.

As Hero Mages supports both real-time multiplayer and asynchronous multiplayer, it was pertinent to design a new game creation screen that highlights the different options available to the player.

As with Hero Academy, I’ve added the ability to buy expansions directly from the hero selection screen. There’s a subtle difference here, however: “Buy” labels are not placed over each character.

Rather, the “Buy” button takes you to a new expansions screen for different products. The first reason for this is that characters are bought in sets. The second is that by having “locked” heroes directly in the list, many existing players express feelings of “not getting the full game” when they purchase the app. This separation helps to better distinguish the fact that new characters are expansions (not part of the core set).

The new multiplayer gateway for Hero Mages

Creating a new multiplayer game in Hero Mages

The ability to buy character expansions has been added to the party builder

Finally, the invitation system for Hero Mages demands a separate screen since, unlike Hero Academy, players can invite up to seven of their friends to a game. One of the weaknesses of the Hero Academy “Friend Search” is that, if your friend is NOT on Facebook, it’s necessary to type in your friends’ username each time you want to play a game. Hero Mages improves on this system by building an in-game friends list as you invite players to join your games. I’ll explain how this system works later in the article.

You can invite up to seven of your friends to play a game of Hero Mages

To invite friends, you select them from a drop down menu which also provides the option to add players who you aren’t yet friends with.

What about joining games?

Notice how neither interface style shown above includes a “Join Game” button. With all this game creation going on, how are people actually connecting with one and other? The answer is that the joining of games is handled for the user behind the scenes by the server. When a player “creates” a new match, they’re actually sending a request to the server to connect with a player. Depending on whether another player is waiting or not, the server will either store their request as a new game record or connect their game preferences with an existing game record waiting on queue. The player shouldn’t be bothered with the task of joining because this diminishes the simplicity of the experience. The exception to this principle is if your game also supports live multiplayer games and you want to allow users to join sessions in progress. This is accomplished in Hero Mages via the main chat lobby. Users can click on live games in the list to the left to join them.

It’s also worthy to note that Hero Mages will also connect asynchronous players to a live game session while they’re taking their turn. If, at the same time a person is playing asynchronously their opponent loads that session from their games list, they’ll be automatically joined together in a live game session.

Summary of an Effective Multiplayer Interface

As demonstrated in the above images, an effective multiplayer game interface includes the following key elements:

Gateway screen for accessing all of the multiplayer features

Obvious and intuitive means to create new games

Effective system for inviting friends

Setting up a Random 1v1 Match

As illustrated above, effective asynchronous multiplayer interfaces eliminate the concept of joining games in favor of matchmaking. The most basic way to create a random 1v1 match between two players is to create a new game record the first time a match is requested. Then, the next time a player requests a match, connect them with the preexisting session.

When a player starts a random opponent match, one of two things happens:

An existing match is not available, so the server creates a new match and stores it in the database. The user is taken to a “Finding Player” screen. They may continue waiting for an opponent to join, or cancel. Even if they cancel, their request remains on the server. This way, they can be notified when an opponent has joined and they are ready to take their turn.

An existing match is available, so the server completes a pending match with the user’s game preferences and sends them the game record to load. The server should always configure the “joining” player to get the first turn. This way, they can begin playing immediately once the game is loaded.

By the time the player reaches this screen, a new game record has been created. The player can wait to connect with an opponent or choose to cancel.

The system will store the match request within the database and notify the player when an opponent has been found so they don’t have to keep waiting.

A new record appears in the player’s game list, representing that the system is searching for opponent.

How it Works

The specific code implementation used to program the random matchmaking for Hero Mages is beyond the scope of this article, but a complete outline of the process is explained below. Using this outline and the techniques for coding client and server side code learned in the last two articles should provide a helpful starting point for programming any asynchronous multiplayer game.

In order to create the seamless matchmaking experience illustrated above, several communications between the client and server take place to appropriately configure the game:

When the user selects the “Random Match” button, a “sendMatchMakeCommand” is triggered which instructs the game creation class on the client side to build a new game data structure and send a request to the server.

On server side, check to see if there are any unmatched games waiting in queue

If no unmatched games available, create a new game record on the server with a status of -1 to indicate that the game is waiting for opponent. Send response back to client indicating that a match was not found.

If an unmatched game is available, load this game record’s data and send it back to the client in the response

On client side,

If no match was found, show “Finding Player” screen. If player cancels, show prompt saying “We’ll notify you when your match is ready.”

If match was found, create a new game data that merges player’s game preferences such as hero selections with the matched player’s existing game setup data and send response back to server

On server side,

Update the game results table with new record entry for the matched player

Update the game record itself with new game setup data

Return response command to load game (works just like loading the game in article 3 except an additional flag for matched game is included)

On client side,

Load the game data and start the game. Matched player may begin playing immediately.

Send a response to server indicating game has been matched

On server side, check if original match creator is online. If so, send them in-app notification that their match is ready. If not online, send a push notification or email. If the player is still on the “Finding Player” screen, we can connect them to a live game session with their opponent.

Random asynchronous games are well suited for 1v1 matches, but what if you want to play a game with more than 2 people? While it’s possible to setup a larger random game, this allows the potential for issues that may be disastrous for an asynchronous game. For example, what if you play a random 2v2 game and your teammate decides to quit playing? Also consider that the more players involved in a large game, the longer it will take before each player’s turn cycles back. With random players, there’s no way to contact each other and say “Hey, you, take your turn so we can finish up this game!” This is why it’s beneficial to create a game invitation system that’s restricted to friends. This way, you know the people you’re playing with have had a chance to see the game settings and are committed to finishing the session.

Designing an Asynchronous Game Invitation System

A game invitation system is essential for players to engage their friends in asynchronous multiplayer battles. The first requirement of building an invitation is the game creation screen- a place where the game host can configure options like which map to play on, whether or not there will be teams or computer opponents, and what the game objective will be. The second requirement is a mean to communicate between all invited players so that each player can submit their character choices and invitation acceptance and the game can begin when everyone is ready.

How it Works

The game organizer launches a new game creation screen and can configure all game options. This includes choosing the map, game objective, organizing teams, and adding computer opponents. The game screen should include cells for each player (human or computer) that can be added.

The game host can invite players using the player options drop down and selecting “Invite Friend”. It’s important to limit invitations to friends because you don’t players being allowed to spam invites to random players who may not want to play a multiplayer game.

When all options are setup and configured, the game organizer can click the “Send Invitation” button. This sends a message to the server with the game setup data and the ID’s of all the players involved.

On the server side, a new game record is created using the same functionality discussed in Tutorial 2 with two differences:

The game status is stored as -2 to indicate the game is pending invitation acceptance

The hm_gameresults table should be modified to include new parameters that store the players’ invitation acceptance status and custom game preferences.

Once the game record has been created by the server in the games data, it will appear in the invited players’ game lists just like other games. Instead of launching the game when a player selects it, however, the application will load the game’s current parameters back into the game creation screen. Here the player can select their heroes and choose to accept or decline the invitation.

If the player declines invitation, the game status is set to -3, or Invitation Declined. The game will be flagged as completed for all players that were invited and will no longer be accessible.

If the player accepts invitation, a call to the server is made to set the acceptance status for that player to true.

On the client side, the game record interface should interpret accepted responses and draw appropriate markers on the game record. For example, players who were invited but haven’t yet responded show an envelope. Players who have accepted show a green check mark. Players who decline show a red x.

When the final player has accepted the game invitation, the server will assemble the game data to incorporate all of the new player preferences. If the player who accepted has the active turn, it will send back a signal to launch the game so they can take their turn. Otherwise, it will send a notification to whichever player has the first turn.

Additions to the Game Results Table

Recall from part 2 of this series the creation of a table called hm_gameresults. This table is responsible for storing player-specific data related to the game, including the player’s win/loss result and the index of the last game command they witnessed (used for viewing game animation replays). For the invitation system, additional values are needed to track invitation response and any parameters for customizing the player’s team or character preferences.

hm_gameresults

Field     Type     Notes

accept     tinyint(4)     Stores value of -1, 1 or 0 to indicate whether player has not yet responded, accepted, or declined respectively

ID_MAGE     int(10)     Stores the unique id of the player’s mage they have chosen to bring to battle

ID_GUARD1     int(10)     Stores the unique id of the player’s guardian they have chosen to bring to battle

ID_GUARD2     int(10)     Stores the unique id of the player’s guardian they have chosen to bring to battle

Remember, a game invitation is simply creating a new game record that can show up in the player’s game list. The only difference is that until all players have accepted, the status of that game is -2, or pending invitation acceptance from all players. We don’t want to store players’ ready status in the game data itself because two players accepting an invitation at the same time could overwrite the others’ acceptance. By using each player’s own game result record, each player can individually modify their status. Only when the final player has accepted the invitation do we rewrite the game data to include all of the player’s game setup information (similar to merging the matched random player in the section above).

Further Design Considerations

Important questions regarding how to handle unique situations will arise during the creation of the game invitation system. Below are a few challenges that came up during the development of Hero Mages invitation system and how I handled them.

What happens to a game invitation once it’s been sent and what if players don’t respond to it?

Game invitations are designed to act in the same fashion as game records. They appear in the player’s game list with the games they are currently playing or have completed. The difference is invitations are marked with a different status id, in this case, -2, and are denoted on the game list as “Pending invitation”.

Game records that are pending invitation use symbols to indicate which players have accepted.

Note that iconic symbols are used to represent the status of the game invitation. Players who were invited but haven’t yet responded show an envelope. Players who have accepted show a green check mark. Players who decline show a red x.

It’s important to keep the game list as tidy as possible to ensure players have a clear set of “tasks” to complete when they return to the application.

The game list sort algorithm is adjusted from the previous articles to work as follows:

Games whose invitation the player needs to respond to are the highest priority because a game can’t start until all players have accepts. These will be listed first in the game list.

Games in progress where it’s the player’s turn to attack are the next highest priority because these games cannot progress until the player has completed their turn. These records are shown next in the list with a secondary sort condition by date.

Games in progress or waiting for other players to accept invitation are listed next, also sorted by the date/time of the last activity on that record.

Finally, completed games and declined invitations, also sorted by date, are listed last.

To address the original design concern, invitations that haven’t been responded to remain listed in the player’s game list, pending action from other players (similar to games waiting on opponent’s turn). Players have the option to “drop” opponents who haven’t taken their turn after (3) days. And, at any time before a game starts, any of the players may change their acceptance to a game invitation to “Decline”. Doing so will set the status of the game to “Invitation Declined”. The game will be considered complete and will not affect player stats.

When a game is ready to play, who takes the first turn?

Since invitation based games can potentially involve up to 8 players, it’s not advisable to simply have the last player who accepts go first. Instead, the game should follow the random turn order pattern originally calculated in the initial game setup. The system should be configured to send a notification to the first player to take their turn once the game has started. Once a game has started, the status changes to “Game in progress”, and players will see the game record updated as such on their game list.

What mechanism prevents a player from spamming undesired game invitation requests?

Players may use the leaderboard as a means to look up the highest ranked player and submit challenge request for the chance to earn higher rating points. Because this could potentially overwhelm popular players, Hero Mages requires that players invite friends rather than just any player. This mitigates unsolicited game invitation requests and keeps players’ games lists manageable.

At the same time, it’s important not to limit the development of friendships within the game. For this reason, Hero Mages allows you to request new friends via the game invitation itself. When a new friend is added, players may send them (1) game invitation request before they’ve accepted the friendship. If the player accepts the game invite, they’ll automatically become friends with the game organizer. If they decline the game request, the friendship status will remain pending until they accept it or the inviting player cancels their invitation request. The process for creating an in-game friends system is explained in the next section.

Creating an In-Game Friends System

While social networks like Facebook are a great solution for connecting players with their existing friends, relying solely on these sites can isolate players that don’t use social media or simply prefer not to give your game access to their social media accounts.

Having an in-game friends system is advisable for the following reasons:

You have full control over how in-game friendships are formed allowing for greater flexibility and viral spread of your game’s internal community

Friendships are independent of social networks, so your game can build community regardless of whether your users are on Facebook or other social networks

The option to integrate with social media to enhance your game’s community is still available

This section describes the process of designing an in-game friends system and integrating it with your game’s interface and invitation system to foster the development of your game’s player community.

The Friends Table

The first step in creating a friends system is to create a new database table. Following the standard Hero Mages convention, I used the identifier “hm_friends”. The table should include the following properties:

hm_friends

Field     Type     Notes

ID_LINK     int(10)     The unique ID of the friend relationship

ID_MEMBER     int(10)     The ID of the member who has a friend

ID_FRIEND     int(10)     The ID of the member who is the member’s friend

accepted     tinyint(4)     ( 0, 1, -1) Indicates whether friend invite has been declined, accepted, or not responded to yet respectively

sentGameInvite     tinyint(4)     (0 or 1) Indicates whether or not game invite has been sent on this friendship

Client Side Friend List UI

In order to create new friend relationships, the client side will need some additional user interface components setup in order to send a new friend request to the server. The important question to ask is: “How will players setup a friendship within the game?” The more intuitive your friends system is, the greater the likelihood that players will establish friendships with the game, strengthening the game’s player community and long-term viability.

Friendships in Hero Mages can be established in three ways:

By opening another player’s stats profile and selecting the “Add Friend” button. Player stat profiles can be accessed in the live chat room, the leaderboard, and within games by selecting the player’s name in the player list.

By using the “Friends Management” screen (accessed via the multiplayer gateway) and searching for the player’s username.

By selecting “Add Friend” when setting up a new game invitation. Using this action will leverage the Friends Management option #2 and then return to the game invitation screen, allowing the player the ability to quickly invite new friends to their game.

Players can add friends via players’ stat cards.

Friends can be added and removed via the Friends Management screen.

Friends can also be added when setting up a custom game invitation

Adding Friends

With the proper UI established, the client side will send the server a friend request that includes the ID of the member who’s requesting the friendship and the ID of the player they want to become friends with.

On the server side, the following happens:

First check to see if an existing friendship exists

sql = “SELECT * FROM hm_friends WHERE ID_MEMBER = “+params.hmId+” AND ID_FRIEND = “+params.fId;

Depending on whether or not query returns results, create new friendship record or update the status of the existing friendship record

If query returns no results, relationship does not exist yet, create new record:

sql = “INSERT into hm_friends (ID_MEMBER, ID_FRIEND, accepted) VALUES (“+params.hmId+”, “+params.fId+”, 1) , (“+params.fId+”, “+params.hmId+”, -1)”;

Otherwise, relationship exists, update the status of the relationship:

sql = “UPDATE hm_friends set accepted = 1 WHERE ID_MEMBER = “+params.hmId+” and ID_FRIEND = “+params.fId;

Send the client side a response that includes the player’s updated friendship list. This list includes the names, ids, avatars, and relationship status of the player’s friends.

It is important to note that each friendship is defined by two records in the hm_friends table. For each friendship, the player will have a record where their ID_MEMBER stores their own ID and another record where for their friend stores their ID in ID_FRIEND. The two records are necessary so that friendships can be added and removed without the need to create/delete additional records.

It’s advisable to follow this practice for three reasons:

Keeping track of existing friendship relationships ensures that player’s cannot indefinitely spam players to be their friends. Once a friend request is declined, the “accepted” property is set to 0 so that additional friend requests will not appear from this user. The friendship can only be established by this player adding the original requester as a friend.

Keeping track of existing friendships allows the program to check the “sentGameInvite” property. This property stores whether or not a game invite was sent on this friendship. The game should not allow players to spam invites to players who have not accepted their friendship if this value has been flagged as true.

Most importantly, two records are needed to validate friendship acceptance. Think of the system as a two-way handshake. The player who initiates the friendship automatically sets their “acceptance” flag to true. The player who is requested as a friend will have their “acceptance” set to -1 (undecided) until they decide to accept the friendship or decline it.

Removing Friends

Removing a friendship with this setup is easy: simply update the “accepted” status of the player opting to remove the friend to ’0′. The following statement is used:

sql =  “UPDATE hm_friends set accepted = 0 WHERE ID_MEMBER = “+params.hmId+” and ID_FRIEND = “+params.fId;

Getting the Friends List

The friend system comes together via the MySQL statement on the server side that returns the friend list back to the player on the client side. Below is an example of a “getFriendsList” function that should be implemented in the server side code:

Handle Server Response on Client Side

As in previous examples, the last step is handling the server side response on the client. The best practice is to store the friend list data in a universally accessible location. This way, the data can populate multiple style views like a friend list UI in the friend management system or a drop down menu in the game invitation system.

Coming Next

This article explained how to design an effective asynchronous multiplayer interface, how to setup random matches, how to design a game invite system, and how to create a simple friends list. The next article in this series will explain the final element necessary to tie the complete asynchronous multiplayer experience together: notifications.(source:indieflashblog


上一篇:

下一篇: