spring – 如何在使用粒子系统处理中制作滑动构件

我在Processing中模拟粒子系统.基于丹尼尔希夫曼的“本质的代码”一书,我做了一个弹簧,然后我开始尝试使用滑块做一个基于滑块的长度更长或更短的滑块.

现在,我试图制作一个滑块滑动,两个粒子移动到两个粒子的相同方向.
我使用PVector添加,找到新位置并绘制节点,但是当我有多个成员且一个受其他成员影响时它不起作用.
我需要使用一个force来执行此操作:请参阅applyForce()函数.

void update(float distance) {
  PVector force = PVector.sub(b.location,a.location); 
  float d = force.mag();
  float x = d - distance;
 //direction of the force
  force.normalize();
  force.mult(-1 * k* x/mass);
 //apply to one node
  b.applyForce(force); 
  force.mult(-1);
 //apply opposite to the other node
  a.applyForce(force);
}

//Newton's law: F = M * A
void applyForce(PVector force) {
  PVector f = force.get();
  f.div(mass);
  acceleration.add(f);
}

检查下图:

diagram

(a)是我想要的,(b)它现在是怎么做的.

在第一个例子中,长度相同,成员滑动(两个粒子).

在第二个中,长度更大并且不会滑动

如果您知道如何施加滑动构件的力,请告诉我.

谢谢

最佳答案
如果我理解正确,你会尝试做一些事情:

>改变弹簧的长度
>在春天的方向上翻译弹簧的端点
>使用滑块控制上述参数

第一部分是微不足道的,因为Spring对象具有len属性.
第二个涉及一点vector math

>一条线的方向是减去它的两个端点
>通过首先对其进行归一化(将其减小以使其长度等于1.0)然后乘以标量值,可以轻松地将矢量缩放到任何长度.
>可以通过简单地向其自身添加一个向量来翻译向量

这是一个注释草图,实现了以上几点:

//sliders to control spring rest length and translation
Slider rlength = new Slider("rest length",5,200,20,50,250,100,false);
Slider translate = new Slider("translate",30,-10,10,false);

Spring spring = new Spring(new Bob(75,350),new Bob(350,75),(int)rlength.value);

void setup(){
  size(400,400);
  spring.k = 0.01;//tweak elasticity
}
void draw(){
  //  update
  //update sliders
  rlength.update(mouseX,mouseY,mousepressed);
  translate.update(mouseX,mousepressed);
  //update spring
  spring.a.update();
  spring.b.update();
  spring.update();
  //make both points draggable
  spring.a.drag(mouseX,mouseY);
  spring.b.drag(mouseX,mouseY);
  //draw
  background(255);
  rlength.draw();
  translate.draw();
  spring.display();
}
//handle mouse events for spring points dragging
void mousepressed() {
  spring.a.clicked(mouseX,mouseY);
  spring.b.clicked(mouseX,mouseY);
}
void mouseReleased() {
  spring.a.stopDragging();
  spring.b.stopDragging();
}
//handle slider events
void onSliderUpdate(Slider s){
  if(s == rlength) spring.len = rlength.value;
  if(s == translate){
    //compute the direction of the spring by subtracting the two points
    PVector direction = PVector.sub(spring.a.location,spring.b.location);
    //normalize the vector -> it will not have a length/magnitude of 1.0,but will still point in the line direction
    direction.normalize();
    //scale or multiply the normalized vector to the translation amount
    direction.mult(translate.value);
    //finally,add the result to each spring point,essentially offsetting/translating
    spring.a.location.add(direction);
    spring.b.location.add(direction);
  } 
}
//Slider
class GUIElement{
  float w,h,x,y;//width,height and position
  color bg = color(200);//background colour
  color fg = color(0);//foreground colour
  String label;
  GUIElement(String label,float x,float y,float w,float h){
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.label = label;
  }
  void update(int mx,int my,boolean md){}
  void draw(){}
}
class Slider extends GUIElement{
  float min,max,value,pvalue;//slider values: minimum,maximum and current
  float cx,pw = 20;//current slider picker position,picker width

  boolean updating,liveDrag = true,isInt = false;
  //label to display on slider,it's position(x,y),size(w,h) and values(min,max and default/current)
  Slider(String label,float h,float min,float max,float value,boolean isInt){
    super(label,y,w,h);
    this.min = min;
    this.max = max;
    this.value = value;
    this.isInt = isInt;
    cx = map(value,min,x+w);
  }
  void update(int mx,boolean md){
    if(md){
      if((mx >= x && mx <= (x+w)) &&
         (my >= y && my <= (y+h))){
        cx = mx;
        value = map(cx,x+w,max);
        updating = true;
        if(liveDrag){
          boolean updated = (isInt ? ((int)value != (int)pvalue) : (value != pvalue));
          if(updated){
            pvalue = value;
            onSliderUpdate(this);
          }
        }
      }else updating = false;
    }else{
      if(updating){
        updating = false;
        onSliderUpdate(this);
      }  
    }
  }
  void draw(){
    pushStyle();
    nostroke();
    fill(bg);
    rect(x,h);
    fill(fg,64);
    rect(x,cx-x,h);//this displays a rect that stretches based on the value
    fill(0);
    text(label+": "+(isInt ? (int)value : value),x+pw,y+h*.75);
    popStyle();
  }
  String toString(){
    return label + ":" + value;
  }
}

// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com

// Bob class,just like our regular Mover (location,veLocity,acceleration,mass)

class Bob { 
  PVector location;
  PVector veLocity;
  PVector acceleration;
  float mass = 12;

  // Arbitrary damping to simulate friction / drag 
  float damping = 0.95;

  // For mouse interaction
  PVector dragOffset;
  boolean dragging = false;

  // Constructor
  Bob(float x,float y) {
    location = new PVector(x,y);
    veLocity = new PVector();
    acceleration = new PVector();
    dragOffset = new PVector();
  } 

  // Standard Euler integration
  void update() { 
    veLocity.add(acceleration);
    veLocity.mult(damping);
    location.add(veLocity);
    acceleration.mult(0);
  }

  // Newton's law: F = M * A
  void applyForce(PVector force) {
    PVector f = force.get();
    f.div(mass);
    acceleration.add(f);
  }


  // Draw the bob
  void display() { 
    stroke(0);
    strokeWeight(2);
    fill(175);
    if (dragging) {
      fill(50);
    }
    ellipse(location.x,location.y,mass*2,mass*2);
  } 

  // The methods below are for mouse interaction

  // This checks to see if we clicked on the mover
  void clicked(int mx,int my) {
    float d = dist(mx,my,location.x,location.y);
    if (d < mass) {
      dragging = true;
      dragOffset.x = location.x-mx;
      dragOffset.y = location.y-my;
    }
  }

  void stopDragging() {
    dragging = false;
  }

  void drag(int mx,int my) {
    if (dragging) {
      location.x = mx + dragOffset.x;
      location.y = my + dragOffset.y;
    }
  }
}

// Nature of Code 2011
// Daniel Shiffman
// Chapter 3: Oscillation

// Class to describe an anchor point that can connect to "Bob" objects via a spring
// Thank you: http://www.myphysicslab.com/spring2d.html

class Spring { 

  // Location
  PVector anchor;

  // Rest length and spring constant
  float len;
  float k = 0.2;

  Bob a;
  Bob b;

  // Constructor
  Spring(Bob a_,Bob b_,int l) {
    a = a_;
    b = b_;
    len = l;
  } 

  // Calculate spring force
  void update() {
    // Vector pointing from anchor to bob location
    PVector force = PVector.sub(a.location,b.location);
    // What is distance
    float d = force.mag();
    // Stretch is difference between current distance and rest length
    float stretch = d - len;

    // Calculate force according to Hooke's Law
    // F = k * stretch
    force.normalize();
    force.mult(-1 * k * stretch);
    a.applyForce(force);
    force.mult(-1);
    b.applyForce(force);
  }


  void display() {
    strokeWeight(3);
    stroke(0);
    line(a.location.x,a.location.y,b.location.x,b.location.y);
    ellipse(a.location.x,10);
    ellipse(b.location.x,b.location.y,10);
  }
}

Slider controlled Spring

相关文章

这篇文章主要介绍了spring的事务传播属性REQUIRED_NESTED的原...
今天小编给大家分享的是一文解析spring中事务的传播机制,相...
这篇文章主要介绍了SpringCloudAlibaba和SpringCloud有什么区...
本篇文章和大家了解一下SpringCloud整合XXL-Job的几个步骤。...
本篇文章和大家了解一下Spring延迟初始化会遇到什么问题。有...
这篇文章主要介绍了怎么使用Spring提供的不同缓存注解实现缓...