簡體   English   中英

如何在box2d中與距離關節碰撞

[英]How allow collision with a Distance joint in box2d

我有一系列通過距離關節附着的粒子(使用box2d Processing )。 顆粒必須具有一定的尺寸。 我想將磚塊扔向顆粒鏈,然后讓磚塊彈起。 此刻,磚塊從顆粒上彈起,但從接縫處反彈。 我該如何使他們這樣做。 我的MCVE:

import shiffman.box2d.*;
import org.jbox2d.common.*;
import org.jbox2d.dynamics.joints.*;
import org.jbox2d.collision.shapes.*;
import org.jbox2d.collision.shapes.Shape;
import org.jbox2d.dynamics.*;
import org.jbox2d.dynamics.contacts.*;
import org.jbox2d.particle.ParticleGroupDef;
import org.jbox2d.particle.ParticleSystem;
import org.jbox2d.particle.ParticleType;
import org.jbox2d.particle.ParticleDef;

import org.jbox2d.collision.shapes.CircleShape;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
// A reference to our box2d world
Box2DProcessing box2d;
ParticleSystem particleSystem;
ParticleDef pd=new ParticleDef();
Bridge bridge;
int PARTICLES = 10; // the amount of particles in your bridge
 ParticleDef pdef=new ParticleDef();
// A list for all of our rectangles
ArrayList<Box> boxes;


void setup() {

  size(1040,1060);
  smooth();

  // Initialize box2d physics and create the world
  box2d = new Box2DProcessing(this);
  box2d.createWorld();
  // Make the bridge total length,number of points,x start position
  bridge = new Bridge(width,PARTICLES,200);
  // 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
  if (mousePressed) {
    Box p = new Box(mouseX,mouseY);
    boxes.add(p);
  }



  // 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);
    }
  }

 bridge.display();

 fill(0);
       float move_1=300;
    for (int i=0; i<10; i++){
            bridge.particles.get(i).body.setTransform(box2d.coordPixelsToWorld(move_1+10,i*20+70), 0);
    }

}

// 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(4,16);
    h = random(4,16);
    // 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;
  }

  // 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);
    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 = 300;
    fd.restitution = 0.0;

    // Define the body and make it from the shape
    BodyDef bd = new BodyDef();
    bd.type = BodyType.DYNAMIC;
    bd.position.set(box2d.coordPixelsToWorld(center));

    body = box2d.createBody(bd);
    body.createFixture(fd);
    // Give it some initial random velocity
   body.setLinearVelocity(new Vec2(random(-5, 5), random(2, 5)));

  }

}


// Series of Particles connected with distance joints

class Bridge {

  // Bridge properties
  float totalLength;  // How long
  int numPoints;      // How many points in a line
  int NewCurvepoints; // How many points in a curve for the top of the stomach
  // Our chain is a list of particles
  ArrayList<Particle> particles;

  // Chain constructor
  Bridge(float l, int n,int start) {

    totalLength = l;
    numPoints = n;
    NewCurvepoints=n;
    particles = new ArrayList();
    float len = totalLength / numPoints;

    // Add particles to the chain    
    for(int i=0; i < PARTICLES; i++) {
      // Make a new particle
      Particle p = null;     
      //x,y,radius,fixed
            p = new Particle(start,i*len,7,3);

      particles.add(p);
      if (i > 0) {
         DistanceJointDef djd = new DistanceJointDef();
         Particle previous = particles.get(i-1);
         djd.bodyA = previous.body;
         djd.bodyB = p.body;
         djd.length = box2d.scalarPixelsToWorld(len/40);
         line(djd.bodyA.getPosition().x,djd.bodyA.getPosition().y,djd.bodyB.getPosition().x,djd.bodyB.getPosition().y);
         djd.frequencyHz = 0;
         djd.dampingRatio = 0;
         DistanceJoint dj = (DistanceJoint) box2d.world.createJoint(djd);
      }
    }

     }

 // // Draw the bridge
  void display() { for(int i=0; i < particles.size()-1; i++) {
    Vec2 pos1 = box2d.getBodyPixelCoord(particles.get(i).body);
    Vec2 pos2 = box2d.getBodyPixelCoord(particles.get(i+1).body);
    stroke(0);
    strokeWeight(2);
    line(pos1.x,pos1.y,pos2.x,pos2.y);
  }
    for (Particle p: particles) {
      p.display();
    }
  }

}

class Particle {

  // We need to keep track of a Body and a radius
  Body body;
  float r;

  color col;

  Particle(float x, float y, float r_, int fixed) {
    r = r_;    
    // Define a body
    BodyDef bd = new BodyDef();
    bd.fixedRotation=true;
    if (fixed==1) bd.type = BodyType.STATIC;
    else if (fixed==2) bd.type = BodyType.KINEMATIC;
    else if (fixed==3) bd.type = BodyType.DYNAMIC;

    // Set its position
    bd.position = box2d.coordPixelsToWorld(x,y);
    body = box2d.world.createBody(bd);

    // Make the body's shape a circle
    CircleShape cs = new CircleShape();
    cs.m_radius = box2d.scalarPixelsToWorld(r);

    FixtureDef fd = new FixtureDef();
    fd.shape = cs;
    // Parameters that affect physics
    fd.density = 0;
    fd.friction = 0;
    fd.restitution = -90;
    body.createFixture(fd);
    col = color(175);
    //determine how it moves
  }


  // 
  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();
    pushMatrix();
    translate(pos.x,pos.y);
    rotate(a);
    fill(col);
    stroke(0);
    strokeWeight(1);
    ellipse(0,0,r*2,r*2);
    // Let's add a line so we can see the rotation
    line(0,0,r,0);
    popMatrix();
  }


}

回答:

你不能 不完全是。

關節不參與碰撞檢測。 因此,身體無法從關節自身反彈。

將物體和關節以不留間隙的方式連接在一起,似乎應該確保物體不能穿過那串物體。 有時會。 但不總是。

附加信息:

以Bridge TestBed案例為例。 跌落到橋上的車身(作為測試的一部分)確實會從橋體件上反彈。 它們通過旋轉關節連接。 但是,如果我使用空格鍵以足夠的力向橋梁發射“炸彈”,它就會穿過構成橋梁的物體。 即使將橋主體部分設置為子彈主體,也會發生這種情況。

這是通過橋的“炸彈”的快照特寫:

炸彈通過橋梁測試

橋梁的一部分被撞掉了,炸彈可以通過它。

遠距關節可能比旋轉關節更好。 我不知道會怎樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM