(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o=0;i--){ for(var j = 0;j0){ matrix[i][j] = matrix[i-1][j]; }else{ matrix[i][j] = 0 ; } } } }; /** Remove rows from game matrix by row numbers. */ var removeRows = function(matrix,rows){ for(var i in rows){ removeOneRow(matrix,rows[i]); } }; /** Check game data to determin wether the game is over */ var checkGameOver = function(matrix){ var firstRow = matrix[0]; for(var i = 0;i1){ return Math.pow(2,rows.length - 1)*100; } return 0; }; /** Calculate game score */ var calcScore = function(rows){ if (rows&&rows.length){ return rows.length*100; } return 0; }; /** Calculate time interval by level, the higher the level,the faster shape moves */ var calcIntervalByLevel = function(level){ return consts.DEFAULT_INTERVAL - (level-1)*60; }; // Default max scene size var defaults = { maxHeight:700, maxWidth:600 }; /** Tetris main object defination */ function Tetris(id){ this.id = id; this.init(); } Tetris.prototype = { init:function(options){ var cfg = this.config = utils.extend(options,defaults); this.interval = consts.DEFAULT_INTERVAL; views.init(this.id, cfg.maxWidth,cfg.maxHeight); canvas.init(views.scene,views.preview); this.matrix = initMatrix(consts.ROW_COUNT,consts.COLUMN_COUNT); this.reset(); this._initEvents(); this._fireShape(); }, //Reset game reset:function(){ this.running = false; this.isGameOver = false; this.level = 1; this.score = 0; this.startTime = new Date().getTime(); this.currentTime = this.startTime; this.prevTime = this.startTime; this.levelTime = this.startTime; clearMatrix(this.matrix); views.setLevel(this.level); views.setScore(this.score); views.setGameOver(this.isGameOver); this._draw(); }, //Start game start:function(){ this.running = true; window.requestAnimationFrame(utils.proxy(this._refresh,this)); }, //Pause game pause:function(){ this.running = false; this.currentTime = new Date().getTime(); this.prevTime = this.currentTime; }, //Game over gamveOver:function(){ }, // All key event handlers _keydownHandler:function(e){ var matrix = this.matrix; if(!e) { var e = window.event; } if (this.isGameOver||!this.shape){ return; } switch(e.keyCode){ case 37:{this.shape.goLeft(matrix);this._draw();} break; case 39:{this.shape.goRight(matrix);this._draw();} break; case 38:{this.shape.rotate(matrix);this._draw();} break; case 40:{this.shape.goDown(matrix);this._draw();} break; case 32:{this.shape.goBottom(matrix);this._update();} break; } }, // Restart game _restartHandler:function(){ this.reset(); this.start(); }, // Bind game events _initEvents:function(){ window.addEventListener('keydown',utils.proxy(this._keydownHandler,this),false); views.btnRestart.addEventListener('click',utils.proxy(this._restartHandler,this),false); }, // Fire a new random shape _fireShape:function(){ this.shape = this.preparedShape||shapes.randomShape(); this.preparedShape = shapes.randomShape(); this._draw(); canvas.drawPreviewShape(this.preparedShape); }, // Draw game data _draw:function(){ canvas.drawScene(); canvas.drawShape(this.shape); canvas.drawMatrix(this.matrix); }, // Refresh game canvas _refresh:function(){ if (!this.running){ return; } this.currentTime = new Date().getTime(); if (this.currentTime - this.prevTime > this.interval ){ this._update(); this.prevTime = this.currentTime; this._checkLevel(); } if (!this.isGameOver){ window.requestAnimationFrame(utils.proxy(this._refresh,this)); } }, // Update game data _update:function(){ if (this.shape.canDown(this.matrix)){ this.shape.goDown(this.matrix); }else{ this.shape.copyTo(this.matrix); this._check(); this._fireShape(); } this._draw(); this.isGameOver = checkGameOver(this.matrix); views.setGameOver(this.isGameOver); if (this.isGameOver){ views.setFinalScore(this.score); } }, // Check and update game data _check:function(){ var rows = checkFullRows(this.matrix); if (rows.length){ removeRows(this.matrix,rows); var score = calcScore(rows); var reward = calcRewards(rows); this.score += score + reward; views.setScore(this.score); views.setReward(reward); } }, // Check and update game level _checkLevel:function(){ var currentTime = new Date().getTime(); if (currentTime - this.levelTime > consts.LEVEL_INTERVAL){ this.level+=1; this.interval = calcIntervalByLevel(this.level); views.setLevel(this.level); this.levelTime = currentTime; } } } window.Tetris = Tetris; },{"./canvas.js":1,"./consts.js":2,"./shapes.js":4,"./utils.js":5,"./views.js":6}],4:[function(require,module,exports){ var consts = require('./consts.js'); var COLORS = consts.COLORS; var COLUMN_COUNT = consts.COLUMN_COUNT; /** Defined all shapes used in Tetris game. You can add more shapes if you wish. */ function ShapeL(){ var state1 = [ [1, 0], [1, 0], [1, 1] ]; var state2 = [ [0, 0, 1], [1, 1, 1] ]; var state3 = [ [1, 1], [0, 1], [0, 1] ]; var state4 = [ [1, 1, 1], [1, 0, 0] ]; this.states = [ state1, state2, state3, state4 ]; this.x = 4; this.y = -3; this.flag = 'L'; } function ShapeLR() { var state1 = [ [0, 1], [0, 1], [1, 1] ]; var state2 = [ [1, 1, 1], [0, 0, 1] ]; var state3 = [ [1, 1], [1, 0], [1, 0] ]; var state4 = [ [1, 0, 0], [1, 1, 1] ]; this.states = [ state1, state2, state3, state4 ]; this.x = 4; this.y = -3; this.flag = 'LR'; } function ShapeO() { var state1 = [ [1, 1], [1, 1] ]; this.states = [ state1 ]; this.x = 4; this.y = -2; this.flag = 'O'; } function ShapeI() { var state1 = [ [1], [1], [1], [1] ]; var state2 = [ [1,1,1,1] ]; this.states = [ state1, state2 ]; this.x = 5; this.y = -4; this.flag = 'I'; } function ShapeT() { var state1 = [ [1, 1, 1], [0, 1, 0] ]; var state2 = [ [1, 0], [1, 1], [1, 0] ]; var state3 = [ [0, 1, 0], [1, 1, 1] ]; var state4 = [ [0, 1], [1, 1], [0, 1] ]; this.states = [ state1, state2, state3, state4 ]; this.x = 4; this.y = -2; this.flag = 'T'; } function ShapeZ() { var state1 = [ [1, 1, 0], [0, 1, 1] ]; var state2 = [ [0, 1], [1, 1], [1, 0] ]; this.states = [ state1, state2 ]; this.x = 4; this.y = -2; this.flag = 'Z'; } function ShapeZR() { var state1 = [ [0, 1, 1], [1, 1, 0] ]; var state2 = [ [1, 0], [1, 1], [0, 1] ]; this.states = [ state1, state2 ]; this.x = 4; this.y = -2; this.flag = 'ZR'; } /** Is shape can move @param shape: tetris shape @param matrix: game matrix @param action: 'left','right','down','rotate' */ var isShapeCanMove = function(shape,matrix,action){ var rows = matrix.length; var cols = matrix[0].length; var isBoxCanMove = function(box){ var x = shape.x + box.x; var y = shape.y + box.y; if (y<0){ return true; } if (action === 'left'){ x -= 1; return x>=0 && x=0 && x= COLUMN_COUNT){ this.x -= right - COLUMN_COUNT + 1; } } }, //Caculate the max column of the shape getColumnCount:function(){ var mtx = this.matrix(); var colCount = 0; for(var i=0;i=0&&x=0&&ydh){ size.height = Math.min(maxH,dh); size.width = Math.min(size.height /2 + SIDE_WIDTH,maxW); }else{ size.width = Math.min(maxW,dw); size.height = Math.min(maxH,dh); } return size; }; /** Layout game elements */ var layoutView = function(container,maxW,maxH){ var size = getContainerSize(maxW,maxH); var st = container.style; st.height = size.height + 'px'; st.width = size.width + 'px'; st.marginTop = (-(size.height/2)) + 'px'; st.marginLeft = (-(size.width/2)) + 'px'; //layout scene scene.height = size.height; scene.width = scene.height / 2; var sideW = size.width - scene.width; side.style.width = sideW+ 'px'; if (sideW< SIDE_WIDTH ){ info.style.width = side.style.width; } preview.width = 80; preview.height = 80; gameOver.style.width = scene.width +'px'; } /** Main tetris game view */ var tetrisView = { init:function(id, maxW,maxH){ this.container = $(id); this.scene = scene; this.preview = preview; this.btnRestart = btnRestart; layoutView(this.container,maxW,maxH); this.scene.focus(); rewardInfo.addEventListener('animationEnd',function(e){ rewardInfo.className = 'invisible'; }); }, // Update the score setScore:function(scoreNumber){ score.innerHTML = scoreNumber; }, // Update the finnal score setFinalScore:function(scoreNumber){ finalScore.innerHTML = scoreNumber; }, // Update the level setLevel:function(levelNumber){ level.innerHTML = levelNumber; }, // Update the extra reward score setReward:function(rewardScore){ if (rewardScore>0){ reward.innerHTML = rewardScore; rewardInfo.className = 'fadeOutUp animated'; }else{ rewardInfo.className = 'invisible'; } }, // Set game over view setGameOver:function(isGameOver){ gameOver.style.display = isGameOver?'block':'none'; } }; module.exports = tetrisView; },{"./consts.js":2,"./utils.js":5}]},{},[3]);