Javascript 使用p5.js创建水

Javascript 使用p5.js创建水,javascript,html,game-physics,p5.js,Javascript,Html,Game Physics,P5.js,我试图在p5.js中用波浪和其他东西创建一些水效果,但我似乎无法让水中的波浪起作用。我正在创造迈克尔·霍夫曼的文章的波浪。我为水创建了两个类,一个称为“Springs”的类,它模拟水的弹簧效果,另一个称为“Liquid”,它只包含一个弹簧列表和一些常量 为了显示水面,我使用p5的beginShape()和vertex()函数创建水面。我穿过并创建了每个弹簧高度的顶点 现在的水是静止的。我希望只有当球碰到水面时,水才会产生波浪。我已经将液体的“contains”方法设置为true,以查看波是否工作

我试图在p5.js中用波浪和其他东西创建一些水效果,但我似乎无法让水中的波浪起作用。我正在创造迈克尔·霍夫曼的文章的波浪。我为水创建了两个类,一个称为“Springs”的类,它模拟水的弹簧效果,另一个称为“Liquid”,它只包含一个弹簧列表和一些常量

为了显示水面,我使用p5的beginShape()和vertex()函数创建水面。我穿过并创建了每个弹簧高度的顶点

现在的水是静止的。我希望只有当球碰到水面时,水才会产生波浪。我已经将液体的“contains”方法设置为true,以查看波是否工作

我想知道我取水的方式是否有问题。以前,当我点击的时候会有一个类似弹簧的效果,除了整个水面会保持一个矩形。使用矢量在水中产生波浪有什么问题吗?与霍夫曼建议的绘制梯形图相比,创建波浪似乎是一个更简单的解决方案,但事实证明,我可以使用p5.js轻松绘制梯形图

谢谢你的帮助

代码如下:

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);
}
var-balls=[];
var液体;
功能液体{
这个。弹簧=s;
该张力=0.025;
该阻尼=0.025;
该系数为0.25;
}
函数Spring(){
此.targetLight=0;
这个高度=0;
这个.vel=0;
this.update=功能(阻尼、张力){
设x=this.targetLight-this.height;
this.vel+=(张力*x-this.vel*阻尼);
this.height+=this.vel;
}
}
Liquid.prototype.update=函数(){
对于(var i=0;i0)
{
lDeltas[i]=this.spread*(this.springs[i].height-this.springs[i-1].height);
this.springs[i-1].vel+=lDeltas[i];
}
如果(i0)
this.springs[i-1].height+=lDeltas[i];
如果(i=0&&indexa=f/m
Mover.prototype.applyForce=功能(力){
var f=p5.Vector.div(力,即质量);
本.加速度.加(f);
}
Mover.prototype.update=函数(){
这个。速度。加(这个。加速度);
this.position.add(this.velocity);
this.acceleration.mult(0);//必须清除加速度;不会添加到自身!
};
Mover.prototype.display=函数(){
笔划(0);//黑色轮廓
strokeWeight(2);//使其更可见
填充(255127);//给它一个灰色
椭圆(this.position.x,this.position.y,this.mass*16,this.mass*16);//在该位置创建一个椭圆
};
函数设置(){
createCanvas(窗口宽度、窗口高度);
背景(255);
var-temp=[];
对于(var i=0;i<340;i++){//340是一个任意数
var tempSpring=newthis.Spring();
tempSpring.targetLight=高度/2;
tempSpring.height=高度/2;
温度[i]=温度弹簧;
}
液体=新液体(温度);
液体显示();
}
函数绘图(){
背景(255);
对于(变量i=0;i
从何处开始:

  • 没有球[i].x这样的东西
  • splash()中未定义的变量“i”
  • 您使用球的x坐标索引到弹簧阵列(在splash()内),这似乎不正确。首先,x坐标范围从0到宽度,弹簧阵列索引范围从0到339。其次,x坐标是一个非整数值,因此使用它来索引数组将不起作用
  • 球总是溅水
  • 水对球不起作用
找到这些东西的最好方法是学习如何在浏览器中使用调试器,逐行检查代码,检查所有内容并确保它们与您期望的内容匹配。大多数这些简单的错误都会立即向你扑来

var-balls=[];
var液体;