Go Back   CodingForums.com > :: Client side development > JavaScript programming > Ajax and Design

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 09-21-2012, 01:46 PM   PM User | #1
timgolding
Senior Coder

 
timgolding's Avatar
 
Join Date: Aug 2006
Location: Southampton
Posts: 1,460
Thanks: 89
Thanked 110 Times in 109 Posts
timgolding is on a distinguished road
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.
timgolding is offline   Reply With Quote
Old 09-21-2012, 06:20 PM   PM User | #2
Rowsdower!
Senior Coder

 
Rowsdower!'s Avatar
 
Join Date: Oct 2008
Location: Some say it's everything.
Posts: 2,007
Thanks: 5
Thanked 395 Times in 388 Posts
Rowsdower! has a spectacular aura aboutRowsdower! has a spectacular aura aboutRowsdower! has a spectacular aura about
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
Rowsdower! is offline   Reply With Quote
Old 09-22-2012, 11:13 AM   PM User | #3
timgolding
Senior Coder

 
timgolding's Avatar
 
Join Date: Aug 2006
Location: Southampton
Posts: 1,460
Thanks: 89
Thanked 110 Times in 109 Posts
timgolding is on a distinguished road
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.
timgolding is offline   Reply With Quote
Reply

Bookmarks

Tags
canvas game, js game

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 04:06 AM.


Advertisement
Log in to turn off these ads.