首先,也是来为虎牙大大的代码加上注释。
FlowField flow;
ArrayList<Vehicle> vlist;
PVector center; //中心点
void setup() {
size(1200, 600);
flow = new FlowField();
vlist = new ArrayList<Vehicle>();
for (int i = 0; i<70; i++) {
vlist.add(new Vehicle(random(width), random(height)));//vlist的初始化
}
center = new PVector(width/2, height/2);//窗口中心
}
void draw() {
background(175);
for (Vehicle v : vlist) { //更新vlist
v.follow(flow);
v.run(center, flow);
}
}
void mousePressed() {
vlist.add(new Vehicle(mouseX, mouseY));//添加一条新的曲线
}
class FlowField {
PVector [][] field; //创建一个二维数组,其中,PVector是二维的,即(x,y)
int cols, rows; //列,行
int sulotion;
FlowField() { //构造函数
sulotion = 10;
cols = width/sulotion;
rows = height/sulotion;
field = new PVector [cols][rows]; //此时拥有cols * rows个二维向量
init(); //为field赋初始值
}
PVector lookUp(PVector lookup) { //获取数组中的一个向量值
//对行列值得一个范围限定
int xrow = int(constrain(lookup.x/sulotion, 0, cols-1));//约束
int ycol = int(constrain(lookup.y/sulotion, 0, rows-1));//约束
return field[xrow][ycol].get();
}
public void init() { //初始化
for (int i=0; i<cols; i++) {
for (int j = 0; j<rows; j++) {
field[i][j] = new PVector(random(cos(0)), random(sin(1)));
}
}
}
}
class Vehicle {
PVector location; //位置
PVector velocity; //速率
PVector acceleration; //加速度
float maxSpeed; //最大速度
float maxforce; //最大力
float mass; //质量
float r;
float w; //边线宽度
float xoffset; //水平偏移量
float yoffset; //垂直偏移量
color c; //边线颜色
Vehicle(float x, float y) {
location = new PVector(x, y); //初始位置
acceleration = new PVector(0, 0); //加速度初始为0
velocity = new PVector(0, 0); //速率初始为0
r = 7.0;
maxSpeed = 4; //最大速率
maxforce = 0.1; //最大力
mass = 2; //质量
xoffset = random(width); //随机偏移
yoffset = random(height); //随机偏移
c = color(random(255), random(255), random(255)); //随机颜色
w = random(1, 2); //随机线宽
}
void update() { //更新位置
velocity.add(acceleration); //v = v + at;v为速度,a为加速度
location.add(velocity); //s = s + vt;s为位移,v为速度
velocity.limit(maxSpeed); //当速度加速到最大速度就不在加速
acceleration.mult(0); //清0
}
void applyForce(PVector f) { //更新加速度
PVector force= f.get();
force.div(mass); //a = f/m;a为加速度,f为施加的力,m为质量
acceleration.add(force); //为加速度赋值
}
void follow(FlowField f) { //实时计算所需力的大小
PVector desire =f.lookUp(location);
desire.mult(maxSpeed);
PVector steer = PVector.sub(desire, velocity);
steer.limit(maxforce);
applyForce(steer);
}
public void display(PVector center, FlowField f) {//绘图
PVector temp;
temp = f.lookUp(new PVector(random(width), random(height)));//随机获取一个点
beginShape();
noFill();
stroke(c);
strokeWeight(w);
vertex(center.x, center.y); //设定第一个锚点
bezierVertex(temp.x, temp.y, temp.x+xoffset, temp.y+yoffset, this.location.x, this.location.y);//贝塞尔曲线(第一控制点,第二控制点,锚点)
endShape(CLOSE);
}
void run(PVector center, FlowField f) {//更新并绘制
update();
display(center, f);
}
}
注释写的不是很详细,有些变量的值我也不知道是做什么的,因此我就没加注释。但大概思想是明了的。
个人认为最中心的地方就是绘制贝塞尔曲线那一行代码,剩下的均是为其做铺垫。从开头看有一个可变数组vlist,初始大小为70,也就是刚开始有70条曲线(我没数过)。再往下有一个鼠标点击新建一条曲线,是将鼠标坐标作为参数传进去的。
我看函数说明上说,bezierVertex涉及四个点,两个锚点,两个控制点,这四个点的具体含义是什么我不能准确描述,按照我的理解:锚点是线条的起点和终点,控制点是控制线条弯曲的。但是在程序运行中线条是闭合的,所以我的理解应该是错误的。等有大佬看到了请在评论里解惑,在此谢过大佬。
线条会整理自己的方向,是因为Vehicle类中update、applyForce、follow一起作用的结果,至于原理么,可以参考高中物理中的运动部分,但我写不了,因为我说不明白(没有深入研究)。
期间也问了度娘很多,flowField意为流体,Vehicle意为传播媒介,是的,我不明白这个意义。
作为官方示例都没有学习完表示抱歉,会随着学习更新。
- 本文固定链接: http://iprocessing.cn/2017/08/06/第三期boss学习及分析/
- 转载请注明: fishVD 于 Processing编程艺术 发表
《第三期boss学习及分析》有 1 条评论