Use Redis as a leaderboard data store in casual games

Source: Internet
Author: User
Tags addchild http post


1. Demand for leaderboards

I have done a website http://www.cgame360.com/, specifically put some simple HTML5 games. Now there are 2 needs, I want to get a top 10 user score for a game, and one is the rank of a certain user, plus the front and back 4 people. Less the name, the Cocos2d JS input box A bit of a problem is not added. Now the question is what database to use to store better? I want to find out the data as quickly as possible. I've done MySQL. This relational database, the first feeling used here will be very slow. The amount of data is very slow, because it handles all the data when it is sorted. There is a second need to use SQL statements will be very painful, I have not thought of efficient implementation of the way. The first top 10, you can make a table to save the top 10. The main is the card in the second demand. I got Google and found that NoSQL is better suited for today's needs. NoSQL is more famous for Hadoop,mongodb. But I found a database redis that is more appropriate for this requirement.
an ordered set in 2.redis
2.1redis Sequential Set inserts a single piece of data
There's no time to talk about installing Redis. I remember as if the MAC system was easier to use and windows seemed to be less useful with redis. an ordered collection of Redis inserts a piece of data very easily:zadd key Score MemeberSpecific examples:Zadd game1 Tomso there's a piece of data in the Game1, and Tom's score is.
2.2 Redis Gets a list of elements ranked in a range
zrange key start stop [Withscores]zrevrange key start stop [Withscores]
Specific examples:zrange game1 0-1 withscoresThis allows you to get all the records in the game1, from small to large, 1 indicates the meaning of the last element. So what order do we want to get the top 10 records for? very simple: Zrange game1-10-1 withscores-10 means a number of 10. Here is the output that my Mac machine performs:




127.0.0.1:6379> zrange g_1 -10 -1 withscores
 1) "tom5"
 2) "506"
 3) "tom6"
 4) "507"
 5) "hug"
 6) "600"
 7) "tom"
 8) "5000"
 9) "tom8"
10) "5088"
11) "tom9"
12) "5089"
13) "tom10"
14) "5090"
15) "tom11"
16) "5091"
17) "tom12"
18) "5092"
19) "tom13"
20) "5093"

Zrevrange is the meaning of reverse, from large to small output.




2.3 Redis Gets the rank of an element
Zrank Key MemberZrevrank Key MemeberSpecific examples:Zrank game1 Tom
2.4 Redis Gets the fraction of an element
Zscore Key MemberSpecific examples:Zscore game1 Tom
using Redis in 3.PHP
the Redis commands above are enough for us to use, and the next step is to use a server language such as Redis and Java or PHP to form a service. I chose PHP here, I feel the user submits a score with the HTTP POST, get the leaderboard score with PHP get enough. There are two ways to use Redis in PHP, namely Predis and Phpredis, which are fully PHP and the PHP extension written in C. The latter performance will be better, but the need to install PHP extension is more troublesome. Predis is very simple, that is, some PHP files, thrown into the site directory will be able to work. This option uses Predis.
3.1 Inserting a piece of data
<?php
require ‘./predis/autoload.php‘;
$redis = new Predis\Client(
    array(
        ‘scheme‘=>‘tcp‘,
        ‘host‘=>‘127.0.0.1‘,
        ‘port‘=>6379,
 ));
//header("content-type:text/html;charset=utf-8");
if(trim($_POST[‘game_id‘]) == ‘‘ || trim($_POST[‘user_name‘]) == ‘‘  || trim($_POST[‘score‘]) == ‘‘){
    echo ‘need more information!‘;
    exit;
}else{
    // echo ‘OK‘;
    // echo $_POST[‘game_id‘];
    // echo $_POST[‘user_name‘];
    // echo $_POST[‘score‘];
    $game_id = "g_" . $_POST[‘game_id‘];
    $name = $_POST[‘user_name‘];
    $score = $_POST[‘score‘];
    if($score > 0){
       $beforeScore = $redis->zscore($game_id
, $name);
       if($score > $beforeScore){
         $itemScore = array($name => $score);
         $redis->zadd($game_id, $itemScore);
       }
    }
}

mainly here I have simply judged that his current score is not higher than before, inserting a piece of data than the previous one. Very simple.
3.2 Get the top 10 player score
<?php
require ‘./predis/autoload.php‘;
$redis = new Predis\Client(
    array(
        ‘scheme‘=>‘tcp‘,
        ‘host‘=>‘127.0.0.1‘,
        ‘port‘=>6379,
 ));

if(trim($_GET[‘game_id‘]) == ‘‘){
    echo ‘need game_id‘;
}else{
	$game_id = "g_" . $_GET[‘game_id‘];
    $board_score = $redis->zrange($game_id, -10, -1, ‘withscores‘);
    //print_r($board_score);
    echo json_encode($board_score);
    //echo $board_score;

}

It looks very simple here, and finally I used the Json_encode to convert the arrays in PHP into JSON. This facilitates processing.
3.3 get my ranking
<?php
require ‘./predis/autoload.php‘;
$redis = new Predis\Client(
    array(
        ‘scheme‘=>‘tcp‘,
        ‘host‘=>‘127.0.0.1‘,
        ‘port‘=>6379,
 ));

if(trim($_GET[‘game_id‘]) == ‘‘ || trim($_GET[‘user_name‘]) == ‘‘){
    echo ‘need game_id and name‘;
}else{
	$game_id = "g_" . $_GET[‘game_id‘];
    $user_name = $_GET[‘user_name‘];

    $userCurrentRange = $redis->zrevrank($game_id, $user_name); 

     //echo ‘current range:‘ . $userCurrentRange;

    $result = array();
    if(true){
        $halfCount = 4;

         $leftRank = $userCurrentRange - $halfCount;
        $rightRank = $userCurrentRange + $halfCount;
        if($leftRank < 0){
          $leftRank  = 0;
        }

        $board_score = $redis->zrevrange($game_id, $leftRank, $rightRank, ‘withscores‘);
        $index = 0;
        foreach($board_score as $name => $score){
           if($name == $user_name){
               break;
           }else{
               $index = $index + 1;
           }
       }

        $firstRank = $userCurrentRange - $index + 1;

        foreach($board_score as $name => $score){
           $eachItem = array();
           $eachItem[‘name‘] = $name;
           $eachItem[‘score‘] = $score;
           $eachItem[‘rank‘] = $firstRank;

           $result[] = $eachItem;

           $firstRank = $firstRank + 1;
        }

        echo json_encode($result);
 

    }else{
        echo json_encode($result);
    }


     

}

here a little bit more complex, I first get this player's ranking, so that he can get his 4 players in the ranking range, with the next zrevrange is OK. It is important to note that left is a negative number, which is the other meaning, so avoid negative numbers. I finally added the rank information to the PHP array and returned it again as JSON.
4.0 talking about the HTTP in cocos2d JS
PHP has been able to return the JSON data, the Cocos2d JS in how to use HTTP to display the top 10 player information. The code is given here, and it's relatively simple. It is important to note that the returned data is json.parse processed. Insert data with post, get leaderboard information with Get on OK. I also did not add anti-cheating function.
getJsonFromUrl:function(){
        var xhr = cc.loader.getXMLHttpRequest();
        var args = "?game_id=" + gameId;
        xhr.open("GET", rankBoardURL + args, true);
        xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status <= 207)) {
                var response = xhr.responseText;
                cc.log("res:" + response);
                cc.log("send success");
                var obj = JSON.parse(response);
                this.initContent(obj);
            }
        }.bind(this);

        xhr.send();
    },
    initContent:function(jsonValue){
        var size = cc.director.getWinSize();

        var fontDefBlueStroke = new cc.FontDefinition();
        fontDefBlueStroke.fontName = "Arial";
        fontDefBlueStroke.fontSize = 50;
        fontDefBlueStroke.textAlign = cc.TEXT_ALIGNMENT_LEFT;

        var jsonLength = 0;
        for(var name in jsonValue){
            jsonLength++;
        }
        cc.log("jsonlength:" + jsonLength);
        var nameMargin = 50;
        var nameStartPositionY = 800 - nameMargin * jsonLength;

        var lastRank = jsonLength;
       for(var name in jsonValue){
          cc.log(name);
          cc.log(jsonValue[name]);

          this.rankLabel = new cc.LabelTTF(lastRank + ‘:‘, fontDefBlueStroke);
          this.addChild(this.rankLabel);
          this.rankLabel.x = 100;
          this.rankLabel.y = nameStartPositionY;
          this.rankLabel.setAnchorPoint(cc.p(0, 0.5));


          this.nameLabel = new cc.LabelTTF(name, fontDefBlueStroke);
          this.addChild(this.nameLabel);
          this.nameLabel.x = size.width * 0.5 - 100;
          this.nameLabel.y = nameStartPositionY;
          this.nameLabel.setAnchorPoint(cc.p(0, 0.5));

          this.scoreLabel = new cc.LabelTTF(parseFloat(jsonValue[name]).toFixed(2), fontDefBlueStroke);
          this.addChild(this.scoreLabel);
          this.scoreLabel.x = size.width * 0.5;
          this.scoreLabel.y = nameStartPositionY;
          this.scoreLabel.setAnchorPoint(cc.p(0, 0.5));

          nameStartPositionY = nameStartPositionY + nameMargin;
          lastRank = lastRank - 1;
       }
    }


Finally, we play this HTML5 game using the technology mentioned above, developed with Cocos2d JS. http://www.cgame360.com/halloweengame/

The entire leaderboard of PHP services I have packaged into a file, click on the link below to download. Contains Predis, if you have a Mac system or Linux system, install Php,redis and so on, unzip this to the site root directory should be able to use. I am also the first to use Redis, where the use of the wrong please comment on the point, thank you. http://www.waitingfy.com/?attachment_id=1421




http://www.waitingfy.com/archives/1420




Use Redis as a leaderboard data store in casual games



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.