Overview
In order to help developers understand the usage of the Steamworks API we have included source code for a fully functional version of the classic
Spacewar! multi-player shooter game. It is a simple 2D game with support for up to 4 players and provides a perfect opportunity to showcase many of the APIs available in the Steamworks SDK.
As you look through the code keep in mind that our goal was to write a simple, stripped-down game so we could showcase the Steamworks API as clearly as possible. You won't find any magnificent new graphics tech here; instead we hope you'll find clear examples of how deeply to integrate Steamworks functionality into your own projects.
The APIs and Steamworks features demonstrated in the example code include:
- Cloud
- Community Integration (avatars, friends names, etc)
- Crash Reporting
- Friends
- HTML Surface
- Inventory
- Leaderboards
- Matchmaking (Both lobbies and server browser)
- Multi-Player Authentication (4 players supported in-game)
- Networking
- Stats & Achievements
- Voice Chat
Building & running the example
Requirements:
- Visual Studio 2005 or newer.
- DirectX SDK
- Steamworks SDK. (Download the latest release.)
Once you have downloaded and extracted the Steamworks SDK package, find the sub-directory named
SteamworksExample
. Inside of this directory you'll find
SteamworksExample.sln
, which can be opened in Visual Studio. Open the solution and compile the project. If compilation succeeds then you're ready to go and can run the project directly from Visual Studio (you'll need to have Steam running in the background). If the build or execution fails try one of the tips below.
Common Build Problems
- Cannot open include file: 'd3d9.h'
If you encounter this error it means that your systems include path does not include the D3D include path, or that you have not installed the D3D SDK. First, make sure you have downloaded and installed the DirectX SDK. Once the SDK is installed you need to set up the include path. You can do this system wide via the standard Visual Studio environment variables, or you can set them up just for the SteamworksExample project by editing the project properties.
- Fatal error LNK1104: cannot open file 'd3d9.lib'
If you encounter this error it means that your systems library path does not include the D3D library directory. See the instructions above, except you need to update the library path instead of the include path.
- Steam must be running to play this game (SteamAPI_Init failed).
If you encounter this error when running the game, make sure that Steam is running. If Steam is running, ensure there is a steam_appid.txt
file in the directory with the game executable. This file ships with the SDK example and should be present if you run from within Visual Studio or directly from the Debug or Release sub directories.
When you are launching the game from the exe directly, outside of the Steam UI this file must be present and must contain a single line with the game's AppID (for your games, Valve will assign each an AppID, the example game's AppID is 480). When you ship your own game through Steam this file will not be needed as Steam will auto-detect your AppID when the game is launched.
- The application has failed to start because steam_api.dll was not found. Re-installing the application may fix this problem.
In order to run successfully steam_api.dll
must be located in the same directory as the example game executable. This will also be true for your own games which utilize Steamworks. The Visual Studio project file should place the executable in the appropriate directory when building, but if you are using a different compiler or have modified the solution or project files you may need to copy it yourself. You can redistribute steam_api.dll
with your own Steamworks games when shipping them.
- The application has failed to start because d3dx_??.dll was not found. Re-installing the application may fix this problem.
The example relies on the D3D9X helper library which ships with the DirectX SDK. If you run the example on the same machine you have built it on the library should be found automatically. If you copy your compiled binary to another machine you may need to install the D3D redistributables to obtain the same version of D3D9X that you compiled against on your development machine.
Code Overview
Once you have the
Spacewar! example project compiling and running you'll want to start looking at the code. If you browse the files within the Visual Studio solution explorer you'll see that the code has been broken up into Game and Engine code. You can ignore the code in the Engine folder - it supports basic 2D rendering via D3D and basic keyboard input. All of the important code documenting Steamworks API usage is files in the Game folder.
The most interesting areas to begin looking at the code are described briefly below:
-
Main.cpp
-- Main entry point for the example game.
API Usage shown:
- Client API Initialization -- You'll need to initialize the API early during app startup, and you'll see how this is done inside of the
RealMain()
function in Main.cpp
.
- API Error/Warning logging -- During development you may want to get some logging output from the Steam APIs in order to help debug problems. You can see an example of setting up debug logging inside the
RealMain()
function where ISteamClient::SetWarningMessageHook is called.
- Crash reporting -- You may wish to use Steam's built in minidump crash reporting in your games. If you do you'll find an example of installing the exception handler and setting up minidump writing in
WinMain()
and MiniDumpFunction()
within Main.cpp
.
-
SpaceWarServer.cpp/h
-- Server code for the example game.
API Usage shown:
- Gameserver API Initialization -- Inside game servers you'll want to initialize a stripped down version of the API that doesn't have the individual user interfaces exposed. You'll find this done in the constructor for
CSpaceWarServer
in SpaceWarServer.cpp
.
- Running API Callbacks -- In your games you'll want to periodically run Steam callbacks to process results from Steam's asynchronous API calls. You'll find an example of running callbacks in a game server via SteamGameServer_RunCallbacks in the
CSpaceWarServer::RunFrame()
function, and you'll find examples of handling individual callbacks and registering them inside the CSpaceWarServer
constructor code and header file.
- Multi-Player Authentication (VAC Ban handling) -- If your game is an online multi-player game then you'll want to confirm that users own the game before you let them join an online server. You'll find callback handlers and calls to the ISteamGameServer API used within
SpaceWarServer.cpp
for these purposes. You'll also see how to handle deny and kick responses that Steam may send you due to users not owning your product, or due to users being banned or needing to be kicked for cheating.
- Networking API -- If you are building an online game you may want to utilize Steam's built in networking APIs. You'll find examples of their usage server side in game servers via ISteamNetworking API calls using the
SteamGameServerNetworking()
accessor and callbacks within SpaceWarServer.cpp
.
- Matchmaking and Master Server communication -- If you are building a multi-player game and wish to utilize the Steam server browser, then your game server will need to communicate with the Steam Master Servers. You'll find examples of doing this in the
CSpaceWarServer
constructor and in the CSpaceWarServer::SendUpdatedServerDetailsToSteam()
method.
-
SpaceWarClient.cpp/h
-- Client side code for the example game.
API Usage shown:
- Matchmaking via Lobbies -- In your online games you may wish to include matchmaking via lobbies in addition to, or instead of, the Server Browser. You'll find examples of using the lobby code and callbacks via the ISteamMatchmaking interface inside of
SpaceWarClient.cpp
. You'll also want to look at Lobby.cpp/h
which include some of the code for handling state and callbacks once inside a given lobby.
- Friends & Community Integration -- Steam allows you to use rich identity information for players, including their persona name and personal avatar, within your game. You'll find an example of integrating persona names and avatars into scoreboards via the ISteamFriends interface inside of
SpaceWarClient.cpp
- Networking API -- You'll find an example of client side usage of the Steam Networking API inside of
SpaceWarClient.cpp
(see SpaceWarServer.cpp
for the server side implementation).
-
StatsAndAchievements.cpp/h
-- Stats and Achievement handling for the example game.
API Usage shown:
- Stats & Achievements -- You'll find an implementation of both Stats and Achievements handling within
StatsAndAchievements.cpp
. The file contains the CStatsAndAchievements
class, which is called with updated state information from CSpaceWarClient
. Once CStatsAndAchievements
has received state change information from the game client, it handles notifying Steam of changes to user stats or achievements obtained via the ISteamUserStats interface.
-
Lobby.cpp/h
-- Matchmaking via Lobbies
API Usage shown:
- Matchmaking via Lobbies -- You'll find part of the example game's lobby-based matchmaking implementation in
Lobby.cpp
. Lobby.cpp
works closely with SpaceWarClient.cpp
to handle matchmaking so you'll want to look at both of them. When examining the lobby code, take special note of the callbacks and calls to ISteamMatchmaking interface methods.
-
ServerBrowser.cpp/h
-- In-game Server Browser
API Usage shown:
- Matchmaking via ServerBrowser -- If you support matchmaking via the Server Browser then you'll probably want to provide a server browser listing directly inside your game to supplement the listing provided by the Steam UI. You'll find an example of getting the list of Internet servers for your game and displaying it to the user inside
ServerBrowser.cpp.
-
Inventory.cpp/h
-- Steam Inventory Service
API Usage shown:
- Steam Inventory -- Integrates with the Steam Inventory which provides access to the Steam Economy. This allows you to easily integrate items into your game.
If your game has an existing authentication and matchmaking engine that you will keep using then you may want to remove the
USE_GS_AUTH_API
define from
Spacewars.h
. When you remove this define it will cause the sample to NOT use Steam authentication or matchmaking but you will still be able to access other Steam functionality such as achievements and friends information, look at the code for details.