0随机游走
效果图
理论
random()函数生成“伪随机数”
Perlin噪声的noise()函数生成随机数
关键代码
//使用random()函数,随机改变生成圆的颜色与大小
void display() {
int a = int(random(1,15));
int r = int(random(0,255));
int g = int(random(0,255));
int b = int(random(0,255));
stroke(r,g,b);
ellipse(x,y,a,a);
}
//随机游走
void step() {
x = map(noise(tx),0,1,0,width);
y = map(noise(ty),0,1,0,height);
tx += 0.01;
ty += 0.01;
}
1向量
效果图
理论
向量通常被绘制为一个带箭头的线段,线段的长度代表向量的大小,箭头的方向代表向量的方向。
模拟生态系统,实现一组物体同时向鼠标加速运动。
运用到了:向量加法
速度变化依靠加速度的加法运算: velocity.add(acceleration);
位置的变化运用了速度的加法运算: position.add(velocity);
加速度数值运用了向量减法: acceleration = PVector.sub(mouse,position);
关键代码
应用示例1.11并进行了修改与拓展
//边缘检测
void checkEdges(){
if(position.x>width){
position.x=0;
}else if(position.x<0){
position.x = width;
}
if(position.y>height){
position.y=0;
}else if(position.y<0){
position.y = height;
}
}
运动数值:
//加速度数值
PVector mouse = new PVector(mouseX,mouseY);
acceleration = PVector.sub(mouse,position);
acceleration.normalize();
acceleration.mult(0.5);
//加速度改变速度,速度改变位置
velocity.add(acceleration);
velocity.limit(topspeed);
position.add(velocity);
闪烁的圆圈
void display() {
int r = int(random(0,255));
int g = int(random(0,255));
int b = int(random(0,255));
stroke(0);
strokeWeight(2);
fill(r,g,b);
ellipse(position.x,position.y,18,18);
}
2力
效果图
理论
力是一个向量,它使有质量的物体产生加速。
牛顿三大定律(从Processing角度):
1、在平衡状态下,对象的速度向量始终是常量。
2、力总是成双成对的出现,且大小相等、方向相反。
3、在模拟物体之间引力时,需要同时计算作用力和反作用力。
实验代码
给了5个质量不同的小球,通过改变小球的半径,体现小球的大小,越大的小球质量响应越大。赋予了重力和风力。其中重力是每个小球运动速度不同的主要原因。
class Mover {
PVector position;
PVector velocity;
PVector acceleration;
float mass;
Mover(float m) {
position = new PVector(0,0);
velocity = new PVector(0,0);
acceleration = new PVector(0,0);
mass = m;
}
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 display() {
stroke(0);
strokeWeight(2);
fill(mass*23+23,mass*30+22,mass*8+82);
ellipse(position.x,position.y,mass*16,mass*16);
}
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;
}
}
}
Mover[] movers = new Mover[5];
void setup() {
size(640,480);
for(int i = 0;i < movers.length; i++){
movers[i] = new Mover(random(1,6));
}
}
void draw() {
background(255);
for(int i=0;i<movers.length;i++){
PVector wind = new PVector(0.01,0);
PVector gravity = new PVector(0,0.1*movers[i].mass);
movers[i].applyForce(wind);
movers[i].applyForce(gravity);
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}
}
3振荡
效果图
改变球的半径,且将球的重力与球的半径相关联: gravity = 0.01*ballr
不同大小的球的不同:
理论
进入粒子系统,运用三角函数。
rotate()函数用于旋转物体
运用三角函数与力来模拟钟摆:
关键代码
//加速度、速度、角度变化
float gravity = 0.01*ballr;
aAcceleration = (-1 * gravity / r) * sin(angle);
aVelocity += aAcceleration;
aVelocity *= damping;
angle += aVelocity;
停止摇动判断:
void stopDragging() {
if (dragging) {
aVelocity = 0;
dragging = false;
}
}
图形绘制:
void display() {
position.set(r*sin(angle), r*cos(angle), 0);
position.add(origin);
stroke(0);
strokeWeight(2);
// Draw the arm
line(origin.x, origin.y, position.x, position.y);
ellipseMode(CENTER);
fill(175);
if (dragging) fill(0);
// Draw the ball
ellipse(position.x, position.y, ballr, ballr);
}
4粒子系统
效果图
理论
"粒子系统"就是由一系列独立对象组成的集合。
创建单个粒子系统的类:PracticeSystem
创建一个ArrayList存放多个粒子系统:ArrayList particles;
点击鼠标即可新加一个粒子系统:
void mousePressed() {
systems.add(new ParticleSystem(1,new PVector(mouseX,mouseY)));
}
关键代码
对4.4的示例进行了拓展,主要修改了单个粒子的形状、使其颜色并不一样,形状也有所变换,且能闪烁
void display() {
stroke(0, lifespan);
strokeWeight(1);
float r = random(0,255);
float g = random(0,255);
float b = random(0,255);
fill(r,g,b, lifespan);
// ellipse(position.x,position.y,12,12);
float k=random(1,10);
line(position.x-k,position.y,position.x+k,position.y);
ellipse(position.x+k,position.y,8,8);
ellipse(position.x-k,position.y,8,8);
line(position.x,position.y-k,position.x,position.y+k);
ellipse(position.x,position.y+k,8,8);
ellipse(position.x,position.y-k,8,8);
}
完整代码为:
class Particle {
PVector position;
PVector velocity;
PVector acceleration;
float lifespan;
Particle(PVector l) {
acceleration = new PVector(0,0.05);
velocity = new PVector(random(-1,1),random(-2,0));
position = l.get();
lifespan = 255;
}
void run() {
update();
display();
}
// Method to update position
void update() {
velocity.add(acceleration);
position.add(velocity);
lifespan -= 2.0;
}
// Method to display
void display() {
stroke(0, lifespan);
strokeWeight(1);
float r = random(0,255);
float g = random(0,255);
float b = random(0,255);
fill(r,g,b, lifespan);
// ellipse(position.x,position.y,12,12);
float k=random(1,10);
line(position.x-k,position.y,position.x+k,position.y);
ellipse(position.x+k,position.y,8,8);
ellipse(position.x-k,position.y,8,8);
line(position.x,position.y-k,position.x,position.y+k);
ellipse(position.x,position.y+k,8,8);
ellipse(position.x,position.y-k,8,8);
}
// Is the particle still useful?
boolean isDead() {
if (lifespan < 0.0) {
return true;
} else {
return false;
}
}
}
class ParticleSystem {
ArrayList<Particle> particles; // An arraylist for all the particles
PVector origin; // An origin point for where particles are birthed
ParticleSystem(int num, PVector v) {
particles = new ArrayList<Particle>(); // Initialize the arraylist
origin = v.get(); // Store the origin point
for (int i = 0; i < num; i++) {
particles.add(new Particle(origin)); // Add "num" amount of particles to the arraylist
}
}
void run() {
for (int i = particles.size()-1; i >= 0; i--) {
Particle p = particles.get(i);
p.run();
if (p.isDead()) {
particles.remove(i);
}
}
}
void addParticle() {
particles.add(new Particle(origin));
}
// A method to test if the particle system still has particles
boolean dead() {
if (particles.isEmpty()) {
return true;
}
else {
return false;
}
}
}
ArrayList<ParticleSystem> systems;
void setup() {
size(640,480);
systems = new ArrayList<ParticleSystem>();
}
void draw() {
background(230, 230, 250);
for (ParticleSystem ps: systems) {
ps.run();
ps.addParticle();
}
fill(0);
}
void mousePressed() {
systems.add(new ParticleSystem(1,new PVector(mouseX,mouseY)));
}