今天加入:1.暂停功能,2.瞬落功能,3.调整预告和计分栏的位置,效果图如下:
本来还想加入等级系统和支持手机的,今天实在木有时间了,下次一定更新上来。
本人QQ:605494869 新浪微博:http://weibo.com/605494869,非常欢迎加好友和互粉~具体代码如下:<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
  .activityModel{margin:1px; width:19px; height:19px; background:red; position:absolute;}
  .forecastModel{margin:0.5px; width:9.5px; height:9.5px; background:yellow; position:absolute;}
  .stationaryModel{margin:1px; width:19px; height:19px; background:gray; position:absolute;}
  .container{top:0px; left:0px; background:black; position:absolute;}
  .info{top:0px; position:absolute;}
  .score{width:80px; height:20px; font-size:10pt; text-align:right; color:white; position:absolute;}
  .forecast{top:0px; left:0px; width:48px; height:48px; background:#151515; position:absolute;}
</style>
<script type="text/javascript">var tetris;
var container;
var intervalId;
var intervalId2;var speed = 600;
var size = 20;
var forecastSize = 10;
var rowCount = 18;
var colCount = 10;
var announcement = 6;var isOver = false;
var isStop = false;
var shapes = ("0,1,1,1,2,1,3,1;1,0,1,1,1,2,2,2;2,0,2,1,2,2,1,2;0,1,1,1,1,2,2,2;1,2,2,2,2,1,3,1;1,1,2,1,1,2,2,2;0,2,1,2,1,1,2,2").split(";");function createElm(tag,css)
{
  var elm = document.createElement(tag);
  elm.className = css;
  document.body.appendChild(elm);
  return elm;
}function Tetris(css,x,y,shape)
{
  // 创建4个div用来组合出各种方块
  var myCss = css?css:"activityModel";
  this.divs = [createElm("div",myCss),createElm("div",myCss),createElm("div",myCss),createElm("div",myCss)];
  
  if(!shape)
  {
    // 初始化计分栏  
    this.score = createElm("div","score");
    this.score.style.top = "0px";
    this.score.style.left = 6*size+"px";
    this.score.innerHTML = "score:000";
    // 初始化预告栏和预告方块
    var forecastCss = "forecastModel";
    this.forecast = createElm("div","forecast");
    this.divs2 = [createElm("div",forecastCss),createElm("div",forecastCss),createElm("div",forecastCss),createElm("div",forecastCss)];
  }
  
  this.container = null;
  
  this.refresh = function()
  {
    this.x = (typeof(x)!='undefined')?x:3;
    this.y = (typeof(y)!='undefined')?y:0;
    
    // 如果有传参,优先使用参数的,如果有预告,优先使用预告,都没有就自己生成
    if(shape)
      this.shape = shape;
    else if(this.shape2)
      this.shape = this.shape2;
    else
      this.shape = shape?shape:shapes[Math.floor((Math.random()*shapes.length-0.000000001))].split(",");
    
    this.shape2 = shapes[Math.floor((Math.random()*shapes.length-0.000000001))].split(",");
    
    if(this.container && !this.container.check(this.x,this.y,this.shape))
    {
      isOver = true;
      alert("游戏结束");
    }
    else
    {
     this.show();
     this.showScore();
     this.showAnnouncement();
    }
  }
  
  // 显示方块
  this.show = function()
  {
    for(var i in this.divs)
    {
      this.divs[i].style.top = (this.shape[i*2+1]- -this.y)*size+"px";
      this.divs[i].style.left = (this.shape[i*2]- -this.x)*size+"px";
    }
  }
  
  // 显示预告
  this.showAnnouncement = function()
  {
    for(var i in this.divs2)
    {
      this.divs2[i].style.top = (this.shape2[i*2+1]- -0.2)*forecastSize+"px";
      this.divs2[i].style.left = (this.shape2[i*2]- -0.2)*forecastSize+"px";
    }
  }
  
  // 显示分数
  this.showScore = function()
  {
    if(this.container && this.score)
    {
      switch((this.container.score + "").length)
      {
        case 1:
          this.score.innerHTML = "score:" + "00" + this.container.score;
          break;
        case 2:
          this.score.innerHTML = "score:" + "0" + this.container.score;
          break;
        default :
          this.score.innerHTML = "score:" + this.container.score;
          break;
      }
    }
  }
  
  // 水平移动方块的位置
  this.hMove = function(step)
  {
    if(this.container.check(this.x- -step,this.y,this.shape))
    {
      this.x += step;
      this.show();
    }
  }
  
  // 垂直移动方块位置
  this.vMove = function(step)
  {
    if(this.container.check(this.x,this.y- -step,this.shape))
    {
      this.y += step;
      this.show();
    }
    else
    {
      this.container.fixShape(this.x,this.y,this.shape);
      this.container.findFull();
      this.refresh();
      clearInterval(intervalId2);
    }
  }
  
  // 旋转方块
  this.rotate = function()
  {
    var newShape = [this.shape[1],3-this.shape[0],this.shape[3],3-this.shape[2],this.shape[5],3-this.shape[4],this.shape[7],3-this.shape[6]];
    if(this.container.check(this.x,this.y,newShape))
    {
      this.shape = newShape;
      this.show();
    }
  }
  
  this.refresh();
}function Container()
{
  this.init = function()
  { 
    // 绘制方块所在区域
    var bgDiv = createElm("div","container");
    bgDiv.style.width = size*colCount+"px";
    bgDiv.style.height = size*rowCount+"px";
    
    // 绘制预告所在区域
    var bgDiv = createElm("div","info");
    bgDiv.style.left = size*colCount+"px";
    bgDiv.style.width = size*announcement+"px";
    bgDiv.style.height = size*rowCount+"px";
    bgDiv.innerHTML = "&nbsp;特殊说明:<br/>&nbsp;回车:'暂停'<br/>&nbsp;空格:'瞬落'";
    
    // 清空积分
    this.score = 0;
  }
  
  this.check = function(x,y,shape)
  {
    // 检查边界越界
    var flag = false;
    var leftmost=colCount;
    var rightmost=0;
    var undermost=0;
    
    for(var i=0;i<8;i+=2)
    {
      // 记录最左边水平坐标
      if(shape[i]<leftmost)
        leftmost = shape[i];
      
      // 记录最右边水平坐标
      if(shape[i]>rightmost)
        rightmost = shape[i];
      
      // 记录最下边垂直坐标
      if(shape[i+1]>undermost)
        undermost = shape[i+1];
      
      // 判断是否碰撞
      if(this[(shape[i+1]- -y)*100- -(shape[i]- -x)])
        flag = true;
    }
    
    // 判断是否到达极限高度
    for(var m=0;m<3;m++)
      for(var n=0;n<colCount;n++)
        if(this[m*100+n])
          flag = true;
      
    if((rightmost- -x+1)>colCount || (leftmost- -x)<0 || (undermost- -y+1)>rowCount || flag)
      return false;
    
    return true;
  }
  
  // 用灰色方块替换红色方块,并在容器中记录灰色方块的位置
  this.fixShape = function(x,y,shape)
  {
    var t = new Tetris("stationaryModel",x,y,shape);
    for(var i=0;i<8;i+=2)
      this[(shape[i+1]- -y)*100- -(shape[i]- -x)] = t.divs[i/2];
  }  // 遍历整个容器,判断是否可以消除
  this.findFull = function()
  {
    var s = 0;
    for(var m=0;m<rowCount;m++)
    {
      var count = 0;
      for(var n=0;n<colCount;n++)
        if(this[m*100+n])
          count++;      if(count==colCount)
      {
        s++;
        this.removeLine(m);
      }
    }
    
    this.score -= -this.calScore(s);
  }
  
  this.calScore = function(s)
  { 
    if(s!=0)
      return s- -this.calScore(s-1)
    else
      return 0;
  }
  
  // 消除指定一行方块
  this.removeLine = function(rowCount)
  {
    // 移除一行方块
    for(var n=0;n<colCount;n++)
      document.body.removeChild(this[rowCount*100+n]);    // 把所消除行上面所有的方块下移一行
    for(var i=rowCount;i>0;i--)
    {
      for(var j=0;j<colCount;j++)
      {
        this[i*100- -j] = this[(i-1)*100- -j]
        
        if(this[i*100- -j]) 
          this[i*100- -j].style.top = i*size + "px";
      }
    }
  }
}function init()
{
  container = new Container();
  container.init();
  
  tetris = new Tetris();
  tetris.container = container;
  
  document.onkeydown = function(e)
  {
    
    var e = window.event?window.event:e;
    
    if(e.keyCode == 13)
      toggleInterval();
      
    if(isOver || isStop) 
      return;
    
    switch(e.keyCode)
    {
      case 13:
        stopInterval();
        break;
      case 32:
        intervalId2 = setInterval("if(!isOver) tetris.vMove(1)",1);
        break;
      case 38: //up
        tetris.rotate();
        break;
      case 40: //down
        tetris.vMove(1);
        break;
      case 37: //left
        tetris.hMove(-1);
        break;
      case 39: //right
        tetris.hMove(1);
        break;
    }
  }
  
  // 方块开始下降
  intervalId = setInterval("if(!isOver) tetris.vMove(1)",speed);
}// 控制暂定
function toggleInterval()
{
  if(isStop)
  {
    isStop = false;
    intervalId = setInterval("if(!isOver) tetris.vMove(1)",speed);
  }
  else
  {
    isStop = true;
    clearInterval(intervalId);
  }
}
</script>
</head>
<body onload="init()">
</body>
</html>