Skip to content

Instantly share code, notes, and snippets.

@gujc71
Last active July 16, 2017 14:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gujc71/a08345a23dbba37a3915b0713578d352 to your computer and use it in GitHub Desktop.
Save gujc71/a08345a23dbba37a3915b0713578d352 to your computer and use it in GitHub Desktop.
Tetris Game
<!DOCTYPE html>
<html>
<head>
<title>Script-based animation using requestAnimationFrame</title>
</head>
<body>
<canvas id="tetrisCanvas" width="200" height="400"></canvas>
<script>
// control with keyboard, block color
var canvas = document.getElementById('tetrisCanvas');
var ctx = canvas.getContext('2d');
var shapes = [
[ 0x4640, 0x0E40, 0x4C40, 0x4E00 ], // 'T'
[ 0x8C40, 0x6C00, 0x8C40, 0x6C00 ], // 'S'
[ 0x4C80, 0xC600, 0x4C80, 0xC600 ], // 'Z'
[ 0x4444, 0x0F00, 0x4444, 0x0F00 ], // 'I'
[ 0x44C0, 0x8E00, 0xC880, 0xE200 ], // 'J'
[ 0x88C0, 0xE800, 0xC440, 0x2E00 ], // 'L'
[ 0xCC00, 0xCC00, 0xCC00, 0xCC00 ] // 'O'
];
function getNextShape() {
curShapeType = Math.floor((Math.random() * 7));
curRotation = 0;
return shapes[curShapeType][curRotation]
}
var ROW_CNT = 20;
var COL_CNT = 10;
var KEY = { ESC: 27, SPACE: 32, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40 };
var shapeColor = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"];
var curShapeType = 0, curRotation = 0, curShape = getNextShape() ;
var sPos = {x: (COL_CNT-4) / 2, y:0};
var gamePanel = [];
for (var y = 0; y < ROW_CNT; y++) {
gamePanel[y] = [];
for (var x = 0; x < COL_CNT; x++) {
gamePanel[y][x] = 0;
}
}
var requestId = 0, isPlaying=true;
var dt = 0, step = 0.6, completedRow = 0;;
var last = now = timestamp();
function timestamp() { return new Date().getTime(); }
function frame() {
now = timestamp();
update(Math.min(1, (now - last) / 1000.0));
last = now;
if (isPlaying){
requestId = requestAFrame(frame);
} else {
window.cancelAFrame(requestId);
}
}
function update(idt) {
dt = dt + idt;
if (dt > step) {
dt = dt - step;
playingTetris();
}
}
window.onload = function(){
requestId = window.requestAFrame(frame);
}
window.requestAFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function (callback) {
return window.setTimeout(callback, 1000 / 60); // shoot for 60 fps
};
})();
window.cancelAFrame = (function () {
return window.cancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.mozCancelAnimationFrame ||
window.oCancelAnimationFrame ||
function (id) {
window.clearTimeout(id);
};
})();
function playingTetris() {
if ( intersects(sPos.y + 1, sPos.x)) {
for (var i = 0; i < 4; i++)
for (var j = 0; j < 4; j++)
if ((curShape & (0x8000 >> (i * 4 + j))) && gamePanel[sPos.y+i]) {
gamePanel[sPos.y+i][sPos.x+j] = curShapeType+1;
}
curShape = getNextShape();
sPos = {x: (COL_CNT-4) / 2, y:0};
if (intersects(sPos.y, sPos.x)) {
isPlaying = false;
alert("Game Over");
}
gamePanel = removeRow();
} else {
sPos.y++;
}
draw();
}
function intersects(y, x) {
for (var i = 0; i < 4; i++)
for (var j = 0; j < 4; j++)
if (curShape & (0x8000 >> (i * 4 + j)))
if (y+i >= ROW_CNT || x+j < 0 || x+j >= 10 || gamePanel[y+i][x+j])
return true;
return false;
}
function draw() {
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, 200, 400);
ctx.rect(0, 0, 200, 400);
ctx.strokeStyle="blue";
ctx.stroke();
ctx.fillStyle = 'black';
for (var y = 0; y < gamePanel.length; y++) {
for (var x = 0; x < gamePanel[y].length; x++) {
if (gamePanel[y][x]) {
ctx.fillStyle = shapeColor[gamePanel[y][x]-1];
ctx.fillRect(x * 20, y * 20, 19, 19);
}
}
}
ctx.fillStyle = shapeColor[curShapeType];
for (var y = 0; y < 4; y++) {
for (var x = 0; x < 4; x++) {
if (curShape & (0x8000 >> (y * 4 + x))) {
ctx.fillRect((sPos.x+x) * 20, (sPos.y+y) * 20, 19, 19);
}
}
}
}
function moveShape(value) {
if ( !intersects(sPos.y, sPos.x+value)) {
sPos.x += value;
draw();
}
}
function dropShape() {
for (var y=sPos.y; y<ROW_CNT; y++) {
if ( !intersects(sPos.y+1, sPos.x)) {
sPos.y++;
draw();
} else {
break;
}
}
}
function rotateShape() {
curRotation = (curRotation + 1) % 4;;
curShape = shapes[curShapeType][curRotation]
draw();
}
function removeRow() {
var newRows = [];
var k = ROW_CNT;
var chkReCalc = false;
for (var y = ROW_CNT-1; y>=0; y--) {
for (var x = 0; x < COL_CNT; x++) {
if (!gamePanel[y][x]) {
newRows[--k] = gamePanel[y].slice();
break;
}
}
}
for (var y = 0; y < k; y++) {
newRows[y] = [];
completedRow++;
chkReCalc = true;
for (var x = 0; x < COL_CNT; x++)
newRows[y][x] = 0;
}
if (chkReCalc) {
step = Math.max(0.1, 0.6 - (0.5*completedRow));
}
return newRows;
}
function keydown(ev) {
var handled = false;
switch(ev.keyCode) {
case KEY.LEFT: moveShape(-1); handled = true; break;
case KEY.RIGHT: moveShape( 1); handled = true; break;
case KEY.UP: rotateShape(); handled = true; break;
case KEY.DOWN: dropShape(); handled = true; break;
case KEY.ESC: window.cancelAFrame(requestId);; handled = true; break;
}
if (handled) {
ev.preventDefault();
}
}
document.addEventListener('keydown', keydown, false);
</script>
</body>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment