Creating Pocket PC games that publish high scores in web
Andrey Lebedev (andrey.lebedev@softspb.com), January 13, 2003.
Introduction
Playing games is more interesting if you can compare your results
with those of other people. Spb Software House along with
PocketGamer.org has developed an open system for creating
Pocket PC games that supports publishing high scores in web.
This system consists of a scores section of the PocketGamer.org website,
a freeware program for desktop PC that retrieves high scores from the connected Pocket PC
and a C++ library for creating Pocket PC games with high scores support.
This article explains how to use this library in your games.
Background
Almost every game application has a high scores (or records) table.
Each developer who writes a game has to implement a high scores
table and he does this in his own way using his own data format.
By the way, he must provide data integrity checking.
The Pocket Highscores
library does all these and many other tasks for you, simplifying the
development process significantly.
There is also a freeware program for desktop PC -
Pocket Highscores that allows users
to publish their high scores in web. You can distribute this program along with your
Pocket PC games that use Pocket Highscores library. The high scores will be published
to the PocketGamer.org website.
Users will be able to compare their results and take part in monthly contests organized
by PocketGamer.org.
About Pocket Highscores system
Pocket Highscores system consists of 3 parts:
What You Need
About Pocket Highscores library
The library loads/saves/enumerates/modifies high scores located
in a HighScores.sco file in your folder. It supports
crypto signature to prevent cheating.
The library is implemented as a single h-file with three classes in it
(CHighScores, CByteStorage, CCryptoHashMD5). CByteStorage class is a simple
memory stream, CCryptoHashMD5 is a wrapper around md5 algorithm. The
Highscores library doesn't use MFC and therefore it can be used in
both MFC and non-MFC projects.
CHighScores class is a container for a limited number of high scores records
with an ability to load the list from a file or a memory stream, to save the list into a file
or a memory stream, to add, sort and enumerate the high scores records. Each high score
record keeps the following information:
- player name (string)
- score value (integer)
- additional information (string).
The Additional information can contain any auxiliary string data.
Here is the CHighScores interface:
class CHighScores
{
public:
CHighScores(int nMaxScores, LPCTSTR pszMagic);
~CHighScores();
void Sort();
BOOL LoadFromBS(CByteStorage& src);
int Load(LPCTSTR pszFilePath);
void SaveToBS(CByteStorage& dest, BOOL bWriteSignatureAnyway = FALSE) const;
int Save(LPCTSTR pszFilePath, BOOL bWriteSignatureAnyway = FALSE) const;
BOOL IsSignatureOk() const;
void Clear();
BOOL AddScore(LPCTSTR pszName, int nScore, LPCTSTR pszAdditionalInfo);
int GetNumberOfRecords() const;
BOOL OpenRecord(int nRecordIndex);
BOOL FirstRecord();
BOOL GetNextRecord();
BOOL GetName(LPTSTR pszString, int nMaxCount) const;
int GetScore() const;
BOOL GetAdditionalInfo(LPTSTR pszString, int nMaxCount) const;
LPTSTR GetAppName();
DWORD GetAppID();
DWORD GetAppVersion();
void SetAppName(LPCTSTR pszAppName);
void SetAppID(DWORD nAppID);
void SetAppVersion(DWORD nAppVersion);
};
Using the Highscores library
Initialization
Define a variable of CHighScores class: it's a good idea for this variable to
exist during the whole application lifetime. For example, in MFC application
the best place for the high scores variable will be a field of the application object.
Pass the following data into the constructor: the maximum number of high scores
records to be kept in the list and the "magic" string to be used in the encryption
for security purposes.
To specify the game application and its version use the
following methods: SetAppName(), SetAppID() and SetAppVersion(). This data
will also be placed into the high scores file and will be saved during the
next save operations and loaded during the load operations.
Loading from file
To load the high scores list from a file call the Load method passing there
the directory path where the high scores file (HighScores.sco) is placed:
pApp->GetHighScores()->Load(_T("\\Program Files\\MyGameFolder"));
If load operation succeeds, the Load method returns HS_OK value. If an error
occurs then it returns one of HS_XXXX or HSL_XXXX constant values. If the
signature check succeeds then the IsSignatureOk() method will return TRUE,
otherwise FALSE. The failure of the signature check will not cause any
error in the load process, but during the save process it will be checked
whenever the signature check succeeded or not (see the description of the save process).
The high scores list is automatically sorted after each loading.
Saving to file
To save the high scores list into a file call the Save method passing there
the directory path where the high scores file (HighScores.sco) should be placed:
pApp->GetHighScores()->Save(_T("\\program files\\MyGameFolder"), TRUE);
The second (boolean) optional parameter of the Save method only makes sense
in a case of the signature check failure during the previous load operation
(call the IsSignatureOk() method to check this). The parameter indicates
whether to add the security signature to the high scores file or not. If no
parameter is passed, the FALSE value is assumed (this is a recommended value
for security purposes).
If save operation succeeds, the Save method returns HS_OK value. If an error
occurs then it returns one of HS_XXXX or HSS_XXXX constant values.
Enumerating the high scores
To list the scores (in the dialog box or wherever you want) call the
FirstRecord() method first to move to the beginning of the records list,
then iteratively call the GetNextRecord() method. Both methods return a boolean
value indicating whether there exists a record or not.
TCHAR szName[1024];
int nScore;
TCHAR szInfo[1024];
if (g_scores.FirstRecord())
{
do
{
g_scores.GetName(szName, 1024);
nScore = g_scores.GetScore();
g_scores.GetAdditionalInfo(szInfo, 1024);
// some code to insert the item into the dialog box or wherever you want
} while (g_scores.GetNextRecord());
}
Adding a new score
To add a high score record into the list use the AddScore() method. It checks
whether the passed score value is "high" - that is if the value should be placed
in the top scores table (checking the maximum number of records in the table, etc.).
Important: the score value should be nonnegative, the player name should not
contain "|" characters. The list is not automatically sorted after each score
insertion, therefore you should sort it by calling the Sort() method.
Misc
You can save and load the high scores list from the memory stream (CByteStorage class):
the appropriate methods are SaveIntoBS() and LoadFromBS() which are boolean. After
calling LoadFromBS() you can also check the IsSignatureOk() value as described above.
Step by step
- Download HighScores.h file
- Add this file to your project
- Choose a key that will be used for high scores signature ("magic string")
- Add code that uses CHighScores class for loading/saving/displaying scores in your game
- Register your game at PocketGamer.org - http://www.pocketgamer.org/scores/add.php
- In case of any questions contact Spb Software House support
Conclusion
You can save your development time and make your Pocket PC games more attractive
to users by using Pocket Highscores library.
Related resources:
-
http://www.pocketpcdn.com/sections/gapi.html
Section: GAPI
-
http://www.pocketpcdn.com/libraries/stgapibuffer.html
Library: STGapiBuffer
-
http://www.pocketpcdn.com/libraries/gapidraw.html
Library: GapiDraw
-
http://www.pocketpcdn.com/libraries/easyce.html
Library: EasyCE
-
http://www.pocketpcdn.com/libraries/gapiemulation.html
Library: GAPI for Emulator
-
http://www.pocketpcdn.com/libraries/pocketgl.html
Library: Pocket GL (iPAQ and Cassiopeia)
-
http://www.pocketpcdn.com/libraries/gapitools.html
Library: GapiTools
-
http://www.pocketpcdn.com/libraries/aspritece.html
Control: ASpriteCE Game Control
-
http://www.pocketpcdn.com/articles/gapibuffer.html
Article: Drawing images and other graphics with GAPI
-
http://www.pocketpcdn.com/articles/gapidraw.html
Article: GapiDraw from a DirectDraw developers perspective
-
http://www.pocketpcdn.com/articles/gapidraw2.html
Article: Creating a new project with GapiDraw
-
http://www.pocketpcdn.com/articles/dieselengine2.html
Article: Programming DieselEngine 2. Using Diesel3D
-
http://www.pocketpcdn.com/articles/dieselengine1.html
Article: Programming DieselEngine 1. Close up and personal with DieselEngine, Using DieselGraphics
- http://www.microsoft.com/mobile/developer/technicalarticles/gameapi.asp
Article: Getting Started with the Game API
- http://www.microsoft.com/mobile/developer/technicalarticles/gapi.asp
Article: Here Comes GAPI!
- http://pocketmatrix.com/phantom/tutorial1.htm
Article: PocketPC Advanced Graphics & Games Programming Tutorial. Part 1 - Getting started with EasyCE
- http://pocketmatrix.com/phantom/tutorial2.htm
Article: Pocket PC Advanced Graphics & Games Programming Tutorial. Part 2 - Advanced tricks with pixels
- http://pocketmatrix.com/phantom/tutorial3.htm
Article: Pocket PC Advanced Graphics & Games Programming Tutorial. Part 3 - Pixel warps and displacement tables
- http://pocketmatrix.com/phantom/tutorial4.htm
Article: Pocket PC Advanced Graphics & Games Programming Tutorial. Part 4 - Buffers, pointers and sprites
- http://pocketmatrix.com/phantom/tutorial5.htm
Article: Pocket PC Advanced Graphics & Games Programming Tutorial. Part 5 - Rotozooming and fixed point arithmetic
- http://www.pocket-g.com/prx/sprite.html
Article: Sprite
- http://www.pocket-g.com/prx/animation.html
Article: Animation
- http://www.pocket-g.com/prx/timer.html
Article: Timer call back
- http://www.pocket-g.com/prx/bckgnd.html
Article: Scrolling background
- http://www.pocket-g.com/prx/collision.html
Article: Object collision
- http://www.pocket-g.com/prx/offscreen.html
Article: Off-screen technique