【JS】使用p5.js画出动画滑稽碰撞图

使用p5.js做了一个动态碰撞的滑稽笑脸,效果如图
【JS】使用p5.js画出动画滑稽碰撞图首先是定义了一个画滑稽的函数,其中参数分别是滑稽的横纵坐标、大小以及眼珠的朝向,L可取-1和1两个值,-1向右,1向左。脸用了两个填充的圆重叠(也可一个圆加边框)。嘴和眼睛以及眉毛是分别画两个圆弧相重叠而成。

function huaji(x,y,size,l){

noStroke();

fill(237,148,14);

ellipse(x,y,1.06*size);

fill(252,222,12);

ellipse(x,y,size);//脸

fill(173,91,10);

arc(x, y, 0.8*size, 0.8*size, 0, PI, CHORD);

fill(252,222,12);

arc(x, y-0.01*size, 0.8*size, 0.7*size, 0, PI, CHORD);//笑

fill(254,240,205);

arc(x-0.25*size, y, 0.8*size, 0.6*size, 1.3*PI,1.7* PI, PIE);

fill(252,222,12);

arc(x-0.25*size, y, 0.8*size, 0.5*size, 1.3*PI,1.7* PI, PIE);

fill(254,240,205);

arc(x+0.25*size, y, 0.8*size, 0.6*size, 1.3*PI,1.7* PI, PIE);

fill(252,222,12);

arc(x+0.25*size, y, 0.8*size, 0.5*size, 1.3*PI,1.7* PI, PIE);//眼壳子

if(l==-1){

fill(173,91,10);

ellipse(x-0.34*size,y-0.28*size,0.1*size);

ellipse(x+0.16*size,y-0.28*size,0.1*size);//眼珠

}

if(l==1){

fill(173,91,10);

ellipse(x-0.1*size,y-0.28*size,0.1*size);

ellipse(x+0.35*size,y-0.28*size,0.1*size);//眼珠

}

fill(58,43,1);

arc(x-0.28*size, y-0.35*size,0.20*size, 0.20*size, 1.1*PI,2.1* PI, OPEN);

fill(252,222,12);

arc(x-0.28*size, y-0.35*size, 0.21*size, 0.16*size, 1*PI,2.2* PI, OPEN);

fill(58,43,1);

arc(x+0.28*size, y-0.35*size,0.20*size,0.20*size, 0.9*PI,1.9* PI, CHORD);

fill(252,222,12);

arc(x+0.28*size, y-0.35*size, 0.21*size, 0.15*size, 0.9*PI,1.9* PI, CHORD);//眉毛

fill(241,74,56);

ellipse(x-0.25*size,y-0.18*size,0.25*size,0.07*size);

ellipse(x+0.25*size,y-0.18*size,0.25*size,0.07*size);

}

接下来是碰撞,

var numBalls = 10;

var spring = 0.05;

var gravity = 0.03;

var friction = -0.9;

var balls = [];

function setup() {

createCanvas(720, 400);

for (var i = 0; i < numBalls; i++) {

balls[i] = new Ball(

random(width),

random(height),

random(30, 100),

i,

balls

);

}

noStroke();

fill(255, 204);

}

function draw() {

background(0);

balls.forEach(ball => {

ball.collide();

ball.move();

ball.display();

});

}

以上可以看出,定义了一些变量以及初始化了画布,并初始化了十个ball。

对每一个ball执行碰撞、移动和展示。我们接下来看看这三个函数分别是怎样的。

首先,第一个函数colide中,对每一个球求距离并与两球半径和进行比较,当小于两球半径之和的时候,证明两球相撞了,求出加速度,对两球速度进行改变。

第二个函数move中,如果球撞到墙,将其速度*-0.9,即反向并略减少速度,而且每次都有个向下的加速度。所以后来的滑稽会慢慢停下。在前两个函数中都对m进行取反的操作,即可每次碰撞都变化眼珠的朝向,而当速度非常小的时候,将m的值固定。

第三个函数display则是调用滑稽函数。

function Ball(xin, yin, din, idin, oin) {

this.x = xin;

this.y = yin;

var vx = 0;

var vy = 0;

var m=1;

this.diameter = din;

this.id = idin;

this.others = oin;

this.collide = function() {

for (var i = this.id + 1; i < numBalls; i++) {

var dx = this.others[i].x - this.x;

var dy = this.others[i].y - this.y;

var distance = sqrt(dx * dx + dy * dy);

var minDist = this.others[i].diameter / 2 + this.diameter / 2;

if (distance < minDist) {

var angle = atan2(dy, dx);

var targetX = this.x + cos(angle) * minDist;

var targetY = this.y + sin(angle) * minDist;

var ax = (targetX - this.others[i].x) * spring;

var ay = (targetY - this.others[i].y) * spring;

vx -= ax;

vy -= ay;

this.others[i].vx += ax;

this.others[i].vy += ay;

m*=-1;

}

}

};

this.move = function() {

vy += gravity;

this.x += vx;

this.y += vy;

if (this.x + this.diameter / 2 > width) {

this.x = width - this.diameter / 2;

vx *= friction;

m*=-1;

} else if (this.x - this.diameter / 2 < 0) {

this.x = this.diameter / 2;

vx *= friction;

m*=-1;

}

if (this.y + this.diameter / 2 > height) {

this.y = height - this.diameter / 2;

vy *= friction;

m*=-1;

} else if (this.y - this.diameter / 2 < 0) {

this.y = this.diameter / 2;

vy *= friction;

m*=-1;

}

if((vx<0.1&&vx>-0.1)&&(vy<=0.1&&vy>-0.1)){

m=-1;}

};

this.display = function() {

huaji(this.x, this.y, this.diameter, m);

};

}

运行效果:https://editor.p5js.org/weihao/sketches/SyvVYveam

参考文献:p5.js官方文档
https://p5js.org/zh-Hans/examples/motion-bouncy-bubbles.html

以上是 【JS】使用p5.js画出动画滑稽碰撞图 的全部内容, 来源链接: utcz.com/a/68405.html

回到顶部