互动媒体技术-代码本色-第3章

振荡

1.概述

本章涉及到角、角速度以及角加速度,正弦函数和余弦函数,它们可以用来制作平滑的波形曲线。有了这些知识,我们就能计算更复杂的力,而这些力往往都涉及角度,比如钟摆的摆动和盒子从斜坡滑下时所受的力。
为了模拟现实世界的各种运动,我们必须要掌握振荡、振幅和频率/周期这些概念。
振荡的公式:float x = 振幅 \* cos(2π * 帧数 / 周期)

2.应用与拓展

(1)弹簧Spring的实现
弹簧的弹力与弹簧的伸长量成正比,弹力是一个向量,除了大小,还有方向。
控制弹簧的最大长度和最小长度。
胡克定律指出了弹力的大小:F=-kx
k:弹性系数,影响弹力的大小。
x:弹簧发生的形变
已知弹性系数,则计算弹力的关键在于求弹簧的形变。

在这里插入图片描述

class Spring { 
  // 位置
  PVector anchor;
  // 静止长度和弹性系数
  float len;
  float k = 0.2;
  Spring(float x, float y, int l) {
    anchor = new PVector(x, y);
    len = l;
  } 
  // 计算弹簧弹力
  void connect(Bob b) {
    // 从弹簧指向bob位置的向量、距离
    PVector force = PVector.sub(b.position, anchor);
    float d = force.mag();
    // 形变
    float stretch = d - len;
    // 根据虎克定律计算力F = k * stretch
    force.normalize();
    force.mult(-1 * k * stretch);
    b.applyForce(force);
  }
  // 距离限制
  void constrainLength(Bob b, float minlen, float maxlen) {
    PVector dir = PVector.sub(b.position, anchor);
    float d = dir.mag();
    // 距离短
    if (d < minlen) {
      dir.normalize();
      dir.mult(minlen);
      //重置位置并停止移动
      b.position = PVector.add(anchor, dir);
      b.velocity.mult(0);
      
    } 
    // 距离长
    else if (d > maxlen) {
      dir.normalize();
      dir.mult(maxlen);
      // 重置位置并停止移动
      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);
  }
  //显示BoB锚点之间的弹簧
  void displayLine(Bob b) {
    strokeWeight(2);
    stroke(0);
    line(b.position.x, b.position.y, anchor.x, anchor.y);
  }
}

(2)Bob与鼠标交互
获取鼠标点击位置与Bob的位置差值,拖动鼠标根据此位置偏移量可以得出Bob被拖去的位置。实现用鼠标拉动钟摆,从而触发它的运动,触发弹力变化。

//弹簧连接的小球
class Bob { 
  PVector position;
  PVector velocity;
  PVector acceleration;
  float mass = 24;
  // 模拟摩擦/阻力的任意阻尼
  float damping = 0.98;
  // 鼠标交互参数
  PVector dragOffset;
  boolean dragging = false;
  Bob(float x, float y) {
    position = new PVector(x,y);
    velocity = new PVector();
    acceleration = new PVector();
    dragOffset = new PVector();
  } 
  // 标准欧拉积分
  void update() { 
    velocity.add(acceleration);
    velocity.mult(damping);
    position.add(velocity);
    acceleration.mult(0);
  }
  //牛顿第二定律计算加速度
  void applyForce(PVector force) {
    PVector f = force.get();
    f.div(mass);
    acceleration.add(f);
  }
  // 显示
  void display() { 
    stroke(0);
    strokeWeight(2);
    fill(75,80,255);
    if (dragging) {
      fill(0);
    }
    ellipse(position.x,position.y,mass*2,mass*2);
  } 
  //鼠标交互
  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;
    }
  }
}

(3)摆锤转动
添加摆锤,摆锤每次转动的角度由Bob的速度控制,可以通过摆锤更价值观的看出Bob的速度变化。
rotate()函数实现摆锤的旋转。

//旋转轴,Bob速度影响轴的转动速度
class AngularMotion{
float angle = 0;
float aVelocity = 0;
//调整选装角度
void calangle(PVector velocity)
{
    angle += velocity.mag()/10;
}
//显示
void display()
{
  pushMatrix();
  fill(127);
  stroke(0);
  translate(width/5, height/4);
  rectMode(CENTER);
  rotate(angle);
  stroke(0);
  strokeWeight(2);
  fill(0,0,127);
  line(-60, 0, 60, 0);
  ellipse(60, 0, 16, 16);
  ellipse(-60, 0, 16, 16);
  popMatrix();
  display2();
}
void display2()
{
  pushMatrix();
  fill(127);
  stroke(0);
  translate((width/5)*4, height/4);
  rectMode(CENTER);
  rotate(-angle);
  stroke(0);
  strokeWeight(2);
  fill(127,0,0);
  line(-60, 0, 60, 0);
  ellipse(60, 0, 16, 16);
  ellipse(-60, 0, 16, 16);
  popMatrix();
}
}

(4)控制Bob受到的重力及弹力,连接弹簧与Bob,并控制鼠标交互。

Bob bob;
AngularMotion am;
Spring spring;
void setup() {
  size(640,360);
  spring = new Spring(width/2,20,100); 
  bob = new Bob(width/2,100); 
  am=new AngularMotion ();
}
void draw()  {
  background(255); 
  // Bob施加重力
  PVector gravity = new PVector(0,2);
  bob.applyForce(gravity);
  // 连接Bob和弹簧并计算弹力
  spring.connect(bob);
  // 限制距离
  spring.constrainLength(bob,30,200);
  bob.update();
  bob.drag(mouseX,mouseY);
  // 锚点bob之间的直线表示弹簧
  spring.displayLine(bob); 
  bob.display(); 
  spring.display();   
  fill(0);
  text("click on bob to drag",10,height-5);
  am.calangle(bob.velocity);
  am.display();
}
void mousePressed()  {
  bob.clicked(mouseX,mouseY);
}
void mouseReleased()  {
  bob.stopDragging(); 
}

3.效果

左右两个摆锤的旋转速度受Bob的速度影响,正比关系,通过两个摆锤的转动速度可以更加直观地观察Bob在受到弹力过程中的速度变化。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值