微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

对象必须在多快是 y 分量才能达到特定峰值 使用的术语求解步骤演示

如何解决对象必须在多快是 y 分量才能达到特定峰值 使用的术语求解步骤演示

我想为达到特定峰值(点(x,y))的玩家(左下角)添加提升。玩家的水平速度 (v_x) 是恒定的,但其垂直速度可能会有所不同。我想计算它需要达到点 (x,y)(这必须是峰值)所需的最终速度 v_y,这也是给定的。我想也许我可以得到 Vector player 和 Vector 点之间的角度并用运动学公式计算,但它没有给我正确的结果。

enter image description here

解决方法

希望我能正确理解您的问题。首先,您要计算爬到那个山峰所需的时间。

// 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 举报,一经查实,本站将立刻删除。