# Solved Interpolate velocity

Discussion in 'Plugin Development' started by Techy4198, Aug 18, 2014.

Not open for further replies.
1. Offline

### Techy4198

I need some kind of way to interpolate between velocities, so say if the player is falling at maximum velocity and he turns on a 'jetpack', rather than immediately shooting up, it slows him to a hover, then starts accelerating him upwards. I know it's possible, but for some reason my code won't work. Also, this is not actually for a jetpack, something else, I just used a jetpack to make the example as clear as possible.

PS: this game I found demonstrates it quite well: http://impactjs.com/demos/physics/

Here is my current code. I probably messed something up big time. Btw I'm still only 14 so I haven't done any advanced math stuff in school yet.
Code:
```Vector targetVector(Vector current,Vector target,double accel){
Vector v = current;
if(current.getX()<target.getX()){
v.setX(Math.max(v.getX()+(target.getX()*accel),target.getX()));
} else {
v.setX(Math.min(v.getX()-(target.getX()*accel),target.getX()));
}
if(current.getY()<target.getY()){
v.setY(Math.max(v.getY()+(target.getY()*accel),target.getY()));
} else {
v.setY(Math.min(v.getY()-(target.getY()*accel),target.getY()));
}
if(current.getZ()<target.getZ()){
v.setZ(Math.max(v.getZ()+(target.getZ()*accel),target.getZ()));
} else {
v.setZ(Math.min(v.getZ()-(target.getZ()*accel),target.getZ()));
}
return v;
}```
EDIT by Moderator: merged posts, please use the edit button instead of double posting.

Last edited by a moderator: Jun 9, 2016
#1
2. Offline

### Lactem

So you basically want to make the velocity slow down and then increase it? This sounds like you should have a runnable and decrease your velocity variable until it gets to the desired result (1 or 2 or 3 or something) and then increase it until it reaches something higher.

#2
3. Offline

### xTrollxDudex

So what exactly isn't working? What happens when you run the code?

#3
4. Offline

### Techy4198

when I run the code, it just instantly goes to the target velocity. Also, it's not quite in a runnable, but it fires out entities every 2 ticks, like water jet. Each entity is supposed to apply a bit of force, and the more entities there are, the faster it should get to max velocity.

#4
5. Offline

### LucasEmanuel

There is no need for all of that, you only have to get their velocity vector, multiply it by the percentage of the velocity you want them to have after the deceleration, then use that new vector as the new velocity for the player.

EDIT:
For example, lets say that for each time you fire a water entity you want them to be slowed down by 10%, so the pseudo code would be:

Code:
```Vector v = players_current_velocity;
v.multiply(0.9);
player.setvelocity(v);```
then you do this everytime you launch that water entity. But remember on a perfect server there are 20 ticks per second, so if you fire that water entity every 2 ticks then you are doing this 10 times per second which is pretty fast.

#5
6. Offline

### Rocoty

Or...just add the desired directional vector to the original vector and THEN set the player's velocity to that new vector, instead of setting the player's vector to the desired direction.

#6
7. Offline

### Techy4198

Rocoty
If I add a vector of (0,1,0) to a player that already has that velocity anyway, he will surely end up going twice as fast? I don't want that.

LucasEmanuel If I keep multiplying it by 0.9, won't the player eventually end up perfectly still? You seem to be only decelerating the player, not pushing them towards a new velocity.

#7
8. Offline

### LucasEmanuel

ah yes, forgot that part.

#8
9. Offline

### Rocoty

Techy4198 Right. Well, if you add a velocity of something like (0,0.3,0) to a player who has a velocity of (1, -3, 1.7), he will end up with a velocity of (1, -2.7, 1.7). If you do that every tick, they will start slowly ascending. So, if you don't want them to ascend faster than a certain y-speed, all you have to do is check if their y-velocity is greater than a certain value before applying the addition.

#9
10. Offline

### Techy4198

Let me get this right, vectors represent the actual velocity right? NOT the coordinates the player is heading towards? If a Bukkit vector represents an actual point in the world, that explains so much of my difficulties. Can someone clarify this?

Edit: Rocoty yeah there I go again, forgetting that velocities aren't integers...

#10
11. Offline

### Rocoty

A vector can represent many things. Usually they represent either coordinates in the world, or velocities. It depends on the use case. In this case the vector represents the player's actual velocity. Not the coordinates they are heading towards.

#11
12. Offline

### Techy4198

Thank god. If a velocity vector represented actual coordinates, OH BOY would I be stumped.

#12
Rocoty likes this.
13. Offline

### Techy4198

Just realized after deleting an unused duplicate class file, I've been modifying that file instead of the right one for about 3 weeks No backup of the class file I had, so I'm currently re-writing most of my velocity check code from scratch. Will report back after testing.

#13
14. Offline

### Garris0n

Acceleration:
int i = 0;
i++;
There. Problem solved.

#14
15. Offline

### Techy4198

Yep, works perfectly now. Now I just gotta mess around with velocity and force until I hit something which feels natural.

Also Garris0n WTF? That doesn't work for velocities in negative x/y/z and doesn't go smoothly from current velocity. My new method works fine, although I may switch out the linear 'add velocity*0.1 until hitting max velocity' with something more like 'add (difference between current velocity and max velocity)*0.1 until hitting max' to try get a smooth acceleration curve rather than a linear acceleration. BTW I have not done physics in school yet so IDK how realistic or unrealistic my physics will turn out to be...

#15
16. Offline

### Garris0n

Of course it works for negative velocities.
Code:
```int i = -10;
for(int j = 0; j < 20; j++)
i++;```
There, from falling to going up.

#16
17. Offline

### Techy4198

Garris0n i mean if the player is going up and I want to push them down, then I need all kinds of if statements. Also no for loops, that would just accelerate the player in the opposite direction as fast as my CPU can count from 0 to 19.

#17
18. Offline

### Rocoty

Techy4198 I think what Garris0n is trying to show you is pseudo-code. Code you're supposed to not take literally but as guidance. Believe me, what he says is exactly the same as I said some posts back, and it will do what you are asking for, if you apply that addition to the Y of the player's current velocity every tick.

To clarify something in your previous post. This has very little to do with physics, but more to do with general vector mathematics. If you know the basics of vector mathematics it is pretty simple to imagine why and how it works.

#18
19. Offline

### Techy4198

Rocoty

I understand exactly how it would in theory work, but it still requires a ton of if-statements surrounding it in order to work in every direction.

Here is roughly what I have right now (pseudo-code)
Code:
```new.x=lerp(old.x,target.x,force/2)
(same for y and z, also some wrapper stuff to limit anti-gravity
exploits and handle target velocity inversion)```

#19
20. Offline

### Rocoty

Techy4198 I'm not sure how it would require a ton of if statements. Could you elaborate on that?

#20
21. Offline

### Techy4198

Rocoty it would require the if statements in order to make sure the velocity caps out at some maximum rather than infinitely growing. Terminal velocity basically. However, if you just lerp between the current velocity and the max velocity, like I did, there's no reason to have such if statements, instead just 3 lerps and lots of getX/Y/Z() and setX/Y/Z().

#21
22. Offline

### Rocoty

Techy4198 And what happened to Location::add or Vector::add? And I still don't see how it would be a ton of if-statements if you want to limit the velocity. One would suffice, surely? I frankly don't see where you're going.

#22
23. Offline

### Techy4198

Rocoty you would have to limit x y and z individually, and also adding to vectors/locations has no way to limit it. Just thought, instead of if statements, the following would probably suffice:
Code:
```vec.add(otherVec);
vec.setX(min(max(vec.getX(),-otherVec.getX()),otherVec.getX()));
vec.setY(min(max(vec.getY(),-otherVec.getY()),otherVec.getY()));
vec.setZ(min(max(vec.getZ(),-otherVec.getZ()),otherVec.getZ()));```
So that cuts it down to 4 lines, but lerp cuts it to 3 and makes it smoother and more realistic:
Code:
```vec.setX(lerp(vec.getX(),otherVec.getX()));
vec.setY(lerp(vec.getY(),otherVec.getY()));
vec.setZ(lerp(vec.getZ(),otherVec.getZ()));```
Btw as you can see I limit the velocity based on the target velocity rather than a fixed value, so there isn't a true terminal velocity, but that could be added within those 3 lines with a few extra max(otherVec.getSomething(),terminalVelocity), which is still independent for x y and z, but the most realistic i can think of.

PS: yes, i kinda proved myself wrong.

#23