简体   繁体   English

用p5.js创建水

[英]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: 从哪儿开始:

  • there's no such thing as balls[i].x . 没有balls[i].x这样的东西。
  • undefined variable 'i' in splash(). splash()中的未定义变量'i'。
  • you're using the ball's x coordinate to index into the springs array (inside splash()), this doesn't seem right. 您正在使用球的x坐标来索引springs数组(在splash()内部),这似乎不正确。 firstly the x-coordinate ranges from 0 to width, and the springs array indices range from 0 to 339. secondly, the x coordinate is a non-integer value, so using it to index an array won't work. 首先,x坐标的范围是0到宽度,springs数组索引的范围是0到339。其次,x坐标是一个非整数值,因此使用它对数组进行索引将不起作用。
  • the balls always splash the water 球总是溅水
  • the water doesn't act on the balls 水不会作用在球上

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM