简体   繁体   中英

applyLinearImpulse not working (Box2d)?

I am using a ContactListener to listen for any contact, and if collision is detected between the ball and ground, the ball should get an impulse in the upward direction, which is provided in the void endContact() function of the ContactListener class. But this impulse is having no effect at all, for any impulse value. The ball just bounces off the same distance for any impulse value. What am I doing wrong. Here's the full code:

public class Game implements ApplicationListener {
     World world ;  
     Box2DDebugRenderer debugRenderer;  
     OrthographicCamera camera;  
     static final float BOX_STEP=1/60f;  
     static final int BOX_VELOCITY_ITERATIONS=8;  
     static final int BOX_POSITION_ITERATIONS=3;  
     static final float WORLD_TO_BOX=0.01f;  
     static final float BOX_WORLD_TO=100f;  
     Rectangle ball;
     Body body;

    @Override  
     public void create() {
          world = new World(new Vector2(0, -100), true);
          camera = new OrthographicCamera(); 

          camera.viewportHeight = 480;  
          camera.viewportWidth = 800;  
          camera.position.set(camera.viewportWidth * .5f, camera.viewportHeight * .5f, 0f);  
          camera.update();

          //Ground body  
          BodyDef groundBodyDef =new BodyDef();  
          groundBodyDef.position.set(new Vector2(0, 10));  
          Body groundBody = world.createBody(groundBodyDef);  
          PolygonShape groundBox = new PolygonShape();  
          groundBox.setAsBox((camera.viewportWidth) * 2, 10.0f);  
          groundBody.createFixture(groundBox, 0.0f);  

          //Dynamic Body  
          BodyDef bodyDef = new BodyDef();  
          bodyDef.type = BodyType.DynamicBody;  
          bodyDef.position.set(camera.viewportWidth / 8, camera.viewportHeight / 2);  
          body = world.createBody(bodyDef); 

          // create a Rectangle to logically represent the ball
          CircleShape dynamicCircle = new CircleShape();  
          dynamicCircle.setRadius(40f);  
          FixtureDef fixtureDef = new FixtureDef();  
          fixtureDef.shape = dynamicCircle;  
          fixtureDef.density = 1.0f;  
          fixtureDef.friction = 0.0f;  
          fixtureDef.restitution =1f;
          body.createFixture(fixtureDef);
          debugRenderer = new Box2DDebugRenderer();  

          listener listener1=new listener();
          world.setContactListener(listener1);
     }
     @Override  
     public void render() {            
          Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);  
          debugRenderer.render(world, camera.combined);  
          world.step(BOX_STEP, BOX_VELOCITY_ITERATIONS, BOX_POSITION_ITERATIONS);


     }  
     class listener implements ContactListener 
     {

        @Override
        public void beginContact(Contact contact) {
            // TODO Auto-generated method stub

        }

        @Override
        public void endContact(Contact contact) {
            // TODO Auto-generated method stub
            body.applyLinearImpulse(0, 500000f, body.getWorldCenter().x, body.getWorldCenter().y, true);
            //body.setLinearVelocity(0,50000000);
            System.out.println("Collision detected");
        }

        @Override
        public void preSolve(Contact contact, Manifold oldManifold) {
            // TODO Auto-generated method stub

        }

        @Override
        public void postSolve(Contact contact, ContactImpulse impulse) {
            // TODO Auto-generated method stub

        } 

     }; 

     @Override  
     public void resize(int width, int height) {  
     }  
     @Override  
     public void pause() {  
     }  
     @Override  
     public void resume() {  
     }  
     @Override  
     public void dispose() {  
     }  
}

In the original C++ version, EndContact is called inside the Step function, which is a time when you cannot alter anything in the world because the engine is still using it. I would think that the Java version is the same. You will probably need to make a note of the fact that the ball has bounced, and apply the impulse after the Step has finished.

The reason that there is no impact on of impulse is you are try to apply impulse in the endcontact method.

In box2d ContactListener methods you cannot change the property or position of body.

You can do like this

boolean b;
 @Override
    public void endContact(Contact contact) {
        // TODO Auto-generated method stub
        //body.applyLinearImpulse(0, 500000f, body.getWorldCenter().x, body.getWorldCenter().y, true);
        //body.setLinearVelocity(0,50000000);
       b = true;
        System.out.println("Collision detected");
    }

In you update method.....

if(b)
{
  body.applyLinearImpulse(0, 500000f, body.getWorldCenter().x, body.getWorldCenter().y, true);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM