Move Number Tiles
After completing the layout and initialization, we will now implement the functionality to move and eliminate number tiles until the game succeeds or fails.
Add the following code to main.js
:
// Listen for keyboard arrow key movements
$(document).keydown(function (event) {
if ($("#score").text() == success_string) {
new_game();
return;
}
switch (event.keyCode) {
case 37: // Left
event.preventDefault();
if (move_left()) {
setTimeout("generate_one_number()", 210);
setTimeout("is_gameover()", 300);
}
break;
case 38: // Up
event.preventDefault();
if (move_up()) {
setTimeout("generate_one_number()", 210);
setTimeout("is_gameover()", 300);
}
break;
case 39: // Right
event.preventDefault();
if (move_right()) {
setTimeout("generate_one_number()", 210);
setTimeout("is_gameover()", 300);
}
break;
case 40: // Down
event.preventDefault();
if (move_down()) {
setTimeout("generate_one_number()", 210);
setTimeout("is_gameover()", 300);
}
break;
default:
break;
}
});
// Listen for touchstart event on mobile devices
document.addEventListener("touchstart", function (event) {
startx = event.touches[0].pageX;
starty = event.touches[0].pageY;
});
// Listen for touchmove event on mobile devices
document.addEventListener("touchmove", function (event) {
event.preventDefault();
});
// Listen for touchend event on mobile devices
document.addEventListener("touchend", function (event) {
endx = event.changedTouches[0].pageX;
endy = event.changedTouches[0].pageY;
var deltax = endx - startx;
var deltay = endy - starty;
if (
Math.abs(deltax) < 0.3 * document_width &&
Math.abs(deltay) < 0.3 * document_width
) {
return;
}
if ($("#score").text() == success_string) {
new_game();
return;
}
// x-axis movement
if (Math.abs(deltax) >= Math.abs(deltay)) {
if (deltax > 0) {
// Move right
if (move_right()) {
setTimeout("generate_one_number()", 210);
setTimeout("is_gameover()", 300);
}
} else {
// Move left
if (move_left()) {
setTimeout("generate_one_number()", 210);
setTimeout("is_gameover()", 300);
}
}
} else {
// y-axis movement
if (deltay > 0) {
// Move down
if (move_down()) {
setTimeout("generate_one_number()", 210);
setTimeout("is_gameover()", 300);
}
} else {
// Move up
if (move_up()) {
setTimeout("generate_one_number()", 210);
setTimeout("is_gameover()", 300);
}
}
}
});
// Move left
function move_left() {
if (!can_move_left(board)) {
return false;
}
// Move left
for (var i = 0; i < 4; i++) {
for (var j = 1; j < 4; j++) {
if (board[i][j] != 0) {
for (var k = 0; k < j; k++) {
if (board[i][k] == 0 && no_block_horizontal(i, k, j, board)) {
show_move_animation(i, j, i, k);
board[i][k] = board[i][j];
board[i][j] = 0;
break;
} else if (
board[i][k] == board[i][j] &&
no_block_horizontal(i, k, j, board) &&
!has_conflicted[i][k]
) {
show_move_animation(i, j, i, k);
board[i][k] += board[i][j];
board[i][j] = 0;
// Add score
score += board[i][k];
update_score(score);
has_conflicted[i][k] = true;
break;
}
}
}
}
}
setTimeout("update_board_view()", 200);
return true;
}
// Move right
function move_right() {
if (!can_move_right(board)) {
return false;
}
// Move right
for (var i = 0; i < 4; i++) {
for (var j = 2; j >= 0; j--) {
if (board[i][j] != 0) {
for (var k = 3; k > j; k--) {
if (board[i][k] == 0 && no_block_horizontal(i, j, k, board)) {
show_move_animation(i, j, i, k);
board[i][k] = board[i][j];
board[i][j] = 0;
break;
} else if (
board[i][k] == board[i][j] &&
no_block_horizontal(i, j, k, board) &&
!has_conflicted[i][k]
) {
show_move_animation(i, j, i, k);
board[i][k] += board[i][j];
board[i][j] = 0;
// Add score
score += board[i][k];
update_score(score);
has_conflicted[i][k] = true;
break;
}
}
}
}
}
setTimeout("update_board_view()", 200);
return true;
}
// Move up
function move_up() {
if (!can_move_up(board)) {
return false;
}
// Move up
for (var j = 0; j < 4; j++) {
for (var i = 1; i < 4; i++) {
if (board[i][j] != 0) {
for (var k = 0; k < i; k++) {
if (board[k][j] == 0 && no_block_vertical(j, k, i, board)) {
show_move_animation(i, j, k, j);
board[k][j] = board[i][j];
board[i][j] = 0;
break;
} else if (
board[k][j] == board[i][j] &&
no_block_vertical(j, k, i, board) &&
!has_conflicted[k][j]
) {
show_move_animation(i, j, k, j);
board[k][j] += board[i][j];
board[i][j] = 0;
// Add score
score += board[k][j];
update_score(score);
has_conflicted[k][j] = true;
break;
}
}
}
}
}
setTimeout("update_board_view()", 200);
return true;
}
// Move down
function move_down() {
if (!can_move_down(board)) {
return false;
}
// Move down
for (var j = 0; j < 4; j++) {
for (var i = 2; i >= 0; i--) {
if (board[i][j] != 0) {
for (var k = 3; k > i; k--) {
if (board[k][j] == 0 && no_block_vertical(j, i, k, board)) {
show_move_animation(i, j, k, j);
board[k][j] = board[i][j];
board[i][j] = 0;
break;
} else if (
board[k][j] == board[i][j] &&
no_block_vertical(j, i, k, board) &&
!has_conflicted[k][j]
) {
show_move_animation(i, j, k, j);
board[k][j] += board[i][j];
board[i][j] = 0;
// Add score
score += board[k][j];
update_score(score);
has_conflicted[k][j] = true;
break;
}
}
}
}
}
setTimeout("update_board_view()", 200);
return true;
}
// Check if the game is successful or failed
function is_gameover() {
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
if (board[i][j] == 2048) {
update_score(success_string);
return;
}
}
}
if (nospace(board) && nomove(board)) {
gameover();
}
}
// Update the game over text when the game ends
function gameover() {
update_score(gameover_string);
}