互动媒体技术课程作业3 《代码本色》编程练习

互动媒体技术课程作业3 《代码本色》编程练习

(processing语言)

1.Ch_0 _RandomWalk

实现米老鼠图形随机平滑移动,位置坐标用map函数生成
在这里插入图片描述
在这里插入图片描述
代码如下



class Walker {
  PVector position;
  PVector noff;

  Walker() {
    position = new PVector(width/2,height/2);      
    noff = new PVector(random(1000),random(1000));
  }
 
  void display() {
      strokeWeight(0);
   //face
    fill(0);
    stroke(0); 
    ellipse(position.x, position.y, 90, 90);  
    ellipse(position.x-40,position.y-40,60,60);
    ellipse(position.x+40,position.y-40,60,60);
    
    fill(255);
    stroke(255);
    ellipse(position.x-10,position.y+7,40,55);
    ellipse(position.x+10,position.y+7,40,55);
    ellipse(position.x,position.y+18,60,50);

    fill(0);
     stroke(0);    
    ellipse(position.x-17,position.y+5,12,25);
    ellipse(position.x+17,position.y+5,12,25);    
    ellipse(position.x,position.y+25,20,12);       
    
    fill(226, 54, 39);
    stroke(226, 54, 39);   
    ellipse(position.x-20,position.y+25,12,10);
    ellipse(position.x+20,position.y+25,12,10);
    
    //word hi
     fill(0);
     strokeWeight(10);
     stroke(0);   
line(position.x+100,position.y-100,position.x+100,position.y-60);   
line(position.x+130,position.y-100,position.x+130,position.y-60);   
line(position.x+100,position.y-80,position.x+130,position.y-80);
line(position.x+160,position.y-75,position.x+160,position.y-60);

    fill(226, 54, 39);
    stroke(226, 54, 39);   
ellipse(position.x+160,position.y-100,10,8); 

  }
 
  // Randomly move up, down, left, right, or stay in one place
  void walk() {
    position.x =map(noise(noff.x),0,1,0,width);      
//map()
    position.y =map(noise(noff.y),0,1,0,height);
   noff.add(0.01,0.01,0);
  }
}
 
Walker w;
void setup() {
  size(800, 800);
  frameRate(60);
  // Create a walker object
  w = new Walker();
}

void draw() {
  background(255);
  // Run the walker object
  w.walk();
  w.display();
}

2.Ch_01 _Vectors

模拟自然生态系统中鱼群觅食场景,鼠标所在位置代表食物,圆圈代表鱼。
原例子中鼠标若一直不动,圆将越来越集中,15个圆趋于同一个;改进部分为将加速度乘以的常数变为用Perlin噪声生成的随机数,使结果更加分散,更加模拟自然。

在这里插入图片描述
在这里插入图片描述
实现模拟“觅食”现象的关键在于
1.计算由物体指向目标位置(鼠标)的向量;
2.单位化该向量(将向量的大小缩短为1);
3.改变以上单位向量的长度(乘以某个合适的值);
4.将步骤3中得到的向量赋给加速度。
在Update()中实现

代码如下

Mover[] movers = new Mover[15];

float t=0;

void setup() {

size(640,640);

  for(int i = 0; i < movers.length; i++)
   {
movers[i] = new Mover(); 
  }
}

void draw() {
 
background(255);

  for(int i = 0; i < movers.length; i++)
   {   
movers[i].update();   
movers[i].display(); 
  } 
t++;
}



class Mover {

// The Mover tracks position, velocity, and acceleration  
PVector position; 
PVector velocity; 
PVector acceleration;
  //The Mover's maximum speed 
float topspeed;
 
Mover() {   
// Start in the center
position = new PVector(random(width),random(height));   
velocity = new PVector(0,0);   
topspeed = 5;
  }
 
void update() {
   // Compute a vector that points from position to mouse
PVector mouse = new PVector(mouseX,mouseY);   
acceleration = PVector.sub(mouse,position);   
// Set magnitude of acceleration   
//acceleration.setMag(n);
    acceleration.normalize();
   
float n =noise(t)/10;   
acceleration.mult(n);      
//acceleration.mult(0.2);
   
// Velocity changes according to acceleration   
velocity.add(acceleration);   
// Limit the velocity by topspeed   
velocity.limit(topspeed);   
// position changes by velocity   
position.add(velocity);
  }
  
void display() {   
stroke(0);   
strokeWeight(2);   
fill(127,200);
ellipse(position.x,position.y,48,48);

  }
}

3.Ch_02 _Forces

模拟了一个原子内部引力系统,场景为一个可以随机移动的原子核和其周围的电子。
所有电子(Mover对象)都被原子核(Attract对象)吸引,绕其周围运动,但相互之间有排斥作用

1.调整原例中的力的作用效果,使模拟更真实
2.原子核的随机移动

模拟关键:斥力和引力的生成(由物理公式转化为代码)
斥力引力 同属 万有引力
在这里插入图片描述
引力示例(斥力只需改变方向,向量乘-1)

PVector attract(Mover m) 
{    // 现在,Mover对象知道如何吸引其他Mover对象         
PVector force = PVector.sub(location,m.location);      
float distance = force.mag();      
distance = constrain(distance,5.0,25.0);  
force.normalize();      
float strength = (G  mass  m.mass) / (distance * distance);
 force.mult(strength);      
   return force; 
      }

在这里插入图片描述
在这里插入图片描述
完整代码如下

Mover[] movers = new Mover[100];
Attractor a;
float g = 1;

void setup() {
 
size(640,640);
 a =new Attractor();

  for(int i = 0; i < movers.length; i++) {   
movers[i] = new Mover(random(4,12),random(width),random(height)); 
  }
}
 
void draw() {

background(255); 
a.display();

  for(int i = 0; i < movers.length; i++) {   
      for (int j = 0; j < movers.length; j++) {     
            if (i != j) {       
PVector force = movers[j].repel(movers[i]);       
movers[i].applyForce(force);
     
}
    }    
PVector force = a.attract(movers[i]);   
movers[i].applyForce(force);   
movers[i].update()   
movers[i].display();

  }
}
 
class Attractor { 
float mass;    // Mass, tied to size 
float radius;  // Radius of the attractor 
PVector position;   // position 
PVector noff;
 
Attractor() {   
position = new PVector(width/2,height/2);   
noff = new PVector(random(width),random(height));   
mass = 10;   
radius = mass * 3;   
drag = new PVector(0.0,0.0); 
  } 
PVector attract(Mover m)    
PVector force = PVector.sub(position,m.position);   // Calculate direction of force
   
float d = force.mag();                   // Distance between objects
d= constrain(d,1.0,25.0);       // Limiting the distance to eliminate "extreme" results for very close or very far objects
   
force.normalize();             // Normalize vector (distance doesn't matter here, we just want this vector for direction)
    
float strength = (g * mass * m.mass) / (d * d);      // Calculate gravitional force magnitude
   
force.mult(5*strength);                    // Get force vector --> magnitude * direction
    
return force;

  }

  //Method to display 
void display() {
   
ellipseMode(CENTER);   
stroke(0);   
fill(0);
//map()      
position.x =map(noise(noff.x),0,1,0,width);         
position.y =map(noise(noff.y),0,1,0,height); 
noff.add(0.001,0.001,0);         
ellipse(position.x,position.y,radius*2,radius*2);

  }
}


class Mover {
 
PVector position; 
PVector velocity; 
PVector acceleration; 
float mass;
  
Mover(float m, float x , float y) {   
mass = m;   
position = new PVector(x,y);
velocity = new PVector(0,0);   
acceleration = new PVector(0,0);
  }
 
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);   
fill(175,200);   
ellipse(position.x,position.y,mass*2,mass*2);
  }
  
PVector repel(Mover m) {
   
PVector force = PVector.sub(position,m.position);             // Calculate direction of force
   
float distance = force.mag();                                 // Distance between objects
    
distance = constrain(distance,1.0,100000.0);                             // Limiting the distance to eliminate "extreme" results for very close or very far objects
    
force.normalize();                                            //Normalize vector (distance doesn't matter here, we just want this vector for direction  
   
float strength = (g * mass * m.mass) / (distance * distance); //Calculate gravitional force magnitude
    
force.mult(-0.001*strength);                                      // Get force vector --> magnitude * direction    

return force;
  }  
  
void checkEdges() {
   
if (position.x > width) {     
position.x = width;     
velocity.x *= -1;
    }   
else if (position.x < 0) {     
position.x = 0;     
velocity.x *= -1;
    }   
if (position.y > height) {     
position.y = height;
velocity.y *= -1;
    }   
else if (position.y < 0) {     
position.y = 0;     
velocity.y *= -1;
    }
  }
}

4.Ch_03 _Oscillation

模拟可微小形变的鱼(有弹性)寻找食物进阶版
1.优化了一条鱼的弹性,使用三个小球加弹簧的系统,模拟具有弹性的身体和鱼的外形
2.鱼食可以鼠标拖动

关键技术:
1.弹簧的弹力实现,三个小球互相作用(Bob类,Spring类)
2.给其中一个小球(作为鱼头)增加向鱼食运动的引力(Bob类中的 applyForce(PVector force) )
3.实现鼠标拖动鱼食(mousePressed() mouseReleased())

胡克定律

class Spring { 
.....
....
void update() {   
// Vector pointing from anchor to bob position   
PVector force = PVector.sub(a.position, b.position);   
// What is distance   
float d = force.mag();   // Stretch is difference between current distance and rest length
   
float stretch = d - len; // Calculate force according to Hooke's Law
   
// F = k * stretch   
force.normalize();   
force.mult(-1 * k * stretch);   
a.applyForce(force);   
force.mult(-1);   
b.applyForce(force);
  }

在这里插入图片描述
完整代码如下


Attractor a;
Bob b1;  Bob b2; Bob b3;
Spring s1;Spring s2;  Spring s3;

void setup() {
 size(640, 640); 
   a= new Attractor(new PVector(width/2,height/2),20,0.4);
  //Create objects at starting position
  //Note third argument in Spring constructor is "rest length"
  b1= new Bob(width/2, 100);
  b2= new Bob(width/2-100, 200);
  b3= new Bob(width/2+100, 300);
  s1= new Spring(b1,b2,100);
  s2= new Spring(b2,b3,80);
  s3= new Spring(b1,b3,100);
}

void draw() { 
background(255); 
a.rollover(mouseX,mouseY); 
a.go(); 
s1.update(); 
s2.update(); 
s3.update(); 
s1.display(); 
s2.display(); 
s3.display();
 PVector f = a.attract(b1);   
// Apply that force to the Crawle  
b1.applyForce(f); 
b1.update(); 
b1.display1(); 
b2.update(); 
b2.display0(); 
b3.update(); 
b3.display0();
}

 

void mousePressed() {
a.clicked(mouseX,mouseY);
}
 
void mouseReleased() 
 a.stopDragging();
}

 

class Bob { 
 
PVector position; 
PVector velocity; 
PVector acceleration; 
float mass = 12;
  //Arbitrary damping to simulate friction / drag 
 float damping = 0.95;
  //Constructor 
Bob(float x, float y) {   
position = new PVector(x,y);
velocity = newPVector();
acceleration =new PVector();    
mass = 12;
  }  

  //Standard Euler integration 
void update() { 
   
velocity.add(acceleration);
   velocity.mult(damping);   
position.add(velocity);   
acceleration.mult(0);
  }

  //Newton's law: F = M * A 
void applyForce(PVector force) {   
PVector f = force.get();   
f.div(mass);   
acceleration.add(f);
  } 
  //Draw the bob 
void display0() {    
stroke(0);   
strokeWeight(2);   
fill(175);
   
if (dragging) {     
fill(50);
    }   
ellipse(position.x,position.y,mass*2,mass*2);
  } 
   
void display1() {    
stroke(0);   
strokeWeight(2);   
fill(0);
   
if (dragging) {     
fill(50);
    }   
ellipse(position.x,position.y,mass*2,mass*2);
  } 
}

 

class Spring { 

  //position 
PVector anchor;
  //Rest length and spring constant 
float len; 
float k = 0.2;
  Bob a;
  Bob b;
  //Constructor 
Spring(Bob a_, Bob b_, int l) ;
    a= a_;
    b= b_;   
len = l;
  } 
  //Calculate spring force

 
void update() {
   
// Vector pointing from anchor to bob position   
PVector force = PVector.sub(a.position, b.position);   
// What is distance   
float d = force.mag();   
// Stretch is difference between current distance and rest length   
float stretch = d - len;    
// Calculate force according to Hooke's Law
   // F = k * stretch   
force.normalize();   
force.mult(-1 * k * stretch);   
a.applyForce(force);   
force.mult(-1);
  b.applyForce(force);
  }
 
void display() {   
strokeWeight(2);   
stroke(0);   
line(a.position.x, a.position.y, b.position.x, b.position.y);
  }
}
 
class Attractor {
 
float mass;    // Mass, tied to size 
float G;       // Gravitational Constant 
PVector pos;   // position 
boolean dragging = false; // Is the object being dragged? 
boolean rollover = false; // Is the mouse over the ellipse? 
PVector drag;  // holds the offset for when object is clicked on
 
Attractor(PVector l_,float m_, float g_) {   
pos = l_.get();   
mass = m_;
    G= g_;   
drag = new PVector(0.0,0.0);
  }

 
void go() {   
render();   
drag();
  } 
 
PVector attract(Bob c) {
   
PVector dir = PVector.sub(pos,c.position);        // Calculate direction of force   
float d = dir.mag();       // Distance between objects
   d= constrain(d,5.0,25.0);                       
// Limiting the distance to eliminate "extreme" results for very close or very far objects   
dir.normalize();       // Normalizevector (distance doesn't matter here, we just want this vector for direction)
   
float force = (G * mass * c.mass) / (d * d); // Calculate gravitional force magnitude
    
dir.mult(5*force);        // Get forcevector --> magnitude * direction    
return dir;
  }

  //Method to display
 
void render() {   
ellipseMode(CENTER);   
stroke(0,100);
   
if (dragging) fill (50);   
else if (rollover) fill(100);   
else fill(175,50);   
ellipse(pos.x,pos.y,mass*3,mass*2);
  }

  //The methods below are for mouse interaction 
void clicked(int mx, int my) {
   
float d = dist(mx,my,pos.x,pos.y);   
if (d < mass) {     
dragging = true;     
drag.x = pos.x-mx;     
drag.y = pos.y-my;
    }
  }
     
void rollover(int mx, int my) {   

float d = dist(mx,my,pos.x,pos.y);   
if (d < mass) {     
rollover = true;
    }
else {     
rollover = false;
    }
  }

 
void stopDragging() {   
dragging = false;
  }  
  
void drag() {   
if (dragging) {     
pos.x = mouseX + drag.x;     
pos.y = mouseY + drag.y;
    }
  }
}

5.Ch_04 _System

模拟烟火特效
模拟关键
1.粒子束生成 (多个Repeller(使用ArrayList))。
2.每个粒子之间的
斥力
(类似第二章)
3.粒子的消亡周期(模拟烟火短暂,且会变色的特性)

在这里插入图片描述

在这里插入图片描述
完整代码如下


ParticleSystem ps;
void setup() { 
size(640,640);
  ps= new ParticleSystem(new PVector(width/2,50));

}
 
void draw() { 
background(255); 
ps.addParticle(mouseX,mouseY); 
ps.update(); 
ps.intersection(); 
ps.display();
}
 
class Particle { 
PVector position; 
PVector velocity; 
PVector acceleration; 
float lifespan; 
float r = 6 ;
boolean highlight;
 
Particle(float x, float y) {   

acceleration = new PVector(0, 0.05);   
velocity = new PVector(random(-1, 1), random(-2, 0));   
position = new PVector(x, y);   
lifespan = 255.0;

  }
  
void run() {   
update();   
display();
  } 
 
void intersects(ArrayList<Particle> particles) {   
highlight = false;
   
for (Particle other : particles) {     
if (other != this) {       
float d = PVector.dist(other.position, position);       
if (d < r + other.r)          
highlight = true;       
}     
}
    }
  }
 
void applyForce(PVector f) {   
acceleration.add(f); 
  }
 
  //Method to update position
 
void update() {
   
velocity.add(acceleration)   
position.add(velocity)   
acceleration.mult(0);   
lifespan -= 1.5;
  }
  //Method to display 
  
void display() {   
stroke(0, lifespan)   
strokeWeight(2);   
fill(127, lifespan);
   
if (highlight) {     
fill(163,18,205);
    }   
ellipse(position.x, position.y, r*2, r*2);
  }
  
  // Is the particle still useful? 
boolean isDead() {   
if (lifespan < 0.0)      
return true;
    }    
else {     
return false;
    }
  }
}

 
class ParticleSystem { 

ArrayList<Particle> particles; 
ParticleSystem(PVector position) {
   particles = new ArrayList<Particle>();
  }

void addParticle(float x, float y) {   
particles.add(new Particle(x, y));
  }
 
void display() {
   
for (Particle p : particles) {     
p.display();
    }
  }
  
void intersection() {
   
for (Particle p : particles)      
p.intersects(particles);
    }
  }
  
void update() {
   
for (int i = particles.size()-1; i >= 0; i--) {     
Particle p = particles.get(i);     
p.update();     
if (p.isDead()) {       
particles.remove(i);
     
}
    }
      }
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值