资讯专栏INFORMATION COLUMN

Chrome 小恐龙游戏源码探究四 -- 随机绘制云朵

svtter / 643人阅读

摘要:文章首发于我的博客前言上一篇文章小恐龙游戏源码探究三进入街机模式实现了开场动画和街机模式。

文章首发于我的 GitHub 博客
前言

上一篇文章:《Chrome 小恐龙游戏源码探究三 -- 进入街机模式》 实现了开场动画和街机模式。这一篇文章中,将实现云朵的随机绘制。

云朵类 Cloud

定义云朵类 Cloud

/**
 * 云朵类
 * @param {HTMLCanvasElement} canvas 画布
 * @param {Object} spritePos 图片在雪碧图中的位置信息
 * @param {Number} containerWidth 容器的宽度
 */
function Cloud(canvas, spritePos, containerWidth) {
  this.canvas = canvas;
  this.ctx = canvas.getContext("2d");
  this.spritePos = spritePos;
  this.containerWidth = containerWidth;

  // 坐标
  this.xPos = containerWidth;
  this.yPos = 0;

  // 该云朵是否需要删除
  this.remove = false;
  // 随机云朵之间的间隙
  this.cloudGap = getRandomNum(Cloud.config.MIN_CLOUD_GAP,
    Cloud.config.MAX_CLOUD_GAP);

  this.init();
}

相关的配置参数:

Cloud.config = {
  WIDTH: 46,
  HEIGHT: 14,
  MIN_CLOUD_GAP: 100,   // 云之间的最小间隙
  MAX_CLOUD_GAP: 400,   // 云之间的最大间隙
  MIN_SKY_LEVEL: 71,    // 云的最小高度
  MAX_SKY_LEVEL: 30,    // 云的最大高度
  BG_CLOUD_SPEED: 0.2,  // 云的速度
  CLOUD_FREQUENCY: 0.5, // 云的频率
  MAX_CLOUDS: 6         // 云的最大数量
};

补充本篇文章中会用到的数据:

Runner.spriteDefinition = {
  LDPI: {
    // ...

+   CLOUD: {x: 86, y: 2},
  },
};

绘制和更新云朵的方法定义如下:

Cloud.prototype = {
  // 初始化云朵
  init: function () {
    this.yPos = getRandomNum(Cloud.config.MAX_SKY_LEVEL,
      Cloud.config.MIN_SKY_LEVEL);
    this.draw();
  },
  // 绘制云朵
  draw: function () {
    this.ctx.save();

    var sourceWidth = Cloud.config.WIDTH;
    var sourceHeight = Cloud.config.HEIGHT;
    var outputWidth = sourceWidth;
    var outputHeight = sourceHeight;

    this.ctx.drawImage(
      Runner.imageSprite,
      this.spritePos.x, this.spritePos.y,
      sourceWidth, sourceHeight,
      this.xPos, this.yPos,
      outputWidth, outputHeight
    );
    
    this.ctx.restore();
  },
  // 更新云朵
  update: function (speed) {
    if (!this.remove) {
      this.xPos -= speed;
      this.draw();

      // 云朵移出 canvas,将其删除
      if (!this.isVisible()) {
        this.remove = true;
      }
    }
  },
  // 云朵是否移出 canvas
  isVisible: function () {
    return this.xPos + Cloud.config.WIDTH > 0;
  },
};

/**
 * 获取 [min, max] 之间的随机数
 * @param {Number} min 最小值
 * @param {Number} max 最大值
 * @return {Number}
 */
function getRandomNum(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

然后需要通过 Horizon 类调用 Cloud 类。首先在 Horizon 类中添加与云朵相关的属性:

- function Horizon(canvas, spritePos) {
+ function Horizon(canvas, spritePos, dimensions) {
    this.canvas = canvas;
    this.ctx = this.canvas.getContext("2d");
    this.spritePos = spritePos;

+   this.dimensions = dimensions;

+   // 云的频率
+   this.cloudFrequency = Cloud.config.CLOUD_FREQUENCY;

+   // 云
+   this.clouds = [];
+   this.cloudSpeed = Cloud.config.BG_CLOUD_SPEED;
    
    // 地面
    this.horizonLine = null;

    this.init();
  }

修改在 Runner 中调用 Horizon 类时传入的参数:

Runner.prototype = {
  init: function () {
    // ...

+   // 加载背景类 Horizon
-   this.horizon = new Horizon(this.canvas, this.spriteDef);
+   this.horizon = new Horizon(this.canvas, this.spriteDef,
+     this.dimensions);

    // ...
  },
};

添加生成云朵的方法,将生成的云朵存入数组 clouds

Horizon.prototype = {
  // 添加新的云朵
  addCloud: function () {
    this.clouds.push(new Cloud(this.canvas, this.spritePos.CLOUD,
      this.dimensions.WIDTH));
  },
};

调用 addCloud 方法来初始化云朵:

Horizon.prototype = {
  init: function () {
+   this.addCloud();
    this.horizonLine = new HorizonLine(this.canvas, this.spritePos.HORIZON);
  },
};

添加更新云朵的方法:

Horizon.prototype = {
  // 更新 canvas 上的云朵
  updateCloud: function (deltaTime, speed) {
    var cloudSpeed = Math.ceil(deltaTime * this.cloudSpeed * speed / 1000);
    var numClouds = this.clouds.length;

    if (numClouds) {
      for (var i = numClouds - 1; i >= 0; i--) {
        this.clouds[i].update(cloudSpeed);
      }

      var lastCloud = this.clouds[numClouds - 1];

      // 检查是否需要添加新的云朵
      // 添加云朵的条件:云朵数量少于最大数量、
      // 最后一个云朵后面的空间大于它的间隙、
      // 云朵出现频率符合要求
      if (numClouds < Cloud.config.MAX_CLOUDS &&
        (this.dimensions.WIDTH - lastCloud.xPos) > lastCloud.cloudGap &&
        this.cloudFrequency > Math.random()) {
        this.addCloud();
      }

      // 删除 remove 属性为 true 的云朵
      this.clouds = this.clouds.filter(function (item) {
        return !item.remove;
      });
    } else {
      this.addCloud();
    }
  },
};

调用 updateCloud 方法,来实现对云朵的更新:

Horizon.prototype = {
  update: function (deltaTime, currentSpeed) {
    this.horizonLine.update(deltaTime, currentSpeed);
+   this.updateCloud(deltaTime, currentSpeed);
  },
};

运行效果如下:

查看添加或修改的代码:戳这里

Demo 体验地址:https://liuyib.github.io/blog/demo/game/google-dino/add-cloud/

上一篇 下一篇
Chrome 小恐龙游戏源码探究三 -- 进入街机模式 Chrome 小恐龙游戏源码探究五 -- 随机绘制障碍

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103882.html

相关文章

  • Chrome 恐龙游戏源码探究一 -- 绘制静态地面

    摘要:首先是绘制静态的地面。上一篇下一篇无小恐龙游戏源码探究二让地面动起来 文章首发于我的 GitHub 博客 目录 Chrome 小恐龙游戏源码探究一 -- 绘制静态地面 Chrome 小恐龙游戏源码探究二 -- 让地面动起来 Chrome 小恐龙游戏源码探究三 -- 进入街机模式 Chrome 小恐龙游戏源码探究四 -- 随机绘制云朵 Chrome 小恐龙游戏源码探究五 -- 随机绘...

    lixiang 评论0 收藏0
  • Chrome 恐龙游戏源码探究五 -- 随机绘制障碍

    摘要:文章首发于我的博客前言上一篇文章小恐龙游戏源码探究四随机绘制云朵实现了云朵的随机绘制,这一篇文章中将实现仙人掌翼龙障碍物的绘制游戏速度的改变障碍物的类型有两种仙人掌和翼龙。 文章首发于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龙游戏源码探究四 -- 随机绘制云朵》 实现了云朵的随机绘制,这一篇文章中将实现:1、仙人掌、翼龙障碍物的绘制 2、游戏速度的改变 障碍物...

    tomorrowwu 评论0 收藏0
  • Chrome 恐龙游戏源码探究三 -- 进入街机模式

    摘要:文章首发于我的博客前言上一篇文章小恐龙游戏源码探究二让地面动起来实现了地面的移动。街机模式的效果就是游戏开始后,进入全屏模式。例如可以看到,进入街机模式之前,有一段开场动画。 文章首发于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龙游戏源码探究二 -- 让地面动起来》 实现了地面的移动。这一篇文章中,将实现效果:1、浏览器失焦时游戏暂停,聚焦游戏继续。 2、开场动...

    yeooo 评论0 收藏0
  • Chrome 恐龙游戏源码探究六 -- 记录游戏分数

    摘要:文章首发于我的博客前言上一篇文章小恐龙游戏源码探究五随机绘制障碍实现了障碍物仙人掌和翼龙的绘制。在游戏中,小恐龙移动的距离就是游戏的分数。 文章首发于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龙游戏源码探究五 -- 随机绘制障碍》 实现了障碍物仙人掌和翼龙的绘制。这一篇将实现当前分数、最高分数的记录和绘制。 在游戏中,小恐龙移动的距离就是游戏的分数。分数每达 1...

    Jingbin_ 评论0 收藏0
  • Chrome 恐龙游戏源码探究八 -- 奔跑的恐龙

    摘要:例如,将函数修改为小恐龙眨眼这样小恐龙会不停的眨眼睛。小恐龙的开场动画下面来实现小恐龙对键盘按键的响应。接下来还需要更新动画帧才能实现小恐龙的奔跑动画。 文章首发于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龙游戏源码探究七 -- 昼夜模式交替》实现了游戏昼夜模式的交替,这一篇文章中,将实现:1、小恐龙的绘制 2、键盘对小恐龙的控制 3、页面失焦后,重新聚焦会重置...

    paulquei 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<