游戏开发论坛

 找回密码
 立即注册
搜索
查看: 20712|回复: 1

H5版俄罗斯方块游戏开发:需求分析和框架实现

[复制链接]

1万

主题

1万

帖子

3万

积分

论坛元老

Rank: 8Rank: 8

积分
36572
发表于 2016-3-22 14:57:02 | 显示全部楼层 |阅读模式
QQ截图20160322145518.png

  GameRes游资网授权发布 文/mumuxinfei

  前言:

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

  这次想借学Html5的机会,重温下俄罗斯方块。当然不是单一的实现,希望有所创新,在可玩性/趣味性上有所突破。

  调研

  在4399这个游戏平台上,选择了几款俄罗斯方块相关的游戏进行试玩。大致总结了下各类俄罗斯方块的新意。


  一、需求分析与目标创新

  引入场景

1.png

  码头俄罗斯方块:借用大型运输船作为游戏主场景,而傍边的卡车作为下个方块的提供者。画风让人舒服,游戏忠于原版算是中规中矩。

  方块组成和消除规则创新

2.png

  烟火俄罗斯方块:方块由六边形组成,消除不在拘泥于行,而在同色的连接区域。

  彩泡俄罗斯方块:由圆来代替方块,消除不在拘泥于行,而在同色的连接区域。

  结合物理引擎

3.png

  外星俄罗斯方块:借助7种形状的方块,来堆一个最高的塔(类似于搭积木)。

  大部分游戏都在图形和消除效果上做足个功夫,为了提高用户的粘度,有的引入排行版等功能。总之只有变化,才能在同质化的产品中脱颖而出。

  初步设想:

  上述的同类产品,好归好。但单机游戏缺少变化容易让人觉得单调。

  由此想参考QQ游戏的火拼俄罗斯的实现。

4.png

  多人PK对战, 引入攻击/防守道具,最终决出胜负。游戏激烈,且充满偶然性。

  俗话说:“他山之石,即可攻玉”。取其精华,多人PK和引入道具,都是很好的点。

  1)两人PK对战,当然这边不联网,采用机器人AI的方式实现。

5.png

  游戏AI分等级,用户可从易到难依次挑战。

  2)引入道具,使得游戏更加刺激和紧凑。

  减行道具:消去本方的行数。

  加行道具:增加对方的行数。

  其余类型的道具,后续再添加。

  3)引入排名,若获胜,则把当前局的得分计入排行榜

  游戏规则可简单描述如下:有限的时间内,用户玩家得分超过游戏AI,即表示玩家获胜。

  小结:

  单机游戏没有网络,也意味着社交元素的缺失。如果能尝试去弥补下,比如引入排行榜,引入社会化分享组件,都是提高游戏用户黏性的好办法。

  这部分讲述了俄罗斯方块的初步目标,下一步将简单实现一个可玩的俄罗斯方块版本。

  二、游戏的基本框架和实现

  演示&下载:

  初步版本效果较为简陋,其大致效果如图所示:

6.gif

  其代码下载地址为:http://pan。baidu。com/s/1dDm4B0P

  该版本参考了不少cnblogs网友的同类版本,尤其是博主"奕秋"的"Canvas俄罗斯方块"。再次表示感谢。

  模型和构建:


  方块抽象和建模

  俄罗斯方块由7种方块组成,各有特点。当然也不能忽视方块的旋转特性,这边采用了"Arika Rotation System"体系,其具体的旋转变化如下所示:

7.png

  因此对方块进行抽象,构建一个基类Shape,然后7种形状继承于基类Shape来构建。

  1. function Shape(x, y, idx, color, shapes) {
  2.   this.x = x;
  3.   this.y = y;
  4.   this.idx = idx;
  5.   this.color = color;
  6.   this.shapes = shapes;
  7. };
复制代码

  注: 这边的属性依次为x,y坐标,颜色,变换形状数组及索引标识。

  由于JavaScript没有所谓类和继承的概念,需要依靠原型链来模拟构建,这边我们采用寄生组合式继承方式来实现。以L型方块为例。

  1. // *) L型方块的转换变换矩阵
  2. LShape.SHAPES = [
  3.   [
  4.     [0, 1, 0, 0],
  5.     [0, 1, 0, 0],
  6.     [0, 1, 1, 0],
  7.     [0, 0, 0, 0]
  8.   ],
  9.   [
  10.     [0, 0, 0, 0],
  11.     [1, 1, 1, 0],
  12.     [1, 0, 0, 0],
  13.     [0, 0, 0, 0]
  14.   ],
  15.   [
  16.     [0, 1, 1, 0],
  17.     [0, 0, 1, 0],
  18.     [0, 0, 1, 0],
  19.     [0, 0, 0, 0]
  20.   ],
  21.   [
  22.     [0, 0, 0, 0],
  23.     [0, 0, 1, 0],
  24.     [1, 1, 1, 0],
  25.     [0, 0, 0, 0]
  26.   ]
  27. ];
  28. function LShape(x, y, idx, color) {
  29.   // *) 继承父类的属性变量
  30.   Shape.call(this, x, y, idx, color, LShape.SHAPES);
  31. };
  32. // *) 继承父类的抽象方法
  33. LShape.prototype = new Shape();
复制代码

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

  1. function createShape() {
  2.     var shapeTypes = [LShape, JShape, IShape, OShape, TShape, SShape, ZShape];
  3.     var colorTypes = ["red", "green", "blue", "pink"]
  4.     var shapeIdx = Math.floor(Math.random() * 100) % shapeTypes.length;
  5.     var shapePos = Math.floor(Math.random() * 100) % 4;
  6.     var colorIdx = Math.floor(Math.random() * 100) % colorTypes.length;
  7.     return new shapeTypes[shapeIdx](4, 0, shapePos, colorTypes[colorIdx]);
  8. }
复制代码

  按键事件的注册和处理

  俄罗斯方块需要对向左,向右,变换的按键事件作出及时的反应外,还需要对向下的长按键进行处理。

  对于向左,向右,变换的按键事件,简单注册按键事件即可。

  1. document.body.addEventListener("keydown", function(e) {
  2.   gameEnv.keydown(e.keyCode);
  3.   switch(e.keyCode) {
  4.   case 37:
  5.     gameScene.keydown(ActionType.ACTION_LEFT);
  6.     break;
  7.   case 38:
  8.     gameScene.keydown(ActionType.ACTION_CHANGE);
  9.     break;
  10.   case 39:
  11.     gameScene.keydown(ActionType.ACTION_RIGHT);
  12.     break;
  13.   case 40:
  14.     gameScene.keydown(ActionType.ACTION_DOWN);
  15.     break;
  16.   }
  17. });
复制代码

  但对于向下的长按键处理,除了监听键盘事件外,还需要在游戏主逻辑循环中,添加轮询该按键状态。

  因此我们引入一个按键数组,用于记录按键的状态。

  1. function GameEnv() {
  2.   this.presskeys = new Array(256);
  3. }
  4. GameEnv.prototype.reset = function() {
  5.   for ( var i = 0; i < this.presskeys.length; i++ ) {
  6.     this.presskeys[i] = false;
  7.   }
  8. }
  9. GameEnv.prototype.keyup = function(keyCode){
  10.   if ( keyCode >= 0 && keyCode < 256 ) {
  11.     this.presskeys[keyCode] = false;
  12.   }
  13. };
  14. GameEnv.prototype.keydown = function(keyCode) {
  15.   if ( keyCode >= 0 && keyCode < 256 ) {
  16.     this.presskeys[keyCode] = true;
  17.   }
  18. };
复制代码

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

  1. var fps = 30 || 0;
  2. setInterval(gameLogic, fps);

  3. function gameLogic() {
  4.   gameScene.updateGame();
  5.   gameScene.renderGame(ctx);
  6. }
复制代码

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

  总结:

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

  相关阅读:对弈类游戏的人工智能设计(1):评估函数+博弈树算法

4

主题

11

帖子

125

积分

注册会员

Rank: 2

积分
125
发表于 2016-3-28 16:53:44 | 显示全部楼层
好详细。谢谢!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2024-5-20 09:02

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表