簡介
這篇文件將會逐步帶領您在十分鐘以內,將非常基本的 Steam 排行榜整合至您的應用程式中。
Steamworks SDK 之中有一個名為
Spacewar 的應用程式範例,完整展示了所有 Steam 功能。如要親眼見識 Steam 的所有功能,這便會是您的第一站。 這篇教學將 Spacewar 和排行榜 API 中的資訊簡化至 Steam 排行榜最基本的必要資料,讓教學盡量簡單明瞭。
第一步 - 定義遊戲的排行榜
排行榜是專屬於各個應用程式的,必須前往後端的 Steamworks 合作夥伴網站中的
排行榜設定頁面進行設定。
要定義排行榜,必須填入下列欄位:
- 名稱 - 開發階段內部可合理使用的名稱
- 社群名稱 - 如要在社群中心展示此排行榜,在此輸入公開顯示的名稱。 若留空,則不會出現排行榜
- 分類方式 - 設置排行榜的排列順序。 如果是排名式的排行榜,使用遞增。 如果是高分榜,使用遞減
- 顯示類型 - 決定排行榜顯示的資料類型。 可選擇數字、秒,或毫秒
- 寫入 - 如選擇受信任的,用戶端便無法設置分數,而只能由 SetLeaderboardScore WebAPI 設置。 預設是否
- 讀取 - 如選擇好友,遊戲便只能讀取使用者好友的排行榜分數。WebAPI 還是永遠可以讀取所有分數。 預設是否
第二步 - 封裝排行榜作業
以下的程式碼皆不限用於哪個遊戲,您可放入自己遊戲中合適的地方。 此類別目前的狀態即可正常運作,但如有更多需求,也可輕易擴展。 所有的程式碼都是直接從 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;
};
程式碼檔
建構函式
參數 - 無
傳回 - N/A
作用 初始化一個成員變數的建構函式。
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()
參數 - N/A
傳回 - 無
作用 - 每次嘗試在 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 的呼叫包裝起來。這是一個不同步呼叫,用來將目前使用者的分數上傳至目前選擇的排行榜。 此方法也會設定將使用的呼叫傳回方法。 必須先用
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()
參數 - N/A
傳回 - 無
作用 - 每次嘗試將分數上傳至 Steam 上的排行榜時使用的回呼方法。
void CSteamLeaderboards::OnUploadScore(LeaderboardScoreUploaded_t *pCallback, bool bIOFailure)
{
if ( !pCallback->m_bSuccess || bIOFailure )
{
OutputDebugString( "Score could not be uploaded to Steam\n" );
}
}
DownloadScores()
參數 - N/A
傳回 - 若尚未選擇排行榜,會傳回 False,不然則傳回 True。
作用 - 將發向
ISteamUserStats::DownloadLeaderboardScore 的呼叫包裝起來。這是一個不同步呼叫,用來從 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()
參數 - N/A
傳回 - 無
作用 - 每次嘗試從 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 和執行檔是否在同一個路徑。
[S_API FAIL] SteamAPI_Init() failed; unable to locate a running instance of Steam, or a local steamclient.dll很可能是因為您的 Steam 用戶端沒有在運作。 啟動並登入 Steam。
[S_API FAIL] SteamAPI_Init() failed; no appID found.很可能是因為您的 steam_appid.txt 不在正確的位置上。 將它放入來源資料夾,並確認裡面有您的 appID 號碼。