粒子逃避光标和其他粒子

时间:2020-05-01 17:43:32

标签: javascript html canvas

我正在尝试创建一个简单的香草JS程序,其中在屏幕上生成了x数量的粒子/对象,它们需要彼此躲避和与鼠标躲避。对于总体规避,我使用了https://gist.github.com/christopher4lis/f9ccb589ee8ecf751481f05a8e59b1dc,它对于粒子之间相互躲避的效果很好,但是现在我仍然坚持实现鼠标规避功能。

我尝试过的所有结果最终都是粒子彼此重叠或出现了其他错误。

有人对如何处理这种情况有任何提示吗,或者甚至没有以前项目中的代码片段?

import {c, canvas, mouse, people} from "./canvas.js";
import {distance} from "./utils.js";

// @ts-ignore
import {resolveCollision} from './util-elastic-collision.js';

export default class Person {
    private velocity: { x: number, y: number };
    private mass: number;
    constructor(
        private _x: number,
        private _y: number,
        private radius: number,
    ) {
        this.velocity = {
            x: (Math.random() - 0.5) * 2,
            y: (Math.random() - 0.5) * 2,
        }
        this.mass = 1;
    }

get x() {
    return this._x;
}

set x(x: number) {
    this._x = x;
}

get y() {
    return this._y;
}

set y(y: number) {
    this._y = y;
}

draw() {
    c.beginPath();
    c.arc(this._x, this._y, this.radius, 0, Math.PI * 2);
    c.fill();
}

update() {
    this.draw();
    this.keepDistance();

    // Bounce off the mouse // Failed
    for (let i = 0; i < people.length; i++) {
        let dist = distance(mouse.x, mouse.y, people[i].x, people[i].y) - 6 * this.radius;
        if (dist <= 0) {

            people[i].x += (mouse.x > people[i].x + this.radius) ? -1 : 1;
            people[i].y += (mouse.y > people[i].y + this.radius) ? -1 : 1;

        }
    }


    // Bounce off the walls
    if (this._x - this.radius < 0 || this._x + this.radius > canvas.width) {
        this.velocity.x *= -1;
    }

    if (this._y - this.radius < 0 || this._y + this.radius > canvas.height) {
        this.velocity.y *= -1;
    }

    this._x += this.velocity.x;
    this._y += this.velocity.y;
}

keepDistance() {
    // Bounce off other people
    for (let i = 0; i < people.length; i++) {
        if (people[i] === this) continue;
        let dist = distance(this._x, this._y, people[i].x, people[i].y) - 4 * this.radius;
        if (dist <= 0) {
            resolveCollision(this, people[i]);
        }
    }
}

}

1 个答案:

答案 0 :(得分:0)

首先我要更改:
dist = distance(this._x, this._y, people[i].x, people[i].y) - 4 * this.radius;

到以下内容:
dist = distance(this._x, this._y, people[i].x, people[i].y) - (this.radius + people[i].radius);

当圆的半径不同时,应该会给您逼真的碰撞


然后在鼠标对象碰撞时,我将从类似以下内容开始:

    var dist = distance(mouse.x, mouse.y, people[i].x, people[i].y) - people[i].radius;
    if (dist <= 100) {
        let m = new Person(mouse.x, mouse.y, 100);
        //TODO set proper velocity
        m.velocity = { x: 2, y: 2 };
        resolveCollision(m, people[i]);
    }

这样,我们重用了resolveCollision,保持与其他对象之间的碰撞相同的效果。您确实需要找到一种方法来设置鼠标的适当速度,因为它假设鼠标在左右移动。

引入鼠标resolveCollision后,我注意到了其他一些东西,它们只是交换了速度:
https://github.com/AlverPalk/collision/blob/master/src/ts/util-elastic-collision.js#L58
我认为它还应该降低碰撞时的速度,因为碰撞时的能量损失,如果不是每次与鼠标的碰撞都将使速度增加到整个系统运行得非常快的程度


代码在我的叉子上:
https://github.com/heldersepu/collision/commits/master