How do I get a body's velocity in Box2D?

edited December 2014 in Library Questions

I want to know if a body is now moving, or is staying still. So how can I get the linear velocity of a body in Box2D for Processing?

Tagged:

Answers

  • First of all, "Hello !"

    You could substract the old position of your body to the current position, the resulting vector will match to the speed of your body

  • edited December 2014

    Inside the Box class I added a line of code to the display() method:

    text(body.getLinearVelocity().toString(), 0,0);

    This is a example straight out of the Box2D library in Processing. (ApplyForceSimpleWind) I did slow it down a bit, though.

    The PDX E mode in Processing is excellent for finding code available within a library.

    // The Nature of Code
    // <http://www.shiffman.net/teaching/nature>;
    // Spring 2011
    // Box2DProcessing example
    
    // Basic example of falling rectangles
    
    import shiffman.box2d.*;
    import org.jbox2d.collision.shapes.*;
    import org.jbox2d.common.*;
    import org.jbox2d.dynamics.*;
    
    // A reference to our box2d world
    Box2DProcessing box2d;
    
    // A list we'll use to track fixed objects
    ArrayList<Boundary> boundaries;
    // A list for all of our rectangles
    ArrayList<Box> boxes;
    
    void setup() {
      size(640,360);
      frameRate(20);
      smooth();
    
      // Initialize box2d physics and create the world
      box2d = new Box2DProcessing(this);
      box2d.createWorld();
      // We are setting a custom gravity
      box2d.setGravity(0, -20);
    
      // Create ArrayLists  
      boxes = new ArrayList<Box>();
      boundaries = new ArrayList<Boundary>();
    
      // Add a bunch of fixed boundaries
      boundaries.add(new Boundary(width/4,height-5,width/2-100,10));
      boundaries.add(new Boundary(3*width/4,height-5,width/2-100,10));
      boundaries.add(new Boundary(width-5,height/2,10,height));
      boundaries.add(new Boundary(5,height/2,10,height));
    }
    
    void draw() {
      background(255);
    
      // We must always step through time!
      box2d.step();
    
      // When the mouse is clicked, add a new Box object
      if (random(1) < 0.01) {
        Box p = new Box(random(width),10);
        boxes.add(p);
      }
    
      if (mousePressed) {
        for (Box b: boxes) {
         Vec2 wind = new Vec2(20,0);
         b.applyForce(wind);
        }
      }
    
      // Display all the boundaries
      for (Boundary wall: boundaries) {
        wall.display();
      }
    
      // Display all the boxes
      for (Box b: boxes) {
        b.display();
      }
    
      // Boxes that leave the screen, we delete them
      // (note they have to be deleted from both the box2d world and our list
      for (int i = boxes.size()-1; i >= 0; i--) {
        Box b = boxes.get(i);
        if (b.done()) {
          boxes.remove(i);
        }
      }
    
      fill(0);
      text("Click mouse to apply a wind force.",20,20);
    }
    
    class Boundary {
    
      // A boundary is a simple rectangle with x,y,width,and height
      float x;
      float y;
      float w;
      float h;
    
      // But we also have to make a body for box2d to know about it
      Body b;
    
      Boundary(float x_,float y_, float w_, float h_) {
        x = x_;
        y = y_;
        w = w_;
        h = h_;
    
        // Define the polygon
        PolygonShape sd = new PolygonShape();
        // Figure out the box2d coordinates
        float box2dW = box2d.scalarPixelsToWorld(w/2);
        float box2dH = box2d.scalarPixelsToWorld(h/2);
        // We're just a box
        sd.setAsBox(box2dW, box2dH);
    
    
        // Create the body
        BodyDef bd = new BodyDef();
        bd.type = BodyType.STATIC;
        bd.position.set(box2d.coordPixelsToWorld(x,y));
        b = box2d.createBody(bd);
    
        // Attached the shape to the body using a Fixture
        b.createFixture(sd,1);
      }
    
      // Draw the boundary, if it were at an angle we'd have to do something fancier
      void display() {
        fill(0);
        stroke(0);
        rectMode(CENTER);
        rect(x,y,w,h);
      }
    
    }
    
    // A rectangular box
    class Box {
    
      // We need to keep track of a Body and a width and height
      Body body;
      float w;
      float h;
    
      // Constructor
      Box(float x, float y) {
        w = random(8, 16);
        h = w;
        // Add the box to the box2d world
        makeBody(new Vec2(x, y), w, h);
      }
    
      // This function removes the particle from the box2d world
      void killBody() {
        box2d.destroyBody(body);
      }
    
      // Is the particle ready for deletion?
      boolean done() {
        // Let's find the screen position of the particle
        Vec2 pos = box2d.getBodyPixelCoord(body);  
        // Is it off the bottom of the screen?
        if (pos.y > height+w*h) {
          killBody();
          return true;
        }
        return false;
      }
    
      void applyForce(Vec2 force) {
        Vec2 pos = body.getWorldCenter();
        body.applyForce(force, pos);
      }
    
      // Drawing the box
      void display() {
        // We look at each body and get its screen position
        Vec2 pos = box2d.getBodyPixelCoord(body);
        // Get its angle of rotation
        float a = body.getAngle();
    
        rectMode(CENTER);
        pushMatrix();
        translate(pos.x, pos.y);
        rotate(-a);
        fill(175);
        stroke(0);
        rect(0, 0, w, h);
        text(body.getLinearVelocity().toString(), 0,0);
        popMatrix();
      }
    
      // This function adds the rectangle to the box2d world
      void makeBody(Vec2 center, float w_, float h_) {
    
        // Define a polygon (this is what we use for a rectangle)
        PolygonShape sd = new PolygonShape();
        float box2dW = box2d.scalarPixelsToWorld(w_/2);
        float box2dH = box2d.scalarPixelsToWorld(h_/2);
        sd.setAsBox(box2dW, box2dH);
    
        // Define a fixture
        FixtureDef fd = new FixtureDef();
        fd.shape = sd;
        // Parameters that affect physics
        fd.density = 1;
        fd.friction = 0.3;
        fd.restitution = 0.2;
    
        // Define the body and make it from the shape
        BodyDef bd = new BodyDef();
        bd.type = BodyType.DYNAMIC;
        bd.position.set(box2d.coordPixelsToWorld(center));
        bd.angle = random(TWO_PI);
    
        body = box2d.createBody(bd);
        body.createFixture(fd);
      }
    }
    
  • With XYZZY's method, I successfully accessed the velocity in the body tab, but how can I access the velocity in the main tab?

  • edited December 2014

    You could create a method within the Box class that returns a PVector. In that method you return the value of getLinearVelocity() (which is a PVector).

    Something like this (not tested, my need to create a new PVector and assign the desired value):

       PVector myVelocity(){
            return body.getLinearVelocity();
        }
    

    To access anywhere in the code, you would call:

        boxes.get( 'desired instance as int').myVelocity();
    

    Again, this returns a PVector, so will need to use it as such in the code.

    Edit: actually getLinearVelocity() returns a Vec2, so replace PVector with Vec2. I'm not sure, but I believe they are them same. That would require some Googling of Vec2.

  • Answer ✓

    Here are three tested methods that can be added to the Box class:

      Vec2 myVelocity() {
        return body.getLinearVelocity();
      }
    
      float myVelocityX() {
        return body.getLinearVelocity().x;
      }
    
      float myVelocityY() {
        return body.getLinearVelocity().y;
      }
    

    The second and third return a float of the x or y velocity.

  • It works well! Thanks, XXZZY.

    The additional question is how to get the position of the body at given time. Should there also be function like the "getLinearVelocity()" one, but to tell the position?

  • edited December 2014

    Yes, that can be done:

      Vec2 myLocation(){
        Vec2 pos = box2d.getBodyPixelCoord(body);
        return pos;
      }
    

    And you can check X like this:

    boxes.get( 'desired instance as int').myLocation().x;
    

    and Y:

    boxes.get( 'desired instance as int').myLocation().y;
    
  • Thanks! But I don't really get what 'desired instance as int' means, and what "boxes" is. Is it the name you give to the body?

    But I can understand the last post, because it has a float value returned to a variable that at my current knowledge level understand.

    " Vec2 myVelocity() { return body.getLinearVelocity(); }

    float myVelocityX() { return body.getLinearVelocity().x; }

    float myVelocityY() { return body.getLinearVelocity().y; } "

    I was thinking if the "myLocation" can also deliver to a float myLocationX() and myLocationY()?

    I tried "float myLocationX() {return getBodyPixelCoord().x", but it is not the correct way of expressing it.

  • I tried float myLocationX() { return box2d.getBodyPixelCoord(body).x Although it works, I am a bit confused about the syntax and the writing of the code, like why we need to write"body" inside the parenthesis for the location one, but not the velocity one? How are these two functions different from one another?

    Thanks great a lot, Buddy!

  • Hello guys !

    Do someone know how to get the current "rotation" of a body ?

    Thanks by advance !

    (If someone have a working example with a texture linked to a body, it could be great too :D )

Sign In or Register to comment.