4ian / GDevelop

🎮 Open-source, cross-platform 2D/3D/multiplayer game engine designed for everyone.
https://gdevelop.io
Other
9.62k stars 806 forks source link

Change physics actions to apply forces at center of mass by default #4002

Open tristanbob opened 2 years ago

tristanbob commented 2 years ago

Description

The first time I tried using physics, my objects were always spinning. It was frustrating and confusing until I realized that I left the "apply force at" fields blank and they need to use the center point (or center of mass). I think this problem affects many new users, and it adds two extra steps when nearly all users want the force to be applied at the center.

Solution suggested

Alternatives considered

This could affect existing games that rely on the force being applied to the origin. This change might require a new version of the action to be created to maintain the same behavior.

tristanbob commented 1 year ago

I'm going to see if I can make this change. Here is my idea:

4ian/GDevelop/Extensions/Physics2Behavior/physics2runtimebehavior.ts

    applyForce(
      forceX: float,
      forceY: float,
      positionX: float,
      positionY: float
    ): void {
      // If there is no body, set a new one
      if (this._body === null) {
        if (!this.createBody()) return;
      }
      const body = this._body!;

      // Wake up the object
      body.SetAwake(true);

// Use the center of mass if no position is provided
if (positionX === null) {
        positionX = this.getMassCenterX()
}

if (positionY === null) {
        positionY = this.getMassCenterY()
}

      // Apply the force
      body.ApplyForce(
        this.b2Vec2(forceX, forceY),
        this.b2Vec2Sec(
          positionX * this._sharedData.invScaleX,
          positionY * this._sharedData.invScaleY
        ),
        // TODO Should let Box2d awake the object itself.
        false
      );
    }
4ian commented 1 year ago

This is more or less how you would do it for a traditional JS function (but with undefined to allow the caller to not pass anything, or using null as you did but then the caller needs to pass null).

The issue is that expressions returning numbers in GDevelop are always returning "0" if you don't specify anything. They are guaranteed to be a number. So this approach would need to support a new construction in an action/condition, which would be numbers which, when not filled, are sending null or undefined to the JavaScript. This would also need to change slightly in the interface to make clear to the user that "it's fine not to fill this, in which case the center of mass will be used". In other words, it's a concept of "optional" parameters.

tristanbob commented 1 year ago

@4ian thanks for the detailed response. I'm afraid the scope of the change you described is outside my current abilities.

I'll leave this for someone else to take the lead.

tristanbob commented 1 year ago

The issue is that expressions returning numbers in GDevelop are always returning "0" if you don't specify anything. They are guaranteed to be a number. So this approach would need to support a new construction in an action/condition, which would be numbers which, when not filled, are sending null or undefined to the JavaScript. This would also need to change slightly in the interface to make clear to the user that "it's fine not to fill this, in which case the center of mass will be used". In other words, it's a concept of "optional" parameters.

Are there any examples of similar functionality in GDevelop that I can learn from?

tristanbob commented 12 months ago

My javascript skills have increased enough to attempt this again.
Is this being done anywhere else in the GDevelop app?

I believe this is one of the biggest obstacles when people try using Physics for the first time.

D8H commented 10 months ago

Box2D has 2 methods:

I think it would make sense to have 2 actions in GDevelop too.