我正在简单的游戏中尝试运动力学,我发现了一篇非常不错的文章,其中有一个例子,说明了如何通过使用速度和摩擦(非常流行的方法)使其“逼真”。所以物体开始缓慢,加速到一个上限,一旦你松开键,它开始减速,直到0。
关键部分是增加“油门”:
if(keys[38]) {
spaceship.ax = Math.cos(spaceship.r) * 0.05;
spaceship.ay = Math.sin(spaceship.r) * 0.05;
} else {
spaceship.ax = spaceship.ay = 0;
}
利用油门来增加摩擦限制的速度
var friction = 0.97;
function updatePosition(obj) {
//update velocity
obj.vx += obj.ax;
obj.vy += obj.ay;
//apply friction
obj.vx *= friction;
obj.vy *= friction;
//update position
obj.x += obj.vx;
obj.y += obj.vy;
}
虽然它看起来很漂亮,感觉也很不错,但它打破了我认为基于时间的移动的逻辑。它是强制性的,因此玩家可以看到每秒的速度,因为它允许进行计划升级,计划旅行和燃料使用。
因此,当前的实现如下所示:
this.now = undefined;
this.delta = undefined;
this.then = Date.now();
this.setMoveDelta = function() {
this.now = Date.now();
this.delta = (this.now - this.then) / 1000;
this.then = this.now;
};
this.speed = 100; // 100 pixels per second
this.move = function() {
this.setMoveDelta();
var partialDistance = this.speed * this.delta;
this.x += Math.cos(this.rad) * partialDistance;
this.y += Math.sin(this.rad) * partialDistance;
}
现在,当你运行附带的演示程序时,可以注意到,由于摩擦盖,有一种“最大”速度。问题是这个上限能设定为多少
this.speed * this.delta
以某种方式或者使用其他一些方法,使用声明的参数(例如每秒100像素)使船舶以最大速度移动?
其想法是保持加速和减速不变,但一旦船舶达到最大速度,它将是声明的速度(并向用户显示)。然后,该速度用于计算从A点到B点行驶所需的时间,以及将使用多少燃油。现在感觉很随意。
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
w = 400,
h = 400;
canvas.width = w;
canvas.height = h;
document.body.appendChild(canvas);
var spaceship = {
x: w / 2, y: h / 2,
vx: 0, vy: 0,
ax: 0, ay: 0,
r: 0,
draw: function(){
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.r);
ctx.fillStyle = 'white';
ctx.fillRect(-10, -5, 20, 10);
ctx.restore();
}
};
var friction = 0.97;
function updatePosition(obj) {
//update velocity
obj.vx += obj.ax;
obj.vy += obj.ay;
applyFriction(obj);
//update position
obj.x += obj.vx;
obj.y += obj.vy;
}
//user interactivity
var keys = [];
document.addEventListener('keydown', function(e){
keys[e.which] = true;
});
document.addEventListener('keyup', function(e){
keys[e.which] = false;
});
function applyFriction(obj){
obj.vx *= friction;
obj.vy *= friction;
}
(function animloop(){
requestAnimationFrame(animloop, canvas);
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, w, h);
//rotation
if(keys[37]) spaceship.r -= 0.05;
if(keys[39]) spaceship.r += 0.05;
//thrust
if(keys[38]){
spaceship.ax = Math.cos(spaceship.r) * 0.05;
spaceship.ay = Math.sin(spaceship.r) * 0.05;
}else{
spaceship.ax = spaceship.ay = 0;
}
updatePosition(spaceship);
spaceship.draw();
})();
-----编辑
我实现了建议的解决方案,但即使使用这个公式,最大速度也略低于声明的速度,从而导致其他对象以每秒100px的速度移动,从长远来看速度更快。这是一个新的演示:
this.now = undefined;
this.delta = undefined;
this.then = Date.now();
this.setMoveDelta = function() {
this.now = Date.now();
this.delta = (this.now - this.then) / 1000;
this.then = this.now;
};
this.speed = 100; // 100 pixels per second
var secondObj = {
x: 0,
y: 250,
r: 0,
active: false,
draw: function(){
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.r);
ctx.fillStyle = 'white';
ctx.fillRect(-10, -5, 20, 10);
ctx.restore();
}
};
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
w = 1200,
h = 400;
canvas.width = w;
canvas.height = h;
document.body.appendChild(canvas);
var spaceship = {
x: 0, y: 200,
vx: 0, vy: 0,
ax: 0, ay: 0,
r: 0,
draw: function(){
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.r);
ctx.fillStyle = 'white';
ctx.fillRect(-10, -5, 20, 10);
ctx.restore();
}
};
var friction = 0.97;
function updatePosition(obj) {
//update velocity
obj.vx += obj.ax;
obj.vy += obj.ay;
applyFriction(obj);
//update position
obj.x += obj.vx;
obj.y += obj.vy;
}
//user interactivity
var keys = [];
document.addEventListener('keydown', function(e){
keys[e.which] = true;
setTimeout(function() {
secondObj.active = true;
}, 600);
});
document.addEventListener('keyup', function(e){
keys[e.which] = false;
});
function applyFriction(obj){
obj.vx *= friction;
obj.vy *= friction;
}
var is = function(c, num) {
if(parseInt(c) < num + 1 || parseInt(c) > num - 1) {
return true;
}
return false;
};
(function animloop(){
requestAnimationFrame(animloop, canvas);
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, w, h);
//rotation
if(keys[37]) spaceship.r -= 0.05;
if(keys[39]) spaceship.r += 0.05;
//thrust
this.setMoveDelta();
if(keys[38]){
spaceship.ax = Math.cos(spaceship.r) * (this.speed * this.delta * (1-0.97));
spaceship.ay = Math.sin(spaceship.r) * (this.speed * this.delta * (1-0.97));
}else{
spaceship.ax = spaceship.ay = 0;
}
updatePosition(spaceship);
spaceship.draw();
if(secondObj.active) {
secondObj.x += Math.cos(0) * ( this.speed * this.delta );
}
secondObj.draw();
})();