2017-04-25 82 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

橋的一個片段已經得到敲出來的地方,允許炸彈熬過來的。

距離關節可能會比旋轉關節做得更好。但我不知道它會如何。