Apply impulse problem

Posts regarding potential bugs, enhancement requests, and general feedback on use of dyn4j
pheelbert
Posts: 3
Joined: Tue Aug 05, 2014 4:09 pm

Apply impulse problem

Postby pheelbert » Tue Aug 05, 2014 5:30 pm

I do not know if this is a misunderstanding of how the engine works or lack of knowledge in physics, but I need to feed in an absurdly big number in body.applyImpulse for it to acheive way less than I would want it to.
I'd like to be able to make stuff move fast against gravity given a huge impulse, for example.

Here is an image of the code that should matter:
Image

I switch the delta from microseconds to seconds in PhysicEngine's update method.
I make the ellipse for the player a little smaller since there is some empty area on the sprite I use, I know that's pretty messy..

PS: Are the fixtures' translation position their center or top left?

Thank you a lot for any and all responses, I would really need to get this sorted out!

William
Site Admin
Posts: 349
Joined: Sat Feb 06, 2010 10:23 pm

Re: Apply impulse problem

Postby William » Tue Aug 05, 2014 6:48 pm

pheelbert wrote:but I need to feed in an absurdly big number in body.applyImpulse for it to acheive way less than I would want it to.
I'd like to be able to make stuff move fast against gravity given a huge impulse, for example.

When you create the Ellipse, what is the width/height that you are using? Remember, dyn4j uses the MKS (meter-kilogram-second) unit system. For example, if you do new Circle(1.0), you've create a 1 meter radius circle, in other words a circle the height of 1 story building. So, if you are passing in pixel values, you will have one heavy object, which will require an enormous force to move. I suspect this is why you've set gravity to 200 m/s^2 as well? If that's not the case can you report back what body.getMass().getMass() is?

Typically, you'll define a constant somewhere that defines the number of pixels per meter and use that to scale any values you send to dyn4j. The default that the Sandbox app uses is 32 pixels / 1 meter. So 256 pixels would be 256 / 32 = 8 meters.

pheelbert wrote:PS: Are the fixtures' translation position their center or top left?

The body.getWorldCenter() returns the center of mass of the body, which may not correspond to the geometric center of the body. Some shapes, Ellipse for example, will always have their center at the origin (0, 0) at creation. The center of mass of an ellipse happens to be the geometric center of the ellipse as well. So, before calling body.translate, body.getWorldCenter() should return (0,0). The translate method, in effect, moves the center of mass. So, in this case body.getWorldCenter() would return whatever you passed in the translate method.

You can get the fixture's center, which is always the geometric center, by doing: body.getWorldPoint(body.getFixture(0).getCenter()); You can get the current top left position by: body.getFixture(0).createAABB(body.getTransform()); and looking at the max y and min x values. Note, that the AABB can change if the body/fixture is rotated.

William

pheelbert
Posts: 3
Joined: Tue Aug 05, 2014 4:09 pm

Re: Apply impulse problem

Postby pheelbert » Tue Aug 05, 2014 8:45 pm

Thank you for the quick reply!

As for the questions you've asked ...

Code: Select all

Geometry.createEllipse(30, 73);

body.getMass().getMass();
Output: 1720.0219778404116


So would it be possible to keep those sprite dimensions and make my object lighter?
Sorry I'm somewhat slow when it comes to this, if I'm asking too much don't hesitate to tell me so!

William
Site Admin
Posts: 349
Joined: Sat Feb 06, 2010 10:23 pm

Re: Apply impulse problem

Postby William » Wed Aug 06, 2014 9:00 am

pheelbert wrote:So would it be possible to keep those sprite dimensions and make my object lighter?

The idea is set X pixels = X meters and convert to and from pixels and meters. Use pixels for rendering and meters for physics.

Take a look at this older post.

The ExampleImages.java file in that post is a good example of how to do this. It's using Java 2D's AffineTransform class to do most of the conversion, but this isn't necessary. Generally, you need to do something like this:

Code: Select all

public final class Helper {
   // the scaling factor. 
   // How many pixels represent 1 meter? 
   // It's arbitrary, you decide!
   public double scale = 100.0;
   
   public double toWorld(double value) {
      return value / scale;
   }
   
   public double toScreen(double value) {
      return value * scale;
   }
   
   public Vector2 toWorld(Vector2 point) {
      return new Vector2(point.x / scale, point.y / scale);
   }
   
   public Vector2 toScreen(Vector2 point) {
      return new Vector2(point.x * scale, point.y * scale);
   }
}

// usage
// obj is your pixel based object
Body body = new Body();
body.addFixture(Geometry.createCircle(Helper.toWorld(obj.radius)));
body.translate(Helper.toWorld(new Vector2(obj.x, obj.y)));
// get the values
Vector2 wc = body.getWorldCenter();
// convert to screen space
Vector2 sc = Helper.toScreen(wc);
// now sc contains the pixel based coordinates


William

pheelbert
Posts: 3
Joined: Tue Aug 05, 2014 4:09 pm

Re: Apply impulse problem

Postby pheelbert » Wed Aug 06, 2014 7:52 pm

It seems to be working, just a little more tweaking to do on the values I put in (because obviously now 2000 impulse for left and right makes no sense)!
Thanks a lot, you were really helpful :).


Return to “Bugs, Enhancements, Feedback”

Who is online

Users browsing this forum: No registered users and 1 guest