BeRo1985 / kraft

Kraft Physics Engine is an open source Object Pascal physics engine library that can be used in 3D games.
107 stars 21 forks source link

Feature request: Constrain position changes to particular axes (for 2D games) #17

Closed michaliskambi closed 7 years ago

michaliskambi commented 7 years ago

In order to use Kraft for 2D games, I needed two things:

  1. constrain rotations to only happen around the Z axis. This is already straightforward using the krbfLockAxis* Flags.
  2. constrain translation to only happen along the X and Y axis. I'm right now doing it using a rather hacky method (more info below).

My feature request is to add flags like

krbfLockTranslationX
krbfLockTranslationY
krbfLockTranslationZ

to the TKraftRigidBodyFlag .

Once you constrain the rotations and positions like above, one can use Kraft for 2D games very comfortably :) Demo (where I constrain position using my hacky method below) is on https://www.youtube.com/watch?v=hIuEGnRm-yM , more information on https://castle-engine.sourceforge.io/wp/2017/09/13/castle-game-engine-2d-physics-using-kraft/ . The CGE manual on https://castle-engine.sourceforge.io/manual_physics.php also has a short section "2D games".

Right now, I constrain the position using this code:

    NewPos := Shape.GetCenter(Shape.InterpolatedWorldTransform);
    if LockPosition <> [] then
    begin
      // apply LockPosition to fix some NewPos coords
      if 0 in LockPosition then NewPos.X := Transform.Translation[0];
      if 1 in LockPosition then NewPos.Y := Transform.Translation[1];
      if 2 in LockPosition then NewPos.Z := Transform.Translation[2];
    end;
    Transform.Translation := VectorFromKraft(NewPos);
    if LockPosition <> [] then
      // fix also position at Kraft side after fixing by LockPosition
      Body.SetWorldTransformation(MatrixToKraft(Transform.Transform));

In other words, I implement the LockPosition by taking the position calculated by Kraft, reverting some of it's components (the locked components) to the previous position, and sending the "fixed" position back to Kraft. This actually works very well (as the demo shows), but it feels like a hack, as I'm reading + writing back the object position every frame, instead of "just reading" the position calculated by Kraft.

If Kraft would allow me to do something like

RigidBody.Flags := RigidBody.Flags + [krbfLockTranslationZ]

then the work would be done on the Kraft side, in a more cleaner way I think:)

BeRo1985 commented 7 years ago

Added to my todo list :smiley:

BeRo1985 commented 7 years ago

Added, see https://github.com/BeRo1985/kraft/commit/9cbf57722fc10be1c0516b5bb089704ec2d9482d