对象必须多快才能到达特定峰值
How quick must an Object be in is y component to reach a specific peak
我想为达到特定峰值(点(x,y))的播放器(左下角)添加一个提升。玩家的水平速度 (v_x) 是恒定的,但其垂直速度可以变化。我想计算到达点 (x,y)(这必须是峰值)所需的结束速度 v_y,这也是给定的。我想也许我可以得到 Vector player 和 Vector point 之间的角度并用运动学公式计算但它没有给我正确的结果。
希望我正确理解你的问题。首先你要计算你需要多少时间才能爬到那个山峰。
// distance left to travel horizontally
delta.x = peak.x - player.x
// time left to reach peak
t = delta.x / speed.x
假设 delta.x 是 200px,玩家的速度(水平)是每秒 40px。这给了我们 5 秒的时间从 player.y 爬升到 peak.y.
现在我们计算需要垂直移动多远。
// We have 5 seconds to move vertically by this much
delta.y = peak.y - player.y
// How fast to move per second to reach peak in 5 seconds.
speed.y = delta.y / t
关于重力的注意事项:
如果重力为 3m/s(为便于数学计算而简化),则重力在持续施加的每一秒都会变大(因为它在加速)。
second - m/s
1 - 3
2 - 6
3 - 9
4 - 12
5 - 15
这并不意味着 5 秒后重力将您的物体拉动 15 米。这是序列中每一秒的力,所以你实际上把它们加起来就是总数,就是 45。所以你要在上面计算的总距离上加上 45。
跳?有多高?
重力是恒定的,但随着我们接近障碍物的距离会发生变化。
在某个点,距离障碍物有一定距离,跳跃速度是清除障碍物所需的最小速度。
越往后需要更大的速度才能在空中停留足够长的时间以清除它,或者越靠近则速度必须越大才能在扩孔时间内清除。
不清楚你是否想要最佳跳跃速度来清除物体,这也将定义何时跳跃。
所以我们将给定重力作为加速度和水平速度,跳过高度和距离的障碍物需要多少垂直速度。
获取跳跃速度
为了简单起见,我们首先将水平速度归一化
使用的术语
v
为跳跃速度,或初速度(正为向上)
t
是时间
a
是重力加速度(负数向下)
h
为障碍物高度。积极向上
d
是到障碍物的距离。相当于归一化水平速度
s
是水平速度。假设正向障碍物。
用于求解的步骤
下落(自由落体)时的速度方程为v + at
方程 f'(t) = v + at
方程的反导数 f(t) = vt + (1/2)at^2
告诉我们在任何时候我们有多高 t
因为我们已经归一化水平速度s
到障碍物的距离等于到障碍物的时间t
或到障碍物的距离d
我们还可以使用反导数求解给定距离的高度h = vd+(1/2)ad^2
(将t
替换为d
)
现在我们在一个等式中有了我们想要的所有项。 h = vd+(1/2)ad^2
我们想要跳跃速度所以根据 v
重新排列 h = vd+(1/2)ad^2
我们得到 v = -ad/2+h/d
最后一件事。水平速度被归一化,因此始终为 1。我们需要使用任何速度。我们可以通过将到障碍物的距离 d
除以水平速度(速度)s
来做到这一点。换句话说,以 s
的速度完成距离 d
需要多长时间(以秒为单位)
最后的结果是v = -a(d/s)/2+h/(d/s)
作为代码
让我们将其写入代码 (JavaScript)
函数jumpObstacle(jumper, obstacle)
将设置物体的跳跃速度jumper
只有当跳跃者正在向障碍物移动时才能清除物体obstacle
。
跳跃者有一个 jumpClear
来提供间隙和最大跳跃速度 maxJumpVel
。这意味着跳跃可能无法越过障碍物。
函数returns跳跃高度,如果没有跳跃则为0。
// Assuming +y is up
const gravity = 9.0;
const jumper = {
vx: 1,
vy: 0,
x: 0,
y: 0,
maxJumpVel: 3, // max jump velocity y
jumpClear: 0.5, // clearance when jumping. May not if max jump to high
};
const wall = {
x: 4,
y: 0, // base
h: 4, // height
};
function jumpObstacle(jumper, obstacle) {
const dist = obstacle.x - jumper.x;
if (jumper.vx && Math.sign(jumper.vx) === Math.sign(dist)) {
const nd = dist / jumper.vx; // normalize dist (time)
const h = (obstacle.h + obstacle.y + jumper.jumpClear) - jumper.y; // height to clear
const vy = -(gravity * nd) / 2 + h / nd;
jumper.vy = Math.min(vy, jumper.maxJumpVel);
return jumper.y + vy * nd + gravity * nd * nd * 0.5;
}
return 0;
}
演示
我不确定答案是否清晰。该演示将上述内容实现为交互式演示。
当盒子在墙的范围内时点击或点击动画。 jumpObstacle 函数将计算越过墙壁所需的跳跃速度。
我还添加了盒子的宽度,以及x跳跃间隙以确保跳跃在视觉上可以清除墙壁。
如果跳线不能清除墙壁,它会闪烁红色。下次再试。
地面下的红色框表示跳线能够越过墙壁的大约距离。
注意坐标是Y+向下
注意我的最低跳跃速度是每秒271px
// Note y is + down the page
requestAnimationFrame(update);
const ctx = canvas.getContext("2d");
ctx.fillStyle = "red";
const h = 120, w = 200;
const ground = h - 10;
canvas.addEventListener("click", () => {
jumper.onGround && (jumper.jumpNextFrame = true);
});
const gravity = 900.0;
const jumper = {
vx: 60,
vy: 0,
x: 0,
y: ground,
h: 24,
w: 8,
jumpTime: 0,
jumpNextFrame: false,
get onGround() { return this.y >= ground },
maxJumpVel: -490,
jumpClear: -5,
jumpClearX: 5,
jumpFail: 0,
draw(ctx) {
this.jumpFail-- > 0 && ctx.fillRect(this.x - this.w / 2, this.y - this.h, this.w, this.h);
ctx.strokeRect(this.x - this.w / 2, this.y - this.h, this.w, this.h);
},
jump(time, what) {
this.jumpNextFrame = false;
this.jumpTime = time;
const h = jumpObstacle(this, what);
if (h < 0 || h > what.h) {
this.jumpTime = 0;
this.jumpFail = 10;
this.vy = 0;
} else {
console.clear();
console.log("Jump vel: " + (-this.vy).toFixed(0) + "px per second");
}
},
update(time) {
this.x = this.vx * time;
if (this.x > w ) { this.x = this.x % w }
if (this.jumpTime > 0) {
const t = time - this.jumpTime;
this.y = ground + this.vy * t + gravity * t * t * 0.5;
if (this.y > ground) {
this.vy = 0;
this.jumpTime = 0;
this.y = ground;
}
}
}
};
const wall = {
x: 140,
y: ground,
h: 34,
draw(ctx) { ctx.strokeRect(this.x - 1, this.y - this.h, 2, this.h) },
};
function jumpObstacle(jumper, obstacle) {
const dist = (obstacle.x - (jumper.x - jumper.w)) + jumper.jumpClearX;
if (jumper.vx && Math.sign(jumper.vx) === Math.sign(dist)) {
const nd = (dist / jumper.vx) ;
const h = -((obstacle.h + obstacle.y + jumper.jumpClear) - jumper.y);
const vy = -(gravity * nd) / 2 + h / nd;
jumper.vy = vy < jumper.maxJumpVel ? jumper.maxJumpVel : vy;
return (jumper.vy * nd + gravity * nd * nd * 0.5) - h;
}
return 0;
}
function update(time) {
time /= 1000;
ctx.clearRect(0, 0, w, h);
ctx.strokeRect(-1, ground, w + 2, h - ground + 2); // draw ground
ctx.fillRect(wall.x - 50, ground + 2, 30, 2);
if (jumper.jumpNextFrame) { jumper.jump(time , wall) }
jumper.update(time);
jumper.draw(ctx);
wall.draw(ctx);
requestAnimationFrame(update);
}
console.log("Click animation to jump. Will flash red is not able to clear wall");
canvas { border: 1px solid black; }
<canvas id="canvas" width ="200" height="120"></canvas>
我想为达到特定峰值(点(x,y))的播放器(左下角)添加一个提升。玩家的水平速度 (v_x) 是恒定的,但其垂直速度可以变化。我想计算到达点 (x,y)(这必须是峰值)所需的结束速度 v_y,这也是给定的。我想也许我可以得到 Vector player 和 Vector point 之间的角度并用运动学公式计算但它没有给我正确的结果。
希望我正确理解你的问题。首先你要计算你需要多少时间才能爬到那个山峰。
// distance left to travel horizontally
delta.x = peak.x - player.x
// time left to reach peak
t = delta.x / speed.x
假设 delta.x 是 200px,玩家的速度(水平)是每秒 40px。这给了我们 5 秒的时间从 player.y 爬升到 peak.y.
现在我们计算需要垂直移动多远。
// We have 5 seconds to move vertically by this much
delta.y = peak.y - player.y
// How fast to move per second to reach peak in 5 seconds.
speed.y = delta.y / t
关于重力的注意事项:
如果重力为 3m/s(为便于数学计算而简化),则重力在持续施加的每一秒都会变大(因为它在加速)。
second - m/s
1 - 3
2 - 6
3 - 9
4 - 12
5 - 15
这并不意味着 5 秒后重力将您的物体拉动 15 米。这是序列中每一秒的力,所以你实际上把它们加起来就是总数,就是 45。所以你要在上面计算的总距离上加上 45。
跳?有多高?
重力是恒定的,但随着我们接近障碍物的距离会发生变化。
在某个点,距离障碍物有一定距离,跳跃速度是清除障碍物所需的最小速度。
越往后需要更大的速度才能在空中停留足够长的时间以清除它,或者越靠近则速度必须越大才能在扩孔时间内清除。
不清楚你是否想要最佳跳跃速度来清除物体,这也将定义何时跳跃。
所以我们将给定重力作为加速度和水平速度,跳过高度和距离的障碍物需要多少垂直速度。
获取跳跃速度
为了简单起见,我们首先将水平速度归一化
使用的术语
v
为跳跃速度,或初速度(正为向上)t
是时间a
是重力加速度(负数向下)h
为障碍物高度。积极向上d
是到障碍物的距离。相当于归一化水平速度s
是水平速度。假设正向障碍物。
用于求解的步骤
下落(自由落体)时的速度方程为v + at
方程 f'(t) = v + at
方程的反导数 f(t) = vt + (1/2)at^2
告诉我们在任何时候我们有多高 t
因为我们已经归一化水平速度s
到障碍物的距离等于到障碍物的时间t
或到障碍物的距离d
我们还可以使用反导数求解给定距离的高度h = vd+(1/2)ad^2
(将t
替换为d
)
现在我们在一个等式中有了我们想要的所有项。 h = vd+(1/2)ad^2
我们想要跳跃速度所以根据 v
重新排列 h = vd+(1/2)ad^2
我们得到 v = -ad/2+h/d
最后一件事。水平速度被归一化,因此始终为 1。我们需要使用任何速度。我们可以通过将到障碍物的距离 d
除以水平速度(速度)s
来做到这一点。换句话说,以 s
d
需要多长时间(以秒为单位)
最后的结果是v = -a(d/s)/2+h/(d/s)
作为代码
让我们将其写入代码 (JavaScript)
函数jumpObstacle(jumper, obstacle)
将设置物体的跳跃速度jumper
只有当跳跃者正在向障碍物移动时才能清除物体obstacle
。
跳跃者有一个 jumpClear
来提供间隙和最大跳跃速度 maxJumpVel
。这意味着跳跃可能无法越过障碍物。
函数returns跳跃高度,如果没有跳跃则为0。
// Assuming +y is up
const gravity = 9.0;
const jumper = {
vx: 1,
vy: 0,
x: 0,
y: 0,
maxJumpVel: 3, // max jump velocity y
jumpClear: 0.5, // clearance when jumping. May not if max jump to high
};
const wall = {
x: 4,
y: 0, // base
h: 4, // height
};
function jumpObstacle(jumper, obstacle) {
const dist = obstacle.x - jumper.x;
if (jumper.vx && Math.sign(jumper.vx) === Math.sign(dist)) {
const nd = dist / jumper.vx; // normalize dist (time)
const h = (obstacle.h + obstacle.y + jumper.jumpClear) - jumper.y; // height to clear
const vy = -(gravity * nd) / 2 + h / nd;
jumper.vy = Math.min(vy, jumper.maxJumpVel);
return jumper.y + vy * nd + gravity * nd * nd * 0.5;
}
return 0;
}
演示
我不确定答案是否清晰。该演示将上述内容实现为交互式演示。
当盒子在墙的范围内时点击或点击动画。 jumpObstacle 函数将计算越过墙壁所需的跳跃速度。
我还添加了盒子的宽度,以及x跳跃间隙以确保跳跃在视觉上可以清除墙壁。
如果跳线不能清除墙壁,它会闪烁红色。下次再试。
地面下的红色框表示跳线能够越过墙壁的大约距离。
注意坐标是Y+向下
注意我的最低跳跃速度是每秒271px
// Note y is + down the page
requestAnimationFrame(update);
const ctx = canvas.getContext("2d");
ctx.fillStyle = "red";
const h = 120, w = 200;
const ground = h - 10;
canvas.addEventListener("click", () => {
jumper.onGround && (jumper.jumpNextFrame = true);
});
const gravity = 900.0;
const jumper = {
vx: 60,
vy: 0,
x: 0,
y: ground,
h: 24,
w: 8,
jumpTime: 0,
jumpNextFrame: false,
get onGround() { return this.y >= ground },
maxJumpVel: -490,
jumpClear: -5,
jumpClearX: 5,
jumpFail: 0,
draw(ctx) {
this.jumpFail-- > 0 && ctx.fillRect(this.x - this.w / 2, this.y - this.h, this.w, this.h);
ctx.strokeRect(this.x - this.w / 2, this.y - this.h, this.w, this.h);
},
jump(time, what) {
this.jumpNextFrame = false;
this.jumpTime = time;
const h = jumpObstacle(this, what);
if (h < 0 || h > what.h) {
this.jumpTime = 0;
this.jumpFail = 10;
this.vy = 0;
} else {
console.clear();
console.log("Jump vel: " + (-this.vy).toFixed(0) + "px per second");
}
},
update(time) {
this.x = this.vx * time;
if (this.x > w ) { this.x = this.x % w }
if (this.jumpTime > 0) {
const t = time - this.jumpTime;
this.y = ground + this.vy * t + gravity * t * t * 0.5;
if (this.y > ground) {
this.vy = 0;
this.jumpTime = 0;
this.y = ground;
}
}
}
};
const wall = {
x: 140,
y: ground,
h: 34,
draw(ctx) { ctx.strokeRect(this.x - 1, this.y - this.h, 2, this.h) },
};
function jumpObstacle(jumper, obstacle) {
const dist = (obstacle.x - (jumper.x - jumper.w)) + jumper.jumpClearX;
if (jumper.vx && Math.sign(jumper.vx) === Math.sign(dist)) {
const nd = (dist / jumper.vx) ;
const h = -((obstacle.h + obstacle.y + jumper.jumpClear) - jumper.y);
const vy = -(gravity * nd) / 2 + h / nd;
jumper.vy = vy < jumper.maxJumpVel ? jumper.maxJumpVel : vy;
return (jumper.vy * nd + gravity * nd * nd * 0.5) - h;
}
return 0;
}
function update(time) {
time /= 1000;
ctx.clearRect(0, 0, w, h);
ctx.strokeRect(-1, ground, w + 2, h - ground + 2); // draw ground
ctx.fillRect(wall.x - 50, ground + 2, 30, 2);
if (jumper.jumpNextFrame) { jumper.jump(time , wall) }
jumper.update(time);
jumper.draw(ctx);
wall.draw(ctx);
requestAnimationFrame(update);
}
console.log("Click animation to jump. Will flash red is not able to clear wall");
canvas { border: 1px solid black; }
<canvas id="canvas" width ="200" height="120"></canvas>