Dokumentacja Steamworks
Statystyki: Krok po kroku

Wprowadzenie

Poniżej znajdują się instrukcje dotyczące integracji najprostszych osiągnięć z aplikacją, które mogą zostać wprowadzone w mniej niż 10 minut i do których nie trzeba więcej niż 10 linii kodu zawartych w głównym kodzie gry. Sekcja Steamworks SDK stanowi doskonały przykład aplikacji o nazwie Spacewar. Pokazuje całą gamę funkcji Steam w akcji, dlatego zaleca się, abyś się z nim zapoznał. W tym przewodniku informacje prezentowane w Spacewar są filtrowane, aby wyświetlić statystyki i osiągnięcia potrzebne do zrozumienia interfejsu API. Pamiętaj, że statystyki i osiągnięcia nakładają się na siebie, więc jeśli zintegrujesz obie funkcje, pamiętaj, że większość połączeń można łączyć.

1. Definicja osiągnięć

Osiągnięcia są zdefiniowane dla konkretnej aplikacji i są instalowane na stronie osiągnięć Stats Configuration w obszarze administracyjnym Steamworks. Oto osiągnięcia ze Spacewar:
stats_spacewar.png

2. Kapsułowanie osiągnięć

Poniższy kod działa we wszystkich grach i można go dodać do dowolnego z nich. Klasa jest już w pełni funkcjonalna, ale w razie potrzeby można ją łatwo rozszerzyć. Cały kod jest pobierany bezpośrednio z pliku Spacewar StatsAndAchievements.cpp/h.

Plik nagłówka

Po pierwsze, zdefiniowana jest struktura do przechowywania statystyk otrzymywanych z platformy Steam, tworzone jest wygodne wyliczanie w celu określenia ich typów, a makra są tworzone w celu tworzenia obiektów statystycznych. Te dane bezpośrednio odnoszą się do tego, co znaleźć można na strona konfiguracji statystyk.
#define _STAT_ID( id,type,name ) { id, type, name, 0, 0, 0, 0 } enum EStatTypes { STAT_INT = 0, STAT_FLOAT = 1, STAT_AVGRATE = 2, }; struct Stat_t { int m_ID; EStatTypes m_eStatType; const char *m_pchStatName; int m_iValue; float m_flValue; float m_flAvgNumerator; float m_flAvgDenominator; };

Ponadto definiowana jest klasa pomocnicza, która będzie zawierać wszystkie wywołania interfejsu statystyk.
class CSteamStats { private: int64 m_iAppID; // Our current AppID Stat_t *m_pStats; // Stats data int m_iNumStats; // The number of Stats bool m_bInitialized; // Have we called Request stats and received the callback? public: CSteamStats(Stat_t *Stats, int NumStats); ~CSteamStats(); bool RequestStats(); bool StoreStats(); STEAM_CALLBACK( CSteamStats, OnUserStatsReceived, UserStatsReceived_t, m_CallbackUserStatsReceived ); STEAM_CALLBACK( CSteamStats, OnUserStatsStored, UserStatsStored_t, m_CallbackUserStatsStored ); };

Kod programu

Konstruktor

Parametry — konstruktor przyjmuje wskaźnik do tablicy statystyk i długości tablicy. Format tej tablicy zostanie pokazany w głównym kodzie gry poniżej.
Odpowiedzi zwrotne — nie dotyczy.
Zastosowanie — inicjuje kilku członków i akceptuje identyfikator app ID bieżącej aplikacji. Oprócz tego łączy on metody wywołań zwrotnych w celu obsługi wywołań asynchronicznych na Steam. Na koniec wywołuje wywołanie funkcji RequestStats(), aby uzyskać statystyki i osiągnięcia bieżącego użytkownika.
CSteamStats::CSteamStats(Stat_t *Stats, int NumStats) : m_iAppID( 0 ), m_bInitialized( false ), m_CallbackUserStatsReceived( this, &CSteamStats::OnUserStatsReceived ), m_CallbackUserStatsStored( this, &CSteamStats::OnUserStatsStored ) { m_iAppID = SteamUtils()->GetAppID(); m_pStats = Stats; m_iNumStats = NumStats; RequestStats(); }

RequestStats()

Parametry — Brak
Odpowiedzi zwrotne — bool, wskazuje, czy połączenie powiodło się. Jeśli połączenie nie powiedzie się, najprawdopodobniej Steam nie zostanie zainicjowany. Przed wywołaniem musisz upewnić się, że klient jest otwarty i że wcześniej wywołano funkcję SteamAPI_Init.
Zastosowanie polega na tym, że ta metoda zasadniczo wywołuje funkcję ISteamUserStats::RequestCurrentStats, która jest asynchronicznym zapytaniem o statystyki bieżącego użytkownika. To wywołanie musi zostać wykonane przed zainstalowaniem statystyk i osiągnięć. Początkowe wywołanie tej metody występuje w konstruktorze. Możesz ją wywołać ponownie w dowolnym momencie, jeśli chcesz poznać zaktualizowane statystyki i osiągnięcia.
bool CSteamStats::RequestStats() { // Czy załadowano Steam? Jeśli nie, statystyki się nie powiodą. if (NULL == SteamUserStats() || NULL == SteamUser()) { return false; } // Użytkownik zalogowany? Jeśli nie, statystyki nie będą dostępne. if ( !SteamUser()->BLoggedOn() ) { return false; } // Poproś o statystyki. return SteamUserStats()->RequestCurrentStats(); }

StoreStats()

Parametry — Brak
Odpowiedzi zwrotne — bool, wskazuje, czy połączenie powiodło się. Jeśli połączenie nie powiedzie się, najprawdopodobniej Steam nie zostanie zainicjowany. Przed wywołaniem musisz upewnić się, że klient jest otwarty i że wcześniej wywołano funkcję SteamAPI_Init.
Zastosowanie polega na tym, że ta metoda zasadniczo wywołuje funkcję ISteamUserStats::RequestCurrentStats, która jest asynchronicznym zapytaniem o statystyki bieżącego użytkownika. To wywołanie musi zostać wykonane przed zainstalowaniem statystyk użytkownika.
bool CSteamStats::StoreStats() { if ( m_bInitialized ) { // załaduj statystyki for ( int iStat = 0; iStat < m_NumStats; ++iStat ) { Stat_t &stat = m_pStats[iStat]; switch (stat.m_eStatType) { case STAT_INT: SteamUserStats()->SetStat( stat.m_pchStatName, stat.m_iValue ); break; case STAT_FLOAT: SteamUserStats()->SetStat( stat.m_pchStatName, stat.m_flValue ); break; case STAT_AVGRATE: SteamUserStats()->UpdateAvgRateStat(stat.m_pchStatName, stat.m_flAvgNumerator, stat.m_flAvgDenominator ); // Uśredniony wynik jest obliczany dla nas SteamUserStats()->GetStat(stat.m_pchStatName, &stat.m_flValue ); break; default: break; } } return SteamUserStats()->StoreStats(); } }

OnUserStatsReceived()

Parametry — Brak
Odpowiedzi zwrotne — Nic
Zastosowanie — Ta metoda to odpowiedź zwrotna, który jest wysyłana, gdy gra próbuje zażądać statystyk na Steam. Możesz zażądać wyświetlenie statystyk poprzez RequestStats(). Ta metoda aktualizuje zmienną członka m_Stats w celu odzwierciedlenia najnowszych danych statystyk zwróconych przez Steam.
void CSteamStats::OnUserStatsReceived( UserStatsReceived_t *pCallback ) { // możemy otrzymywać zgłoszenia zwrotne o otrzymaniu statystyk innych gier, zignoruj je if ( m_iAppID == pCallback->m_nGameID ) { if ( k_EResultOK == pCallback->m_eResult ) { OutputDebugString( "Received stats and achievements from Steam\n" ); // załaduj statystyki for ( int iStat = 0; iStat < m_iNumStats; ++iStat ) { Stat_t &stat = m_Stats[iStat]; switch (stat.m_eStatType) { case STAT_INT: SteamUserStats()->GetStat(stat.m_pchStatName, &stat.m_iValue); break; case STAT_FLOAT: case STAT_AVGRATE: SteamUserStats()->GetStat(stat.m_pchStatName, &stat.m_flValue); break; default: break; } } m_bInitialized = true; } else { char buffer[128]; _snprintf( buffer, 128, "RequestStats - failed, %d\n", pCallback->m_eResult ); OutputDebugString( buffer ); } } }

OnUserStatsStored()

Parametry — Brak
Zwrócone wartości — Nic
Zastosowanie — Ta metoda to odpowiedź zwrotna, która jest wysyłana za każdym razem, gdy gra próbuje zapisać statystyki na Steam. Jeśli podczas próby ustawienia statystyk jedna z nich naruszy nałożone ograniczenia, poprzednie wartości zostaną przywrócone.
void CSteamStats::OnUserStatsStored( UserStatsStored_t *pCallback ) { // możemy otrzymywać zgłoszenia zwrotne o otrzymaniu statystyk innych gier, zignoruj je if ( m_iAppID == pCallback->m_nGameID ) { if ( k_EResultOK == pCallback->m_eResult ) { OutputDebugString( "StoreStats - success\n" ); } else if ( k_EResultInvalidParam == pCallback->m_eResult ) { // Jedna lub więcej statystyk naruszyło limit. Значения восстановлены, // a teraz musisz ponownie uruchomić wartości synchronizacji. OutputDebugString( "StoreStats - some failed to validate\n" ); // symuluj wiadomość zwrotną w celu odświeżenia wartości. UserStatsReceived_t callback; callback.m_eResult = k_EResultOK; callback.m_nGameID = m_iAppID; OnUserStatsReceived( &callback ); } else { char buffer[128]; _snprintf( buffer, 128, "StoreStats - failed, %d\n", pCallback->m_eResult ); OutputDebugString( buffer ); } } }

3. Integracja w grze

Poniżej znajduje się pełna lista fragmentów kodu, które należy zintegrować z grą w odpowiednich miejscach.

Definicje i zmienne globalne

Poniżej znajduje się lista elementów, które są potrzebne do tego potrzebne oraz tablica dla naszych statystyk dotyczących gry i globalnego wskaźnika do naszego obiektu pomocniczego. Statystyki są zbieżne z tymi, które są wymienione na stronie Steamworks.
... #include "steam_api.h" #include "isteamuserstats.h" #include "SteamStats.h" // Tablica statystyk zawierających statystyki i ich status Stat_t g_Stats[] = { _STAT_ID( 1, STAT_INT, "NumGames"), _STAT_ID( 2, STAT_INT, "NumWins"), _STAT_ID( 3, STAT_INT, "NumLosses"), _STAT_ID( 4, STAT_FLOAT, "FeetTraveled"), _STAT_ID( 5, STAT_AVGRATE, "AverageSpeed"), _STAT_ID( 7, STAT_FLOAT, "MaxFeetTraveled"), }; // Globalny dostęp do statystyk CSteamStats* g_SteamStats = NULL; ...

Inicjalizacja

Wywołanie SteamAPI_Init inicjuje Steam i musi zostać wykonane jako pierwsze. Jeśli wywołanie się powiedzie, tworzony jest obiekt pomocniczy, do którego przekazywane są tablica statystyk i rozmiar tablicy.
... // inicjalizacja Steam bool bRet = SteamAPI_Init(); // twórz obiekt SteamStats, jeśli inicjalizacja Steam powiedzie się if (bRet) { g_SteamStats = new CSteamStats(g_Stats, 6); } ...

Obsługa odpowiedzi zwrotnych

Aby obsłużyć wszystkie wywołania zwrotne Steam, musisz regularnie sprawdzać, czy nie pojawiły się nowe wiadomości. Aby to zrobić, należy dodać to połączenie do pętli gry.
... SteamAPI_RunCallbacks(); ...

Zachowywanie statystyk

Statystyki są zapisywane przy użyciu StoreStats().
... if (g_SteamStats) g_SteamStats->StoreStats(); ...

Zamykanie interfejsu SteamAPI

Wywołanie SteamAPI_Shutdown, które zamyka Steam, najprawdopodobniej znajduje się już w twoim kodzie. Musi zostać wysłane przed zamknięciem aplikacji. Na końcu poprzednio utworzony obiekt pomocniczy zostaje usunięty.
... // Zamknąć Steam SteamAPI_Shutdown(); // Usuń obiekt SteamStats if (g_SteamStats) delete g_SteamStats; ...

4. Testowanie i rozwiązywanie problemów

Ten przykładowy kod wyświetla informacje debugowania w konsoli debugowania, które są potrzebne do zrozumienia, które połączenia są wykonywane, a które nie. Poniżej przedstawiono typowe komunikaty o błędach i rozwiązania:

This application has failed to start because steam_api.dll was not found. Re-installing the application may fix this problem. (Aplikacja nie została uruchomiona, ponieważ nie znaleziono pliku d3dx_??. Dll. Ponowna instalacja aplikacji może rozwiązać problem).
Plik steam_api.dll powinien znajdować się w tym samym katalogu, co plik wykonywalny.

[S_API FAIL] SteamAPI_Init() failed; unable to locate a running instance of Steam, or a local steamclient.dll (Wywołanie funkcji SteamAPI_Init() nie powiodło się, ponieważ nie można znaleźć działającego pliku Steam lub lokalnego pliku steamclient.dll)
Najprawdopodobniej klient Steam nie działa. Uruchom Steam i zaloguj się.

[S_API FAIL] SteamAPI_Init() failed; no appID found. (Wywołanie funkcji SteamAPI_Init () nie powiodło się, nie znaleziono AppID)
Najprawdopodobniej brakuje pliku steam_appid.txt we właściwym folderze. Umieść go we właściwym miejscu i upewnij się, że ma numer aplikacji.