# 1.14.4 Moveable spring simulation

Discussion in 'Spigot Plugin Development' started by CaptainXan, Mar 16, 2020.

Not open for further replies.
1. ### CaptainXan

I'm working on a feature that will make it possible for a player to catch another player and connect them using a "rubber band". As the player moves around the player that got caught will swing around using a spring simulation. I've tried several math formulas but none of them seem to accomplish what I had in mind.

This GIF is a perfect example of what I'd hope to accomplish.
Red box = player, Blue cirlce = player that got caught

Hopefully somebody can help me out with this.

bump

3. ### drives_a_ford Moderator

If the object on the other end of the spring is not in the spring's equilibrium position, there will be an elastic force acting upon both ends of the spring (F = k ∆x). You probably want to assume that one end (the one that's not supposed to move) is rigid.
Given Newton's second law of motion (F = m a) you can get the relationship between the acceleration of the body (a) and the displacement (∆x).

Now, the problem is that the API doesn't have the means to set acceleration. So you'll have to manage that yourself.
So during each tick, you'll have to calculate the current acceleration (the relation between acceleration and displacement above) and then get the velocity that needs to be added. You can get the necessary velocity to add by assuming the last tick had a constant acceleration and it took 50ms. So from ∆v = a ∆t you can get the additional velocity.

Make sure to get the vector from the moving object's location to the center's location, then Vector#normalize and Vector#multiply with your ∆v.

Another thing to keep in mind is that you want to add the velocity, not set it. So first Entity#getVelocity and then Vector#add and only then Entity#setVelocity.

• Useful x 1
4. ### Schottky

The problem here is, that
1) You are neglecting the dimensionality of the problem (1D vs potentially 3D)
2) You have stated the mechanical equations, but not a method to solve them. So far, we have
m * a = k * x. As the acceleration is the second-order derivative of the way x, we have m * x'' = k * x, which is a differential equation.
3) In my opinion, we cannot assume that the one end is rigid, based on the fact that the player can move. Probably it's an acceptable simplification, but you should mention that a better approach would be to state F_player + F_spring - F_total = 0. The player force could (for example) be modeled as the velocity, multiplied by a constant k.
Consequences:
The equation should be rewritten as:
m * a = K * x, where a and x are vectors and K is a tensor (a matrix), describing the behavior of the spring in all possible "directions". You will now have to solve this set of coupled second-order differential equations (numerically). I believe a simple leapfrog-solver should do the trick here.
For simplification purposes, we could assume the Tensor K to be a diagonal-matrix (which means that the spring is basically a ball made out of some elastic material or something), in that case, we can solve each equation separately and get the total movement using a superposition of all movements.
As mentioned above, you can use a simple Leapfrog solver (or any Euler-method or any other numerical integration method) to solve these equations.

#4
Last edited: Mar 19, 2020
5. ### drives_a_ford Moderator

There is no need to do any of that.
You just solve m a = k ∆x for a = k ∆x/m. Now, given that time is already forcibly discrete, you can simple approximate a = dv/dt ≃ ∆v/∆t. Thus v/t = k ∆x/m gives you ∆v = ∆t k ∆x/m. That's all you need. You already know that ∆t is always 50ms and you can calculate ∆x from the two locations. The mass and the spring constant can also be combined into 1 constant since there is no effective 'mass' that a player has in game.

And while this is a 3D problem, you can simply solve it as a 1 D problem (for the modulus) and then simply create a vector of the length you calculated. At any given moment in time you can look at this problem as a 1D problem. The axes do not matter.

6. ### Schottky

The approximation you described is basically what a leapfrog-solver does (and obviously the mass and the feather-constant can be combined into one constant). My point (I'm sorry if I didn't communicate it that well) is, that you are proposing simplifications that I believe should at least be mentioned and should be applied if the simplifications yield an unrealistic result. A Spring does not "bounce" equally in all directions, and the player is definitely not rigid (again, unsure if that does anything, but by that, you are assuming he is pulling the spring with a zero-force. If the player were to move rapidly in the opposite direction of the spring, we might have an infeasible solution).

7. ### drives_a_ford Moderator

Just look at the 2D example he posted. One end is completely rigid.
This would become entirely useless if you allowed the other end to freely move along.

As for a spring not "bouncing equally in all directions", that's incorrect. The elastic force does not care about direction.
You could argue that gravity means it's not "bouncing" equally in all directions, but the velocity of players is already affected by gravity between 2 ticks in game.

And the simplifications I've mentioned will lead to as much of a realistic situation as this game allows.

But what do I know, I suppose.

#7
Last edited: Mar 19, 2020
8. ### Schottky

So you are saying that if you have any Spring in a 3D coordinate system, the equation F = k * x still holds for all Vectors x? No matter in which direction you displace the spring, this equation still holds? Not to be offensive or anything, but that is just not true.
And you can get more realistic, the question is just if you care. If you don't, that's fine, if you do, that's not.
By the rigid end, do you mean the red end? Again, you can say that this is a rigid end and take that as a simplification. But you can also say that the end is getting pushed by the mouse using a certain force. Just imagine the rigid end being moved constantly into one direction, while the loose end is oscillating. In your model, this would mean that it continues to oscillate, while in reality, it would not.

9. ### drives_a_ford Moderator

What are you on about exactly?
Imagine 2 points in a 3D space. Those are you two "ends" of the spring.
Now draw a line between those 2 points. On this line, F = k ∆x always holds.
It simply doesn't matter which way the spring is oriented. All that matters is that there's a displacement.

On the example, yes, the red end.

When the mouse is not moving, the red bit is stationary. When the mouse moves, the red bit moves with it. Whether you like it or not, for the benefit of this exercise, the red bit is rigid. If it does move, then we have no way of estimating its movement.

If you move the red bit at a constant velocity, you're simply talking about another inertial frame of reference. Move your frame of reference at a constant speed with the red end and you've still got a rigid red end.

10. ### Schottky

Ah, I see the whole issue here; we're talking about different frames of reference. I am talking about the global coordinate system, you are talking about the local one. But then your transformation back to the global System is a simple addition of velocities? You would, therefore, neglect every rotational aspect as well as how the player moves. Your spring would then just be a 'stick' between two points that can freely move in one direction, not something that (as the animation suggests) could freely rotate around the square.

Again, an issue of viewpoints here. If you are in your local coordinate system, I agree. If you are in the global coordinate system, you will have to model the movement somehow. I suggested a simple model, where the force is linear dependent with the velocity. Solving this analytically is probably somewhat impossible, therefore I was suggesting a numerical method.

11. ### drives_a_ford Moderator

The thing is, you don't care about anything other than the frame of reference with respect to the stationary red end of the spring. Everything else is dealt with by the MC server.
And since these are inertial frames of reference, measurements in one can be converted to measurements in the other by a simple transformation.

And no, this does not mean the spring can only move in the direction of the red end. If the red end "moves out of the way", the other end continues to move towards where the red end previously was. It's just that any additional velocity (∆v) would be added towards the red end.

Again, you do not need to model the movements of the other end. For all intents and purposes it is rigid. The elastic force does not control the movement of the other end. The player does.

12. ### Schottky

I think I gotta work on some visualization for clarification. I believe we are talking about the same thing, but words are the issue. But please explain to me this: How, in your model, would the spring start moving if the player moves (and the two positions; red and green; are the same). By that, I don't mean in the global System (where movement can obviously be expected), but in the local System (which would cause the 'lagging' effect; basically 'dragging' the spring behind you, like in the gif)

13. ### Maxx_Qc

Isn’t this what happen when you hold mobs on a lead while flying?

14. ### drives_a_ford Moderator

That's not a special case in any way. ∆v = ∆t k ∆x/m still applies. You get the additional velocity and add it to the current one.

15. ### VivianMusic

Jesus, people are getting genius responses to hard questions like this but my threads can't even get one reply. Oof

• Funny x 2
• Like x 1
16. ### Schottky

But in any iteration, the local system would only yield 0 as a solution. You are saying that ∆x is the displacement between the red and green object, but that stays zero in every iterate (thus resulting in an additional velocity of 0 that you are adding to the entity’s, effectively always putting the entity to where the player was). You are not modeling the ’inertia’ of the object in any way.

17. ### xDJ_

If I'm not mistaken, ∆x should just be x, right? In other words, the distance between the two objects. That should always be positive, so a force is always being applied.

18. ### drives_a_ford Moderator

If the player manages to move at exactly the same velocity as the "victim" (for a tick), then you'd simply get the same value for ∆v you did last tick. It'll only be 0 if the "victim" remains at the equilibrium distance. When the rigid end moves about freely at its will, this will not be the case for long.
Hell, even if ∆v=0, that doesn't guarantee the velocity of either is 0. So the "victim" might very well still move, thus creating a new ∆x and thus creating a new ∆v for the next tick.

The MC server deals with inertia itself (that's why you'll move a little after you've let go of the W button). You don't need to concern yourself with that.

Not necessarily. Depends on what you want. If you want the equilibrium to be a meter of few away, then your assumption would be wrong. If you want the other end to be pulled right up against you, your assumption would be correct.

• Agree x 1
19. ### xDJ_

Equilibrium is determined by other forces like friction and gravity though, so given a small enough spring constant it would be just plain x. I'm assuming delta x would be used when you want to keep about the same length of spring in between the objects, which isn't what's shown in the given gif.

20. ### Schottky

But the 'victim' does not move at any velocity itself; it is being moved by the player via the spring.
which is exactly my issue. If the player stops moving for long enough, the equilibrium will be reached. Then, if the player moves again, the entity will be given a velocity that is exactly the same as the player's velocity (due to the fact that ∆x is 0). If you look at the example above, the system is in an equilibrium state initially. Then, the red box is being moved, but the spring does not move at the same speed as the red one.

Again, I'm not saying your approach is wrong; I'm just saying that the result will not be as depicted in the gif. Just suppose you let go of the red box (as depicted in the last couple of frames). Why, in your model, would the spring start spinning around the player in any way?