【问题标题】:Particles "run away" from mouse粒子从鼠标“逃跑”
【发布时间】:2013-02-26 19:31:46
【问题描述】:

我正在画布上创建一个简单的粒子实验。现在我希望他们从画布上的鼠标光标“逃跑”。检测与鼠标的距离不是问题,但如何编码它们的行为?

每个粒子的创建如下:

    var particle = {
        x: Math.floor(Math.random() * width),
        y: Math.floor(Math.random() * height),
        xVel: Math.random() * 10 - 5,
        yVel: Math.random() * 10 - 5,
    }

所以我假设我也应该以某种方式保存方向,如果与指针的距离

如何检测方向?

【问题讨论】:

    标签: javascript canvas particles


    【解决方案1】:

    Velocity (xVel, yVel, together) 是一个二维向量。鼠标和粒子之间的距离也是如此。 vector 包含方向和大小。所以你想要一个向量,它是鼠标位置和粒子位置之间的差异。

    var posRelativeToMouse = {
      x: particle.x - mousPosX,
      y: particle.y - mousPosY
    };
    

    x 和 y 的小数表示粒子离鼠标很近,大的表示离鼠标很远。

    接下来我们需要弄清楚这些数字应该如何影响粒子的速度。所以我们需要两件事。

    我们将他们推向什么方向?

    大部分情况下,我们已经有了这个。 posRelativeToMouse 是一个具有我们想要的方向的向量。我们只是对其进行归一化,这意味着将向量的长度设置为 1。为此,我们将每个分量除以向量的当前长度。这个向量的长度始终是从粒子到鼠标的distance

    var distance = Math.sqrt(
      posRelativeToMouse.x * posRelativeToMouse.x +
      posRelativeToMouse.y * posRelativeToMouse.y
    );
    var forceDirection = {
      x: posRelativeToMouse.x / distance,
      y: posRelativeToMouse.y / distance,
    };
    

    我们推动粒子的力度有多大?

    这是距离的倒数。近意味着大推,远意味着小推。所以让我们重用我们上面计算的distance

    // distance past which the force is zero
    var maxDistance = 1000;
    
    // convert (0...maxDistance) range into a (1...0).
    // Close is near 1, far is near 0
    // for example:
    //   250 => 0.75
    //   100 => 0.9
    //   10  => 0.99
    var force = (maxDistance - distance) / maxDistance;
    
    // if we went below zero, set it to zero.
    if (force < 0) force = 0;
    

    好的,我们有方向,我们有力量。剩下的就是将其应用于粒子速度。

    particle.xVel += forceDirection.x * force * timeElapsedSinceLastFrame;
    particle.yVel += forceDirection.y * force * timeElapsedSinceLastFrame;
    

    假设您通过 xVel/yVel 为每一帧的位置设置动画,您现在应该有粒子被鼠标推开。

    【讨论】:

    • 效果很好,但现在我遇到了另一个问题。如何让粒子“回到”之前的速度?因为在逃离鼠标后,他们开始疯狂地使用新的速度 + 力
    • @mjanisz1 这取决于您希望他们如何表现。但这听起来有点像你想要对粒子施加阻力,这意味着它们会随着时间的推移自行减速?一个粗略但简单的方法是让每帧的速度稍微小一点。 particle.xVel *= 0.99 之类的东西(当然yVel 也是如此)。这意味着粒子每帧将损失 1% 的速度,如果没有其他力作用于它们,最终应该接近于零。您可以将 0.99 的值调整为您想要的任何阻力。
    • 非常感谢没有考虑乘法(简单的事情总是最好的和最难想到的)。我只存储第一个速度,如果 force == 0 &amp;&amp; xVel &gt; xVelOriginal 比乘以 0.99!希望它有效:) 非常感谢!
    【解决方案2】:

    鼠标的位置减去粒子的位置就可以得到向量v,

    那么你可以找到这个向量的大小我取sqrt(x^2 + y^2)

    通过将 v 除以幅度,您可以在您希望粒子前进的方向上获得一个单位向量。

    例如。

    假设我在列表 U 中有 10 个粒子,每个粒子都有一个 x 和 y 场。

    我可以通过设置 v = (xpart - mousepart, ypart - mousepart) 从每个粒子 v 中获取它的向量

    那么你需要通过取 sqrt(vx^2 + vy^2) 来找到幅度 vmag

    然后你得到 vunit = (vx / vmag, vy / vmag)

    这是“远离鼠标”的向量。

    剩下的可以留给确定你想要移动的速度,并确保你反弹墙壁等。

    我在 github 开源有一个类似的项目: https://github.com/dmitrymakhnin/JavaParticleSystem/blob/master/Main.java

    【讨论】:

      猜你喜欢
      • 2017-07-21
      • 2022-06-13
      • 2014-12-26
      • 2016-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多