互动媒体技术,代码本色0-4

实验要求:

主题:创作一组编程习作,体现随机行为及牛顿运动学

要求:

编程语言与工具:编程工具不限;
作品:参考《代码本色》的第0~4章内容及其实例程序(自行在processing内下载),针对这5章分别编写1个习作(一共5个),每个习作都有不少于2个案例参考,且必须有一定的拓展;

报告:写一篇文章(也可以多篇文章,但最好有一个总的导航文章),发表为博文/推文等形式,描述运用的规律,若用到了数学/物理/化学等学科中的知识,要用平实易懂的语言介绍原理,尝试运用凝练的数学语言表达(公式、方程、推导等),特别要描述出这些原理如何在作品中呈现的。

第0章 引言
根据书中引用的例子和方法,添加噪声,通过改变不同的参数来实现不同的效果:

例如:

float z=0;
void setup() 
{
  size(640, 360);
}
void draw() 
{
  background(0);
  z++;  loadPixels();
  for (int x = 0; x < width; x++)
  {
      for (int y = 0; y < height; y++)
      {
           float bright = noise(x*0.05, y*0.06)*255;
           pixels[x+y*width] = color(bright);
      }
  }
  updatePixels();
}

在这里插入图片描述
将参数xy改为0.15和0.16可以发现图片的噪声横纵坐标都变得更加紧密:

在这里插入图片描述

为其添加第三维坐标:
原代码中修改为:
float bright = noise(x0.15, y0.16,z*0.05)*255;
就可以实现以下效果:有点类似于飞鸟的翅膀律动。。。
在这里插入图片描述

第1章 向量
该章节的主要内容是向量,最基础的效果是,运用好向量可以是代码大大简化,(虽然刚开始只运用向量可能不太明显)

向量的运动:包括速度,加速度,角度等;
主要对象:拥有速度和变化加速度的mover;
(通过类名直接调用静态函数)

这里还主要讲解了鼠标与实现的该模型的交互,通过测量鼠标所在位置来使用函数决定几个物体的加速度,

当前位置加速度向量就是新的位置
当前速度加加速度向量就是新的速度;

//在前面恒定加速的基础上实现,变化的加速度(使用函数控制)
class Mover {

  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(0.2);
    acceleration.normalize();
    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(int(random(200)),int(random(240)),int(random(255)));
    ellipse(position.x,position.y,int(random(50)),50);
  }

}


Mover[] movers = new Mover[10];

void setup() {
  size(640,360);
  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(); 
  }
}

这里是实现的实例:其效果为:

在这里插入图片描述

第2章 力

在本章中依然使用mover来封装物体的受力状况
mover类和之前一样,这里省略。

该实例显示物体之间的引力,使用该公式可以计算两个物体之间的引力,为了使之更加形象具体,我们将这个力放大来看。
在这里插入图片描述
效果::
创建Attractor类:


class Attractor {
  float mass;    // Mass, tied to size
  float G;       // Gravitational Constant
  PVector position;   // position
  boolean dragging = false; // Is the object being dragged?
  boolean rollover = false; // Is the mouse over the ellipse?
  PVector dragOffset;  // holds the offset for when object is clicked on

  Attractor() {
    position = new PVector(width/2,height/2);
    mass = 20;
    G = 1;
    dragOffset = 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,5.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(strength);                                  // Get force vector --> magnitude * direction
    return force;
  }

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

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

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

  void stopDragging() {
    dragging = false;
  }



  void drag() {
    if (dragging) {
      position.x = mouseX + dragOffset.x;
      position.y = mouseY + dragOffset.y;
    }
  }

}

主函数:


Mover[] movers = new Mover[10];

Attractor a;

void setup() {
  size(640, 360);
  for (int i = 0; i < movers.length; i++) {
    movers[i] = new Mover(random(0.1, 2), random(width), random(height));
  }
  a = new Attractor();
}

void draw() {
  background(255);

  a.display();
  a.drag();
  a.hover(mouseX, mouseY);

  for (int i = 0; i < movers.length; i++) {
    PVector force = a.attract(movers[i]);
    movers[i].applyForce(force);

    movers[i].update();
    movers[i].display();
  }
}

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

void mouseReleased() {
  a.stopDragging();
}


这样子就是多个物体之间万有引力的模拟
效果如下:
在这里插入图片描述
接下来进行拓展:
通过改变上述函数的mass可以改变其质量,但是两个物体之间的有引力产生的加速度是与其本身质量无关的,而之间的力却与本身质量有关。所以讲mass改为随机产生的random函数其效果是一样的。

我们可以讲G改为9.8来接近模拟一下重力的场景:
Mover[] movers = new Mover[5];

void setup() {
size(640, 360);
for (int i = 0; i < movers.length; i++) {
movers[i] = new Mover(random(2, 6), 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);

movers[i].applyForce(wind);
movers[i].applyForce(gravity);

movers[i].update();
movers[i].display();
movers[i].checkEdges();

}
}

在这里插入图片描述
第3章 振荡

用曲线来画振荡波形:

float angle = 0;
float angleVel = 0.1;

size(640,360);
background(255);
stroke(0);
strokeWeight(2);
noFill();

beginShape();
for (int x = 0; x <= width; x += 5) {
  float y = map(sin(angle),-1,1,0,height);
  vertex(x,y);
  angle +=angleVel;
} 
endShape();

在这里插入图片描述
由公式:
在这里插入图片描述
延伸为:
在这里插入图片描述
但是更加简单的是:角度是一个标量,它没有方向。

简谐运动:
简谐运动是最基本也最简单的机械振动。当某物体进行简谐运动时,物体所受的力跟位移成正比,并且总是指向平衡位置。它是一种由自身系统性质决定的周期性运动。(如单摆运动和弹簧振子运动)实际上简谐振动就是正弦振动。故此在无线电学中简谐信号实际上就是正弦信号。
如果质点的位移与时间的关系遵从正弦函数的规律,即它的振动图像(x-t图像)是一条正弦曲线,这样的振动叫做简谐运动。

三角函数就是一个振荡方程:
在这里插入图片描述
弹簧在理想情况下也可以看作是再平衡点的简谐运动,

mover类:


class Mover { 
  PVector position;
  PVector velocity;
  PVector acceleration;
  float mass = 20;
  
  // Arbitrary damping to simulate friction / drag 
  float damping = 1;

  // For mouse interaction
  PVector dragOffset;
  boolean dragging = false;

  // Constructor
  Mover(float x, float y) {
    position = new PVector(x,y);
    velocity = new PVector();
    acceleration = new PVector();
    dragOffset = new PVector();
  } 

  // 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 mover
  void display() { 
    stroke(0);
    strokeWeight(2);
    fill(175);
    if (dragging) {
      fill(50);
    }
    ellipse(position.x,position.y,mass*2,mass*2);
  } 

  // The methods below are for mouse interaction

  // This checks to see if we clicked on the mover
  void clicked(int mx, int my) {
    float d = dist(mx,my,position.x,position.y);
    if (d < mass) {
      dragging = true;
      dragOffset.x = position.x-mx;
      dragOffset.y = position.y-my;
    }
  }

  void stopDragging() {
    dragging = false;
  }

  void drag(int mx, int my) {
    if (dragging) {
      position.x = mx + dragOffset.x;
      position.y = my + dragOffset.y;
    }
  }
}

其他控制函数:

void setup() {
  size(640,360);
  // Create objects at starting position
  // Note third argument in Spring constructor is "rest length"
  spring = new Spring(width/2,10,100); 
  mover = new Mover(width/2,100); 

}

void draw()  {
  background(255); 
  // Apply a gravity force to the mover
  PVector gravity = new PVector(0,2);
  mover.applyForce(gravity);
  
  // Connect the mover to the spring (this calculates the force)
  spring.connect(mover);
  // Constrain spring distance between min and max
  spring.constrainLength(mover,30,200);
  
  // Update mover
  mover.update();
  // If it's being dragged
  mover.drag(mouseX,mouseY);
  
  // Draw everything
  spring.displayLine(mover); // Draw a line between spring and mover
  mover.display(); 
  spring.display(); 
  
  fill(0);

}

主函数:

class Spring { 

  // position
  PVector anchor;

  // Rest length and spring constant
  float len;
  float k = 0.2;

  // Constructor
  Spring(float x, float y, int l) {
    anchor = new PVector(x, y);
    len = l;
  } 

  // Calculate spring force
  void connect(Mover b) {
    // Vector pointing from anchor to mover position
    PVector force = PVector.sub(b.position, anchor);
    // 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);
    b.applyForce(force);
  }

  // Constrain the distance between mover and anchor between min and max
  void constrainLength(Mover b, float minlen, float maxlen) {
    PVector dir = PVector.sub(b.position, anchor);
    float d = dir.mag();
    // Is it too short?
    if (d < minlen) {
      dir.normalize();
      dir.mult(minlen);
      // Reset position and stop from moving (not realistic physics)
      b.position = PVector.add(anchor, dir);
      b.velocity.mult(0);
      // Is it too long?
    } 
    else if (d > maxlen) {
      dir.normalize();
      dir.mult(maxlen);
      // Reset position and stop from moving (not realistic physics)
      b.position = PVector.add(anchor, dir);
      b.velocity.mult(0);
    }
  }

  void display() { 
    stroke(0);
    fill(175);
    strokeWeight(2);
    rectMode(CENTER);
    rect(anchor.x, anchor.y, 10, 10);
  }

  void displayLine(Mover b) {
    strokeWeight(2);
    stroke(0);
    line(b.position.x, b.position.y, anchor.x, anchor.y);
  }
}

效果如下:
在这里插入图片描述

第4章 粒子系统

粒子系统表示三维计算机图形学中模拟一些特定的模糊现象的技术,而这些现象用其它传统的渲染技术难以实现真实感的物理运动规律。经常使用粒子系统模拟的现象有火、爆炸、烟、水流、火花、落叶、云、雾、雪、尘、流星尾迹或者象发光轨迹这样的抽象视觉效果等等。

而在processing中粒子就是在屏幕中移动的对象,它有位置、速度和加速度变量,有构造函数用于内部变量的初始化,有display()函数用于绘制自身,还有update()函数用于更新位置。

受重力和阻力共同影响的粒子系统:
在这里插入图片描述

拓展:

模拟粒子系统

 float R = random(255);          
  float G = random(255);
  float B = random(255);

  Particle(){
    location = new PVector(random(width), random(height));
    velocity = new PVector(random(-1, 1), random(-2, 0));
    acceleration = new PVector(0, 0);
    mass = 1;
    lifespan = 255;
  }
  Particle(PVector l){
    location = l.get();
    acceleration = new PVector(0, 0);
    velocity = new PVector(random(-1, 1),random(-2, 0));
    mass = 1;
    lifespan = 255;
  }
  void applyForce(PVector force){
    acceleration.add(PVector.div(force, mass));
  }
  void update(){
    velocity.add(acceleration);
    location.add(velocity);
    acceleration.mult(0);
    lifespan -= 1.0;
  }
  void display(){
    stroke(R,G,B,lifespan);
    fill(R,G,B,lifespan);
    ellipse(location.x, location.y, 8, 8);
  }
  boolean isDead(){
    if(lifespan < 0.0){
      return true;
    }else{
      return false;
    }
  }
  void run(){
    update();
    display();
  }
}

class Confetti extends Particle{
  float R = random(255);
  float G = random(255);
  float B = random(255);
  Confetti(PVector l){
    super(l);
  }
  void display(){
    stroke(R, G, B, lifespan);
    fill(R,G,B,lifespan);
    //ellipse(location.x, location.y, 8, 8);
    
    rect(location.x, location.y, 8, 8);
  }
}

class Repeller{
  PVector location;
  float r = 10;
  float G = 100;
  Repeller(float x, float y){
    location = new PVector(x, y);
  }
  void display(){
    stroke(0);
    fill(0,0);
    ellipse(location.x, location.y, r*2, r*2);
  }
  PVector repel(Particle p){
    PVector dir = PVector.sub(location, p.location);
    float d = dir.mag();
    d = constrain(d, 5, 100);
    dir.normalize();
    float force = -1*G/(d*d);
    
    dir.mult(force);
    return dir;
  }
}

主函数:(运行)

 import java.util.*;
ArrayList<ParticleSystem> systems;
PVector gravity;
Repeller repeller;
void mousePressed(){
  systems.add(new ParticleSystem(new PVector(mouseX, mouseY)));
  //gravity = new PVector(0, 0.1);
}
void setup(){
  size(640, 240);
  systems = new ArrayList<ParticleSystem>();
  repeller = new Repeller(width/2-20, height/2);
}
void draw(){
 background(255);
 Iterator<ParticleSystem> it = systems.iterator();
 while(it.hasNext()){
   ParticleSystem p = it.next();
   gravity = new PVector(random(-0.1, 0.1), random(-0.1, 0.2));
   p.applyRepeller(repeller);
   p.applyForce(gravity);
   p.run();
   p.addParticle();
   if(p.isDead()){
     it.remove();
   }
 }
 repeller.display();
}

结果:

在这里插入图片描述
(这里的GIF截图软件有点垃圾,只要碰撞中心圆就会不知怎么回事绿屏,老师见谅一下。)

这里前五章都有一个创建模拟自然系统的练习,在有了粒子系统的基础后,就可以实现一部分了。
(在例子中学习了一下)
根据教程https://blog.csdn.net/qq_38694695/article/details/89677186
成功实现了该系统,运用了较多的后面几章的知识

效果图:在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值