liabru / matter-js

a 2D rigid body physics engine for the web ▲● ■
MIT License
16.83k stars 1.97k forks source link

Body.setParts breaks the physics of the Body entirely #1050

Open pagesrichie opened 3 years ago

pagesrichie commented 3 years ago

For this code here: https://codesandbox.io/s/phaser-tilemap-post-5-04-platformer-step-2-forked-mkues?file=/js/player.js

I added a simple on line 77: setTimeout(() => { Body.setParts(compoundBody, [mainBody, this.sensors.bottom]); }, 2000);

.. and the character completely falls through the screen ignoring/not respecting any and all physics.

For some games such as top down games where a character could be slashing a sword and we need to change the animation frames as well as the collision properties by deleting one of the sub bodies in a compound body, or adding another body in the compound body on the fly - this is crucial. If this isn't fixed, is there any other reported solution?

(Same issue as the comment form https://github.com/liabru/matter-js/issues/575#issuecomment-504803869)

liabru commented 3 years ago

This example looks a little complex for me to understand what's going on (I'm not a Phaser user myself). Is it possible to reproduce the problem in a minimal Matter.js only example?

dtgreene commented 3 years ago

I've been scratching my head at this problem as well. Here's a simple example.

In the example I set the parts when creating the body but I also got the same results when setting the parts after creation either directly through .parts or via Body.setParts.

liabru commented 2 years ago

Thanks for the example @dtgreene that does look strange. Worth trying out 0.18.0 to see if that resolves this, otherwise I'll have to investigate.

tylerfurtwangler commented 2 years ago

(should note I tried this on v0.18.0 with same result at v0.17.1)

I ran into a very similar situation, in which my game was setting the parts dynamically during runtime based on events. My setup was essentially: 1) use a Body as a container, call setParts with children bodies 2) when an event happened, replace the bodies with other bodies using setParts

When 2) happened, the bodies would appear to fall through objects etc. I think I traced down my issue by stepping through what the code in setParts was doing near https://github.com/liabru/matter-js/blob/master/src/body/Body.js#L420

The new children bodies when set on the container body would not have been translated compared to other bodies on the object nor the container body - essentially a body that was translated/rotated would then get a child body set with values that were relative. For me, I had to reverse the modifications and then re-apply them...

something like:

// ensure newChild body is reverted back to its original values in case it is being reused
Body.setPosition(newChild, Vector.create(childRelativeX, childRelativeY));
Body.setAngle(newChild, childRelativeRotation);

// now clear the container body, revert position/angle, then add bodies and re-apply position/angle
// there may be a better way to do this?
const p = Vector.clone(container.position);
const r = container.angle;
Body.setParts(container, []); // without doing this, I think it would change any existing child/part bodies on the next lines
Body.setAngle(container, 0);
Body.setPosition(container, Vector.create(0, 0));

// add new parts, reapply values
Body.setParts(container, [newChild]);
Body.setPosition(container, p);
Body.setAngle(container, r);
pagesrichie commented 2 years ago

@tylerfurtwangler Would you consider forking my codesandbox here: https://codesandbox.io/s/phaser-tilemap-post-5-04-platformer-step-2-forked-mkues?file=/js/player.js and attempting your method on that to see if it fixes it?

@liabru I'm too deep in the phaser 3 ecosphere with matterjs, hard to separate it out as a matterjs only example at the moment, sorry :/. I hope @dtgreene 's example helped simplify the problem that's going on to you! Were you able to make any headway into the solution for this?

Beasleydog commented 8 months ago

I'm having this issue as well, any update?