Created
July 19, 2010 02:05
-
-
Save bcoe/480916 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// All the Tetris blocks are instances of this Block class. | |
Block = Class.extend({ | |
init: function(game, grid, color) { | |
this.color = color; | |
this.grid = grid; | |
this.game = game; | |
this.x = 64; | |
this.y = -128; | |
this.rotation = 0; | |
this.lock = false; | |
}, | |
// Update is called to move the block down the screen. | |
update: function() { | |
if (this.lock) { | |
return; | |
} | |
var ex = this.x; | |
var ey = this.y + 32; | |
var erotate = this.rotation; | |
if (!this.collide(ex, ey, erotate, true)) { | |
this.y += 32; | |
} | |
}, | |
// Move the block left. | |
left: function() { | |
if (this.lock) { | |
return; | |
} | |
var ex = this.x - 32; | |
var ey = this.y; | |
var erotate = this.rotation; | |
if (!this.collide(ex, ey, erotate, false)) { | |
this.x -= 32; | |
} | |
}, | |
// Move the block right. | |
right: function() { | |
if (this.lock) { | |
return; | |
} | |
var ex = this.x + 32; | |
var ey = this.y; | |
var erotate = this.rotation; | |
if (!this.collide(ex, ey, erotate, false)) { | |
this.x += 32; | |
} | |
}, | |
// 'rotate' the block. | |
rotate: function() { | |
if (this.lock) { | |
return; | |
} | |
var ex = this.x; | |
var ey = this.y; | |
var erotate = (this.rotation + 1) % 4; | |
if (!this.collide(ex, ey, erotate, true)) { | |
this.rotation = (this.rotation + 1) % 4; | |
} | |
}, | |
// Test for collision. | |
collide: function(ex, ey, erotate, can_lock) { | |
var self = this; | |
var y = ey; | |
var return_me = false; | |
var finish = false; | |
$.each(self.grid[erotate], function(k, v) { | |
var x = ex; | |
$.each(v, function(k2, v2) { | |
if (v2) { | |
var cx = x / 32; | |
var cy = y / 32; | |
if (cx >= 0 && cy >= 0) { | |
if (cx < self.game.max_x && cy < self.game.max_y) { | |
if (self.game.grid[cy][cx]) { | |
if (cx > 0 && cx < 11) { | |
finish =true; | |
} | |
return_me = true; | |
} | |
} | |
} | |
} | |
x += 32; | |
}); | |
y += 32; | |
}); | |
if (finish && can_lock) { | |
this.lock = true; | |
this.copy(); | |
} | |
return return_me; | |
}, | |
// Copy the block object onto the game grid. Create square objects. | |
copy: function() { | |
var self = this; | |
var y = self.y; | |
$.each(self.grid[self.rotation], function(k, v) { | |
var x = self.x; | |
$.each(v, function(k2, v2) { | |
if (v2) { | |
var cx = x / 32; | |
var cy = y / 32; | |
if (cx >= 0 && cy >= 0) { | |
if (cx < self.game.max_x && cy < self.game.max_y) { | |
self.game.grid[cy][cx] = 1; | |
square = new Square(self.game, cx, cy, self.color); | |
self.game.squares.push(square); | |
} | |
} | |
} | |
x += 32; | |
}); | |
y += 32; | |
}); | |
this.game.drop(); | |
}, | |
// Render this block on the HTML 5 canvas. | |
render: function() { | |
var self = this; | |
var y = self.y; | |
$.each(self.grid[self.rotation], function(k, v) { | |
var x = self.x; | |
$.each(v, function(k2, v2) { | |
if (v2) { | |
self.game.context.fillStyle = self.color; | |
self.game.context.fillRect (x, y, 32, 32); | |
} | |
x += 32; | |
}); | |
y += 32; | |
}); | |
} | |
}); | |
// When a tetris block has reached its final resting place on the play | |
// area, it is copied onto square objects. | |
Square = Class.extend({ | |
init: function(game, x, y, color) { | |
this.game = game; | |
this.x = x; | |
this.y = y; | |
this.color = color; | |
this.display = true; | |
}, | |
get_x: function() { | |
return this.x; | |
}, | |
get_y: function() { | |
return this.y; | |
}, | |
set_y: function(y) { | |
this.y = y; | |
}, | |
no_show: function() { | |
this.display = false; | |
}, | |
down: function() { | |
}, | |
render: function() { | |
if (this.display) { | |
this.game.context.fillStyle = this.color; | |
this.game.context.fillRect (this.x * 32, this.y * 32, 32, 32); | |
} | |
} | |
}) | |
// The game itself. | |
Game = Class.extend({ | |
// The tetris game area. | |
init_grid: function() { | |
// 12 x 18 | |
this.max_x = 12; | |
this.max_y = 18; | |
this.grid = [ | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1 , 1, 1] | |
] | |
}, | |
// All the tetris blocks, I realize I should have used a | |
// rotation matrix, but was on a plane and couldn't look | |
// up the math. | |
generate_blocks: function() { | |
var self = this; | |
var square_block = new Block(self, | |
[ | |
[ | |
[1, 1], | |
[1, 1] | |
], | |
[ | |
[1, 1], | |
[1, 1] | |
], | |
[ | |
[1, 1], | |
[1, 1] | |
], | |
[ | |
[1, 1], | |
[1, 1] | |
] | |
], | |
"rgba(255, 125, 0, 0.8)" | |
); | |
var straight_block = new Block(self, | |
[ | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 1, 0, 0], | |
[0, 0, 1, 0, 0], | |
[0, 0, 1, 0, 0], | |
[0, 0, 1, 0, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 1, 1, 1, 1] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 1, 0, 0], | |
[0, 0, 1, 0, 0], | |
[0, 0, 1, 0, 0], | |
[0, 0, 1, 0, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 1, 1, 1, 1] | |
] | |
], | |
"rgba(255, 255, 0, 0.8)" | |
); | |
var l1_block = new Block(self, | |
[ | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 1, 1], | |
[0, 0, 0, 1, 0], | |
[0, 0, 0, 1, 0], | |
[0, 0, 0, 0, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 1, 1, 1, 0], | |
[0, 0, 0, 1, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 1, 0, 0, 0], | |
[0, 1, 0, 0, 0], | |
[1, 1, 0, 0, 0], | |
[0, 0, 0, 0, 0] | |
], | |
[ | |
[0, 1, 0, 0, 0], | |
[0, 1, 1, 1, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0] | |
] | |
], | |
"rgba(50, 126, 32, 0.8)" | |
); | |
var l2_block = new Block(self, | |
[ | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 1, 1, 0], | |
[0, 0, 0, 1, 0], | |
[0, 0, 0, 1, 0], | |
[0, 0, 0, 0, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 1, 0], | |
[0, 1, 1, 1, 0], | |
[0, 0, 0, 0, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 1, 0, 0, 0], | |
[0, 1, 0, 0, 0], | |
[0, 1, 1, 0, 0], | |
[0, 0, 0, 0, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 1, 1, 1, 0], | |
[0, 1, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0] | |
] | |
], | |
"rgba(0, 255, 0, 0.8)" | |
); | |
var crazy_block = new Block(self, | |
[ | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 1, 0, 0], | |
[0, 1, 1, 1, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 1, 0, 0], | |
[0, 0, 1, 1, 0], | |
[0, 0, 1, 0, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 1, 1, 1, 0], | |
[0, 0, 1, 0, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 1, 0, 0], | |
[0, 1, 1, 0, 0], | |
[0, 0, 1, 0, 0] | |
], | |
], | |
"rgba(255, 0, 0, 0.8)" | |
); | |
var crazy_block2 = new Block(self, | |
[ | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 1, 0], | |
[0, 0, 1, 1, 0], | |
[0, 0, 1, 0, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 1, 1, 0, 0], | |
[0, 0, 1, 1, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 1, 0], | |
[0, 0, 1, 1, 0], | |
[0, 0, 1, 0, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 1, 1, 0, 0], | |
[0, 0, 1, 1, 0] | |
], | |
], | |
"rgba(0, 255, 255, 0.8)" | |
); | |
var crazy_block3 = new Block(self, | |
[ | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 1, 0, 0], | |
[0, 0, 1, 1, 0], | |
[0, 0, 0, 1, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 1, 1, 0], | |
[0, 1, 1, 0, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 1, 0, 0], | |
[0, 0, 1, 1, 0], | |
[0, 0, 0, 1, 0] | |
], | |
[ | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 1, 1, 0], | |
[0, 1, 1, 0, 0] | |
], | |
], | |
"rgba(255, 125, 16, 0.8)" | |
); | |
this.blocks = [ | |
l1_block, | |
l2_block, | |
square_block, | |
straight_block, | |
crazy_block, | |
crazy_block2, | |
crazy_block3 | |
]; | |
}, | |
init: function() { | |
// Get the context of the 2D canvas for rendering. | |
var screen = document.getElementById('screen'); | |
this.context = screen.getContext('2d'); | |
var self = this; | |
this.init_grid(); | |
this.speed = 6; | |
this.squares = []; | |
this.score = 0; | |
this.generate_blocks(); | |
this.current_block = this.blocks[Number(Math.random() * (this.blocks.length - 0.5)).toFixed(0)]; | |
this.line_count = 0; | |
this.increment = 0; | |
setInterval(function() { | |
// 10 x 17 rows. | |
self.context.fillStyle = "rgba(0, 0, 0, 1.0)"; | |
self.context.fillRect (0, 0, 384, 576); | |
self.context.fillStyle = "rgba(100, 100, 100, 0.75)"; | |
self.context.fillRect (0, 0, 32, 576); | |
self.context.fillRect (384 - 32, 0, 32, 576); | |
self.context.fillRect (32, 576 - 32, 384 - 64, 32); | |
// Allow the speed to change. | |
if (self.increment % self.speed == 0) { | |
self.current_block.update(); | |
} | |
$.each(self.squares, function(k, v) { | |
v.render(); | |
}); | |
self.current_block.render(); | |
self.increment++; | |
}, 50); | |
$(document).keydown( function(e) { | |
if (e.keyCode == 37) { | |
self.current_block.left(); | |
} | |
if (e.keyCode == 39) { | |
self.current_block.right(); | |
} | |
if (e.keyCode == 38) { | |
self.current_block.rotate(); | |
} | |
if (e.keyCode == 40) { | |
self.current_block.update(); | |
} | |
}); | |
}, | |
// Check to see whether any lines have been created. | |
check_lines: function() { | |
var self = this; | |
var lines = []; | |
var y = 0; | |
$.each(self.grid, function(k, v) { | |
var sum = 0; | |
if (y != 17) { | |
$.each(v, function(k2, v2) { | |
if (v2) { | |
sum += 1; | |
} | |
}); | |
} | |
if (sum == 12) { | |
lines.push(y); | |
} | |
y++; | |
}); | |
var add_score = 1; | |
$.each(lines, function(k, v) { | |
self.remove_line(v); | |
self.line_count++; | |
$('.lines').html("Lines: " + self.line_count); | |
if (self.line_count % 10 == 0) { | |
self.speed--; | |
if (self.speed < 1) { | |
self.spedd = 1; | |
} | |
} | |
add_score *= 10; | |
}); | |
if (lines.length) { | |
self.score = self.score + add_score; | |
$('.score').html("Score: " + self.score); | |
this.check_lines(); | |
} | |
}, | |
// Remove a line from the screen updating all the square objects. | |
remove_line: function(line_num) { | |
var self = this; | |
var temp = [1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1]; | |
this.grid[line_num] = temp; | |
$.each(self.squares, function(k, v) { | |
if (v.get_y() == line_num) { | |
v.no_show(); | |
} else | |
if (v.get_y() < line_num) { | |
v.set_y(v.get_y() + 1) | |
} | |
}); | |
var temp_grid = [ | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 , 0, 1], | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1 , 1, 1] | |
]; | |
var y = 0; | |
$.each(self.grid, function(k, v) { | |
var x = 0; | |
$.each(v, function(k2, v2) { | |
if (y < line_num) { | |
if (self.grid[y][x]) { | |
temp_grid[y+1][x] = 1; | |
} else if (self.grid[y][x]) { | |
temp_grid[y][x] = self.grid[y][x]; | |
} | |
} else { | |
if (self.grid[y][x]) { | |
temp_grid[y][x] = self.grid[y][x]; | |
} | |
} | |
x++; | |
}); | |
y++; | |
}); | |
self.grid = temp_grid; | |
}, | |
// Have you lost the game? | |
check_lose: function() { | |
var self = this; | |
var sum = 0; | |
$.each(self.grid[0], function(k, v) { | |
if (v) { | |
sum ++; | |
} | |
}); | |
if (sum > 2) { | |
self.lose = true; | |
$('.lose').html("YOU LOSE | |
AND | |
THEREFORE | |
SUCK!") | |
} | |
}, | |
// Drop a new block. | |
drop: function() { | |
if (!this.lose) { | |
this.check_lose(); | |
this.generate_blocks(); | |
this.current_block = this.blocks[Number(Math.random() * (this.blocks.length - 0.5)).toFixed(0)]; | |
this.check_lines(); | |
} | |
} | |
}) | |
// Load the tetris game. | |
// Main application entry point. | |
$(document).ready(function() { | |
var game = new Game; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment