jQuery is often used on websites to enhance the user experience and to make the page interactive. Recently, I was trying to integrate gravitational equations to the DIV elements of the DOM and ended up the rabbit hole which resulted in this simple game Balloon Burst game. The game is simple! you click on balloons to increase your score from a heap of randomly moving balloons and bombs. High speed balloons gives more points and clicking a bomb will result in GAME OVER! Number of balloons increase with time and you can also configure things like speed etc before staring the game. I thought, why not write about my experience -- below is a rundown of creating the game.
I started with setting up the initial DOM structure and give some styling to it. In the document.ready() function initialize the global variables for configuring the movement.
var marks_factor = 5; // Marks multiplying factor
var max_limit_items = 40; // Max limit for items to render on page
var max_diameter = 90; // Max limit for balloon diameter
var diameter = 50, // Setting up default value
max_items = 10,
probability = 80,
max_speed_limit = 10,
min_speed_limit = 3;
To get a random number we will simply use Math.random() function which is predefined in jQuery and to have a random number between a range of values, we will play with this function a little bit
function getRandomNumber(min, max) { // To generate random speed between between max and min rage of speed for the created balloons
return Math.floor(Math.random() * (max - min) + min); // Get difference of max and min and select a random number and add the lower bound to get the result
}
This function will return a random integer between min and max values. Another simple function using Math.random() which will return a random direction string
function getRandomDirection() { // To generate random direction for the created balloons
var decidingUnit = Math.floor(Math.random() * 100) % 4;
if (decidingUnit === 0) {
return 'top-left'; // 45 deg
} else if (decidingUnit === 1) {
return 'top-right';
} else if (decidingUnit === 2) {
return 'bottom-left';
} else if (decidingUnit === 3) {
return 'bottom-right';
}
}
createItem() function to create a random number based on the probability variable
var createItems = function () {
//Creating a balloon at random positions
var left = getRandomNumber(0, $(window).width() - diameter); // Random left position
var top = getRandomNumber(0, $(window).height() - diameter); // Random top position
var $newObj;
var speed = getRandomNumber(min_speed_limit, max_speed_limit);
if (getRandomNumber(0, 100) < probability) {
$newObj = $('<div>', {
class: 'ball gravity-enabled',
style:
'width : ' +
diameter +
'px; height: ' +
diameter +
'px; top : ' +
top +
'px ; left : ' +
left +
'px; background-color : rgb(' +
getRandomNumber(0, 255) +
', ' +
getRandomNumber(0, 255) +
' ,' +
getRandomNumber(0, 255) +
');',
'data-speed': speed,
}); // Creating a DOM object and assigning random css values to it
} else {
if ($('.bomb').length < Math.floor(max_items / 5)) {
// Render bombs only when screen has less than 20% (1/5) of bombs
$newObj = $('<div>', {
class: 'bomb gravity-enabled',
style: 'width : ' + diameter + 'px; height: ' + diameter + 'px; top : ' + top + 'px ; left : ' + left + 'px',
'data-speed': speed,
});
} else {
$newObj = $('<div>', {
class: 'ball gravity-enabled',
style:
'width : ' +
diameter +
'px; height: ' +
diameter +
'px; top : ' +
top +
'px ; left : ' +
left +
'px; background-color : rgb(' +
getRandomNumber(0, 255) +
', ' +
getRandomNumber(0, 255) +
' ,' +
getRandomNumber(0, 255) +
');',
'data-speed': speed,
});
}
}
$('body').append($newObj);
updatePosition($newObj, getRandomDirection(), speed); // binding random speed and direction to the newly created object
};
Considering only 4 directions for now. createItems() function will create a random item (balloon or a bomb according to the probability given by the user). The reason of storing the speed of the div in the markup is to calculate the score when the balloon bursts( click event). Since the newly created element will be a jQuery object, so creating a jQuery object variable using '$'. That means every time createItem() will get called, a new DIV element will be appended to the body with a random position through css. Note here, balloons need to have position absolute to get rendered at the random positions on the screen. Don't worry about the global variables values that will be fetched from the user from the initial screen. Fetching and setting variables for the functions through input screen-
$('.form-action .action').click(function() { // On click of Start New Game button.
var complexity = $('.radio-button[type="radio"][name="complexity"]:checked').val();
if (complexity === 'easy') {
max_speed_limit = 10;
min_speed_limit = 3;
probability = 80;
} else if (complexity === 'normal') {
max_speed_limit = 25;
min_speed_limit = 7;
probability = 70;
} else if (complexity === 'expert') {
max_speed_limit = 40;
min_speed_limit = 15;
probability = 55;
}
$('.initial-screen').addClass('hidden');
generateContiniousItems(1000, max_items); // this function will initiate the generation of items after certain time interval. (We will see its implementation later)
});
So far so good ! Items creation function has been created, the DOM has been created and variables has been fetched. Now the main challenge comes ! How to update the positions of all the objects simultaneously and dynamically and have a rebound effect when balloon touches the screen boundaries. JQuery doesn't support classes and OOPS so we cannot create objects instances of class. Then ? In jQuery we can declare a function (here updatePosition() ) once and call it with different parameters thereby creating a new unique instance for each function call. That mean for every newly created item updatePosition() function will have a different instance with different parameters. The function should take three parameters viz. the newly created object as a parameter (to update its css), a random direction and random speed.
We have to update the position in specific time intervals so this fact is clear that position should be updated using setTimeInterval() function. The speed logic can be induced to the div elements using two methods.
- Having dynamic time interval and fixed distance update factor The random speed of the div can be set by having speed variable as a time interval parameter. In this case the magnitude of positioning factor will be static but the time interval will be different for different div elements.
- Having dynamic distance update factor and fixed time interval The random speed of the div will be set by having static time interval for each element and speed variable as the distance update factor for each of them. In this case time interval will not change but the magnitude of positioning factor will differ.
Both approach are right but in first approach the maximum speed is limited from coding end as the max speed according to it will be when the time interval will be 1ms, whereas in second approach the magnitude of positioning factor can exceed to any positive number. So we will use second approach here.
According to the second approach -
var updatePosition = function ($obj, direction, speed) {
var down_direc, up_direc, left_direc, right_direc, speedUnit;
// Setting up the local variables for setting up the left right directions
// Splitting up the variables to smaller ones to enhance the code readbility
if (direction === 'top-left') {
down_direc = false;
up_direc = true;
right_direc = false;
left_direc = true;
} else if (direction === 'top-right') {
down_direc = false;
up_direc = true;
right_direc = true;
left_direc = false;
} else if (direction === 'bottom-right') {
down_direc = true;
up_direc = false;
right_direc = true;
left_direc = false;
} else if (direction === 'bottom-left') {
down_direc = true;
up_direc = false;
right_direc = false;
left_direc = true;
} else {
down_direc = false;
up_direc = true;
right_direc = false;
left_direc = true;
}
// Conditioning and massaging the speed variable to have sensible speed
speedUnit = speed / 10;
// Setting up the boundaries for rebound effect
var max_bottom_limit = $(window).height() - $obj.height(); // (-) because boundary collision will occur when lower part of the balloon touches the window boundary
var max_left_limit = $(window).width() - $obj.width(); // (-) because boundary collision will occur when right part of the balloon touches the window boundary
var init_left = $obj.offset().left; // Getting the current position of the div element
var init_top = $obj.offset().top;
setInterval(function () {
// Main logic
$obj.css({
top: init_top, // Updating the position of the div element (starts from the second iteration)
left: init_left,
});
if (down_direc) {
// If the ball vertical movement is down
if (init_top < max_bottom_limit) {
init_top = init_top + speedUnit; // Update the top position
if (init_top >= max_bottom_limit) {
// If the element bottom position exceeds the max lower boundary limit
init_top = max_bottom_limit; //set the element position to the max bottom boundary limit
}
}
if (init_top === max_bottom_limit) {
// If the element has reached to the bottom of the page update the direction variables.
down_direc = false; // Direction to top
up_direc = true;
}
}
if (up_direc) {
// If the ball vertical movement is up
if (init_top > 0) {
init_top = init_top - speedUnit; // Update the top position
if (init_top <= 0) {
// If the element bottom position exceeds the max upper boundary limit
init_top = 0; //set the element position to the upper max boundary limit
}
}
if (init_top === 0) {
// If the element has reached to the bottom of the page update the direction variables.
down_direc = true; // Direction to bottom
up_direc = false;
}
}
if (right_direc) {
// If the ball horizontal movement is right
if (init_left < max_left_limit) {
init_left = init_left + speedUnit; // Update the left position
if (init_left >= max_left_limit) {
// If the element left position exceeds the max right boundary limit
init_left = max_left_limit; //set the element position to the max right boundary limit
}
}
if (init_left === max_left_limit) {
// If the element has reached to the bottom of the page update the direction variables.
right_direc = false; // Direction to left
left_direc = true;
}
}
if (left_direc) {
// If the ball horizontal movement is left
if (init_left > 0) {
init_left = init_left - speedUnit; // Update the left position
if (init_left <= 0) {
// If the element left position exceeds the max left boundary limit
init_left = 0; //set the element position to the max left boundary limit
}
}
if (init_left === 0) {
right_direc = true; // Direction to right
left_direc = false;
}
}
}, 1); // Updating the position on every ms
};
The function will update the position of the passed jQuery object through 'init_left' and 'init_top' variables in every 1ms. This will generate the animation effect and on having these values greater than the boundary values the directions are changed. This logic will update left and top both position simultaneously.
Not that hard! Right? You can add new implementations to this project by cloning or forking the code base from https://github.com/swastikpareek/jq_ballon_game or you can create your own jQuery effects or create your own custom game. In this way you will get to learn about new features and new functions in jQuery.