《代码本色》 结合牛顿力学 习作
第0章
随机游走+柏林噪声
参考0-1、0-6
0-1
0-6
代码:
class Walker{
float x;
float y;
Walker(){
x = 1;
y = 1;
}
void step(){
float stepx = int(random(3))-1;
float stepy = int(random(3))-1;
x += stepx;
y += stepy;
}
}
Walker w;
void setup(){
size(600, 300, P3D);
background(0);
fill(255, 128);
noStroke();
//lights();
}
float t = 0;
void draw(){
++t;
w = new Walker();
w.step();
clear();
for(int x = 0; x<width; x += 20){
for(int y = 0; y<height; y += 20){
for(int z = 40; z<300; z += 20){
float n = noise(0.02*x, 0.02*y, 0.02*(z+t));
x += 0.1*w.x;
y += 0.1*w.y;
translate(x, y, -z);
float bright = map(noise(x,y), 0, 1, 0, 255);
fill(5+bright, n*160);
//box(n*20);
ellipse(2,n*20,20,20);
translate(-x, -y, z);
}
}
}
}
结果图:
思路:
定义了一个Walker类,使圆产生一定程度的偏移,随时间不断移动,运用0-6中的写法定义bright变量,让颜色的亮度也产生变化,其余是生成大小和空间前后位置随时间运用柏林噪音生成平滑变化的小圆圈。
第1章
向量
参考1-7、1-8、1-9
1-7
1-8
1-9
代码:
class Mover{
PVector location;
PVector velocity;
PVector acceleration;
float topspeed;
float t = 0;
Mover(){
location = new PVector(width/2, height/2);
velocity = new PVector(0, 0);
acceleration = new PVector(-noise(t-1), noise(t));
topspeed = 10;
}
void update(){
t+=1;
if(t>175) t = 0;
acceleration.add(PVector.random2D());
acceleration.mult(random(2));
velocity.add(acceleration);
velocity.limit(topspeed);
location.add(velocity);
}
void display(){
stroke(0);
fill(175-t);
ellipse(location.x, location.y, 16, 16);
}
void checkEdges(){
if(location.x>width){
location.x = 0;
}else if(location.x<0){
location.x = width;
}
if(location.y>height){
location.y = 0;
}else if(location.y<0){
location.y = height;
}
}
}
Mover m;
void setup(){
size(200,200);
smooth();
m = new Mover();
}
void draw(){
m.update();
m.display();
m.checkEdges();
}
结果图:
思路:
1-8、1-9代码大致相同,在1-8的基础上修改加速度acceleration的初值,由noise()柏林噪音赋值,添加上1-9修改加速度随机方向的代码。由于代码最后会出现由小圆球组成的乱线,难以分辨,所以修改了颜色,随时间变化。
第2章
力
参考2-1、2-2、2-3、2-4
2-1
2-2
2-3
2-4
代码:
class Mover{
PVector location;
PVector velocity;
PVector acceleration;
float mass;
Mover(){
location = new PVector(30, 30);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
mass = 1;
}
void setLocation(PVector location){
this.location = location;
}
void setVeciloty(PVector veciloty){
this.velocity = veciloty;
}
void setMass(float mass){
this.mass = mass;
}
void applyForce(PVector force){
PVector f = PVector.div(force,mass);
acceleration.add(f);
}
void update(){
velocity.add(acceleration);
location.add(velocity);
acceleration.mult(0);
}
void display(){
stroke(0);
fill(175);
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){
location.x = 0;
velocity.x *= -1;
}
if(location.y>height){
velocity.y *= -1;
location.y = height;
}
}
}
Mover[] movers = new Mover[100];
void setup(){
size(600,300);
for(int i = 0; i<movers.length; i++){
movers[i] = new Mover();
movers[i].setMass(random(0.1,5));
}
}
void draw(){
background(255);
for(int i = 0; i<movers.length; i++){
PVector wind = new PVector(0.01, 0);
float m = movers[i].mass;
PVector gravity = new PVector(0, 0.1*m);
float normal = 1;
float c = 0.01;
float frictionMag = c*normal;
PVector friction = movers[i].velocity.get();
//friction.div(movers[i].mass);
friction.mult(-1);
friction.normalize();
friction.mult(frictionMag);
movers[i].applyForce(friction);
movers[i].applyForce(wind);
movers[i].applyForce(gravity);
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}
}
结果图:
思路:
2-1、2-2、2-3、2-4其实是一步步完善的代码,将它们结合起来就能得到一个较为真实的小球在受重力和风力作用下的运动状态,这里代码稍微不同的是,书上的代码给小球赋重力是通过构造方法而我是添加了set函数
第3章
震荡
参考3-4、3-10
3-4
3-10
代码:
float theta = 0;
float r = 0;
float s = 5;
Pendulm p;
class Pendulm{
PVector location;
PVector origin;
float r;
float angle;
float aVelocity;
float aAcceleration;
float damping;
Pendulm(PVector origin_,float r_){
origin = origin_.get();
location = new PVector();
r = r_;
angle = PI/4;
aVelocity = 0.0;
aAcceleration = 0.0;
damping = 0.995;
}
void setR(float x){
r = x;
}
void go(){
update();
display();
}
void update(){
float gravity = 0;
aAcceleration = (-1*gravity/r)*sin(angle);
aVelocity += aAcceleration;
angle += aVelocity;
aVelocity += damping;
}
void display(){
location.set(r*sin(angle),r*cos(angle),0);
location.add(origin);
stroke(0);
//line(origin.x,origin.y,location.x,location.y);
fill(175);
ellipse(location.x, location.y, 8,8);
}
}
void setup(){
p = new Pendulm(new PVector(width/2, height/2),r);
size(400, 400);
background(0);
smooth();
}
void love(){
pushMatrix();
fill(225,0,0);
noStroke();
ellipseMode(CENTER);
pushMatrix();
rotate(-QUARTER_PI);
translate(-s/2.0, 0);
ellipse(0, 0, s, s);
rect(-s/2.0, 0, s, s);
popMatrix();
rotate(QUARTER_PI);
translate(s/2.0, 0);
ellipse(0, 0, s, s);
popMatrix();
}
void wiredcicle1(){
for(float t = 0, theta1 = 0; t<r; t += 0.5,theta1 += 0.5){
float tx = t*cos(theta1);
float ty = t*sin(theta1);
noStroke();
fill(0,0,225);
ellipse(tx+width/2, ty+height/2, 4, 4);
}
}
void wiredcicle2(){
for(float t = 0, theta1 = 0; t<r; t += 1,theta1 += 1){
float tx = t*cos(theta1+10);
float ty = t*sin(theta1+10);
noStroke();
fill(240,120,0);
ellipse(tx+width/2, ty+height/2, 5, 5);
}
}
void wiredcicle3(){
for(float t = 0, theta1 = 0; t<r; t += 2,theta1 += 2){
float tx = t*cos(theta1+50);
float ty = t*sin(theta1+50);
noStroke();
fill(255);
ellipse(tx+width/2, ty+height/2, 6, 6);
}
}
void draw(){
clear();
p.setR(1.2*r+10);
p.go();
s+=0.01;
wiredcicle1();
wiredcicle2();
wiredcicle3();
float x = r*cos(theta);
float y = r*sin(theta);
//noStroke();
//fill(255);
//ellipse(x+width/2, y+height/2, 4, 4);
translate(width/2+x,height/2+y-0.5*s+8);
rotate(theta/10);
love();
theta += 0.05;
r += 0.05;
}
结果图:
思路:
这里应用了3-4的变形,即3-4下面的思考题,螺旋形生成图中的蓝黄白点,只需要将theta变大,就不会出现连续的线,而外围旋转的灰点则是应用了钟摆
第4章
粒子系统
参考4-1、4-3
4-1
4-3
代码:
class Particle {
PVector location;
PVector velocity;
PVector acceleration;
float lifespan;
Particle(PVector l) {
// The acceleration
acceleration = new PVector(0, 0.05);
// circel's x and y ==> range
velocity = new PVector(random(-1, 1), random(-2, 0));
// apawn's position
location = l.copy();
// the circle life time
lifespan = 255.0;
}
void run() {
update();
display();
}
void update() {
velocity.add(acceleration);
location.add(velocity);
lifespan-=1.0;
}
boolean isDead() {
if (lifespan <= 0) {
return true;
} else {
return false;
}
}
void display() {
// border
stroke(0, lifespan);
// border's weight
strokeWeight(1);
float r = random(0,255);
float g = random(0,255);
float b = random(0,255);
// random the circle's color
fill(r,g,b, lifespan);
// draw circle
ellipse(location.x, location.y, 3, 3);
}
}
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);
}
}
}
}
ParticleSystem ps;
void setup() {
size(640, 360);
ps = new ParticleSystem(new PVector(width/2, 50));
}
void draw() {
background(0);
ps.addParticle();
ps.run();
}
结果图:
思路:
粒子类和粒子系统类基本都是按照书上的代码来的,改动不大,加上了随机的粒子颜色,让粒子看起来更加好看了一点
39