Tài liệu Steamworks
Từng bước một: Bảng xếp hạng

Giới thiệu

Sau đây là hướng dẫn từng bước ngắn gọn để tích hợp bảng xếp hạng Steam vô cùng cơ bản vào ứng dụng dưới 10 phút. Steamworks SDK có một ứng dụng ví dụ tuyệt vời mang tên Spacewar phô diễn tất tần tật các tính năng Steam và nên là chặng dừng đầu tiên của bạn để xem cách mọi tính năng Steam vận hành. Hướng dẫn này cô đọng thông tin tìm thấy trong Spacewar và API bảng xếp hạng tại ISteamUserStats thành thông tin cần thiết cho bảng xếp hạng Steam, theo cách đơn giản và rõ ràng nhất có thể.

Bước 1 - Xác định bảng xếp hạng trò chơi

Bảng xếp hạng dành riêng cho ứng dụng và được cài đặt trên trang thiết lập bảng xếp hạng tại trang web đối tác Steamworks.

Để xác định bảng xếp hạng, bạn phải điền các trường sau:
  • Tên - Đặt một cái tên có nghĩa tới quá trình phát triển nội bộ.
  • Tên cộng đồng - Nếu bảng xếp hạng xuất hiện trong trung tâm cộng đồng, nhập tên hiển thị công khai tại đây. Nếu để trống, bảng xếp hạng sẽ không xuất hiện.
  • Phương pháp phân loại - Đặt thứ tự cho bảng xếp hạng. Khi xếp hạng theo vị trí, sử dụng thứ tự tăng dần. Khi xếp hạng theo số điểm cao nhất, dùng thứ tự giảm dần.
  • Kiểu hiển thị - Xác định loại dữ liệu hiển thị trong bảng xếp hạng. Chọn số, giây hoặc mili giây.
  • Viết - Nếu ở chế độ Trusted, điểm số bản xếp hạng không thể đặt bởi client, mà phải thông qua WebAPI SetLeaderboardScore. Mặc định là false.
  • Đọc - Nếu ở chế độ Friends, trò chơi chỉ có thể đọc điểm số bảng xếp hạng của bạn bè người dùng, nhưng WebAPI có thể đọc tất cả điểm số. Mặc định là false.

spacewar_leaderboards

Bước 2 - Tóm lược công việc bảng xếp hạng

Mã sau tồn tại độc lập với trò chơi và có thể thêm vào trò chơi nếu thích hợp. Class này vốn đã đầy đủ chức năng, nhưng cũng có thể dễ dàng mở rộng để đáp ứng nhiều nhu cầu hơn. Tất cả mã được lấy từ file ví dụ Spacewar Leaderboards.cpp/h.

Header của file

Chúng tôi định nghĩa một class helper sẽ bọc mọi lệnh gọi API của bảng xếp hạng Steam, cũng như tạo tất cả handler kết quả gọi của Steam.
class CSteamLeaderboards { private: SteamLeaderboard_t m_CurrentLeaderboard; // Handle to leaderboard public: int m_nLeaderboardEntries; // How many entries do we have? LeaderboardEntry_t m_leaderboardEntries[10]; // The entries 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; };

Mã file

Constructor

Tham số - Không
Trả về – N/A
Chức năng - Constructor này khởi chạy các biến thành viên.
CSteamLeaderboards::CSteamLeaderboards() : m_CurrentLeaderboard( NULL ), m_nLeaderboardEntries( 0 ) { }

FindLeaderboard()

Tham số - Chuỗi indentifier của bảng xếp hạng bạn muốn tìm (vd: "Quãng đường tính bằng feet")
Trả về - Trống
Chức năng - Phương pháp này gói một lệnh gọi tới ISteamUserStats::FindLeaderboard, tức là một lệnh gọi không đồng bộ tới Steam, yêu cầu xử lý một handle đến bảng xếp hạng xác định. Bạn cần thực hiện lệnh gọi này trước khi truy xuất hoặc thiết lập các mục trong bảng xếp hạng. Cách này cũng thiết lập phương pháp trả về cuộc gọi để sử dụng.
void CSteamLeaderboards::FindLeaderboard( const char *pchLeaderboardName ) { m_CurrentLeaderboard = NULL; SteamAPICall_t hSteamAPICall = SteamUserStats()->FindLeaderboard(pchLeaderboardName); m_callResultFindLeaderboard.Set(hSteamAPICall, this, &CSteamLeaderboards::OnFindLeaderboard); }

OnFindLeaderboard()

Tham số - N/A
Trả về - Trống
Chức năng - Phương pháp này là một hàm callback, được kích hoạt bất cứ khi nào bắt đầu tìm một bảng xếp hạng trên Steam. Nếu tìm thấy bảng xếp hạng yêu cầu, handle bảng xếp hạng được đặt làm bảng xếp hạng hiện tại.
void CSteamLeaderboards::OnFindLeaderboard( LeaderboardFindResult_t *pCallback, bool bIOFailure ) { // kiểm tra nếu có lỗi trong khi gửi lệnh call không if ( !pCallback->m_bLeaderboardFound || bIOFailure ) { OutputDebugString( "Không tìm thấy leaderboard\n" ); return; } m_CurrentLeaderboard = pCallback->m_hSteamLeaderboard; }

UploadScore()

Tham số - int32 đại diện cho giá trị lưu trữ trong bảng xếp hạng hiện tại.
Trả về - false nếu chưa chọn bảng xếp hạng, nếu không, nó sẽ trả về true.
Chức năng - Phương pháp này gói một lệnh gọi tới ISteamUserStats::UploadLeaderboardScore, tức là một lệnh gọi không đồng bộ tới Steam, để tải điểm số của người dùng hiện tại lên bảng xếp hạng hiện được chọn. Cách này cũng thiết lập phương pháp trả về cuộc gọi để sử dụng. Cần thực hiện lệnh gọi này sau khi bạn đã chọn một bảng xếp hạng thông qua 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()

Tham số - N/A
Trả về - Trống
Chức năng - Phương pháp này là một lệnh gọi lại, được kích hoạt bất cứ khi nào cố gắng tải điểm số lên một bảng xếp hạng trên Steam.
void CSteamLeaderboards::OnUploadScore(LeaderboardScoreUploaded_t *pCallback, bool bIOFailure) { if ( !pCallback->m_bSuccess || bIOFailure ) { OutputDebugString( "Không thể gửi score tới Steam\n" ); } }

DownloadScores()

Tham số - N/A
Trả về - false nếu chưa chọn bảng xếp hạng, còn không sẽ trả về true.
Chức năng - Phương pháp này gói một lệnh gọi tới ISteamUserStats::DownloadLeaderboardEntrie, tức là một lệnh gọi không đồng bộ tới Steam, để tải xuống một bộ mục nhập từ bảng xếp hạng hiện được chọn. Trong trường hợp này, chúng ta đang tải xuống 10 mục nhập; 4 trước người dùng hiện tại, người dùng hiện tại, và 5 sau người dùng hiện tại. Lệnh gọi này có thể thay đổi để trả về bất kỳ lượng mục nhập vào từ mọi nơi trong bản xếp hạng. Cách này cũng thiết lập phương pháp trả về cuộc gọi để sử dụng. Cần thực hiện lệnh gọi này sau khi bạn đã chọn một bảng xếp hạng thông qua FindLeaderboard().
bool CSteamLeaderboards::DownloadScores() { if (!m_CurrentLeaderboard) return false; // nạp dữ liệu bảng xếp hạng cụ thể về người dùng này SteamAPICall_t hSteamAPICall = SteamUserStats()->DownloadLeaderboardEntries( m_CurrentLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -4, 5); m_callResultDownloadScore.Set(hSteamAPICall, this, &CSteamLeaderboards::OnDownloadScore); return true; }

OnDownloadScore()

Tham số - N/A
Trả về - Trống
Chức năng - Phương pháp này là một lệnh gọi lại, được kích hoạt bất cứ khi nào cố gắng tải xuống mục nhập từ một bảng xếp hạng trên Steam. Sau khi tải xuống thành công, dữ liệu sẽ được sao chép vào một loạt mục nhập. Số lượng mục nhập tải xuống được lưu trong 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); } } }

Bước 3 - Tích hợp vào trò chơi

Đây là danh sách đầy đủ các đoạn mã bạn cần để tích hợp vào trò chơi tại những vị trí thích hợp.

Các Define và Global

Dưới đây là danh sách các mục cần thiết để xây dựng với bảng xếp hạng và con trỏ chung cho các object helper.
... #include "steam_api.h" #include "SteamLeaderboards.h" // Truy cập chung tới đối tượng bảng xếp hạng CSteamLeaderboards* g_SteamLeaderboards = NULL; ...

Khởi chạy

Lệnh gọi tới SteamAPI_Init khởi chạy toàn bộ Steam và phải được thực hiện trước hết. Nếu lệnh gọi thành công, object helper sẽ được tạo.
... // Khởi chạy Steam bool bRet = SteamAPI_Init(); // Tạo đối tượng SteamLeaderboards nếu khởi chạy Steam thành công if (bRet) { g_SteamLeaderboards = new CSteamLeaderboards(); } ...

Xử lý lệnh gọi lại

Để đảm bảo xử lý tất cả lệnh gọi lại trên Steam, ta cần thường xuyên bơm tin nhắn mới. Thực hiện bằng cách thêm lệnh gọi vào vòng lặp trò chơi.
... SteamAPI_RunCallbacks(); ...

Tắt

Lệnh gọi tới SteamAPI_Shutdown có lẽ đã tồn tại trong mã của bạn. Nó tắt Steam và phải được gọi trước khi thoát ứng dụng. Cuối cùng, xóa đối object helper đã tạo.
... // Tắt Steam SteamAPI_Shutdown(); // Xóa đối tượng SteamLeaderboards if (g_SteamLeaderboards) delete g_SteamLeaderboards; ...

Bước 4 - Thử nghiệm và xử lý sự cố

Mã mẫu này xuất thông tin gỡ lỗi tới console gỡ lỗi, giúp bạn biết lệnh gọi nào thành công hoặc thất bại. Sau đây là vài thông báo lỗi điển hình và cách sửa:

Ứng dụng này không thể khởi chạy vì không tìm thấy steam_api.dll. Cài đặt lại ứng dụng có thể giải quyết vấn đề này.
Đảm bảo rằng steam_api.dll ở cùng thư mục với file thực thi.

[S_API FAIL] SteamAPI_Init() failed; unable to locate a running instance of Steam, or a local steamclient.dll
Rất có thể không có phần mềm Steam nào đang chạy. Khởi động Steam và đăng nhập.

[S_API FAIL] SteamAPI_Init() failed; no appID found.
Rất có thể tệp steam_appid.txt không ở đúng vị trí. Đặt nó vào thư mục nguồn và đảm bảo rằng nó chứa mã appID của bạn.