//游戏类
Freewind.Tetris = function(){
Freewind.Base.apply(this, arguments);
this._nIndex = this._getIndex();
this._map = null;
this._nextMap = null;
this._nMaxRow = 20;
this._nMaxCol = 10;
this._nCurRow = 0;
this._nCurCol = 4;
this._nCurNum = 0;
this._nCurShape = 0;
this._nNextRow = 1;
this._nNextCol = 1;
this._nNextNum = 0;
this._nNextShape = 0;
this._curBoxs = [];
this._nextBoxs = [];
this._Keys = {};
this._gameState = "ready";
this._nNum = 7; // or 15
this._Boxs = [ ["060102","601020"],
["606101"],
["600601","600110","060110","600610"],
["666001","610110"],
["606106","600111"],
["601011","060116","666010","610601"],
["601016","660601","606110","060111"],
[""],
["60","01"],
["6010","0601"],
["0610","6006","6001","0110"],
["60060110"],
["66610601","60611011","06011611","66601610"],
["66606110","61060111","60161011","66060116"],
["66060111","60611610"] ]
this._nLines = 0;
this._nScore = 0;
this._nSpeed = 0;
this._nLevel = 0;
this._nInitSpeed = 0;
this._nInitLevel = 0;
this._nTimerID = 0;
this._nDelay = 1000;
this._nInterval = 95;
this._init();
};
Freewind.Tetris.prototype = {
_getIndex : function(){
if(this.DOM.nTetrisCount){
return ++this.DOM.nTetrisCount;
}else{
this.DOM.nTetrisCount = 1;
return this.DOM.nTetrisCount;
}
},
_init : function(){
this.Tetris = this._createDiv("Tetris");
var html = [];
html.push("<div class='FW_Te_Left'>");
html.push(" <div id='FW_GameArea-1' class='FW_GameArea'></div>");
html.push("</div>");
html.push("<div class='FW_Te_Right'>");
html.push(" <div id='FW_NextBox-1' class='FW_NextBox'></div>");
html.push(" <ul class='FW_Prototype'>");
html.push(" <li>行数:</li>");
html.push(" <li><input type='text' id='FW_Lines-1' name='FW_Lines-1' value='0' readonly = 'readonly' /></li>");
html.push(" <li>分数:</li>");
html.push(" <li><input type='text' id='FW_Score-1' name='FW_Score-1' value='0' readonly = 'readonly' /></li>");
html.push(" <li>速度:</li>");
html.push(" <li><input type='text' id='FW_Speed-1' name='FW_Speed-1' value='0' readonly = 'readonly' /></li>");
html.push(" <li>难度:</li>");
html.push(" <li><input type='text' id='FW_Level-1' name='FW_Level-1' value='0' readonly = 'readonly' /></li>");
html.push(" </ul>");
html.push("</div>");
var str = html.join("");
str = str.replace(/-1/g, this._nIndex);
this.Tetris.innerHTML = str;
this._parent.appendChild(this.Tetris);
var i = this._nIndex;
this._GameArea = this._$("FW_GameArea" + i);
this._NextBox = this._$("FW_NextBox" + i);
this._Lines = this._$("FW_Lines" + i);
this._Score = this._$("FW_Score" + i);
this._Speed = this._$("FW_Speed" + i);
this._Level = this._$("FW_Level" + i);
this._createMap();
this._setDefaultKey();
},
_setDefaultKey : function(){
this._Keys = this._getDefaultKey();
},
_getDefaultKey : function(){
return {
left: 37,
right: 39,
down: 40,
cshape: 32
};
},
_createMap : function(){
var html = [];
html.push("<table width='100%' cellpadding='0' onselectstart='return false;' cellspacing='0' id='FW_Table" + this._nIndex + "' >");
for(var i=0; i<this._nMaxRow; i++){
html.push("<tr>");
for(var j=0; j<this._nMaxCol; j++){
html.push("<td class='FW_HideBox'> </td>");
}
html.push("</tr>");
}
html.push("</table>");
this._GameArea.innerHTML = html.join("");
this._map = this._$("FW_Table" + this._nIndex);
var next = [];
next.push("<table width='100%' cellpadding='0' onselectstart='return false;' cellspacing='0' id='FW_Table2" + this._nIndex + "' >");
for(var i=0; i<4; i++){
next.push("<tr>");
for(var j=0; j<4; j++){
next.push("<td class='FW_HideBox2'> </td>");
}
next.push("</tr>");
}
next.push("</table>");
this._NextBox.innerHTML = next.join("");
this._nextMap = this._$("FW_Table2" + this._nIndex);
},
_getRandom : function(nMin, nMax){
return parseInt(Math.random()*(nMax-nMin)) + nMin;
},
_clearTimer : function(){
if(this._nTimerID > 0){
clearTimeout(this._nTimerID);
this._nTimerID = 0;
}
},
_resetData : function(){
this._clearTimer();
this._nLines = 0;
this._nScore = 0;
this._nSpeed = 0;
this._nLevel = 0;
this._gameState = "start";
for(var i=0; i<this._nMaxRow; i++){
for(var j=0; j<this._nMaxCol; j++){
this._map.rows.cells[j].className = "FW_HideBox";
this._map.rows.cells[j].isHave = false;
}
}
for(var i=0; i<4; i++){
for(var j=0; j<4; j++){
this._nextMap.rows.cells[j].className = "FW_HideBox2";
this._nextMap.rows.cells[j].isHave = false;
}
}
},
_parseBox : function(row, col, num, shape){
var boxs = this._Boxs[num][shape] + "00";
var len = boxs.length;
var ret = [];
for(var i=0; i<len; i+=2){
r = parseInt(boxs.charAt(i));
c = parseInt(boxs.charAt(i+1));
if(r >= 6) r -= 7;
if(c >= 6) c -= 7;
r += row;
c += col;
ret.push(r);
ret.push(c);
}
return ret;
},
_createBox : function(){
this._nCurRow = 1;
this._nCurCol = 4;
this._nCurNum = this._nNextNum;
this._nCurShape = this._nNextShape;
this._curBoxs = this._parseBox(this._nCurRow, this._nCurCol, this._nCurNum, this._nCurShape);
var n = this._getRandom(0, this._nNum);
var s = this._getRandom(0, 4);
if(s >= this._Boxs[n].length){
if(this._Boxs[n].length == 1){
s = 0;
}else{
s -= 2;
}
}
this._nNextNum = n;
this._nNextShape = s;
this._nextBoxs = this._parseBox(this._nNextRow, this._nNextCol, n, s);
},
_setBoxStyle : function(obj, row, col, clsname){
if(row >= 0 && col >= 0 && row < obj.rows.length && col < obj.rows[row].cells.length){
obj.rows[row].cells[col].className = clsname;
}
},
_showBoxs : function(isGameArea, isShow){
//class name, obj;
var map, clsname, boxs;
clsname = "FW_Box"; //show
if(isGameArea){
map = this._map;
if(!isShow) clsname = "FW_HideBox";
boxs = this._curBoxs;
}else{
map = this._nextMap;
if(!isShow) clsname = "FW_HideBox2";
boxs = this._nextBoxs;
}
for(var i=0; i<boxs.length; i+=2){
this._setBoxStyle(map, boxs, boxs[i+1], clsname);
}
},
_showCurBox : function(){
this._showBoxs(true, true);
},
_showNextBox : function(){
this._showBoxs(false, true);
},
_setInitLevel : function(){
var n = 5;
for(var i=this._nInitLevel; i>0; i--){
r = this._nMaxRow - i;
for(var j=0; j<n; j++){
c = this._getRandom(0, this._nMaxCol);
this._map.rows[r].cells[c].isHave = true;
this._map.rows[r].cells[c].className = "FW_Box";
}
}
},
_start : function(){
this._resetData();
this._createBox();
this._createBox();
this._showCurBox();
this._showNextBox();
this._showScore();
if(this._nInitLevel > 0){
this._setInitLevel();
}
this._moveDown(false);
},
_pause : function(){
if(this._gameState == "start"){
this._gameState = "pause";
}else if(this._gameState == "pause"){
this._gameState = "start";
}
},
_stop : function(){
this._clearTimer();
},
_gameOver : function(){
alert("game over!");
},
_move : function(dir){
var rr = 0, cc = 0;
var isFound = false;
switch(dir.toLowerCase()){
case "left":
cc = -1;
break;
case "right":
cc = 1;
break;
case "down":
rr = 1;
break;
}
for(var i=0; i<this._curBoxs.length; i+=2){
r = this._curBoxs + rr;
c = this._curBoxs[i+1] + cc;
if(r >= 0){
if(r >= this._nMaxRow || c < 0 || c >= this._nMaxCol || this._map.rows[r].cells[c].isHave){
isFound = true;
break;
}
}
}
if(!isFound){
this._showBoxs(true, false); //hide;
for(var i=0; i<this._curBoxs.length; i+=2){
this._curBoxs += rr;
this._curBoxs[i+1] += cc;
}
this._nCurRow += rr;
this._nCurCol += cc;
this._showBoxs(true, true);
}
return !isFound;
},
_setCurBox : function(){
for(var i=0; i<this._curBoxs.length; i+=2){
r = this._curBoxs;
c = this._curBoxs[i+1];
if(r < 0 || this._map.rows[r].cells[c].isHave == true){
this._gameState = "over";
return;
}
this._map.rows[r].cells[c].isHave = true;
}
},
_deleteRow : function(n){
for(var i=n; i>0; i--){
for(var j=0; j<this._nMaxCol; j++){
if(this._map.rows.cells[j].isHave != this._map.rows[i-1].cells[j].isHave){
this._map.rows.cells[j].isHave = this._map.rows[i-1].cells[j].isHave;
this._map.rows.cells[j].className = this._map.rows[i-1].cells[j].className;
}
}
}
},
_showScore : function(){
this._Lines.value = this._nLines;
this._Score.value = this._nScore;
this._Speed.value = this._nSpeed;
if(this._nInitSpeed > 0) this._Speed.value += " + " + this._nInitSpeed;
this._Level.value = this._nLevel;
if(this._nInitLevel > 0) this._Level.value += " + " + this._nInitLevel;
},
_checkRow : function(){
var rs = [];
for(var i=0; i<this._curBoxs.length; i+=2){
isFound = false;
r = this._curBoxs;
for(var j=0; j<rs.length; j++){
if(rs[j] == r){
isFound = true;
break;
}
}
if(!isFound){
rs.push(r);
}
}
//
rs.sort();
//document.title = rs;
var nCount = 0;
for(var i=0; i<rs.length; i++){
isFound = true;
r = rs;
for(var c=0; c<this._nMaxCol; c++){
if(this._map.rows[r].cells[c].isHave != true){
isFound = false;
break;
}
}
if(isFound){
nCount ++;
this._deleteRow(r);
}
}
if(nCount > 0){
this._nLines += nCount;
this._nScore += (Math.pow(2, nCount)-1) * 100;
this._nSpeed = parseInt(this._nScore / 10000) ;
this._nLevel = parseInt(this._nScore / 10000) ;
if(this._nSpeed >= 10) this._nSpeed = 10;
if(this._nLevel >= 10) this._nLevel = 10;
this._showScore();
}
},
_moveDown : function(isMove){
if(this._gameState == "start"){
var isMoved = true;
this._clearTimer();
if(isMove){
isMoved = this._move("down");
}
if(!isMoved){ //不能移动
this._setCurBox();
if(this._gameState == "over"){
this._gameOver();
return;
}
//check row
this._checkRow();
//new
this._showBoxs(false, false); //hide next
this._createBox();
this._showBoxs(true, true);
this._showBoxs(false, true);
}
}
//
var self = this;
this._nTimerID = setTimeout(function(){self._moveDown(true);}, self._nDelay - (self._nSpeed + self._nInitSpeed) * self._nInterval);
},
_changeShape : function(){
var s = this._nCurShape + 1;
var n = this._nCurNum;
if(s >3 ) s = 0;
if(s >= this._Boxs[n].length){
if(this._Boxs[n].length == 1){
s = 0;
}else{
s -= 2;
}
}
var tmp = this._parseBox(this._nCurRow, this._nCurCol, n, s);
var isFound = false;
for(var i=0; i<tmp.length; i+=2){
r = tmp;
c = tmp[i+1];
if(r >= 0){
if(r >= this._nMaxRow || c < 0 || c >= this._nMaxCol || this._map.rows[r].cells[c].isHave){
isFound = true;
break;
}
}
}
if(!isFound){
this._showBoxs(true, false); //hide;
this._curBoxs = tmp;
this._nCurShape = s;
this._showBoxs(true, true);
}
return !isFound;
},
_quickDown : function(){
var add = 0, isFound = false;
for(var i=this._nCurRow+1; !isFound && i<=this._nMaxRow; i++){
add = i - this._nCurRow;
for(var j=0; j<this._curBoxs.length; j+=2){
r = add + this._curBoxs[j];
c = this._curBoxs[j+1];
if(r >= this._nMaxRow || this._map.rows[r].cells[c].isHave){
isFound = true;
break;
}
}
}
add -= 1;
if(add > 0){
this._showBoxs(true, false);
this._nCurRow += add;
for(var i=0; i<this._curBoxs.length; i+=2){
this._curBoxs += add;
}
this._showBoxs(true, true);
this._moveDown(true);
}
},
onKeyPress : function(keyCode){
if(!(this._gameState == "start" || keyCode == 113 || keyCode == 118)) return;
switch(keyCode){
case 113: //F2
this._start();
break;
case 118: //F7
this._pause();
break;
case this._Keys.left: //37 Left
this._move("left");
break;
case this._Keys.right: //39: //Right
this._move("right");
break;
case this._Keys.cshape: //32: //Space
this._changeShape();
break;
case this._Keys.down: //40: //quick down
this._quickDown();
break;
}
},
onCommand : function(sCommand){
switch(sCommand){
case "start":
this._start();
break;
case "pause":
this._pause();
break;
case "stop":
this._stop();
break;
}
},
setMode : function(sMode){
if(sMode == "adv"){
this._nNum = 15;
}else{
this._nNum = 7;
}
},
getMode : function(){
if(this._nNum == 15){
return "adv";
}else{
return "normal";
}
},
setNum : function(n){
if(n < 0 && n >15) n = 1;
this._nNum = n;
},
getNum : function(n){
return this._nNum;
},
setInit : function(nSpeed, nLevel){
if(nSpeed < 0 || nSpeed > 10) nSpeed = 0;
if(nLevel < 0 || nLevel > 10) nLevel = 0;
this._nInitSpeed = nSpeed;
this._nInitLevel = nLevel;
},
getInit : function(){
return {speed: this._nInitSpeed, level: this._nInitLevel};
},
getDefaultKey : function(){
return this._getDefaultKey();
},
getKey : function(){
return this._Keys;
},
setKey : function(left, right, down, changeShape){
this._Keys.left = left;
this._Keys.right = right;
this._Keys.down = down;
this._Keys.cshape = changeShape;
}
};