前言:
  上文中谈到了H5版俄罗斯方块的需求和目标, 这次要实现一个可玩的版本. 但饭要一口一口吃, 很多东西并非一蹴而就. 本文将简单实现一个可玩的俄罗斯方块版本. 下一步会引入AI, 最终采用cocos2d-js来重构之.
  本系列的文章链接如下:
  1). 需求分析和目标创新 
  这些博文和代码基本是同步的, 并不确定需求是否会改变, 进度是否搁置, 但期翼自己能坚持和实现.

演示&下载:
  初步版本效果较为简陋, 其大致效果如图所示:
  
  其代码下载地址为: http://pan.baidu.com/s/1dDm4B0P
  该版本参考了不少cnblogs网友的同类版本, 尤其是博主"奕秋"的"Canvas俄罗斯方块". 再次表示感谢.

模型和构建:
  • 方块抽象和建模
  俄罗斯方块由7种方块组成, 各有特点. 当然也不能忽视方块的旋转特性, 这边采用了"Arika Rotation System"体系, 其具体的旋转变化如下所示:
     
  因此对方块进行抽象, 构建一个基类Shape, 然后7种形状继承于基类Shape来构建.

function Shape(x, y, idx, color, shapes) {
  this.x = x;
  this.y = y;
  this.idx = idx;
  this.color = color;
  this.shapes = shapes;
};

  注: 这边的属性依次为x,y坐标, 颜色, 变换形状数组及索引标识.
  由于JavaScript没有所谓类和继承的概念, 需要依靠原型链来模拟构建, 这边我们采用寄生组合式继承方式来实现. 以L型方块为例.

// *) L型方块的转换变换矩阵
LShape.SHAPES = [
  [
    [0, 1, 0, 0],
    [0, 1, 0, 0],
    [0, 1, 1, 0],
    [0, 0, 0, 0]
  ],
  [
    [0, 0, 0, 0],
    [1, 1, 1, 0],
    [1, 0, 0, 0],
    [0, 0, 0, 0]
  ],
  [
    [0, 1, 1, 0],
    [0, 0, 1, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 0]
  ],
  [
    [0, 0, 0, 0],
    [0, 0, 1, 0],
    [1, 1, 1, 0],
    [0, 0, 0, 0]
  ]
];
function LShape(x, y, idx, color) {
  // *) 继承父类的属性变量
  Shape.call(this, x, y, idx, color, LShape.SHAPES);
};
// *) 继承父类的抽象方法
LShape.prototype = new Shape();

  对方块的生成, 可以采用工厂方法, 不过为了简便, 并没有采用.

    function createShape() {
var shapeTypes = [LShape, JShape, IShape, OShape, TShape, SShape, ZShape];
var colorTypes = ["red", "green", "blue", "pink"]
var shapeIdx = Math.floor(Math.random() * 100) % shapeTypes.length;
var shapePos = Math.floor(Math.random() * 100) % 4;
var colorIdx = Math.floor(Math.random() * 100) % colorTypes.length;
return new shapeTypes[shapeIdx](4, 0, shapePos, colorTypes[colorIdx]);
}

  • 按键事件的注册和处理
  俄罗斯方块需要对向左, 向右, 变换的按键事件作出及时的反应外, 还需要对向下的长按键进行处理.
  对于向左, 向右, 变换的按键事件, 简单注册按键事件即可.

document.body.addEventListener("keydown", function(e) {
  gameEnv.keydown(e.keyCode);
  switch(e.keyCode) {
  case 37:
    gameScene.keydown(ActionType.ACTION_LEFT);
    break;
  case 38:
    gameScene.keydown(ActionType.ACTION_CHANGE);
    break;
  case 39:
    gameScene.keydown(ActionType.ACTION_RIGHT);
    break;
  case 40:
    gameScene.keydown(ActionType.ACTION_DOWN);
    break;
  }
});

  但对于向下的长按键处理, 除了监听键盘事件外, 还需要在游戏主逻辑循环中, 添加轮询该按键状态.
  因此我们引入一个按键数组, 用于记录按键的状态.

function GameEnv() {
  this.presskeys = new Array(256);
}
GameEnv.prototype.reset = function() {
  for ( var i = 0; i < this.presskeys.length; i++ ) {
    this.presskeys[i] = false;
  }
}
GameEnv.prototype.keyup = function(keyCode){
  if ( keyCode >= 0 && keyCode < 256 ) {
    this.presskeys[keyCode] = false;
  }
};
GameEnv.prototype.keydown = function(keyCode) {
  if ( keyCode >= 0 && keyCode < 256 ) {
    this.presskeys[keyCode] = true;
  }
};

  而游戏的主循环如下所示:

var fps = 30 || 0;
setInterval(gameLogic, fps); function gameLogic() {
  gameScene.updateGame();
  gameScene.renderGame(ctx);
}

  以上是我觉得有些小难度的地方, 其余的都是数据结构和canvas绘图的一些知识点, 这边暂略过.

总结:
  一个游戏, 说简单也简单, 说难也难. 难是因为它是个系统工程, 涉及图形绘制, 语音播放, 以及javascript的事件模型等. 当前的俄罗斯方块已有个基本框架, 初步能玩. 虽然离最终设定的目标还有些距离, 但"千里之行, 始于足下", 终是一个很好的开头.

写在最后:
  
如果你觉得这篇文章对你有帮助, 请小小打赏下. 其实我想试试, 看看写博客能否给自己带来一点小小的收益. 无论多少, 都是对楼主一种由衷的肯定.

  

H5版俄罗斯方块(2)---游戏的基本框架和实现的更多相关文章

  1. H5版俄罗斯方块(3)---游戏的AI算法

    前言: 算是"long long ago"的事了, 某著名互联网公司在我校举行了一次"lengend code"的比赛, 其中有一题就是"智能俄罗斯方 ...

  2. H5版俄罗斯方块(4)---火拼对战的雏形

    前言: 勿忘初心, 本系列的目标是实现一款类似QQ"火拼系列"的人机对战版俄罗斯方块. 在完成了基本游戏框架和AI的算法探索后, 让我们来尝试一下人机大战雏形编写. 本系列的文章链 ...

  3. H5版俄罗斯方块(5)---需求演进和产品迭代

    前言: 产品的形态是不断迭代的, 从粗糙到精致, 从简易到立体. 有了最初的技术积累和时间思考后, 终于明确了该游戏的方向. 我想说的是: 技术不是重点, 产品/用户体验才是核心议题. 结合朋友的游戏 ...

  4. H5版俄罗斯方块(1)---需求分析和目标创新

    前言: 俄罗斯方块和五子棋一样, 规则简单, 上手容易. 几乎每个开发者, 都会在其青春年华时, 签下"xx到此一游". 犹记得大一老师在布置大程作业的时候提过: "什么 ...

  5. 排名前10的H5、Js 3D游戏引擎和框架

    由于很多人都在用JavaScript.HTML5和WebGL技术创建基于浏览器的3D游戏,所有JavaScript 3D游戏引擎是一个人们主题.基于浏览器的游戏最棒的地方是平台独立,它们能在iOS.A ...

  6. Android版俄罗斯方块的实现

    学习Android的基本开发也有一段时间了,可是由于没有常常使用Android渐渐的也就忘记了. Android编程学的不深,不过为了对付逆向,可是有时还是会感到力不从心的.毕竟不是一个计算机专业毕业 ...

  7. JS国际化网站中英文切换(理论支持所有语言)应用于h5版APP

    网页框架类APP实现国际化参考文案一 参考:https://blog.csdn.net/CSDN_LQR/article/details/78026254 另外付有自己实现的方法 本人用于H5版的AP ...

  8. jQuery实践-网页版2048小游戏

    ▓▓▓▓▓▓ 大致介绍 看了一个实现网页版2048小游戏的视频,觉得能做出自己以前喜欢玩的小游戏很有意思便自己动手试了试,真正的验证了这句话-不要以为你以为的就是你以为的,看视频时觉得看懂了,会写了, ...

  9. html5 canvas简易版捕鱼达人游戏源码

    插件描述:html5利用canvas写的一个js版本的捕鱼,有积分统计,鱼可以全方位移动,炮会跟着鼠标移动,第一次打开需要鼠标移出背景图,再移入的时候就可以控制炮的转动,因为是用的mouseover触 ...

随机推荐

  1. 特征的SID表、M表、P表、Q表、X表、Y表、T表

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  2. 《BI那点儿事》数据流转换——数据转换

    数据转换执行类似于T-SQL中的函数CONVERT或CAST的功能.数据转换的编辑界面如图,选择需要转换的列,在DataType下拉列表中选择需要的数据类型.Output Alias栏内设置输出时使用 ...

  3. Flex 文本控件实现自定义复制粘贴

    由于添加了自定义右键菜单,导致Textinput控件默认的右键复制粘贴功能被屏蔽了.最后通过JS脚本实现这个功能,参考代码如下 <?xml version="1.0" enc ...

  4. javaScript对文字按照拼音排序

    <title>JavaScript对文字按照拼音排序</title> <SCRIPT type="text/javascript"> funct ...

  5. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

  6. java高薪之路__009_网络

    1. InetAddress类2. Socket: IP地址和端口号的结合,socket允许程序把网络连接当成一个流,数据在两个socket间通过IO传输, 通信的两端都要有socket. 主动发起通 ...

  7. Head First 设计模式--2 观察者模式 解耦

    观察者模式定义了对象之间一对多的依赖,这样依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新. 假如有这么一个项目,监控每天的天气状况WeatherData(温度,湿度,气压).有布告板 ...

  8. 函数指针与指针函数以及typedef

    c难于理解的是指针,其魅力之处也是指针,函数方法结构,化繁为简可以理解为:返回值 函数名(形参表),具体来说: 返回值:1.可以为空void 2.基本数据类型char short int long f ...

  9. ubuntu忘记密码怎么办

    刚安装了,ubuntu14.04,就想着,如果忘记登录密码,这可不好办,所以测试下开机,刚过bios显示画面,不停的点击,,键盘左边的shift键.(因为刚开始是采用按着不放的办法,结果不灵.所以我不 ...

  10. setInterval和setTimeout的区别

    setInterval会每隔指定的毫秒数后反复执行指定代码. setTimeout只会在指定的毫秒数后执行一次指定代码. setInterval的用法: // 创建(创建后即开始计时) var int ...