内容简介:上一篇文章:《要实现地面的移动就要不断更新地面的其中
前言
上一篇文章:《 Chrome 小恐龙游戏源码探究一 -- 绘制静态地面 》 中定义了游戏的主体类 Runner,并实现了静态地面的绘制。这一篇文章中,将实现效果:1、地面无限滚动。2、刚开始地面不动,按下空格后地面滚动。
地面无限滚动
要实现地面的移动就要不断更新地面的 x 坐标。定义方法:
HorizonLine.prototype = {
/**
* 更新地面的 x 坐标
* @param {Number} pos 地面的位置
* @param {Number} incre 移动距离
*/
updateXPos: function (pos, incre) {
var line1 = pos;
var line2 = pos === 0 ? 1 : 0;
// 第一段地面向左移动,第二段地面随之
this.xPos[line1] -= incre;
this.xPos[line2] = this.xPos[line1] + this.dimensions.WIDTH;
// 第一段地面移出了 canvas
if (this.xPos[line1] <= -this.dimensions.WIDTH) {
// 将第一段地面放到 canvas 右侧
this.xPos[line1] += this.dimensions.WIDTH * 2;
// 此时第二段地面的 x 坐标刚好和 canvas 的 x 坐标对齐
this.xPos[line2] = this.xPos[line1] - this.dimensions.WIDTH;
// 给放到 canvas 后面的地面随机地形
this.sourceXPos[line1] = this.getRandomType() + this.spritePos.x;
}
},
/**
* 获取随机的地形
*/
getRandomType: function () {
return Math.random() > this.bumpThreshold ? this.dimensions.WIDTH : 0;
},
};
其中 updateXPos 实现了地面 x 坐标的更新。当第一段地面移出 canvas 时,会将第一段地面 x 坐标乘 2 放到 canvas 后面,然后为其随机地形。这时,原来的第二段地面就变成了第一段地面继续向前移动,以此类推。这样就实现了地面的不断移动和更新。
上面的函数只是实现了地面移动相关的逻辑,真正让地面动起来还需要调用这个函数。添加方法:
HorizonLine.prototype = {
/**
* 更新地面
* @param {Number} deltaTime 间隔时间
* @param {Number} speed 速度
*/
update: function (deltaTime, speed) {
// 计算地面每次移动的距离(距离 = 速度 x 时间)时间由帧率和间隔时间共同决定
var incre = Math.floor(speed * (FPS / 1000) * deltaTime);
if (this.xPos[0] <= 0) {
this.updateXPos(0, incre);
} else {
this.updateXPos(1, incre);
}
this.draw();
},
};
然后需要通过 Horizon 上的 update 方法来调用 HorizonLine 上的 update 方法。
在 Horizon 的原型链上添加方法:
Horizon.prototype = {
update: function (deltaTime, currentSpeed) {
this.horizonLine.update(deltaTime, currentSpeed);
},
};
同理,按照上面的逻辑,现在应该在 Runner 上定义 update 方法来调用 Horizon 上的 update 方法。
在 Runner 上添加方法:
Runner.prototype = {
/**
* 更新游戏帧并进行下一次更新
*/
update: function () {
this.updatePending = false; // 等待更新
var now = getTimeStamp();
var deltaTime = now - (this.time || now);
this.time = now;
this.clearCanvas();
this.horizon.update(deltaTime, this.currentSpeed);
// 进行下一次更新
this.scheduleNextUpdate();
},
clearCanvas: function () {
this.ctx.clearRect(0, 0, this.dimensions.WIDTH,
this.dimensions.HEIGHT);
},
scheduleNextUpdate: function () {
if (!this.updatePending) {
this.updatePending = true;
this.raqId = requestAnimationFrame(this.update.bind(this));
}
},
};
// 获取时间戳
function getTimeStamp() {
return performance.now();
}
最后在 Runner 的 init 方法中调用它的 update 方法:
Runner.prototype = {
init: function () {
// ...
// 更新 canvas
+ this.update();
},
};
现在地面就可以进行无限滚动了,效果如下:
查看添加的代码: 戳这里
响应空格键
下面要实现的效果是:刚开始地面不动,按下空格后地面滚动。
修改 Runner 原型链中的 update 方法:
Runner.prototype = {
/**
* 更新游戏帧并进行下一次更新
*/
update: function () {
var now = getTimeStamp();
var deltaTime = now - (this.time || now);
this.time = now;
+ if (this.playing) {
this.clearCanvas();
this.horizon.update(deltaTime, this.currentSpeed);
+ }
+ if (this.playing) {
// 进行下一次更新
this.scheduleNextUpdate();
+ }
},
};
监听键盘事件:
Runner.prototype = {
startListening: function () {
document.addEventListener(Runner.events.KEYDOWN, this);
document.addEventListener(Runner.events.KEYUP, this);
},
stopListening: function () {
document.removeEventListener(Runner.events.KEYDOWN, this);
document.removeEventListener(Runner.events.KEYUP, this);
},
};
添加数据:
Runner.events = {
// ...
+ KEYDOWN: 'keydown',
+ KEYUP: 'keyup',
};
在 Runner 的 init 方法中调用上面定义的 startListening 方法:
Runner.prototype = {
init: function () {
// ...
// 开始监听用户动作
+ this.startListening();
},
};
当浏览器监听到用户按下键盘时,会执行 handleEvent 方法来处理键盘事件:
Runner.prototype = {
// 用来处理 EventTarget(这里就是 Runner 类) 上发生的事件
// 当事件被发送到 EventListener 时,浏览器就会自动调用这个方法
handleEvent: function (e) {
return (function (eType, events) {
switch (eType) {
case events.KEYDOWN:
this.onKeyDown(e);
break;
default:
break;
}
}.bind(this))(e.type, Runner.events);
},
};
上面用到的 onKeyDown 方法定义如下:
Runner.prototype = {
onKeyDown: function (e) {
if (!this.crashed && !this.paused) {
if (Runner.keyCodes.JUMP[e.keyCode]) {
e.preventDefault();
if (!this.playing) {
this.setPlayStatus(true);
this.update();
}
}
}
},
setPlayStatus: function (isPlaying) {
this.playing = isPlaying;
},
};
这里需要说一下,当按下空格键后, 为什么浏览器会执行handleEvent 事件 :当使用 addEventListener 监听某个对象上的事件时,只要被监听的事件触发了,就会执行该对象上的名为 handleEvent 的方法(如果有)。
到此,就实现了预期的效果:
查看添加的代码, 戳这里
Demo 体验地址: https://liuyib.github.io/pages/demo/games/google-dino/horizonline-move/
| 上一篇 | 下一篇 | Chrome 小恐龙游戏源码探究一 -- 绘制静态地面 | Chrome 小恐龙游戏源码探究三 -- 进入街机模式 |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Chrome 小恐龙游戏源码探究八 -- 奔跑的小恐龙
- Chrome 小恐龙游戏源码探究六 -- 记录游戏分数
- Chrome 小恐龙游戏源码探究五 -- 随机绘制障碍
- Chrome 小恐龙游戏源码探究九 -- 游戏碰撞检测
- Chrome 小恐龙游戏源码探究完 -- 游戏结束和其他要素
- 用语言模型命名恐龙
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
CASIO fx-5800P编程计算器公路与铁路施工测量程序
2011-8 / 40.00元
《CASIO fx-5800P 编程计算器公路与铁路施工测量程序(第2版)》内容简介:第2版是一本全新的图书。书中的QH2-7T与QH2-8T程序都具有三维中边桩坐标正、反算,路基超高及边桩设计高程计算,边坡坡口与坡脚计算,桥墩桩基坐标计算,隧道超欠挖计算等功能。QH2-7T为交点法程序,QH2-8T为线元法程序,两个程序均使用数据库子程序输入平竖曲线的全部设计数据。测试程序各项功能所用的案例均取......一起来看看 《CASIO fx-5800P编程计算器公路与铁路施工测量程序》 这本书的介绍吧!