第0章 引言
参考 0.6.2 二维噪声
迷雾森林:
loat increment = 0.01;
float zoff = 0.0;
float zincrement = 0.02;
void setup() {
size(200,200);
}
void draw() {
background(0);
loadPixels();
float xoff = 0.0;
for (int x = 0; x < width; x++) {
xoff += increment;
float yoff = 0.0;
for (int y = 0; y < height; y++) {
yoff += increment;
float bright = noise(xoff,yoff,zoff)*255;
pixels[x+y*width] = color(bright*0.5,bright,bright*0.1);
}
}
updatePixels();
zoff += zincrement;
}
第一章 向量
一个简化的"飞碟",让它渐渐地驶向鼠标。(距离越近,渐进越慢)具有影子拖移效果
float x,
x0=0.0,
x1=0.0,
x2=0.0,
x3=0.0,
x4=0.0,
x5=0.0,
x6=0.0,
y,
y0=0.0,
y1=0.0,
y2=0.0,
y3=0.0,
y4=0.0,
y5=0.0,
y6=0.0;
void positonsSet()
{
y6=y5;
y5=y4;
y4=y3;
y3=y2;
y2=y1;
y1=y;
x6=x5;
x5=x4;
x4=x3;
x3=x2;
x2=x1;
x1=x;
}
float easing;
float diameterWidth = 32.0,
diameterHeight = 4.0;
void draw_a_UFO(float x, float y, int c)
{
fill(c);
ellipse(x,y,diameterWidth / 2,diameterHeight * 2.5);
ellipse(x,y,diameterWidth,diameterHeight);
}
int colorSet = 250;
int myColor;
void colorChange()
{
myColor -= 33;
fill(myColor);
}
void setup()
{
frameRate(10);
size(720,404);
smooth();
x = 0.5 * width;
y = 0.5 * height;
easing = 0.2;
}
void draw()
{
background(20);
float targetX = mouseX,
targetY = mouseY;
x += (targetX - x) * easing;
y += (targetY - y) * easing;
noStroke();
positonsSet();
myColor = colorSet;
draw_a_UFO(x0,y0,myColor);
colorChange();
draw_a_UFO(x1,y1,myColor);
colorChange();
draw_a_UFO(x2,y2,myColor);
colorChange();
draw_a_UFO(x3,y3,myColor);
colorChange();
draw_a_UFO(x4,y4,myColor);
colorChange();
draw_a_UFO(x5,y5,myColor);
colorChange();
draw_a_UFO(x6,y6,myColor);
colorChange();
println(frameCount);
}
第二章 力
2.7 摩檫力
摩檫力是一种耗散力.耗散力的定义是:在运动中使系统总能量减少的力.比如说,开车时,脚踩刹车板会让车通过摩檫力使轮胎减速,在这个过程中,动能被转化为热能.只要两个物体的表面相互接触,它们之间就有摩檫力.摩檫力可分为静摩檫力(物体相对表面静止不动)和动摩檫力(物体在表面上运动)
Mover[] movers = new Mover[20];
void setup() {
size(1000,500);
randomSeed(1);
for(int i = 0; i < movers.length;i++) {
movers[i] = new Mover(random(1,4),0,0);
}
}
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);
float c = 0.05;
float normal = 1;
PVector friction = movers[i].velocity.get();
friction.mult(-1);
friction.normalize();
friction.mult(c);
friction.mult(normal);
if(movers[i].location.x > width / 2) {
movers[i].applyForce(friction);
}
movers[i].applyForce(wind);
movers[i].applyForce(gravity);
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}
}
class PVector {
float x;
float y;
PVector(float x_,float y_) {
x = x_;
y = y_;
}
PVector get() {
PVector newVector = new PVector(x,y);
return newVector;
}
void add(PVector v) {
x = x + v.x;
y = y + v.y;
}
void sub(PVector v) {
x = x - v.x;
y = y - v.y;
}
void mult(float n) {
x = x * n;
y = y * n;
}
void div(float n) {
x = x / n;
y = y / n;
}
float mag() {
return sqrt(x * x + y * y);
}
void normalize() {
float m = mag();
if(m != 0) {
div(m);
}
}
void limit(float max) {
if(mag() > max) {
normalize();
mult(max);
println(mag());
}
}
}
class Mover {
PVector location;
PVector velocity;
PVector acceleration;
float mass;
color c;
Mover(float m,float x,float y) {
location = new PVector(x,y);
velocity = new PVector(0,0);
acceleration = new PVector(0,0);
mass = m;
c = color(random(255),random(255),random(25));
}
void applyForce(PVector force) {
PVector newVector = force.get();
newVector.div(mass);
acceleration.add(newVector);
}
void update() {
velocity.add(acceleration);
location.add(velocity);
acceleration.mult(0);
}
void display() {
stroke(0);
strokeWeight(2);
fill(c);
fill(random(255),random(255),random(255));
ellipse(location.x,location.y,mass * 16,mass * 16);
}
void checkEdges() {
if(location.x > width) {
location.x = width;
velocity.x *= -1;
} else if(location.x < 0) {
velocity.x *= -1;
location.x = 0;
}
if(location.y > height) {
velocity.y *= -1;
location.y = height;
}
}
}
液滴的大小会影响其所受阻力的大小,而在不同的介质中,液滴所受到的阻力也不同,所以他的下降速度也就不同。轻的液滴重量轻,碰到液面后会反弹,重点的液滴直接落入液体中,但受到阻力大本身重力也大,故向下的力大,液体中下降快。这里设置一条空气与蜂蜜的分界线,越过分界线后,下降所受的阻力加大,速度变慢。运用到物理上浮力的公式:F浮=ρ液gV排以及阻力公式f=k*v²
Mover[] movers = new Mover[10];
Liquid liquid;
void setup() {
size(800, 500);
reset();
liquid = new Liquid(0, height/2, width, height/2, 0.3);
}
void draw() {
background(255);
liquid.display();
for (int i = 0; i < movers.length; i++) {
if (liquid.contains(movers[i])) {
PVector drag = liquid.drag(movers[i]);
movers[i].applyForce(drag);
}
PVector gravity = new PVector(0, 0.1*movers[i].mass);
movers[i].applyForce(gravity);
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}
fill(0, 120);
}
void mousePressed() {
reset();
}
void reset() {
for (int i = 0; i < movers.length; i++) {
movers[i] = new Mover(random(0.05, 3), 30+i*60, 0);
}
}
// Liquid class
class Liquid {
// Liquid is a rectangle
float x,y,w,h;
// Coefficient of drag
float c;
Liquid(float x_, float y_, float w_, float h_, float c_) {
x = x_;
y = y_;
w = w_;
h = h_;
c = c_;
}
// Is the Mover in the Liquid?
boolean contains(Mover m) {
PVector l = m.location;
if (l.x > x && l.x < x + w && l.y > y && l.y < y + h) {
return true;
} else {
return false;
}
}
// Calculate drag force
PVector drag(Mover m) {
// Magnitude is coefficient * speed squared
float speed = m.velocity.mag();
float dragMagnitude = c * speed * speed;
PVector drag = m.velocity.get();
drag.mult(-1);
drag.setMag(dragMagnitude);
return drag;
}
void display() {
noStroke();
fill(255,185,15);
rect(x,y,w,h);
}
}
class Mover {
// location, velocity, and acceleration
PVector location;
PVector velocity;
PVector acceleration;
// Mass is tied to size
float mass;
Mover(float m, float x, float y) {
mass = m;
location = new PVector(x, y);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
}
// Newton's 2nd law: F = M * A
// or A = F / M
void applyForce(PVector force) {
// Divide by mass
PVector f = PVector.div(force, mass);
// Accumulate all forces in acceleration
acceleration.add(f);
}
void update() {
// Velocity changes according to acceleration
velocity.add(acceleration);
// Location changes by velocity
location.add(velocity);
// We must clear acceleration each frame
acceleration.mult(0);
}
// Draw Mover
void display() {
noStroke();
fill(0,1, 255, 30);
ellipse(location.x, location.y, mass*16, mass*16);
}
void checkEdges() {
if (location.y > height) {
velocity.y *= -1; // A little dampening when hitting the bottom
location.y = height;
}
}
}
当 mouseX > pmouseX 时,即向右运动时,设定腿部相对于身体的旋转角度为PI/4
当mouseX < pmouseX 时,即向左运动时,设定腿部相对于身体的旋转角度为-PI/4
当mouseX = pmouseX 时,即不动时,设定腿部相对于身体的旋转角度为0为避免太灵敏,可以设定一个范围(如-5~5):
当mouseX - pmouseX > 5时,设定角度为PI/4
当mouseX - pmouseX < -5时,设定角度为-PI/4
当-5 <= mouseX - pmouseX <= 5时,设定角度为0
大白会随着鼠标的移动而移动,腿会随着身体而摆动。
void setup(){
size(600,400);
}
void draw(){
colorMode(HSB,360,100,100);
background(0,40,100);
float w = 120;
float l = w/3*5;
DaBai db = new DaBai(w,l);
db.leftArm.a=atan2(mouseY,mouseX);
db.rightArm.a=PI-atan2(mouseY,width-mouseX);
if((mouseX-pmouseX)>5){
db.leftLeg.a=PI/4;db.rightLeg.a=PI/4;
}else if((mouseX-pmouseX)<-5){
db.leftLeg.a=-PI/4;db.rightLeg.a=-PI/4;
}else{
db.leftLeg.a=0;db.rightLeg.a=0;
}
stroke(30,75,75);strokeWeight(2);
line(0,0,mouseX-db.body.w-db.leftArm.l*cos(db.leftArm.a),mouseY-db.body.l/2-db.leftArm.l*sin(db.leftArm.a));
line(width,0,mouseX+db.body.w-db.rightArm.l*cos(db.rightArm.a),mouseY-db.body.l/2-db.rightArm.l*sin(db.rightArm.a));
pushMatrix();
translate(mouseX,mouseY);
db.display();
popMatrix();
}
class DaBai{
float w,l;
Head head;
Body body;
Arm leftArm;
Arm rightArm;
Leg leftLeg;
Leg rightLeg;
DaBai(float w,float l){
this.w=w;this.l=l;
head = new Head(w/3.5);
body = new Body(l/3);
leftArm = new Arm(l/5,0);
rightArm = new Arm(l/5,0);
leftLeg = new Leg(l/6,0);
rightLeg = new Leg(l/6,0);
}
void display(){
ellipseMode(RADIUS);
// left arm
pushMatrix();
translate(-body.w,-body.l/2);
rotate(leftArm.a);
leftArm.display();
popMatrix();
// right arm
pushMatrix();
translate(body.w,-body.l/2);
rotate(rightArm.a);
rightArm.display();
popMatrix();
// left leg
pushMatrix();
translate(-body.w/3,body.l/1.25);
rotate(leftLeg.a);
leftLeg.display();
popMatrix();
// right leg
pushMatrix();
translate(body.w/3,body.l/1.25);
rotate(rightLeg.a);
rightLeg.display();
popMatrix();
// body
body.display();
// head
pushMatrix();
translate(0,-body.l);
head.display();
popMatrix();
}
}
class Head{
float w,l;
Head(float w){
this.w=w;l=w*2/3;
}
void display(){
ellipseMode(RADIUS);
fill(0,0,100);stroke(0,0,0);strokeWeight(2);
ellipse(0,0,w,l);
fill(0,0,0);stroke(0,0,0);
ellipse(-w/5*2,-l/10,l/10,l/10);
ellipse(w/5*2,-l/10,l/10,l/10);
noFill();stroke(0,0,0);strokeWeight(2);
bezier(-w/5*2,-l/10,0,l/20,0,l/20,w/5*2,-l/10);
fill(20,80,80);stroke(20,80,80);strokeWeight(2);
ellipse(-w/5*3,l/5,l/10,l/15);
ellipse(w/5*3,l/5,l/10,l/15);
}
}
class Body{
float w,l;
Body(float l){
this.l=l;w=l*1/1.2;
}
void display(){
ellipseMode(RADIUS);
fill(0,0,100);stroke(0,0,0);strokeWeight(2);
ellipse(0,0,w,l);
fill(30,10,100);stroke(0,10,60);strokeWeight(1);
ellipse(w/5*2,-l/5*2,w/8,w/8);
beginShape();
vertex(w/5*2-w/8,-l/5*2);
vertex(w/5*2-w/16,-l/5*2);
vertex(w/5*2-w/16,-l/5*2-w/16);
vertex(w/5*2+w/16,-l/5*2-w/16);
vertex(w/5*2+w/16,-l/5*2);
vertex(w/5*2+w/8,-l/5*2);
endShape();
}
}
class Arm{
float w,l;
float a;
Arm(float w,float a){
this.w=w;l=w*1/3;this.a=a;
}
void display(){
ellipseMode(RADIUS);
fill(0,0,100);stroke(0,0,0);strokeWeight(2);
ellipse(0,0,w,l);
}
}
class Leg{
float w,l;
float a;
Leg(float l,float a){
this.l=l;w=l*1/2;this.a=a;
}
void display(){
ellipseMode(RADIUS);
fill(0,0,100);stroke(0,0,0);strokeWeight(2);
ellipse(0,0,w,l);
}
}
第三章 震荡
带有角速度的振荡
一个以弧度为单位的圆(一个圆周为2π,即:360度=2π),在单位时间内所走的弧度即为角速度.公式为:ω=Ч/t(Ч为所走过弧度,t为时间)ω的单位为:弧度每秒
Oscillator[] oscillators = new Oscillator[200];
void setup() {
size(800,500);
background(255);
for(int i = 0; i < oscillators.length; i++) {
oscillators[i] = new Oscillator();
}
}
void draw() {
background(255);
for(int i = 0; i < oscillators.length; i++) {
oscillators[i].oscillate();
oscillators[i].display();
}
}
class Oscillator {
PVector angle;
PVector velocity;
PVector amplitude;
color c;
Oscillator() {
angle = new PVector();
velocity = new PVector(random(-0.05,0.05),random(-0.05,0.05));
amplitude = new PVector(random(width / 2),random(height / 2));
c = color(random(55),random(255),random(255));
}
void oscillate() {
angle.add(velocity);
}
void display() {
float x = sin(angle.x) * amplitude.x;
float y = sin(angle.y) * amplitude.y;
pushMatrix();
translate(width / 2,height / 2);
stroke(0);
fill(c);
line(0,0,x,y);
ellipse(x,y,16,16);
popMatrix();
}
}
class PVector {
float x;
float y;
PVector() {
x = 0;
y = 0;
}
PVector(float x_,float y_) {
x = x_;
y = y_;
}
PVector get() {
PVector newVector = new PVector(x,y);
return newVector;
}
void add(PVector v) {
x = x + v.x;
y = y + v.y;
}
void sub(PVector v) {
x = x - v.x;
y = y - v.y;
}
void mult(float n) {
x = x * n;
y = y * n;
}
void div(float n) {
x = x / n;
y = y / n;
}
float mag() {
return sqrt(x * x + y * y);
}
void normalize() {
float m = mag();
if(m != 0) {
div(m);
}
}
void limit(float max) {
if(mag() > max) {
normalize();
mult(max);
}
}
float heading2D() {
return atan2(y,x);
}
}
第四章 粒子系统
ParticleSystem ps;
PShape s;
float angle=0;
float aVelocity=0;
float aAcceleration=0.001;
void setup() {
size(300, 800);
ps = new ParticleSystem(new PVector(width/2, height-50));
}
void draw() {
background(255);
ps.addParticle();
ps.run();
}
void mousePressed(){
ps=(new ParticleSystem(new PVector(mouseX,mouseY)));
}
class Particle {
PVector location;
PVector velocity;
PVector acceleration;
float lifespan;
Particle(PVector l) {
acceleration = new PVector(0, 0.05);
velocity = new PVector(random(-1, 1), random(-14, -1));
location = l.copy();
lifespan = 255.0;
}
void run() {
update();
display();
}
void update() {
velocity.add(acceleration);
location.add(velocity);
}
boolean isDead() {
if (lifespan <= 0) {
return true;
} else {
return false;
}
}
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);
rectMode(CENTER);
pushMatrix();
rotate(angle);
float k=random(1,10);
line(location.x-k,location.y,location.x+k,location.y);
ellipse(location.x+k,location.y,8,8);
ellipse(location.x-k,location.y,8,8);
line(location.x,location.y-k,location.x,location.y+k);
ellipse(location.x,location.y+k,8,8);
ellipse(location.x,location.y-k,8,8);
s=createShape();
s.beginShape();
s.vertex(location.x+50/2,location.y+18/2);
s.vertex(location.x+61/2,location.y+37/2);
s.vertex(location.x+83/2,location.y+43/2);
s.vertex(location.x+69/2,location.y+60/2);
s.vertex(location.x+71/2,location.y+82/2);
s.vertex(location.x+50/2,location.y+73/2);
s.vertex(location.x+29/2,location.y+82/2);
s.vertex(location.x+31/2,location.y+60/2);
s.vertex(location.x+17/2,location.y+43/2);
s.vertex(location.x+39/2,location.y+37/2);
s.endShape();
shape(s);
popMatrix();
}
}
class ParticleSystem {
ArrayList<Particle> particles;
PVector origin;
ParticleSystem(PVector position) {
origin = position.copy();
particles = new ArrayList<Particle>();
}
void addParticle() {
particles.add(new Particle(origin));
}
void run() {
for (int i = particles.size()-1; i >= 0; i--) {
Particle p = particles.get(i);
p.run();
if (p.isDead()) {
particles.remove(i);
}
}
}
}
参考到一个知乎博主的代码
利用公式:
x = r * sin(a) * cos(b)
y = r * cos(a) * cos(b)
z = r * sin(b)
设置粒子数:100
设置粒子的大小:8
背景使用P3D,使得可以旋转
int num = 100;
ArrayList<Particle> particles;
PVector Rotate;
Particle tempP;
void setup(){
size(1080,680,P3D);
colorMode(HSB);
Rotate = new PVector();
particles = new ArrayList<Particle>();
for(int i = 0; i < num; i++){
particles.add( new Particle() );
}
background(255);
}
void draw(){
noStroke();
fill(255, 18);
rect(0,0,width,height);
Rotate = new PVector(frameCount*0.003, frameCount*0.04, frameCount*0.03);
pushMatrix();
translate(width/2, height/2);
rotateX(Rotate.x);
rotateY(Rotate.y);
rotateZ(Rotate.z);
for(int i = particles.size()-1; i >= 0; i--){
tempP = particles.get(i);
tempP.move();
}
popMatrix();
}
class Particle{
PVector pos,radian;
float dis,h,s,b;
float _weight = 8;
Particle(){
radian = new PVector(random(TWO_PI), random(TWO_PI));
pos = new PVector();
dis = 160;
}
void move(){
update();
display();
}
void update(){
pos.x = dis*sin(radian.x)*cos(radian.y);
pos.y = dis*cos(radian.x)*cos(radian.y);
pos.z = dis*sin(radian.y);
}
void display(){
h = noise(radian.x*0.3, frameCount*0.012)*95 + 130 + map(mouseX, 0 ,width, -20, 20);
noStroke();
fill(h,85,55);
translate(pos.x,pos.y,pos.z);
sphere(_weight);
translate(-pos.x,-pos.y,-pos.z);
}
}