互动编程习作1——表现随机行为及牛顿运动学

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

  • 一、序章——随机游走
  • 二、第一章——向量
  • 三、第二章——力
  • 四、第三章——振荡
  • 五、第四章——粒子系统

一、序章——随机游走

规律:根据鼠标位置的x、y坐标决定随机游走的方向
技术:

  1. 概率和非均匀分布
    绘制了一个小球使他有60%的概率向着鼠标所在的方向移动。
    改变使用random()函数的方式,使它产生“非均匀”分布的随机数。
  2. Perlin噪声
    Processing的noise()函数告诉我们噪声是通过几个“八度”计算出来的。调用noiseDetail()函数会改变“八度”的数量以及各个八度的重要性,这反过来会影响noise()函数的行为。

代码:
程序入口:

Walker w;

void setup() {
  size(640,360);
  // Create a walker object
  w = new Walker();
  background(200);
}

void draw() {
  // Run the walker object
  w.step();
  w.render();
}

Walker.pde

class Walker {
  int x, y;

  Walker() {
    x = width/2;
    y = height/2;
  }

  void render() {
    stroke(100,100,100);
    ellipse(x,y,40,40);
  }

  // Randomly move up, down, left, right, or stay in one place
  void step() {

    float r = random(1);
    // A 50% of moving towards the mouse
    if (r < 0.6) {    
      int xdir = (mouseX-x);
      int ydir = (mouseY-y);
      if (xdir != 0) {
        xdir /= abs(xdir);
      } 
      if (ydir != 0) {
        ydir /= abs(ydir);
      }
      x += xdir;
      y += ydir;
    } else {
      int xdir = int(random(-2, 2));
      int ydir = int(random(-2, 2));
      println(xdir);
      x += xdir;
      y += ydir;
    }

    x = constrain(x, 0, width-1);
    y = constrain(y, 0, height-1);
  }
}

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

二、第一章——向量

规律:一组同时超向鼠标,速度加速度均不同的物体组成的朝向鼠标运动的圆管形状
技术:

  1. 向量的运动:速度
  1. 当前位置加上速度得到一个新的位置;
  2. 在新的位置上绘制对象。
  1. 加速度的交互
    我们想要根据某个规则或公式计算一个向量,都必须同时算出两部分数据:大小和方向。先从方向开始,加速度的方向是物体朝向鼠标的方向,假设物体的位置是(x,y),鼠标的位置是(mouseX,mouseY)。
    在这里插入图片描述
    在这里插入图片描述

步骤:

  1. 计算由物体指向目标位置(鼠标)的向量;
  2. 单位化该向量(将向量的大小缩短为1);
  3. 改变以上单位向量的长度(乘以某个合适的值);
  4. 将步骤3中得到的向量赋给加速度。

代码:
程序入口:

Mover[] movers = new Mover[20];

void setup() {
    background(255);
  size(1000,1000);
  for (int i = 0; i < movers.length; i++) {
    movers[i] = new Mover(); 
  }
}

void draw() {
  

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

Mover.pde:

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 = random(10);
  }

  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(127,200);
    ellipse(position.x,position.y,48,48);
  }

}

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

三、第二章——力

规律:受朝向中心圆形引力作用的三色小球的运动轨迹
技术:

  1. 主角对于其他Mover在距离不同时具有不同的作用,距离远的时候表现为吸引,距离近时表现为排斥。(分子之间距离变小,表现为斥力,距离变大,变大,表现为引力)

距离不同时,力的作用效果不一样,距离大时表现为引力,距离小时表现为斥力,即距离到达临界小值时,力的方向改变,代码表现为:
float strength = (G * mass * m.mass) / (d * d); // Calculate gravitional force magnitude
if(d < 20){
strength *= -1;
}
force.mult(strength);

  1. 主角对于不同颜色的其他Mover的作用效果不同。
    代码:
    程序入口:
//Mover m;
Attractor a;

Mover[] movers = new Mover[30];

void setup() {
  size(1000,1000);
  for (int i = 0; i < movers.length/3; i++) {
    movers[i] = new Mover(1, random(width), random(height), 'R');
  }
  for (int i = 10; i < movers.length/3+10; i++) {
    movers[i] = new Mover(3, random(width), random(height), 'G');
  }
  for (int i = 20; i < movers.length/3+20; i++) {
    movers[i] = new Mover(5, random(width), random(height), 'B');
  }
  a = new Attractor();
  background(255);
}

void draw() {
  
  
  PVector wind = new PVector(0.01,0);

  for (int i = 0; i < movers.length; i++) {
    PVector force = a.attract(movers[i]);
    movers[i].applyForce(wind);
    movers[i].applyForce(force);
    movers[i].update();
    movers[i].display();
  }
  
  a.drag();
  a.hover(mouseX,mouseY);
 
  a.display();
}

Attracter.pde:

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
    if(d < 20){
      strength *= -1;
    }
    force.mult(strength);     // Get force vector --> magnitude * direction
    return force;
  }

  // Method to display
  void display() {
    ellipseMode(CENTER);
    strokeWeight(4);
    stroke(0);
    if (dragging) fill (255);
    else if (rollover) fill(255);
    else fill(255);
    ellipse(width/2,height/2,mass*2,mass*2);

  }



  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.pde:

class Mover {
  
  char col;

  PVector position;
  PVector velocity;
  PVector acceleration;
  float mass;

  Mover(float m, float x, float y, char c) {
    mass = m;
    position = new PVector(x, y);
    velocity = new PVector(1, 0);
    acceleration = new PVector(0, 0);
    col = c;
  }
  
  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);
    strokeWeight(2);
    if(col == 'R'){
      fill(200,0,0);
    }
    if(col == 'G'){
      fill(0,200,0);
    }
    if(col == 'B'){
      fill(0,0,200);
    }
    ellipse(position.x,position.y,16,16);
  }

  void checkEdges() {

    if (position.x > width) {
      position.x = 0;
    } else if (position.x < 0) {
      position.x = width;
    }

    if (position.y > height) {
      position.y = 0;
    } else if(position.y < 0){
      position.y = height;
    }

  }

}

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

第三章——振荡

规律:以三角函数的运动形式体现振荡以及加速旋转和力的作用模拟自然系统。
技术:
动态的波形曲线体现三角函数的运动,颜色会随着位置和时间变化,波也在不停地变化。

代码:
程序入口:

float startAngle = 0;
float angleVel = 0.2;
float angle = 0;
float anglec = 0;

// Mover object
Bob bob;

// Spring object
Spring spring;

void setup() {
  size(500,500);
  smooth();
  spring = new Spring(width/2,10,100); 
  bob = new Bob(width/2,height); 
}
int C = 1;
void draw() {
  background(175);
  
  fill(127);
  stroke(0);
  rectMode(CENTER);
  translate(width/2, height/2);
  rotate(angle);
  line(-50, 0, 50, 0);
  stroke(0);
  strokeWeight(2);
  fill(127);
  ellipse(50, 0, 16, 16);
  ellipse(-50, 0, 16, 16);
  anglec += 0.001;
  angle += anglec;

  rotate(-angle+anglec);
  translate(-width/2, -height/2);
  startAngle += 0.05;
  float angle = startAngle;
  float angleColor = 15 * angle;
  if (angleColor > 255*C){
    angleColor = angleColor - 255*C;
    C += 1;
  }

 for (int x = 0; x <= width; x += 10) {
    float y = map(sin(angle),-1,1,0,height);
    stroke(175);
    fill(angleColor,y,x);
    strokeWeight(2);
    ellipse(x,y,48,48);
    angle += angleVel;
  }  
    // Apply a gravity force to the bob
  PVector gravity = new PVector(0,2);
  bob.applyForce(gravity);
  
  // Connect the bob to the spring (this calculates the force)
  spring.connect(bob);
  // Constrain spring distance between min and max
  spring.constrainLength(bob,30,200);
  
  // Update bob
  bob.update();
  // If it's being dragged
  bob.drag(mouseX,mouseY);
  
  // Draw everything
  //spring.displayLine(bob); // Draw a line between spring and bob
  //bob.display(); 
  //spring.display(); 
}

// For mouse interaction with bob

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

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

Mover.pde:

class Bob { 
  PVector position;
  PVector velocity;
  PVector acceleration;
  float mass = 24;
  
  // Arbitrary damping to simulate friction / drag 
  float damping = 0.98;

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

  // Constructor
  Bob(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 bob
  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;
    }
  }
}

Spring.pde:

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(Bob b) {
    // Vector pointing from anchor to bob 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 bob and anchor between min and max
  void constrainLength(Bob 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(Bob b) {
    strokeWeight(2);
    stroke(0);
    line(b.position.x, b.position.y, anchor.x, anchor.y);
  }
}

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

第四章——粒子系统

规律:一个粒子发射器,在黑色系统中发生彩色圆点。
代码:
程序入口:

ParticleSystem ps;
 
void setup() {
  size(640, 360);
  ps = new ParticleSystem(new PVector(width/2, 50));
}
void draw() {
 
  background(0);
  ps.addParticle();
  ps.run();
}


Particle.pde:

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);
  }
}

ParticleSystem.pde:

// A class to describe a group of Particles
// An ArrayList is used to manage the list of Particles 
 
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);
      }
    }
  }
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值