schteppe / p2.js

JavaScript 2D physics library
Other
2.64k stars 330 forks source link

springs | damping parameter of spring 1 affects newly created spring 2 if spring 1 is removed in a streched state #130

Closed valueerrorx closed 10 years ago

valueerrorx commented 10 years ago

i created two testcases. you can create a spring between the body that is fixed to the mouse and the circle by clicking on the circle ! if you let go of the mousebutton the spring will be removed immediately so you can throw the circle.

i made the following examples in phaser but tried to use p2 directly to rule out the possibility that it's a phaser bug :)

(damping : 0 ) http://test.xapient.net/phaser/springtest/index1.html (damping: 2 ) http://test.xapient.net/phaser/springtest/index2.html

as you can see in the second example every new spring created is influenced by the one you just destroyed. if you strech a spring very much and then let go of it and create a new spring the new one will have a strange offset that is slowly reducing itself.

if you wait long enough for the offset to get to almost to zero the next spring will behave normal again. (as if the damping or the streched state of spring 1 is still somewhere in the p2 world and beeing applied to spring 2 even if spring 1 doesn't exist anymore)

reproducable: always.

the only way to get rid of this distance/damping transfer from one spring to the other is by setting damping to 0 (but that way the objects get too fast and the whole thing becomes unusable)

schteppe commented 10 years ago

I think this is no bug, but rather a consequence of how the spring damper works.

The damping is only working in the spring direction. In the orthogonal direction, there's no friction, which makes it possible for the spring to rotate around the connection point freely. Like a satellite, but with resistance when it tries to move closer or away from Earth.

The first time you attach the spring, there's no initial velocity, and the ball will go straight for the spring connection point. No satellite behavior. The second time, it will have some initial velocity, and almost in 100% of the cases, this velocity will make the ball not go straight to the connection point. Which will make it possible for it to get into "orbit" :)

I suggest you add some velocity damping to the ball, this will prevent this "satellite behavior", and make the ball spiral faster to the connection point. For example:

// In the create function
circle.body.damping = 0.7;

You could also try to implement own damping in the direction orthogonal to the spring.

valueerrorx commented 10 years ago

catching a moving object and connecting it to a spring results in a satellite behaviour.. thats right and thats really ok... it is the realistic thing that should happen.. but catching an object that rarely moves and then - the moment you apply the spring - suddenly moves away 4 inches on the screen and slooooowly reduces the distance to the other object afterwards seems to be something different.. and not intended

please try my second example ... throw the big ball (try to stretch the spring as much as possible when releasing it) and then catch the ball.. oke then it is very likely moving fast and orbiting so the effect is not easily seen.. let it go again. now the ball should not move very much because you didn't throw it

fetch it a second time.. the moment you click on it it will go into safe distance of the center of the mousebody and stay there - closing in very slowly..

adding body damping would affect the speed of the body after letting it go too .. wouldn't it ? i think i already tried body.damping but it did nothing when the body was on the spring but then (released) slowed the body down (which is also unwanted)

valueerrorx commented 10 years ago

http://test.xapient.net/phaser/springtest/index3.html

i made a third example with 2 circles now you can throw the 1st circle and then click on the other circle that is at zero velocity .. the second circle will suddenly move away !

there is no such effect if you make sure you release the first circle when its not moving and the spring is in it's center

schteppe commented 10 years ago

The second circle will start moving if you click on it anywhere, except the center. Which is expected, since the spring attachment point is at the circle center. And the spring rest length is zero. Right?

valueerrorx commented 10 years ago

sorry to bother you with this but i think we are not talking about the same thing.. what you are saying is all true and it is the natural thing i would exspect.. when i click into the absolute center of the circle and i didn't move anything before.. nothing happens because my restlength is zero.. IF i move one of the circles first and then click the absolute center of the other (still not moving) circle it suddenly jumps to the side..

to be absolutely sure you know what i am trying to say i made a video so you don't have to recreate it yourself..

what you see there: first i click the center of the circle.. nothing then i click on the edge.. the exact thing you described happens.. thats fine!!! then i move the circel and let it go on high speed then i click the other (not moving) circle in the exact center the circle suddeny jumps into a safe distance you can then see that this distance is reducing itself slowly.. if i wait until its 0 i can safely click on another circle into the center and again (as expected) nothing will happen..

(you can hear my clicks) http://test.xapient.net/phaser/springtest/test.mp4

i really hope you can see now that this is not the intended behaviour.. i already talked to rich about this and he told me that this is not a phaser problem - it has to be something related to p2

thanks in advance !

schteppe commented 10 years ago

Oooooh. Now I see what you mean! Thanks for the video. This is definitely a bug, not sure why it happens though. Will try to find out why.

schteppe commented 10 years ago

Okay, I found it! You need to set the anchor body as static. Otherwise, the spring will apply force to it, and it will get velocity. You don't actually see this velocity in action since you always set the position of the anchor body each frame. This "hidden velocity" is added to the calculations of the damping.

To fix, do this:

mouseAnchor.body.static = true;
valueerrorx commented 10 years ago

Wow .. thank you so much! works as advertised :) http://test.xapient.net/phaser/springtest/index4.html (the prove) my game suddenly is playable again.

so it's not actually a bug and can be resolved in phaser after all.

thx again :)