前言
在《代码本色》的第3章 振荡 中,主要讲到了三角函数的运动形式体现振荡以及力的作用模拟自然系统,以下为第3章的内容目录:
针对三角函数的运动形式体现振荡以及加速旋转和力的作用模拟自然系统,我进行了自己的习作。
关于习作
学习了《代码本色》第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坐标和角度的变化去实现颜色的变化。
加速旋转的图形,原本坐标是原点位置,经过平移屏幕,使图形移动到屏幕中心位置,再旋转屏幕,达到旋转图形的效果。然后将屏幕旋转的效果恢复正常,再将屏幕平移回原本位置。这里需要注意的是,需要先恢复屏幕旋转效果再恢复平移效果,如果先平移再旋转,最后的屏幕效果不是原先状态,而是屏幕仍然在旋转。
弹力系统中用到了重力,将一根绳子将小球和固定点用线连接,鼠标点击改变小球位置,松开鼠标,小球开始受重力和绳子的弹力,达到振荡的效果。
来源:CSDN
作者:产品经理顾清宇
链接:https://blog.csdn.net/A_Ainley/article/details/103469075