Creating Pocket PC games that publish high scores in web

Andrey Lebedev (andrey.lebedev@softspb.com), January 13, 2003.

Introduction

Desktop program for publishing high scores in web. 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:

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

  1. Download HighScores.h file
  2. Add this file to your project
  3. Choose a key that will be used for high scores signature ("magic string")
  4. Add code that uses CHighScores class for loading/saving/displaying scores in your game
  5. Register your game at PocketGamer.org - http://www.pocketgamer.org/scores/add.php
  6. 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: