Version compl�te: jsB@nk » Game » Tetris » JsTetris: Free JavaScript Awesome jeu en ligne Tetris
URL: https://www.javascriptbank.com/jstetris-free-awesome-javascript-online-tetris-game.html
Peut-?tre que Tetris n'est pas ?trange ? quiconque en raison de son famousness, est n? en 1984 (m?me ?ge avec Mario), Tetris est un des plus anciens jeux Et maintenant, Tetris a ?t? lib?r? au cours des millions d'exemplaires 125, Tetris pr?sente sur toutes les plates-formes de jeu: PC, console, de l'environnement bas? sur le Web, mobile, etc
Jeux Tetris est ?galement disponible sur ACC @ nk tr?s t?t depuis le d?but avec des jeux Tetris JavaScript:
JavaScript Advance tetris
? Tetris JavaScript Simple
? tetris simple JavaScript
jeux Facebook, D'autres jeux sur JavaScript ACC @ nk si vous voulez ou ? jouer:
? Top 50 Most Addictive et jeux populaires mini Facebook
? 12 Awesome et Creative Jeux JavaScript vous devriez essayer
? Navigateur Croix Noire jeu Snake
Version compl�te: jsB@nk » Game » Tetris » JsTetris: Free JavaScript Awesome jeu en ligne Tetris
URL: https://www.javascriptbank.com/jstetris-free-awesome-javascript-online-tetris-game.html
<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>
<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>
<!--/* 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>