Documentazione di Steamworks
Tutorial sulle classifiche

Introduzione

Quella che segue è una guida rapida per aiutarti a integrare le classifiche di Steam più basilari nella tua applicazione in meno di 10 minuti. L'SDK di Steamworks include un'ottima applicazione esemplificativa denominata Spacewar che mostra l'intera gamma delle funzionalità di Steam e consente di vederle in azione. In questo tutorial, le informazioni disponibili in Spacewar e nell'API delle classifiche in ISteamUserStats vengono sintetizzate e ridotte al necessario per rendere il procedimento il più semplice possibile.

Passaggio 1: definizione delle classifiche del gioco

Le classifiche sono diverse per ogni applicazione e possono essere configurate nella pagina di configurazione delle classifiche nel sito dei partner di Steamworks.

Per definire una classifica è necessario compilare i campi di seguito:
  • Nome: assegna un nome che possa avere senso ai fini del tuo processo di sviluppo interno.
  • Nome nella Comunità: se la classifica verrà mostrata nell'hub della Comunità, inserisci qui il nome pubblico da visualizzare. Se non inserisci alcun nome, la classifica non verrà mostrata.
  • Metodo di ordinamento: definisci un criterio per ordinare i dati della classifica. Seleziona "Crescente" per le classifiche basate sulla posizione e "Decrescente" per quelle basate sul punteggio più alto.
  • Tipo da mostrare: determina i tipi di dati da visualizzare con la classifica. Seleziona un'opzione tra "Numerico", "Secondi" e "Millisecondi".
  • Scritture: se impostato su "Affidabile", i punteggi della classifica non potranno essere definiti dai client, ma soltanto tramite l'API web SetLeaderboardScore. Il valore predefinito è "false".
  • Letture: se impostato su "Amici", il gioco potrà leggere solo i punteggi degli amici dell'utente. Tutti i punteggi possono comunque essere letti dall'API web. Il valore predefinito è "false".

spacewar_leaderboards

Passaggio 2: incapsulamento delle classifiche

Il codice presentato di seguito non dipende dal gioco e può essere aggiunto al tuo titolo come meglio credi. La classe è già completamente funzionante, ma può essere estesa per soddisfare qualsiasi ulteriore necessità. L'intero codice è stato estratto direttamente dai file di esempio di Spacewar Leaderboards.cpp/h.

File di intestazione

Definiamo una classe helper in grado di incapsulare tutte le chiamate all'API delle classifiche di Steam e di creare tutti gli handler per i risultati delle chiamate di Steam.
class CSteamLeaderboards { private: SteamLeaderboard_t m_CurrentLeaderboard; // Handle per la classifica public: int m_nLeaderboardEntries; // Quante voci abbiamo? LeaderboardEntry_t m_leaderboardEntries[10]; // Le voci 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; };

File del codice

Costruttore

Parametri: nessuno.
Restituisce: nessun valore.
Funzione: il costruttore si limita a inizializzare le variabili membro.
CSteamLeaderboards::CSteamLeaderboards() : m_CurrentLeaderboard( NULL ), m_nLeaderboardEntries( 0 ) { }

FindLeaderboard()

Parametri: una stringa che identifica la classifica che vuoi cercare (ad esempio: "Feet Traveled").
Restituisce: nessun valore.
Funzione: questo metodo include una chiamata asincrona a ISteamUserStats::FindLeaderboard per richiedere l'handle per la classifica di interesse. È necessario effettuare questa chiamata prima di poter recuperare o impostare le voci della classifica. Viene definito anche il metodo di callback da utilizzare.
void CSteamLeaderboards::FindLeaderboard( const char *pchLeaderboardName ) { m_CurrentLeaderboard = NULL; SteamAPICall_t hSteamAPICall = SteamUserStats()->FindLeaderboard(pchLeaderboardName); m_callResultFindLeaderboard.Set(hSteamAPICall, this, &CSteamLeaderboards::OnFindLeaderboard); }

OnFindLeaderboard()

Parametri: nessuno.
Restituisce: nessun valore.
Funzione: questo metodo è una callback chiamata a ogni tentativo di ricerca di una classifica su Steam. Se la classifica richiesta è stata trovata, impostiamo il rispettivo handle come classifica attuale.
void CSteamLeaderboards::OnFindLeaderboard( LeaderboardFindResult_t *pCallback, bool bIOFailure ) { // Controlliamo se sono stati riscontrati errori durante la chiamata if ( !pCallback->m_bLeaderboardFound || bIOFailure ) { OutputDebugString( "Impossibile trovare la classifica\n" ); return; } m_CurrentLeaderboard = pCallback->m_hSteamLeaderboard; }

UploadScore()

Parametri: un int32 che rappresenta il valore da inserire nella classifica attuale.
Restituisce: "false" se la classifica non è ancora stata selezionata, altrimenti "true".
Funzione: questo metodo include una chiamata asincrona a ISteamUserStats::UploadLeaderboardScore per inserire il punteggio dell'utente attuale nella classifica attualmente selezionata. Viene definito anche il metodo di callback da utilizzare. Questa chiamata deve essere effettuata dopo aver selezionato una classifica tramite 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()

Parametri: nessuno.
Restituisce: nessun valore.
Funzione: questo metodo è una callback chiamata a ogni tentativo di inserimento di un punteggio in una classifica su Steam.
void CSteamLeaderboards::OnUploadScore(LeaderboardScoreUploaded_t *pCallback, bool bIOFailure) { if ( !pCallback->m_bSuccess || bIOFailure ) { OutputDebugString( "Impossibile salvare il punteggio su Steam\n" ); } }

DownloadScores()

Parametri: nessuno.
Restituisce: "false" se la classifica non è ancora stata selezionata, altrimenti "true".
Funzione: questo metodo include una chiamata asincrona a ISteamUserStats::DownloadLeaderboardEntries per scaricare una serie di voci dalla classifica attualmente selezionata. In questo caso scarichiamo dieci voci: quella dell'utente attuale, le quattro precedenti e le cinque successive. Questa chiamata può essere modificata per restituire tutte le voci desiderate da qualsiasi posizione nella classifica. Viene definito anche il metodo di callback da utilizzare. Questa chiamata deve essere effettuata dopo aver selezionato una classifica tramite FindLeaderboard().
bool CSteamLeaderboards::DownloadScores() { if (!m_CurrentLeaderboard) return false; // Carica i dati della classifica intorno all'utente attuale SteamAPICall_t hSteamAPICall = SteamUserStats()->DownloadLeaderboardEntries( m_CurrentLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -4, 5); m_callResultDownloadScore.Set(hSteamAPICall, this, &CSteamLeaderboards::OnDownloadScore); return true; }

OnDownloadScore()

Parametri: nessuno.
Restituisce: nessun valore.
Funzione: questo metodo è una callback chiamata a ogni tentativo di download delle voci di una classifica su Steam. Se sono stati scaricati correttamente, i dati vengono poi inseriti nel nostro array di voci. Il numero di voci scaricate viene inserito in 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); } } }

Passaggio 3: integrazione nel gioco

Di seguito è riportato l'elenco completo dei frammenti di codice che è necessario integrare al posto giusto all'interno del tuo gioco.

Definizioni e variabili globali

Di seguito elenchiamo le direttive "include" necessarie per lavorare con le classifiche e un puntatore globale al nostro oggetto helper.
.. #include "steam_api.h" #include "SteamLeaderboards.h" // Accesso globale all'oggetto delle classifiche CSteamLeaderboards* g_SteamLeaderboards = NULL; ...

Inizializzazione

La chiamata a SteamAPI_Init inizializza Steam e deve essere effettuata prima di qualsiasi altra operazione. Se la chiamata va a buon fine, procediamo alla creazione dell'oggetto helper.
... // Inizializza Steam bool bRet = SteamAPI_Init(); // Crea l'oggetto SteamLeaderboards in caso di inizializzazione corretta di Steam if (bRet) { g_SteamLeaderboards = new CSteamLeaderboards(); } ...

Elaborazione delle callback

Per garantire l'elaborazione di tutte le callback di Steam, è necessario verificare regolarmente se ci sono nuovi messaggi. Per farlo, aggiungiamo la seguente chiamata al ciclo del gioco.
... SteamAPI_RunCallbacks(); ...

Arresto

Probabilmente la chiamata a SteamAPI_Shutdown è già presente nel tuo codice. Tale funzione consente l'arresto di Steam e deve essere eseguita prima di uscire dall'applicazione. Eliminiamo infine l'oggetto helper creato in precedenza.
... // Arresta Steam SteamAPI_Shutdown(); // Elimina l'oggetto SteamLeaderboards if (g_SteamLeaderboards) delete g_SteamLeaderboards; ...

Passaggio 4: test e risoluzione dei problemi

Questo codice di esempio scrive nella console di debug una serie di informazioni utili per capire quali chiamate hanno esito positivo e quali non vanno a buon fine. Di seguito riportiamo alcuni messaggi di errore e come correggerli:

This application has failed to start because steam_api.dll was not found. Re-installing the application may fix this problem.
Assicurati che steam_api.dll si trovi nella stessa cartella dell'eseguibile.

[S_API FAIL] SteamAPI_Init() failed; unable to locate a running instance of Steam, or a local steamclient.dll.
Probabilmente il client di Steam non è in esecuzione. Avvia Steam ed effettua l'accesso.

[S_API FAIL] SteamAPI_Init() failed; no appID found.
Probabilmente il file steam_appid.txt non è nella posizione corretta. Inseriscilo nella cartella di origine e assicurati che contenga il numero del tuo appID.
  翻译: