1 | import { CollisionMode } from "../../Enums";
|
2 | import { NumberUtils, Utils } from "../../Utils";
|
3 | function bounce(p1, p2) {
|
4 | Utils.circleBounce(Utils.circleBounceDataFromParticle(p1), Utils.circleBounceDataFromParticle(p2));
|
5 | }
|
6 | function destroy(p1, p2) {
|
7 | if (p1.getRadius() === undefined && p2.getRadius() !== undefined) {
|
8 | p1.destroy();
|
9 | }
|
10 | else if (p1.getRadius() !== undefined && p2.getRadius() === undefined) {
|
11 | p2.destroy();
|
12 | }
|
13 | else if (p1.getRadius() !== undefined && p2.getRadius() !== undefined) {
|
14 | if (p1.getRadius() >= p2.getRadius()) {
|
15 | p2.destroy();
|
16 | }
|
17 | else {
|
18 | p1.destroy();
|
19 | }
|
20 | }
|
21 | }
|
22 | export class Collider {
|
23 | constructor(container) {
|
24 | this.container = container;
|
25 | }
|
26 | isEnabled(particle) {
|
27 | return particle.options.collisions.enable;
|
28 | }
|
29 | reset() {
|
30 | }
|
31 | interact(p1) {
|
32 | const container = this.container;
|
33 | const pos1 = p1.getPosition();
|
34 | const query = container.particles.quadTree.queryCircle(pos1, p1.getRadius() * 2);
|
35 | for (const p2 of query) {
|
36 | if (p1 === p2 ||
|
37 | !p2.options.collisions.enable ||
|
38 | p1.options.collisions.mode !== p2.options.collisions.mode ||
|
39 | p2.destroyed ||
|
40 | p2.spawning) {
|
41 | continue;
|
42 | }
|
43 | const pos2 = p2.getPosition();
|
44 | const dist = NumberUtils.getDistance(pos1, pos2);
|
45 | const radius1 = p1.getRadius();
|
46 | const radius2 = p2.getRadius();
|
47 | const distP = radius1 + radius2;
|
48 | if (dist <= distP) {
|
49 | this.resolveCollision(p1, p2);
|
50 | }
|
51 | }
|
52 | }
|
53 | resolveCollision(p1, p2) {
|
54 | switch (p1.options.collisions.mode) {
|
55 | case CollisionMode.absorb: {
|
56 | this.absorb(p1, p2);
|
57 | break;
|
58 | }
|
59 | case CollisionMode.bounce: {
|
60 | bounce(p1, p2);
|
61 | break;
|
62 | }
|
63 | case CollisionMode.destroy: {
|
64 | destroy(p1, p2);
|
65 | break;
|
66 | }
|
67 | }
|
68 | }
|
69 | absorb(p1, p2) {
|
70 | const container = this.container;
|
71 | const fps = container.actualOptions.fpsLimit / 1000;
|
72 | if (p1.getRadius() === undefined && p2.getRadius() !== undefined) {
|
73 | p1.destroy();
|
74 | }
|
75 | else if (p1.getRadius() !== undefined && p2.getRadius() === undefined) {
|
76 | p2.destroy();
|
77 | }
|
78 | else if (p1.getRadius() !== undefined && p2.getRadius() !== undefined) {
|
79 | if (p1.getRadius() >= p2.getRadius()) {
|
80 | const factor = NumberUtils.clamp(p1.getRadius() / p2.getRadius(), 0, p2.getRadius()) * fps;
|
81 | p1.size.value += factor;
|
82 | p2.size.value -= factor;
|
83 | if (p2.getRadius() <= container.retina.pixelRatio) {
|
84 | p2.size.value = 0;
|
85 | p2.destroy();
|
86 | }
|
87 | }
|
88 | else {
|
89 | const factor = NumberUtils.clamp(p2.getRadius() / p1.getRadius(), 0, p1.getRadius()) * fps;
|
90 | p1.size.value -= factor;
|
91 | p2.size.value += factor;
|
92 | if (p1.getRadius() <= container.retina.pixelRatio) {
|
93 | p1.size.value = 0;
|
94 | p1.destroy();
|
95 | }
|
96 | }
|
97 | }
|
98 | }
|
99 | }
|