»
Tiếng AnhTiếng PhápTiếng Việt

In - JsTetris: Xếp gạch cực cool với JavaScript - JavaScriptBank.com

Phiên bản đầy đủ: jsB@nk » Trò chơi » Xếp gạch » JsTetris: Xếp gạch cực cool với JavaScript
URL: https://www.javascriptbank.com/jstetris-free-awesome-javascript-online-tetris-game.html

JsTetris: Xếp gạch cực cool với JavaScript © JavaScriptBank.comCó lẽ chúng ta không lạ gì với trò chơi xếp gạch (Tetris) này sự quá nổi tiếng của nó, ra đời cùng thời đại với Mario (tính đến thời điểm này là trên 25 năm) và cũng rất nổi tiếng như Mario. Tetris có mặt lần đầu tiên là vào năm 1984, hiện tại có hơn 125 triệu bản đã được phát hành trên tất cả các hệ máy chơi game.Tetris - một trò chơi trí tuệ cực phổ biến - cũng đã có mặt trên jsB@nk từ những ngày đầu mới thành lập, với các hiệu ứng như: - JavaScript Xếp gạch cao cấp - JavaScript Xếp gạch - JavaScript Trò chơi xếp gạchHôm nay jsB@nk muốn giới thiệu với bạn thêm hiệu đoạn mã JavaScript khác để tạo trò chơi Tetris cực kì độc đáo trên trang web.

Phiên bản đầy đủ: jsB@nk » Trò chơi » Xếp gạch » JsTetris: Xếp gạch cực cool với JavaScript
URL: https://www.javascriptbank.com/jstetris-free-awesome-javascript-online-tetris-game.html



CSS
<style type="text/css">/*     This script downloaded from www.JavaScriptBank.com     Come to view and download over 2000+ free javascript at www.JavaScriptBank.com*/html, body { height: 100%; margin: 0; padding: 0; }body {    background: #E1D4C0;}body, table {    font: 11px tahoma;    color: #826C55;    text-align: center;}/*** tetris 168,308 ***/#tetris {    position: relative;    width: 300px;    height: 310px;    border: 1px solid #BAA68E;    background: #ffffff;    margin: 0 auto;}/*** left ***/#tetris .left {    background: #F5EDE3;    position: absolute;    width: 130px;    height: 100%;    left: 0px;    top: 0px;}#tetris .left h1 {    font-size: 11px;    text-align: center;    margin-top: 10px;    margin-bottom: 10px;}#tetris .left h1 a {    color: #3366CC;    text-decoration: none;}#tetris .left h1 a:hover {    color: #FF6600;    text-decoration: none;}/* menu */#tetris .left .menu {    text-align: center;}#tetris .left input {    font: 10px tahoma;    color: #333333;    text-transform: uppercase;    background: #EAE0D1;}#tetris .left .menu input {    width: 90px;}/* keyboard */#tetris .left .keyboard {    position: absolute;    top: 163px;    left: 32px;    width: 85px;    height: 55px;    overflow: visible;    display: none;}#tetris .left .keyboard input {    font: 11px tahoma;    width: 25px;    height: 25px;    padding-bottom: 2px;    text-transform: none;}* html #tetris .left .keyboard input {    padding-left: 1px;}#tetris .left .keyboard .up {    position: absolute;    left: 30px;    top: 0px;    width: 30px;    height: 30px;}#tetris .left .keyboard .up input {    font: 15px tahoma;    padding-top: 3px;}#tetris .left .keyboard .down {    position: absolute;    left: 30px;    top: 30px;    width: 30px;    height: 30px;}#tetris .left .keyboard .down input {    font: 14px tahoma;}#tetris .left .keyboard .left {    position: absolute;    left: 0px;    top: 30px;    width: 30px;    height: 30px;}#tetris .left .keyboard .right {    position: absolute;    left: 60px;    top: 30px;    width: 30px;    height: 30px;}/* game over */#tetris-gameover {    position: absolute;    width: 100%;    top: 50%;    text-align: center;    font-weight: bold;    display: none;}/* next puzzle */#tetris-nextpuzzle {    position: absolute;    top: 49%;    left: 35%;    background: #ffffff;    overflow: visible;    display: none;}/* stats */#tetris .left .stats {    position: absolute;    left: 35px;    bottom: 10px;}#tetris .stats td { padding-bottom: 1px; }#tetris .stats .level { text-align: right; padding-right: 10px; }#tetris-stats-level { font-weight: bold; }#tetris .stats .time { text-align: right; padding-right: 10px; }#tetris-stats-time { font-weight: bold; }#tetris .stats .apm { text-align: right; padding-right: 10px; }#tetris-stats-apm { font-weight: bold; }#tetris .stats .lines { text-align: right; padding-right: 10px; }#tetris-stats-lines { font-weight: bold; }#tetris .stats .score { text-align: right; padding-right: 10px; }#tetris-stats-score { font-weight: bold; }/*** area ***/#tetris-area {    background: #FFFFFF;    position: absolute;    width: 168px;    height: 308px;    left: 131px;    top: 1px;    overflow: hidden;}#tetris .block0,#tetris .block1,#tetris .block2,#tetris .block3,#tetris .block4,#tetris .block5,#tetris .block6 {    position: absolute;    width: 13px;    height: 13px;    border: 0.5px solid #ffffff;    /* with margin 0.5px there were problems with offsetLeft and offsetTop */}#tetris .block0,#tetris .block1 {    background: #6699FF;}#tetris .block2,#tetris .block3 {    background: #FF6600;}#tetris .block4 {    background: #FFAC1C;}#tetris .block5 {    background: #BAA68E;}#tetris .block6 {    background: #FF0000;}/*** window ***/#tetris .window {    background: #EFE8DE;    position: absolute;    width: 168px;    height: 308px;    left: 131px;    top: 1px;    z-index: 5;    display: none;}#tetris .window .top {    position: relative;    background: #EAE0D1;    color: #666666;    font: 10px tahoma;    letter-spacing: +1px;    height: 20px;    line-height: 20px;    vertical-align: middle;    border-bottom: 1px solid #ffffff;    text-indent: 10px;}#tetris .window .top .close {    position: absolute;    background: #EAE0D1;    font: 11px verdana;    font-weight: bold;    right: 0px;    top: 0px;    height: 20px;    line-height: 19px;    text-indent: 7px;    width: 21px;    border-left: 1px solid #ffffff;    cursor: pointer;}#tetris .window .top .close:hover {    background: #EFE8DE;}#tetris .window .content {    font: 10px tahoma;    margin: 10px;}#tetris .window .content table {    font: 10px tahoma;}</style>


JavaScript
<script type="text/javascript">// Created by: Cezary Tomczak | http://gosu.pl// Licensed under: BSD// This script downloaded from www.JavaScriptBank.com/* * PROJECT:  JsTetris * VERSION:  1.1.0 * LICENSE:  BSD (revised) * AUTHOR:   (c) 2004 Cezary Tomczak * LINK:     http://gosu.pl/dhtml/JsTetris.html * * This script can be used freely as long as all * copyright messages are intact. *//** * Tetris Game * Initializes the buttons automatically, no additional actions required * * Score: * 1) puzzle speed = 80+700/level * 2) if puzzles created in current level >= 10+level*2 then increase level * 3) after puzzle falling score is increased by 1000*level*linesRemoved * 4) each down action increases score by 5+level * * API: * * public - method can be called outside of the object * event - method is used as event, "this" refers to html object, "self" refers to javascript object * * class Tetris * ------------ * public event void start() * public event void reset() * public event void gameOver() * public event void up() * public event void down() * public event void left() * public event void right() * public event void space() * * class Window * ------------ * event void activate() * event void close() * public bool isActive() * * class Keyboard * -------------- * public void set(int key, function func) * event void event(object e) * * class Stats * ----------- * public void start() * public void stop() * public void reset() * public event void incTime() * public void setScore(int i) * public void setLevel(int i) * public void setLines(int i) * public void setPuzzles(int i) * public void setActions(int i) * public int getScore() * public int getLevel() * public int getLines() * public int getPuzzles() * public int getActions() * * class Area * ---------- * public Constructor(int unit, int x, int y, string id) * public void destroy() * public int removeFullLines() * public bool isLineFull(int y) * public void removeLine(int y) * public mixed getBlock(int y, int x) * public void addElement(htmlObject el) * * class Puzzle * ------------ * public Constructor(object area) * public void reset() * public bool isRunning() * public bool isStopped() * public int getX() * public int getY() * public bool mayPlace() * public void place() * public void destroy() * private array createEmptyPuzzle(int y, int x) * event void fallDown() * public event void forceMoveDown() * public void stop() * public bool mayRotate() * public void rotate() * public bool mayMoveDown() * public void moveDown() * public bool mayMoveLeft() * public void moveLeft() * public bool mayMoveRight() * public void moveRight() * * class Highscores * ---------------- * public Constructor(maxscores) * public void load() * public void save() * public bool mayAdd(int score) * public void add(string name, int score) * public array getScores() * public string toHtml() * private void sort() * * class Cookie * ------------ * public string get(string name) * public void set(string name, string value, int seconds, string path, string domain, bool secure) * public void del(string name) * * TODO: * document.getElementById("tetris-nextpuzzle") cache ? * */function Tetris() {    var self = this;    this.stats = new Stats();    this.puzzle = null;    this.area = null;    this.unit  = 20; // unit = x pixels    this.areaX = 20; // area width = x units    this.areaY = 20; // area height = y units    this.highscores = new Highscores(10);    /**     * @return void     * @access public event     */    this.start = function() {        self.reset();        self.stats.start();        document.getElementById("tetris-nextpuzzle").style.display = "block";        self.area = new Area(self.unit, self.areaX, self.areaY, "tetris-area");        self.puzzle = new Puzzle(self, self.area);        if (self.puzzle.mayPlace()) {            self.puzzle.place();        } else {            self.gameOver();        }    }    /**     * @return void     * @access public event     */    this.reset = function() {        if (self.puzzle) {            self.puzzle.destroy();            self.puzzle = null;        }        if (self.area) {            self.area.destroy();            self.area = null;        }        document.getElementById("tetris-gameover").style.display = "none";        document.getElementById("tetris-nextpuzzle").style.display = "none";        self.stats.reset();    }    /**     * End game.     * Stop stats, ...     * @return void     * @access public event     */    this.gameOver = function() {        self.stats.stop();        self.puzzle.stop();        document.getElementById("tetris-nextpuzzle").style.display = "none";        document.getElementById("tetris-gameover").style.display = "block";        if (this.highscores.mayAdd(this.stats.getScore())) {            var name = prompt("Game Over !\nEnter your name:", "");            if (name && name.trim().length) {                this.highscores.add(name, this.stats.getScore());            }        }    }    /**     * @return void     * @access public event     */    this.up = function() {        if (self.puzzle && self.puzzle.isRunning() && !self.puzzle.isStopped()) {            if (self.puzzle.mayRotate()) {                self.puzzle.rotate();                self.stats.setActions(self.stats.getActions() + 1);            }        }    }    /**     * @return void     * @access public event     */    this.down = function() {        if (self.puzzle && self.puzzle.isRunning() && !self.puzzle.isStopped()) {            if (self.puzzle.mayMoveDown()) {                self.stats.setScore(self.stats.getScore() + 5 + self.stats.getLevel());                self.puzzle.moveDown();                self.stats.setActions(self.stats.getActions() + 1);            }        }    }    /**     * @return void     * @access public event     */    this.left = function() {        if (self.puzzle && self.puzzle.isRunning() && !self.puzzle.isStopped()) {            if (self.puzzle.mayMoveLeft()) {                self.puzzle.moveLeft();                self.stats.setActions(self.stats.getActions() + 1);            }        }    }    /**     * @return void     * @access public event     */    this.right = function() {        if (self.puzzle && self.puzzle.isRunning() && !self.puzzle.isStopped()) {            if (self.puzzle.mayMoveRight()) {                self.puzzle.moveRight();                self.stats.setActions(self.stats.getActions() + 1);            }        }    }    /**     * @return void     * @access public event     */    this.space = function() {        if (self.puzzle && self.puzzle.isRunning() && !self.puzzle.isStopped()) {            self.puzzle.stop();            self.puzzle.forceMoveDown();        }    }    // windows    var helpwindow = new Window("tetris-help");    var highscores = new Window("tetris-highscores");    // game menu    document.getElementById("tetris-menu-start").onclick = function() { helpwindow.close(); highscores.close(); self.start(); this.blur(); }    document.getElementById("tetris-menu-reset").onclick = function() { helpwindow.close(); highscores.close(); self.reset(); this.blur(); }    // help    document.getElementById("tetris-menu-help").onclick = function() { highscores.close(); helpwindow.activate(); this.blur(); }    document.getElementById("tetris-help-close").onclick = helpwindow.close;    // highscores    document.getElementById("tetris-menu-highscores").onclick = function() {        helpwindow.close();        document.getElementById("tetris-highscores-content").innerHTML = self.highscores.toHtml();        highscores.activate();        this.blur();    }    document.getElementById("tetris-highscores-close").onclick = highscores.close;    // keyboard - buttons    document.getElementById("tetris-keyboard-up").onclick = function() { self.up(); this.blur(); }    document.getElementById("tetris-keyboard-down").onclick = function() { self.down(); this.blur(); }    document.getElementById("tetris-keyboard-left").onclick = function () { self.left(); this.blur(); }    document.getElementById("tetris-keyboard-right").onclick = function() { self.right(); this.blur(); }    // keyboard    var keyboard = new Keyboard();    keyboard.set(keyboard.n, this.start);    keyboard.set(keyboard.r, this.reset);    keyboard.set(keyboard.up, this.up);    keyboard.set(keyboard.down, this.down);    keyboard.set(keyboard.left, this.left);    keyboard.set(keyboard.right, this.right);    keyboard.set(keyboard.space, this.space);    document.onkeydown = keyboard.event;    /**     * Window replaces game area, for example help window     * @param string id     */    function Window(id) {        this.id = id;        this.el = document.getElementById(this.id);        var self = this;        /**         * Activate or deactivate a window - update html         * @return void         * @access event         */        this.activate = function() {            self.el.style.display = (self.el.style.display == "block" ? "none" : "block");        }        /**         * Close window - update html         * @return void         * @access event         */        this.close = function() {            self.el.style.display = "none";        }        /**         * @return bool         * @access public         */        this.isActive = function() {            return (self.el.style.display == "block");        }    }    /**     * Assigning functions to keyboard events     * When key is pressed, searching in a table if any function has been assigned to this key, execute the function.     */    function Keyboard() {        this.up = 38;        this.down = 40;        this.left = 37;        this.right = 39;        this.n = 78;        this.r = 82;        this.space = 32;        this.f12 = 123;        this.escape = 27;        this.keys = [];        this.funcs = [];        var self = this;        /**         * @param int key         * @param function func         * @return void         * @access public         */        this.set = function(key, func) {            this.keys.push(key);            this.funcs.push(func);        }        /**         * @param object e         * @return void         * @access event         */        this.event = function(e) {            if (!e) { e = window.event; }            for (var i = 0; i < self.keys.length; i++) {                if (e.keyCode == self.keys[i]) {                    self.funcs[i]();                }            }        }    }    /**     * Live game statistics     * Updating html     */    function Stats() {        this.level;        this.time;        this.apm;        this.lines;        this.score;        this.puzzles; // number of puzzles created on current level        this.actions;        this.el = {            "level": document.getElementById("tetris-stats-level"),            "time":  document.getElementById("tetris-stats-time"),            "apm":   document.getElementById("tetris-stats-apm"),            "lines": document.getElementById("tetris-stats-lines"),            "score": document.getElementById("tetris-stats-score")        }        this.timerId = null;        var self = this;        /**         * Start counting statistics, reset stats, turn on the timer         * @return void         * @access public         */        this.start = function() {            this.reset();            this.timerId = setInterval(this.incTime, 1000);        }        /**         * Stop counting statistics, turn off the timer         * @return void         * @access public         */        this.stop = function() {            if (this.timerId) {                clearInterval(this.timerId);            }        }        /**         * Reset statistics - update html         * @return void         * @access public         */        this.reset = function() {            this.stop();            this.level = 1;            this.time  = 0;            this.apm   = 0;            this.lines = 0;            this.score = 0;            this.puzzles = 0;            this.actions = 0;            this.el.level.innerHTML = this.level;            this.el.time.innerHTML  = this.time;            this.el.apm.innerHTML   = this.apm;            this.el.lines.innerHTML = this.lines;            this.el.score.innerHTML = this.score;        }        /**         * Increase time, update apm - update html         * This func is called by setInterval()         * @return void         * @access public event         */        this.incTime = function() {            self.time++;            self.el.time.innerHTML = self.time;            self.apm = parseInt((self.actions / self.time) * 60);            self.el.apm.innerHTML = self.apm;        }        /**         * Set score - update html         * @param int i         * @return void         * @access public         */        this.setScore = function(i) {            this.score = i;            this.el.score.innerHTML = this.score;        }        /**         * Set level - update html         * @param int i         * @return void         * @access public         */        this.setLevel = function(i) {            this.level = i;            this.el.level.innerHTML = this.level;        }        /**         * Set lines - update html         * @param int i         * @return void         * @access public         */        this.setLines = function(i) {            this.lines = i;            this.el.lines.innerHTML = this.lines;        }        /**         * Number of puzzles created on current level         * @param int i         * @return void         * @access public         */        this.setPuzzles = function(i) {            this.puzzles = i;        }        /**         * @param int i         * @return void         * @access public         */        this.setActions = function(i) {            this.actions = i;        }        /**         * @return int         * @access public         */        this.getScore = function() {            return this.score;        }        /**         * @return int         * @access public         */        this.getLevel = function() {            return this.level;        }        /**         * @return int         * @access public         */        this.getLines = function() {            return this.lines;        }        /**         * Number of puzzles created on current level         * @return int         * @access public         */        this.getPuzzles = function() {            return this.puzzles;        }        /**         * @return int         * @access public         */        this.getActions = function() {            return this.actions;        }    }    /**     * Area consists of blocks (2 dimensional board).     * Block contains "0" (if empty) or Html Object.     * @param int x     * @param int y     * @param string id     */    function Area(unit, x, y, id) {        this.unit = unit;        this.x = x;        this.y = y;        this.el = document.getElementById(id);        this.board = [];        // create 2-dimensional board        for (var y = 0; y < this.y; y++) {            this.board.push(new Array());            for (var x = 0; x < this.x; x++) {                this.board[y].push(0);            }        }        /**         * Removing html elements from area.         * @return void         * @access public         */        this.destroy = function() {            for (var y = 0; y < this.board.length; y++) {                for (var x = 0; x < this.board[y].length; x++) {                    if (this.board[y][x]) {                        this.el.removeChild(this.board[y][x]);                        this.board[y][x] = 0;                    }                }            }        }        /**         * Searching for full lines.         * Must go from the bottom of area to the top.         * Returns the number of lines removed - needed for Stats.score.         * @see isLineFull() removeLine()         * @return void         * @access public         */        this.removeFullLines = function() {            var lines = 0;            for (var y = this.y - 1; y > 0; y--) {                if (this.isLineFull(y)) {                    this.removeLine(y);                    lines++;                    y++;                }            }            return lines;        }        /**         * @param int y         * @return bool         * @access public         */        this.isLineFull = function(y) {            for (var x = 0; x < this.x; x++) {                if (!this.board[y][x]) { return false; }            }            return true;        }        /**         * Remove given line         * Remove html objects         * All lines that are above given line move down by 1 unit         * @param int y         * @return void         * @access public         */        this.removeLine = function(y) {            for (var x = 0; x < this.x; x++) {                this.el.removeChild(this.board[y][x]);                this.board[y][x] = 0;            }            y--;            for (; y > 0; y--) {                for (var x = 0; x < this.x; x++) {                    if (this.board[y][x]) {                        var el = this.board[y][x];                        el.style.top = el.offsetTop + this.unit + "px";                        this.board[y+1][x] = el;                        this.board[y][x] = 0;                    }                }            }        }        /**         * @param int y         * @param int x         * @return mixed 0 or Html Object         * @access public         */        this.getBlock = function(y, x) {            if (y < 0) { return 0; }            if (y < this.y && x < this.x) {                return this.board[y][x];            } else {                throw "Area.getBlock("+y+", "+x+") failed";            }        }        /**         * Add Html Element to the area.         * Find (x,y) position using offsetTop and offsetLeft         * @param object el         * @return void         * @access public         */        this.addElement = function(el) {            var x = parseInt(el.offsetLeft / this.unit);            var y = parseInt(el.offsetTop / this.unit);            if (y >= 0 && y < this.y && x >= 0 && x < this.x) {                this.board[y][x] = el;            } else {                // not always an error ..            }        }    }    /**     * Puzzle consists of blocks.     * Each puzzle after rotating 4 times, returns to its primitive position.     */    function Puzzle(tetris, area) {        var self = this;        this.tetris = tetris;        this.area = area;        // timeout ids        this.fallDownID = null;        this.forceMoveDownID = null;        this.type = null; // 0..6        this.nextType = null; // next puzzle        this.position = null; // 0..3        this.speed = null;        this.running = null;        this.stopped = null;        this.board = []; // filled with html elements after placing on area        this.elements = [];        this.nextElements = []; // next board elements        // (x,y) position of the puzzle (top-left)        this.x = null;        this.y = null;        // width & height must be the same        this.puzzles = [            [                [0,0,1],                [1,1,1],                [0,0,0]            ],            [                [1,0,0],                [1,1,1],                [0,0,0]            ],            [                [0,1,1],                [1,1,0],                [0,0,0]            ],            [                [1,1,0],                [0,1,1],                [0,0,0]            ],            [                [0,1,0],                [1,1,1],                [0,0,0]            ],            [                [1,1],                [1,1]            ],            [                [0,0,0,0],                [1,1,1,1],                [0,0,0,0],                [0,0,0,0]            ]        ];        /**         * Reset puzzle. It does not destroy html elements in this.board.         * @return void         * @access public         */        this.reset = function() {            if (this.fallDownID) {                clearTimeout(this.fallDownID);            }            if (this.forceMoveDownID) {                clearTimeout(this.forceMoveDownID);            }            this.type = this.nextType;            this.nextType = random(this.puzzles.length);            this.position = 0;            this.speed = 80 + (700 / this.tetris.stats.getLevel());            this.running = false;            this.stopped = false;            this.board = [];            this.elements = [];            for (var i = 0; i < this.nextElements.length; i++) {                document.getElementById("tetris-nextpuzzle").removeChild(this.nextElements[i]);            }            this.nextElements = [];            this.x = null;            this.y = null;        }        this.nextType = random(this.puzzles.length);        this.reset();        /**         * Check whether puzzle is running.         * @return bool         * @access public         */        this.isRunning = function() {            return this.running;        }        /**         * Check whether puzzle has been stopped by user. It happens when user clicks         * "down" when puzzle is already at the bottom of area. The puzzle may still         * be running with event fallDown(). When puzzle is stopped, no actions will be         * performed when user press a key.         * @return bool         * @access public         */        this.isStopped = function() {            return this.stopped;        }        /**         * Get X position of puzzle (top-left)         * @return int         * @access public         */        this.getX = function() {            return this.x;        }        /**         * Get Y position of puzzle (top-left)         * @return int         * @access public         */        this.getY = function() {            return this.y;        }        /**         * Check whether new puzzle may be placed on the area.         * Find (x,y) in area where beginning of the puzzle will be placed.         * Check if first puzzle line (checking from the bottom) can be placed on the area.         * @return bool         * @access public         */        this.mayPlace = function() {            var puzzle = this.puzzles[this.type];            var areaStartX = parseInt((this.area.x - puzzle[0].length) / 2);            var areaStartY = 1;            var lineFound = false;            var lines = 0;            for (var y = puzzle.length - 1; y >= 0; y--) {                for (var x = 0; x < puzzle[y].length; x++) {                    if (puzzle[y][x]) {                        lineFound = true;                        if (this.area.getBlock(areaStartY, areaStartX + x)) { return false; }                    }                }                if (lineFound) {                    lines++;                }                if (areaStartY - lines < 0) {                    break;                }            }            return true;        }        /**         * Create empty board, create blocks in area - html objects, update puzzle board.         * Check puzzles on current level, increase level if needed.         * @return void         * @access public         */        this.place = function() {            // stats            this.tetris.stats.setPuzzles(this.tetris.stats.getPuzzles() + 1);            if (this.tetris.stats.getPuzzles() >= (10 + this.tetris.stats.getLevel() * 2)) {    this.tetris.stats.setLevel(this.tetris.stats.getLevel() + 1);    this.tetris.stats.setPuzzles(0);    }            // init            var puzzle = this.puzzles[this.type];            var areaStartX = parseInt((this.area.x - puzzle[0].length) / 2);            var areaStartY = 1;            var lineFound = false;            var lines = 0;            this.x = areaStartX;            this.y = 1;            this.board = this.createEmptyPuzzle(puzzle.length, puzzle[0].length);            // create puzzle            for (var y = puzzle.length - 1; y >= 0; y--) {                for (var x = 0; x < puzzle[y].length; x++) {                    if (puzzle[y][x]) {                        lineFound = true;                        var el = document.createElement("div");                        el.className = "block" + this.type;                        el.style.left = (areaStartX + x) * this.area.unit + "px";                        el.style.top = (areaStartY - lines) * this.area.unit + "px";                        this.area.el.appendChild(el);                        this.board[y][x] = el;                        this.elements.push(el);                    }                }                if (lines) {                    this.y--;                }                if (lineFound) {                    lines++;                }            }            this.running = true;            this.fallDownID = setTimeout(this.fallDown, this.speed);            // next puzzle            var nextPuzzle = this.puzzles[this.nextType];            for (var y = 0; y < nextPuzzle.length; y++) {                for (var x = 0; x < nextPuzzle[y].length; x++) {                    if (nextPuzzle[y][x]) {                        var el = document.createElement("div");                        el.className = "block" + this.nextType;                        el.style.left = (x * this.area.unit) + "px";                        el.style.top = (y * this.area.unit) + "px";                        document.getElementById("tetris-nextpuzzle").appendChild(el);                        this.nextElements.push(el);                    }                }            }        }        /**         * Remove puzzle from the area.         * Clean some other stuff, see reset()         * @return void         * @access public         */        this.destroy = function() {            for (var i = 0; i < this.elements.length; i++) {                this.area.el.removeChild(this.elements[i]);            }            this.elements = [];            this.board = [];            this.reset();        }        /**         * @param int y         * @param int x         * @return array         * @access private         */        this.createEmptyPuzzle = function(y, x) {            var puzzle = [];            for (var y2 = 0; y2 < y; y2++) {                puzzle.push(new Array());                for (var x2 = 0; x2 < x; x2++) {                    puzzle[y2].push(0);                }            }            return puzzle;        }        /**         * Puzzle fall from the top to the bottom.         * After placing a puzzle, this event will be called as long as the puzzle is running.         * @see place() stop()         * @return void         * @access event         */        this.fallDown = function() {            if (self.isRunning()) {                if (self.mayMoveDown()) {                    self.moveDown();                    self.fallDownID = setTimeout(self.fallDown, self.speed);                } else {                    // move blocks into area board                    for (var i = 0; i < self.elements.length; i++) {                        self.area.addElement(self.elements[i]);                    }                    // stats                    var lines = self.area.removeFullLines();                    if (lines) {                        self.tetris.stats.setLines(self.tetris.stats.getLines() + lines);                        self.tetris.stats.setScore(self.tetris.stats.getScore() + (1000 * self.tetris.stats.getLevel() * lines));                    }                    // reset puzzle                    self.reset();                    if (self.mayPlace()) {                        self.place();                    } else {                        self.tetris.gameOver();                    }                }            }        }        /**         * After clicking "space" the puzzle is forced to move down, no user action is performed after         * this event is called. this.running must be set to false. This func is similiar to fallDown()         * Also update score & actions - like Tetris.down()         * @see fallDown()         * @return void         * @access public event         */        this.forceMoveDown = function() {            if (!self.isRunning() && !self.isStopped()) {                if (self.mayMoveDown()) {                    // stats: score, actions                    self.tetris.stats.setScore(self.tetris.stats.getScore() + 5 + self.tetris.stats.getLevel());                    self.tetris.stats.setActions(self.tetris.stats.getActions() + 1);                    self.moveDown();                    self.forceMoveDownID = setTimeout(self.forceMoveDown, 30);                } else {                    // move blocks into area board                    for (var i = 0; i < self.elements.length; i++) {                        self.area.addElement(self.elements[i]);                    }                    // stats: lines                    var lines = self.area.removeFullLines();                    if (lines) {                        self.tetris.stats.setLines(self.tetris.stats.getLines() + lines);                        self.tetris.stats.setScore(self.tetris.stats.getScore() + (1000 * self.tetris.stats.getLevel() * lines));                    }                    // reset puzzle                    self.reset();                    if (self.mayPlace()) {                        self.place();                    } else {                        self.tetris.gameOver();                    }                }            }        }        /**         * Stop the puzzle falling         * @return void         * @access public         */        this.stop = function() {            this.running = false;        }        /**         * Check whether puzzle may be rotated.         * Check down, left, right, rotate         * @return bool         * @access public         */        this.mayRotate = function() {            for (var y = 0; y < this.board.length; y++) {                for (var x = 0; x < this.board[y].length; x++) {                    if (this.board[y][x]) {                        var newY = this.getY() + this.board.length - 1 - x;                        var newX = this.getX() + y;                        if (newY >= this.area.y) { return false; }                        if (newX < 0) { return false; }                        if (newX >= this.area.x) { return false; }                        if (this.area.getBlock(newY, newX)) { return false; }                    }                }            }            return true;        }        /**         * Rotate the puzzle to the left.         * @return void         * @access public         */        this.rotate = function() {            var puzzle = this.createEmptyPuzzle(this.board.length, this.board[0].length);            for (var y = 0; y < this.board.length; y++) {                for (var x = 0; x < this.board[y].length; x++) {                    if (this.board[y][x]) {                        var newY = puzzle.length - 1 - x;                        var newX = y;                        var el = this.board[y][x];                        var moveY = newY - y;                        var moveX = newX - x;                        el.style.left = el.offsetLeft + (moveX * this.area.unit) + "px";                        el.style.top = el.offsetTop + (moveY * this.area.unit) + "px";                        puzzle[newY][newX] = el;                    }                }            }            this.board = puzzle;        }        /**         * Check whether puzzle may be moved down.         * - is any other puzzle on the way ?         * - is it end of the area ?         * If false, then true is assigned to variable this.stopped - no user actions will be performed to this puzzle,         * so this func should be used carefully, only in Tetris.down() and Tetris.puzzle.fallDown()         * @return bool         * @access public         */        this.mayMoveDown = function() {            for (var y = 0; y < this.board.length; y++) {                for (var x = 0; x < this.board[y].length; x++) {                    if (this.board[y][x]) {                        if (this.getY() + y + 1 >= this.area.y) { this.stopped = true; return false; }                        if (this.area.getBlock(this.getY() + y + 1, this.getX() + x)) { this.stopped = true; return false; }                    }                }            }            return true;        }        /**         * Move the puzzle down by 1 unit.         * @return void         * @access public         */        this.moveDown = function() {            for (var i = 0; i < this.elements.length; i++) {                this.elements[i].style.top = this.elements[i].offsetTop + this.area.unit + "px";            }            this.y++;        }        /**         * Check whether puzzle may be moved left.         * - is any other puzzle on the way ?         * - is the end of the area         * @return bool         * @access public         */        this.mayMoveLeft = function() {            for (var y = 0; y < this.board.length; y++) {                for (var x = 0; x < this.board[y].length; x++) {                    if (this.board[y][x]) {                        if (this.getX() + x - 1 < 0) { return false; }                        if (this.area.getBlock(this.getY() + y, this.getX() + x - 1)) { return false; }                    }                }            }            return true;        }        /**         * Move the puzzle left by 1 unit         * @return void         * @access public         */        this.moveLeft = function() {            for (var i = 0; i < this.elements.length; i++) {                this.elements[i].style.left = this.elements[i].offsetLeft - this.area.unit + "px";            }            this.x--;        }        /**         * Check whether puzle may be moved right.         * - is any other puzzle on the way ?         * - is the end of the area         * @return bool         * @access public         */        this.mayMoveRight = function() {            for (var y = 0; y < this.board.length; y++) {                for (var x = 0; x < this.board[y].length; x++) {                    if (this.board[y][x]) {                        if (this.getX() + x + 1 >= this.area.x) { return false; }                        if (this.area.getBlock(this.getY() + y, this.getX() + x + 1)) { return false; }                    }                }            }            return true;        }        /**         * Move the puzzle right by 1 unit.         * @return void         * @access public         */        this.moveRight = function() {            for (var i = 0; i < this.elements.length; i++) {                this.elements[i].style.left = this.elements[i].offsetLeft + this.area.unit + "px";            }            this.x++;        }    }    /**     * Generates random number that is >= 0 and < i     * @return int     * @access private     */    function random(i) {        return Math.floor(Math.random() * i);    }    /**     * Store highscores in cookie.     */    function Highscores(maxscores) {        this.maxscores = maxscores;        this.scores = [];        /**         * Load scores from cookie.         * Note: it is automatically called when creating new instance of object Highscores.         * @return void         * @access public         */        this.load = function() {            var cookie = new Cookie();            var s = cookie.get("tetris-highscores");            this.scores = [];            if (s.length) {                var scores = s.split("|");                for (var i = 0; i < scores.length; ++i) {                    var a = scores[i].split(":");                    this.scores.push(new Score(a[0], Number(a[1])));                }            }        }        /**         * Save scores to cookie.         * Note: it is automatically called after adding new score.         * @return void         * @access public         */        this.save = function() {            var cookie = new Cookie();            var a = [];            for (var i = 0; i < this.scores.length; ++i) {                a.push(this.scores[i].name+":"+this.scores[i].score);            }            var s = a.join("|");            cookie.set("tetris-highscores", s, 3600*24*1000);        }        /**         * Is the score high enough to be able to add ?         * @return bool         * @access public         */        this.mayAdd = function(score) {            if (this.scores.length < this.maxscores) { return true; }            for (var i = this.scores.length - 1; i >= 0; --i) {                if (this.scores[i].score < score) { return true; }            }            return false;        }        /**         * @param string name         * @param int score         * @return void         * @access public         */        this.add = function(name, score) {            name = name.replace(/[;=:|]/g, "?");            name = name.replace(/</g, "<").replace(/>/g, ">");            if (this.scores.length < this.maxscores) {                this.scores.push(new Score(name, score));            } else {                for (var i = this.scores.length - 1; i >= 0; --i) {                    if (this.scores[i].score < score) {                        this.scores.removeByIndex(i);                        this.scores.push(new Score(name, score));                        break;                    }                }            }            this.sort();            this.save();        }        /**         * Get array of scores.         * @return array [Score, Score, ..]         * @access public         */        this.getScores = function() {            return this.scores;        }        /**         * All highscores returned in html friendly format.         * @return string         * @access public         */        this.toHtml = function() {            var s = '<table cellspacing="0" cellpadding="2"><tr><th></th><th>Name</th><th>Score</th></tr>';            for (var i = 0; i < this.scores.length; ++i) {                s += '<tr><td>?.</td><td>?</td><td>?</td></tr>'.format(i+1, this.scores[i].name, this.scores[i].score);            }            s += '</table>';            return s;        }        /**         * Sort table with scores.         * @return void         * @access private         */        this.sort = function() {            var scores = this.scores;            var len = scores.length;            this.scores = [];            for (var i = 0; i < len; ++i) {                var el = null, index = null;                for (var j = 0; j < scores.length; ++j) {                    if (!el || (scores[j].score > el.score)) {                        el = scores[j];                        index = j;                    }                }                scores.removeByIndex(index);                this.scores.push(el);            }        }        /* Simple score object. */        function Score(name, score) {            this.name = name;            this.score = score;        }        this.load();    }    /**     * Managing cookies.     */    function Cookie() {        /**         * @param string name         * @return string         * @access public         */        this.get = function(name) {            var cookies = document.cookie.split(";");            for (var i = 0; i < cookies.length; ++i) {                var a = cookies[i].split("=");                if (a.length == 2) {                    a[0] = a[0].trim();                    a[1] = a[1].trim();                    if (a[0] == name) {                        return unescape(a[1]);                    }                }            }            return "";        };        /**         * @param string name         * @param string value (do not use special chars like ";" "=")         * @param int seconds         * @param string path         * @param string domain         * @param bool secure         * @return void         * @access public         */        this.set = function(name, value, seconds, path, domain, secure) {            var cookie = (name + "=" + escape(value));            if (seconds) {                var date = new Date(new Date().getTime()+seconds*1000);                cookie += ("; expires="+date.toGMTString());            }            cookie += (path    ? "; path="+path : "");            cookie += (domain  ? "; domain="+domain : "");            cookie += (secure  ? "; secure" : "");            document.cookie = cookie;        };        /**         * @param name         * @return void         * @access public         */        this.del = function(name) {            document.cookie = name + "=; expires=Thu, 01-Jan-70 00:00:01 GMT";        };    }}if (!String.prototype.trim) {    String.prototype.trim = function() {        return this.replace(/^\s*|\s*$/g, "");    };}if (!Array.prototype.removeByIndex) {    Array.prototype.removeByIndex = function(index) {        this.splice(index, 1);    };}if (!String.prototype.format) {    String.prototype.format = function() {        if (!arguments.length) { throw "String.format() failed, no arguments passed, this = "+this; }        var tokens = this.split("?");        if (arguments.length != (tokens.length - 1)) { throw "String.format() failed, tokens != arguments, this = "+this; }        var s = tokens[0];        for (var i = 0; i < arguments.length; ++i) {            s += (arguments[i] + tokens[i + 1]);        }        return s;    };}</script>


HTML
<!--/*     This script downloaded from www.JavaScriptBank.com     Come to view and download over 2000+ free javascript at www.JavaScriptBank.com*/--><table cellspacing="0" cellpadding="0" width="100%" height="100%"><tr><td valign="middle"><div id="tetris">  <div class="left">    <h1>JsTetris 1.1.0</h1>    <div class="menu">      <div><input type="button" value="New Game" id="tetris-menu-start" /></div>      <div><input type="button" value="Reset" id="tetris-menu-reset" /></div>      <div><input type="button" value="Help" id="tetris-menu-help" /></div>      <div><input type="button" value="Highscores" id="tetris-menu-highscores" /></div>    </div>    <div class="keyboard">      <div class="up"><input type="button" value="^" id="tetris-keyboard-up" /></div>      <div class="down"><input type="button" value="v" id="tetris-keyboard-down" /></div>      <div class="left"><input type="button" value="<" id="tetris-keyboard-left" /></div>      <div class="right"><input type="button" value=">" id="tetris-keyboard-right" /></div>    </div>    <div id="tetris-nextpuzzle"></div>    <div id="tetris-gameover">Game Over</div>    <div class="stats">      <table cellspacing="0" cellpadding="0">      <tr>        <td class="level">Level:</td>        <td><span id="tetris-stats-level">1</span></td>      </tr>      <tr>        <td class="score">Score:</td>        <td><span id="tetris-stats-score">0</span></td>      </tr>      <tr>        <td class="lines">Lines:</td>        <td><span id="tetris-stats-lines">0</span></td>      </tr>      <tr>        <td class="apm">APM:</td>        <td><span id="tetris-stats-apm">0</span></td>      </tr>      <tr>        <td class="time">Time:</td>        <td><span id="tetris-stats-time">0</span></td>      </tr>      </table>    </div>  </div>  <div id="tetris-area"></div>  <div id="tetris-help" class="window">    <div class="top">      Help <span id="tetris-help-close" class="close">x</span>    </div>    <div class="content">      <b>Controllers:</b> <br />      up - rotate <br />      down - move down <br />      left - move left <br />      right - move right <br />      space - fall to the bottom <br />      n - new game <br />      r - reset <br />      <br />      <b>Rules:</b> <br />      1) Puzzle speed = 80+700/level miliseconds, the smaller value the faster puzzle falls <br />      2) If puzzles created in current level >= 10+level*2 then increase level <br />      3) After puzzle falling score is increased by 1000*level*linesRemoved <br />      4) Each "down" action increases score by 5+level (pressing space counts as multiple down actions)    </div>  </div>  <div id="tetris-highscores" class="window">      <div class="top">        Highscores <span id="tetris-highscores-close" class="close">x</span>      </div>      <div class="content">        <div id="tetris-highscores-content"></div>        <br />        Note: these scores are kept in cookies, they are only visible to your computer, other players that visit this page see their own scores.      </div>  </div></div></td></tr></table><script type="text/javascript">  var tetris = new Tetris();  tetris.unit = 14;  tetris.areaX = 12;  tetris.areaY = 22;</script>