作者:马宁
OpenXLive SDK 0.9.9下载地址:
http://developer.openxlive.net/sdk/download/
现在,很多休闲游戏都支持用户将游戏的精彩画面分享到社交网络中,这已经成为了最吸引用户的新功能。但是开发者如果想实现这个功能,就必须在游戏中内置不同社交网络的SDK,还要通过漫长的审核过程,这对于很多开发者来说,都是不堪重负的。
所以,OpenXLiveSDK 0.9.9.0版提供了SNS分享的功能,无需在软件中内置各种各样的社交网络SDK,而且可以在不修改客户端的情况下,增加新的SNS分享功能。
目前,我们在全球支持Facebook和Twitter分享,在中国支持新浪微博分享,后续还会陆续加入对于人人网和腾讯QQ的支持。
本文将介绍如何使用这一功能,并提供相应的示例代码。
OpenXLive所有的示例代码可以在OpenXLive SDK安装目录下的.\Sample文件夹下找到(默认应该在C:\Program Files (x86)\Fulcrum Mobile Networks Inc\OpenXLiveSDK\Sample)。有关本主题的完整示例代码在该文件夹下的SNS.zip文件中,你需要先将其解压,然后再用Visual Studio 2010打开。
该示例包含了在Silverlight和XNA下的详细实现步骤。
1. 架构介绍
我们首先来看一下,OpenXLive SNS分享的技术架构:客户端只需要嵌入OpenXLive SDK 0.9.9或以上版本,就可以实现SNS分享功能了,无需嵌入每一种需要支持的SNS SDK。用户需要分享的内容会首先发送到OpenXLive的服务器中,然后由OpenXLive服务器进行分发,最后显示在SNS中。需要注意的是,受到SNS网站策略限制。每条分享内容不能同时出现在多个SNS中。
这样的好处是,当OpenXLive增加新的SNS时,无需修改客户端的代码。OpenXLive SNS分享的技术架构,如图:
OpenXLive SNS分享功能的操作步骤,大致分为下列几步:
1. 客户端向OpenXLive服务器请求目前可以支持的SNS列表;
2. 客户端向OpenXLive服务器发送分享内容,并指定发送到哪个SNS中;
3. OpenXLive服务器首先将内容存储到OpenXLive Cloud中;
4. 然后通过分发服务,将分享内容发送到指定的SNS中。
为了实现OpenXLive SNS分享功能时,需要用户首先使用SNS帐号登录,或者使用OpenXLive帐号登录,然后绑定SNS帐号。如果您使用了Facebook帐号登录,也可以绑定Twitter帐号,然后直接在Twitter中发送分享内容。
在实际开发中,开发者需要实现下面的功能:
1. 实现屏幕截图;
2. 让用户预览发布的图片;
3. 让用户能够编辑自己的心得;
4. 让用户选择发布到哪个SNS中。
我们并未提供标准的SNS分享界面,只是在示例代码中实现了一个例子。这是因为,开发者需要实现与自己游戏风格一致的分享界面,可以直接调用API来实现这个界面,而不需要使用标准的SNS分享界面。
接下来,我们来看一下,如果实现SNS分享功能,需要哪些步骤来完成。流程图如下所示:
1. 首先在游戏界面中实现截图功能,一般是在界面上有一个拍照按钮,用户可以点击该按钮实现截图功能;
2. 进入分享界面,将现在可供分享的SNS类别列在界面上;
3. 如果用户选择了一个SNS分享游戏内容,则判断该用户是否已经与该SNS建立了连接;
4. 如果用户选择的SNS未与当前用户建立连接,则弹出SNS连接界面,允许用户连接该SNS帐号;
5. 如果用户连接SNS帐号成功,则向服务器端提交分享内容。
对于开发者来说,这里有两个类需要着重介绍一下:SNSProvider和SNSContract。SNSProvider代表的是可供分享的SNS类型,包括了名称、图标和链接等信息;而SNSContract则代表了用户与SNS之间的连接关系。
我们可以通过XLiveGameManager.CurrentSession.SNSProviders属性,来获取当前有效的SNS列表;也可以通过MyPlayer.SNSContracts属性来获取当前玩家绑定的所有SNS;也可以通过MyPlayer. GetSNSContract方法,根据SNSProvider来获取对应的SNSContract,如果该用户未绑定SNS,则返回为空。
好了,到这里,我们就将SNS分享的原理和技术架构介绍完了。接下来,我们来介绍,如果实现一个完整的SNS分享游戏,包括Silverlight和XNA两个版本。
2. 在Silverlight游戏中实现分享功能
打开Visual Studio 2010 ,新建一个OpenXLive Silverlight Game with Startup UI项目,项目名称输入OpenXLiveSilverlight,点击Ok,在选择显示语言对话框中,选择默认显示语言,点击OK。
首先你需要在App.cs中填入正确的Application Secret Key。
#error Please full your game Secret Key in below code
private string APISecretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
然后注释掉#error那行代码,此时程序将能够正常编译。[MN1] [MN2]
获取Secret Key的方法,请参考《在开发者网站上创建OpenXLive游戏》,链接如下:
http://wiki.openxlive.net/Tutorial-4-Create-OpenXLive-Game-in-website.ashx
有关如何将OpenXLive的服务,加入到您已有的游戏中去,请参考:
OpenXLive Silverlight 入门
OpenXLive XNA 入门
2.1实现游戏界面与截图
接下来我们需要实现游戏界面,在后边会对游戏界面进行截屏,并且将截屏图片发送到SNS社交网络中。请注意,游戏界面是由开发者自己实现的,请根据自己的具体需求来实现游戏界面。
首先要添加几张图片,右键项目 选择 Add -> Existing item…,找到示例代码中的OpenXLiveSilverlight文件夹下的Capture.png、GameBackPortrait.jpg、UpdateBackPortrait.jpg点击Ok。当然,你也可以使用自己的图片,并在后面的代码中将图片名称改为自己的图片。
由于本次示例我们使用了ListPicker控件,所以需要先添加Microsoft.Phone.Controls.Toolkit.dll引用。
接着我们添加一个SNS分享页面,右键项目 选择 Add -> New item…,选择Windows Phone Portrait Page,命名为UpdateStatusPage.xaml。
接下来,我们要实现游戏界面和屏幕截图功能。首先我们要为游戏界面提供一个截屏按钮和相应的提示。打开MainPage.xaml,在适当的位置添加如下代码:
<Grid x:Name="CapGrid"> <Grid.Background> <ImageBrush ImageSource="/OpenXLiveSilverlight;component/GameBackPortrait.jpg" /> </Grid.Background> </Grid> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Button Width="100" Margin="0,0,0,0" HorizontalAlignment="Left" Name="button1" VerticalAlignment="Top" Click="button1_Click"> <Button.Template> <ControlTemplate> <Grid Background="Transparent"> <Image Source="/OpenXLiveSilverlight;component/Capture.png" /> </Grid> </ControlTemplate> </Button.Template> </Button> <TextBlock Text="Click to capture and share" FontSize="20" Foreground="White" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,100,0,0"/> </Grid>
所谓CapGrid,就是我们截图的Grid区域,而ContentPanel则是用于放置截图按钮的Grid区域。
如果想查看完整的示例代码,请直接访问OpenXLiveSNS工程。MainPage界面如下:
左上角为截图的Button按钮,玩家点击该按钮进行截图,并导航至UpdateStatusPage页面。
然后,打开MainPage.xaml.cs代码文件,实现具体的截屏功能。
// 捕捉屏幕截图 private void button1_Click(object sender, RoutedEventArgs e) { if (XLiveGameManager.CurrentSession != null && XLiveGameManager.CurrentSession.SNSProviders.Count > 0) // Must exist available provider { WriteableBitmap wb = new WriteableBitmap(CapGrid, null); MemoryStream ms = new MemoryStream(); wb.SaveJpeg(ms, (int)CapGrid.ActualWidth, (int)CapGrid.ActualHeight, 0, 70); ms.Seek(0, SeekOrigin.Begin); byte[] pic = new byte[ms.Length]; int count = ms.Read(pic, 0, pic.Length); ms.Close(); UpdateStatus(pic); } }
在这部分代码中,我们使用了WriteableBitmap对象,从CapGrid中获取了需要截取的图像。然后,调用SaveJpeg将其保存到一个MemoryStream对象中,最后转存到一个byte数组中。
请注意:if语句用来判断当前是否有可用的SNSProvider ,只有存在SNSProvider时才能进行SNS分享,所以这个判断是必须的。
然后,我们需要调用UpdateStatus方法,将刚刚捕获的图像,传递给UpdateStatusPage页面,并导航到该页面,进行SNS分享。
// 分析屏幕截图 private void UpdateStatus(byte[] picture) { if (XLiveGameManager.CurrentSession != null) { UpdateStatusPage.SharingPicture = picture; this.NavigationService.Navigate(new Uri("/OpenXLiveSilverlight;component/UpdateStatusPage.xaml", UriKind.Relative)); } }
到这一步MainPage中的功能就实现完毕。接下来需要完成分享页面并实现相应逻辑。
2.2实现分享界面
在分享页面中我们需要一个Image控件用于显示当前分享的图片的缩略图,一个TextBox用于输入分享的文本内容,一个ListPicker控件用于用户选择要分享到哪个SNSProvider。
打开UpdateStatusPage.xaml文件,添加如下代码,完整代码请查看工程:
<toolkit:ListPicker x:Name="lisPickerSNS" Grid.Row="3" Header="Share" FullModeHeader="Share" ItemTemplate="{StaticResource SNSItemTemplate}" FullModeItemTemplate="{StaticResource SNSItemFullModeTemplate}" ExpansionMode="FullScreenOnly"> </toolkit:ListPicker>
此时的分享界面应该如下图所示:
打开UpdateStatusPage.xaml.cs文件,首先在文件顶部添加如下引用:
using System.Windows.Media.Imaging; using OpenXLive.Features; using OpenXLive.Silverlight;
然后,添加如下属性,以表示要分享的图片。
/// <summary> /// 得到或者设置需要分享的图片 /// </summary> internal static byte[] SharingPicture { get; set; }
然后将构造函数替换为如下代码:
public UpdateStatusPage() { InitializeComponent(); lisPickerSNS.ItemsSource = XLiveGameManager.CurrentSession.SNSProviders; txtContent.TextChanged += new TextChangedEventHandler(txtContent_TextChanged); ShowPicture(); }
在页面的构造函数中,我们可以通过XLiveGameManager.CurrentSession.SNSProviders属性得到目前有效的SNS列表,并将其绑定到ListPicker控件中。
ShowPicture方法用于显示分享图片的缩略图。
// 显示用于分享的图片 private void ShowPicture() { if (imageCap.Source == null) { byte[] picture = SharingPicture; if (picture.Length == 0) throw new InvalidOperationException("There is no picture used to share."); MemoryStream ms = new MemoryStream(); ms.Write(picture, 0, picture.Length); BitmapImage bi = new BitmapImage(); bi.SetSource(ms); imageCap.Source = bi; } }
2.3 实现连接SNS帐号功能
根据SNS分享功能的原理,我们需要在分享SNS内容前,判断用户是否连接对应SNS帐号。
首先,我们从lisPickerSNS控件中获取到用户要发布的SNS Provider对象;然后,获取到当前用户的MyPlayer对象;接下来,调用MyPlayer的GetSNSContract方法,返回SNS对应的SNSContract对象。
如果能够返回SNSContract对象,说明当前用户和SNS建立了连接关系,直接调用Share方法发布信息;如果返回空,则说明当前用户和SNS未建立连接,我们需要调用XLiveSLFormManager的ShowSocialConnect方法,来显示SNS连接界面。
添加如下代码用于处理分享按钮的点击事件:
private void btnUpdate_Click(object sender, RoutedEventArgs e) { SNSProvider provider = lisPickerSNS.SelectedItem as SNSProvider; if (provider == null) { return; } MyPlayer player = XLiveGameManager.CurrentSession.CurrentPlayer; SNSContract contract = player.GetSNSContract(provider); //如果用户未连接该SNS账号,则显示Social Connect界面来获取SNS contract if (contract != null) { Share(contract); } else { //如果用户已经连接了该SNS的账号,则直接使用SNS Contract对象进行分享 XLiveSLFormManager.ShowSocialConnect(this, provider, ConnectCompleted); } }
说明:只有当用户已经与选择的SNSProvider连接才能成功分享。
首先通过MyPlayer的GetSNSContract方法获取SNSContract,该方法有一个SNSProvider
的参数。如果返回值不为null,则表示该用户已与该SNSProvider连接,此时可以调用Share方法分享内容;如果返回值为null,则表示该用户未与该SNSprovider连接,此时应该调用XLiveSLFormManager的ShowSocialConnect静态方法跳转到连接页面与该SNSprovider建立连接。
XLiveSLFormManager的静态方法ShowSocialConnect如下:
XLiveSLFormManager.ShowSocialConnect(PhoneApplicationPage page, SNSProvider provider, EventHandler<SocialConnectEventArgs> connectCompleted)
该方法有三个参数:第一个表示当前的页面,第二个参数为需要与该用户建立连接的SNSProvider,第三个参数为连接页面关闭并返回时的处理函数。该处理函数如下:
///如果从SocialConnectPage 返回并成功连接SNS,则分享内容和图片 private void ConnectCompleted(object sender, SocialConnectCompletedEventArgs e) { SNSContract contract = e.Contract; if (contract != null) { Share(contract); } }
在该处理函数中你应该判断SocialConnectCompletedEventArgs参数中的Contract是否为null。如果为null,表示未连接;如果不为null,则表示用户与SNS帐号连接成功了,我们就可以大胆的分享SNS消息了。
2.4 实现分享功能
接下来,我们就要实现SNS分享的功能了。我们需要创建一个MyStatus对象,创建对象需要SNSContract参数,然后调用UpdateStatus方法来发布SNS消息。
SNS消息的内容是由开发者自定义的,OpenXLive不会有任何限制。作为最佳实践,我们建议您可以在SNS消息中增加游戏的名称和下载链接,这样有助于您的游戏获得更多用户。
接着在UpdateStatusPage.xaml.cs文件中添加如下方法:
// 分享内容和图片 private void Share(SNSContract contract) { // 获取发布者的信息 GameProfile profile = XLiveGameManager.CurrentSession.Profile; string content = string.Format("I was playing an amazing Silverlight game, its name is {0}, I feel {1}, you can also try it.", (profile != null ? profile.Name : ""), txtContent.Text); // 创建Status对象,并更新到社交网络 MyStatus status = new MyStatus(contract); status.UpdateStatusCompleted += new OpenXLive.Features.AsyncEventHandler(status_SNSUpdateStatusCompleted); status.UpdateStatus(content, SharingPicture); }
说明: Share方法用于分享内容和图片。SNS分享时,你需要使用指定的SNSContract实例化一个MyStatus对象,并调用MyStatus的UpdateStatus方法,该方法有两个重载:
MyStatus. UpdateStatus(string content) |
将文本内容分享到指定的SNS。 |
MyStatus. UpdateStatus(string content, byte[] picture) |
将图片和文本内容分享到指定的SNS。 |
在完整代码中,我们还需要处理UpdateStatus方法的完成事件。添加status_SNSUpdateStatusCompleted 方法为MyStatus 的UpdateStatusCompleted事件处理程序,以在分享完成后进行处理。
现在,SNS分享功能就实现完毕,编译并运行程序,我们来分享一张图片。
1. 运行程序点击New Game。
2. 点击左上角的截图按钮。
3. 输入分享的内容,并选择一个SNSProvider,此次我们选择Twitter。
4. 点击Share按钮,此时将会跳转到连接页面,输入你的Twitter账号和密码进行连接。
如果连接成功将会返回到分享页面并分享该图片到Twitter。
5. 登陆Twitter查看刚才分享的图片。
2 在XNA游戏中实现分享功能
打开Visual Studio 2010 ,新建一个OpenXLive Game with Startup UI项目,项目名称输入OpenXLiveXNA,点击Ok,在选择显示语言对话框中,选择默认显示语言,点击OK。
首先你需要在Game1.cs中填入正确的Application Secret Key。
#error Please full your game Secret Key in below code private string APISecretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
然后注释掉#error那行代码,此时程序将能够正常编译。
3.1添加资源
接下来我们需要添加几张图片,右键Content项目 选择 Add -> Existing item…,找到示例代码中OpenXLiveXNAContent文件夹下的ButtonChange_50.png、ButtonOk_50.png、 Capture.png、GameBackPortrait.jpg、GameBackLandscape.jpg、UpdateBackPortrait.jpg、UpdateBackLandScape.jpg点击Ok。当然,你也可以使用自己的图片,并在后面的代码中将图片名称改为自己的图片。
在游戏中我们需要一个用于截图的按钮和一个分享图片的界面。当点击截图按钮后将跳转到该分享界面,所以我们需要创建一个Button和一个XLiveForm,我们从示例代码中添加这两个类,右键游戏项目选择 Add -> Existing item…,找到示例代码中XNA游戏项目文件夹下的Button.cs和UpdateStatus.cs两个文件,点击OK。
3.2 实现游戏截图
我们先在Game1.cs中,实现游戏截图和分享界面对象的创建。
首先在.cs文件顶部添加如下引用
using System.IO;
然后在类中添加如下字段:
Button button; // 游戏的背景图片 Texture2D background; private bool _Capture = false; private Texture2D captureImage;
以上变量的作用是:button 为游戏界面左上角的截图按钮;background 表示游戏背景;_Capture用于判断是否点击了截图按钮;captureImage用于保存截图。
在LoadContent方法中,加载背景图片,并创建Button对象:
Texture2D xliveBack = Content.Load<Texture2D>("OpenXLive"); button = new Button(Content.Load<Texture2D>("Capture"), new Vector2(10, 0)); button.Click += new EventHandler(button_Click);
在Game1.cs类中添加Button的事件处理方法:
void button_Click(object sender, EventArgs e) { if (XLiveGameManager.CurrentSession != null && XLiveGameManager.CurrentSession.SNSProviders.Count > 0) // Must exist available provider { System.Diagnostics.Debug.WriteLine("Cpature"); _Capture = true; } }
button_Click方法为截图按钮的Click事件处理程序。如果用户点击Button,则将_Capture变量设置为true,真正的图片捕捉则是在Update方法中完成的。
// 捕捉屏幕快照 private Texture2D Capture(GameTime gameTime) { RenderTarget2D target2D = new RenderTarget2D(GraphicsDevice, GraphicsDevice.PresentationParameters.BackBufferWidth, GraphicsDevice.PresentationParameters.BackBufferHeight); GraphicsDevice.SetRenderTarget(target2D); spriteBatch.Begin(); spriteBatch.Draw(background, Vector2.Zero, null, Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); spriteBatch.End(); GraphicsDevice.SetRenderTarget(null); MemoryStream stream = new MemoryStream(); target2D.SaveAsJpeg(stream, target2D.Width, target2D.Height); target2D.Dispose(); Texture2D texture = Texture2D.FromStream(GraphicsDevice, stream); return texture; }
Capture方法用于游戏截图,具体的实现方法是,创建一个与屏幕大小相等的RenderTarget2D对象;然后通过GraphicsDevice的SetRenderTarget方法将RenderTarget2D对象设置为绘制表面,之后的所有操作都会绘制到新创建的RenderTarget2D对象中,在完成绘制后,我们还需要再次调用GraphicsDevice的SetRenderTarget方法,这次的参数为null,再次绘制时,效果就会出现在屏幕上了。
然后,创建一个MemoryStream对象,通过RenderTarget2D对象的SaveAsJpeg方法,将刚才保存的对象,保存到内存中。最后,再调用Texture2D的FromStream对象,将刚才的绘制结果保存到一个Texture2D对象中。
最后,在 Draw方法中,除了正常的绘制代码外,还要添加下面的代码:
protected override void Draw(GameTime gameTime) { if (manager.IsRunning) { GraphicsDevice.Clear(Color.CornflowerBlue); // … // 捕捉屏幕截图并显示UpdateStatus窗体 if (_Capture) { captureImage = Capture(gameTime); _Capture = false; UpdateStatus updateStatus = new UpdateStatus(manager); updateStatus.Show("very cool!",captureImage); } } base.Draw(gameTime); }
在Draw方法中,如果_Capture变量为true,则调用Capture方法来捕捉游戏的当前画面,然后创建UpdateStatus窗体的实例,并且调用Show方法来显示该窗体。
3.3 实现分享界面
然后,我们来看一下分享界面的实现,因为XNA中没有窗体的概念,所以,我们使用了OpenXLive中的XLiveForm作为分享界面的基类。
UpdateStatus类派生自XLiveForm类,UpdateStatus类中 BeginUpdateStatus方法用于分享图片,代码如下:
private void BeginUpdateStatus(SNSContract contract) { // … //获取游戏信息 GameProfile profile = XLiveGameManager.CurrentSession.Profile; string content = string.Format("I was playing an amazing XNA game, its name is {0}, I feel {1}, you can also try it.", (profile != null ? profile.Name : ""), _TextBoxContent.Text); // 分析内容和图片 MyStatus status = new MyStatus(contract); status.UpdateStatusCompleted += new AsyncEventHandler(Status_UpdateStatusCompleted); status.UpdateStatus(content, _PicBytes); }
SNS分享时,你需要实例化一个MyStatus对象,并调用MyStatus的UpdateStatus方法,该方法有两个重载:
MyStatus. UpdateStatus(string content |
将文本内容分享到指定的SNS。 |
MyStatus. UpdateStatus(string content, byte[] picture) |
将图片和文本内容分享到指定的SNS。 |
你需要注册MyStatus 的UpdateStatusCompleted事件处理程序,以在分享完成后进行处理。
3.4 实现连接SNS账号功能
UpdateStatus类中分享按钮的Click事件处理程序如下:
void _ButtonOk_Click(object sender, EventArgs e) { // … MyPlayer player = XLiveGameManager.CurrentSession.CurrentPlayer; if (player == null) { return; } SNSContract contract = player.GetSNSContract(_Provider); if (null == contract) { // 如果用户未连接该SNS账号,则显示Social Connect界面来获取SNS contract var connectForm = XLiveFormFactory.Factory.ShowSocialConnect(_Provider, new EventHandler<SoicalConnectCompletedArgs>(connectForm_SocialConnectCompleted)); } else { // 如果用户已经连接了该SNS的账号,则直接使用SNS Contract对象进行分享 BeginUpdateStatus(contract); } }
说明:只有当用户已经与选择的SNSProvider连接才能成功分享。
首先通过MyPlayer的GetSNSContract方法获取SNSContract,该方法有一个SNSProvider
的参数。如果返回值不为null,则表示该用户已与该SNSProvider连接,此时可以调用BeginUpdateStatus方法分享内容;如果返回值为null,则表示该用户未与该SNSprovider连接,此时应该调用XLiveFormFactory的ShowSocialConnect方法跳转到连接页面与该SNSprovider建立连接。
XLiveFormFactory的ShowSocialConnect方法如下:
ShowSocialConnect(SNSProvider provider, EventHandler<SoicalConnectCompletedArgs> socialConnectCompleted)
该方法有两个参数:第一个参数为需要与该用户建立连接的SNSProvider,第二个参数为连接页面关闭并返回时的处理函数。该处理函数如下:
void connectForm_SocialConnectCompleted(object sender, SoicalConnectCompletedArgs e) { // 当SNS连接成功,直接分享消息 if (null != e.Contract) { _ProgressTips.Text = "Sharing..."; BeginUpdateStatus(e.Contract); } }
在该处理函数中你应该判断SoicalConnectCompletedArgs参数中的Contract是否为null。如果为null,表示未连接;如果不为null,则表示用户与SNS帐号连接成功了,我们就可以大胆的分享SNS消息了。
现在,XNA游戏的SNS分享功能就实现完毕,编译并运行程序,我们来分享一张图片。
1、运行程序点击New Game。
2、点击左上角的截图按钮。
3、输入分享的内容,并选择一个SNSProvider,此次我们选择Twitter。
4、点击Share按钮,此时将会跳转到连接页面,输入你的Twitter账号和密码进行连接。
如果连接成功将会返回到分享页面并分享该图片到Twitter。
5、登陆Twitter查看刚才分享的图片。
写在最后
我们介绍了OpenXLive的SNS分享功能,比起其他功能来说,OpenXLive SNS分享功能的操作和代码是比较多的,所以我们尽可能详细地给出了所有的描述和代码。这样做的主要原因,是希望用户能够编写符合自己游戏风格的SNS分享界面。
好了,赶紧把OpenXLive SNS分享功能加入到你的游戏中去吧!更多的玩家正在等着呢!