1 / 65

Box2D

Box2D. What is the Box2D?. Open-Source 2D Physics Engine C++ by Erin Catto for the Game Developer’s Conference in 2006 . Box2D site (http://www.box2d.org/) for reference Crayon Physics Angry Birds JBox2D : Java Wrapper Box2D site (http://www.jbox2d.org//) for reference.

yehudi
Télécharger la présentation

Box2D

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Box2D

  2. What is the Box2D? • Open-Source 2D Physics Engine • C++ by Erin Catto for the Game Developer’s Conference in 2006. • Box2D site (http://www.box2d.org/) for reference • Crayon Physics • Angry Birds • JBox2D : Java Wrapper • Box2D site (http://www.jbox2d.org//) for reference. • Can be directly used in Processing • PBox2D : Processing Wrapper • Make it easy to use JBox2D • A layer library between JBox2D and Processing • a Processing Box2D “helper” library ( a set of functions that help you get your Box2D) • PBox2D is not a Processing wrapper for all of Box2D • https://github.com/shiffman/PBox2D

  3. Box2D Basics • In old physical simulation • SETUP: • Create all the objects in our world. • DRAW: • Calculate all the forces in our world. • Apply all the forces to our objects (F = M * A). • Update the locations of all the objects based on their acceleration. • Draw all of our objects. • In Box2D • SETUP: • Create all the objects in our world. • DRAW: • Draw all of our objects.

  4. Five core parts for using Box2D • World: Manages the physics simulation. It knows everything about the overall coordinate space and also stores lists of every element in the world • Body: Serves as the primary element in the Box2D world. It has a location. It has a velocity. Sound familiar? The Body is essentially the class we’ve been writing on our own in our vectors and forces examples. • Shape: Keeps track of all the necessary collision geometry attached to a body. • Fixture: Attaches a shape to a body and sets properties such as density, friction, and restitution. • Joint: Acts as a connection between two bodies (or between one body and the world itself).

  5. A new Vector Class : Vec2

  6. Box2D worlds How can we convert between them?

  7. Helper functions

  8. Set up the world PBox2D box2d; void setup() { box2d = new PBox2D(this); //Initializes a Box2D world with default settings box2d.createWorld(); }

  9. Set up the Body • Step 1: Define a body. //define the properties of the body we intend to make BodyDefbd = new BodyDef(); • Step 2: Configure the body definition. Vec2 center = box2d.coordPixelsToWorld(width/2,height/2)); bd.position.set(center); bd.fixedRotation = true; //Fixed, never rotating objects bd.linearDamping = 0.8; //Friction bd.angularDamping = 0.9; bd.bullet = true; //if it is FAST moving objects bd.type = BodyType.DYNAMIC; // body type

  10. Body types • Dynamic (BodyType.DYNAMIC) • a “fully simulated” body. A dynamic body moves around the world, collides with other bodies, and responds to the forces in its environment. • Static (BodyType.STATIC) • cannot move (as if it had an infinite mass). We’ll use static bodies for fixed platforms and boundaries. • Kinematic(BodyType.KINEMATIC) • can be moved manually by setting its velocity directly. If you have a user-controlled object in your world, you can use a kinematic body. Note that kinematic bodies collide only with dynamic bodies and not with other static or kinematic ones.

  11. Set up the Body • Step 3: Create the body. Body body = box2d.createBody(bd); • Step 4: Set any other conditions for the body’s starting state. body.setLinearVelocity(new Vec2(0,3)); body.setAngularVelocity(1.2);

  12. Linking Shape with Body • Body does not have geometry • We have to attach geometry shape to body with a Fixture • We can attach multiple shapes to a single body in order to create more complex forms. • Step 1: Define a shape PolygonShapeps = new PolygonShape(); float box2Dw = box2d.scalarPixelsToWorld(150); float box2Dh = box2d.scalarPixelsToWorld(100); ps.setAsBox(box2Dw, box2Dh);

  13. Width & Height height height width width Processing BOX2D

  14. Step 2: Create a fixture. FixtureDeffd = new FixtureDef(); //The fixture is assigned the PolygonShape we just made. fd.shape = ps; fd.friction = 0.3; //The coefficient of friction for the shape, typically between 0 and 1 fd.restitution = 0.5; //The Shape’s restitution (i.e. elasticity), typically between 0 and 1 fd.density = 1.0; //The Shape’s density, measured in kilograms per meter squared • Step 3: Attach the shape to the body with the fixture. body.createFixture(fd); Or you can use the default fixture body.createFixture(ps,1); // Creates the Fixture and attaches the Shape with a density of 1

  15. In summary • Define a body using a BodyDefobject (set any properties, such as location). • Create the Body object from the body definition. • Define a Shape object using PolygonShape, CircleShape, or any other shape class. • Define a fixture using FixtureDef and assign the fixture a shape (set any properties, such as friction, density, and restitution). • Attach the shape to the body.

  16. In processing term. //Step 1. Define the body. BodyDefbd = new BodyDef(); bd.position.set(box2d.coordPixelsToWorld(width/2,height/2)); //Step 2. Create the body. Body body = box2d.createBody(bd); //Step 3. Define the shape. PolygonShapeps = new PolygonShape(); float w = box2d.scalarPixelsToWorld(150); float h = box2d.scalarPixelsToWorld(100); ps.setAsBox(w, h) //Step 4. Define the fixture. FixtureDeffd = new FixtureDef(); fd.shape= ps; fd.density= 1; fd.friction= 0.3; fd.restitution= 0.5; //Step 5. Attach the shape to the body with the Fixture. body.createFixture(fd);

  17. How can we keep tracking objects? • Use the arrayList (Dynamic array) • Exercise • Making boxes on the fly whenever we move the box and put it on an arrayList.

  18. Class Design // A list for all of our rectangles ArrayList<Box> boxes; void setup() { size(800,200); smooth(); // Create ArrayLists boxes = new ArrayList<Box>(); } void draw() { background(255); // When the mouse is clicked, add a new Box object if (mousePressed) { Box p = new Box(mouseX,mouseY); boxes.add(p); } // Display all the boxes for (Box b: boxes) { b.display(); } } // A rectangular box class Box { float x,y; float w,h; // Constructor Box(float x_, float y_) { x = x_; y = y_; w = 16; h = 16; } // Drawing the box void display() { fill(127); stroke(0); strokeWeight(2); rectMode(CENTER); rect(x,y,w,h); } }

  19. Let’s put those boxes on the Box2D world class Box { Body body; float w,h; Box(float x, float y) { //initial position w = 16; h = 16; // following the steps //Step 1. Define the body. //Step 2. Create the body.(bodyType=DYNAMIC) //Step 3. Define the shape. // Step 4. Define the fixture. // Step 5. Attach the shape to the body with the Fixture } display() { Vec2 pos = box2d.getBodyPixelCoord(body); float a = body.getAngle(); pushMatrix(); translate(pos.x,pos.y); // Box2D coordinate system considers rotation in the opposite direction from Processing rotate(-a); fill(127); stroke(0); strokeWeight(2); rectMode(CENTER); rect(0,0,w,h); popMatrix(); } } • Revise the Box class • Box size (8,8) • fd.density = 1; • fd.friction= 0.3; • fd.restitution= 0.5;

  20. Main function • import pbox2d.*; • import org.jbox2d.collision.shapes.*; • import org.jbox2d.common.*; • import org.jbox2d.dynamics.*; • // A list for all of our rectangles • ArrayList<Box> boxes; • PBox2D box2d; • void setup() { • size(800, 200); • smooth(); • // Initialize and create the Box2D world • box2d = new PBox2D(this); • box2d.createWorld(); • // Create ArrayLists • boxes = new ArrayList<Box>(); • } • void draw() { • background(255); • // We must always step through time! • box2d.step(); • // When the mouse is clicked, add a new Box object • Box p = new Box(mouseX, mouseY); • boxes.add(p); • // Display all the boxes • for (Box b: boxes) { • b.display(); • } • }

  21. Let’s put some boundaries. • To create boundaries, we need to set BodyDef object’s type to STATIC.

  22. Let’s design Boundary class 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_; // following the steps //Step 1. Define the body. //Step 2. Create the body.(bodyType=STATIC) //Step 3. Define the shape. //(Step 4. Define the fixture) (Skip this step and use the default fixture!) // Step 5. Attach the shape to the body with the Fixture } // 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); } }

  23. Let’s design main function // A reference to our box2d world PBox2D 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(800, 200); smooth(); // Initialize and create the Box2D world box2d = new PBox2D(this); box2d.createWorld(); // 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-50,10)); boundaries.add(new Boundary(3*width/4,height-50,width/2-50,10)); }

  24. One problem of this example • Computationally expensive as we increase the number of boxes • It is getting slow as it goes. • How can we fix it? • If the box is out of screen, remove it!!

  25. Let’s modify Box class and main function void killBody() { box2d.destroyBody(body); //ask box2d to destroy the 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+h) { killBody(); return true; } return false; } for (inti = boxes.size()-1; i >= 0; i--) { Box b = boxes.get(i); if (b.done()) { boxes.remove(i); //remove from the array } } Draw() in main function BOX class

  26. Curvy Boundary • If you want a fixed boundary that is a curved surface (as opposed to a polygon) • Use the ChainShape

  27. polygonShape : Convex moving object chainShape : static game world

  28. Steps • Step 1: Define a body. BodyDefbd = new BodyDef(); Body body = box2d.world.createBody(bd); • Step 2: Define the Shape. ChainShape chain = new ChainShape(); • Step 3: Configure the Shape. Vec2[] vertices = new Vec2[2]; vertices[0] = box2d.coordPixelsToWorld(0,150); vertices[1] = box2d.coordPixelsToWorld(width,150); chain.createChain(vertices, vertices.length);

  29. Steps • Step 4: Attach the Shape to the body with a Fixture. FixtureDeffd = new FixtureDef(); fd.shape= chain; fd.density = 1; fd.friction = 0.3; fd.restitution = 0.5; body.createFixture(fd);

  30. Define a Surface class Surface { // We'll keep track of all of the surface points ArrayList<Vec2> surface; Surface() { surface = new ArrayList<Vec2>(); // Here we keep track of the screen coordinates of the chain surface.add(new Vec2(0, height/2)); //surface.add(new Vec2(width/2, height/2+50)); surface.add(new Vec2(width, height/2)); // This is what box2d uses to put the surface in its world ChainShape chain = new ChainShape(); // We can add 3 vertices by making an array of 3 Vec2 objects Vec2[] vertices = new Vec2[surface.size()]; for (inti = 0; i < vertices.length; i++) { vertices[i] = box2d.coordPixelsToWorld(surface.get(i)); } chain.createChain(vertices, vertices.length); // The edge chain is now a body! BodyDefbd = new BodyDef(); Body body = box2d.world.createBody(bd); // Shortcut, we could define a fixture if we // want to specify frictions, restitution, etc. body.createFixture(chain, 1); }

  31. How to draw it? void display() { strokeWeight(1); stroke(0); fill(0); beginShape(); for (inti=0; i<surface.size(); i++) { Vec2 v = surface.get(i); vertex(v.x,v.y); } vertex(width, height); vertex(0, height); endShape(CLOSE); } vertex(v.x,v.y); vertex(v.x,v.y); (0,height) (width,height)

  32. Exercise • Use the sin() to draw the mountains • Use the mouse to create circles • Use the CircleShapecs = new CircleShape() for body

  33. Body type and parameters float r = random(4,8); CircleShapecs = new CircleShape(); cs.m_radius= box2d.scalarPixelsToWorld(r); FixtureDeffd = new FixtureDef(); fd.shape= cs; fd.density= 1; fd.friction= 0.01; fd.restitution= 0.3; . . . body.setLinearVelocity(new Vec2(random(-10f,10f),random(5f,10f)));

  34. Building Mountain : use the sin function float angle = 0; float angleVel = 0.2; float amplitude = 100; size(400,200); background(255); smooth(); stroke(0); strokeWeight(2); noFill(); beginShape(); for (int x = 0; x <= width; x += 5) { //map one value from the current range to another range float y = map(sin(angle),-1,1,0,height); vertex(x,y); angle +=angleVel; } endShape();

  35. Complex Shapes • How to create more complex shapes? • build a completely custom shape as a series of connected vertices

  36. Vec2[] vertices = new Vec2[4]; // An array of 4 vectors vertices[0] = box2d.vectorPixelsToWorld(new Vec2(-15, 25)); vertices[1] = box2d.vectorPixelsToWorld(new Vec2(15, 0)); vertices[2] = box2d.vectorPixelsToWorld(new Vec2(20, -15)); vertices[3] = box2d.vectorPixelsToWorld(new Vec2(-10, -10)); PolygonShapeps = new PolygonShape(); ps.set(vertices, vertices.length); Order of vertices! If you are thinking in terms of pixels (as above) the vertices should be defined in counterclockwise order. Convex shapes only! A concave shape is one where the surface curves inward. Convex is the opposite

  37. Complex shapes • We can attach several shapes on a single body BodyDefbd = new BodyDef(); bd.type = BodyType.DYNAMIC; bd.position.set(box2d.coordPixelsToWorld(center)); body = box2d.createBody(bd); PolygonShapeps = new PolygonShape(); float box2dW = box2d.scalarPixelsToWorld(w/2); float box2dH = box2d.scalarPixelsToWorld(h/2); sd.setAsBox(box2dW, box2dH); CircleShapecs = new CircleShape(); cs.m_radius = box2d.scalarPixelsToWorld(r); body.createFixture(ps,1.0); body.createFixture(cs, 1.0); Body center

  38. Moving Vec2 offset = new Vec2(0,-h/2); //Converting the vector to Box2D world offset = box2d.vectorPixelsToWorld(offset); //Setting the local position of the circle circle.m_p.set(offset.x,offset.y); m_p : local center of shape

  39. Setting shapes on body • Setting proper shapes on the body is really important for correct simulation. • If not, the collision detection does not work and simulation has errors. Overlapping each other !!

  40. Exercise : Revise the old example

  41. Draw() void display() { Vec2 pos = box2d.getBodyPixelCoord(body); float a = body.getAngle(); rectMode(CENTER); pushMatrix(); translate(pos.x,pos.y); rotate(-a); fill(175); stroke(0); //First the rectangle at (0,0) rect(0,0,w,h); //Then the ellipse offset at (0,-h/2) ellipse(0,-h/2,r*2,r*2); popMatrix(); }

  42. Box2D Joints • Connecting one body to another • Three different joints • distance joints • revolute joints • “mouse” joints

  43. Distant Joints • A joint that connects two bodies with a fixed length • Steps • Step 1. Make sure you have two bodies ready to go. • Step 2. Define the joint. • Step 3. Configure the joint’s properties (What are the bodies? Where are the anchors? What is its rest length? Is it elastic or rigid?) • Step 4. Create the joint.

  44. Example • Assume that we have a particle body Particle p1 = new Particle(); Particle p2 = new Particle(); DistanceJointDefdjd = new DistanceJointDef(); djd.bodyA = p1.body; djd.bodyB = p2.body; //if our rest length is in pixels, we need to convert it! djd.length= box2d.scalarPixelsToWorld(10); Joint dj= (DistanceJoint) box2d.world.createJoint(djd);

  45. Revolute Joints • connects two Box2D bodies at a common anchor point, • Steps • Step 1. Make sure you have two bodies ready to go. • Step 2. Define the joint. • Step 3. Configure the joint’s properties (What are the bodies? Step 4. Create the joint.

  46. Example • Assume that we have a particle body Box box1 = new Box(); Box box2 = new Box(); RevoluteJointDefrjd = new RevoluteJointDef(); //the anchor point (i.e. where they are connected)is set with the function initialize(). rjd.initialize(box1.body, box2.body, box1.body.getWorldCenter()); rjd.motorSpeed = PI*2; // how fast? rjd.maxMotorTorque= 1000.0; // how powerful? rjd.enableMotor= false; // is it on? rjd.enableLimit= true; rjd.lowerAngle = -PI/8; rjd.upperAngle = PI/8; Joint joint = box2d.world.createJoint(rjd);

  47. Exercise: Let’s making a windmill class Windmill { RevoluteJointjoint; Box box1; Box box2; Windmill(float x, float y) { // Initialize locations of two boxes box1 = new Box(x, y-20, 120, 10, false); box2 = new Box(x, y, 10, 40, true); // Define joint as between two bodies RevoluteJointDefrjd = new RevoluteJointDef(); rjd.initialize(box1.body, box2.body, box1.body.getWorldCenter()); // Turning on a motor (optional) rjd.motorSpeed = PI*2; // how fast? rjd.maxMotorTorque = 1000.0; // how powerful? rjd.enableMotor = false; // is it on? // Create the joint rjd.enableLimit = true; rjd.lowerAngle= -PI/8; rjd.upperAngle= PI/8; } void display() { box2.display(); box1.display(); // Draw anchor just for debug Vec2 anchor = box2d.coordWorldToPixels(box1.body.getWorldCenter()); fill(0); noStroke(); ellipse(anchor.x, anchor.y, 8, 8); } } Create a ball whenever you click the mouse!

  48. Exercise: main function import pbox2d.*; import org.jbox2d.common.*; import org.jbox2d.dynamics.joints.*; import org.jbox2d.collision.shapes.*; import org.jbox2d.collision.shapes.Shape; import org.jbox2d.common.*; import org.jbox2d.dynamics.*; import org.jbox2d.dynamics.contacts.*; // A reference to our box2d world PBox2D box2d; // An object to describe a Windmill (two bodies and one joint) Windmill windmill; // An ArrayList of particles that will fall on the surface ArrayList<Particle> particles; void setup() { size(800,200); smooth(); // Initialize box2d physics and create the world box2d = new PBox2D(this); box2d.createWorld(); // Make the windmill at an x,y location windmill = new Windmill(width/2,175); // Create the empty list particles = new ArrayList<Particle>(); } void mousePressed() { float sz = random(4,8); //radius particles.add(new Particle(mouseX,mouseY,sz)); } Create a particle class!! Class Particle{ //following the steps for creating body and shape }

  49. Applying Forces • When we want to apply any forces other than gravity, call applyForce() function class Box { Body body; void applyForce(Vec2 force) { Vec2 pos = body.getWorldCenter(); //Calling the Body's applyForce() function body.applyForce(force, pos); } } Our earlier forces examples assumed that the force was always applied at the mover’s center. Here we get to specify exactly where on the body the force is applied

  50. Collision Detection • How do we know when two objects collide? • beginContact() is triggered when two shapes collide void setup() { box2d = new PBox2D(this); box2d.createWorld(); Add this line if you want to listen for collisions. box2d.listenForCollisions(); } void beginContact(Contact cp) { println("Something collided in the Box2D World!"); }

More Related