简介
本文是一份快速指南,逐步指导您在 10 分钟内,将非常基础的 Steam 排行榜集成到您的应用程序中。
Steamworks SDK 中有一个名为
Spacewar 的绝佳应用程序实例,完整展示了所有 Steam 功能。若要全面了解 Steam 所有使用中的功能,请首先访问此处。 本教程将 Spacewar 中的信息和
ISteamUserStats 中的排行榜 API 简化至 Steam 排行榜所必需的信息,尽量简单明了。
第一步:定义游戏排行榜
排行榜专属于各个应用程序,在 Steamworks 合作伙伴站点中的
排行榜配置页面进行设置。
要定义排行榜,必须填写以下字段:
- 名称 - 内部开发可用的合理名称。
- 社区名称 - 如要在社区中心显示此排行榜,在此设置公开显示的名称。 如未输入名称,则该排行榜将不会显示。
- 排序方式 - 设置排行榜的排列顺序。 按名次的排行榜请使用升序。 高分榜请使用降序。
- 显示类型 - 决定排行榜显示的数据类型。 可选择数字、秒或毫秒。
- 写入 - 如设置为“可信任”,客户端便无法设置排行榜分数,只能通过 SetLeaderboardScore WebAPI 设置。 默认为 false。
- 读取 - 如选择为“好友”,游戏便只能读取该用户好友的排行榜分数,但 WebAPI 可始终读取所有分数。 默认为 false。
第二步:封装排行榜工作
以下代码独立于游戏之外,您可将其放入游戏中合适的地方。 此类代码已可正常运行,但也可轻易扩展,满足更多需求。 所有代码均直接来自于 Spacewar 的示例文件
Leaderboards.cpp/h
。
头文件
定义一个帮助程序类,可用于包装所有 Steam 排行榜 API 调用及创建所有 Steam 调用结果处理程序。
class CSteamLeaderboards
{
private:
SteamLeaderboard_t m_CurrentLeaderboard; // 排行榜句柄
public:
int m_nLeaderboardEntries; // 有多少个条目?
LeaderboardEntry_t m_leaderboardEntries[10]; // 条目
CSteamLeaderboards();
~CSteamLeaderboards(){};
void FindLeaderboard( const char *pchLeaderboardName );
bool UploadScore( int score );
bool DownloadScores();
void OnFindLeaderboard( LeaderboardFindResult_t *pResult, bool bIOFailure);
CCallResult m_callResultFindLeaderboard;
void OnUploadScore( LeaderboardScoreUploaded_t *pResult, bool bIOFailure);
CCallResult m_callResultUploadScore;
void OnDownloadScore( LeaderboardScoresDownloaded_t *pResult, bool bIOFailure);
CCallResult m_callResultDownloadScore;
};
代码文件
构造函数
参数 - 无
返回 – 不适用
作用 - 此构造函数只初始化成员变量。
CSteamLeaderboards::CSteamLeaderboards() :
m_CurrentLeaderboard( NULL ),
m_nLeaderboardEntries( 0 )
{
}
FindLeaderboard()
参数 - 您要设置的排行榜字符串标识符(如 "Feet Traveled")
返回 - 无
作用 - 包装对
ISteamUserStats::FindLeaderboard 的调用。该调用为对 Steam 的异步调用,请求给定排行榜的句柄。 必须执行该调用后才能检索或设置排行榜条目。 该方法也可设置要使用的调用返回方法。
void CSteamLeaderboards::FindLeaderboard( const char *pchLeaderboardName )
{
m_CurrentLeaderboard = NULL;
SteamAPICall_t hSteamAPICall = SteamUserStats()->FindLeaderboard(pchLeaderboardName);
m_callResultFindLeaderboard.Set(hSteamAPICall, this,
&CSteamLeaderboards::OnFindLeaderboard);
}
OnFindLeaderboard()
参数 – 不适用
返回 - 无
作用 - 尝试在 Steam 上寻找排行榜时调用的回调方法。 如找到请求的排行榜,则设置该排行榜句柄为当前排行榜。
void CSteamLeaderboards::OnFindLeaderboard( LeaderboardFindResult_t *pCallback, bool bIOFailure )
{
// 检查调用期间是否遇到错误
if ( !pCallback->m_bLeaderboardFound || bIOFailure )
{
OutputDebugString( "Leaderboard could not be found\n" );
return;
}
m_CurrentLeaderboard = pCallback->m_hSteamLeaderboard;
}
UploadScore()
参数 - 一个 int32,表示将存入当前排行榜的值。
返回 - 如果尚未选择排行榜,返回 False ,否则返回 True。
作用 - 包装对
ISteamUserStats::UploadLeaderboardScore 的调用。该调用为对 Steam 的异步调用,将当前用户分数上传至当前已选排行榜。 该方法也可设置要使用的调用返回方法。 在使用
FindLeaderboard()
选择排行榜后方可执行此调用。
bool CSteamLeaderboards::UploadScore( int score )
{
if (!m_CurrentLeaderboard)
return false;
SteamAPICall_t hSteamAPICall =
SteamUserStats()->UploadLeaderboardScore( m_CurrentLeaderboard, k_ELeaderboardUploadScoreMethodKeepBest, score, NULL, 0 );
m_callResultUploadScore.Set(hSteamAPICall, this, &CSteamLeaderboards::OnUploadScore);
return true;
}
OnUploadScore()
参数 – 不适用
返回 - 无
作用 - 尝试将分数上传至 Steam 排行榜时调用的回调方法。
void CSteamLeaderboards::OnUploadScore(LeaderboardScoreUploaded_t *pCallback, bool bIOFailure)
{
if ( !pCallback->m_bSuccess || bIOFailure )
{
OutputDebugString( "Score could not be uploaded to Steam\n" );
}
}
DownloadScores()
参数 – 不适用
返回 - 如果尚未选择排行榜,返回 False ,否则返回 True。
作用 - 包装对
ISteamUserStats::DownloadLeaderboardEntries 的调用。该调用为指向 Steam 的异步调用,从当前已选排行榜下载条目。 下方示例中我们下载十个条目:当前用户之前四条、当前用户及当前用户之后五条。 此调用可进行修改,以从排行榜任意位置返回任意数量的条目。 该方法也可设置要使用的调用返回方法。 在使用
FindLeaderboard()
选择排行榜后方可执行此调用。
bool CSteamLeaderboards::DownloadScores()
{
if (!m_CurrentLeaderboard)
return false;
// 加载当前用户的特定排行榜数据
SteamAPICall_t hSteamAPICall = SteamUserStats()->DownloadLeaderboardEntries(
m_CurrentLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -4, 5);
m_callResultDownloadScore.Set(hSteamAPICall, this,
&CSteamLeaderboards::OnDownloadScore);
return true;
}
OnDownloadScore()
参数 – 不适用
返回 - 无
作用 - 尝试从 Steam 排行榜下载条目时调用的回调方法。 成功下载数据后,将数据复制至条目数组中。 已下载条目数量存储于
m_nLeaderboardEntries
。
void CSteamLeaderboards::OnDownloadScore(LeaderboardScoresDownloaded_t *pCallback, bool bIOFailure)
{
if (!bIOFailure)
{
m_nLeaderboardEntries = min(pCallback->m_cEntryCount, 10);
for (int index = 0; index < m_nLeaderboardEntries; index++)
{
SteamUserStats()->GetDownloadedLeaderboardEntry(
pCallback->m_hSteamLeaderboardEntries,index,&m_leaderboardEntries[index],NULL,0);
}
}
}
第三步:与游戏集成
以下是您需要整合至游戏中适当位置的代码段的完整列表。
定义和全局
以下是建立排行榜所需的 include 列表及指向帮助程序对象的全局指针。
...
#include "steam_api.h"
#include "SteamLeaderboards.h"
// 排行榜对象的全局访问
CSteamLeaderboards* g_SteamLeaderboards = NULL;
...
初始化
调用
SteamAPI_Init 可以全面初始化 Steam,且必须早于任何其他调用。 如果调用成功,即可创建帮助程序对象。
...
// 初始化 Steam
bool bRet = SteamAPI_Init();
// 如果 Steam 初始化成功,则创建 SteamLeaderboards 对象
if (bRet)
{
g_SteamLeaderboards = new CSteamLeaderboards();
}
...
回调处理
为了确保处理到所有 Steam 回调,我们需要经常抽取新的信息。 将此调用加入游戏循环即可达到效果。
...
SteamAPI_RunCallbacks();
...
关闭
对
SteamAPI_Shutdown 的调用可能已存在于您的代码中。 此调用将关闭 Steam,且必须在应用程序退出之前调用。 最后我们需要删除先前建立的帮助程序对象。
...
// 关闭 Steam
SteamAPI_Shutdown();
// 删除 SteamLeaderboards 对象
if (g_SteamLeaderboards)
delete g_SteamLeaderboards;
...
第四步:测试和故障排除
此示例代码可向调试控制台输出调试信息,帮您了解成功和失败的调用信息。 以下是一些典型的失败信息和修复方法:
This application has failed to start because steam_api.dll was not found. Re-installing the application may fix this problem.(由于未找到 steam_api.dll,此应用程序启动失败。重新安装应用程序也许能修复问题。)请确定 steam_api.dll 与可执行文件处于同一个目录。
[S_API FAIL] SteamAPI_Init() failed; unable to locate a running instance of Steam, or a localsteamclient.dll ([S_API FAIL] SteamAPI_Init()失败;未找到运行的 Steam 实例或本地 steamclient.dll)很可能是因为您的 Steam 客户端没有在运行。 启动 Steam 并登录。
[S_API FAIL] SteamAPI_Init() failed; no appID found.([S_API FAIL] SteamAPI_Init() 失败;未找到 appID。)很可能是因为您的 steam_appid.txt 文件不在正确的位置上。 将其放入您的源文件夹,并确保其中包含您的 appID 号码。