p5.js码绘:融入概率论/随机性的线库
前言
本文记录的是自己用p5.js完成线库的拓展:加入随机性和概率论
一、DarkForestLine
函数简介: 该函数用柏林噪声noise()来确定树的位置以及生长高度。
函数原型: function Darkforest_line(x0,y0,x1,y1,maxH)
参数说明: x0和x1确定树木的水平生长范围,y0=y1确定森林的纵坐标,maxH为树的最大高度。该曲线只能水平放置。
交互性: 滚动鼠标滚轮可使画面静止,移动鼠标恢复。
- 负责树的排列
function Darkforest_line(x0,y0,x1,y1,maxH)
{
for(let i=0;i<x1;i=6+i)
{
x=map(noise(i),0,1,0,width);
h=map(noise(i^2),0,1,0,maxH);
tree(x,y0-h,h);
}
line(x0,y0,x1,y0);
}
- 负责生成树
function tree(x,y,h)
{
let tx,ty,a=1;
let angle=random(PI/10,PI/5);
strokeWeight(random(3,5));
stroke(random(0,255),random(255,255),random(100,255),255-map(mouseY,0,height,0,255));
line(x,y,x,y+h);
for(let j=0;j<h;j=j+random(5,10))
{
if(j>h/2){a=0.8;}
strokeWeight(random(1,3));
tx=x-j*tan(angle)*a;
ty=y+j;
line(x,y+j*3/4,tx,ty);
strokeWeight(random(1,3));
tx=x+j*tan(angle)*a;
ty=y+j;
line(x,y+j*3/4,tx,ty);
}
}
效果展示:
二、DarkCityLine
函数说明: 该函数用柏林噪声noise()来确定建筑物的位置以及高度。
函数原型: function Darkcity_line(x0,y0,x1,y1,maxH)
参数说明: x0和x1确定建筑物的水平范围,y0=y1确定建筑物的纵坐标,maxH为建筑物的最大高度。该曲线同样只能水平放置。
交互性: 滚动鼠标滚轮可使画面静止,移动鼠标恢复。
- 负责条形建筑物的排列
function Darkcity_line(x0,y0,x1,y1,maxH)
{
for(let i=0;i<x1;i=4+i)
{
x=map(noise(i),0,1,0,width);
h=map(noise(i^2),0,1,0,maxH);
city(x,y0-h,h);
}
line(x0,y0,x1,y0);
}
- 负责生成条形建筑物和雪花噪声
function city(x,y,h)
{
noFill();
stroke(random(0,255),random(255,255),random(255,255),255-map(mouseY,0,height,0,255));
strokeWeight(random(1,2));
rect(x,y,100,h);
fill(random(0,255),random(255,255),random(255,255),map(mouseY,0,height,0,255));
for(let j=1;j<h;j=j+35)
{
rect(x+random(0,80),y+random(0,h),random(1,5),random(1,5));
}
}
效果展示:
三、ParticleSystemPro
简介: 对先前做的线库中粒子链的一些拓展,主要有以下几点:
- 粒子运动的加速度都是由random函数产生。
- 之前粒子生成的位置为固定的点,现在改为由柏林噪声产生随机数然后利用map函数映射到整个画布范围产生一个位置作为粒子的初始位置。
- 如果两个粒子的距离在指定的范围则两个粒子在产生连线的同时,粒子的速度也会收到影响。
- 可以利用鼠标操作与粒子进行交互(加速、减速、暂停)
参数说明: range表示鼠标交互范围的半径。
交互性:
- 点击鼠标左键产生红色圆圈,给圈内的粒子额外施加一个指向鼠标位置的速度。
- 点击鼠标中键产生绿色圆圈,使圈内的粒子的速度减为原来的十分之一。
- 滚动鼠标滚轮可使画面静止,同时调节鼠标交互范围的半径。
- 移动鼠标滚轮使画面恢复运动状态
//负责鼠标点击交互事件
if (mouseIsPressed) {
if (mouseButton == LEFT) {
stroke(255, 100, 100, 150);
strokeWeight(2);
noFill();
ellipse(mouseX, mouseY, range, range);
for (let i = system_1.particles.length-1; i >= 0; i--)
{
let p=system_1.particles[i];
if (dist(p.position.x, p.position.y, mouseX, mouseY)<range)
{
p.velocity.x=p.velocity.x+0.01*(mouseX-p.position.x);
p.velocity.y=p.velocity.y+0.01*(mouseY-p.position.y);
}
}
}
if (mouseButton === CENTER) {
stroke(0, 255, 0, 150);
strokeWeight(2);
noFill();
ellipse(mouseX, mouseY, range, range);
for (let i = system_1.particles.length-1; i >= 0; i--)
{
let p=system_1.particles[i];
if (dist(p.position.x, p.position.y, mouseX, mouseY)<range)
{
p.velocity.x=p.velocity.x*0.1;
p.velocity.y=p.velocity.y*0.1;
}
}
}
}
//控制画面静止与运动,以及鼠标交互范围的半径
function mouseWheel()
{
range=(range+25)%600+50;
noFill();
stroke(255, 255, 255, 255);
strokeWeight(0.8);
ellipse(mouseX, mouseY, range, range);
noLoop();
}
function mouseMoved()
{
loop();
}
//指定范围粒子间速度的影响
for (let j=this.particles.length-1; j>=0; j--)
{
let q=this.particles[j];
if (dist(q.position.x, q.position.y, p.position.x, p.position.y)<30||(dist(q.position.x, q.position.y, p.position.x, p.position.y)>200&&dist(q.position.x, q.position.y, p.position.x, p.position.y)<250))
{
strokeWeight(random(0.8, 1.2));
stroke(map(noise(millis(),0,1,0,255)), random(255,255), random(255,255), random(100, 150));
line(p.position.x, p.position.y, q.position.x, q.position.y);
p.velocity.x=p.velocity.x+random(-0.01, 0.01)*q.velocity.x;
p.velocity.y=p.velocity.y+random(-0.01, 0.01)*q.velocity.y;
}
效果展示:
https://www.bilibili.com/video/BV1qa4y1H7Sy/
互动媒体技术码绘:粒子系统+鼠标交互