Skip to content

Instantly share code, notes, and snippets.

@ojarjur
Created April 28, 2019 02:00
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 ojarjur/9768d4a98e09db9a80726218d9c19bee to your computer and use it in GitHub Desktop.
Save ojarjur/9768d4a98e09db9a80726218d9c19bee to your computer and use it in GitHub Desktop.
An implementation of Tetris in HTML that I implemented back in 2008
<!--
Copyright (C) 2008 Omar Jarjur. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<title>Tetris</title>
<script type="text/javascript">
var RowCount = 25;
var ColumnCount = 15;
/**
* Rotate a collection of locations in a 4x4 grid 90 degrees
* around the midpoint, producing a new collection as the result.
*/
function rotate(squares) {
var result = new Array();
for (var squareNumber in squares) {
var oldSquare = squares[squareNumber];
result[squareNumber] =
new Array((3-oldSquare[1]), oldSquare[0]);
}
return result;
}
/**
* Construct a new piece with the specified color and initial
* squares. Each returned piece has the member methods paint,
* paintPreview, rotate, moveLeft, moveRight, and moveDown.
*/
function Piece(color, blocks) {
var position = new Array(Math.floor(ColumnCount/2)-2, -3);
this.isStuck = function() {
return position[1] < 0;
};
this.paint = function(board) {
for (var squareNumber in blocks) {
var square = blocks[squareNumber];
var squareX = position[0] + square[0];
var squareY = position[1] + square[1];
if (squareY >= 0) {
board[squareX][squareY] = color;
}
}
};
this.paintPreview = function(preview) {
for (var columnNumber in preview) {
for (var rowNumber in preview[columnNumber]) {
preview[columnNumber][rowNumber] = "black";
}
}
for (var squareNumber in blocks) {
var square = blocks[squareNumber];
preview[square[0]][square[1]] = color;
}
};
this.rotate = function(board) {
var newBlocks = rotate(blocks);
for (var squareNumber in newBlocks) {
var square = newBlocks[squareNumber];
var squareX = position[0] + square[0];
var squareY = position[1] + square[1];
if (squareX < 0) {
return;
} else if (squareY >= 0) {
if ((squareY >= RowCount)
||
(squareX >= ColumnCount)
||
(board[squareX][squareY] != "black")) {
return;
}
}
}
blocks = newBlocks;
};
this.moveLeft = function(board) {
for (var squareNumber in blocks) {
var square = blocks[squareNumber];
var newX = position[0] + square[0] - 1;
var newY = position[1] + square[1];
if (newX < 0) {
return;
} else if ((newY >= 0) && (board[newX][newY] != "black")) {
return;
}
}
position[0] = position[0] - 1;
};
this.moveRight = function(board) {
for (var squareNumber in blocks) {
var square = blocks[squareNumber];
var newX = position[0] + square[0] + 1;
var newY = position[1] + square[1];
if (newX >= ColumnCount) {
return;
} else if ((newY >= 0) && (board[newX][newY] != "black")) {
return;
}
}
position[0] = position[0] + 1;
};
this.moveDown = function(board) {
for (var squareNumber in blocks) {
var square = blocks[squareNumber];
var newX = position[0] + square[0];
var newY = position[1] + square[1] + 1;
if (newY >= RowCount) {
return false;
} else if ((newY >= 0) && (board[newX][newY] != "black")) {
return false;
}
}
position[1] = position[1] + 1;
return true;
};
}
/**
* Get a new, random piece.
*/
function getRandomPiece() {
var type = Math.floor(Math.random()*7);
switch (type) {
case 0: // O
return new Piece("purple", [[1,1],[2,1],[1,2],[2,2]]);
case 1: // S
return new Piece("red", [[1,1],[2,1],[0,2],[1,2]]);
case 2: // Z
return new Piece("green", [[0,1],[1,1],[1,2],[2,2]]);
case 3: // L
return new Piece("orange", [[1,0],[1,1],[1,2],[2,2]]);
case 4: // J
return new Piece("blue", [[2,0],[2,1],[1,2],[2,2]]);
case 5: // T
return new Piece("white", [[0,1],[1,1],[2,1],[1,2]]);
default: // I
return new Piece("yellow", [[1,0],[1,1],[1,2],[1,3]]);
}
}
/**
* Create a new, empty playing board.
*/
function newBoard() {
var board = new Array();
for (var columnNumber = 0;
columnNumber < ColumnCount;
columnNumber++) {
var column = new Array();
for (var rowNumber = 0; rowNumber < RowCount; rowNumber++) {
column[rowNumber] = "black";
}
board[columnNumber] = column;
}
return board;
}
/**
* Copy a playing board.
*/
function copyBoard(oldBoard) {
var board = new Array();
for (var columnNumber in oldBoard) {
var oldColumn = oldBoard[columnNumber];
var column = new Array();
for (var rowNumber in oldColumn) {
column[rowNumber] = oldColumn[rowNumber];
}
board[columnNumber] = column;
}
return board;
}
function Game() {
var board = newBoard();
var piece = getRandomPiece();
var nextPiece = getRandomPiece();
var score = 0;
var cleared = 0;
var speed = 1;
this.getSpeed = function() { return speed; }
var augmentScore = function(amount) {
score += amount;
if (score >= (speed * 100)) {
speed++;
}
};
var printGridHTML = function(grid, rowCount, columnCount) {
var gridString = "";
for (var rowNumber = 0; rowNumber < rowCount; rowNumber++) {
gridString += "<tr>";
for (var columnNumber = 0;
columnNumber < columnCount;
columnNumber++) {
gridString += "<td bgcolor='";
gridString += grid[columnNumber][rowNumber];
gridString += "'>&nbsp;</td>";
}
gridString += "</tr>";
}
return gridString;
};
var clearRows = function() {
var targetRow = RowCount-1;
var clearedCount = 0;
for (var rowNumber = RowCount-1; rowNumber >= 0; rowNumber--) {
var isCleared = true;
for (var columnNumber = 0;
columnNumber < ColumnCount;
columnNumber++) {
value = board[columnNumber][rowNumber];
board[columnNumber][rowNumber] = "black";
board[columnNumber][targetRow] = value;
if (value == "black") {
isCleared = false;
}
}
if (isCleared) {
clearedCount++;
} else {
targetRow--;
}
}
cleared += clearedCount;
augmentScore(Math.pow(2,clearedCount));
};
this.display = function() {
var displayBoard = copyBoard(board);
piece.paint(displayBoard);
var boardString =
printGridHTML(displayBoard, RowCount, ColumnCount);
document.getElementById("board").innerHTML=boardString;
var previewGrid = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
nextPiece.paintPreview(previewGrid);
var previewString = printGridHTML(previewGrid,4,4);
document.getElementById("next").innerHTML=previewString;
document.getElementById("score").innerHTML = score;
document.getElementById("cleared").innerHTML = cleared;
document.getElementById("speed").innerHTML = speed;
};
this.rotate = function() { piece.rotate(board); };
this.moveLeft = function() { piece.moveLeft(board); };
this.moveRight = function() { piece.moveRight(board); };
this.moveDown = function() { piece.moveDown(board); };
this.tick = function() {
if (! piece.moveDown(board)) {
piece.paint(board);
if (piece.isStuck()) {
return false;
}
clearRows();
piece = nextPiece;
nextPiece = getRandomPiece();
}
this.display();
return true;
};
}
var game = new Game();
function handleKeyPressed(event) {
var handled = true;
switch(event.keyCode) {
case 37: // left
game.moveLeft();
break;
case 38: // up
game.rotate();
break;
case 39: // right
game.moveRight();
break;
case 40: // down
game.moveDown();
break;
default:
handled = false;
}
if (handled) {
game.display();
}
return (! handled);
}
</script>
</head>
<body onkeydown="handleKeyPressed(event)">
<style type="text/css">
td {
height: 20px;
width: 20px;
}
div.game {
position: relative;
}
div.sidepanel {
position: absolute;
top: 0px;
left: 375px;
}
</style>
<div class="game">
<table id="board", bgcolor="black", border="0">
</table>
</div>
<div class="sidepanel">
<p>Score:<br /><span id="score"></span></p>
<p>Cleared:<br /><span id="cleared"></span></p>
<p>Speed:<br /><span id="speed"></span></p>
<p>Next:</p>
<table id="next", bgcolor="black", border="0">
</table>
</div>
<script type="text/javascript">
function gameLoop() {
if (game.tick()) {
var delay = 1100 - (Math.min(10,game.getSpeed()) * 100);
setTimeout('gameLoop()', delay);
} else {
if (confirm("You loose. You suck!\n\nPlay again?")) {
game = new Game();
gameLoop();
}
}
}
gameLoop();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment