Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 3 of 3
  1. #1
    Senior Coder timgolding's Avatar
    Join Date
    Aug 2006
    Location
    Southampton
    Posts
    1,519
    Thanks
    114
    Thanked 110 Times in 109 Posts

    verify high score

    I've written a game in javascript and canvas. It works fine. But i want to add a high scores database to it. I have made mysql database and use php to access the database and create an array that is passed back to the javascript. When a user score that is greater than any of the high scores i would like to allow the user to enter there name and it store the name and score in the database. I could do that easily but the problem is then anyone could navigate to the enter high scores page and send a random high score. What i can't get my head around is how to verify that the user did actually get that score. Since the users score is only really handled by the javascript. I can't for the life of me work out how i am meant to verify that the score is a real high score.

    Code:
    <!DOCTYPE html>
    <html>
    <head>
    <style type="text/css">
        body{
            margin:0;
            padding:0;
        }
    </style>
        <title>Hidden Objects</title>
    
    <script type="text/javascript">
    
        // initialise gloabl variables
        var images = new Array();
        var positions_x = new Array();
        var positions_y = new Array();
        var selected_imgs = new Array();
        var correct_imgs = new Array();
        var high_scores = new Array();
        var img = new Array();
        var status = new Array();
        var round = 1; //3 rounds per level 5 images per round
        var corrects = 0;
        var timer_total = 90;
        var timer = timer_total;
        var level = 1;
        var score = 0;
        for(i=0;i<50;i++)
        {
            status[i] = 1;
        }
    <?php
        //localhost:8888/hidden-objects/
        // read objects images
        $i=0;
        $images = array();
        if ($handle = opendir('images')) {
        while (false !== ($entry = readdir($handle))) {
            if ($entry != "." && $entry != "..") {
                echo "images[$i] ='$entry';<br />\n";
                $images[] = $entry;
                $i++;
            }
        }
        closedir($handle);
        }
        
        //get high scores from the database
        $link = mysql_connect('localhost', 'root', 'root');
        
        if($link)
        {
            mysql_select_db("HIDDEN_OBJECTS");
        }
        else
            die("Could not connect to databse");
            
        $sql = "SELECT * FROM HIGH_SCORES ORDER BY SCORE DESC";
        if($res = mysql_query($sql))
        {
            $i=0;
            while($row = mysql_fetch_assoc($res))
            {
                echo "
                high_scores[$i] = new Array(2);
                high_scores[$i][0] = '".$row["NAME"]."';
                high_scores[$i][1] = ".$row["SCORE"].";
                ";
                $i++;
            }
            
        }
        
    ?>
    function init() {
       // iniitialise the canvas and start main menu interval.
        can = document.getElementById("can");
    <?php
        foreach($images as $key=>$image)
        {
            echo "img[$key] = document.getElementById('image_$key');
            ";
        }      
    ?>
        level_bkdrop1 = document.getElementById('level_bkdrop1');
        level_bkdrop2 = document.getElementById('level_bkdrop2');
        level_bkdrop3 = document.getElementById('level_bkdrop3');
        level_bkdrop4 = document.getElementById('level_bkdrop4');
        level_bkdrop5 = document.getElementById('level_bkdrop5');
        applause = document.getElementById("applause");
        bloop = document.getElementById("bloop");
        blurp = document.getElementById("blurp");
        boo = document.getElementById("boo");
        ctx =can.getContext("2d");
        ctx.fillRect(0,0,665,500);
        ctx.strokeStyle="white";
        alpha=0;
        main_menu_timer = setInterval(main_menu, 5);
    }
    
    
    
    function main_menu()
    {
        //main menu at start 
        if(alpha<1)
            alpha+=.1;
        ctx.globalAlpha = alpha;
        
        ctx.font = "bold 36px sans-serif";
        ctx.shadowColor = "rgb(100, 100, 25)";
        ctx.shadowOffsetX = 3;
        ctx.shadowOffsetY = 3;
        ctx.fillStyle = "rgb(200, 200, 50)";
        ctx.fillText("Start Game", 250, 200);
        
        ctx.fillText("High Scores", 250, 250);
        
        // get the mouse co ords
        document.onmousemove = function( ev ){
           x_mouse_pos = ev.pageX; 
           y_mouse_pos = ev.pageY;
        };
        
        // if mouse clicked and co ords with in start game button start game
        document.onclick = function( ev ){
            if(x_mouse_pos > 250 && x_mouse_pos < 450)
            {
                if(y_mouse_pos > 170 && y_mouse_pos < 200)
                {
                    clearInterval(main_menu_timer);
                    alpha = 0;
                    ctx.fillStyle = "black";
                    cls_timer = setInterval(clear_screen, 50);
                    
                }
            }
            
            if(x_mouse_pos > 250 && x_mouse_pos < 460)
            {
                if(y_mouse_pos > 220 && y_mouse_pos < 250)
                {
                    clearInterval(main_menu_timer);
                    alpha = 0;
                    ctx.fillStyle = "black";
                    ctx.fillRect(0,0,1100,500);
                    ctx.font = "bold 24px sans-serif";
                    ctx.fillStyle = "rgb(200, 200, 50)";
                    high_timer = setInterval(high_scores_func, 50);
                    
                }
            }
    
        };
        
    }
    
    function new_score()
    {
        // add input for a new high score
        
        //what do i do here?
    }
      
      
    function high_scores_func()
    {
        if(alpha<1)
            alpha+=.1;
        ctx.globalAlpha = alpha;
        ctx.font = "bold 24px sans-serif";
        for(i=0;i<10;i++)
        {
            ctx.fillText(high_scores[i][0]+" : "+high_scores[i][1], 170, 40+(i*40));
        }
        
        ctx.font = "bold 36px sans-serif";
        ctx.fillText("Main Menu", 400, 450);
        document.onmousemove = function( ev ){
           x_mouse_pos = ev.pageX; 
           y_mouse_pos = ev.pageY;
        };
        
        document.onclick = function( ev ){
            if(x_mouse_pos > 400 && x_mouse_pos < 620)
            {
                if(y_mouse_pos > 420 && y_mouse_pos < 450)
                {
                    clearInterval(high_timer);
                    alpha = 0;
                    ctx.fillStyle="black";
                    ctx.fillRect(0,0,665,500);
                    main_menu_timer = setInterval(main_menu, 5);
                    
                }
            }
        };
        
    }
    
    function clear_screen()
    {
        // clears the screen on game start and enter main loop 
        ctx.globalAlpha = alpha;
        alpha +=0.1;
        ctx.fillRect(0,0,1100,500);
        if(alpha>=1)
        {
            clearInterval(cls_timer);
            ctx.shadowOffsetX = 0;
            ctx.shadowOffsetY = 0;
            ctx.globalAlpha = 1;
            setup_game();
            game_timer = setInterval(main_loop, 1);
        }
    }
    
    function clear_screen2()
    {
        //clear the screen on game over and enter back to main menu loop
        ctx.globalAlpha = alpha;
        alpha +=0.1;
        ctx.fillStyle="black";
        ctx.fillRect(0,0,1100,500);
        ctx.shadowColor = "rgb(100, 100, 25)";
        ctx.shadowOffsetX = 3;
        ctx.shadowOffsetY = 3;
        ctx.fillStyle = "rgb(200, 200, 50)";
        ctx.fillText("Start Game", 250, 200);
        if(alpha>=1)
        {
            clearInterval(cls2_timer);
            main_menu_timer = setInterval(main_menu, 5);
        }
    }
    
    function is_too_close(x, y, total)
    {
        // checks if the objects are too close to each other
        for(j=0;j<total;j++)
        {
            if(positions_x[j] - 4 < x && positions_x[j] +4 > x &&  positions_y[j] - 4 < y && positions_y[j] +4 > y )
                return true;
        }
        return false;
    }
    
    function setup_game()
    {
        // sets up some of the game variables. runs each time a new level is reached.
        start = new Date().getTime();
        start = Math.floor(start/1000);
        
        //set up random positions for all the objects
        for(i=0;i<50;i++)
        {
            do
            {
                positions_x[i] = Math.floor((Math.random()*380)+221);
                positions_y[i] = Math.floor((Math.random()*440)+11);   
            }while(is_too_close(positions_x[i], positions_y[i], i))
        }
        
        // pick 15 objects out at random... these are the objects the user has to find
        for(i=0;i<15;i++)
        {
            rand = Math.floor(Math.random()*49);
            while(in_array(rand, selected_imgs))
            {
                rand = Math.floor(Math.random()*49)
            }
            selected_imgs[i] = rand;
            correct_imgs[i]=1;
        }
    }
    
    function next_level()
    {
        // This funtion is run when a new level reached
        
        //first check if finished game
        if(level==6 && nxt_lvl_timer==0)
        {
            //end game
            step = 3;
        }
        
        switch(step)
        {
        //step 1 - clear screen and display the level they are to start
        case 1:
            ctx.globalAlpha = alpha;
            if(alpha<1)
                alpha +=0.1;
            ctx.fillStyle="black";
            ctx.fillRect(0,0,1100,500);
            ctx.shadowColor = "rgb(100, 100, 25)";
            ctx.shadowOffsetX = 3;
            ctx.shadowOffsetY = 3;
            ctx.fillStyle = "rgb(200, 200, 50)";
            ctx.fillText("Level "+(level+1), 250, 200);
            ctx.fillText("Time Bonus: "+ (timer*100), 170, 250);
            nxt_lvl_timer++;
            if(nxt_lvl_timer>=100)
            {
                step = 2;
                alpha=0;
            }
        break;
        case 2:
           // step 2 - clear screen and setup game for new level
            ctx.globalAlpha = alpha;
            if(alpha<1)
                alpha +=0.1;
            ctx.fillStyle="black";
            ctx.fillRect(0,0,1100,500);
            nxt_lvl_timer++;
            if(nxt_lvl_timer>=130)
            {
                step = 0;
                clearInterval(next_level_timer);
                timer_total-=10;
                timer = timer_total;
                corrects = 0;
                round=1;
                level++;
                for(i=0;i<50;i++)
                {
                    status[i] = 1;
                }
                setup_game();
                game_timer = setInterval(main_loop, 1);
            }
    
        break;
        case 3:
            ctx.globalAlpha = alpha;
            if(alpha<1)
                alpha +=0.1;
            ctx.fillStyle="black";
            ctx.fillRect(0,0,1100,500);
            ctx.shadowColor = "rgb(100, 100, 25)";
            ctx.shadowOffsetX = 3;
            ctx.shadowOffsetY = 3;
            ctx.fillStyle = "rgb(200, 200, 50)";
            ctx.fillText("Completed Game", 170, 200);
            ctx.fillText("Time Bonus: "+ (timer*100), 170, 250);
            ctx.fillText("Game Bonus: "+ 10000, 170, 300);
            ctx.fillText("Your score: "+(score+10000+(timer*100)),170, 350);
            nxt_lvl_timer++;
            if(nxt_lvl_timer>=100)
            {
                clearInterval(next_level_timer);
                score +=10000;
                score +=timer*100;
                alpha=0;
                level=1;
                corrects=0
                timer_total = timer = 90;
                round=1;
                for(i=0;i<50;i++)
                {
                    status[i] = 1;
                }
                if(check_for_high_score())
                {
                    high_timer2 = setInterval(new_score, 5);
                }
                else
                    cls2_timer = setInterval(clear_screen2, 5); 
            }
    
        break;
        }
    }
    
    function check_for_high_score()
    {
        for(i=0;i<10;i++)
        {
            if(score> high_scores[i][1])
            {
                return true;
            }
        }
        return false;
    }
    
    function game_over()
    {
        // game over - clear screen and show game over text
        ctx.globalAlpha = alpha;
        if(alpha<1)
            alpha +=0.1;
        ctx.fillStyle = "black";
        score = 0;
        ctx.fillRect(0,0,1100,500);
        ctx.fillStyle = "rgb(200, 200, 50)";
        ctx.fillText("Game Over", 250, 200);
        end_game_timer++;
        if(end_game_timer>=30)
        {
            clearInterval(game_over_timer);
            round = 1; //3 rounds per level 5 images per round
            corrects = 0;
            timer_total = timer = 90;
            level=1;
            for(i=0;i<50;i++)
            {
                status[i] = 1;
            }
            if(check_for_high_score())
            {
                high_timer2 = setInterval(new_score, 5);
            }
            else
                cls2_timer = setInterval(clear_screen2, 5); 
        }
    }
    
    function main_loop()
    {
        // main game loop 
        
        // get the current time
        now = new Date().getTime();
        now = Math.floor(now /1000);
        
        
        // test if level completed. Id so go to next_level function
        if(round==4)
        {
            clearInterval(game_timer);
            applause.play();
            alpha=0;
            step=1;
            score += timer*100;
            nxt_lvl_timer = 0;
            next_level_timer = setInterval(next_level, 50);
        }
        
        // if time runs out game over
        if(timer<0)
        {
            clearInterval(game_timer);
            boo.play();
            alpha=0;
            end_game_timer=0;
            game_over_timer = setInterval(game_over, 50);
        }
        
        draw_template();
        draw_timer();
        draw_imgs();
        
        // get mouse postition
        document.onmousemove = function( ev ){
           x_mouse_pos = ev.pageX; 
           y_mouse_pos = ev.pageY;
        };
        
        
        // if mouse clicked loop through objects
        found = false;
        document.onclick = function( ev ){
        clearInterval(game_timer);
            for(i=49;i>=0;i--)
            {
                // test if mouse clicked over and object
                if(x_mouse_pos > positions_x[i] && x_mouse_pos< positions_x[i]+img[i].width)
                {
                    if(y_mouse_pos > positions_y[i] && y_mouse_pos < positions_y[i]+img[i].height)
                    {
                        // test if mouse clicked on an object in this round
                        for(j=((round*5)-5);j<(round*5);j++)
                        {
                            if(selected_imgs[j]==i && found==false && correct_imgs[j]==1)
                            {
                                bloop.play();
                                status[i] = 2;
                                correct_imgs[j] = 0;
                                found = true;
                                /*
                                // debugging code example
                                document.getElementById("debug").innerHTML=document.getElementById("debug").innerHTML+
                                "found "+i+" - "+img[i].src+"<br />";
                                */
                                score+=100+((level-1)*20);
                                corrects++;
                                if(corrects==5)
                                {
                                    corrects = 0;
                                    round++;
                                }
                            }
                        }
                    }
                }
            }
            // 5 seconds penalty
            if(!found)
            {
                blurp.play();
                start = start -5;
            }
            game_timer = setInterval(main_loop, 1);
        }
    }
    
    function draw_timer()
    {
        // draw the timer at the bottom of screen and the current level and score
        timer = timer_total-(now - start);
        ctx.strokeStyle="red";
        ctx.strokeText(timer + " Level - " +level , 15, 440);
        ctx.font = "bold 14px sans-serif";
        ctx.strokeText("Score: " +score , 15, 470);
        ctx.font = "bold 36px sans-serif";
    }
    
    function draw_imgs()
    {
        // draw the objects
        j=0;
        for(i=((round*5)-5);i<(round*5);i++)
        {
            if(correct_imgs[i]==1)
            {
                index = selected_imgs[i];
                ctx.drawImage(img[index], 30, ((j*70)+30));
                
            }
            
            j++;
        }
    
        score_i_messages = new Array();
        score_i_alpha = new Array();
        for(i=0;i<50;i++)
        {
            if(status[i]==1)
                ctx.drawImage(img[i], positions_x[i], positions_y[i]);
            else
            {
                if(status[i]>1)
                {
                    if(status[i]>30)
                        status[i]=0;
                    else
                    {
                        ctx.globalAlpha = 1-(status[i]/30);
                        ctx.drawImage(img[i], positions_x[i], positions_y[i]);
                        score_i_messages[i] = "+"+(100+((level-1)*20));
                        score_i_alpha[i] = 1-(status[i]/30);
                        status[i]++;
                        ctx.globalAlpha =1;
                       // 
                    }
                }
            }
        }
        
        for(var key in score_i_messages)
        {
            var value = score_i_messages[key];
            ctx.globalAlpha = score_i_alpha[key];
            ctx.strokeText(score_i_messages[key], positions_x[key], positions_y[key]);
            ctx.globalAlpha =1;
        }
    
    }
    
    function draw_template()
    {
       //  the the game template including level backdrop
        ctx.fillStyle = "rgb(200, 200, 50)";
        ctx.fillRect(0,0,665,500);
        ctx.shadowOffsetX = 3;
        ctx.shadowOffsetY = 3;
        ctx.fillStyle ="white";
        ctx.fillRect(10,10,200,480);
        switch(level)
        {
        case 1:
            ctx.fillRect(220,10, 435, 480);
        break;
        case 2:
            ctx.drawImage(level_bkdrop1 , 220,10);
        break;
        case 3:
            ctx.drawImage(level_bkdrop2 , 220,10);
        break;
        case 4:
            ctx.drawImage(level_bkdrop3 , 220,10);
        break;
        case 5:
            ctx.drawImage(level_bkdrop4 , 220,10);
        break;
        case 6:
            ctx.drawImage(level_bkdrop5 , 220,10);
        break;
        }
        ctx.shadowOffsetX = 0;
        ctx.shadowOffsetY = 0;
    }
    
    function in_array (needle, haystack, argStrict) {
        // Checks if the given value exists in the array  
        // 
        // version: 1109.2015
        // discuss at: http://phpjs.org/functions/in_array    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
        // +   improved by: vlado houba
        // +   input by: Billy
        // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
        // *     example 1: in_array('van', ['Kevin', 'van', 'Zonneveld']);    // *     returns 1: true
        // *     example 2: in_array('vlado', {0: 'Kevin', vlado: 'van', 1: 'Zonneveld'});
        // *     returns 2: false
        // *     example 3: in_array(1, ['1', '2', '3']);
        // *     returns 3: true    // *     example 3: in_array(1, ['1', '2', '3'], false);
        // *     returns 3: true
        // *     example 4: in_array(1, ['1', '2', '3'], true);
        // *     returns 4: false
        var key = '',        strict = !! argStrict;
     
        if (strict) {
            for (key in haystack) {
                if (haystack[key] === needle) {                return true;
                }
            }
        } else {
            for (key in haystack) {            if (haystack[key] == needle) {
                    return true;
                }
            }
        } 
        return false;
    }
    
    </script>
    </head>
    <body onload="init()">
    <?php
     foreach($images as $key=>$image)
     {
        echo '<img id="image_'.$key.'" src="images/'.$image.'" style="display:none;">
        ';
     }
    ?>
    <img id="level_bkdrop1" src="backdrops/beach.jpg" style="display:none;">
    <img id="level_bkdrop2" src="backdrops/bathroom.jpg" style="display:none;">
    <img id="level_bkdrop3" src="backdrops/gallery.jpg" style="display:none;">
    <img id="level_bkdrop4" src="backdrops/diningroom.jpg" style="display:none;">
    <img id="level_bkdrop5" src="backdrops/clutter.jpg" style="display:none;">
    <div id="debug" style="font-size:xx-small;float:right;clear:none;"></div>
    <canvas id="can" height="500" width="665">
    
    </canvas>
    <audio id="applause" src="sounds/applause_y.wav">
    <audio id="bloop" src="sounds/bloop_x.wav">
    <audio id="blurp" src="sounds/blurp_x.wav">
    <audio id="boo" src="sounds/boo.wav">
    </body>
    </html>
    Its the new_score function is the only thing missing at the moment. I wondered if there is something i can do with ajax here? Or it a dead loss.

    I wanted to upload the game to a zip with all the images and sounds but i cant attach it as its 512KB to big for the forum. I know it will be hard to test with out the images but if anyone can suggest anything. please do!
    You can not say you know how to do something, until you can teach it to someone else.

  • #2
    Senior Coder Rowsdower!'s Avatar
    Join Date
    Oct 2008
    Location
    Some say it's everything.
    Posts
    2,027
    Thanks
    5
    Thanked 397 Times in 390 Posts
    I can't really think of any way to prevent it. Other than through some easy-to-defeat means that would only stop the casual cheater, I can't even think of any good way to widely deter it. Since the data comes from the user, they will always be able to manipulate it and abuse your system. If you want to stop the vast majority of cheating I think you probably need to go with a compiled language running through a browser plugin (Java, Flash, etc.).

    My best guess for what to do with a pure js application is to encode the $_GET or $_POST string you send to the PHP page so it's not as simple as ?myscore=550. If you find a reversible way to encode it (or even encrypt it with a shared key - perhaps one that is generated randomly for each session but persists throughout a given session until that session sets a record, at which time the key changes - that way no two sessions would be likely to be able to use the same variable values to set a score and a user who set a score once wouldn't be able to resubmit the string to get a second high score) you could at least keep the totally uninitiated from cheating your system. If you obfuscate the variable names and functions and/or stuff the script inside an eval() you could make it one step more inconvenient to cheat. But nothing will ever be even clost to bullet-proof.

    So the question is: "Is the effort worth the benefit?" That's up to you.
    The object of opening the mind, as of opening the mouth, is to shut it again on something solid. –G.K. Chesterton
    See Mediocrity in its Infancy
    It's usually a good idea to start out with this at the VERY TOP of your CSS: * {border:0;margin:0;padding:0;}
    Seek and you shall find... basically:
    validate your markup | view your page cross-browser/cross-platform | free web tutorials | free hosting

  • #3
    Senior Coder timgolding's Avatar
    Join Date
    Aug 2006
    Location
    Southampton
    Posts
    1,519
    Thanks
    114
    Thanked 110 Times in 109 Posts
    well im not too fussed really as the game was originally designed for my girlfriend as she likes hidden object games. But i had the idea of hosting it on the web so i can let other people play. Maybe i will use sessions and just see if it gets abused lol
    You can not say you know how to do something, until you can teach it to someone else.


  •  

    Tags for this Thread

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •