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

前言

在《代码本色》的第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坐标和角度的变化去实现颜色的变化。

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值