相连的体系I:绳子

分享
手机软件开发 2024-9-30 12:27:23 44 0 来自 中国
书名:代码本色:用编程模拟天然体系
作者:Daniel Shiffman
译者:周晗彬
ISBN:978-7-115-36947-5
目次
5.18 相连的体系I:绳子

1、模拟柔软物体


  • 在上例中,两个粒子对象通过一根弹簧相连。
  • toxiclibs物理库尤其实用于模拟柔软物体,
  • 好比可以用毗连成一条线的粒子模拟绳子,
  • 可以用毗连在一起的粒子网格模拟毯子。
  • 下面这个可爱的卡通模子也可以用相连的粒子举行模拟,这些粒子都通过弹簧相连。


2、模拟一个“柔软的钟摆”模子


  • 下面我们要模拟一个“柔软的钟摆”模子——将摆球挂在绳子的底端,这里的摆臂不再是第3章里使用的刚性摆臂,而是图5-14所示的“绳子”。
1)起首,我们须要一个粒子列表

(使用上例的Particle类)
ArrayList<article> particles = new ArrayList<article>();

  • 假如我们须要20个粒子,它们之间的隔断是10个像素。


float len = 10;float numParticles = 20;

  • 我们可以将下标i从0递增到20,将每个粒子的y坐标设置成i * 10,如许一来,第1个粒子位于坐标(0,10),第2个粒子位于(0,20),第3个粒子位于(0,30)……
for (int i=0; i < numPoints; i++) {    Particle particle=new Particle(i*len, 10);  沿着x轴摆放粒子    physics.addParticle(particle);   将粒子参加列表    particles.add(particle);   将粒子参加物理天下}

  • 除了将粒子对象参加toxiclibs的物理天下,我们还将它放入本身的列表中。只管这有些多余,但背面大概会有很多条绳子,到时间我们可以方便地获知粒子被连在哪一条绳子上。
  • 下面要做一件风趣的事:将全部的粒子毗连在一起。粒子1和粒子0相连,粒子2和粒子1相连,粒子3和粒子2相连……

    3.png
  • 也就是:粒子i和粒子i - 1相连(撤消i即是0的环境)。
if (i != 0) {      Particle previous = particles.get(i-1);  起首,我们须要前一个粒子的引用      VerletSpring2D spring = new VerletSpring2D(particle,previous,len,strength);     之后,我们须要在两个粒子之间创建弹簧毗连,并指定弹簧的静止长度和强度(都是浮点数)      physics.addSpring(spring);  不要忘记将弹簧参加物理天下  }

  • 假如我们想让绳子挂在某个定点上,该怎么做?可以将其中一个粒子锁定——好比第一个粒子、末了一个粒子大概最中央的粒子等。以下代码的作用就是将第一个粒子的位置锁定。
Particle head=particles.get(0);head.lock();

  • 假如想要绘制绳子上的全部粒子,我们可以从ArrayList获取全部的粒子位置,再调用beginShape()函数、endShape()函数和vertex()函数绘制它们。
3、示例

示例代码5-11 柔软的钟摆
import toxi.physics2d.*;import toxi.physics2d.behaviors.*;import toxi.geom.*;// Reference to physics "world" (2D)VerletPhysics2D physics;// Our "Chain" objectChain chain;void setup() {  size(640, 360);  // Initialize the physics world  physics=new VerletPhysics2D();  physics.addBehavior(new GravityBehavior(new Vec2D(0, 0.1)));  physics.setWorldBounds(new Rect(0, 0, width, height));  // Initialize the chain  chain = new Chain(180, 20, 16, 0.2);}void draw() {  background(255);  // Update physics  physics.update();  // Update chain's tail according to mouse position   chain.updateTail(mouseX, mouseY);  // Display chain  chain.display();}void mousePressed() {  // Check to see if we're grabbing the chain  chain.contains(mouseX, mouseY);}void mouseReleased() {  // Release the chain  chain.release();}Chain.pde
class Chain {  // Chain properties  float totalLength;  // How long  int numPoints;      // How many points  float strength;     // Strength of springs  float radius;       // Radius of ball at tail    // This list is redundant since we can ask for physics.particles, but in case we have many of these  // it's a convenient to keep track of our own list  ArrayList<article> particles;  // Let's keep an extra reference to the tail particle  // This is just the last particle in the ArrayList  Particle tail;  // Some variables for mouse dragging  PVector offset = new PVector();  boolean dragged = false;  // Chain constructor  Chain(float l, int n, float r, float s) {    particles = new ArrayList<article>();    totalLength = l;    numPoints = n;    radius = r;    strength = s;    float len = totalLength / numPoints;    // Here is the real work, go through and add particles to the chain itself    for(int i=0; i < numPoints; i++) {      // Make a new particle with an initial starting position      Particle particle=new Particle(width/2,i*len);      // Redundancy, we put the particles both in physics and in our own ArrayList      physics.addParticle(particle);      particles.add(particle);      // Connect the particles with a Spring (except for the head)      if (i != 0) {        Particle previous = particles.get(i-1);        VerletSpring2D spring = new VerletSpring2D(particle,previous,len,strength);        // Add the spring to the physics world        physics.addSpring(spring);      }    }    // Keep the top fixed    Particle head=particles.get(0);    head.lock();    // Store reference to the tail    tail = particles.get(numPoints-1);    tail.radius = radius;  }  // Check if a point is within the ball at the end of the chain  // If so, set dragged = true;  void contains(int x, int y) {    float d = dist(x,y,tail.x,tail.y);    if (d < radius) {      offset.x = tail.x - x;      offset.y = tail.y - y;      tail.lock();      dragged = true;    }  }  // Release the ball  void release() {    tail.unlock();    dragged = false;  }  // Update tail position if being dragged  void updateTail(int x, int y) {    if (dragged) {      tail.set(x+offset.x,y+offset.y);    }  }  // Draw the chain  void display() {    // Draw line connecting all points    beginShape();    stroke(0);    strokeWeight(2);    noFill();    for (Particle p : particles) {      vertex(p.x,p.y);    }    endShape();    tail.display();  }}Particle.pde
class Particle extends VerletParticle2D {    float radius = 4;  // Adding a radius for each particle    Particle(float x, float y) {    super(x,y);  }  // All we're doing really is adding a display() function to a VerletParticle  void display() {    fill(127);    stroke(0);    strokeWeight(2);    ellipse(x,y,radius*2,radius*2);  }}4、运行效果

4.gif
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 18:27, Processed in 0.167071 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表