* @author 流浪大法师
* @time 2015-7-13 上午2:59:16
* @email liuliangsir@gmail.com
* @descript 面向对象实现俄罗斯方块
*/
function Tetris(rows,cols,width){
//实现俄罗斯方块界面的生成
if(!rows || !cols){rows = 20;cols = 10;}
if(!width){width = (document.body.scrollWidth * 0.7 / cols) > (document.body.scrollHeight * 0.95 / rows) ? (document.body.scrollHeight * 0.95 / rows) : (document.body.scrollWidth * 0.7 / cols);}
var colors = ["#66ccff","#0000ff","#ffff00","#cc00ff","#ff0000","#00ff00","#ff6600","#becfea"];//颜色的种类
var types = [4,9,16,25];//表示大砖可以由4、6、8小砖构成,考虑旋转的话,将大砖可以由4、9、16、25小砖构成
var typesDisplay = {};//表示4、9、16,25小砖构成大砖的形式
var borderSize = 1;//每个砖块的边界
var myBlockContainer = null;//俄罗斯方块大容器
var myBlockContainerPositionInfo = {};//大砖的位置信息
var myAllBlockContainerPositionInfo = [];//记录所有大砖块的位置信息
var zIndexMax = 99999;//便于absolute元素布局
var zIndexMin = 1000;//便于分层
//保存Tetris的实例对象,便于实例中方法之间调用
var tetrisInstanceObj = this;
this.divArray = [];
this.absoluteDivContainerArray = [];
this.downAbsoluteDivRankArray = [];
this.minRowNum = 1000;
//实现统计每种类型大砖块出现的数目
//初始化typesDisplay
types.forEach(function(item,index,array) {
tetrisInstanceObj["type"+item] = 0;
if(item == 4){
typesDisplay["type"+item] = [
[[[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3]],4]
];
}else if(item == 9){
typesDisplay["type"+item] = [
[[[0,1,4,5],[1,3,4,6],[0,1,4,5],[1,3,4,6]],5],
[[[1,2,3,4],[1,4,5,8],[4,5,6,7],[0,3,4,7]],0],
[[[3,4,5,7],[1,3,4,7],[1,3,4,5],[1,4,5,7]],2],
];
}else if(item == 16){
typesDisplay["type"+item] = [
[[[0,1,2,3],[0,4,8,12],[0,1,2,3],[0,4,8,12]],6]
];
}else if(item == 25){
typesDisplay["type"+item] = [
[[[12,13,14,17],[11,12,17,22],[7,10,11,12],[2,7,12,13]],1],
[[[10,11,12,17],[2,7,11,12],[7,12,13,14],[12,13,17,22]],3],
];
}
});
this.createTetrisUserInterface = function(){
//js动态生成样式
tetrisInstanceObj.myCreateStyleSheet();
myBlockContainer = tetrisInstanceObj.createOneTetrisBlock();
var myBlock = null;
var str = "";
document.body.appendChild(myBlockContainer);
for(var i = 0; i < rows; i++){
for(var j = 0; j < cols; j++){
myBlock = tetrisInstanceObj.createOneTetrisBlock((i+"")+(j+""));
tetrisInstanceObj.divArray.push([true,-1]);
str += myBlock.outerHTML;
myBlock = null;
}
}
myBlockContainer.innerHTML = str;
str = null;
};
this.createOneTetrisBlock = function(id,issetPositionAbsolute,colorIndex,isHidden,typeIndex){
var block = document.createElement("div");
if(!issetPositionAbsolute){
block.id = "myBlock" + (id ? id : "Container");
block.className = id ? "myBlocks" : "myBlockContainer";
}else{
var idIsInt = typeof id === "number";
block.id = "myAbsoluteBlockContainer" + (idIsInt ? id+"-"+(++tetrisInstanceObj["type"+id]) : id);
if(idIsInt){
block.className = "transparent rotate0 myBlockContainer"+id+" myBlockContainer"+id+"-"+tetrisInstanceObj["type"+id]+"-"+typeIndex;
}else{
block.className = "myBlocks myAbsolute "+"color"+colorIndex+" topLeft"+id.replace(new RegExp("-.-"),"-")+(isHidden ? " myHidden" : "");
}
}
return block;
};
this.createOneBigTetrisBlock = function(bigTetrisBlockNum){
//if(!bigTetrisBlockNum) bigTetrisBlockNum = types[types.length - 1];
var length = typesDisplay["type"+bigTetrisBlockNum].length;
//随机产生在bigTetrisBlockNum块的形式种类
var num = Math.floor(Math.random()*(length));
var array = typesDisplay["type"+bigTetrisBlockNum][num];
var myBlockContainerByNum = tetrisInstanceObj.createOneTetrisBlock(bigTetrisBlockNum,true,-1,false,num);
myBlockContainerPositionInfo = Utils.setTopAndLeft(array[0][0],bigTetrisBlockNum,cols,rows);
//myAllBlockContainerPositionInfo.push(myBlockContainerPositionInfo);
myBlockContainerByNum.style.cssText = "top:"+(myBlockContainerPositionInfo["currentY"] * (borderSize * 2 + width))+"px; left:"+(myBlockContainerPositionInfo["currentX"] * (borderSize * 2 + width))+"px;";
myBlockContainer.appendChild(myBlockContainerByNum);
tetrisInstanceObj.absoluteDivContainerArray.push([myBlockContainerByNum,true]);
var obj = null;
//for(var j = 0; j < array[0].length; j++){
for(var i = 0; i < bigTetrisBlockNum; i++){
obj = tetrisInstanceObj.createOneTetrisBlock(bigTetrisBlockNum+"-"+tetrisInstanceObj["type"+bigTetrisBlockNum]+"-"+i,true,array[1] + 1,(array[0][0].indexOf(i) === -1));
myBlockContainerByNum.appendChild(obj);
obj = null;
}
/*Utils.sleep(2000);*/
//}
return myBlockContainerByNum;
};
this.rotate = function(div,typeNum,num){
//在typeNum下的砖块种类很多,所以通过获取index来确定砖块的种类
var index = parseInt(div.className[div.className.length - 1]);
var array = typesDisplay["type"+typeNum][index][0];
var preClildrenBlockStatusByNum = (num === 0 ?array[array.length - 1] : array[num - 1]);
var currentClildrenBlockStatusByNum = array[num];
var arr = Utils.findSameItemDeleteInTwoArray(preClildrenBlockStatusByNum,currentClildrenBlockStatusByNum);
arr.forEach(function(item,index){
item.forEach(function(value) {
div.childNodes.item(value).className = (!index)? div.childNodes.item(value).className + " myHidden" : div.childNodes.item(value).className.replace("myHidden","");
});
});
};
this.myCreateStyleSheet = function(){
var str = ".myBlocks {height : "+width+"px;width : "+width+"px;background-color : "+"white"/*colors[colors.length - 1]*/+";display: inline-block;border:"+borderSize+"px solid "+colors[colors.length - 1]+";} .myBlockContainer {/*height: "+((width + 2 * borderSize) * rows)+"px;*/width:"+((width + 2 * borderSize) * cols)+"px;background-color: "+colors[colors.length - 1]+";display: block;margin-left: auto;margin-right: auto;font-size: 0;overflow: hidden;position: relative;} .myHidden{display:none;} .myAbsolute{position:absolute;}";
types.forEach(function(item,index,array) {
str+=(".myBlockContainer"+item+" {position: absolute;height :"+((width + 2 * borderSize) * Math.sqrt(item))+"px;width: "+((width + 2 * borderSize) * Math.sqrt(item))+"px; font-size:0;opacity: 1;background-color: "+colors[colors.length - 1]+";top: 0;}");
//实现item下小砖块实现absolute距离父容器的top以及left
for(var i = 0; i < item; i++){
str+=".topLeft"+item+"-"+i+" {top: "+( parseInt(( i / Math.sqrt(item)) )*(width + borderSize * 2) )+"px;left: "+(i%(Math.sqrt(item)))*(width + borderSize * 2)+"px;}";
}
});
//将颜色弄成样式
colors.forEach(function(item,index,array) {
str+=".color"+(index+1)+" {background-color:"+item+";} html{height:100%} body{height:100%;overflow:hidden;} .maxZIndex{z-index:"+zIndexMax+";} .minZIndex{z-index:"+zIndexMin+"} .transparent{background-color:transparent;}";
});
Utils.addClass(str,"myStyleSheet");
};
this.getMyBlockContainer = function(){
return myBlockContainer;
};
this.getMyBlockContainerPositionInfo = function(){
return myBlockContainerPositionInfo;
};
this.setMyBlockContainerPositionInfo = function(positionInfo){
myBlockContainerPositionInfo = positionInfo;
};
this.getMyAllBlockContainerPositionInfo = function(){
return myAllBlockContainerPositionInfo;
};
this.getTypesDisplay = function(){
return typesDisplay;
};
this.getWidth = function(){
//包含border边界
return width + borderSize * 2;
};
this.getTypes = function(){
return types;
};
this.getRows = function(){
return rows;
};
this.getCols = function(){
return cols;
};
}
//考虑到定时器过多的话,会带来性能的损失,因此采用一个定时器
window.onload = function(){
var tetris = new Tetris();
tetris.createTetrisUserInterface();
var myEvent = new Event();
var hasNext = false,objectElementIsRight = false;
var args = [tetris,myEvent,hasNext,objectElementIsRight];
var timer = new Timer(1000);
myEvent.setTetris(tetris);
myEvent.setPositionInfo(tetris.getMyBlockContainerPositionInfo());
timer.schedule(function(args){
var tetris = args[0],myEvent = args[1],hasNext = args[2],typeIndex = Math.floor(Math.random()*(tetris.getTypes().length)),isRight = args[3];
var div = null,array = [],positionInfo = null,width = tetris.getWidth(),flag = true,length = 0;
if(!hasNext){
div = tetris.createOneBigTetrisBlock(tetris.getTypes()[typeIndex]);
myEvent.setWidth(tetris.getWidth());myEvent.setDiv(div);myEvent.setPositionInfo(tetris.getMyBlockContainerPositionInfo());
myEvent.bind("keydown");
if(Utils.getScrollPosition().Y === 0){
Utils.scroll(1000);
}
args[2] = true;args[3] = true;
}
if(!div && isRight){
array = tetris.absoluteDivContainerArray;
div = array[array.length - 1][0];
positionInfo = tetris.getMyBlockContainerPositionInfo();
if(Utils.collideCheck(tetris,'d')){
positionInfo["currentY"] = positionInfo["currentY"] < positionInfo["maxY"] ? positionInfo["currentY"] + 1 : positionInfo["maxY"];
div.style.cssText = "top:"+(positionInfo["currentY"] * width)+"px; left:"+(positionInfo["currentX"] * width)+"px;";
}else{
flag = false;
}
}
if((positionInfo && positionInfo["currentY"] == positionInfo["maxY"]) || !flag){
//实现已被覆盖的小砖块置为disabled状态
Utils.smallBlockSetDisabled(tetris);
//保存最后的位置状态
array[array.length - 1].push(positionInfo);
Utils.removeSomeRows(tetris);
args[2] = false;
//Utils.scroll(1000,0);
}
array = null;div = null;tetris = null;myEvent = null;position = null;
}, args);
timer.start();
//组合键监听,旋转操作
shortcut.add("R",function(){
var array = tetris.absoluteDivContainerArray;
var div = array[array.length - 1][0];
var numStrArray = div.className.match(/\d+/g);
var preNum = parseInt(numStrArray[0]);
var typeNum = parseInt(numStrArray[1]);
var typeIndex = parseInt(numStrArray[numStrArray.length - 1]);
var postNum = (preNum+1)%4;
tetris.rotate(div, typeNum, postNum);
div.className = div.className.replace(/\d+/,postNum);
//重新更新位置信息
var positionInfo = tetris.getMyBlockContainerPositionInfo();
var updateXAndYPositionInfo = Utils.setTopAndLeftBySimple(tetris.getTypesDisplay()["type"+typeNum][typeIndex][0][postNum],typeNum,tetris.getCols(),tetris.getRows());
positionInfo["minX"] = updateXAndYPositionInfo["minX"];positionInfo["maxX"] = updateXAndYPositionInfo["maxX"];
positionInfo["minY"] = updateXAndYPositionInfo["minY"];positionInfo["maxY"] = updateXAndYPositionInfo["maxY"];
positionInfo["div_show"] = updateXAndYPositionInfo["div_show"];
positionInfo = null; updateXAndYPositionInfo = null;
})
};
/*utils.js*/
var Utils = {
'getElementPositionById' : function(id){
var obj = document.getElementById(id);
},
'sleep' : function(numberMillis){
var currentTime = new Date().getTime();
var end = currentTime + numberMillis;
while(true){
if(new Date().getTime() > end){
return false;
}
}
},
'findSameItemDeleteInTwoArray' : function(arr1,arr2){
var array1 = arr1.slice();
var array2 = arr2.slice();
array1.forEach(function(item,index,array){
if(array2.indexOf(item) !== -1){
array1.splice(index,1);
array2.splice(array2.indexOf(item),1);
}
});
return [array1,array2];
},
'setTopAndLeft' : function(array,type,bigContainerCols,bigContainerRows){
var obj = Utils.setTopAndLeftBySimple(array,type,bigContainerCols,bigContainerRows);
var arrX = [];
for(var i = obj["minX"]; i <= obj["maxX"]; i++){
arrX.push(i);
}
obj["currentY"] = obj["minY"];
obj["currentX"] = arrX[Math.floor(Math.random() * (arrX.length))];
return obj;
},
'setTopAndLeftBySimple' : function(array,type,bigContainerCols,bigContainerRows){
var smallContainerRows = parseInt(Math.sqrt(type));
var minX = 1000,minY = 1000,maxX = 0,maxY = 0;
array.forEach(function(item,index,array){
minX = (item % smallContainerRows) > minX ? minX : (item % smallContainerRows);
maxX = (item % smallContainerRows) > maxX ? (item % smallContainerRows) : maxX;
minY = parseInt((item / smallContainerRows)) > minY ? minY : parseInt((item / smallContainerRows));
maxY = parseInt((item / smallContainerRows)) > minY ? parseInt((item / smallContainerRows)) : minY;
});
return {
'minX' : (0 - minX),
'maxX' : (bigContainerCols-1-maxX),
'minY' : (0 - minY),
'maxY' : (bigContainerRows-1-maxY),
'div_show' : array,
'type' : type,
};
},
'smallBlockSetDisabled' : function(tetris){
var positionInfo = tetris.getMyBlockContainerPositionInfo();
var intArray = Utils.findSmallBlockIndex(positionInfo["currentX"],positionInfo["currentY"],positionInfo["type"],positionInfo["div_show"],tetris.getCols());
var myIndex = -1;
intArray.forEach(function(item,index,array){
tetris.divArray[item][0] = false;
tetris.divArray[item][1] = tetris.absoluteDivContainerArray.length - 1;
});
if(tetris.minRowNum > intArray[0]) tetris.minRowNum = intArray[0];
var rowsNum = parseInt(intArray[intArray.length - 1] / tetris.getCols());
if(!tetris.downAbsoluteDivRankArray[rowsNum]){
tetris.downAbsoluteDivRankArray[rowsNum] = [];
tetris.downAbsoluteDivRankArray[rowsNum].push(tetris.absoluteDivContainerArray.length - 1);
}else{
tetris.downAbsoluteDivRankArray[rowsNum].push(tetris.absoluteDivContainerArray.length - 1);
}
var filter = [];
tetris.divArray.forEach(function(item,index,array){
if(!item[0]) filter.push(index);
})
console.log(filter);
console.log("........................................");
},
'removeSomeRows' : function(tetris){
//实行对插入的砖块进行动态监测
var divArray = tetris.divArray;
var removeAbsoluteDivIndexArray = [];//实现将要消除absolute的DIV层的index保存
var currentPosition = tetris.getMyBlockContainerPositionInfo();
var smallContainerRows = parseInt(Math.sqrt(currentPosition["type"]));
var minY = 1000,maxY = 0,cols = 0,isAllColsOccupy = true,myIndex = -1;
currentPosition.div_show.forEach(function(item,index,array){
minY = parseInt((item / smallContainerRows)) > minY ? minY : parseInt((item / smallContainerRows));
maxY = parseInt((item / smallContainerRows)) > minY ? parseInt((item / smallContainerRows)) : minY;
});
minY = minY + currentPosition["currentY"];
maxY = maxY + currentPosition["currentY"];
for(var i = minY; i <= maxY; i++){
isAllColsOccupy = true;
for(var j = 0; j < tetris.getCols(); j++){
if(divArray[i*tetris.getCols()+j][0]){
isAllColsOccupy = false;
break;
}
}
if(isAllColsOccupy){
//实现记录从中间消去的小砖块应变化的数组
var myDivPositionSameColsArray = [];
for(var j = 0; j < tetris.getCols(); j++){
myIndex = i*tetris.getCols()+j;
if(!tetris.absoluteDivContainerArray[divArray[myIndex][1]]) break;
var myPositionArray = tetris.absoluteDivContainerArray[divArray[myIndex][1]][2];
var myAbsoluteDiv = tetris.absoluteDivContainerArray[divArray[myIndex][1]][0];
var childrenCols = parseInt(Math.sqrt(myPositionArray["type"])),myAllChildrenIndexArray = Utils.findSmallBlockIndex(myPositionArray["currentX"],myPositionArray["currentY"],myPositionArray["type"],myPositionArray["div_show"],tetris.getCols());
for(var k = 0; k < myPositionArray["div_show"].length; k++){
if(myIndex === myAllChildrenIndexArray[k]){
//console.log(myAllChildrenIndexArray);
myAbsoluteDiv.childNodes.item(myPositionArray["div_show"][k]).className += " myHidden";
divArray[myIndex][0] = true;
//改变状态,注意数组属于引用,删除里面的元素对原来的数组有影响
for(var m = tetris.downAbsoluteDivRankArray.length - 1; m >= 0; m--){
//divArray[myIndex]有可能为undefined
if(divArray[myIndex] && tetris.downAbsoluteDivRankArray[m] && (tetris.downAbsoluteDivRankArray[m].length != 0)&& tetris.downAbsoluteDivRankArray[m].indexOf(divArray[myIndex][1])!== -1 && m > i){
var myIndex = [];
myPositionArray["div_show"].forEach(function(item,index,myArr){
if(item < myPositionArray["div_show"][k] && (item % childrenCols === myPositionArray["div_show"][k] % childrenCols)){
myIndex.push(item);
}
});
//console.log(myIndex);
if(myIndex && myIndex.length != 0){
myIndex.forEach(function(item,index){
if(!index){
tetris.divArray[myAllChildrenIndexArray[index]][0] = true;
tetris.absoluteDivContainerArray[tetris.divArray[myAllChildrenIndexArray[index]][1]][0].childNodes.item(item).className += " myHidden";
}else{
tetris.divArray[myAllChildrenIndexArray[index]][0] = false;
}
myDivPositionSameColsArray[myAllChildrenIndexArray[index]] = true;
});
tetris.divArray[myAllChildrenIndexArray[k]][0] = false;
var className = tetris.absoluteDivContainerArray[tetris.divArray[myAllChildrenIndexArray[k]][1]][0].childNodes.item(myPositionArray["div_show"][k]).className;
tetris.absoluteDivContainerArray[tetris.divArray[myAllChildrenIndexArray[k]][1]][0].childNodes.item(myPositionArray["div_show"][k]).className = className.replace("myHidden","");
className = null;
}else{
tetris.divArray[myAllChildrenIndexArray[k]][0] = true;
}
//将消去的元素补上
myDivPositionSameColsArray[myAllChildrenIndexArray[k]] = true;
myIndex = null;
}
}
break;
}
}
myPositionArray = null;
myAbsoluteDiv = null;
myClassName = null;
}
//实现出现的砖块整体下移,将未下移之前所有的小砖块的状态置为true
for(var j=parseInt(tetris.minRowNum/tetris.getCols()); j <=i-1; j++){
for(var k=0;k<tetris.getCols();k++){
if(!myDivPositionSameColsArray[j*tetris.getCols()+k])
tetris.divArray[j*tetris.getCols()+k][0] = true;
}
}
var myAbsoluteDiv2015 = null,indexArray = null,indexSum = tetris.getCols()*tetris.getRows(),isNotHidden = false;
for(var j = tetris.downAbsoluteDivRankArray.length - 1; j >= 0; j--){
if(tetris.downAbsoluteDivRankArray[j] &&(tetris.downAbsoluteDivRankArray[j].length > 0)&& j <= i){
for(var k = 0,temp = tetris.downAbsoluteDivRankArray[j].length; k < temp; k++){
myAbsoluteDiv2015 = tetris.absoluteDivContainerArray[tetris.downAbsoluteDivRankArray[j][k]];
myAbsoluteDiv2015[0].style.cssText = "top:"+((myAbsoluteDiv2015[2]["currentY"]+1) * tetris.getWidth())+"px; left:"+(myAbsoluteDiv2015[2]["currentX"] * tetris.getWidth())+"px;";
myAbsoluteDiv2015[2]["currentY"]++;
//重新所有的小砖块的状态置为应有的状态
indexArray = Utils.findSmallBlockIndex(myAbsoluteDiv2015[2]["currentX"],myAbsoluteDiv2015[2]["currentY"],myAbsoluteDiv2015[2]["type"],myAbsoluteDiv2015[2]["div_show"],tetris.getCols());
indexArray.forEach(function(item,index,array){
//判断里面是否含有已经隐藏的div子类
isNotHidden = myAbsoluteDiv2015[0].childNodes.item(myAbsoluteDiv2015[2]["div_show"][index]).className.indexOf("myHidden") === -1;
if(item < indexSum ){
if(isNotHidden) tetris.divArray[item][0] = false;
}
});
}
}
}
}
}
},
//碰撞检测方法
'collideCheck' : function(tetris,direction){
var positionInfo = tetris.getMyBlockContainerPositionInfo();
var intArray = [], x = positionInfo["currentX"], y = positionInfo["currentY"],flag = true;
switch(direction) {
case 'l':
x = x - 1;
break;
case 'r':
x = x + 1;
break;
case 'd':
y = y + 1;
break;
default :;
}
intArray = Utils.findSmallBlockIndex(x,y,positionInfo["type"],positionInfo["div_show"],tetris.getCols());
for(var i = 0; i < intArray.length; i++){
if(tetris.divArray[intArray[i]]&&!tetris.divArray[intArray[i]][0]){
flag = false;
break;
}
}
return flag;
},
'findSmallBlockIndex' : function(x,y,type,array,width){
var mod = parseInt(Math.sqrt(type));
var indexArray = [];
var myIndex = -1;
var start = y * width + x - 1;
array.forEach(function(item,index,arr){
myIndex = start + parseInt((item / mod))* width + item % mod + 1;
indexArray.push(myIndex);
});
return indexArray;
},
'round' : function(floatNum,save){
//通过四舍五入保留save位小数
if(typeof floatNum !== "number" || typeof save !== "number") return NaN;
var floatNumStr = floatNum+"";
var saveStr = saveStr+"";
var saveIsInt = saveStr.indexOf(".") === -1;
var floatNumIsFloat = floatNumStr.indexOf(".") !== -1;
if(!saveIsInt || !floatNumIsFloat) return new Error("数据不合法");
var floatNumStrLastCharIndex = floatNumStr.length - 1,dotIndexInFloatNumStr = floatNumStr.indexOf(".");
var add = 0;//表示进位
var array = [];//存储字符串中的字符
for(var i = floatNumStrLastCharIndex; i >= 0; i--){
if(i != dotIndexInFloatNumStr)
array.push((Number(floatNumStr.charAt(i)) + 0 + add));
else
array.push(".");
if(array[array.length - 1]>= 5){
array[array.length - 1] = 0;
add = 1;
}else{
add = 0;
}
}
if(array[array.length - 1] === 0){
array[array.length] = 1;
dotIndexInFloatNumStr++;
}
return Number(array.reverse().join("").substring(0,dotIndexInFloatNumStr + save + 1));
},
'addClass' : function(styleContent,styleId){
if(!document.styleSheets[document.styleSheets.length]){
var style = document.createElement("style");
style.type = "text/css";
style.innerHTML = styleContent;
var head = document.getElementsByTagName("head").item(0) || document.head || document.documentElement.firstChild;
head.appendChild(style);
}
},
'scroll' : function(numberMillis,value,element){
if(!element) element = "html,body";
var distance = -1000;
if(value === undefined) distance = $(document).height() - $(window).height();
else distance = value;
$(element).animate({scrollTop:distance},numberMillis);
},
'getScrollPosition' : function(){
var x, y;
if(window.pageYOffset)
{ // all except IE
y = window.pageYOffset;
x = window.pageXOffset;
}else if(document.documentElement && document.documentElement.scrollTop)
{ // IE 6 Strict
y = document.documentElement.scrollTop;
x = document.documentElement.scrollLeft;
}else if(document.body) { // all other IE
y = document.body.scrollTop;
x = document.body.scrollLeft;
}
return {X:x, Y:y};
},
'addClassByInternetSource' : function(cssText,num){
var style = document.createElement('style'), //创建一个style元素
head = document.head || document.getElementsByTagName('head')[0] || document.documentElement.item(0); //获取head元素
style.type = 'text/css'; //这里必须显示设置style元素的type属性为text/css,否则在ie中不起作用
if(num || num === 1){
if(style.styleSheet || document.all){ //IE
var func = function(){
try{ //防止IE中stylesheet数量超过限制而发生错误
style.styleSheet.cssText = cssText;
}catch(e){
}
}
//如果当前styleSheet还不能用,则放到异步中则行
if(style.styleSheet.disabled){
setTimeout(func,10);
}else{
func();
}
}else{ //w3c
//w3c浏览器中只要创建文本节点插入到style元素中就行了
var textNode = document.createTextNode(cssText);
style.appendChild(textNode);
}
head.appendChild(style); //把创建的style元素插入到head中
}else{
if(document.all){//IE11不再支持createStyleSheets方法
document.createStyleSheet().cssText = cssText;
}else{
}
}
},
'bindsOnEvent' : function(evenTarget,eventName,func){
if(evenTarget.addEventListener){
evenTarget.addEventListener(eventName,func,false);
}else if(evenTarget.attachEvent){
evenTarget.attachEvent("on"+eventName,func);
}else{
evenTarget["on"+eventName] = func;
}
},
'isPC' : function(){
var platform = navigator.platform.toLowerCase();
var system = {};
system.win = platform.indexOf("win") === 0;
system.mac = platform.indexOf("mac") === 0;
system.xll = (platform === "xll") || (platform.indexOf("linux") === 0);
if((system.win || system.mac || system.xll) && (window.screen.width > 1000)){
return true;
}else{
return false;
}
}
};
/*timer.js*/
function Timer(numberMillis,isSetTimeOut){
var timerInstance = this;
var id = -1;
var hander;
var params = [];
this.start = function(){
if(isSetTimeOut){
id = setTimeout(hander,numberMillis);
}else{
id = setInterval(hander,numberMillis);
}
};
this.schedule = function(func,args){
if(!isSetTimeOut){
hander = function(){
func(args);
};
}else{
hander = function(func,args){
func(args);
//alert(typeof func);
ar-guments.callee(func,args);
}
}
};
this.cancel = function(){
};
this.end = function(){
if(isSetTimeOut){
clearTimeout(id);
}else{
clearInterval(id);
}
};
}
/*event.js*/
function Event(){
var eventTarget;//事件目标
var myEvent;//事件
var width;
var positionInfo;
var tetris;
var div;
var eventInstance = this;
var handler = function(event){
myEvent = event || window.event || arguments.callee.caller.arguments[0];
eventTarget = myEvent.target || myevent.srcElement;
if(myEvent.type === "keydown"){
if(myEvent.keyCode == 37){
//Left Arrow
if(Utils.collideCheck(tetris,'l')){
positionInfo["currentX"] = positionInfo["currentX"] > positionInfo["minX"] ? positionInfo["currentX"] - 1 : positionInfo["currentX"];
}
}else if(myEvent.keyCode == 38){
//Up Arrow
}else if(myEvent.keyCode == 39){
//Right Arrow
if(Utils.collideCheck(tetris,'r')){
positionInfo["currentX"] = positionInfo["maxX"] > positionInfo["currentX"] ? positionInfo["currentX"] + 1 : positionInfo["currentX"];
}
}else if(myEvent.keyCode == 40){
//Down Arrow Speed加速前进
/*var flag = Utils.collideCheck(tetris,'d',5);
console.log(flag);
if(flag){
positionInfo["currentY"] = positionInfo["maxY"] > positionInfo["currentY"] ? positionInfo["currentY"] + 5 : positionInfo["currentY"];
}*/
}else{
}
div.style.cssText = "top:"+(positionInfo["currentY"] * width)+"px; left:"+(positionInfo["currentX"] * width)+"px;";
}
}
this.bind = function(eventName,eventSource){
if(!eventSource) eventTarget = document;
else eventTarget = eventSource;
if(eventTarget.addEventListener){
eventTarget.addEventListener(eventName,handler,false);
}else if(eventTarget.attachEvent){
eventTarget.attachEvent("on"+eventName,handler);
}else{
eventTarget["on"+eventName] = handler;
}
};
this.setWidth = function(widthValue){
width = widthValue;
};
this.setTetris = function(tetrisValue){
tetris = tetrisValue;
}
this.setPositionInfo = function(positionInfoValue){
positionInfo = positionInfoValue;
};
this.setDiv = function(divValue){
div = divValue;
};
this.getEventTarget = function(){
return eventTarget;
};
this.getEvent = function(){
return myEvent;
}
}
扫码关注w3ctech微信公众号
没demo地址,没分析,让人怎么看啊
@老六 主要是还没完全实现所以的话,线上地址暂时不能公布呀
好厉害!
变换方块形状,有设计吗?
@阿魏 有的,你可以按r键
@钱端 哈哈,你也可以的呀,关键是思路
楼主是基于dom做的,代码看起来挺复杂的,还没有细看。我前些天也写了一个基于canvas俄罗斯方块小游戏,放在github上,https://github.com/sandywalker/Tetris。用browserify做了模块化分层,代码量少,也比较容易理解。有想拓展思路的同学可以关注一下。
不好意思,第一次写评论,链接没做好。地址是Tetris
@sandy 已fork,谢谢呀,我觉得canvas挺好的呀,共同进步
共收到11条回复