上一章主要是绘制马里奥和绘制图像代码的部分重构
本章主要是用于时间控制,实现马里奥每次弹跳的定点和弹跳起点一致,对源代码拆分比较多,各位可以跟着原作者视频一起敲
本章的提交ID:90dc4d0a02cc67339b120e55f29e46751e76e0c6、6773e3baedba43f22978e2d0a2a61f514fa524d1
github地址:ainuo5213的超级马里奥
本节目录
本章效果
目录说明:
mario.js:马里奥实体工厂类文件,用于创建马里奥,封装马里奥的绘制过程
Entity.js:马里奥实体类,用于记录实体的位置和速度等信息
Velocity.js:用来记录马里奥横向和纵向速度的实体
Timer.js:绘制玛丽奥,更新马里奥位置的方法(原入口文件main方法中的update)封装
入口文件改动
入口文件改动:
1. 将原本加载马里奥的方法移动到了mario.js
2. 将马里奥位置改变的方法也内聚到了mario.js,并新增了横向和纵向速度变量对象,实现对横向速度和纵向速度的控制
Entity实体:
Entity实体主要用于对速度和位置的记录对象,其实现交给马里奥工厂函数
import { Velocity } from "./Velocity.js";
export class Entity {
constructor() {
this.pos = new Velocity(0, 0);
this.vel = new Velocity(0, 0);
}
}
创建马里奥工厂函数
创建马里奥的工厂函数将原本loadMarioSprite方法内聚返回了马里奥对象,并在马里奥对象上面增加了两个方法分别是drawMario(绘制马里奥)和updateMario(更新马里奥位置)的方法,其中updateMario方法将速度和时间进行累加操作,使马里奥不再做匀速运动
import { Entity } from "./Entity.js"
import { loadMarioSprite } from "./sprites.js";
export function createMario() {
return loadMarioSprite()
.then(marioSprite => {
const mario = new Entity();
mario.draw = function drawMario(context) {
marioSprite.draw('mario', context, this.pos.x, this.pos.y);
}
mario.update = function updateMario(deltaTime) {
this.pos.x += this.vel.x * deltaTime;
this.pos.y += this.vel.y * deltaTime;
}
return mario;
})
}
马里奥运动的时间控制
为实现马里奥的每次跳跃的定点都保持在y轴方向一致,原作者这里使用累加法,当误差大于阈值时,就减去阈值,相当于归0
马里奥入口中增加了update方法,用于updateProxy调用,来更新马里奥位置。
export default class Timer {
constructor(deltaTime = 1 / 60) {
let accumulatedTime = 0;
let lastTime = 0;
this.updateProxy = time => {
// 因为deltaTime是以秒为单位,所以这里运动的累加误差时间需要除以1000
accumulatedTime += (time - lastTime) / 1000;
while (accumulatedTime > deltaTime) {
this.update(deltaTime);
accumulatedTime -= deltaTime
}
lastTime = time;
this.enqueue();
}
}
enqueue = () => {
requestAnimationFrame(this.updateProxy);
}
start = () => {
this.enqueue();
}
}