1
votes

If got a game project where I'm using box2d. Now in my MovementSystem (I'm using a Entity-Component-Based-Approach), I want Box2D to move my objects arround, according to the desired velocities which are set by the controls.

Unfortunately the velocities seems never to get high enough. Even when doing an applyLinearImpulse with a velocity-vector (the desired velocity) of 245044.23 for each axis for example, the resulting velocity of the body just became something about 90.0. What am I'm doing wrong? Is there a limitation or something?

Here's my code for running the velocity-update and world-step:

//************************
// physics-system
//************************
public void update(float deltaTime) {

        float frameTime = Math.min(deltaTime, 0.25f);
        accumulator += frameTime;
        if (accumulator >= MAX_STEP_TIME) {

            world.step(MAX_STEP_TIME, 6, 2);
            accumulator -= MAX_STEP_TIME;

            for (Entity entity : entities) {
                TransformComponent transform = tim.get(entity);
                BodyComponent bodyComp = bod.get(entity);
                VelocityComponent velocity = vel.get(entity);

                Vector2 bodyVelocity = bodyComp.body.getLinearVelocity();
                float velChangeX = velocity.horizontalVelocity - bodyVelocity.x;
                float velChangeY = velocity.verticalVelocity - bodyVelocity.y;

                float impulseX = bodyComp.body.getMass() * velChangeX;
                float impulseY = bodyComp.body.getMass() * velChangeY;

                bodyComp.body.applyLinearImpulse(new Vector2(impulseX, impulseY), bodyComp.body.getWorldCenter(),
                        false);

                // update transform
                Vector2 position = bodyComp.body.getPosition();
                transform.x = (int) position.x;
                transform.y = (int) position.y;

                // slowingdownVelocitys(velocity);

            }
        }

    }

And here the definiton of my currently only entity with a box2D-Component (called a BodyComponent):

        Entity entity = new Entity();
        //...
        BodyComponent bodyComponent = new BodyComponent();
        BodyDef bodyDef = new BodyDef();

        bodyDef.type = BodyDef.BodyType.DynamicBody;

        bodyDef.position.set(transformComponent.getX(), transformComponent.getY());

        bodyComponent.body = GameManager.getB2dWorld().createBody(bodyDef);
        bodyComponent.body.applyAngularImpulse(50f, true);

        CircleShape circle = new CircleShape();
        circle.setRadius(2f);

        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = circle;
        fixtureDef.density = 10f;
        fixtureDef.friction = 0.4f;
        fixtureDef.restitution = 0.6f; // Make it bounce a little bit

        bodyComponent.body.createFixture(fixtureDef);

        circle.dispose();

        entity.add(bodyComponent);
        //... 
1
Take a look of this threadAbhishek Aryan
Marc M, please consider accepting my answer if it solves your problem otherwise please leave a comment explaining what's unanswered still for you. Thank you!Louis Langholtz

1 Answers

2
votes

Box2D does limit velocities yes. The limit is there basically to avoid inaccuracies of floating point arithmetic. A velocity of 245044.23 with a step time of 1/60th of a second is well above this limit as you've discovered. If you could lower your step time to say 1/200000th of a second you could simulate 245044.23 meters per second but I think most of us would have trouble getting that to run in real-time. At a step rate of 60 steps per second (each step being only 1/60 of a simulated second), the velocity you've stated is approximately 4084 meters per step since Box2D units are basically MKS units (meters, kilograms, seconds). The velocity limit meanwhile is limited per step to 2 meters per step (by b2_maxTranslation). This limit can be increased but as it's increased you're more likely to see less physical-like behaviors like tunneling.

As to what you're doing wrong, besides trying to use a velocity way higher than Box2D can handle, usually problems like you've described are the result of the visual scaling used. Keep in mind that Box2D positions are in units of meters while most of our monitors are significantly smaller (in either horizontal or vertical direction) than a meter. The Box2D FAQ has this to say about scaling in terms of pixels:

Suppose you have a sprite for a character that is 100x100 pixels. You decide to use a scaling factor that is 0.01. This will make the character physics box 1m x 1m. So go make a physics box that is 1x1. Now suppose the character starts out at pixel coordinate (345,679). So position the physics box at (3.45,6.79). Now simulate the physics world. Suppose the character physics box moves to (2.31,4.98), so move your character sprite to pixel coordinates (231,498). Now the only tricky part is choosing a scaling factor. This really depends on your game. You should try to get your moving objects in the range 0.1 - 10 meters, with 1 meter being the sweet spot.

The question that you'll want to answer is what scaling to use such that the physical velocities which Box2D can handle can translate to the visual effect in a way that can still be seen. At the step simulation of 1/60 of second (per step), the limit of velocity that Box2D will deal with is +/- 120 meters per second. But with clever use of scaling between world coordinates and graphical coordinates, that can be like 120 units-of-distance per second where you can sort of make the units-of-distance to be kilometers or tera-meters or whatever.

Beware that going really slow can pose problems too - like running into the velocity threshold for collision responses (b2_velocityThreshold).

Hope this helps!