Part1 实现效果以及扩展
水平方向给一个向左或向右的(风)力,垂直方向给一个重力或反重力,力的方向随帧数而改变。灰色小球为阻力小球,该区域内阻力系数不同。
操作说明:
1、点击鼠标重置。
2、移动鼠标来移动阻力球。
3、滚动滑轮来缩放阻力球大小。
Part2 力
力是一个向量。力的书面化概念源自牛顿运动定律。
牛顿三大运动定律:
1、物体有保持静止或运动的趋势。
2、力等于质量乘以加速度,F=M*A。
3、每个作用力都有一个大小相等、方向相反的作用力。
其中第二条定律编程时最为重要,在处理像素时,常常令所有对象的质量等于1。于是根据公式有A=F,即物体的加速度等于力。
因为加速度控制速度,速度控制位置,于是力就是物体运动的起因。
而当考虑质量时,加速度=力/质量。
程序常用的外力有:风力、摩擦力、空气和流体阻力、引力等。
《代码本色》参考案例:
1、制造两个外力:风力和重力。指向不同的方向,大小不相等,同时作用在对象上。
2、流体阻力
物体通过流体或者气体时同样会受摩擦力的作用。流体阻力产生的效果和摩擦力相同(物体会减速),计算阻力公式如下:
简化公式,以便于Processing模拟:
设置一块流体区域,该区域内阻力系数与区域外不同,当物体进入区域时,会产生与速度方向相反的阻力。
Part3 设计思路
参照上述案例一,给窗口中的小球两个力:一个水平力和一个垂直力,力的方向随帧数增加而改变(每500帧)。同时,小球的颜色也每500帧改变一次,可以起到提示用户力的方向发生改变的作用。
参照案例二,设置一个阻力小球,在球体范围内的物体受到阻力的作用。阻力小球的半径随鼠标滚轮变化,位置跟随鼠标移动。
通过该实验可以直观地感受出外力(风力、重力、反重力)对物体的作用,以及阻力对于物体的影响,同时具有较强的交互性,具有一定的趣味性和较好的视觉感受。
Part4 代码实现
①主代码
Mover[] movers = new Mover[9];
Liquid liquid;
int Radius=100;
int t=1;
float H;
void setup() {
colorMode(HSB, 360, 100, 100, 300); //颜色模型
size(640, 360);
reset();
liquid = new Liquid(width/2,height/2,50,0.1); //起始位置,半径,阻力系数
}
void draw() {
background(360);
liquid.display();
for (int i = 0; i < movers.length; i++) {
if (liquid.contains(movers[i])) {
PVector dragForce = liquid.drag(movers[i]);
movers[i].applyForce(dragForce);
}
if(frameCount%500==0) //每隔500帧改变一次力的方向
{t=-t;
H=random(360);
}
PVector wind = new PVector(t*0.01*movers[i].mass,0);
PVector gravity = new PVector(0, t*0.1*movers[i].mass);
movers[i].applyForce(wind);
movers[i].applyForce(gravity);
movers[i].changeColor(H);
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}
fill(0);
text("click mouse to reset", 5, 10);
text("move mouse to move Drag Ball", 5, 25);
text("roll mouse to zoom Drag Ball", 5, 40);
}
void mouseWheel(MouseEvent event){
float e=event.getCount();
Radius+=e*5;
liquid = new Liquid(mouseX,mouseY,Radius,0.1);
}
void mouseMoved() {
liquid = new Liquid(mouseX,mouseY,Radius, 0.1);
}
void mousePressed() {
reset();
}
void reset() {
H=random(360);
for (int i = 0; i < movers.length; i++) {
movers[i] = new Mover(1, 40+i*70, 0,H);
}
}
②流体-Liquid类
class Liquid {
float x, y, r;
float c;
Liquid(float x_, float y_, float r_, float c_) {
x = x_;
y = y_;
r = r_;
c = c_;
}
boolean contains(Mover m) {
PVector l = m.position;
float d;
d=sqrt(sq(x-l.x)+sq(y-l.y));
return d<r+24; //24为小球半径
}
PVector drag(Mover m) {
float speed = m.velocity.mag();
float dragMagnitude = c * speed * speed;
PVector dragForce = m.velocity.get();
dragForce.mult(-1);
dragForce.normalize();
dragForce.mult(dragMagnitude);
return dragForce;
}
void display() {
noStroke();
fill(20,200);
ellipse(x, y, r*2,r*2);
}
}
③Mover类
class Mover {
PVector position;
PVector velocity;
PVector acceleration;
float H;
float mass;
Mover(float m, float x, float y,float H) {
mass = m;
position = new PVector(x, y);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
this.H=H;
}
void applyForce(PVector force) {
PVector f = PVector.div(force, mass);
acceleration.add(f);
}
void update() {
velocity.add(acceleration);
position.add(velocity);
acceleration.mult(0);
}
void changeColor(float H){
this.H=H;
}
void display() {
stroke(0);
strokeWeight(1);
fill(H,90,50, 200);
ellipse(position.x, position.y, 48, 48);
}
void checkEdges() {
if (position.x > width) {
position.x = width;
velocity.x *= -1;
}
else if (position.x < 0) {
velocity.x *= -1;
position.x = 0;
}
if (position.y > height) {
velocity.y *= -1;
position.y = height;
}
else if (position.y < 0) {
velocity.y *= -1;
position.y = 0;
}
}
}
来源:CSDN
作者:我也没办法啊
链接:https://blog.csdn.net/weixin_44914272/article/details/103622860