Lusito / box2d.ts

Full blown Box2D Ecosystem for the web, written in TypeScript
https://lusito.github.io/box2d.ts
60 stars 6 forks source link

An error occurs when using the SetTransformXY method #42

Closed 8Observer8 closed 1 year ago

8Observer8 commented 1 year ago

@Lusito hi! How are you? I hope you are alive. There was no activity from you for six months.

I am making a simple Pong game. Sandbox: https://plnkr.co/edit/ievETHfAsuARZtzf?preview

I want to set a ball position to zero when it collides with holes:

image

I try to make it in the contact-listener.js file:

         let ballBody = null;

        if (nameA === "leftPointTrigger" || nameB === "rightPointTrigger" ||
            nameA === "rightPointTrigger" || nameB === "leftPointTrigger") {
            if (nameA === "ball") {
                ballBody = fixtureA.GetBody();
            } else {
                ballBody = fixtureB.GetBody();
            }
            ballBody.SetTransformXY(0, 0, 0);
        }

But the error happens when the ball collides with holes at this line: ballBody.SetTransformXY(0, 0, 0); in the contact-listener.js file:

image

Lusito commented 1 year ago

Hi @8Observer8,

I am fine, just a bit busy after moving to a new city and having to renovate my new home.

In box2d (also the original lib)You can not modify physics within a contact listener. You will need to delay that until the world step is done.

You can either do that using a queue that you process after the world step or possibly even via requestanimationframe or settimeout with 0 seconds delay. I have not tried the last 2 methods, they are just an idea.

Hope that helps

8Observer8 commented 1 year ago

@Lusito I'm happy that you're okay!

You can either do that using a queue that you process after the world step

Could you explain what do you mean?

settimeout with 0 seconds delay

It doesn't work:

        setTimeout(() => {
            world.Step(dt, { velocityIterations: 3, positionIterations: 2 });
         }, 0);
Lusito commented 1 year ago

You misunderstood. In your contact listener, instead of calling SetTransform instantly, you need to call it delayed.

Contact listeners are called during world step. If you modify stuff during world step, things stop working. So you need to wrap your SetTransform in a setTimeout, not the world step.

About the queue: Without setTimeout, you would need to create an array where you can push physic changes that happen during world step (applying force, deleting or creating objects, etcs. Then after calling world step, you iterate over that array and execute those changes

8Observer8 commented 1 year ago

Thanks a lot! I created a fork for solution: https://plnkr.co/edit/ElTA0CW28HjDweAg?preview

@Lusito please set up discussions: https://docs.github.com/en/discussions/quickstart

8Observer8 commented 1 year ago

I want to publish my simple games and examples in discussions.

Lusito commented 1 year ago

Done