文档章节

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

青瓷引擎
 青瓷引擎
发布于 2015/11/12 21:16
字数 1963
阅读 135
收藏 0

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

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

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

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

1. 功能分析

2. 创建工程与场景

3. 玩家分数管理

4. 棋盘设计与实现

5. 屏幕布局

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

 

功能分析

首先分析游戏的功能点、算法和数据,然后依此制订代码组织结构。如下图:

主要功能点

  1. 棋盘的数据结构与绘制

  2. 3个形状的生成

  3. 形状拖拽填入棋盘

  4. 行消除判定与死亡判定

  5. 各种表现,例如消除动画、加分动画等

代码结构

将游戏逻辑(例如棋盘数据结构、死亡判定等)和界面逻辑分开,分别置于logic和ui界面。所有的UI界面交给UIManager脚本统一维护管理。

二. 创建工程与场景

创建工程Tetris和空的主场景Main,设置如下:

本工程中,画布背景(background)设置为透明

游戏入口与游戏初始化

在Scripts目录下创建文件:Tetris.js。代码如下:

/**
     * 游戏入口
     */
    window.Tetris = qc.Tetris = {
        // 所有的操作指令集合
        operation: {}
    };
 
    // 游戏逻辑初始化
    qc.initGame = function(game) {
        // 将游戏实例记录下来,便于访问
        Tetris.game = game;
 
        // 帧率显示为60帧(满帧)
        game.time.frameRate = 60;
    };


设置此脚本为入口脚本:

此脚本首先定义了名字空间,将全局的数据都记录在qc.Tetris。

游戏入口中,记录了game的实例并将帧率限定为60帧(默认在手机下为30帧)



三. 玩家分数管理

1. 创建脚本:Scripts/logic/Score.js:

/**
  * 维护分数信息
  */
 var Score = qc.Tetris.Score = function() {
     var self = this;
     self._current = 0;
     self._best = 0;
 
     // 将本地数据读取出来
     var game = qc.Tetris.game;
     var current = game.storage.get('current'),
         best = game.storage.get('best');
     if (current) self._current = current;    
     if (best) self._best = best;
 };
 Score.prototype = {};
 Score.prototype.constructor = Score;
 
 Object.defineProperties(Score.prototype, {
     current: {
         get: function() { return this._current; },
         set: function(v) {
             this._current = v;
             if (this.best < v) this.best = v;
         }
     },
 
     best: {
         get: function() { return this._best; },
         set: function(v) {
             this._best = v;
             var storage = qc.Tetris.game.storage;
             storage.set('best', v);
             storage.save();
         }
     }
 });

2. 实例化Score类
打开Tetris.js脚本,在initGame方法中,加入代码:

qc.initGame = function(game) {
     // 将游戏实例记录下来,便于访问
     Tetris.game = game;
 
     // 帧率显示为60帧(满帧)
     game.time.frameRate = 60;
 
     // 初始化分数信息
     Tetris.score = new qc.Tetris.Score();
 };


四. 棋盘设计与实现

棋盘为一边长为5的正六变形,为了方便计算,我们如下设定棋盘的坐标系(下文称为:格子逻辑坐标):

原点在六边形中心点,半径为4。

  1. 修改Tetris.js文件,增加棋盘的配置信息:

    window.Tetris = qc.Tetris = {
         // 棋盘的大小(半径)
         SIZE: 4,
     
         // 棋盘中,每个格子的宽度和高度
         BLOCK_W: 61,
         BLOCK_H: 67,
     
         // 所有的操作指令集合
         operation: {}
     };

    棋盘格子的大小 = 格子图片的大小,后续导入资源后可以看到其大小为61*67。

  2. 在Scripts/logic下创建文件Board.js,维护棋盘的数据,代码如下:

     var Board = qc.Tetris.Board = function() {
         var self = this,
             size = qc.Tetris.SIZE,
             len = qc.Tetris.BLOCK_H;
     
         // 构建用来转换格子坐标的矩阵
         var m = self.m = new qc.Matrix();
         m.a = len;
         m.c = len / 2;
         m.d = len * (Math.sqrt(3) / 2);
     
         // 初始化棋盘数据
         self.data = {};
         for (var i = -size; i <= size; i++) {
             for (var j = -size; j <= size; j++) {
                 // 这些格子落在六边形外,忽略掉
                 if (i * j > 0 && Math.abs(i + j) > size) continue;
                 if (i * j < 0 && (Math.abs(i) > size || Math.abs(j) > size)) continue;
     
                 // 计算格子的坐标和对应屏幕上的偏移
                 var pos = Tetris.makePos(i, j);
                 var pt = self.toWorld(new qc.Point(i, j));
                 self.data[pos] = {
                     value: 0,
                     x: pt.x,
                     y: pt.y
                 };
             }
         }
     };
     Board.prototype = {};
     Board.prototype.constructor = Board;
     
     Object.defineProperties(Board.prototype, {
         /**
          * @property {boolean} die - 当前是否已经死亡了
          * @readonly
          */ 
         die: {
             get: function() {
                 // TODO: 等待实现
             }
         }
     });
     
     /**
      * 清空棋盘
      */
     Board.prototype.clear = function() {
         for (var pos in this.data) {
             this.data[pos].value = 0;
         }
     };
     
     /**
      * 重新开始游戏
      */
     Board.prototype.restart = function() {
         this.clear();
     };
     
     // 判定形状可以放进来不
     // pos: 目标逻辑坐标
     // list: 形状的信息
     Board.prototype.checkPutIn = function(pos, list) {
         // TODO: 等待实现
     };
     
     // 把某个形状放进来
     Board.prototype.putIn = function(pos, list, value) {
         // TODO: 等待实现
     };
     
     // 根据格子的逻辑坐标,算出所在的屏幕坐标
     // distance: 两个格子中心点之间的距离
     Board.prototype.toWorld = function(p, distance) {
         if (!distance)
             return this.m.apply(p);
     
         var m = new qc.Matrix();
         m.a = distance;
         m.c = distance * 0.5;
         m.d = distance * (Math.sqrt(3) * 0.5);
         return m.apply(p);
     };
     
     // 根据格子的屏幕坐标,反算格子的逻辑坐标
     Board.prototype.toLocal = function(p) {
         return this.m.applyInverse(p);
     };


  3. 修改Tetris.js,在qc.initGame方法中,实例化本对象:


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

    同时,在本文件中实现两个函数:makePos和readPos:

    // 构建坐标
     window.Tetris.makePos = function(x, y) {
         return x + '_' + y;
     };
     
     // 获取坐标
     window.Tetris.readPos = function(pos) {
         var arr = pos.split('_');
         return new qc.Point(arr[0]*1, arr[1]*1);
     };


五. 屏幕布局

在美术设计时,以640*960分辨率(iPhone4)进行设计,其他分辨率的屏幕需要自适应。如下图:

  • 整个界面分为标题栏(Top)、棋盘(Board)、3个形状(Shape)

    • Top:高度在iPhone4上为130。这里有两个信息:当前分数与历史最高分数

    • Board:棋盘,其大小为600*580

    • Shape:3个形状,大小为600*230,距离底部20

  • 自适应方案:

    • 以 640*960为基准,等比缩放,确保所有内容都能全部显示

    • 当分辨率比较瘦长时(即Height/Width > 960/640)时,Board和Shape保持和底部位置不变(方便单手操作)。Top高度自动增加

    • 当分辨率比较宽时(即Height/Width < 960/640)时,Board和Shape保持居中,两边留白

导入资源

  1. 新建文件夹:Assets/atlas/ui@atlas ,将以下文件拖入并打包图集(图片请在示例工程中查看)
    blue.png、cyan.png、gray.png、green.png、lightyellow.png、red.png、shadow.png、white.png、yellow.png
    darkblue.png、darkcyan.png、darkgreen.png、darklightyellow.png、darkred.png、darkyellow.png等,具体请参看示例工程
    格子在没有数据时,显示gray.png。其他形状的格子颜色,有6种(blue、cyan、green、lightyellow、yellow、red)

  2. 将以下文件拖入文件夹Assets/raw(raw目录下的资源都不会被打包,例如图片直接原样保留,适用于css样式表指定资源)
    blue.png、cyan.png、gray.png、green.png、lightyellow.png、red.png、yellow.png等,具体请参看示例工程,各图片的用途在后续中会说明。

界面布局

      1. 创建UIRoot,并设置Reference Resolution(分辨率)为 640*960,Manual Type为Expand

         

         简单的理解:设置了以后,就可以认为屏幕的宽度>=640,高度>=960

2. 创建棋盘。棋盘大部分情况下是“静态”的,只是在有新的形状放入时才会变化。如果棋盘的每个格子作为UIImage进行贴图,则每帧都需要重绘几十个格子图片,对渲染效率会有所影响。这里我们适用DOM方案,里面每个格子使用div进行绘制。因此创建一个DOM节点,设置其大小为:600*580,同时由于棋盘距离底部的位置固定,因此在布局上:水平居中、垂直距离底部250,自身中心点在底部中心位置。如下图:

3. 添加一个Node节点,挂载3个形状。Node大小为 600*230,距离底部20。如下图:

4. 创建DOM节点显示历史最高分(不常变化,因此不用UIText,使用Dom更高效)。本节点大小为200*60,距离屏幕右边20,顶部20:

5. 创建DOM节点显示当前分(不常变化,因此不用UIText,使用Dom更高效)。本节点大小为200*80,水平居中,顶部顶部29:


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



© 著作权归作者所有

青瓷引擎
粉丝 3
博文 10
码字总数 13265
作品 1
厦门
私信 提问
HTML5游戏开发高级教程 | Lynda教程 中文字幕

HTML5游戏开发高级教程 | Lynda教程 中文字幕 Advanced HTML5 Game Development 课程ID: 597988 时长: 2.3小时 所属类别:Html 全部游戏开发课程 了解如何使用HTML5创建交互式,动态和丰富多彩...

zwsub
2018/08/04
0
0
再来 10 个新鲜的 HTML5 教程

HTML5 火吗?看看 oschina 三天两头的 xx 个 xxx 就知道了。本文为你推荐最新的 10 个 HTML5 相关的教程,或许能启发你项目中的思路。 1. HTML5 canvas – Creating own Paint program Canva...

红薯
2011/11/15
3.9K
4
好程序员技术分享html5和JavaScript的区别

好程序员技术分享html5和JavaScript的区别,HTML5广义上讲是前端开发学科的代名词,包含HTML5、CSS3及JavaScript三个重要的部分,是运行在浏览器上应用的统称。如PC端网站、管理系统、手机网...

好程序员IT
04/26
17
0
分享几个令人震撼的JS和HTML5游戏

或许你对网页游戏仅仅停留在Flash的时代,认为只有Flash才能做出非常绚丽的游戏特效。那么今天就打破大家的这个观念,一起来看看用Javascript和HTML5实现的网页游戏,这些游戏个人认为做得已...

tp_wire
2012/06/27
24.6K
20
分享一个帮助你快速构建HTML5游戏的javascript类库 - CreateJS

日期:2012-4-23 来源:GBin1.com HTML5是一个非常重要的web标准,针对HTML5衍生了很多的富客户端javascript开发类库,今天这里我们将介绍一个非常棒的帮助你开发基于HTML5游戏的类库 - crea...

gbin1
2012/04/25
287
0

没有更多内容

加载失败,请刷新页面

加载更多

java通过ServerSocket与Socket实现通信

首先说一下ServerSocket与Socket. 1.ServerSocket ServerSocket是用来监听客户端Socket连接的类,如果没有连接会一直处于等待状态. ServetSocket有三个构造方法: (1) ServerSocket(int port);...

Blueeeeeee
今天
6
0
用 Sphinx 搭建博客时,如何自定义插件?

之前有不少同学看过我的个人博客(http://python-online.cn),也根据我写的教程完成了自己个人站点的搭建。 点此:使用 Python 30分钟 教你快速搭建一个博客 为防有的同学不清楚 Sphinx ,这...

王炳明
昨天
5
0
黑客之道-40本书籍助你快速入门黑客技术免费下载

场景 黑客是一个中文词语,皆源自英文hacker,随着灰鸽子的出现,灰鸽子成为了很多假借黑客名义控制他人电脑的黑客技术,于是出现了“骇客”与"黑客"分家。2012年电影频道节目中心出品的电影...

badaoliumang
昨天
16
0
很遗憾,没有一篇文章能讲清楚线程的生命周期!

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本。 简介 大家都知道线程是有生命周期,但是彤哥可以认真负责地告诉你网上几乎没有一篇文章讲得是完全正确的。 ...

彤哥读源码
昨天
18
0
jquery--DOM操作基础

本文转载于:专业的前端网站➭jquery--DOM操作基础 元素的访问 元素属性操作 获取:attr(name);$("#my").attr("src"); 设置:attr(name,value);$("#myImg").attr("src","images/1.jpg"); ......

前端老手
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部