首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

HTML5 2D 游戏开发 实现 Sprite 行为(2)跑步小人行为

HTML5 2D 游戏开发 实现 Sprite 行为(2)跑步小人行为

跑步小人行为Snail Bait 的跑步小人有 4 种行为,如表 2 所示:
表 2. 跑步小人的行为行为说明runBehavior循环显示 sprite 表单中的跑步小人,以产生跑步小人正在跑动的效果jumpBehavior控制跳跃的所有方面:上升、下降和着地fallBehavior控制跑步小人在下落时的垂直移动runnerCollideBehavior检测跑步小人与其他 sprite 之间的碰撞并做出反应
我通过一个对象数组来指定跑步小人的行为,并将这个数组传递给 Sprite 构造函数,如清单 1 所示:
清单 1. 创建 SnailBait 的跑步小人
1
2
3
4
5
6
7
8
9
10
11
12
var SnailBait = function () {
   ...

   this.runner = new Sprite('runner',              // Type
                            this.runnerArtist,    //  Artist
                            [this.runBehavior,  //  Behaviors
                          this.jumpBehavior,
                          this.fallBehavior,
                          this.runnerCollideBehavior

                           ]);
};




跑步小人的行为如清单 2 中所示,其中删除了实现细节:
清单 2. 跑步小人行为对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var SnailBait = function () {
   ...

   this.runBehavior = {
      execute: function(sprite, time, fps) { // sprite is the runner
         ...
      }
   };
   this.jumpBehavior = {
      execute: function(sprite, time, fps) { // sprite is the runner
         ...
      }
   };
   this.fallBehavior = {
      execute: function(sprite, time, fps) { // sprite is the runner
         ...
      }
   };
   this.runnerCollideBehavior = {
      execute: function(sprite, time, fps) { // sprite is the runner
         ...
      }
   };
};




在每个动画帧中,Snail Bait 都会迭代它的 sprite 数组,调用每个 sprite 的 update() 方法,如清单 3 所示:
清单 3. 执行行为
1
2
3
4
5
6
7
8
9
10
11
Sprite.prototype = {
   update: function (time, fps) {
      for (var i=0; i < this.behaviors.length; ++i) {
         if (this.behaviors === undefined) { // You never know
            return;
         }

         this.behaviors.execute(this, time, fps);
      }
   }
};




Sprite.update() 方法迭代了 sprite 的行为,调用每个行为的 execute() 方法。Snail Bait 持续(每个动画帧一次)调用与所有可视 sprite 有关联的行为。因此,一个行为的 execute() 方法与其他大多数方法可能有所不同,大多数方法的调用频率相对较低;而每个 execute() 方法就像一个不停运转的小型马达。
现在您已经大致理解了 sprite 和行为,我将分别介绍它们的具体实现。
Strategy 设计模式行为是 Strategy 设计模式的一种实现,Strategy 设计模式将算法封装在对象中(参阅 )。在运行时,您可混搭这些算法,将一个行为集合分配给一个 sprite。行为比将算法直接硬编码到各个 sprite 中更灵活。

跑动Snail Bait 通过两种操作来让跑步小人看起来正在跑动。首先,正如本系列第二篇文章中  一节所述,游戏不停滚动背景,让它看起来像是跑步小人正在水平移动。第二,跑步小人跑动行为的循环显示来自游戏的 sprite 表单的一系列图像,如图 2 所示:
图 2. 跑动序列清单 4 中的代码实现了跑动行为:
清单 4. 跑步小人的 runBehavior
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var SnailBait =  function () {
   ...
   this.BACKGROUND_VELOCITY = 32, // pixels/second
   this.RUN_ANIMATION_RATE = 17, // frames/second
   ...

   this.runAnimationRate,

   this.runBehavior = {
      // Every  milliseconds, this behavior advances the
      // runner's artist to the next frame of the sprite sheet.

      lastAdvanceTime: 0,
      
      execute: function(sprite, time, fps) {
         if (sprite.runAnimationRate === 0) {
            return;
         }
         
         if (this.lastAdvanceTime === 0) {  // skip first time
            this.lastAdvanceTime = time;
         }
         else if (time - this.lastAdvanceTime > 1000 / sprite.runAnimationRate) {
            sprite.artist.advance();
            this.lastAdvanceTime = time;
         }
      }
   },
   ...
};




runBehavior 对象的 execute() 方法定期将跑步小人的 artist 前进到 sprite 表单中的跑步小人序列中的下一个图像。(可以在本系列第 4 篇文章中的  一节中看到 Snail Bait 的 sprite 表单)。
runBehavior 前进到下一个图像的频率决定了跑步小人跑动的速度。该时间间隔使用跑步小人的 runAnimationRate 属性设置。在游戏启动时,跑步小人并没有跑动,所以它的 runAnimationRate 最初为 0。但是,当玩家向左转或向右转时,Snail Bait 将该属性设置为 17 帧/秒,如清单 5 所示,跑步小人开始跑动:
清单 5. 开始播放跑动动画
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SnailBait.prototype = {
   ...
            
   turnLeft: function () {
      this.bgVelocity = -this.BACKGROUND_VELOCITY;
      this.runner.runAnimationRate = this.RUN_ANIMATION_RATE; // 17 fps, see <a href="#listing4">Listing 4</a>
      this.runnerArtist.cells = this.runnerCellsLeft;
      this.runner.direction = this.LEFT;
   },

   turnRight: function () {
      this.bgVelocity = this.BACKGROUND_VELOCITY;
      this.runner.runAnimationRate = this.RUN_ANIMATION_RATE; // 17 fps, see <a href="#listing4">Listing 4</a>
      this.runnerArtist.cells = this.runnerCellsRight;
      this.runner.direction = this.RIGHT;
   },

};




时间流像跑步小人的跑动行为一样,几乎所有行为都以时间为基础。而且因为一个游戏的动画不断在运行,所以许多修改游戏行为的函数(比如  中的 turnLeft() 和 turnRight())会设置简单的游戏变量来完成任务。当游戏绘制下一个动画帧时,这些变量会影响游戏的行为。

前面已经讨论过,turnLeft() 和 turnRight() 方法(由游戏的键盘事件处理函数调用)使用 runAnimationRate 属性控制跑步小人循环其图像序列的速度。这些方法还通过设置 bgVelocity 属性来控制跑步小人从左移动到右的速度,该属性表示背景滚动的速度。
返回列表