GC DevKit 快速入门 -- 游戏概览(二)
接上节  http://www.cnblogs.com/hangxin1940/archive/2013/04/11/3011555.html
## 创建屏幕视图
当导入屏幕视图类后,我们会在`initUI`函数中对它进行实例化,这时,游戏引擎就准备就绪了。
    var titlescreen = new TitleScreen(),
        gamescreen = new GameScreen();
之后的内容会详细介绍屏幕视图的构造的。
当游戏引擎将场景创建好后,它会被存储在 `GC.app.view` 的根节点。任何 `View` 只要附加到根节点上,都会被呈现到屏幕上,而根节点视图有些特殊,它是 `ui.StackView` 的实例,`ui.StackView` 又是 `ui.View` 的子类, 它另外的功能就是压入和弹出视图栈,并且做相应的转换。
这里还有一些声音相关的代码,我们将会在结尾看到详细的说明。`soundcontroller`模块会返回一个 `AudioManager` 的单例对象,当我们转到游戏视图时,它会播放关卡音乐。
## 事件管理
在事件处理代码中,我们在两个屏幕视图中监听了游戏开始与结束的事件,并且管理 `StackView`
    titlescreen.on('titlescreen:start', function () {
      //...
      GC.app.view.push(gamescreen);
      gamescreen.emit('app:start');
    });
    gamescreen.on('gamescreen:end', function () {
      //...
      GC.app.view.pop();
    });
在收到游戏开始事件后,游戏视图会被压入`rootView`视图栈中,这里没有必要将已存在与试图栈中的标题视图删除,因为压入栈顶后这个游戏视图已经可见。默认情况下,压入另一个视图进入视图栈时会有一个横向滚动的动画,当然也可以关闭动画。下面我们通过标题视图来看看整个程序的事件流程的细节。
## 游戏等待状态: `TitleScreen.js`
标题视图是 `TitleScreen`类 的一个实例,在 `./src/TitleScreen.js` 文件中定义,在 `./src/Application.js` 中被实例化一次并加入到根书图,在整个生命周期中存在。
## 视图剖析
`TitleScreen`类的视图结构相对来说是比较简单的。它由一个图片来填充背景,以及被放置在背景中央并且看不见的一个视图,它被作为`Play`按钮。这个按钮将检测输入事件,然后向主程序发送一个事件并通知用户准备好开始游戏。下面来分析这个类:
    import ui.View;
    import ui.ImageView;
    exports = Class(ui.ImageView, function (supr) {
      this.init = function (opts) {
        opts = merge(opts, {
          x: 0,
          y: 0,
          image: "resources/images/title_screen.png"
        });
        supr(this, 'init', [opts]);
        var startbutton = new ui.View({
          superview: this,
          x: 58,
          y: 313,
          width: 200,
          height: 100
        });
        startbutton.on('InputSelect', bind(this, function () {
          this.emit('titlescreen:start');
        }));
      };
    });
首先,需要导入一下两个模块:
    import ui.View;
    import ui.ImageView;
`ui.View`类被用作一个基础的显示对象将元素渲染在屏幕上,要做到这点,一个视图必须得附加到游戏的场景中(视图树中的节点)。 视图具有样式属性,用来控制如何被渲染到屏幕上,并且可以触发和订阅事件,也可以增加/删除子视图或父视图。
`ui.ImageView` 类是 `ui.View`的子类,不但`ui.View`继承了父类的属性,而且还可以在视图中设置图像。
现在我们已经导入了所依赖的模块,现在可以定义我们的 `TitleScreen` 类。
    exports = Class(ui.ImageView, function (supr) {
      this.init = function (opts) {
        opts = merge(opts, {
          //...
        });
        supr(this, 'init', [opts]);
      };
    });
每一个类中定义的`init`方法都会在实例化的时候被执行,`merge`函数用来合并属性(犹如两个集合选取合集),用来将它合并的属性传递给构造函数。这之后,调用父类的`init`方法,并传入合并后的属性对象。
下面是完整的`init`方法:
    this.init = function (opts) {
      opts = merge(opts, {
        x: 0,
        y: 0,
        image: "resources/images/title_screen.png"
      });
      supr(this, 'init', [opts]);
      this.build();
    };
`title_screen.png`将会作为 `ui.ImageView`类的`image`属性加载。`supr`函数将当前对象以参数形式传递给父类来进行初始化。这三个参数分别是当前对象,以及将要调用的当前对象的方法名,还有包含当前对象属性的数组。
## `Play`按钮
还记得在`init`结束时调用的这个`build`函数么:
    this.build = function() {
      var startbutton = new ui.View({
        superview: this,
        x: 58,
        y: 313,
        width: 200,
        height: 100
      });
      startbutton.on('InputSelect', bind(this, function () {
        this.emit('titlescreen:start');
      }));
    };
在标题视图中,我们创建了一个不可见的开始按钮,它位于背景图的中央,这个按钮视图通过`superview`属性附加于当前类,然后通过`InputSelect`监听器来捕获点击与触摸事件,最后,我们出发一个事件用以通知标题视图已经运行。
## 事件流程
我们目前只看到如何捕获用户的输入并传递给主程序,下面来介绍整个游戏的事件流程,之后会看到其余的事件

程序成功运行,并装载好游戏后,用户首先会进入标题视图。单击开始按钮后`titlescreen:start`事件会被发出,并被上层的程序捕获,在那里,游戏视图将会加载,之后,用户开完游戏,直到 `gamescreen:end` 事件发出,上层代码删除游戏试图,最终又回到标题视图。
## 进行游戏: `GameScreen.js`
`GameScreen`类定义在 `./src/GameScreen.js` 文件,它也是项目中最长的代码了。其中大部分代码都是在构建视图结构,我们在前面已经了解其中的一些细节。除了建立子视图与游戏资源,它还定义了游戏逻辑相关的函数以及游戏结束时显示得分的方法。后面我们将会看到比较重要的一些代码。
## 设置屏幕
与之前的代码一样,首先会导入一些模块
    import animate;
    import device;
    import ui.View;
    import ui.ImageView;
    import ui.TextView;
    import src.MoleHill as MoleHill;
之前已经讲过 `ui.View`, `ui.ImageView`, 与 `device`,现在主要看看其他的模块。
`ui.TextView`的作用,应该很容易猜到,它主要是显示文字,除了常规试图的样式之外,还可以对它进行字号与颜色的设置。
`animate`模块主要用来为视图、对象以及样式生成动画,它所生成的是`补间动画`,也就在移动位置之间进行插值,以生成动画。更重要的是,它针对原生设备进行了专门的优化,我们应该在游戏中善加利用此模块,而不是手动的进行额外的计算。之后的代码中我们会遇到它,到时候在进行详细的说明。
最后的一个模块导入语句比较有意思:
    import src.MoleHill as MoleHill;
`src.MoleHill`类引用了工程目录中的`./src/MoleHill.js` 文件。除了Devkit引擎的模块与类之外,我们还可以自己定义,并且被项目导入并引用。`as`语句用来给模块或类起个别名,方便我们更加方便的引用,不必输入繁长的路径。
同`TitleScreen`类相同,`GameScreen`也只在`Application.js`中被实例化一次,`init`函数用来定义尺寸以进行屏幕适配,并且将绿草地填充为背景,通过`supr`函数为父类传递构造属性。
    this.init = function (opts) {
      opts = merge(opts, {
        x: 0,
        y: 0,
        width: 320,
        height: 480,
        backgroundColor: '#37B34A'
      });
      supr(this, 'init', [opts]);
      this.build();
    };
    this.build = function() {
      this.on('app:start', bind(this, start_game_flow));
      this._scoreboard = new ui.TextView({
        superview: this,
        x: 0,
        y: 15,
        width: device.width,
        height: 50,
        autoSize: false,
        size: 38,
        verticalAlign: 'middle',
        textAlign: 'center',
        multiline: false,
        color: '#fff'
      });
      var x_offset = 5;
      var y_offset = 160;
      var y_pad = 25;
      var layout = [[1, 0, 1], [0, 1, 0], [1, 0, 1]];
      this._molehills = [];
      //循环,布局网格,先是行然后是列
      for (var row = 0, len = layout.length; row < len; row++) {
        for (var col = 0; col < len; col++) {
            //如果是1,则创建一个鼹鼠
          if (layout[row][col] !== 0) {
            var molehill = new MoleHill();
            molehill.style.x = x_offset + col * molehill.style.width;
            molehill.style.y = y_offset + row * (molehill.style.height + y_pad);
            this.addSubview(molehill);
            this._molehills.push(molehill);
            //打到鼹鼠时,更新得分
            molehill.on('molehill:hit', bind(this, function () {
              if (game_on) {
                score = score + hit_value;
                this._scoreboard.setText(score.toString());
              }
            }));
          }
        }
      }
      this._countdown = new ui.TextView({
        superview: this._scoreboard,
        visible: false,
        x: 260,
        y: -5,
        width: 50,
        height: 50,
        size: 24,
        color: '#fff',
        opacity: 0.7
      });
    };
`build`函数的代码比之前看到过的稍微有点长,但是它很容易看懂。首先,在启动游戏时监听`app:start`事件,`app:start`是游戏的根所派发的事件,当开始按钮被处理后,会执行`start_game_flow`函数。
定义好用户得分牌后,会在屏幕上定义鼹鼠洞网格以及定义它们的位置与大小,这里创建了一定数量的`MoleHill`对象,将它们作为子视图附加到`GameScreen`对象,并且为每一个`MoleHill`对象都注册了敲打事件用以更新用户得分。
`MoleHill`类定义在工程中的`./src/MoleHill.js`文件,稍后会说到。基本上它是一个图像的集合,用来生成鼹鼠出洞,敲头等复合图像,以及动画相关的代码。
最后,创建一个倒计时文本,作为得分牌的子视图。
GC DevKit 快速入门 -- 游戏概览(三)  http://www.cnblogs.com/hangxin1940/archive/2013/04/13/3017640.html 
                    
                
                
            
        
浙公网安备 33010602011771号