2017-04-25 54 views
0

我有一系列通过距离关节附着的粒子(使用Processingbox2d)。颗粒必须具有一定的尺寸。我想把砖块扔到粒子链上,让砖块反弹。此刻砖块从粒子反弹而不是联合。我怎样才能让他们这样做。我MCVE:如何允许与距离关节在box2d发生碰撞

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


} 
+0

你认为你的粒子串没有任何空隙吗?我相信这是实现你所描述内容的一种方式。可能也是最简单的。 –

+0

也许用足够窄的矩形多边形填补空白,以期望的方式? –

+0

是的。问题是,用足够的力量,盒子从缝隙中逃脱。此外,粒子最终会被排列成两个串,以正弦波向下推砖,同一链的粒子之间的伸展也会产生间隙,通过这些间隙,砖可以逃脱 –

回答

0

答:

你不能。不完全是。

关节不参与碰撞检测。所以身体不能从关节本身反弹。

以不留下身体间隙的方式将身体与关节连接在一起似乎应确保身体不能穿过那串身体。它有时会。但不总是。

附加信息:

走天桥测试床情况下,例如。落在桥上的尸体(作为测试的一部分)会从桥体部件弹开。它们通过旋转关节连接。但是如果我用空格键在桥上用足够的力量发射一个“炸弹”,它就会通过组成桥梁的身体。即使我将桥体部件设置为子弹体,也会发生这种情况。

这里有一个快照特写一个“炸弹”,通过桥获得的:

Bomb getting through in Bridge Test

桥的一个片段已经得到敲出来的地方,允许炸弹熬过来的。

距离关节可能会比旋转关节做得更好。但我不知道它会如何。