我在Processing中模拟粒子系统。基于丹尼尔希夫曼的“本质的代码”一书,我做了一个弹簧,然后我开始尝试使用滑块做一个基于滑块的长度更长或更短的滑块。
现在,我试图制作一个滑块滑动,两个粒子移动到两个粒子的相同方向。 我使用PVector添加,找到新位置并绘制节点,但是当我有多个成员且一个受其他成员影响时,它不起作用。 我需要使用一个力来执行此操作:请参阅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);
}
检查下图:
(a)是我想要的,(b)就是现在这样做的。
在第一个例子中,长度相同,成员滑动(两个粒子)。
在第二个长度更大但不滑动
如果您知道如何施加滑动会员的力量,请告诉我。
谢谢
答案 0 :(得分:3)
如果我理解正确,你会尝试做一些事情:
第一部分是微不足道的,因为Spring对象具有len
属性。
第二个涉及一点vector math:
这是一个评论草图,实现了以上几点:
//sliders to control spring rest length and translation
Slider rlength = new Slider("rest length", 5, 5, 200, 20, 50, 250, 100, false);
Slider translate = new Slider("translate", 5, 30, 200, 20, -10, 10, 0, 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,mouseY,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 x,float y,float w,float h,float min,float max,float value,boolean isInt){
super(label,x,y,w,h);
this.min = min;
this.max = max;
this.value = value;
this.isInt = isInt;
cx = map(value,min,max,x,x+w);
}
void update(int mx,int my,boolean md){
if(md){
if((mx >= x && mx <= (x+w)) &&
(my >= y && my <= (y+h))){
cx = mx;
value = map(cx,x,x+w,min,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,y,w,h);
fill(fg,64);
rect(x,y,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, a.location.y,10,10);
ellipse(b.location.x, b.location.y,10,10);
}
}