文章目录
1 重力和风力
在做A2作业的时候,我画了一副江南图书馆雪景图,其中下雪的粒子,我是每次draw的时候速度+0.8,没有模拟出自由落体的效果,因此结合《代码本色》第二章力,因此在A5这个实验,我想要把地球引力,空气和流体阻力加入进来。
//江南冬
//var box;
var circleX = 0;
var car = 0;
var snowParticles = []; //雪的粒子集合
var WarterSets = []; //水纹的集合
function setup()
{
createCanvas(600, 600);
noStroke();
circleX = 0;
WarterSets = GenerateWater();
}
function draw()
{
background(30, 73, 100, 170);
//SUN
DrawShiner(450, 100,"MOON"); //调用A1_0115_circle中的光晕圆
//BUILDINGS
fill(0, 80);
//rect(0, 290, 100, 200);
//图书馆的主楼
rect(240, 180, 110, 350);//120,200,100,300
windowsOfBuilding1(240, 180);
rect(350, 380, 110, 150);
windowsOfBuildingRight(350, 380);
rect(130, 380, 110, 150);
windowsOfBuildingleft(130, 380);
fill(255);
rect(240, 178, 110, 2);
rect(350, 378, 110, 2);
rect(130, 378, 110, 2);
//rect(410, 350, 200, 300);
//rect(520, 300, 100, 50);
//FILL GROUND
//fill(255);
fill(200, 250, 250);
rect(0, 500, 600, 200);
//GROUND
fill(0);
ellipse(0, 500, 200, 100);
ellipse(0, 500, 300, 50);
ellipse(300, 500, 70, 20);
ellipse(500, 500, 100, 40);
ellipse(450, 500, 100, 20);
ellipse(300, 500, 70, 20);
ellipse(580, 490, 170, 100);
//BRIDGE
fill(255, 150);
rect(0, 428, 600, 2);
fill(0);
//quad(width/2+500, height/2+150, width/2+576, height/2+170, width/2-586, height/2+170, width/2-560, height/2+150);
rect(0, 430, 600, 5);
rect(20, 430, 5, 20);
rect(40, 430, 5, 20);
rect(60, 430, 5, 20);
rect(80, 430, 5, 20);
rect(100, 430, 5, 20);
rect(120, 430, 5, 20);
rect(140, 430, 5, 20);
rect(160, 430, 5, 20);
rect(180, 430, 5, 20);
rect(200, 430, 5, 20);
rect(220, 430, 5, 20);
rect(240, 430, 5, 20);
rect(260, 430, 5, 20);
rect(280, 430, 5, 20);
rect(300, 430, 5, 20);
rect(320, 430, 5, 20);
rect(340, 430, 5, 20);
rect(360, 430, 5, 20);
rect(380, 430, 5, 20);
rect(400, 430, 5, 20);
rect(420, 430, 5, 20);
rect(440, 430, 5, 20);
rect(460, 430, 5, 20);
rect(480, 430, 5, 20);
rect(500, 430, 5, 20);
rect(520, 430, 5, 20);
rect(540, 430, 5, 20);
rect(560, 430, 5, 20);
rect(580, 430, 5, 20);
//BRIDGE SHADOW
fill(0, 50);
rect(0, 505, 600, 10);
//REFLECTION
fill(100, 150);
rect(0, 500, 600, 200);
//SNOW
fill(255, 150);
if(random()>0.8)
{
snowParticles.push(new SnowAddForce(random(-300,600),-1,1,random(5,12)));
}
for(let i = 0;i<snowParticles.length;i++)
{
snowParticles[i].DrawSnow();
}
//水波纹
for(let i = 0;i<WarterSets.length;i++)
{
WarterSets[i].calWave();
WarterSets[i].drawWave();
}
fill(255);
ellipse(100, 630, 400, 100);
ellipse(0, 600, 350, 100);
fill(255, 150);
ellipse(370, 500, 100, 1);
ellipse(570, 510, 100, 1);
ellipse(140, 500, 100, 1);
ellipse(360, 550, 100, 3);
ellipse(400, 560, 50, 1);
ellipse(150, 530, 50, 1);
}
function windowsOfBuilding1(x,y)
{
push();
translate(x,y);
//WINDOWS BUILDING 2
//120,200,100,300
rect(10, 20, 10, 10);
rect(50, 20, 10, 10);
rect(70, 20, 10, 10);
rect(90, 20, 10, 10);
rect(70, 40, 10, 10);
rect(70, 60, 10, 10);
rect(50, 60, 10, 10);
rect(10, 60, 10, 10);
rect(50, 80, 10, 10);
rect(30, 80, 10, 10);
rect(70, 100, 10, 10);
rect(90, 120, 10, 10);
rect(30, 140, 10, 10);
rect(10, 140, 10, 10);
rect(10, 160, 10, 10);
rect(50, 160, 10, 10);
rect(90, 180, 10, 10);
rect(90, 200, 10, 10);
rect(70, 220, 10, 10);
rect(30, 220, 10, 10);
rect(70, 200, 10, 10);
rect(50, 240, 10, 10);
rect(10, 270, 10, 10);
rect(30, 270, 10, 10);
rect(70, 270, 10, 10);
pop();
}
function windowsOfBuildingleft(x,y)
{
push();
translate(x,y);
//WINDOWS BUILDING 2
//120,200,100,300
rect(10, 20, 10, 10);
rect(50, 20, 10, 10);
rect(70, 20, 10, 10);
rect(90, 20, 10, 10);
rect(70, 40, 10, 10);
rect(70, 60, 10, 10);
rect(50, 60, 10, 10);
rect(10, 60, 10, 10);
rect(50, 80, 10, 10);
rect(30, 80, 10, 10);
rect(10, 100, 10, 10);
rect(50, 100, 10, 10);
pop();
}
function windowsOfBuildingRight(x,y)
{
push();
translate(x,y);
//WINDOWS BUILDING 2
//120,200,100,300
rect(10, 20, 10, 10);
rect(50, 20, 10, 10);
rect(70, 20, 10, 10);
rect(90, 40, 10, 10);
rect(70, 40, 10, 10);
rect(70, 60, 10, 10);
rect(50, 60, 10, 10);
rect(10, 60, 10, 10);
rect(90, 60, 10, 10);
rect(50, 80, 10, 10);
rect(30, 80, 10, 10);
rect(10, 100, 10, 10);
rect(50, 100, 10, 10);
pop();
}
2 引力
2.1 引力正方形
在A1中画正方形的时候,我画过一组碰撞正方形,碰壁后就弹回,当大小随机的时候可以产生比较好的效果。
2.1.1 引力正方形的效果
2.1.2 引力正方形的原理
这里的原理是学习了《代码本色》这本书的2.9章,其中他是设置了一个mover类,我将update中的draw换成了我A1作业写的正方形,调用代码如下。
let AttractRects = [];
var n = 30;
function setup()
{
createCanvas(700, 600);
background(0);
AttractRects = new Array(n);
for (var i = 0; i < n; i++)
{
//var p = createVector(random(0, width), random(0, height));
AttractRects[i] = new mouseAttractRect(random(0, width), random(0, height));
}
}
function draw() {
background(255);
for (var i = 0; i < n; i++) {
AttractRects[i].addForce(AttractRects[i].attractTo(mouseX, mouseY));
AttractRects[i].run();
}
}
2.2 蝴蝶
A1中的蝴蝶
引力很适用于自然界中的物体,翻看前面的效果,我发现我画的比较像自然界的生物的有蝴蝶,因此我想完善蝴蝶系统,把引力作用施加于蝴蝶系统,最后的效果如下。
调用方法如下:
var AttractRects;
var n = 30;
function setup()
{
createCanvas(900, 900);
background(0);
AttractRects = new Array(n);
for (var i = 0; i < n; i++)
{
//var p = createVector(random(0, width), random(0, height));
AttractRects = new mouseAttractButterfly(100,100);
}
}
function draw() {
background(255);
for (var i = 0; i < n; i++)
{
AttractRects.addForce(AttractRects.attractTo(mouseX, mouseY));
AttractRects.run();
}
}
3 斥力
3.1 斥力圆矩阵
在A1中的circle接口中,我做过一个矩阵圆,圆按照矩阵的样子排列,并且圆的大小与圆与鼠标的距离有关,效果如下。
这看起来有点像排斥效果,但是不是真实的排斥效果,我想用《代码本色》2.10章中斥力来修改一下圆矩阵,让其真正模拟
var count = 800;
var spacing = 40;
var repulsionRadius = 100;
var particles = [];
function setup() {
createCanvas(windowWidth, windowHeight);
//colorMode(HSB, 255);
for (let i = 0; i < count; i++)
{
let angle = i * 37.5;
let r = spacing * sqrt(i);
let x = r * cos(radians(angle)) + width / 2;
let y = r * sin(radians(angle)) + height / 2;
let distToCenter = dist(x, y, width / 2, height / 2);
let s = 255 - distToCenter * 1.25;
let b = 150 + distToCenter * 1;
particles.push(new RepulsiveParticle(
width, -300,
x, y,
0.5,
s, b));
}
}
function draw() {
background(255);
for (let i = 0; i < particles.length; i++) {
particles[i].move();
particles[i].display();
}
stroke(0, 50);
strokeWeight(repulsionRadius * 2);
point(mouseX, mouseY);
}
4 震荡
《代码本色》的Chapter 3为我们介绍了振荡的相关概念,引入了关于角运动、指向运动的概念,更让我们熟知了物体旋转、周期变化的原理。我也通过书上的案例加上以前完成的A1做了一些创作。
4.1 简谐运动
说起震荡,我第一个想到的就是简谐运动,因为这是在大物里面最常接触的,所以我想先从这个简谐运动开始做起,这个背后的原理是能量传递,一个物体运动带动另一个物体运动。刚开始尝试时每一个位置上的图案我使用的是Point函数,后来改成了自己A1中写的一个虚线圆,看起来效果更好了。
- 虚线圆介绍
链接:虚线圆
因为当时就是只留的接口在外面,其他全部封装了起来,因此调用还是很方便。
var xspacing = 16;
var w;
var theta = 0.0;
var amplitude = 75.0;
var period = 500.0;
var dx;
var yvalues;
function setup()
{
createCanvas(1000, 500);
w = width+16;
dx = (TWO_PI / period) * xspacing;
yvalues = new Array(floor(w/xspacing));
}
function draw() {
background(0);
calcWave();
renderWave();
}
function calcWave() {
theta += 0.02;
var x = theta;
for (var i = 0; i < yvalues.length; i++) {
yvalues[i] = sin(x)*amplitude;
x+=dx;
}
}
function renderWave() {
noStroke();
fill(255);
for (var x = 0; x < yvalues.length; x++) {
//调用虚线圆
dashedCircle(x*xspacing, height/2+yvalues[x],16,20,10) ;
}
}
4.2 钟摆太阳圆
这个钟摆效果在书中有提到过,因此我就跟着书中一起实现了,并且结合A1中的内容,我将钟摆的circle,变成了A1当中我模拟自然界的发光体做的一个圆(光晕圆)。
- 光晕圆介绍
并且为了模拟“残影”的现象,我加入了钟摆慢慢消失的效果。
var a;
var a_vel = 0;
var l;
var m;
var x;
var y;
var movable;
var lastPos = [];
var pointsToKeep = [];
var centerX;
var centerY;
var scaleOfPendulum;
var lastSecond;
var lastMillis;
function setup() {
createCanvas(windowWidth,windowHeight);
a = PI/3;
centerX = width/2;
centerY = height/2
scaleOfPendulum = min(height,width)*.01
l = scaleOfPendulum*30
}
function draw() {
update();
//moveSeconds();
background(255);
var angle = p5.Vector.fromAngle(a,l);
x = centerX+angle.x;
y = centerY+angle.y;
headPoint = new createAngledVector(x,y,calcTrueA(a),abs(a_vel));
pointsToKeep.push(headPoint);
if(pointsToKeep.length>100){
pointsToKeep.shift();
}
for (var i = 0; i < pointsToKeep.length; i++) {
var color = pointsToKeep[i].a/(2*PI)*255;
var color2 = pointsToKeep[i].a_vel*255;
stroke(color2,250,color,(i+1)/pointsToKeep.length*60);
strokeWeight(scaleOfPendulum*6*(i+1)/pointsToKeep.length)
fill(255,255,255,50);
rect(0,0,windowWidth,windowHeight);
//调用光晕圆
DrawShiner(pointsToKeep[i].x,pointsToKeep[i].y,"SUN");
}
strokeWeight(scaleOfPendulum);
stroke(255,0,0)
line(centerX,centerY,x,y)
strokeWeight(scaleOfPendulum*6);
point(x,y);
}
function moveSeconds(){
if(lastSecond != second()){
lastSecond = second();
lastMillis = millis();
}
a = second() * 2 * PI / 60 + 2*PI/60/1000*(millis()-lastMillis);
}
function update(){
if(!movable){
a_vel = a_vel - sin(a-PI/2)/l;
a_vel = a_vel ;
a = a + a_vel;
}
}
function calcTrueA(angle){
if(angle<=0){
while(angle<=-PI){
angle = angle+2*PI;
}
trueA = 2*PI+angle;
} else {
while(angle>PI){
angle = angle-2*PI;
}
trueA = angle;
}
return trueA;
}
function createAngledVector(x,y,a,a_vel){
this.x = x;
this.y = y;
this.a = a;
this.a_vel = a_vel;
}
4.2 多个钟摆—文字圆
在做了单个钟摆后,我也想到要把多个钟摆放在一起,效果肯定也不错。因为钟摆的震动周期是和他的线长有关系的,像我们在律老师放的短片《神奇的钟摆效应》中,也可以看到类似的效果。
在圆的使用上,我选择了空心圆,这样不会相互遮挡。
- 文字圆介绍
A1文字圆
- 调用方法
var p = [];
var hue;
function setup(){
createCanvas(600,600);
colorMode(HSB);
for(var i=0;i< 20;i++){
p[i]=new TextPendulum(createVector(width/2,20),200);
p[i].r=random(300,500);
}
}
function draw(){
background(0);
for(var i=0;i<p.length;i++){
p[i].go();
}
hue+=10;
if(hue>255){
hue=0;
}
}
4.4 棒棒糖弹簧
简单的弹簧效果在代码本色这本书的第三章里也有提到,在此基础上我做了圆和颜色随频率的改变。
var b;
var s;
var relp;
var d;
function setup()
{
createCanvas(windowWidth, windowHeight);
background(255);
b = new SpringLolly(width/2,height *0.75);
s= new Spring(width/2, 0, HALF_PI)
}
function draw()
{
background(255);
b.update(calcForce(b,s))
b.show()
s.show(p5.Vector.sub(b.loc,s.loc).mag())
}
function calcForce(b,s)
{
relp = p5.Vector.sub(b.loc,s.loc)
d=relp.mag()
return relp.normalize().mult(0.1*(d-s.l)).mult(-1)
}