[英]Creating water with p5.js
I'm trying to create some water effects in p5.js with waves and everything, but I can't seem to get the waves in the water to work. 我试图在p5.js中创建带有波浪和所有东西的水效果,但是我似乎无法使水中的波浪起作用。 I am creating the waves off of this article by Michael Hoffman.
我正在掀起Michael Hoffman撰写的这篇文章。 I created two classes for the water, one class called "Springs," which simulates the spring effect of the water, and one class called "Liquid", which just hold a list of springs and some constants.
我为水创建了两个类,一个类名为“ Springs”,用于模拟水的弹簧效果,另一个类名为“ Liquid”,其中仅包含一系列弹簧和一些常数。
To display the water, I used p5's beginShape() and vertex() functions to create the surface of the water. 为了显示水,我使用了p5的beginShape()和vertex()函数来创建水的表面。 I went through and created a vertex of the height of each spring.
我遍历并创建了每个弹簧高度的顶点。
The water right now is staying static. 现在的水保持静止。 I want the water to create a wave only when a ball hits the surface of the water.
我希望水只有在球碰到水面时才产生波浪。 I have set the Liquid's "contains" method to true to just to see if the waves are working.
我已将Liquid的“ contains”方法设置为true,以仅查看波浪是否正在起作用。
I want to know if there is a problem with the way I am drawing the water. 我想知道我吸水的方式是否有问题。 Previously, there would be a spring-like effect when I clicked, except the entire surface of the water would remain a rectangle.
以前,当我单击时会有类似弹簧的效果,除了水的整个表面将保持矩形。 Is there something wrong with using vectors to create waves in the water?
使用向量在水中产生波浪是否有问题? It seemed like a simpler solution to creating the waves than drawing trapezoids like Hoffman suggests, but it turns out I can draw trapezoids easily with p5.js.
与绘制霍夫曼建议的绘制梯形相比,这似乎是创建波浪的一种更简单的解决方案,但是事实证明,我可以使用p5.js轻松绘制梯形。
Thanks for the help. 谢谢您的帮助。
Here is the code: 这是代码:
var balls = [];
var liquid;
function Liquid(s) {
this.springs = s;
this.tension = 0.025;
this.dampening = 0.025;
this.spread = 0.25;
}
function Spring() {
this.targetHeight = 0;
this.height = 0;
this.vel = 0;
this.update = function(dampening, tension) {
let x = this.targetHeight - this.height;
this.vel += (tension * x - this.vel * dampening);
this.height += this.vel;
}
}
Liquid.prototype.update = function () {
for (var i = 0; i < this.springs.length; i++)
this.springs[i].update(this.dampening, this.tension);
var lDeltas = [];
var rDeltas = [];
// do some passes where columns pull on their neighbours
for (var j = 0; j < 8; j++)
{
for (var i = 0; i < this.springs.length; i++)
{
if (i > 0)
{
lDeltas[i] = this.spread * (this.springs[i].height - this.springs[i - 1].height);
this.springs[i - 1].vel += lDeltas[i];
}
if (i < this.springs.length - 1)
{
rDeltas[i] = this.spread * (this.springs[i].height - this.springs[i + 1].height);
this.springs[i + 1].vel += rDeltas[i];
}
}
for (var i = 0; i < this.springs.length; i++)
{
if (i > 0)
this.springs[i - 1].height += lDeltas[i];
if (i < this.springs.length - 1)
this.springs[i + 1].height += rDeltas[i];
}
}
}
Liquid.prototype.splash = function (index, speed) {
if (index >= 0 && index < this.springs.length)
this.springs[i].vel = speed;
}
Liquid.prototype.display = function () {
fill(0, 0, 255);
beginShape();
vertex(0, height - this.springs[0].height);
for (var i = 0; i < this.springs.length; i++) {
vertex(i * (width / this.springs.length), height-this.springs[i].height); //consider using the map function
}
vertex(width, height);
vertex(0, height);
endShape(CLOSE);
}
Liquid.prototype.contains = function(m) {
return true;
};
function Mover(m, x, y) {
this.mass = m;
this.position = createVector(x,y);
this.velocity = createVector(0,0);
this.acceleration = createVector(0,0);
}
// f = m / a --> a = f / m
Mover.prototype.applyForce = function(force) {
var f = p5.Vector.div(force,this.mass);
this.acceleration.add(f);
}
Mover.prototype.update = function() {
this.velocity.add(this.acceleration);
this.position.add(this.velocity);
this.acceleration.mult(0); //acceleration must be cleared; does not add to itself!
};
Mover.prototype.display = function() {
stroke(0); //black outline
strokeWeight(2); //make it more visible
fill(255,127); //give it a gray color
ellipse(this.position.x,this.position.y,this.mass*16,this.mass*16); //create an ellipse at the position
};
function setup() {
createCanvas(windowWidth, windowHeight);
background(255);
var temp = [];
for (var i = 0; i < 340; i++) { //340 is an arbitrary num
var tempSpring = new this.Spring();
tempSpring.targetHeight = height/2;
tempSpring.height = height/2;
temp[i] = tempSpring;
}
liquid = new Liquid(temp);
liquid.display();
}
function draw() {
background(255);
for (var i = 0; i < balls.length; i++) {
if(liquid.contains(balls[i])) {
liquid.splash(balls[i].x, 0.05);
}
liquid.update();
liquid.display();
// Gravity is scaled by mass here!
var gravity = createVector(0, 0.1*balls[i].mass);
// Apply gravity
balls[i].applyForce(gravity);
balls[i].update();
balls[i].display();
}
liquid.display();
}
function mousePressed() {
balls[balls.length] = new Mover(5, mouseX, mouseY);
}
where to start: 从哪儿开始:
balls[i].x
. balls[i].x
这样的东西。 the single best way to find this stuff is to learn how to use the debugger in your browser, step through the code line by line, inspect all the things and make sure they match up with what you expect. 找到这些东西的唯一最佳方法是学习如何在浏览器中使用调试器,逐行浏览代码,检查所有内容并确保它们与您的期望相符。 most of these simple errors will jump out at you immediately.
这些简单的错误大多数都会立即跳到您的身边。
var balls = []; var liquid; function Liquid(s) { this.springs = s; this.tension = 0.025; this.dampening = 0.025; this.spread = 0.25; } function Spring() { this.targetHeight = 0; this.height = 0; this.vel = 0; this.update = function(dampening, tension) { let x = this.targetHeight - this.height; this.vel += tension * x - this.vel * dampening; this.height += this.vel; }; } Liquid.prototype.update = function() { for (var i = 0; i < this.springs.length; i++) this.springs[i].update(this.dampening, this.tension); var lDeltas = []; var rDeltas = []; // do some passes where columns pull on their neighbours for (var j = 0; j < 8; j++) { for (var i = 0; i < this.springs.length; i++) { if (i > 0) { lDeltas[i] = this.spread * (this.springs[i].height - this.springs[i - 1].height); this.springs[i - 1].vel += lDeltas[i]; } if (i < this.springs.length - 1) { rDeltas[i] = this.spread * (this.springs[i].height - this.springs[i + 1].height); this.springs[i + 1].vel += rDeltas[i]; } } for (var i = 0; i < this.springs.length; i++) { if (i > 0) this.springs[i - 1].height += lDeltas[i]; if (i < this.springs.length - 1) this.springs[i + 1].height += rDeltas[i]; } } }; Liquid.prototype.splash = function(index, speed) { if (index >= 0 && index < this.springs.length) this.springs[floor(index)].vel = speed; }; Liquid.prototype.display = function() { fill(0, 0, 255); beginShape(); vertex(0, height - this.springs[0].height); for (var i = 0; i < this.springs.length; i++) { vertex(i * (width / this.springs.length), height - this.springs[i].height); //consider using the map function } vertex(width, height); vertex(0, height); endShape(CLOSE); }; Liquid.prototype.contains = function(m) { return true; }; function Mover(m, x, y) { this.mass = m; this.position = createVector(x, y); this.velocity = createVector(0, 0); this.acceleration = createVector(0, 0); } // f = m / a --> a = f / m Mover.prototype.applyForce = function(force) { var f = p5.Vector.div(force, this.mass); this.acceleration.add(f); }; Mover.prototype.update = function() { this.velocity.add(this.acceleration); this.position.add(this.velocity); this.acceleration.mult(0); //acceleration must be cleared; does not add to itself! }; Mover.prototype.display = function() { stroke(0); //black outline strokeWeight(2); //make it more visible fill(255, 127); //give it a gray color ellipse(this.position.x, this.position.y, this.mass * 16, this.mass * 16); //create an ellipse at the position }; function setup() { createCanvas(windowWidth, windowHeight); background(255); var temp = []; for (var i = 0; i < 340; i++) { //340 is an arbitrary num var tempSpring = new Spring(); tempSpring.targetHeight = height / 2; tempSpring.height = height / 2; temp[i] = tempSpring; } liquid = new Liquid(temp); liquid.display(); } function draw() { background(255); liquid.update(); liquid.display(); for (var i = 0; i < balls.length; i++) { var ball = balls[i]; if (liquid.contains(ball)) { liquid.splash(ball.position.x, 54.5); } //liquid.display(); // Gravity is scaled by mass here! var gravity = createVector(0, 0.1 * ball.mass); // Apply gravity ball.applyForce(gravity); ball.update(); ball.display(); } } function mousePressed() { balls[balls.length] = new Mover(5, mouseX, mouseY); }
html, body { margin: 0; padding: 0; border: none; background: black; } canvas { display: block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.js"></script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.