on Tutorials

jQuery Calculus Game Tutorial – part 1

0 comments
jQuery Calculus Game
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditShare on StumbleUpon

The idea behind this jQuery Calculus Game is fairly simple. You get a generated grid of number pairs and calculus task with some operand and anticipated result.

You then have to find pairs of numbers which makes the correct result.You start with 30 seconds at the beginning.

If you click on correct pairs, you get some bonus time, and if you click on wrong ones, you get some negative time.

If all that sounds confusing, here is a picture:

jQuery Calculus Game

I hope that this makes sense. The number 27 on the image is number of seconds remaining to solve the grid. It looks easy, as this part of the tutorial is for building a beginner’s level game which you can give your kids to enjoy.

So, let’s begin with some simple HTML markup for the game, so create a new game.php file and paste this markup in:

<!doctype html>
<html lang="en">
<head>

    <title>Calculus Game by CodeForest</title>

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <link type="text/css" rel="stylesheet" href="styles.css" />
    <link href='http://fonts.googleapis.com/css?family=Volkhov:400,700' rel='stylesheet' type='text/css'>

</head>

<body>

    <div id="header">
		<h1><a href=""><img src="calculus-logo.png" alt="Calculus Game by CodeForest" /></a></h1>
    </div>

	<div id="game_header">

		<div id="task">
			<span id="first">?</span>
			<span id="operation"></span>
			<span id="second">?</span>
			&nbsp;=&nbsp;
			<span id="result"></span>
		</div>

		<div id="timer" class=""></div>

	</div>

	<div id="grid"></div>
<script type="text/javascript" src="scripts/main.js"></script>
</body>
</html>

As you already noticed, we need to create a scripts folder and put main.js file in it. This file will be used for all JavaScript needed for the game.

All the files will be available on GitHub, so there is no need to show the CSS here, you can make your own, or take mine from Github. All CSS, design and some grid generation were made by Zoran Jambor, so I really thank him for that.

Generating the grid

Our next task is to generate the grid, well not the HTML table, but an array of number pairs that will be used later to fill the table.

This is the function that is dealing with that part:

// gridDimension - dimension of the grid (if 6 is entered, grid will be 6*6)
// maxValue - max value for the result. Should not be less than 8.
// operation - '+' or '-', the value is optional, if not entered, operation will be addition (+)
function generateGrid( gridDimension, maxValue, operation ) {

    if (gridDimension % 2 != 0) {
    	gridDimension += 1; // as gridDimension can only be an even number
    }
    var grid = {
                    //Get random value for the result, based on maxValue
                    result : Math.ceil( Math.random() * maxValue ),

                    size : (gridDimension * gridDimension),

                    fields : [],

                    operation : operation || '+'
        },

        tempItem     = '';

    //So that the problem doesn't become too easy to solve
    if ( grid.result < 8 ) grid.result += 6;

    //Generating values for all fields in grid.
    //Each pass generates 2 field values that when calculated give the result.
    while ( grid.size ){

        //Generate first random value
        tempItem = Math.ceil( Math.random() * grid.result );

        //Pair value is calculated based on operation
        if ( grid.operation == '+'){

            grid.fields.push( tempItem );
            grid.fields.push( grid.result - tempItem );

        } else {

            tempItem += grid.result;
            grid.fields.push( tempItem );
            grid.fields.push( tempItem - grid.result);

        }

        grid.size -= 2;

    }

    //Randomize the field values
    grid.fields.sort( function(){return 0.5 - Math.random()} );

    return grid;

}

The above code is really heavily commented, so I think everything is clear here. Basically, this function will be helping us with quickly generating the grid based on some parameters, which will come in handy in the later versions of the game, which will be even more dynamic.

Timer

Oh, I forgot to mention, there is a catch. For the game not to be too easy, the time to find all pairs is limited. So let us create a timer function which will be responsible for all time related tasks:

function timer(increment) {
    // our HTML id for showing the time
    var $timer = $('#timer');

    if(increment == 0) {
        timer_start = start_time;
    }

    timer_start += increment;
    $timer.html(timer_start);

	// some colors on the timer
	if( timer_start < 4 ) {

		$timer
			.removeClass('warning')
			.addClass('danger');

	} else if( timer_start < 8 ) {

		$timer
			.addClass('warning');

	} else {

		$timer.
			removeClass('warning danger');

	}

	if(timer_start < 1) {
            reset();
            play();
        }
}

Ok, again pretty straightforward code. Let us write the reset function mentioned above, which will clear all elements, the intervals used and reset everything to it’s beginning state.

function reset(){
    $('#grid, #operation, #result').html('');
    $('#first, #second').html('?');
    clearInterval(interval);
}

The main play function

First, we will set some global variables which will be used through the game:

// global variables for the game
var interval,
    start_time = 30, // time from which timer starts counting
    bonusTime = 3, // bonus seconds for correct answer
    punishmentTime = 3, // punishment seconds for wrong answer
    gridSize = 6, // should be an even number, this is the side for our grid of numbers
    maxValue = 10; // max result value

    if (gridSize % 2 != 0) {
	gridSize += 1; // if someone did not put an even number, correct it!
    }

Ok, I know you’re eager, here is our main play function, which is handling all, from generating the grid, drawing the table, setting timer and intervals, checking the results, adding bonus seconds, subtracting punishment time and announcing the winner or resetting the game if time runs out.

/**
 * Main method for playing
 */
function play() {

	// choose operation randomly
	if (Math.ceil(Math.random() * 2) == 2) {
		operand = '+';
	} else {
		operand = '-';
	}
	// generating our grid
	var result = generateGrid(gridSize, maxValue, operand);

	// filling the table with grid values
	var html = '<table><tbody><tr>', fieldsLength = result.fields.length;
	for ( var i = 0; i < fieldsLength; i++) {
		attr = 'cell';

		html += '<td id="cell' + (i + 1) + '">' + result.fields[i] + '</td>\n';

		if ((i + 1) % gridSize == 0) {
			html += '</tr><tr>';
		}
	}

	html += '</tr></tbody></table>'

	//this will be better solved next time
	$('#grid').append(html);
	$('#operation').append(result.operation);
	$('#result').append(result.result);

	// core gaming
	timer(0);

	// setting the interval to 1 second
	interval = setInterval(function() {
		timer(-1);
	}, 1000);

	var check = false, first = 0, second = 0, firstID = '', secondID = '';

	//Cache often used selectors.
	var animationTimeout = 200, $first = $('#first'), $second = $('#second'), hasWon = (gridSize * gridSize) / 2, correctPairs = 0;

	$('#grid').find('td').each(
	function() {

		$(this).click(
				function() {

					if (!check) {

						first = $(this).html();
						$(this).addClass('active');
						$first.html(first);
						firstID = $(this).attr('id');
						check = true;

					} else {

						second = $(this).html();
						$second.html(second);
						secondID = $(this).attr('id');

						if (result.operation == '+') {

							tempResult = parseInt(first)
									+ parseInt(second);

						} else {

							tempResult = parseInt(first)
									- parseInt(second);

						}

						// correct
						if (tempResult == result.result
								&& firstID != secondID) { // also checking for 2 clicks on the same cell

							$('#' + firstID + ', #' + secondID).html(
									'X').addClass('success');

							//Timeout to allow success animation to finish.
							setTimeout(function() {

								$('#' + firstID + ', #' + secondID)
										.removeClass('success active')
										.addClass('completed');

							}, animationTimeout);

							timer(bonusTime); // bonus time

							// incrementing number of correct pairs
							correctPairs += 1;
							// did we won the game?
							if (correctPairs == hasWon) { //yes, we did!!!
								reset();
								alert('You won the game!');
							}

						} else {

							timer(-punishmentTime); // punishment

							$('#' + firstID + ', #' + secondID)
									.addClass('active error');

							setTimeout(function() {

								$('#' + firstID + ', #' + secondID)
										.removeClass('error active');

							}, animationTimeout);

							check = false;

						}

						$second.html('?');
						$first.html('?');
						check = false;
					}
				});
	});
}

The code above is also commented heavily, so I hope that you can find your way through it.

There is one more thing to do and that is to call the play method on document.ready:

$(document).ready(function(){
    play();
});

You can see the demo or download files below:

Source filesDemo

What’s next

This concludes the first part of jQuery Calculus game tutorial. In the next part we will go further with difficulty levels, rounds, scores and high scores tables.

I am eager to see what will come out of this.

If you have any questions, do not hesitate to ask in the comments section below!

Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditShare on StumbleUpon



Comments are closed.