实现游戏排行榜

实现排行榜是许多开发者想要了解的活动,以便他们可以将其包含在他们的游戏功能中。Corona 支持各种用于管理排行榜的服务,包括 Google Play 游戏服务Apple 游戏中心

本教程将概述一种设置游戏以同时使用Google Play 游戏服务 Apple 游戏中心.

注意

本教程未概述在 iTunes Connect 或 Google Play 中设置您的游戏。 请参考许多在线资源以获取这些说明。

收集信息

Google

对于Google Play 游戏服务,您需要从 Google Play 开发者控制台 收集各种详细信息,包括

  1. 您的许可证密钥,在开发者控制台中找到的一个很长的字符串。

  2. 您的Google Play 游戏应用 ID.

  3. 标识您排行榜的字符串 — 看起来像 CgkA8kb12jK0onOQBg

记录所有这些信息,因为您需要将其提供给您的 Corona 应用。

Apple

Apple 游戏中心也要求您收集一些信息用于您的应用代码。 创建排行榜时,系统会要求您为其指定一个唯一的名称。 建议您遵循反向域名命名方案,例如 com.yourdomain.yourgame.leaderboardname。 记下这一点,因为您需要在 Corona 应用中指定它。

项目设置

对于每个相应服务,您需要将上面收集的信息包含在 Corona 项目的特定区域中。

Google

有关必要的 Google Play 游戏服务 设置的详细信息,请参阅文档,但以下是必要方面的概述

  1. 按照此处所述实施 Google 应用许可,并使用此处所述的私钥对 .apk 进行签名。

  2. 确保您已在 Google Play 开发者控制台 中启用了云端硬盘 APIGoogle Play 开发者 API

  3. build.settingsplugins 表中为Google Play 游戏服务插件

settings = {

    plugins =
    {
        ["plugin.gpgs.v2"] =
        {
            publisherId = "com.coronalabs",
            supportedPlatforms = { android=true }
        },
    },
}
  1. 添加一个条目Google Play 游戏应用 ID指定为 googlePlayGamesAppId
settings = {

    android =
    {
        googlePlayGamesAppId = "YOUR_APPLICATION_ID",
    },
}

Apple

Apple 游戏中心 更简单一些 — 基本上,只需将插件包含在 build.settingsplugins 表中,如下所示

settings =
{
    plugins =
    {
        ["CoronaProvider.gameNetwork.apple"] =
        {
            publisherId = "com.coronalabs"
        },
    },
}

数据模块

告别全局变量! 教程中,我们概述了如何使用数据模块在场景和模块之间共享信息。 此技术将再次用于存储本教程中使用的各种游戏网络插件句柄。

  1. 首先,创建一个名为 globalData.lua 的新的空白 Lua 文件并将其保存到您的项目目录中。 在内部,包含以下几行
-- Pseudo-global space
local M = {}

return M
  1. 现在,在 main.lua 文件中,require() 数据模块并向其表中添加两个变量,globalData.gpgsglobalData.gameCenter,两者最初都设置为 nil。 这些将保存插件句柄以供以后使用。
local globalData = require( "globalData" )
local json = require( "json" )

globalData.gpgs = nil
globalData.gameCenter = nil

请注意,我们还 require()JSON 库。 这并非所有实现都必不可少,但我们将在本教程中使用 JSON 将游戏网络响应数据输出到控制台。

平台检测

接下来,让我们测试以查看用户所在的平台。 如果是 Android 设备,我们将 require()Google Play 游戏服务;如果是 iOS,我们将 require()Apple 游戏中心。 请注意,每个相应的包含都存储在上面配置的 globalData 句柄中。

local globalData = require( "globalData" )
local json = require( "json" )

globalData.gpgs = nil
globalData.gameCenter = nil

local platform = system.getInfo( "platform" )
local env = system.getInfo( "environment" )

if ( platform == "android" and env ~= "simulator" ) then
    globalData.gpgs = require( "plugin.gpgs.v2" )
elseif ( platform == "ios" and env ~= "simulator" ) then
    globalData.gameCenter = require( "gameNetwork" )
end

游戏网络初始化

现在我们准备初始化并将用户登录到适当的游戏网络。 为此,我们首先需要添加侦听器函数来处理游戏网络初始化事件。 由于 Lua 是一种单遍编译器,您需要以相反的顺序编写代码。 基本工作流程是初始化插件,这将触发将在侦听器函数中处理的事件。

这是Google Play 游戏服务Apple 游戏中心不同的一个主要点。 对于 Apple,初始化过程会自动将用户登录,但对于 Google,您必须显式调用命令才能将用户登录。 此外,GPGS v2 插件不再具有 .init() 调用。 您只需要登录。

-- Google Play Games Services initialization/login listener
local function gpgsInitListener( event )

    if not event.isError then
        if ( event.name == "login" ) then  -- Successful login event
            print( json.prettify(event) )
        end
    end
end

-- Apple Game Center initialization/login listener
local function gcInitListener( event )

    if event.data then  -- Successful login event
        print( json.prettify(event) )
    end
end
注意

您可以在成功登录后执行其他任务,例如请求玩家信息,但出于本教程的目的,我们只需输出事件返回的值。

有了侦听器函数,我们现在可以根据用户所在的平台初始化游戏网络

-- Initialize game network based on platform
if ( globalData.gpgs ) then
    -- Initialize Google Play Games Services
    globalData.gpgs.login( { userInitiated=true, listener=gpgsInitListener } )

elseif ( globalData.gameCenter ) then
    -- Initialize Apple Game Center
    globalData.gameCenter.init( "gamecenter", gcInitListener )
end

将分数发送到排行榜

现在我们已经初始化了游戏网络并且用户已登录,我们就可以传输分数了。 通常,您会在游戏结束后或玩家完成值得注意的事情后执行此操作。 如果您在本地跟踪用户的最高分,您可以选择只传输您知道是最高分的分数,或者您可以将分数发送到Google Play 游戏服务Apple 游戏中心,让服务决定是否需要记录最高分。

为此,与初始化过程类似,我们需要一个用于提交分数的侦听器函数

local function submitScoreListener( event )

    -- Google Play Games Services score submission
    if ( globalData.gpgs ) then

        if not event.isError then
            local isBest = nil
            if ( event.scores["daily"].isNewBest ) then
                isBest = "a daily"
            elseif ( event.scores["weekly"].isNewBest ) then
                isBest = "a weekly"
            elseif ( event.scores["all time"].isNewBest ) then
                isBest = "an all time"
            end
            if isBest then
                -- Congratulate player on a high score
                local message = "You set " .. isBest .. " high score!"
                native.showAlert( "Congratulations", message, { "OK" } )
            else
                -- Encourage the player to do better
                native.showAlert( "Sorry...", "Better luck next time!", { "OK" } )
            end
        end

    -- Apple Game Center score submission
    elseif ( globalData.gameCenter ) then

        if ( event.type == "setHighScore" ) then
            -- Congratulate player on a high score
            native.showAlert( "Congratulations", "You set a high score!", { "OK" } )
        else
            -- Encourage the player to do better
            native.showAlert( "Sorry...", "Better luck next time!", { "OK" } )
        end
    end
end

请注意,由于每个网络返回不同的数据,我们必须测试正确的网络并独立处理返回的数据。

有了侦听器函数,我们现在可以将分数提交给任何相应服务。 对于此任务,您将需要从 Google 获取或为 Apple 创建的排行榜标识符。 这些必须与服务预期的内容完全匹配。

为了以后方便,让我们将其包装在一个接受单个 score 参数的函数中

local function submitScore( score )

    if ( globalData.gpgs ) then
        -- Submit a score to Google Play Games Services
        globalData.gpgs.leaderboards.submit(
        {
            leaderboardId = "CgkA8kb12jK0onOQBg",
            score = score,
            listener = submitScoreListener
        })

    elseif ( globalData.gameCenter ) then
        -- Submit a score to Apple Game Center
        globalData.gameCenter.request( "setHighScore",
        {
            localPlayerScore = {
                category = "com.yourdomain.yourgame.leaderboard",
                value = score
            },
            listener = submitScoreListener
        })
    end
end

现在,提交分数就像调用 submitScore() 函数一样简单,例如

submitScore( 10000 )

显示排行榜

包含排行榜的游戏必须在逻辑上为玩家提供某种查看它们的方式。 这可能是由 按钮控件 的侦听器处理程序触发的,或者,它可以在用户在 我们已经创建的 submitScoreListener() 函数中 achieving(或未能 achieving)最高分后显示。

无论采用何种方法,都可以像这样显示排行榜

if ( globalData.gpgs ) then
    -- Show a Google Play Games Services leaderboard
    globalData.gpgs.leaderboards.show( "CgkA8kb12jK0onOQBg" )

elseif ( globalData.gameCenter ) then
    -- Show an Apple Game Center leaderboard
    globalData.gameCenter.show( "leaderboards",
    {
        leaderboard = {
            category = "com.yourdomain.yourgame.leaderboard"
        }
    })
end

结论

虽然您自己的游戏网络实现可以(并且可能应该)扩展到排行榜之外,但希望本教程能够为您构建跨平台游戏网络功能(使用 Google Play 游戏服务Apple 游戏中心)奠定坚实的基础。