Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change position of a moving body - Box2D

I currently have a body created that is Dynamic and moves at a constant speed with a Vector2(). What I want is for when the body leaves the edge of the screen, to come back from that current point back to its original point instantaneously. How do I do this?

    a.applyForceToCenter(aMovement, true);
    a.applyTorque(3000, true);

    FixtureDef fDef = new FixtureDef();
    BodyDef ballD = new BodyDef();

    ballD.type = BodyType.DynamicBody;

    //random location for asteroid
    int aLoc = (int) (aLocation * 15);
    float x = 300;
    switch(aLoc)
    {
    case 0:
        ballD.position.set(x, -105);
        break;
    case 1:
        ballD.position.set(x, -95);
        break;
    case 2:
        ballD.position.set(x, -80);
        break;
    case 3:
        ballD.position.set(x, -65);
        break;
    case 4:
        ballD.position.set(x, -50);
        break;
    case 5:
        ballD.position.set(x, -35);
        break;
    case 6:
        ballD.position.set(x, -20);
        break;
    case 7:
        ballD.position.set(x, -5);
        break;
    case 8:
        ballD.position.set(x, 10);
        break;
    case 9:
        ballD.position.set(x, 25);
        break;
    case 10:
        ballD.position.set(x, 40);
        break;
    case 11:
        ballD.position.set(x, 55);
        break;
    case 12:
        ballD.position.set(x, 70);
        break;
    case 13:
        ballD.position.set(x, 85);
        break;
    default:
        ballD.position.set(x, 0);
    }

    PolygonShape asteroid = new PolygonShape();
    asteroid.setAsBox(12.5f, 12.5f);

    //asteroid definition
    fDef.shape = asteroid;
    fDef.density = .5f;
    fDef.friction = .25f;
    fDef.restitution = .75f;

    a = world.createBody(ballD);
    a.createFixture(fDef);
    a.setFixedRotation(false);

   //asteroid image
    aSprite = new Sprite(new Texture("img/asteroid-icon.png"));
    aSprite.setSize(12.5f * 4, 12.5f * 4);
    aSprite.setOrigin(aSprite.getWidth() / 2, aSprite.getHeight() / 2);
    a.setUserData(aSprite);
    asteroid.dispose();
like image 516
Mercify Avatar asked Mar 05 '14 01:03

Mercify


2 Answers

You could use Body.setTransform() for that task, but I would not do that. setTransform() causes a lot of trouble in the long run.

For me it lead to weird bugs. For example using setTransform disabled my ContactFilter in random moments, which cost me several days of debugging until I found that.

Furthermore it causes non-physical behaviour, because you basically teleport the Body.

Better would be to destroy the Body completely and recreate a new one at the same initial position of the old one.

like image 88
noone Avatar answered Nov 15 '22 05:11

noone


You can set the position of your Box2D a body instantly through this method:

a.setTransform(new_x, new_y, new_angle);

With this, you can create a condition that sets the x and y position of the body back to its original position when the x or y value of the body is outside of the screen.

if(outsideBounds()){
    a.setTransform(start_x, start_y, start_angle);
}

You can check whether your object is offscreen by either checking its Box2D position and its converted screen coordinates, or by checking the sprite's location.

Once you've received the x and y screen positions, you can compare them to the screen bounds like this:

pos_x>screenWidth||pos_x<0||pos_y>screenHeight||pos_y<0

This can be improved by including the dimensions of the object, depending on when you want the transformation to happen:

(pos_x-objWidth)>screenWidth || (pos_x+objWidth)<0 ||
(pos_y-objHeight)>screenHeight || (pos_y+objHeight)<0
like image 33
user3312130 Avatar answered Nov 15 '22 04:11

user3312130