首页 > 技术文章 > H5实现俄罗斯方块(二)

sunliyuan 2016-12-11 21:43 原文

对应的js

1.封装操作dom的js:

(function (document) {
    //游戏的实例
    var gameInst;
   
   /**封装一个返回原型的DOM对象 */
   function DomObject(dom){
     this.dom=dom;
   }

   /**返回真正的dom元素 */
   DomObject.prototype.get=function () {
       return this.dom;
   };

   /**分装事件的注册 */
   DomObject.prototype.on=function (eventName,eventHandler) {
       this.get().addEventListener(eventName,eventHandler);
   };

  
   /**分装操作CSS样式的方法 */
   DomObject.prototype.css=function (stylekey,styleValue){
       this.get().style[stylekey]=styleValue;
   };

 /**能够操作以上对象的作法的方法 */
   function $(selector,context) {
       return  new DomObject((context||document).querySelector(selector));
   };

/**启动游戏的方法 */
function  startGame() {
    //注册一个时间  OK时 启动游戏
        ResourceManager.onResourceLoaded = function () {
      // new Board();   调用游戏的计时方法
    gameInst = new Tetris();
      gameInst.startGame();
    };
    ResourceManager.init();
}

  /**初始化的一个方法 */
   function  _init() {
       $('#btn-start').on('click',function (ev) {
           $('.start-container').css('display','none');
             $('.game-container').css('display', 'block');
             /**调用游戏启动的方法 */
             startGame();
       });

       $('#btn-setting').on('click', function(ev){
            // alert('You clicked the setting button.');
            $('.modal-dialog').css('display','block');
        
        });

     $('#btn-dialog-close').on('click',function () {
           $('.modal-dialog').css('display','none');
               gameInst && gameInst.resume();
     });

     $('#ck-sound').on('click',function () {
         var enable=$('#ck-sound').get().checked;
         window.TetrisConfig.config.enableSound=enable;
     });

     $('#btn-game-setting').on('click',function () {
            $('.modal-dialog').css('display','block');
            gameInst.pause();
     });
     //暂停和继续
  $('#btn-game-pause').on('click', function (evt) {
      var el = evt.target;
      if (el.innerText === '暂停') {
        el.innerText = '继续';
        gameInst.pause();
      } else {
        el.innerText = '暂停';
        gameInst.resume();
      }
    });
   }
   /**监听事件的方法 */
   document.addEventListener('DOMContentLoaded',function (ev) {
      _init(); 
   });
   
})(document);

 全局的配置:

(function (window) {
  window.TetrisConfig = {
    rows: 20,
    cols: 13,
    speed: 1000,
    constSpeed:1000,
    intervalId: 0,
    config:{
      
    }
  };
})(window);

 绘制方块的js:

(function (window) {
  'use strict';
  function Block(blockType) {
    this.blockType = blockType;
    this.size = 30;
    this.originalSize = 32;
    this.sprite = window.ResourceManager.getResource('blocks');
  }

  Block.prototype = {
    constructor: Block,
    draw: function (context, x, y,blockType,size) {
      size=size || this.size;
      context.drawImage(this.sprite, ((blockType || this.blockType) -1) * this.originalSize, 0, this.originalSize, this.originalSize, x * size, y * size, size, size);
    }
  };

  window.Block = Block;

})(window);

 放置游戏主元素的面板:

/**放置游戏主元素的面板 */
(function (window) {
  'use strict';

function  Board(gameInst) {
    //传递游戏的实例
    this.gameInst=gameInst;
    this.blockSize=30;
    this.rows=TetrisConfig.rows;
    this.cols=TetrisConfig.cols;
    /**拿到Canvas对象 */
     this.canvas = new Canvas('c_game_main', this.cols * this.blockSize, this.rows * this.blockSize);
    this.context=this.canvas.context;
    /**生成画布二维数组的数据 */
    this.boardList=[];

    //绘制方块的属性
      this.shape = new window.Shape();
    

    this._init();

    //验证是否成功
    var b = ResourceManager.getResource('blocks');
    console.log(b);
}

/**操作_init方法 */
Board.prototype={
   constructor:Board,
   _init:function(){
          this._buildGridData();
          this._initGrid();

         //初始化的时候绘制方块
      this.shape.draw(this.context);
      var self=this;
      setTimeout(function(){
        //调用构建下一步方块的方法
            self._buildNextShape();
      });
   },



//构建下一步方块的方法
 _buildNextShape: function () {
      this.nextShape = new window.Shape();
  this.nextShape.setPosition(this.gameInst.nextshape.cols, this.gameInst.nextshape.rows);
    //找到面板
  this.gameInst.nextshape.render(this.nextShape);
    },
 

   /**_init中的两个方法*/
  _buildGridData(){
      var i,j;
      for(i=0;i<this.rows;i++){
          this.boardList[i]=[];
          for(j=0;j<this.cols;j++){
              this.boardList[i][j]=0;
          }
      }
    //  console.log(this.boardList);
  },    
  /**绘制表格数据  */
  _initGrid(){
   /**设置画笔 */
      var i;
   this.context.strokeStyle='green';
   this.context.linewidth=0.5;

   //绘制线条的 笔迹
   for(i=0;i<this.rows;i++){
       /**找到起始点 ()*/
       this.context.moveTo(0,i*this.blockSize);
       this.context.lineTo(this.canvas.width,i*this.blockSize);
   }

   for(i=0;i<=this.cols;i++){
       this.context.moveTo(i*this.blockSize,0);
       this.context.lineTo(i*this.blockSize,this.canvas.height);
   }
    //绘制 线条
    this.context.stroke(); 
    
    //把数据进行缓存
    this.gridImageData=this.context.getImageData(0,0,this.canvas.width,this.canvas.height);
  },
  tick:function(){
      //跳动一次加一个数
      if(this.validMove(0,1)){
            this.shape.y+=1;
      }else{
          //不能向下移动添加
          this.addShapeToBoardList();
          //游戏 
          if(this.gameInst._state==='over'){
              this.gameInst.endGame();
              return;
          }
          
          //执行清理方法
          this.clearFullRows();
         this.shape=this.nextShape;
         this.shape.setPosition(this.cols,this.rows,true);
         this._buildNextShape();
          //添加后重新实例化
         // this.shape=new window.Shape();
      }
   
     //画布刷新一次
     this.refresh();
     //画出方块
     this.shape.draw(this.context);

  },
  refresh:function(){
      this.canvas.clear();
      //把图像数据推送到Canvas中
      this.context.putImageData(this.gridImageData,0,0);
      //绘制方块
      this.drawBlocks();
  },

   //边际的检查算法
  validMove:function(moveX,moveY){
     //下一步的位置
     var  nextX=this.shape.x+moveX;
     var nextY=this.shape.y+moveY;

     //循环检查有没有越界  (越界的算法)
     for(var y=0;y<this.shape.layout.length;y++){
         for(var x=0;x<this.shape.layout[y].length;x++){
             //判断有没有方块
            if(this.shape.layout[y][x]){
               if (typeof this.boardList[nextY + y] === 'undefined'  //找不到行
              || typeof this.boardList[nextY + y][nextX + x] === 'undefined'    //找不到列
              ||this.boardList[nextY+y][nextX+x]    //当前位置已有方块
              ||nextX+x<0    //超出左边界
              ||nextX+x>=this.cols  //超出右边界
              ||nextY+y>=this.rows    //超出上边界
              ){
                return false;
              }
             
            }
         }
     }
    return true;
  },
    //添加堆积容器
  addShapeToBoardList:function(){
for(var y=0;y<this.shape.layout.length;y++){
         for(var x=0;x<this.shape.layout[y].length;x++){
         if(this.shape.layout[y][x]){
             var boardX=this.shape.x+x;
             var boardY=this.shape.y+y;
             if(this.boardList[boardY][boardX]){
                 //说明已经有了  状态的变化
                 this.gameInst._state='over';
                 return;
             }else{
                 //没有碰上默认等于1  让他显示出来
                 this.boardList[boardY][boardX]=this.shape.blockType;

             }
         }
         }
      }
  },
  //绘制方块
  drawBlocks:function(){
      for(var y=0;y<this.rows;y++){
          for(var x=0;x<this.cols;x++){
              if(this.boardList[y][x]){
                  this.shape.block.draw(this.context,x,y,this.boardList[y][x]);  
              }
          }
      }
  },

   //创建空行
   createEmptyRow(){
       var emptyArr=[];
       for(var i=0;i<this.cols;i++){
           emptyArr.push(0);
       }
       return emptyArr;
   },


  //消除行的方法
  clearFullRows:function(){
      var self=this;
      var  lines=0;
      //重下往上判断
  for(var y=this.rows-1;y>=0;y--){
      //全部填充
      var filled=this.boardList[y].filter(function(item){return item>0;}).length===this.cols;
      //做移除操作
      if(filled&&y){
          this.boardList.splice(y,1);
          //追加一行  用创建的新行进行填充
          this.boardList.unshift(this.createEmptyRow());
          lines++;
          y++;
      }
  }
   //计算出得分
   var score=lines*100*lines;  //清楚的行数  *  单行得分  *  倍数
   //调用得分的方法
  var totalScore= this.gameInst.score.addScore(score); 
  //最高分
    this.gameInst.highscore.checkScore(totalScore);
  //当前的级别
  var currentLevel= this.gameInst.level.checkLevel(totalScore);
    if(currentLevel){
        //升级算法速度的变化
        window.TetrisConfig.speed= Math.floor(window.TetrisConfig.constSpeed *(1-(currentLevel-1) /10  ));
        //提示用户   1.暂停游戏
        this.gameInst.pause();
        setTimeout(function() {
            window.alert('恭喜您升级了!');
            self.gameInst.resume();
        });

    }


  }
};
  window.Board = Board;

})(window);

 绘制面板:

/**
 * @param  canvasId Canvas元素的ID 属性
 * @param  width  Canvas宽度
 * @param  height Canvas高度
 */

(function (window){
    'user strict';
    
  function Canvas(canvasId, width, height) {
    this.canvasId = canvasId;
      this.el = document.getElementById(canvasId);
    if(!this.el) {
       throw new Error ('Must provider a right canvas id.');
    }
    /**获取Canvas的上下文 */
    this.context=this.el.getContext('2d');
    this.width=width||window.innerWidth;
    this.height=height||window.innerHeight;
    this._init();
}

/**操作原型 */
Canvas.prototype={
    constructor:Canvas,
    _init :function(){
        /**style 中的宽高  赋值给参数中的值 */
      this.el.width=this.width;
      this.el.height=this.height;
    },

    clear:function(fromX,fromY,toX,toY){
        fromX=fromX||0;
        fromY=fromY||0;
        toX=toX||this.width;
        toY=toY||this.height;
     this.context.clearRect(fromX,fromY,toX,toY)
    },
    //绘制文本
     drawText: function (text, x, y) {
      //清理画布
     this.clear(0, 0);
      //设置画笔
      this.context.font = '25px Arial';
      this.context.fillStyle = 'purple';
      this.context.textAlign = 'center';
      this.context.fillText(text, x === undefined ? (this.width / 2) : x, y === undefined ? 45 : y);
    }
};

 window.Canvas=Canvas; 

})(window);

 

推荐阅读