JS开发HTML5游戏《神奇的六边形》(二)

近期出现一款魔性的消除类HTML5游戏《神奇的六边形》,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏。

点击这里可进入游戏体验)

因内容太多,为方便大家阅读,所以分成部分来讲解。

本文为第二部分,主要包括:

6. 历史最高分显示

7. 当前分数显示

8. 绘制棋盘

9. 形状池设计与实现

若要一次性查看所有文档,也可点击这里

六. 历史最高分显示

对于DOM节点,其实就是个div,可以指定其样式,指定其样式表类名,也可以内嵌html元素。

  1. 在Scripts/ui下新建文件:BestScore.js,处理最高分数的显示逻辑,并将此逻辑脚本挂载到UIRoot/best节点上。

 /**
  * 绘制最高分数
  */
 var BestScore = qc.defineBehaviour('qc.tetris.BestScore', qc.Behaviour, function() {
     var self = this;
     self.runInEditor = true;
 }, {
 });
 
 /**
  * 初始化处理
  */
 BestScore.prototype.awake = function() {
     var self = this, div = self.gameObject.div;
     div.className = 'score_best';
     self.setScore(qc.Tetris.score.current);
 };
 
 /**
  * 更新最新的高分
  */
 BestScore.prototype.setScore = function(best) {
     this.gameObject.div.innerHTML = 'Best: ' + best;
 };

 

   本脚本可以在编辑器下运行(方便在编辑状态下查看效果),首先设置DOM的样式表类名为score_best,然后获取最高分数并显示之。

 2. 增加score_best样式表。打开Assets/css/style.css,添加样式表:

    

.score_best {
     font-weight: 60;
     font-size:30px;
     color: #ffffff; text-align: right;
 }

3.刷新下页面,查看效果:

4. 注意:更改样式表目前需要刷新页面才能看到效果。

 

七. 当前分数显示

1. 在Scripts/ui下新建文件:CurrentScore.js,处理当前分的显示逻辑,并将此逻辑脚本挂载到UIRoot/score节点上。

/**
  * 绘制当前分数
  */
 var CurrentScore = qc.defineBehaviour('qc.tetris.CurrentScore', qc.Behaviour, function() {
     var self = this;
     self.runInEditor = true;
 }, {
 });
 
 /**
  * 初始化处理
  */
 CurrentScore.prototype.awake = function() {
     var self = this, div = self.gameObject.div;
 
     div.className = 'score_current';
     self.setScore(qc.Tetris.score.current);
 };
 
 /**
  * 更新最新的分数
  */
 CurrentScore.prototype.setScore = function(best) {
     this.gameObject.div.innerHTML = '' + qc.Tetris.score.current;
 };

本脚本可以在编辑器下运行(方便在编辑状态下查看效果),首先设置DOM的样式表类名为score_current,然后获取当前分数并显示之。

 

2.增加score_current样式表。打开Assets/css/style.css,添加样式表:

.score_current{
     color: #ffffff;
     font-weight: 100;
     font-size:50px;
     text-align: center;
 }

3.刷新下页面,查看效果

 

八. 绘制棋盘

DOM的层次

DOM节点可以绘制在最底层(当工程背景设置为非透明时,将不可见),也可以绘制在最上层(在所有精灵、UIImage等节点之上)。
本棋盘放在最底层,因为棋盘上面还需要拖拽形状、显示可放入指示等。方法是:选中board节点,在Inspector中设置Pos=BACK:

开始绘制棋盘

    1. 棋盘中的每个格子都作为一个div元素,采用绝对定位。
      格子可能表现为7种图片形式(空时为灰色,其他为形状的对应颜色),这7种图片通过不同的样式类来区分。

    2. 打开Assets/css/style.css,加入如下几个样式表:

 .board { width: 61px; height: 67px; position: absolute; background-repeat: no-repeat; }
 .board_gray {
     background-image: url("../raw/gray.png");
 }
 .board_blue {
     background-image: url("../raw/blue.png");
 }
 .board_cyan {
     background-image: url("../raw/cyan.png");
 }
 .board_green {
     background-image: url("../raw/green.png");
 }
 .board_lightyellow {
     background-image: url("../raw/lightyellow.png");
 }
 .board_red {
     background-image: url("../raw/red.png");
 }
 .board_yellow {
     background-image: url("../raw/yellow.png");
 }

      这些样式表指明了棋盘格子中的图片

 

3. 编辑Tetris.js,加入IMAGES常量,指明在不同的值下面格子所使用的className

       

3. className
 window.Tetris = qc.Tetris = {
     // 棋盘的大小(半径)
     SIZE: 4,
 
     // 棋盘中,每个格子的宽度和高度
     BLOCK_W: 61,
     BLOCK_H: 67,
 
     // 所有的格子图片
     IMAGES: [
         'gray',        // 0
         'blue',        // 1
         'cyan',        // 2
         'green',       // 3
         'lightyellow', // 4
         'red',         // 5
         'yellow'       // 6
     ],
 
     // 所有的操作指令集合
     operation: {}
 };

 

4. 在Scripts/ui下创建脚本BoardUI.js,负责棋盘的绘制逻辑:

    

 
 /**
  * 管理棋盘的数据并绘制棋盘
  */
 var BoardUI = qc.defineBehaviour('qc.tetris.BoardUI', qc.Behaviour, function() {
     var self = this;
 
     /**
      * 棋盘的棋子元素
      */
     self.pieces = {};
 
     // 本脚本在编辑模式下可以运行
     self.runInEditor = true;
 }, {
     linePrefab: s.PREFAB
 });
 
 /**
  * 初始化处理
  */
 BoardUI.prototype.awake = function() {
     var self = this;
     self.reset();
 
     // 立刻重绘制下
     self.redraw();
 
     // 设置游戏画布的背景色
     self.gameObject.div.parentNode.style.background = '#1F1E1E';
 
     // 缓存图片,防止在图片切换过程中出现卡顿
     if (self.game.device.editor) return;
     qc.Tetris.IMAGES.forEach(function(c) {
         var div = document.createElement('div');
         div.className = 'board board_' + c;
         div.style.left = '-2000px';
         div.style.left = '-2000px';
         self.gameObject.div.appendChild(div);
     });
 };
 
 /**
  * 重绘棋盘
  * @private
  */
 BoardUI.prototype.redraw = function() {
     var self = this;
 
     // 绘制背景
     self.drawBackground();
 };
 
 /**
  * 绘制棋盘背景
  */
 BoardUI.prototype.drawBackground = function() {
     var self = this;
 
     for (var pos in self.pieces) {
         var div = self.pieces[pos];
         div.className = 'board board_' + qc.Tetris.IMAGES[qc.Tetris.board.data[pos].value];
     }
 };
 
 /**
  * 初始化棋盘
  */
 BoardUI.prototype.reset = function() {
     var self = this, o = self.gameObject;
 
     // 构建棋盘数据
     if (o.children.length === 0) {
         for (var pos in qc.Tetris.board.data) {
             var info = qc.Tetris.board.data[pos];
             var div = self.pieces[pos] = document.createElement('div');
             div.className = 'board board_' + qc.Tetris.IMAGES[info.value];
             div.style.left = Math.round(info.x + (o.width - qc.Tetris.BLOCK_W) / 2) + 'px';
             div.style.top = Math.round(info.y + (o.height - qc.Tetris.BLOCK_H) / 2) + 'px';
             o.div.appendChild(div);
         }
     }
     else {
         o.children.forEach(function(child) {
             self.pieces[child.name] = child;
         });
     }
 };

本脚本运行在编辑模式下,这样就可以实时看到棋盘。对本脚本做一些解释:

  • 属性pieces存放了下面所有的div元素(显示格子),key为其逻辑坐标

  • 初始化时,会将底下的所有格子创建出来,并设置上合适的位置(由于在Board.js中计算坐标时,是以棋盘中心为原点;但格子div是以棋盘的左上角为原点,因此代码中做了换算)

  • redraw方法中,以格子的值获取对应的className,对应的设置到格子div就可以了

  • 工程设置的背景是为透明的,因此在初始化时,顺便将游戏背景的颜色设置为:1F1E1E(最底层div的background-color属性)

  • 另外,初始时我们把所有格子的图片都加载进来(方法是创建个屏幕内不可见的div),这样在className切换过程中,就可以直接从本地缓存读取图片,避免加载图片影响体验


5. 将此脚本挂载到board节点上,保存场景并刷新页面,就可以看到效果了:

 

九. 形状池设计与实现

1. 本游戏中,总共有23种形状,每种类型的形状,其颜色是不同的。
在Scripts/logic下创建脚本Shapes.js,负责各种形状的配置、抽取等。        

var Shapes = qc.Tetris.Shapes = {
     // 所有可能的形状
     tiles: [
         // 1个点的
         {
             value: 1,
             list: [[[0, 0]]]
         },
 
         {
             value: 2,
             list: [
                 [[1, -1], [0, 0], [1, 0], [0, 1]],
                 [[0, 0],  [1, 0], [-1, 1], [0, 1]],
                 [[0, 0], [1, 0], [0, 1], [1, 1]]
             ]
         }, {
             value: 3,
             list: [
                 [[0, -1], [0, 0], [0, 1], [0, 2]],
                 [[0, 0], [1, -1], [-1, 1], [-2, 2]],
                 [[-1, 0], [0, 0], [1, 0], [2, 0]]
             ]
         }, {
             value: 4,
             list: [
                 [[0, 0], [0, 1], [0, -1], [-1, 0]],
                 [[0, 0], [0, -1], [1, -1], [-1, 1]],
                 [[0, 0], [0, 1], [0, -1], [1, 0]],
                 [[0, 0], [1, 0], [-1, 0], [1, -1]],
                 [[0, 0], [1, 0], [-1, 0], [-1, 1]]
             ]
         }, {
             value: 5,
             list: [
                 [[0, 0], [0, 1], [0, -1], [1, -1]],
                 [[0, 0], [1, -1], [-1, 1], [-1, 0]],
                 [[0, 0], [1, -1], [-1, 1], [1, 0]],
                 [[0, 0], [1, 0], [-1, 0], [0, -1]],
                 [[0, 0], [1, 0], [-1, 0], [0, 1]]
             ]
         }, {
             value: 6,
             list: [
                 [[0, -1], [-1, 0], [-1, 1], [0, 1]],
                 [[-1, 0], [0, -1], [1, -1], [1, 0]],
                 [[0, -1], [1, -1], [1, 0], [0, 1]],
                 [[-1, 1], [0, 1], [1, 0], [1, -1]],
                 [[-1, 0], [-1, 1], [0, -1], [1, -1]],
                 [[-1, 0], [-1, 1], [0, 1], [1, 0]]
             ]
         }
     ],
 
     /**
      * 重新开始的逻辑
      */
     restart: function() {
         qc.Tetris.Shapes.pool = [];
         for (var i = 0; i < 3; i++) {
             qc.Tetris.Shapes.pool.push(qc.Tetris.Shapes.random());
         }
     },
 
     /**
      * 随机抽取一个形状
      */
     random: function() {
         // 先抽取分类
         var math = qc.Tetris.game.math;
         var shapes = Shapes.tiles;
         var shape = shapes[math.random(0, shapes.length - 1)];
 
         // 再抽子类
         var list = shape.list[math.random(0, shape.list.length - 1)];
         return {
             color: shape.color,
             value: shape.value,
             list: list
         };
     },
 
     /**
      * 当前的pool数据
      */
     pool: []
 };

代码说明如下:

  • value指明了格子应该使用哪个图片

  • list包含了多个形状,形状由数组组成,每个元素指明了逻辑坐标

  • pool属性存储了当前屏幕上3个形状的数据信息


2. 修改Tetris.js的qc.initGame方法,最后面添加3个形状的初始化逻辑:  

qc.initGame = function(game) {
     // 将游戏实例记录下来,便于访问
     Tetris.game = game;
 
     // 帧率显示为60帧(满帧)
     game.time.frameRate = 60;
 
     // 初始化分数信息
     Tetris.score = new qc.Tetris.Score();
 
     // 构建棋盘对象
     Tetris.board = new qc.Tetris.Board();
 
     // 3个形状
     qc.Tetris.Shapes.restart();
 };

 

上一篇:JS开发HTML5游戏《神奇的六边形》(一) 

下一篇:JS开发HTML5游戏《神奇的六边形》(三)


转载于:https://my.oschina.net/u/2510595/blog/530164

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值