您的位置:首页 > 编程语言

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

2020-01-12 15:35 471 查看

互动媒体技术课程作业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);

}
}
}
}
  • 点赞
  • 收藏
  • 分享
  • 文章举报
别给我放香菜 发布了4 篇原创文章 · 获赞 2 · 访问量 198 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: