mphe / GDNative-Ropesim

A 2D verlet integration based rope simulation for Godot 4. Written in C++ using GDExtension for fast performance.
MIT License
60 stars 2 forks source link

Velocity calculation doesn't take parallax layers into account #19

Open bienjensu opened 1 week ago

bienjensu commented 1 week ago

Placing a rope on a parallax layer and moving the camera causes a movement in the rope when motion_scale on the ParallaxLayer is set to anything other than Vector2.ONE.

This feels like incorrect behaviour.

Had a quick look at the code but couldn't see a fix.

mphe commented 1 week ago

Technically it is correct behavior, because the node is moved and the rope inherently reacts to movement.

You can tick the pause property on the rope object to disable simulation.

Edit: I agree it is not very intuitive that the rope is affected by parallax movement, but I'm not sure if this can be handled in a simple manner.

What exactly is your use case? Do you still need simulation to be enabled, just no react to camera movement?

bienjensu commented 1 week ago

Thanks for the information.

I'm using the rope decoratively for an object on a parallax layer.

Hence, I don't want the rope to react simply while the camera is moving.

However, I do still need the rope to simulate when the object is moved. Also, I can't just pause it while the camera moves, as the object can be dragged at the same time the camera is moving.

I'll have a look to see if it's as simple as checking if the rope is on a parallax layer, and then applying the basis of the motion scale.

mphe commented 1 week ago

I see. Luckily I just remembered there is a simple workaround.

You can use a RopeRendererLine2D for rendering, if you are not already using it. Place it in the parallax layer and the rope node outside the parallax layer. This way the rope rendering is affected by the parallax layer but not the rope itself. And you can still interact with the rope.

An alternative solution would be to use a CanvasLayer with follow_viewport_scale instead of a ParallaxLayer. This works because it does not modify the node's position. However, it performs perspective scaling which might be undesired.

I'll have a look to see if it's as simple as checking if the rope is on a parallax layer, and then applying the basis of the motion scale.

It's not as simple unfortunately. In order to cancel the movement, the position difference of the parallax layer needs to be tracked. Then this difference needs to be added to all rope points, not just the root point, so the rope is moved uniformly. Additionally, the old points array needs to be updated accordingly as well, so the position shift is not interpreted as velocity. Easy so far. Problems arise with RopeHandles. These are also affected by the parallax layer and update the corresponding rope points to their new position. Now if we apply the shift from earlier, these points will get moved double the distance. That means, handles need to be aware of parallax layers as well.

As you see there are quite some interactions going on that need to be handled properly. Also a generic solution would be nice, since this problem can also be transferred to e.g. an elevator-like situation, where the rope is part of a moving entity but should not be affected by the outer movement.

While not impossible, this will require quite some time and effort to implement in a clean and reliable manner. So, ideally we can make the workarounds work for you.