I want to add a boost to the player (bottom left) that reaches a specific peak(Point (x,y)). The players horizontal speed (v_x) is constant but its vertical speed can vary. I want to calculate the needed end speed v_y that it needs to reach the point (x,y) (this has to be the peak) which is also given. I thought maybe I can get the angle between Vector player and Vector point and calculate with the kinematic formulars but it didnt give me the right result.
-
What exactly is your problem? – cavalcantelucas Jul 27 '21 at 16:05
-
The player (the ball) jumps on a boost object that boosts him. I want to calculate the needed velocity that the ball has to reach (the y component) to get to the Point which is the peak as illustrated. The players velocity in x is constant but I could change the position of the boost object – Jul 27 '21 at 16:12
-
It doesn't seem a technologic-specific question. Have you considered exploring the other communities? Check it out: https://stackexchange.com/sites – cavalcantelucas Jul 27 '21 at 16:15
2 Answers
Hoping I understand your problem correctly. First you want to calculate how much time you have to climb to that peak.
// distance left to travel horizontally
delta.x = peak.x - player.x
// time left to reach peak
t = delta.x / speed.x
Let's say delta.x is 200px and the player's speed (horizontal) is 40px per second. This gives us a time of 5 seconds to climb from player.y to peak.y.
Now we calculate how far we need to move vertically.
// 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
A note about gravity:
If gravity is 3m/s (simplified for easier math), then the force of gravity will be greater at each second it continues to be applied (because it's accelerating).
second - m/s
1 - 3
2 - 6
3 - 9
4 - 12
5 - 15
This doesn't mean after 5 seconds gravity has pulled your object 15 meters. That's the force at each second in the sequence, so you actually add them all up for the total, which would be 45. So you'd add 45 to the total distance calculated from above.

- 1,814
- 1
- 7
- 19
-
U are right. Thank you. I just found it out for myself but this confirms it. I was, as usual, thinking to complicated again. – Jul 27 '21 at 16:26
-
If your game uses gravity, you can calculate the amount of gravity applied over time (5seconds in my example) and add that to the total vertical distance needed to travel then do your division to find the speed needed. – Phaelax z Jul 27 '21 at 16:32
-
So I have done what you said but still have not the wanted result. First of all i added the gravitydistance to deltay by calculating it with gravity/t^2 but then the Ball doesnt seem to reach its peak quite yet. – Jul 28 '21 at 16:06
-
How are you calculating the gravity over time? I added a note to my post above but it looks like Blindman already went into much greater detail. – Phaelax z Jul 28 '21 at 17:38
Jump? How high?
Gravity is constant, but the distance to the obstacle is changing as we approach.
At some point there is a distance to the obstacle where the jump velocity is the minimum needed to clear it.
Further back will require a greater velocity to stay in the air long enough to clear it, or closer the velocity must be greater to clear in the reaming time.
It is unclear if you want the optimal jump velocity to clear an object, which will also define when to jump.
So we will just make it Given gravity as acceleration and a horizontal velocity what vertical velocity is required to jump an obstacle of height and distance.
Getting jump velocity
To keep it simple as we go we first normalize the horizontal velocity
Terms used
v
is jump velocity, or initial velocity (positive is up)t
is timea
is acceleration due to gravity (negative is down)h
is obstacle height. Positive is upd
is distance to obstacle. Equivalent to normalized horizontal velocitys
is horizontal velocity. Assumes positive towards obstacle.
Steps used to solve
The equation for velocity at time when falling (free fall) is v + at
With the equation f'(t) = v + at
the anti-derivative of that equation which is f(t) = vt + (1/2)at^2
tells use how high we are at any time t
Because we have normalized horizontal velocity s
the distance to the obstacle is equivalent to time to obstacle t
or distance to obstacle d
We can also use the anti-derivative to solve a height for a given distance h = vd+(1/2)ad^2
(replacing t
with d
)
Now we have all the terms we want in the one equation. h = vd+(1/2)ad^2
We want the jump velocity so rearrange h = vd+(1/2)ad^2
in terms of v
we get v = -ad/2+h/d
One last thing. The horizontal velocity is normalized and thus always 1. We need to use any velocity. We can do this by dividing the distance to obstacle d
by the horizontal velocity (speed) s
. In other words how long in seconds to cover distance d
at speed s
The final result is v = -a(d/s)/2+h/(d/s)
As code
Lets put that into code (JavaScript)
The function jumpObstacle(jumper, obstacle)
will set the jump velocity of the object jumper
to clear the object obstacle
only if the jumper is moving towards the obstacle.
The Jumper has a jumpClear
to give a clearance and a max jump velocity maxJumpVel
. This means that the jump may not clear the obstacle.
The function returns the jump height or 0 if no jump.
// 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;
}
Demo
I am not sure if the answer is as clear it should be. The demo implements the above as a interactive demo.
Click or Tap the animation when box is in range of wall. The jumpObstacle function will calculate the jump velocity needed to clear the wall.
I have also added the width of the box, and the x jump clearance to ensure that the jump visually clears the wall.
If the jumper can not clear the wall it will flash red. Try again next time around.
The red box under the ground indicates the approx distance that the jumper is able to clear the wall.
Note that the coordinates are Y+ is down
Note The lowest jump speed I manged to was 271px per second
// 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>

- 51,134
- 11
- 73
- 136