This is an interesting matter and I think everybody handle it in a different way.
Since I’ve almost finished a game I would like to discuss with you (and @Gildas especially since he showed interest in another post) the way you manage to have a scoreboard online.
Usually, as for example Gamecenter does, the system is an infinite table (maybe diveded in different tables by game mode) of names and scores
What the user see is the first ten names (which is usually never you and seldomly is obviously hacked with 9999999) and then an extract of your position (something like 34.566th) and your fellow unknown neighbours of “anonymity town” .
This IMHO doesn’t really work and especially doesn’t give the user any push to make a better score, because it’s terribly useless.
Few months ago I’ve played the beautiful SpaceChem (especially funny for a programmer, since basically it’s like a programming language with two simultaneous threads)
http://www.zachtronics.com/spacechem/
the guy who developed the game implemented a beautiful score system.
You never know who is the best of every level (it’s a game with a lot of levels), what you know is how good you are compared to everybody else.
So basically you have a graph (in this game best is always lower value) with all the score submitted (the graph axis are x=“score” and y=“number of submission”).
This is what it looks like
This system is brilliant and I’ve loved it since the first time I’ve played the game.
It pushes you to play against the average player (you wanna be better than the average don’t you) instead of competing with the best 10 (which probably is too much challenge and most of the players will never care).
So everybody feel pushed to be better. There is no showing off (which would involve just few players) but a lot of challenge and payback for your efforts (which involve the majority of players).
So I’ve tried to get the idea and develop my system based on this.
Problems:
- back-end (server) structure
- showing the score on the game (client)
- block users from submitting forged request to the back-end
My solution:
- STORE THE SCORE ON THE SERVER
the back end I’ve set up is based on two tables, but I will talk about the second on later.
the SCORE_TABLE has two fields
SCORE Uint
HITS Ubigint
everytime a score is submitted (there is a game-over in my game and with an URLRequest I call my server page) the back-end perform a query this made
"INSERT INTO score_table (score, hits) VALUES (" . mysql_escape_string($score) . ",1) ON DUPLICATE KEY UPDATE hits=hits+1"
that’s it.
what I get is a table with a row per every score (which is a number) with how many submission where made.
- SHOW THE SCORE ON THE CLIENT
Now the point is showing them on the client.
Since I want a graph made of a discrete number of X (columns) I have to aggregate the raw table in 25 (or any number you want) rows.
So I divide the the difference between the lowest score and the highest score in 25 ranges and get the aggregate hits on every range.
Then I give this data as json.
The client load this json and after it has just to draw the bars anyway I want.
example raw table:
score | hits
60 | 1
67 | 1
99 | 1
228 | 1
252 | 1
263 | 1
274 | 1
300 | 1
354 | 1
367 | 1
375 | 1
399 | 1
401 | 1
405 | 1
425 | 1
429 | 1
435 | 1
437 | 1
500 | 1
519 | 1
527 | 2
552 | 1
597 | 1
598 | 1
618 | 1
example aggregate data:
(every tier is made of FROM_SCORE,TO_SCORE,HITS)
(I make two queries, one to get MAX and MIN, and the other one is query made of lots (in this case 25) SUM(IF(score >= $low and score <= $high, hits, 0)) AS s$i
)
{ "top_score":1120,
"bottom_score":60,
"top_hits":6,
"tiers":[[60,102,3],
[103,144,0],
[145,187,0],
[188,229,1],
[230,272,2],
[272,314,2],
[315,356,1],
[357,399,3],
[400,441,6],
[442,483,0],
[484,526,2],
[527,568,3],
[569,611,2],
[612,653,2],
[654,696,1],
[696,738,2],
[739,780,0],
[781,823,0],
[824,865,0],
[866,908,1],
[908,950,0],
[951,992,0],
[993,1035,0],
[1036,1077,0],
[1078,1120,1]]
}
example rendering on client:
I just draw the line of the local LAST SCORE and BEST SCORE in a different way to show that to the user (and push to be better)
The graphic design of this screen has to be improved (give info about the axis and their values), but it is a working prototype.
- DAMN CHEATERS
When you deal with online stuff you know people are going to expoit your system and try to submit crazy score or break it.
We have to defend ourselves.
So, basically the system now has a SUBMIT page (called with the score) to send a score on the online board and a AGGREGATE page (called on the statistics screen) to get the aggregated score to be showed on the client.
If I see this, as a cheater, I will try to call the SUBMIT page directly with a very high score parameter. In this case there is no proper leaderboard so it is quite pointless in the act of showing off, but anyway this could f*ck your system and make your graph quite pointless with all the score on the bottom and one little one on the top and nothing in the middle, when actually what we are looking for is a kind of gaussian curve.
How to defend?
We need a kind of authentication to check if our application sent the score (legit) and not something else (cheating).
I’ve looked around, and since I don’t want the user to be registered but rather an anonymous system, I thought the best way could be a shared secret.
basically the client and the server knows the same way to encrypt data so when a request is sent a CHECKSUM field is sent as well (based on a seed which in this case is the SCORE).
so I send the SCORE and the CHECKSUM to the SUBMIT page.
noone else knows how to make the CHECKSUM from a score so it is easy to know if it was the game and not a cheater who sent the score.
This system is dangerous because IN the game code there is written the algorithm to generate a CHECKSUM from a SCORE.
The best way is trying to obfuscate the code as best as possible (lots of guide on the internet, break every good writing code rule and lots of programming fantasy are your friend).
It is not completely safe but it works and if someone breaks it you can make it more complicated updating the server and the client.
The last problem is multiple submissions: with this system if you have a SUBMIT request for a specific score (for example 200) you have the checksum as well.
So a cheater can submit that score thousand times and the server will accept it because the checksum is right.
Solution: a token!
(The system I’ve developed follow a principle: one request only.
I don’t want the server and client to talk and talk, just one request and the job is done.)
So what is this token? Every time the client send a request to the server generate a random string and use it (with the SCORE) as a seed for the checksum.
So now we send SCORE, CHECKSUM and TOKEN.
The tokens are one use only.
The back-end has a second table who store the TOKENS.
At every succesful request the token is written in that table.
If the same request (same score, checksum and token) is sent again the checksum is right, but the token is already used and the double submission denied.
I know this post was long and maybe it contains some big ingenuities, this is why I’m sharing this with you, hoping to get your suggestion and ideas and improve myself and my ideas.
Thank you for reading everything and hopefully to join the discussion.