Giter Site home page Giter Site logo

source2018-whucs / tetris Goto Github PK

View Code? Open in Web Editor NEW

This project forked from newxps/tetris

1.0 0.0 0.0 21 KB

俄罗斯方块

Home Page: http://demo.fanlinfeng.com/tetris---%E4%BF%84%E7%BD%97%E6%96%AF%E6%96%B9%E5%9D%97/

JavaScript 74.25% HTML 13.29% CSS 12.46%

tetris's Introduction

俄罗斯方块

前端时间有空, 还是想找点事干, 正好那天听一个朋友说写一个 俄罗斯方块, 于是就想尝试一下. 经过两天的思考, 我终于在完全不借助外力的情况下想到了一个自己的实现方法. 当然, 如果网上早就有类似方法纯属巧合.

构思和操作

因为以前写过点DOM动画, 这次遇到俄罗斯方块自然也想到了碰撞检测, 让元素移动起来并不难, 难得是在碰撞时候的各种检测, 主要是当前下落方块和已有的复杂结构方块的碰撞, 因为当前下落方块还可以旋转位移. 简单的碰撞检测通常也就是找到元素的Bounding Box, 然后根据Bounding Box四边位置和边界或其他元素进行判断. 比如碰撞动画.

但是, 俄罗斯方块的形状比普通圆形或矩形复杂, 而且它包含的旋转中心也不同. 所以光是直接通过外形判断是否碰撞(尤其是形态不同的方块之间)比较麻烦.

俄罗斯方块是矩阵形式的, 为什么不可以用矩阵表示?

然后我想到了如下数据结构表示整个游戏舞台:

var stage = [
    // 总共20行, 10列
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    // ...
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]

方块矩阵, 如:

var block = [
    [0, 1, 0],
    [1, 1, 1]
]

方块走到哪里, 就和stage相加到哪里, 如果某个位置之前已经有方块存在, 则这个位置会>1, 因此可以判断方块之间发生了碰撞.

可以说, 想到这个方法, 整个俄罗斯方块已经相当于完成了1/3了.

但事情并没完...

既然想到了用矩阵, 为何不直接使用二进制数取代数组表示?

如果使用数组表示矩阵, 那么水平移动, 向下移动, 检测碰撞 会添加大量的代码. 直接用二进制数表示岂不是更方便? 我只需要添加一个pad函数, 即可将10进制数字展开成二进制数, 且前面补0. 比如pad(3, 10)得到0000000011 而且可以直接使用<<>>对数字进行移位, 如果使用数组表示还需要单独添加一大坨函数来做 使用数字表示舞台:

// 因为俄罗斯方块是20行
var stage = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

方块例子:

var block = [32, 112];  // 因为方块默认是从舞台顶部中间位置出现

又会有问题...

上一步中block已经和stage对应行数相加(add函数实现)了, 但下一步动画block已经变了一格位置. 根据上面的<=1法则, 难道算是碰撞了? 然而方块并没有和其他方块或墙壁碰撞

所以, 我想到了一个mix函数, mix函数内部先执行minus, 然后进行某些操作, 最后再add.

中间的"某些操作" 可以是平移,向下移动... 如果不操作, 则下一步位置不变.

中间还需要判断方块在边界是否可变换, 方块在方块之间是否可变换....

最终每一步都得到一个修改后的stage都是最终要呈现的model, 然后将model直接投射到dom或者canvas(使用render), over!

遇到的坑

上面说的检测碰撞算是小坑.

检测边界稍微大点, 直接平移的话边界当然非常容易检测, 但一个奇葩的形状在边界还想变换呢? 有可能一部分就跑到边界之外了. 上面使用的是10个二进制数来表示一行, 在左边界自然可以通过判断是否>=1024, 因为第11位如果为1说明方块已经有一部分在左边界之外. 但右边界就不好弄了, 因为不管怎么向右平移得到都是0. 最终只能使用11或12位的二进制表示一行. 虽然展示的只有10列.

总结

  • 涉及到复杂碰撞的效果, 可以使用矩阵(3D空间可以扩展到三维矩阵), 如果矩阵直接相加大于指定的值, 说明已经碰撞.
  • 展示型的效果(不一定必须是游戏, 可以是一个动画, 展示面板等等), 虚拟舞台最好都比实际显示舞台大, 才方便检测各种效果. 不然坑大了...
  • 视图渲染和模型分离, model出来了, render方法无论呈现给DOM还是Canvas都已经非常简单了.

tetris's People

Contributors

newxps avatar

Stargazers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.