角色的更新
角色对象的update方法接受时间步长、状态对象和keys对象作为参数。Lava角色类型忽略keys对象。
Lava.prototype.update = function(time, state) {let newPos = this.pos.plus(this.speed.times(time));if (!state.level.touches(newPos, this.size, "wall")) {return new Lava(newPos, this.speed, this.reset);} else if (this.reset) {return new Lava(this.reset, this.speed, this.reset);} else {return new Lava(this.pos, this.speed.times(-1));}};
它通过将时间步长乘上当前速度,并将其加到其旧位置,来计算新的位置。如果新的位置上没有障碍,它移动到那里。如果有障碍物,其行为取决于岩浆块的类型:滴落岩浆具有reset位置,当它碰到某物时,它会跳回去。跳跃岩浆将其速度乘以-1,从而开始向相反的方向移动。
硬币使用它们的act方法来晃动。他们忽略了网格的碰撞,因为它们只是在它们自己的方块内部晃动。
const wobbleSpeed = 8, wobbleDist = 0.07;Coin.prototype.update = function(time) {let wobble = this.wobble + time * wobbleSpeed;let wobblePos = Math.sin(wobble) * wobbleDist;return new Coin(this.basePos.plus(new Vec(0, wobblePos)),this.basePos, wobble);};
递增wobble属性来跟踪时间,然后用作Math.sin的参数,来找到波上的新位置。然后,根据其基本位置和基于波的偏移,计算硬币的当前位置。
还剩下玩家本身。玩家的运动对于每和轴单独处理,因为碰到地板不应阻止水平运动,碰到墙壁不应停止下降或跳跃运动。
const playerXSpeed = 7;const gravity = 30;const jumpSpeed = 17;Player.prototype.update = function(time, state, keys) {let xSpeed = 0;if (keys.ArrowLeft) xSpeed -= playerXSpeed;if (keys.ArrowRight) xSpeed += playerXSpeed;let pos = this.pos;let movedX = pos.plus(new Vec(xSpeed * time, 0));if (!state.level.touches(movedX, this.size, "wall")) {pos = movedX;}let ySpeed = this.speed.y + time * gravity;let movedY = pos.plus(new Vec(0, ySpeed * time));if (!state.level.touches(movedY, this.size, "wall")) {pos = movedY;} else if (keys.ArrowUp && ySpeed > 0) {ySpeed = -jumpSpeed;} else {ySpeed = 0;}return new Player(pos, new Vec(xSpeed, ySpeed));};
水平运动根据左右箭头键的状态计算。当没有墙壁阻挡由这个运动产生的新位置时,就使用它。否则,保留旧位置。
垂直运动的原理类似,但必须模拟跳跃和重力。玩家的垂直速度(ySpeed)首先考虑重力而加速。
我们再次检查墙壁。如果我们不碰到任何一个,使用新的位置。如果存在一面墙,就有两种可能的结果。当按下向上的箭头,并且我们向下移动时(意味着我们碰到的东西在我们下面),将速度设置成一个相对大的负值。这导致玩家跳跃。否则,玩家只是撞到某物上,速度就被设定为零。
重力、跳跃速度和几乎所有其他常数,在游戏中都是通过反复试验来设定的。我测试了值,直到我找到了我喜欢的组合。
