dacha 0.17.2 → 0.18.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/build/contrib/components/collider/index.d.ts +17 -4
  2. package/build/contrib/components/collider/index.js +30 -2
  3. package/build/contrib/components/rigid-body/index.d.ts +29 -17
  4. package/build/contrib/components/rigid-body/index.js +64 -21
  5. package/build/contrib/components/shape/index.d.ts +17 -2
  6. package/build/contrib/components/shape/index.js +16 -0
  7. package/build/contrib/events/index.d.ts +10 -75
  8. package/build/contrib/events/index.js +0 -36
  9. package/build/contrib/systems/camera-system/{service.d.ts → api.d.ts} +4 -4
  10. package/build/contrib/systems/camera-system/{service.js → api.js} +2 -2
  11. package/build/contrib/systems/camera-system/index.d.ts +1 -1
  12. package/build/contrib/systems/camera-system/index.js +1 -1
  13. package/build/contrib/systems/camera-system/system.d.ts +1 -1
  14. package/build/contrib/systems/camera-system/system.js +5 -4
  15. package/build/contrib/systems/index.d.ts +3 -3
  16. package/build/contrib/systems/index.js +3 -3
  17. package/build/contrib/systems/mouse-input-system/subsystems/coordinates-projector/index.d.ts +0 -1
  18. package/build/contrib/systems/mouse-input-system/subsystems/coordinates-projector/index.js +4 -5
  19. package/build/contrib/systems/physics-system/api.d.ts +58 -0
  20. package/build/contrib/systems/physics-system/api.js +67 -0
  21. package/build/contrib/systems/physics-system/index.d.ts +2 -21
  22. package/build/contrib/systems/physics-system/index.js +2 -40
  23. package/build/contrib/systems/physics-system/physics-system.d.ts +24 -0
  24. package/build/contrib/systems/physics-system/physics-system.js +47 -0
  25. package/build/contrib/systems/physics-system/subsystems/collision-broadcast/collision.d.ts +5 -3
  26. package/build/contrib/systems/physics-system/subsystems/collision-broadcast/collision.js +7 -5
  27. package/build/contrib/systems/physics-system/subsystems/collision-broadcast/index.d.ts +4 -6
  28. package/build/contrib/systems/physics-system/subsystems/collision-broadcast/index.js +20 -17
  29. package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-circle-aabb.js +1 -2
  30. package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-point-aabb.d.ts +2 -0
  31. package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-point-aabb.js +7 -0
  32. package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-ray-aabb.d.ts +2 -0
  33. package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-ray-aabb.js +9 -0
  34. package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-segment-aabb.d.ts +2 -0
  35. package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-segment-aabb.js +14 -0
  36. package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/index.js +6 -0
  37. package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-box-geometry.d.ts +3 -1
  38. package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-box-geometry.js +52 -16
  39. package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-circle-geometry.d.ts +3 -1
  40. package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-circle-geometry.js +32 -7
  41. package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-point-geometry.d.ts +3 -0
  42. package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-point-geometry.js +5 -0
  43. package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-ray-geometry.d.ts +3 -0
  44. package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-ray-geometry.js +7 -0
  45. package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-segment-geometry.d.ts +3 -0
  46. package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-segment-geometry.js +33 -0
  47. package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/index.d.ts +12 -1
  48. package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/index.js +6 -0
  49. package/build/contrib/systems/physics-system/subsystems/collision-detection/index.d.ts +21 -9
  50. package/build/contrib/systems/physics-system/subsystems/collision-detection/index.js +177 -92
  51. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/check-boxes-intersection.d.ts +10 -0
  52. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/check-boxes-intersection.js +36 -0
  53. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/utils.d.ts +17 -0
  54. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/utils.js +126 -0
  55. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-circle/check-box-and-circle-intersection.d.ts +9 -0
  56. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-circle/check-box-and-circle-intersection.js +46 -0
  57. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-segment/check-box-and-segment-intersection.d.ts +10 -0
  58. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-segment/check-box-and-segment-intersection.js +28 -0
  59. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-segment/utils.d.ts +19 -0
  60. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-segment/utils.js +76 -0
  61. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/circle-circle/check-circles-intersection.d.ts +12 -0
  62. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/circle-circle/check-circles-intersection.js +47 -0
  63. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/circle-segment/check-circle-and-segment-intersection.d.ts +10 -0
  64. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/circle-segment/check-circle-and-segment-intersection.js +33 -0
  65. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/index.d.ts +2 -2
  66. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/index.js +27 -3
  67. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/point-box/check-point-and-box-intersection.d.ts +9 -0
  68. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/point-box/check-point-and-box-intersection.js +36 -0
  69. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/point-circle/check-point-and-circle-intersection.d.ts +9 -0
  70. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/point-circle/check-point-and-circle-intersection.js +33 -0
  71. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/point-segment/check-point-and-segment-intersection.d.ts +9 -0
  72. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/point-segment/check-point-and-segment-intersection.js +26 -0
  73. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-box/check-ray-and-box-intersection.d.ts +11 -0
  74. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-box/check-ray-and-box-intersection.js +69 -0
  75. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-circle/check-ray-and-circle-intersection.d.ts +10 -0
  76. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-circle/check-ray-and-circle-intersection.js +45 -0
  77. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-segment/check-ray-and-segment-intersection.d.ts +16 -0
  78. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-segment/check-ray-and-segment-intersection.js +51 -0
  79. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-segment/utils.d.ts +2 -0
  80. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-segment/utils.js +4 -0
  81. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/tests/helpers.d.ts +20 -0
  82. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/tests/helpers.js +69 -0
  83. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/utils.d.ts +9 -0
  84. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/utils.js +23 -0
  85. package/build/contrib/systems/physics-system/subsystems/collision-detection/query-utils.d.ts +10 -0
  86. package/build/contrib/systems/physics-system/subsystems/collision-detection/query-utils.js +63 -0
  87. package/build/contrib/systems/physics-system/subsystems/collision-detection/reorientation-checkers/check-collider.js +17 -8
  88. package/build/contrib/systems/physics-system/subsystems/collision-detection/types.d.ts +41 -11
  89. package/build/contrib/systems/physics-system/subsystems/collision-detection/types.js +0 -3
  90. package/build/contrib/systems/physics-system/subsystems/constraint-solver/index.d.ts +7 -10
  91. package/build/contrib/systems/physics-system/subsystems/constraint-solver/index.js +117 -79
  92. package/build/contrib/systems/physics-system/subsystems/index.d.ts +0 -1
  93. package/build/contrib/systems/physics-system/subsystems/index.js +0 -1
  94. package/build/contrib/systems/physics-system/subsystems/physics/index.d.ts +3 -9
  95. package/build/contrib/systems/physics-system/subsystems/physics/index.js +57 -93
  96. package/build/contrib/systems/physics-system/types.d.ts +37 -0
  97. package/build/contrib/systems/renderer/actor-render-tree.js +1 -2
  98. package/build/contrib/systems/renderer/{service → api}/index.d.ts +6 -6
  99. package/build/contrib/systems/renderer/{service → api}/index.js +14 -16
  100. package/build/contrib/systems/renderer/api/utils.d.ts +4 -0
  101. package/build/contrib/systems/renderer/{service → api}/utils.js +5 -0
  102. package/build/contrib/systems/renderer/builders/shape-builder/index.js +9 -1
  103. package/build/contrib/systems/renderer/builders/shape-builder/utils.js +16 -0
  104. package/build/contrib/systems/renderer/index.d.ts +1 -1
  105. package/build/contrib/systems/renderer/index.js +1 -1
  106. package/build/contrib/systems/renderer/renderer.d.ts +2 -1
  107. package/build/contrib/systems/renderer/renderer.js +9 -7
  108. package/build/engine/actor/actor-creator.js +6 -4
  109. package/build/engine/math-lib/math/ops.d.ts +1 -2
  110. package/build/engine/math-lib/math/ops.js +3 -3
  111. package/build/engine/math-lib/vector/ops.d.ts +18 -3
  112. package/build/engine/math-lib/vector/ops.js +28 -5
  113. package/build/engine/math-lib/vector/vector2.d.ts +22 -7
  114. package/build/engine/math-lib/vector/vector2.js +29 -5
  115. package/build/engine/template/template-collection.js +1 -1
  116. package/build/engine/world/index.d.ts +4 -24
  117. package/build/engine/world/index.js +5 -33
  118. package/build/engine/world/system-api-registry.d.ts +17 -0
  119. package/build/engine/world/system-api-registry.js +34 -0
  120. package/build/events/index.d.ts +2 -2
  121. package/build/events/index.js +1 -1
  122. package/build/types/global.d.ts +4 -0
  123. package/package.json +4 -1
  124. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/check-box-and-circle-intersection.d.ts +0 -16
  125. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/check-box-and-circle-intersection.js +0 -80
  126. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/check-boxes-intersection.d.ts +0 -6
  127. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/check-boxes-intersection.js +0 -72
  128. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/check-circles-intersection.d.ts +0 -11
  129. package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/check-circles-intersection.js +0 -39
  130. package/build/contrib/systems/physics-system/subsystems/collision-solver/index.d.ts +0 -10
  131. package/build/contrib/systems/physics-system/subsystems/collision-solver/index.js +0 -50
  132. package/build/contrib/systems/renderer/service/utils.d.ts +0 -3
@@ -1,36 +1,12 @@
1
- import { Vector2 } from '../../../../../engine/math-lib';
2
1
  import { RigidBody } from '../../../../components/rigid-body';
3
2
  import { Transform } from '../../../../components/transform';
4
- import { Collision } from '../../../../events';
5
3
  import { RIGID_BODY_TYPE } from '../../consts';
4
+ const SOLVER_ITERATIONS = 8;
5
+ const POSITION_CORRECTION_PERCENT = 0.8;
6
+ const PENETRATION_SLOP = 0.01;
7
+ const DEFAULT_CONTACT_FRICTION = 0.6;
6
8
  export class ConstraintSolver {
7
- scene;
8
- processedPairs;
9
- mtvMap;
10
- constructor(options) {
11
- this.scene = options.scene;
12
- this.processedPairs = new Map();
13
- this.mtvMap = new Map();
14
- this.scene.addEventListener(Collision, this.handleCollision);
15
- }
16
- destroy() {
17
- this.scene.removeEventListener(Collision, this.handleCollision);
18
- }
19
- handleCollision = (event) => {
20
- const { actor1, actor2, mtv1, mtv2 } = event;
21
- if (this.processedPairs.has(actor2) &&
22
- this.processedPairs.get(actor2).has(actor1)) {
23
- return;
24
- }
25
- if (!this.processedPairs.has(actor1)) {
26
- this.processedPairs.set(actor1, new Set());
27
- }
28
- this.processedPairs.get(actor1).add(actor2);
29
- if (!this.validateCollision(actor1, actor2)) {
30
- return;
31
- }
32
- this.resolveCollision(actor1, actor2, mtv1, mtv2);
33
- };
9
+ validContacts = [];
34
10
  validateCollision(actor1, actor2) {
35
11
  const rigidBody1 = actor1.getComponent(RigidBody);
36
12
  const rigidBody2 = actor2.getComponent(RigidBody);
@@ -41,68 +17,130 @@ export class ConstraintSolver {
41
17
  rigidBody2.type === RIGID_BODY_TYPE.STATIC) {
42
18
  return false;
43
19
  }
44
- if (rigidBody1.type === RIGID_BODY_TYPE.STATIC ||
45
- rigidBody2.type === RIGID_BODY_TYPE.STATIC) {
46
- return !rigidBody1.ghost && !rigidBody2.ghost;
20
+ return true;
21
+ }
22
+ getInverseMass(rigidBody) {
23
+ if (rigidBody.disabled || rigidBody.type === RIGID_BODY_TYPE.STATIC) {
24
+ return 0;
25
+ }
26
+ return rigidBody.inverseMass;
27
+ }
28
+ applyNormalImpulse(contact) {
29
+ const { actor1, actor2, normal } = contact;
30
+ const rigidBody1 = actor1.getComponent(RigidBody);
31
+ const rigidBody2 = actor2.getComponent(RigidBody);
32
+ const inverseMass1 = this.getInverseMass(rigidBody1);
33
+ const inverseMass2 = this.getInverseMass(rigidBody2);
34
+ const inverseMassSum = inverseMass1 + inverseMass2;
35
+ if (inverseMassSum === 0) {
36
+ return 0;
37
+ }
38
+ const relativeVelocityX = rigidBody2.linearVelocity.x - rigidBody1.linearVelocity.x;
39
+ const relativeVelocityY = rigidBody2.linearVelocity.y - rigidBody1.linearVelocity.y;
40
+ const velocityAlongNormal = relativeVelocityX * normal.x + relativeVelocityY * normal.y;
41
+ if (velocityAlongNormal >= 0) {
42
+ return 0;
43
+ }
44
+ const impulseMagnitude = -velocityAlongNormal / inverseMassSum;
45
+ const impulseX = normal.x * impulseMagnitude;
46
+ const impulseY = normal.y * impulseMagnitude;
47
+ if (inverseMass1 > 0) {
48
+ rigidBody1.linearVelocity.x -= impulseX * inverseMass1;
49
+ rigidBody1.linearVelocity.y -= impulseY * inverseMass1;
47
50
  }
48
- return (!rigidBody1.ghost &&
49
- !rigidBody1.isPermeable &&
50
- !rigidBody2.ghost &&
51
- !rigidBody2.isPermeable);
51
+ if (inverseMass2 > 0) {
52
+ rigidBody2.linearVelocity.x += impulseX * inverseMass2;
53
+ rigidBody2.linearVelocity.y += impulseY * inverseMass2;
54
+ }
55
+ return impulseMagnitude;
52
56
  }
53
- setMtv(actor, mtvX, mtvY, type) {
54
- if (!this.mtvMap.has(actor)) {
55
- this.mtvMap.set(actor, {});
57
+ applyFrictionImpulse(contact, normalImpulseMagnitude) {
58
+ if (normalImpulseMagnitude <= 0) {
59
+ return;
60
+ }
61
+ const { normal } = contact;
62
+ const rigidBody1 = contact.actor1.getComponent(RigidBody);
63
+ const rigidBody2 = contact.actor2.getComponent(RigidBody);
64
+ const inverseMass1 = this.getInverseMass(rigidBody1);
65
+ const inverseMass2 = this.getInverseMass(rigidBody2);
66
+ const inverseMassSum = inverseMass1 + inverseMass2;
67
+ if (inverseMassSum === 0) {
68
+ return;
56
69
  }
57
- const mtvs = this.mtvMap.get(actor);
58
- if (!mtvs?.[type]) {
59
- mtvs[type] = new Vector2(mtvX, mtvY);
70
+ const relativeVelocityX = rigidBody2.linearVelocity.x - rigidBody1.linearVelocity.x;
71
+ const relativeVelocityY = rigidBody2.linearVelocity.y - rigidBody1.linearVelocity.y;
72
+ const velocityAlongNormal = relativeVelocityX * normal.x + relativeVelocityY * normal.y;
73
+ const tangentX = relativeVelocityX - normal.x * velocityAlongNormal;
74
+ const tangentY = relativeVelocityY - normal.y * velocityAlongNormal;
75
+ const tangentMagnitude = Math.sqrt(tangentX ** 2 + tangentY ** 2);
76
+ if (tangentMagnitude === 0) {
60
77
  return;
61
78
  }
62
- switch (type) {
63
- case 'static':
64
- mtvs[type].x =
65
- Math.abs(mtvX) > Math.abs(mtvs[type].x) ? mtvX : mtvs[type].x;
66
- mtvs[type].y =
67
- Math.abs(mtvY) > Math.abs(mtvs[type].y) ? mtvY : mtvs[type].y;
68
- break;
69
- case 'dynamic':
70
- mtvs[type].x += mtvX;
71
- mtvs[type].y += mtvY;
79
+ const normalizedTangentX = tangentX / tangentMagnitude;
80
+ const normalizedTangentY = tangentY / tangentMagnitude;
81
+ const velocityAlongTangent = relativeVelocityX * normalizedTangentX +
82
+ relativeVelocityY * normalizedTangentY;
83
+ const unclampedImpulseMagnitude = -velocityAlongTangent / inverseMassSum;
84
+ const maxFrictionImpulseMagnitude = DEFAULT_CONTACT_FRICTION * normalImpulseMagnitude;
85
+ const impulseMagnitude = Math.max(-maxFrictionImpulseMagnitude, Math.min(unclampedImpulseMagnitude, maxFrictionImpulseMagnitude));
86
+ const impulseX = normalizedTangentX * impulseMagnitude;
87
+ const impulseY = normalizedTangentY * impulseMagnitude;
88
+ if (inverseMass1 > 0) {
89
+ rigidBody1.linearVelocity.x -= impulseX * inverseMass1;
90
+ rigidBody1.linearVelocity.y -= impulseY * inverseMass1;
91
+ }
92
+ if (inverseMass2 > 0) {
93
+ rigidBody2.linearVelocity.x += impulseX * inverseMass2;
94
+ rigidBody2.linearVelocity.y += impulseY * inverseMass2;
72
95
  }
73
96
  }
74
- resolveCollision(actor1, actor2, mtv1, mtv2) {
97
+ applyPositionCorrection(contact) {
98
+ const { actor1, actor2, normal, penetration } = contact;
75
99
  const rigidBody1 = actor1.getComponent(RigidBody);
76
100
  const rigidBody2 = actor2.getComponent(RigidBody);
77
- if (rigidBody1.type === RIGID_BODY_TYPE.STATIC) {
78
- this.setMtv(actor2, mtv2.x, mtv2.y, rigidBody1.type);
101
+ const inverseMass1 = this.getInverseMass(rigidBody1);
102
+ const inverseMass2 = this.getInverseMass(rigidBody2);
103
+ const inverseMassSum = inverseMass1 + inverseMass2;
104
+ if (inverseMassSum === 0) {
105
+ return;
79
106
  }
80
- else if (rigidBody2.type === RIGID_BODY_TYPE.STATIC) {
81
- this.setMtv(actor1, mtv1.x, mtv1.y, rigidBody2.type);
107
+ const correctionMagnitude = (Math.max(penetration - PENETRATION_SLOP, 0) *
108
+ POSITION_CORRECTION_PERCENT) /
109
+ inverseMassSum;
110
+ if (correctionMagnitude === 0) {
111
+ return;
112
+ }
113
+ const correctionX = normal.x * correctionMagnitude;
114
+ const correctionY = normal.y * correctionMagnitude;
115
+ const transform1 = actor1.getComponent(Transform);
116
+ const transform2 = actor2.getComponent(Transform);
117
+ if (inverseMass1 > 0) {
118
+ transform1.world.position.x -= correctionX * inverseMass1;
119
+ transform1.world.position.y -= correctionY * inverseMass1;
82
120
  }
83
- else {
84
- this.setMtv(actor1, mtv1.x / 2, mtv1.y / 2, rigidBody2.type);
85
- this.setMtv(actor2, mtv2.x / 2, mtv2.y / 2, rigidBody1.type);
121
+ if (inverseMass2 > 0) {
122
+ transform2.world.position.x += correctionX * inverseMass2;
123
+ transform2.world.position.y += correctionY * inverseMass2;
86
124
  }
87
125
  }
88
- update() {
89
- for (const [actor, entry] of this.mtvMap) {
90
- const transform = actor.getComponent(Transform);
91
- const { static: staticMtv, dynamic: dynamicMtv } = entry;
92
- /*
93
- * TODO:: Enable this part when it will be possible to run
94
- * phycics pipeline several times per single game loop iteration
95
- */
96
- // transform.world.position.x += Math.sign(staticMtv.x) === Math.sign(dynamicMtv.x)
97
- // ? staticMtv.x + dynamicMtv.x
98
- // : staticMtv.x || dynamicMtv.x;
99
- // transform.world.position.y += Math.sign(staticMtv.y) === Math.sign(dynamicMtv.y)
100
- // ? staticMtv.y + dynamicMtv.y
101
- // : staticMtv.y || dynamicMtv.y;
102
- transform.world.position.x += (staticMtv?.x ?? 0) + (dynamicMtv?.x ?? 0);
103
- transform.world.position.y += (staticMtv?.y ?? 0) + (dynamicMtv?.y ?? 0);
104
- }
105
- this.processedPairs.clear();
106
- this.mtvMap.clear();
126
+ update(contacts) {
127
+ let validContactsCount = 0;
128
+ contacts.forEach((contact) => {
129
+ if (!this.validateCollision(contact.actor1, contact.actor2)) {
130
+ return;
131
+ }
132
+ this.validContacts[validContactsCount] = contact;
133
+ validContactsCount += 1;
134
+ });
135
+ this.validContacts.length = validContactsCount;
136
+ for (let iteration = 0; iteration < SOLVER_ITERATIONS; iteration += 1) {
137
+ this.validContacts.forEach((contact) => {
138
+ const normalImpulseMagnitude = this.applyNormalImpulse(contact);
139
+ this.applyFrictionImpulse(contact, normalImpulseMagnitude);
140
+ });
141
+ }
142
+ this.validContacts.forEach((contact) => {
143
+ this.applyPositionCorrection(contact);
144
+ });
107
145
  }
108
146
  }
@@ -1,5 +1,4 @@
1
1
  export { PhysicsSubsystem } from './physics';
2
2
  export { CollisionDetectionSubsystem } from './collision-detection';
3
3
  export { CollisionBroadcastSubsystem } from './collision-broadcast';
4
- export { CollisionSolver } from './collision-solver';
5
4
  export { ConstraintSolver } from './constraint-solver';
@@ -1,5 +1,4 @@
1
1
  export { PhysicsSubsystem } from './physics';
2
2
  export { CollisionDetectionSubsystem } from './collision-detection';
3
3
  export { CollisionBroadcastSubsystem } from './collision-broadcast';
4
- export { CollisionSolver } from './collision-solver';
5
4
  export { ConstraintSolver } from './constraint-solver';
@@ -1,17 +1,11 @@
1
1
  import type { SceneSystemOptions, UpdateOptions } from '../../../../../engine/system';
2
2
  export declare class PhysicsSubsystem {
3
- private scene;
4
3
  private actorQuery;
5
4
  private gravity;
6
- private actorVectors;
7
5
  constructor(options: SceneSystemOptions);
8
6
  destroy(): void;
9
- private handleActorRemove;
10
- private handleStopMovement;
11
- private handleAddForce;
12
- private handleAddImpulse;
13
- private setUpVectors;
14
- private applyDragForce;
15
- private getGravityForce;
7
+ private applyLinearDamping;
8
+ private integrateVelocities;
9
+ private integratePositions;
16
10
  update(options: UpdateOptions): void;
17
11
  }
@@ -1,125 +1,89 @@
1
- import { Vector2 } from '../../../../../engine/math-lib';
2
1
  import { ActorQuery } from '../../../../../engine/actor';
3
2
  import { RigidBody } from '../../../../components/rigid-body';
4
3
  import { Transform } from '../../../../components/transform';
5
- import { AddForce, AddImpulse, StopMovement } from '../../../../events';
6
- import { RemoveActor } from '../../../../../engine/events';
7
- const DIRECTION_VECTOR = {
8
- UP: new Vector2(0, -1),
9
- LEFT: new Vector2(-1, 0),
10
- RIGHT: new Vector2(1, 0),
11
- DOWN: new Vector2(0, 1),
12
- };
13
4
  export class PhysicsSubsystem {
14
- scene;
15
5
  actorQuery;
16
6
  gravity;
17
- actorVectors;
18
7
  constructor(options) {
19
8
  const { gravity, scene } = options;
20
- this.scene = scene;
21
9
  this.actorQuery = new ActorQuery({ scene, filter: [RigidBody, Transform] });
22
10
  this.gravity = gravity;
23
- this.actorVectors = {};
24
- this.actorQuery.addEventListener(RemoveActor, this.handleActorRemove);
25
- this.scene.addEventListener(StopMovement, this.handleStopMovement);
26
- this.scene.addEventListener(AddForce, this.handleAddForce);
27
- this.scene.addEventListener(AddImpulse, this.handleAddImpulse);
28
11
  }
29
12
  destroy() {
30
- this.actorQuery.removeEventListener(RemoveActor, this.handleActorRemove);
31
- this.scene.removeEventListener(StopMovement, this.handleStopMovement);
32
- this.scene.removeEventListener(AddForce, this.handleAddForce);
33
- this.scene.removeEventListener(AddImpulse, this.handleAddImpulse);
13
+ this.actorQuery.destroy();
34
14
  }
35
- handleActorRemove = (event) => {
36
- const { actor } = event;
37
- delete this.actorVectors[actor.id];
38
- };
39
- handleStopMovement = (event) => {
40
- const { target } = event;
41
- if (!this.actorVectors[target.id]) {
42
- this.setUpVectors(target);
43
- }
44
- this.actorVectors[target.id].velocity.multiplyNumber(0);
45
- };
46
- handleAddForce = (event) => {
47
- const { target, value } = event;
48
- if (!this.actorVectors[target.id]) {
49
- this.setUpVectors(target);
50
- }
51
- this.actorVectors[target.id].force.add(value);
52
- };
53
- handleAddImpulse = (event) => {
54
- const { target, value } = event;
55
- if (!this.actorVectors[target.id]) {
56
- this.setUpVectors(target);
57
- }
58
- this.actorVectors[target.id].impulse.add(value);
59
- };
60
- setUpVectors(actor) {
61
- this.actorVectors[actor.id] = {
62
- velocity: new Vector2(0, 0),
63
- force: new Vector2(0, 0),
64
- impulse: new Vector2(0, 0),
65
- };
66
- }
67
- applyDragForce(actor, deltaTime) {
68
- const { mass, drag } = actor.getComponent(RigidBody);
69
- const velocity = this.actorVectors[actor.id]?.velocity;
70
- if (!drag || !velocity || (!velocity.x && !velocity.y)) {
15
+ applyLinearDamping(rigidBody, deltaTime) {
16
+ const { mass, linearDamping, linearVelocity } = rigidBody;
17
+ if (!linearDamping || (!linearVelocity.x && !linearVelocity.y)) {
71
18
  return;
72
19
  }
73
- const velocitySignX = Math.sign(velocity.x);
74
- const velocitySignY = Math.sign(velocity.y);
20
+ const velocitySignX = Math.sign(linearVelocity.x);
21
+ const velocitySignY = Math.sign(linearVelocity.y);
75
22
  const reactionForceValue = mass * this.gravity;
76
- const dragForceValue = -1 * drag * reactionForceValue;
23
+ const dragForceValue = -1 * linearDamping * reactionForceValue;
77
24
  const forceToVelocityMultiplier = deltaTime / mass;
78
25
  const slowdownValue = dragForceValue * forceToVelocityMultiplier;
79
- const normalizationMultiplier = 1 / velocity.magnitude;
80
- const slowdown = velocity.clone();
81
- slowdown.multiplyNumber(slowdownValue * normalizationMultiplier);
82
- velocity.add(slowdown);
83
- if (Math.sign(velocity.x) !== velocitySignX &&
84
- Math.sign(velocity.y) !== velocitySignY) {
85
- velocity.multiplyNumber(0);
26
+ const normalizationMultiplier = 1 / linearVelocity.magnitude;
27
+ const slowdownMultiplier = slowdownValue * normalizationMultiplier;
28
+ linearVelocity.x += linearVelocity.x * slowdownMultiplier;
29
+ linearVelocity.y += linearVelocity.y * slowdownMultiplier;
30
+ if (Math.sign(linearVelocity.x) !== velocitySignX &&
31
+ Math.sign(linearVelocity.y) !== velocitySignY) {
32
+ linearVelocity.multiplyNumber(0);
86
33
  }
87
34
  }
88
- getGravityForce(rigidBody) {
89
- const { mass, useGravity } = rigidBody;
90
- const gravityVector = new Vector2(0, 0);
91
- if (useGravity) {
92
- gravityVector.add(DIRECTION_VECTOR.DOWN);
93
- gravityVector.multiplyNumber(mass * this.gravity);
94
- }
95
- return gravityVector;
96
- }
97
- update(options) {
98
- const { deltaTime } = options;
99
- const deltaTimeInMsec = deltaTime;
100
- const deltaTimeInSeconds = deltaTimeInMsec / 1000;
35
+ integrateVelocities(deltaTimeInSeconds) {
101
36
  this.actorQuery.getActors().forEach((actor) => {
102
37
  const rigidBody = actor.getComponent(RigidBody);
103
- const transform = actor.getComponent(Transform);
104
- const { mass } = rigidBody;
105
- if (!this.actorVectors[actor.id]) {
106
- this.setUpVectors(actor);
38
+ const { mass, inverseMass } = rigidBody;
39
+ if (rigidBody.disabled || rigidBody.type === 'static' || mass <= 0) {
40
+ rigidBody.clearForces();
41
+ return;
42
+ }
43
+ const { force, impulse } = rigidBody;
44
+ const velocity = rigidBody.linearVelocity;
45
+ if (rigidBody.sleeping) {
46
+ if (force.x || force.y || impulse.x || impulse.y) {
47
+ rigidBody.wakeUp();
48
+ }
49
+ else {
50
+ return;
51
+ }
52
+ }
53
+ if (rigidBody.gravityScale) {
54
+ force.y += mass * this.gravity * rigidBody.gravityScale;
107
55
  }
108
- const { velocity, force, impulse } = this.actorVectors[actor.id];
109
- force.add(this.getGravityForce(rigidBody));
110
56
  if (force.x || force.y) {
111
- force.multiplyNumber(deltaTimeInSeconds / mass);
57
+ force.multiplyNumber(deltaTimeInSeconds * inverseMass);
112
58
  velocity.add(force);
113
59
  }
114
60
  if (impulse.x || impulse.y) {
115
- impulse.multiplyNumber(1 / mass);
61
+ impulse.multiplyNumber(inverseMass);
116
62
  velocity.add(impulse);
117
63
  }
118
- this.applyDragForce(actor, deltaTimeInSeconds);
119
- transform.world.position.x += velocity.x * deltaTimeInSeconds;
120
- transform.world.position.y += velocity.y * deltaTimeInSeconds;
121
- force.multiplyNumber(0);
122
- impulse.multiplyNumber(0);
64
+ this.applyLinearDamping(rigidBody, deltaTimeInSeconds);
65
+ rigidBody.clearForces();
123
66
  });
124
67
  }
68
+ integratePositions(deltaTimeInSeconds) {
69
+ this.actorQuery.getActors().forEach((actor) => {
70
+ const rigidBody = actor.getComponent(RigidBody);
71
+ const transform = actor.getComponent(Transform);
72
+ if (rigidBody.disabled ||
73
+ rigidBody.type === 'static' ||
74
+ rigidBody.mass <= 0 ||
75
+ rigidBody.sleeping) {
76
+ return;
77
+ }
78
+ transform.world.position.x +=
79
+ rigidBody.linearVelocity.x * deltaTimeInSeconds;
80
+ transform.world.position.y +=
81
+ rigidBody.linearVelocity.y * deltaTimeInSeconds;
82
+ });
83
+ }
84
+ update(options) {
85
+ const deltaTimeInSeconds = options.deltaTime / 1000;
86
+ this.integrateVelocities(deltaTimeInSeconds);
87
+ this.integratePositions(deltaTimeInSeconds);
88
+ }
125
89
  }
@@ -1,4 +1,41 @@
1
1
  import type { SceneSystemOptions } from '../../../engine/system';
2
+ import type { Actor } from '../../../engine/actor';
3
+ import type { Vector2, Point } from '../../../engine/math-lib';
2
4
  export interface PhysicsSystemOptions extends SceneSystemOptions {
3
5
  gravity: number;
4
6
  }
7
+ export interface CollisionLayer {
8
+ id: string;
9
+ name: string;
10
+ }
11
+ export type CollisionMatrix = Record<string, Record<string, boolean>>;
12
+ export interface PhysicsSettings {
13
+ collisionLayers: CollisionLayer[];
14
+ collisionMatrix: CollisionMatrix;
15
+ }
16
+ export interface PhysicsQueryFilter {
17
+ layer?: string;
18
+ }
19
+ export interface RaycastParams extends PhysicsQueryFilter {
20
+ origin: Point;
21
+ direction: Vector2;
22
+ maxDistance: number;
23
+ }
24
+ export interface RaycastHit {
25
+ actor: Actor;
26
+ point: Point;
27
+ normal: Vector2;
28
+ distance: number;
29
+ }
30
+ export interface OverlapPointParams extends PhysicsQueryFilter {
31
+ point: Point;
32
+ }
33
+ export interface OverlapCircleParams extends PhysicsQueryFilter {
34
+ center: Point;
35
+ radius: number;
36
+ }
37
+ export interface OverlapBoxParams extends PhysicsQueryFilter {
38
+ center: Point;
39
+ size: Point;
40
+ rotation?: number;
41
+ }
@@ -108,8 +108,6 @@ export class ActorRenderTree {
108
108
  container.addChild(view);
109
109
  }
110
110
  });
111
- this.updateParent(container, actor);
112
- this.updatePosition(container, actor);
113
111
  return container;
114
112
  }
115
113
  delete(actor) {
@@ -178,6 +176,7 @@ export class ActorRenderTree {
178
176
  renderLayer?.attach(view);
179
177
  meta.sortingLayer = sortingLayer;
180
178
  }
179
+ view.__dacha.isReady = true;
181
180
  });
182
181
  }
183
182
  update() {
@@ -6,7 +6,7 @@ import type { FilterSystem } from '../filters';
6
6
  import type { FilterEffectConfig } from '../filters/filter-effect';
7
7
  import type { MaterialSystem } from '../material';
8
8
  import type { ShaderConstructor } from '../material/shader';
9
- interface RendererServiceOptions {
9
+ interface RendererAPIOptions {
10
10
  application: Application;
11
11
  worldContainer: Container;
12
12
  getViewEntries: () => Set<ViewContainer> | undefined;
@@ -15,21 +15,21 @@ interface RendererServiceOptions {
15
15
  materialSystem: MaterialSystem;
16
16
  }
17
17
  /**
18
- * Service that provides rendering utilities and view management
18
+ * API that provides rendering utilities and view management
19
19
  *
20
20
  * Offers methods for view intersection testing, bounds calculation, and
21
21
  * direct access to the underlying PIXI.js application
22
22
  *
23
23
  * @category Systems
24
24
  */
25
- export declare class RendererService {
25
+ export declare class RendererAPI {
26
26
  private application;
27
27
  private worldContainer;
28
28
  private getViewEntries;
29
29
  private sortFn;
30
30
  private filterSystem;
31
31
  private materialSystem;
32
- constructor({ application, worldContainer, getViewEntries, sortFn, filterSystem, materialSystem, }: RendererServiceOptions);
32
+ constructor({ application, worldContainer, getViewEntries, sortFn, filterSystem, materialSystem, }: RendererAPIOptions);
33
33
  /**
34
34
  * Returns the underlying PIXI.js application
35
35
  *
@@ -61,9 +61,9 @@ export declare class RendererService {
61
61
  * the bounds will be the smallest rectangle that contains all views
62
62
  *
63
63
  * @param actor - Actor to get the bounds of
64
- * @returns Bounds of the actor
64
+ * @returns Bounds of the actor or null if the actor has no available views
65
65
  */
66
- getBounds(actor: Actor): Bounds;
66
+ getBounds(actor: Actor): Bounds | null;
67
67
  /**
68
68
  * Adds a post-processing effect that applies to the entire scene.
69
69
  * Effects are applied in the order they are added.
@@ -1,15 +1,14 @@
1
- import { Transform } from '../../../components/transform';
2
1
  import { VIEW_COMPONENTS } from '../consts';
3
- import { convertBounds } from './utils';
2
+ import { convertBounds, getWorldPosition } from './utils';
4
3
  /**
5
- * Service that provides rendering utilities and view management
4
+ * API that provides rendering utilities and view management
6
5
  *
7
6
  * Offers methods for view intersection testing, bounds calculation, and
8
7
  * direct access to the underlying PIXI.js application
9
8
  *
10
9
  * @category Systems
11
10
  */
12
- export class RendererService {
11
+ export class RendererAPI {
13
12
  application;
14
13
  worldContainer;
15
14
  getViewEntries;
@@ -43,6 +42,9 @@ export class RendererService {
43
42
  const intersects = new Set();
44
43
  const inverseMatrix = this.worldContainer.worldTransform.clone().invert();
45
44
  this.getViewEntries()?.forEach((entry) => {
45
+ if (!entry.__dacha.isReady) {
46
+ return;
47
+ }
46
48
  const { minX, minY, maxX, maxY } = convertBounds(entry, inverseMatrix);
47
49
  if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
48
50
  intersects.add(entry);
@@ -67,8 +69,12 @@ export class RendererService {
67
69
  */
68
70
  intersectsWithRectangle(minX, minY, maxX, maxY) {
69
71
  const actors = new Set();
72
+ const inverseMatrix = this.worldContainer.worldTransform.clone().invert();
70
73
  this.getViewEntries()?.forEach((entry) => {
71
- const { x, y } = entry.position;
74
+ if (!entry.__dacha.isReady) {
75
+ return;
76
+ }
77
+ const { x, y } = getWorldPosition(entry, inverseMatrix);
72
78
  if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
73
79
  actors.add(entry.__dacha.actor);
74
80
  }
@@ -81,10 +87,9 @@ export class RendererService {
81
87
  * the bounds will be the smallest rectangle that contains all views
82
88
  *
83
89
  * @param actor - Actor to get the bounds of
84
- * @returns Bounds of the actor
90
+ * @returns Bounds of the actor or null if the actor has no available views
85
91
  */
86
92
  getBounds(actor) {
87
- const { world } = actor.getComponent(Transform);
88
93
  let minX = Infinity;
89
94
  let minY = Infinity;
90
95
  let maxX = -Infinity;
@@ -92,7 +97,7 @@ export class RendererService {
92
97
  const inverseMatrix = this.worldContainer.worldTransform.clone().invert();
93
98
  VIEW_COMPONENTS.forEach((ViewComponent) => {
94
99
  const viewComponent = actor.getComponent(ViewComponent);
95
- if (!viewComponent?.renderData?.view) {
100
+ if (!viewComponent?.renderData?.view?.__dacha.isReady) {
96
101
  return;
97
102
  }
98
103
  const bounds = convertBounds(viewComponent.renderData.view, inverseMatrix);
@@ -102,14 +107,7 @@ export class RendererService {
102
107
  maxY = Math.max(maxY, bounds?.maxY);
103
108
  });
104
109
  if (minX === Infinity) {
105
- return {
106
- minX: world.position.x,
107
- minY: world.position.y,
108
- maxX: world.position.x,
109
- maxY: world.position.y,
110
- width: 0,
111
- height: 0,
112
- };
110
+ return null;
113
111
  }
114
112
  return {
115
113
  minX,
@@ -0,0 +1,4 @@
1
+ import { type Container, Point, type Matrix } from 'pixi.js';
2
+ import { type Bounds } from '../types';
3
+ export declare const convertBounds: (container: Container, matrix: Matrix) => Bounds;
4
+ export declare const getWorldPosition: (container: Container, matrix: Matrix) => Point;
@@ -12,3 +12,8 @@ export const convertBounds = (container, matrix) => {
12
12
  height: bottomRight.y - topLeft.y,
13
13
  };
14
14
  };
15
+ export const getWorldPosition = (container, matrix) => {
16
+ const worldPoint = new Point();
17
+ container.getGlobalPosition(worldPoint, true);
18
+ return matrix.apply(worldPoint);
19
+ };