【互动编程习作】振荡——振荡的实现及其应用

浪尽此生 提交于 2019-12-10 14:24:26

前言

在《代码本色》的第3章 振荡 中,主要讲到了三角函数的运动形式体现振荡以及力的作用模拟自然系统,以下为第3章的内容目录:
在这里插入图片描述
针对三角函数的运动形式体现振荡以及加速旋转和力的作用模拟自然系统,我进行了自己的习作。

关于习作

学习了《代码本色》第3章的内容之后,关于习作,我想表现的元素就是:

  1. 三角函数波形运动
  2. 加速旋转效果
  3. 力的作用模拟自然系统

关于第一点,我使用了动态的波形曲线体现三角函数的运动,颜色会随着位置和时间变化,波也在不停地变化。

关于第二点,我用的是一个加速旋转的两圆头棒子,从屏幕左上角平移到屏幕中间,进行加速旋转,再将屏幕平移会原先位置,旋转效果中和,进行其他操作。

关于第三点,做的就是一个弹力系统,可以鼠标点击拉动小球,显现弹力效果。

下面是效果图和具体代码实现:
在这里插入图片描述
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);
  }
}

sketch_3.pde

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

关于代码

动态三角函数波形的实现主要就是不同的圆形在不同的x坐标位置生成,然后y坐标根据角度的变化,依据三角函数原理生成不同的y坐标,这是波形动态的实现,颜色的变化是根据x坐标、y坐标和角度的变化去实现颜色的变化。

加速旋转的图形,原本坐标是原点位置,经过平移屏幕,使图形移动到屏幕中心位置,再旋转屏幕,达到旋转图形的效果。然后将屏幕旋转的效果恢复正常,再将屏幕平移回原本位置。这里需要注意的是,需要先恢复屏幕旋转效果再恢复平移效果,如果先平移再旋转,最后的屏幕效果不是原先状态,而是屏幕仍然在旋转。

弹力系统中用到了重力,将一根绳子将小球和固定点用线连接,鼠标点击改变小球位置,松开鼠标,小球开始受重力和绳子的弹力,达到振荡的效果。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!