美文网首页
用面向对象的方法写一个俄罗斯方块(一):设计思路

用面向对象的方法写一个俄罗斯方块(一):设计思路

作者: HolidayPeng | 来源:发表于2018-10-29 10:43 被阅读50次

    俄罗斯方块的逻辑稍微有些复杂,实现的方法也有很多,这里分享其中一种。
    首先我们得有数据驱动的思维,把这个游戏抽象成两组数据:
    方块活动的范围是一组数据,方块可以在这个范围向左、向右、向下移动,我们可以把这个范围标记为一个二维数组,类似于一个xy坐标轴:

    gameAreaData: [
      [0, 0, 0, 0, 1, 0, 0, 0, 0, 0] ,
      [0, 0, 0, 0, 1, 1, 1, 0, 0, 0] ,
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ,
      [2, 2, 2, 2, 2, 2, 2, 2, 2, 0] 
      …
    ]
    

    没有方块的时候该坐标单位的值为0,有方块并且方块可以移动的时候值为1,方块不能移动的时候值为2。
    方块有不同的形状,每种形状又可以旋转,同样可以用一个二维数组来保存这些形状,比如长条:

    teris: {
      origin: [
        [1, 1, 1, 1]
      ],
      rotate: [
        [
          [1, 1, 1, 1]
        ],
        [
          [1],
          [1],
          [1],
          [1]
        ],
        [
          [1, 1, 1, 1]
        ],
        [
          [1],
          [1],
          [1],
          [1]
        ]
      ]
      …
    }
    

    另外方块在移动时,我们需要知道方块移动的位置,是向下移动一个单位,还是向右/向左移动了一个单位。我们可以用一个对象来保存当前位置:

    position: {
     x: 0,
     y: 0
    };
    

    现在两组数据我们都有了,要做的就是在方块位置移动的时候或者形状变化(旋转)的时候,把第二组数据的值赋给第一组数据:

    function updateData() {
      for (let i = 0; i < teris.origin.length; i++) {
        for (let j = 0; j < teris.origin[0].length; j++) {
          gameAreaData[teris.position.x + 1][teris.position.y + j] = teris.origin[i][j];
        }
      }
    }
    

    这样俄罗斯方块的基本逻辑我们就有了,现在可以来考虑一下代码结构的问题。
    首先七种方块由于形状不同,内部的数据也不同,我们可以把它们分成七个类:

    class IBlock ;
    class Square;
    class RLblock;
    class TBolck;
    class Swagerly;
    class RSwagerly;
    class LinePiece;
    

    操作这其中方块的方法是共享的,可以把这些方法放在一个共同的类里,并让这个类继承七种方块的属性(数据):

    class Shapes() {
      constructor: {
        this.shapesData = [
          lBlock,
          Square,
          RLblock,
          TBolck,
          Swagerly,
          RSwagerly,
          LinePiece
        ]
      }
    }
    

    为了让Shapes每次被实例化的时候系统不必分配内存给它的方法,我们把这些方法写在原型链上:

    class Shapes() {
      constructor: {
        this.shapesData = [
          lBlock,
          Square,
          RLblock,
          TBolck,
          Swagerly,
          RSwagerly,
          LinePiece
        ]
      }
    }
    
    Shapes.prototype.updateData = function() {
      for (let i = 0; i < teris.origin.length; i++) {
        for (let j = 0; j < teris.origin[0].length; j++) {
          gameAreaData[teris.position.x + 1][teris.position.y + j] = teris.origin[i][j];
        }
      }
    }
    ……
    

    最后到游戏的具体操作部分,我们把这些操作都放在一个JS文件里。这一篇先讲解思路,下一篇再续上完整的实现过程。

    相关文章

      网友评论

          本文标题:用面向对象的方法写一个俄罗斯方块(一):设计思路

          本文链接:https://www.haomeiwen.com/subject/rjfltqtx.html