This is a simple game that uses the "HighscoreComponent" to manage a highscore list. It stores the list both locally, and uses Xbox Live! sessions to exchante highscore information with other players who happen to be playing the game at the same time. This way, high scores from people who are not your local players will show up, which is all kinds of cool :-)
This is version 1 of the component, from 2008. It is saved here for historical reasons. You want to get the latest version at http://www.enchantedage.com/highscores which has more features, bug fixes, and is easier to use.
The game itself is very silly: Hold down left shift (or the left trigger) to make a yellow bar go across the screen. Make it stop before it hits the right hand side. Then hold down right shift (or right trigger) to make a blue bar go across the screen. Make it stop before it runs out of space created by the yellow bar. The score is a factor of how far right you managed to push the yellow bar and the blue bar without overrun. Yeah, a total hit at parties!
This allows you to implement a limited kind of leaderboards. Usage is really simple: just create a GamerServicesComponent and add to your components, then create the HighscoreComponent and add to your components. As arguments, pass your game, null, and the name of your game as a brief string.
When your player finishes a game, call HighscoreComponent.Global.SetNewScore() and pass in the player index, the score, and an optional message (could be an empty string) not to exceed 64 characters. That data will be stored in the highscore table, and exchanged with other players of your game. The best N scores for each local player, and the best N scores for all networked players you've seen (which includes players they have seen, etc) are remembered on the hard disk. N is currently 50.
When you ask for highscores, you can ask for highscores for a current user, or for the global highscore list including the network downloaded data (if any). You will receive a list of objects containing the gamertag, score, date and message for each of the entries. For example, to receive scores for the gamer currently signed in as PlayerIndex.One, simply call:
Highscore[] scores = new Highscore[10];
int n = HighscoreComponent.Global.GetHighscores(PlayerIndex.One, scores);
This will return the number of scores that were actually returned, in case the local player hasn't yet played (in this case) 10 full games yet.
This code is released Open Source under the MIT license. Copyright 2008 Jon Watte, All Rights Reserved. You may use it free of charge for any purposes, provided that Jon Watte's copyright is reproduced in your use, and that you indemnify and hold harmless Jon Watte from any claim arising out of any use (or lack of use or lack of ability of use) you make of it. This software is provided as-is, without any warranty or guarantee, including any implicit guarantee of merchantability or fitness for any particular purpose. Use at your own risk!
For more information and updates, stop by my XNA programming area at http://www.enchantedage.com/highscores
You will have to register and log in to download the code to build the game (which includes the component).
| Attachment | Size |
|---|---|
| highscores-1.png | 13.72 KB |
| highscores-2.png | 64.43 KB |
| Highscores20081022b.zip | 60.81 KB |
Comments
Found a bug
I found a bug in the HighscoreComponent which concerns the handling of dead game sessions (or failure to connect to a session for whatever reason) -- If a dead session is in the list of sessions found, the HighscoreComponent will get stuck trying to connect to that over and over again.
The fix is to mark the server as visited before trying to connect. Then if the connection fails, it won't be continually re-tried. Specifically, instead of ...
... previousHosts_ should be updated here ...
Martin.
Thanks for sharing! That
Thanks for sharing! That sounds like a great solution.
Dead sessions are such a pain. You'd think Xbox Live could remove those by itself...
Thanks for your excellent highscore component!
Hello Jon,
Thanks for your excellent highscore component!
I'm using it in my pipes puzzler game Paipa which is in playtest right now.
It would be nice if you took a look when you get the chance and let me know what you think :D
... Can't post the link because its spam :(
Chris
Session's Not Starting Unexpectedly
Hey, thanks for the component. It is great!
However, recently during my testing, the component stopped creating sessions with others playing the same game completely. It had bounced fine for over 2 weeks, but recently, specifically in the last 12ish hours, I haven't been able to connect to a single session. This is the same for the others trying to bounce off of me.
I've tried restarting my box, deleting all data and starting anew, etc, to no avail. There has been no code change in this entire process.
This sounds like a Microsoft problem to me - is that possible with the code you've written? It seems strange that all sessions have stopped working randomly.
Thanks in advance.
Any Xbox networking code is
Any Xbox networking code is at the mercy of Microsoft and their Live operations. This means that if your console gets banned, highscores will stop working, too...
I've been having random Live! connectivity problems recently, too, and I've heard others on the XNA forums report it. If connectivity comes back, I'd blame Microsoft (or Internet Gremlins -- they pop up when you least expect them!)
Nevermind!
Nevermind - immediately after my last reply the Gremlins decided to punch out! It's all working again - Thanks for your time and component though!
Not Banned
I've done nothing that would warrant my console being banned, and the issue seems to be more widespread than just my console. At minimum, it is two different boxes under the same generally connection (attending University). It is likely that a couple friends in completely different parts of the state are also having this issue.
Does this mean their Live! service is somehow either limiting or completely stopping our connections, or connections for the entire game itself?
Thanks in advance.
The Xbox is not like a PC. It
The Xbox is not like a PC. It requires Live! to be up and operating to do pretty much anything network related, unless you do System Link connections.
Xbox Live Gold Subscription
Hey, great work on the component.
When a player that doesn't have a gold subscription plays a game with the component inside, does the game still store scores in the local saved list despite being not connected to any network session? Or does the entire component not enable itself if a user does not have a gold subscription?
Thanks in advance!
I believe that it will still
I believe that it will still store local scores, and just act as if it cannot create a connection to other boxes. However, I wrote it a while ago, so I don't remember for sure.
Enable/Disable bug
I've just come across a little bug related to enabling and disabling the component. If the component is disabled when the component is creating a session then NetworkSession.EndCreate() is called. However, the result of the method call is currently ignored.
In my situation I was attempting to find a game shortly after disabling the component and getting a "there's already a session around" exception when calling NetworkSession.EndFind(). Obviously the garbage collector hadn't kicked in to properly dispose of HighscoreComponent's session.
Thankfully this is easily fixed by assigning the result of EndCreate() and EndJoin() to this.session_ which will then be explicitly disposed of if it's not null. The same goes for disposing of the return value of EndFind().
Cheers,
Dave
Thanks for the note. That
Thanks for the note. That sounds like a great fix!
Using this component to gather analytics.
This is helpful. Can't wait to put this into my first game. I am new to this game design stuff so excuse me for sounding like a "noob." Does Microsoft supply us with back end analytics? Like Total players, scores, ect.
Once again I am such a noob!
Once you have released, you
Once you have released, you will get some amount of data from Microsoft (trial downloads, actual conversions). However, you won't get any rich metrics, such as you'd want to use to change the game design.
Copyright question
If I put "Highscore table Copyright 2008 Jon Watte, All Rights Reserved" at the bottom of my highscore table, would that be acceptable?
That would be perfect!
That would be perfect!
Content Unavailable
After extracting and running Highscroes.sln, the project loads into Visual Studio without a Content folder. VS says
The project file 'C:\XNA\Highscores\Content\Content.contentproj' has been moved, renamed, or is not on your computer. The project will be labeled as "unavailable" in Solution Explorer.
I've never seent his before. In VS the Content folder is (unavailable).
Any idea what I'm doing wrong? Is this an XNA version issue? I'm using 3.1 the current version. I'm sure I can just copy everything over into a new project but I thought I would mention this.
Thanks for the sample.
Allan
Probably an absolute path vs
Probably an absolute path vs relative path problem. If you open the sln file in a text editor and edit the path to that project, it should find it.
could you explain that a bit
could you explain that a bit more? I dont even have content.contentproj in the download.....
You are right -- it's not in
You are right -- it's not in the download. Weird.
I've uploaded a new archive with that project. It's easy to just right-click and "Add->New Content Project" and add the three pieces of content, though, as you say.
Works now! :)
Works now! :)
Local High Score
Can this be used without xbox live? My game isnt an onlinemultiplayer game so would i be able to just store scores locally without global scores?
Yes, it can be used to store
Yes, it can be used to store the high score locally, but you'd have to manually cut out all the Xbox Live bits -- it doesn't have a simple boolean to just turn that off.
GamePad.GetState?
In the component Update there is a call to GamePad.GetState, the result of which isn't used at all. Is there a purpose for doing this? Or is it leftover from something else?
byte[] data = new byte[1000];
GamePadState gps = GamePad.GetState(PlayerIndex.One);
using (StorageContainer sc = storage_.OpenContainer(titleName_))
Thanks.
Multiple high score tables
I was wondering if creating several version of HighscoreComponent would work? I'd like to have 3 different high score tables for the easy, medium and hard difficulties in my game. Will creating multiple versions with different NetworkSessionProperties just work or would I need to keep flicking the Enabled properties so only one is enabled at any one time?
Thanks!
Actually, it would probably
Actually, it would probably be best if you marked each highscore entry with a "hard," "medium" or "easy" tag, and kept say 30 of each. Then exchange all of them with the other nodes in the code. Make sure that you always keep the 30 best of each (plus the local player scores if you want), and sort out which particular scores you display to the user in the UI code.
will not work for me
I have not be able to get this to work even the sample. when i run it the output of one of the pc / xboxs says this
Xbox360: Beginning PlayerMatch find.
Xbox360: Beginning PlayerMatch join.
A first chance exception of type 'Microsoft.Xna.Framework.Net.NetworkSessionJoinException' occurred in Microsoft.Xna.Framework.dll
Xbox360: Session not found. It may have ended, or there may be no network connectivity between the local machine and session host.
since the games seems to work for everyone else im asuming that somthing is wrong with my computer. cound a firewall be at fault?
I don't know whether
I don't know whether firewalls can make Live! not work -- it's possible.
Are you using a gamer profile that has a Live! gold subscription?
Also, is that profile signed in anywhere else (such as on an Xbox)?
got live accounts at both
got live accounts at both ends and not got anyone signed in anywhere else.
I get the same error
Did you ever figure out what the problem was?
Crashing issue
I really like this component and have integrated it into my game. I have run into a couple of problems however.
The first was down to the Highscore.Encode() method using a semi-colon as a seperator. I'm letting users enter their own name for a high score and storing that as the 'Message' component instead of displaying the Gamertag. However, this means they can enter a semi-colon which will obviously mean the Decode() method will then find an extra semi-colon which screws things up. I've changed this in my game so char(0) is used as a seperator instead. That shouldn't cause any problems should it?
I've got a problem at the moment which has been reported as a result of a failed review. The trouble is I've been unable to reproduce the problem but I wondered if it might be down to the issue where a save file can have garbage at the end of it as a result of using File.OpenOrCreate() (See http://forums.xna.com/forums/t/19525.aspx caveat 2). I know this code uses StreamWriter but I wonder if that could suffer from the same problem?
Dave
I checked the documentation
I checked the documentation for StreamWriter, and it doesn't actually explicitly promise to remove/truncate the old file first. However, in practice, that's what I've found that it does, so I do not believe this component has the "junk data at end" problem.
I believe a C# string can store a char[0] just fine. I also believe (but haven't verified) that network packet sending marshals strings with 0 fine, too, as it should marshal a length value first, followed by the actual characters.
Finally, an alternative to using 0 for separators would be to encode the elements as uuencode (base-64) or similar, and use a character that's not part of that encoding as separator.
Credits
Hi,
well done! I'm extending it just a little to use it in my games. I've added you in the "Acknowledgements and Copyrights" section of the Credits.
Thanks,
Pino
I really like this component
I really like this component and believe that it's absolutely critical for games that keep track of any sort of score.
My one wish is that it also saved friend data to a seperate list allowing the user to view his/her friends best scores. I usually find myself more concerned with the scores of my friends than the scores of strangers.
Thanks for the suggestion. I
Thanks for the suggestion. I have no immediate plans to update the component, but if I ever do, that sounds like a great feature to add. Given that the source is included, perhaps you could even add that on your own :-)
Nice idea!
We were planning to include a similar service in our game to enable automated level exchange between users (the game cames with integrated level editor). We don't really now for sure that is was possible until this, so a big thank you, you saved me a lot of research time!! xD