如何解决对象必须在多快是 y 分量才能达到特定峰值 使用的术语求解步骤演示
我想为达到特定峰值(点(x,y))的玩家(左下角)添加提升。玩家的水平速度 (v_x) 是恒定的,但其垂直速度可能会有所不同。我想计算它需要达到点 (x,y)(这必须是峰值)所需的最终速度 v_y,这也是给定的。我想也许我可以得到 Vector player 和 Vector 点之间的角度并用运动学公式计算,但它没有给我正确的结果。
解决方法
希望我能正确理解您的问题。首先,您要计算爬到那个山峰所需的时间。
// distance left to travel horizontally
delta.x = peak.x - player.x
// time left to reach peak
t = delta.x / speed.x
假设 delta.x 为 200 像素,玩家的速度(水平)为每秒 40 像素。这给了我们 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
我们想要跳跃速度,所以根据 h = vd+(1/2)ad^2
重新排列 v
我们得到 v = -ad/2+h/d
最后一件事。水平速度被归一化,因此始终为 1。我们需要使用任何速度。我们可以通过将到障碍物的距离 d
除以水平速度(速度)s
来做到这一点。换句话说,以速度 d
s
需要多长时间
最终结果是v = -a(d/s)/2+h/(d/s)
作为代码
让我们把它写成代码(JavaScript)
函数jumpObstacle(jumper,obstacle)
会设置物体jumper
的跳跃速度,只有当跳跃者向障碍物移动时才能清除物体obstacle
。
Jumper 有一个 jumpClear
来提供间隙和最大跳跃速度 maxJumpVel
。这意味着跳跃可能无法清除障碍物。
函数返回跳跃高度,不跳跃返回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,// 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+向下
注意我设法达到的最低跳跃速度是每秒 271 像素
// 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,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.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,h: 34,draw(ctx) { ctx.strokeRect(this.x - 1,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,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>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。