Introdução
O que se segue é um guia passo a passo rápido para integrar tabelas de classificações Steam bem básicas no seu aplicativo em menos de 10 minutos. O
SDK do Steamworks vem com um ótimo aplicativo de exemplo denominado
Spacewar que demonstra os diversos recursos do Steam e deve ser o primeiro lugar para ver todos os recursos do Steam em ação. Este tutorial detalha apenas as informações encontradas no Spacewar e na API de tabelas de classificações contida em
ISteamUserStats que são necessárias para tabelas de classificações para que seja o mais direto possível.
1º passo — Definição das tabelas de classificação do jogo
Tabelas de classificação são separadas por aplicativo e configuradas pela página de
configuração de classificações no site de parceiros Steamworks.
Os campos a seguir devem ser preenchidos para definir uma tabela de classificações:
- Nome — Um nome que faça sentido como parte do desenvolvimento interno;
- Nome na Comunidade — Se a tabela deverá ser exibida na Central da Comunidade, defina o nome público aqui. Se não houver um nome preenchido, a tabela não será exibida;
- Forma de ordenação — Define a forma de ordenação da tabela. Para tabelas baseadas em posição, use crescente. Para recordes de pontuação, use decrescente;
- Tipo de exibição — Determina o tipo de dado que será exibido na tabela. Selecione entre numérico, segundos ou milissegundos;
- Escritas Se definido como "Fontes confiáveis" as pontuações da tabela não poderão ser definidas por clientes, apenas pela Web API SetLeaderboardScore. Padrão: false;
- Leituras — Se definido como "Amigos", o jogo só poderá consultar as pontuações de amigos do usuário. A Web API sempre terá acesso a todas as pontuações na tabela. Padrão: false.
2º passo — Encapsulamento do funcionamento de tabelas de classificações
O código a seguir independe do jogo e pode ser adicionado ao seu jogo da forma que achar melhor. A classe é completamente funcional, mas pode ser estendida para atender a necessidades adicionais. O código foi extraído dos arquivos de exemplo do Spacewar
Leaderboards.cpp/h
. Strings literais e comentários foram traduzidos para uma melhor compreensão.
Arquivo de cabeçalho
Definimos uma classe auxiliar, que encapsulará todas as chamadas à API de tabelas de classificações do Steam assim como criar os handlers aos resultados de chamada do Steam.
class CSteamLeaderboards
{
private:
SteamLeaderboard_t m_CurrentLeaderboard; // Handle para a tabela
public:
int m_nLeaderboardEntries; // Quantas entradas temos?
LeaderboardEntry_t m_leaderboardEntries[10]; // As entradas
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;
};
Arquivo de código
Construtor
Parâmetros — Nenhum
Retorna — Nada
O que faz — Este construtor apenas inicializa as variáveis-membro.
CSteamLeaderboards::CSteamLeaderboards() :
m_CurrentLeaderboard( NULL ),
m_nLeaderboardEntries( 0 )
{
}
FindLeaderboard()
Parâmetros — Uma string que identifica a tabela que deseja recuperar (ex.: "Metros percorridos")
Retorna — Nada
O que faz — Este método encapsula uma chamada à função
ISteamUserStats::FindLeaderboard, que é uma chamada assíncrona ao Steam requisitando um handle para a tabela informada. Precisa ser realizada antes de recuperar ou definir entradas da tabela. Também configura o método usado para o resultado de chamada.
void CSteamLeaderboards::FindLeaderboard( const char *pchLeaderboardName )
{
m_CurrentLeaderboard = NULL;
SteamAPICall_t hSteamAPICall = SteamUserStats()->FindLeaderboard(pchLeaderboardName);
m_callResultFindLeaderboard.Set(hSteamAPICall, this,
&CSteamLeaderboards::OnFindLeaderboard);
}
OnFindLeaderboard()
Parâmetros — Nenhum
Retorna — Nada
O que faz — Este método é um retorno de chamada, disparado sempre que tentamos buscar uma tabela de classificações no Steam. Se a tabela requisitada foi encontrada, então definimos o handle como a tabela atual.
void CSteamLeaderboards::OnFindLeaderboard( LeaderboardFindResult_t *pCallback, bool bIOFailure )
{
// Verifica se houve erro durante a chamada
if ( !pCallback->m_bLeaderboardFound || bIOFailure )
{
OutputDebugString( "Tabela nao encontrada\n" );
return;
}
m_CurrentLeaderboard = pCallback->m_hSteamLeaderboard;
}
UploadScore()
Parâmetros — Um int32 que representa o valor a ser armazenado na tabela atual.
Retorna — false se a tabela não foi selecionada; true caso contrário.
O que faz — Este método encapsula uma chamada à função
ISteamUserStats::UploadLeaderboardScore, que é uma chamada assíncrona ao Steam que envia a pontuação do usuário atual à tabela atualmente selecionada. Também configura o método usado para o resultado de chamada. Deve ser chamado depois de selecionar uma tabela por meio do método
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()
Parâmetros — Nada
Retorna — Nada
O que faz — Este método é um retorno de chamada, disparado sempre que tentamos enviar uma pontuação a uma tabela no Steam.
void CSteamLeaderboards::OnUploadScore(LeaderboardScoreUploaded_t *pCallback, bool bIOFailure)
{
if ( !pCallback->m_bSuccess || bIOFailure )
{
OutputDebugString( "Nao foi possivel salvar a pontuacao no Steam\n" );
}
}
DownloadScores()
Parâmetros — Nenhum
Retorna — false se a tabela não foi selecionada; true caso contrário.
O que faz — Este método encapsula uma chamada à função
ISteamUserStats::DownloadLeaderboardEntries, que é uma chamada assíncrona ao Steam para baixar um conjunto de entradas da tabela atualmente selecionada. Neste caso, estamos baixando dez entradas; quatro anteriores ao usuário atual, a do usuário atual e cinco posteriores ao usuário atual. Essa chamada pode ser alterada para retornar n entradas de qualquer posição da tabela. Também configura o método usado para o resultado de chamada. Deve ser chamado depois de selecionar uma tabela por meio do método
FindLeaderboard()
.
bool CSteamLeaderboards::DownloadScores()
{
if (!m_CurrentLeaderboard)
return false;
// carrega os dados da tabela especificada proximos ao usuario atual
SteamAPICall_t hSteamAPICall = SteamUserStats()->DownloadLeaderboardEntries(
m_CurrentLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -4, 5);
m_callResultDownloadScore.Set(hSteamAPICall, this,
&CSteamLeaderboards::OnDownloadScore);
return true;
}
OnDownloadScore()
Parâmetros — Nenhum
Retorna — Nada
O que faz — Este método é um retorno de chamada, disparado sempre que tentamos baixar entradas de uma tabela do Steam. Se os dados foram baixados com sucesso, então os copiamos ao nosso vetor de entradas. A quantidade de entradas baixadas é armazenada na variável
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);
}
}
}
3º passo — Integração com o jogo
Segue uma listagem completa de trechos de códigos que precisam ser integrados ao jogo nos locais apropriados.
Defines e globais
Confira abaixo uma lista de
include
s necessários para a construção com tabelas de classificações e um ponteiro global ao nosso objeto auxiliar.
...
#include "steam_api.h"
#include "SteamLeaderboards.h"
// Acesso global ao objeto auxiliar de tabelas de classificações
CSteamLeaderboards* g_SteamLeaderboards = NULL;
...
Inicialização
Esta chamada à função
SteamAPI_Init inicializará a base do Steam e deve ser chamada antes de qualquer outra função da API. Se bem-sucedida, então criamos o objeto.
...
// Inicializacao do Steam
bool bRet = SteamAPI_Init();
// Criacao do objeto SteamLeaderboards se o Steam foi inicializado com sucesso
if (bRet)
{
g_SteamLeaderboards = new CSteamLeaderboards();
}
...
Processamento de retornos de chamada
Para garantir o processamento de todos os retornos de chamada do Steam, precisamos sempre verificar se há novas mensagens. Para tal, adicionamos a chamada a seguir ao ciclo de vida do jogo.
...
SteamAPI_RunCallbacks();
...
Encerramento
O seu código já deve ter uma chamada à função
SteamAPI_Shutdown. Ela encerra o Steam e deve ser chamada antes do encerramento do aplicativo. Por último, excluímos o objeto auxiliar criado.
...
// Encerramento do Steam
SteamAPI_Shutdown();
// Exclusao do objeto SteamLeaderboards
if (g_SteamLeaderboards)
delete g_SteamLeaderboards;
...
4º passo — Testes e solução de problemas
Este código de amostra imprime dados de depuração ao console de depuração, facilitando a compreensão de quais chamadas estão funcionando e quais estão falhando. Confira abaixo algumas mensagens de falha comuns, assim como correções:
This application has failed to start because steam_api.dll was not found. Re-installing the application may fix this problem.(
O aplicativo falhou em iniciar porque steam_api.dll não foi encontrado. Reinstalar o aplicativo pode corrigir este problema.)
Confirme que o arquivo steam_api.dll está no mesmo diretório do executável.
[S_API FAIL] SteamAPI_Init() failed; unable to locate a running instance of Steam, or a local steamclient.dll(
[S_API FAIL] SteamAPI_Init() falhou; não foi possível encontrar uma instância local do Steam ou um arquivo steamclient.dll local)
É possível que não haja um cliente Steam em execução. Inicie o Steam e inicie a sessão.
[S_API FAIL] SteamAPI_Init() failed; no appID found.(
[S_API FAIL] SteamAPI_Init() falhou; nenhum AppID encontrado.)
É possível que o arquivo steam_appid.txt não esteja no lugar certo. Coloque-o na pasta de códigos-fonte e confirme que ele contém o número do AppID.