@safe-engine/pixi 8.3.7 → 8.4.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 (139) hide show
  1. package/.github/workflows/npm-publish.yml +35 -0
  2. package/README.md +70 -5
  3. package/dist/app.d.ts +2 -5
  4. package/dist/app.d.ts.map +1 -1
  5. package/dist/app.js +44 -27
  6. package/dist/base/gworld.d.ts +2 -0
  7. package/dist/base/gworld.d.ts.map +1 -1
  8. package/dist/box2d-wasm/ContactListener.d.ts +12 -0
  9. package/dist/box2d-wasm/ContactListener.d.ts.map +1 -0
  10. package/dist/box2d-wasm/ContactListener.js +64 -0
  11. package/dist/box2d-wasm/PhysicsComponent.d.ts +50 -0
  12. package/dist/box2d-wasm/PhysicsComponent.d.ts.map +1 -0
  13. package/dist/box2d-wasm/PhysicsComponent.js +17 -0
  14. package/dist/box2d-wasm/PhysicsSprite.d.ts +11 -0
  15. package/dist/box2d-wasm/PhysicsSprite.d.ts.map +1 -0
  16. package/dist/box2d-wasm/PhysicsSprite.js +30 -0
  17. package/dist/box2d-wasm/PhysicsSystem.d.ts +17 -0
  18. package/dist/box2d-wasm/PhysicsSystem.d.ts.map +1 -0
  19. package/dist/box2d-wasm/PhysicsSystem.js +145 -0
  20. package/dist/box2d-wasm/debugDraw.d.ts +67 -0
  21. package/dist/box2d-wasm/debugDraw.d.ts.map +1 -0
  22. package/dist/box2d-wasm/debugDraw.js +224 -0
  23. package/dist/box2d-wasm/index.d.ts +6 -0
  24. package/dist/box2d-wasm/index.d.ts.map +1 -0
  25. package/dist/box2d-wasm/index.js +17 -0
  26. package/dist/collider/CollideComponent.d.ts.map +1 -1
  27. package/dist/collider/CollideComponent.js +12 -13
  28. package/dist/collider/CollideSystem.d.ts.map +1 -1
  29. package/dist/collider/CollideSystem.js +1 -2
  30. package/dist/collider/helper/utils.d.ts +2 -0
  31. package/dist/collider/helper/utils.d.ts.map +1 -1
  32. package/dist/collider/helper/utils.js +22 -0
  33. package/dist/collider/index.d.ts +1 -0
  34. package/dist/collider/index.d.ts.map +1 -1
  35. package/dist/collider/index.js +12 -0
  36. package/dist/components/NodeComp.d.ts +6 -4
  37. package/dist/components/NodeComp.d.ts.map +1 -1
  38. package/dist/components/NodeComp.js +13 -13
  39. package/dist/components/Scene.d.ts.map +1 -1
  40. package/dist/components/Scene.js +3 -4
  41. package/dist/core/director.d.ts.map +1 -1
  42. package/dist/core/director.js +4 -3
  43. package/dist/dragonbones/DragonBonesSystem.d.ts +2 -1
  44. package/dist/dragonbones/DragonBonesSystem.d.ts.map +1 -1
  45. package/dist/dragonbones/DragonBonesSystem.js +2 -0
  46. package/dist/dragonbones/index.d.ts +1 -0
  47. package/dist/dragonbones/index.d.ts.map +1 -1
  48. package/dist/dragonbones/index.js +7 -0
  49. package/dist/gui/GUIComponent.d.ts +0 -9
  50. package/dist/gui/GUIComponent.d.ts.map +1 -1
  51. package/dist/gui/GUIComponent.js +0 -37
  52. package/dist/gui/GUISystem.d.ts +1 -0
  53. package/dist/gui/GUISystem.d.ts.map +1 -1
  54. package/dist/gui/GUISystem.js +2 -15
  55. package/dist/index.d.ts +1 -0
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +1 -0
  58. package/dist/planck/PhysicsComponent.d.ts +7 -7
  59. package/dist/planck/PhysicsComponent.js +4 -4
  60. package/dist/planck/PhysicsSystem.js +12 -12
  61. package/dist/richtext/RichTextComp.d.ts +17 -0
  62. package/dist/richtext/RichTextComp.d.ts.map +1 -0
  63. package/dist/richtext/RichTextComp.js +38 -0
  64. package/dist/richtext/RichTextSystem.d.ts +7 -0
  65. package/dist/richtext/RichTextSystem.d.ts.map +1 -0
  66. package/dist/richtext/RichTextSystem.js +25 -0
  67. package/dist/richtext/html-text-parser.d.ts +20 -0
  68. package/dist/richtext/html-text-parser.d.ts.map +1 -0
  69. package/dist/richtext/html-text-parser.js +64 -0
  70. package/dist/richtext/index.d.ts +3 -0
  71. package/dist/richtext/index.d.ts.map +1 -0
  72. package/dist/richtext/index.js +7 -0
  73. package/dist/spine/index.d.ts +1 -0
  74. package/dist/spine/index.d.ts.map +1 -1
  75. package/dist/spine/index.js +7 -0
  76. package/package.json +9 -11
  77. package/src/@types/index.d.ts +2 -0
  78. package/src/@types/safex.d.ts +15 -0
  79. package/src/app.ts +85 -0
  80. package/src/base/EnhancedComponent.ts +37 -0
  81. package/src/base/gworld.ts +19 -0
  82. package/src/base/index.ts +3 -0
  83. package/src/base/utils.ts +23 -0
  84. package/src/box2d-wasm/ContactListener.ts +66 -0
  85. package/src/box2d-wasm/PhysicsComponent.ts +83 -0
  86. package/src/box2d-wasm/PhysicsSprite.ts +42 -0
  87. package/src/box2d-wasm/PhysicsSystem.ts +145 -0
  88. package/src/box2d-wasm/debugDraw.ts +257 -0
  89. package/src/box2d-wasm/index.ts +19 -0
  90. package/src/collider/CollideComponent.ts +257 -0
  91. package/src/collider/CollideSystem.ts +166 -0
  92. package/src/collider/helper/Intersection.ts +139 -0
  93. package/src/collider/helper/utils.ts +37 -0
  94. package/src/collider/index.ts +16 -0
  95. package/src/components/BaseComponent.ts +17 -0
  96. package/src/components/NodeComp.ts +434 -0
  97. package/src/components/Scene.ts +17 -0
  98. package/src/core/Color.ts +7 -0
  99. package/src/core/LoadingBar.ts +63 -0
  100. package/src/core/NodePool.ts +28 -0
  101. package/src/core/Size.ts +21 -0
  102. package/src/core/director.ts +11 -0
  103. package/src/core/math.ts +13 -0
  104. package/src/dragonbones/DragonBonesComponent.ts +32 -0
  105. package/src/dragonbones/DragonBonesSystem.ts +35 -0
  106. package/src/dragonbones/index.ts +11 -0
  107. package/src/gui/GUIComponent.ts +159 -0
  108. package/src/gui/GUISystem.ts +116 -0
  109. package/src/helper/utils.ts +50 -0
  110. package/src/index.ts +23 -0
  111. package/src/norender/NoRenderComponent.ts +60 -0
  112. package/src/norender/NoRenderSystem.ts +66 -0
  113. package/src/planck/PhysicsComponent.ts +83 -0
  114. package/src/planck/PhysicsSprite.ts +43 -0
  115. package/src/planck/PhysicsSystem.ts +201 -0
  116. package/src/planck/index.ts +3 -0
  117. package/src/render/RenderComponent.ts +138 -0
  118. package/src/render/RenderSystem.ts +67 -0
  119. package/src/richtext/RichTextComp.ts +46 -0
  120. package/src/richtext/RichTextSystem.ts +26 -0
  121. package/src/richtext/html-text-parser.ts +87 -0
  122. package/src/richtext/index.ts +8 -0
  123. package/src/spine/SpineComponent.ts +18 -0
  124. package/src/spine/SpineSystem.ts +30 -0
  125. package/src/spine/index.ts +11 -0
  126. package/src/spine/lib/BatchableSpineSlot.ts +138 -0
  127. package/src/spine/lib/Spine.ts +910 -0
  128. package/src/spine/lib/SpineDebugRenderer.ts +615 -0
  129. package/src/spine/lib/SpinePipe.ts +203 -0
  130. package/src/spine/lib/SpineTexture.ts +143 -0
  131. package/src/spine/lib/assets/atlasLoader.ts +158 -0
  132. package/src/spine/lib/assets/skeletonLoader.ts +81 -0
  133. package/src/spine/lib/darktint/DarkTintBatchGeometry.ts +92 -0
  134. package/src/spine/lib/darktint/DarkTintBatcher.ts +186 -0
  135. package/src/spine/lib/darktint/DarkTintShader.ts +74 -0
  136. package/src/spine/lib/darktint/darkTintBit.ts +77 -0
  137. package/src/spine/lib/index.ts +43 -0
  138. package/src/spine/lib/require-shim.ts +43 -0
  139. package/tsconfig.json +18 -0
@@ -0,0 +1,35 @@
1
+ # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3
+
4
+ name: Publish NPM Package
5
+
6
+ on:
7
+ release:
8
+ types: [created]
9
+ workflow_dispatch: # Allows you to run this workflow manually
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-node@v3
17
+ with:
18
+ node-version: 20
19
+ - run: npm ci
20
+ - run: npm run build
21
+
22
+ publish-npm:
23
+ needs: build
24
+ runs-on: ubuntu-latest
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ - uses: actions/setup-node@v3
28
+ with:
29
+ node-version: 20
30
+ registry-url: https://registry.npmjs.org/
31
+ - run: npm ci
32
+ - run: npm run build
33
+ - run: npm publish
34
+ env:
35
+ NODE_AUTH_TOKEN: ${{secrets.npm_token}}
package/README.md CHANGED
@@ -16,8 +16,8 @@ Safex is an open-source game engine written in TypeScript, combining the power o
16
16
  - Example `<SpriteRender node={{ x: 5, y: 9 }} />`
17
17
  - `$ref` bind component with current class property as string
18
18
  - `$push` push component to list
19
- - `Array(2).map(_, i)` iteration repeat component 2 times
20
- - `Loading.listItems.map(item, i)` iteration in static property
19
+ - `Array(2).map(i)` iteration repeat component 2 times
20
+ - `Loading.listItems.map(item, i = 1)` iteration in static property
21
21
  - `listItems.map(item, i)` iteration in const variable
22
22
 
23
23
  ## Benefits
@@ -32,10 +32,16 @@ Safex is an open-source game engine written in TypeScript, combining the power o
32
32
  npm install @safe-engine/pixi
33
33
  ```
34
34
 
35
+ # Quick start
36
+
37
+ ```sh
38
+ git clone https://github.com/Safe-engine/pixi-safe-engine-demo
39
+ ```
40
+
35
41
  ## Basic Example
36
42
 
37
43
  ```tsx game.ts
38
- import { addGameCanvasTo, loadScene, startGameSystems } from '@safe-engine/pixi'
44
+ import { addGameCanvasTo, loadScene, startGameSystems } from 'safex'
39
45
  async function start() {
40
46
  await addGameCanvasTo('canvasId')
41
47
  startGameSystems()
@@ -45,19 +51,35 @@ start()
45
51
  ```
46
52
 
47
53
  ```tsx GameScene.tsx
48
- import { SceneComponent, LabelComp, ButtonComp, SpriteRender } from '@safe-engine/pixi'
54
+ import { SceneComponent, LabelComp, ButtonComp, SpriteRender, instantiate } from 'safex'
55
+ import ColliderSprite from './ColliderSprite'
49
56
 
50
57
  export class GameScene extends ComponentX {
51
58
  sprite: SpriteRender
59
+ label: LabelComp
52
60
 
53
61
  onPress() {
54
62
  this.sprite.spriteFrame = 'other.sprite.png'
63
+ this.label.string = 'Pressed'
64
+ }
65
+
66
+ onTouchMove(event: FederatedPointerEvent) {
67
+ console.log('onTouchMove', event.global)
68
+ const sprite = instantiate(ColliderSprite)
69
+ sprite.node.x = event.global.x
70
+ sprite.node.y = event.global.y
71
+ this.node.addChild(sprite)
55
72
  }
56
73
 
57
74
  render() {
58
75
  return (
59
76
  <SceneComponent>
60
- <LabelComp node={{ x: 106, y: 240 }} string="Hello safex" font={defaultFont} />
77
+ <TouchEventRegister
78
+ // onTouchStart={this.onTouchStart}
79
+ // onTouchEnd={this.onTouchEnd}
80
+ onTouchMove={this.onTouchMove}
81
+ />
82
+ <LabelComp $ref={this.label} node={{ x: 106, y: 240 }} string="Hello safex" font={defaultFont} />
61
83
  <SpriteRender $ref={this.sprite} node={{ x: 500, y: 600 }} spriteFrame={'path/to/sprite.png'}>
62
84
  <ButtonComp onPress={this.onPress} />
63
85
  </SpriteRender>
@@ -67,6 +89,49 @@ export class GameScene extends ComponentX {
67
89
  }
68
90
  ```
69
91
 
92
+ ## Collider Events
93
+
94
+ ```tsx
95
+ import { BoxCollider, Collider, ComponentX, SpriteRender } from 'safex'
96
+ import { sf_crash } from '../assets'
97
+
98
+ export class ColliderSprite extends ComponentX {
99
+ onCollisionEnter(other: Collider) {
100
+ console.log(other.tag)
101
+ }
102
+
103
+ render() {
104
+ return (
105
+ <SpriteRender node={{ x: 640, y: 360 }} spriteFrame={sf_crash}>
106
+ <BoxCollider height={100} width={100}></BoxCollider>
107
+ </SpriteRender>
108
+ )
109
+ }
110
+ }
111
+ ```
112
+
113
+ ## Physics Events
114
+
115
+ ```tsx
116
+ import { PhysicsBoxCollider, PhysicsCollider, RigidBody, ComponentX, SpriteRender } from 'safex'
117
+ import { sf_crash } from '../assets'
118
+
119
+ export class PhysicsCollider extends ComponentX {
120
+ onCollisionEnter(col: PhysicsCollider) {
121
+ console.log('onCollisionEnter', col)
122
+ }
123
+
124
+ render() {
125
+ return (
126
+ <SpriteRender node={{ x: 640, y: 360 }} spriteFrame={sf_crash}>
127
+ <RigidBody type="static"></RigidBody>
128
+ <PhysicsBoxCollider height={100} width={100}></PhysicsBoxCollider>
129
+ </SpriteRender>
130
+ )
131
+ }
132
+ }
133
+ ```
134
+
70
135
  ## Contributing
71
136
 
72
137
  We welcome all contributions! If you have ideas or want to improve the engine, feel free to create an issue or submit a pull request on GitHub.
package/dist/app.d.ts CHANGED
@@ -1,9 +1,6 @@
1
1
  import { Application } from 'pixi.js';
2
- export declare const app: Application<import("pixi.js").Renderer>;
3
- export declare function addGameCanvasTo(id?: string): Promise<void>;
4
- export declare function setupResolution(designedResolution?: {
2
+ export declare function startGame(defaultFont: any, designedResolution?: {
5
3
  width: number;
6
4
  height: number;
7
- }): void;
8
- export declare function startGameSystems(list?: any[]): void;
5
+ }, id?: string): Promise<Application<import("pixi.js").Renderer>>;
9
6
  //# sourceMappingURL=app.d.ts.map
package/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AASrC,eAAO,MAAM,GAAG,yCAAoB,CAAA;AAEpC,wBAAsB,eAAe,CAAC,EAAE,SAAS,iBAoBhD;AAED,wBAAgB,eAAe,CAAC,kBAAkB;;;CAA+B,QAKhF;AAaD,wBAAgB,gBAAgB,CAAC,IAAI,QAAK,QAezC"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAQrC,wBAAsB,SAAS,CAAC,WAAW,KAAA,EAAE,kBAAkB;;;CAA+B,EAAE,EAAE,SAAS,oDA6B1G"}
package/dist/app.js CHANGED
@@ -11,14 +11,12 @@ import { actionManager } from 'pixi-action-ease';
11
11
  import { Application } from 'pixi.js';
12
12
  import { GameWorld } from './base';
13
13
  import { CollideSystem } from './collider';
14
- import { DragonBonesSystem } from './dragonbones';
15
14
  import { GUISystem } from './gui/GUISystem';
16
15
  import { NoRenderSystem } from './norender/NoRenderSystem';
17
16
  import { RenderSystem } from './render/RenderSystem';
18
- import { SpineSystem } from './spine';
19
- export const app = new Application();
20
- export function addGameCanvasTo() {
21
- return __awaiter(this, arguments, void 0, function* (id = 'game') {
17
+ export function startGame(defaultFont_1) {
18
+ return __awaiter(this, arguments, void 0, function* (defaultFont, designedResolution = { width: 720, height: 1280 }, id = 'game') {
19
+ const app = new Application();
22
20
  yield app.init({
23
21
  antialias: true,
24
22
  resolution: window.devicePixelRatio,
@@ -38,37 +36,56 @@ export function addGameCanvasTo() {
38
36
  height: `${window.innerHeight}px`,
39
37
  overflow: 'visible',
40
38
  });
39
+ const { width, height } = designedResolution;
40
+ app.renderer.resize(width, height);
41
+ // app.stage.position.y = app.renderer.height / app.renderer.resolution
42
+ // app.stage.scale.y = -1
43
+ GameWorld.Instance.app = app;
44
+ initWorld(defaultFont);
45
+ startGameLoop(GameWorld.Instance);
46
+ return app;
41
47
  });
42
48
  }
43
- export function setupResolution(designedResolution = { width: 720, height: 1280 }) {
44
- const { width, height } = designedResolution;
45
- app.renderer.resize(width, height);
46
- // app.stage.position.y = app.renderer.height / app.renderer.resolution
47
- // app.stage.scale.y = -1
48
- }
49
49
  function startGameLoop(world) {
50
50
  // Listen for frame updates
51
- app.ticker.add(() => {
52
- const dt = app.ticker.deltaMS * 0.001;
51
+ world.app.ticker.add(() => {
52
+ const dt = world.app.ticker.deltaMS * 0.001;
53
53
  actionManager.update(dt);
54
54
  world.update(dt);
55
55
  });
56
56
  // app.ticker.speed = 0.5
57
57
  }
58
- const systemsList = [RenderSystem, GUISystem, SpineSystem, DragonBonesSystem, CollideSystem, NoRenderSystem];
59
- export function startGameSystems(list = []) {
58
+ // const systemsList = [RenderSystem, GUISystem, SpineSystem, DragonBonesSystem, CollideSystem, NoRenderSystem]
59
+ // export function startGameSystems(list = []) {
60
+ // const world = GameWorld.Instance
61
+ // systemsList.forEach(system => {
62
+ // world.systems.add(system)
63
+ // world.systems.configureOnce(system)
64
+ // })
65
+ // world.listUpdate.push(CollideSystem)
66
+ // // world.listUpdate.push(PhysicsSystem)
67
+ // list.forEach(system => {
68
+ // world.systems.add(system)
69
+ // world.systems.configureOnce(system)
70
+ // world.listUpdate.push(system)
71
+ // })
72
+ // startGameLoop(world)
73
+ // // console.log('startGameLoop', world.listUpdate)
74
+ // }
75
+ function initWorld(defaultFont) {
60
76
  const world = GameWorld.Instance;
61
- systemsList.forEach(system => {
62
- world.systems.add(system);
63
- world.systems.configureOnce(system);
64
- });
77
+ world.systems.add(RenderSystem);
78
+ world.systems.add(CollideSystem);
79
+ world.systems.add(GUISystem);
80
+ world.systems.add(NoRenderSystem);
65
81
  world.listUpdate.push(CollideSystem);
66
- // world.listUpdate.push(PhysicsSystem)
67
- list.forEach(system => {
68
- world.systems.add(system);
69
- world.systems.configureOnce(system);
70
- world.listUpdate.push(system);
71
- });
72
- startGameLoop(world);
73
- // console.log('startGameLoop', world.listUpdate)
82
+ world.systems.configureOnce(RenderSystem);
83
+ world.systems.configureOnce(CollideSystem);
84
+ world.systems.configureOnce(GUISystem);
85
+ world.systems.configureOnce(NoRenderSystem);
86
+ if (defaultFont) {
87
+ const guiSystem = world.systems.get(GUISystem);
88
+ guiSystem.defaultFont = defaultFont;
89
+ }
90
+ // startGameLoop(world, app)
74
91
  }
@@ -1,6 +1,8 @@
1
1
  import { Constructor, System, World } from 'entityx-ts';
2
+ import { Application } from 'pixi.js';
2
3
  export declare class GameWorld extends World {
3
4
  listUpdate: (System | Constructor<System>)[];
5
+ app: Application;
4
6
  update(dt: number): void;
5
7
  private static _instance;
6
8
  static get Instance(): GameWorld;
@@ -1 +1 @@
1
- {"version":3,"file":"gworld.d.ts","sourceRoot":"","sources":["../../src/base/gworld.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEvD,qBAAa,SAAU,SAAQ,KAAK;IAClC,UAAU,EAAE,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,CAAK;IACjD,MAAM,CAAC,EAAE,EAAE,MAAM;IAMjB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAW;IAEnC,WAAkB,QAAQ,cAGzB;CACF"}
1
+ {"version":3,"file":"gworld.d.ts","sourceRoot":"","sources":["../../src/base/gworld.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAErC,qBAAa,SAAU,SAAQ,KAAK;IAClC,UAAU,EAAE,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,CAAK;IACjD,GAAG,EAAE,WAAW,CAAA;IAChB,MAAM,CAAC,EAAE,EAAE,MAAM;IAMjB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAW;IAEnC,WAAkB,QAAQ,cAGzB;CACF"}
@@ -0,0 +1,12 @@
1
+ import { NodeComp } from "..";
2
+ type Meta = {
3
+ [key: number]: NodeComp;
4
+ };
5
+ export declare const makeContactListener: (world: Box2D.b2World, metadata: Meta, box2D: typeof Box2D) => Box2D.JSContactListener & {
6
+ BeginContact(contact: Box2D.b2Contact | number): void;
7
+ EndContact(contact: Box2D.b2Contact | number): void;
8
+ PreSolve(contact: Box2D.b2Contact | number, oldManifold: Box2D.b2Manifold | number): void;
9
+ PostSolve(contact: Box2D.b2Contact | number, impulse: Box2D.b2ContactImpulse | number): void;
10
+ };
11
+ export {};
12
+ //# sourceMappingURL=ContactListener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContactListener.d.ts","sourceRoot":"","sources":["../../src/box2d-wasm/ContactListener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAE9B,KAAK,IAAI,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,CAAA;AACvC,eAAO,MAAM,mBAAmB,GAAI,OAAO,KAAK,CAAC,OAAO,EAAE,UAAU,IAAI,EAAE,OAAO,OAAO,KAAK;0BAWnE,KAAK,CAAC,SAAS,GAAG,MAAM,GAAG,IAAI;wBAwBjC,KAAK,CAAC,SAAS,GAAG,MAAM,GAAG,IAAI;sBAmBjC,KAAK,CAAC,SAAS,GAAG,MAAM,eAAe,KAAK,CAAC,UAAU,GAAG,MAAM,GAAG,IAAI;uBAGtE,KAAK,CAAC,SAAS,GAAG,MAAM,WAAW,KAAK,CAAC,gBAAgB,GAAG,MAAM,GAAG,IAAI;CAK/F,CAAA"}
@@ -0,0 +1,64 @@
1
+ import { ColliderPhysics } from "./PhysicsComponent";
2
+ export const makeContactListener = (world, metadata, box2D) => {
3
+ const { JSContactListener, getPointer, NULL } = box2D;
4
+ function getContactById(contact) {
5
+ for (let contactList = world.GetContactList(); getPointer(contactList) !== getPointer(NULL); contactList = contactList.GetNext()) {
6
+ if (getPointer(contactList) === contact) {
7
+ console.log('contactBegin', contact, getPointer(contactList), getPointer(NULL));
8
+ return contactList;
9
+ }
10
+ }
11
+ }
12
+ const listener = Object.assign(new JSContactListener(), {
13
+ BeginContact(contact) {
14
+ if (typeof contact === 'number') {
15
+ contact = getContactById(contact);
16
+ }
17
+ const ett1 = metadata[getPointer(contact.GetFixtureA().GetBody())];
18
+ const ett2 = metadata[getPointer(contact.GetFixtureB().GetBody())];
19
+ // world.addPostStepCallback(() => {
20
+ // // log('addPostStepCallback');
21
+ // listRemoveShape.forEach((s) => world.removeShape(s))
22
+ // listRemoveBody.forEach((b) => world.removeBody(b))
23
+ // listRemoveBody = []
24
+ // listRemoveShape = []
25
+ // })
26
+ const phys1 = ett1.getComponent(ColliderPhysics);
27
+ const phys2 = ett2.getComponent(ColliderPhysics);
28
+ if (phys1 && phys2) {
29
+ if (Object.prototype.hasOwnProperty.call(phys1, 'onCollisionEnter')) {
30
+ phys1.props.onCollisionEnter(phys2);
31
+ }
32
+ if (Object.prototype.hasOwnProperty.call(phys2, 'onCollisionEnter')) {
33
+ phys2.props.onCollisionEnter(phys1);
34
+ }
35
+ }
36
+ },
37
+ EndContact(contact) {
38
+ if (typeof contact === 'number') {
39
+ contact = getContactById(contact);
40
+ }
41
+ const ett1 = metadata[getPointer(contact.GetFixtureA().GetBody())];
42
+ const ett2 = metadata[getPointer(contact.GetFixtureB().GetBody())];
43
+ // const event1 = ett1.getComponent(NodeComp)
44
+ const phys1 = ett1.getComponent(ColliderPhysics);
45
+ const phys2 = ett2.getComponent(ColliderPhysics);
46
+ // const event2 = ett2.getComponent(NodeComp)
47
+ if (phys1 && phys2) {
48
+ if (Object.prototype.hasOwnProperty.call(phys1, 'onCollisionExit')) {
49
+ phys1.props.onCollisionExit(phys2);
50
+ }
51
+ if (Object.prototype.hasOwnProperty.call(phys2, 'onCollisionExit')) {
52
+ phys2.props.onCollisionExit(phys1);
53
+ }
54
+ }
55
+ },
56
+ PreSolve(contact, oldManifold) {
57
+ console.log('collisionSeparate');
58
+ },
59
+ PostSolve(contact, impulse) {
60
+ console.log('collisionPost');
61
+ }
62
+ });
63
+ return listener;
64
+ };
@@ -0,0 +1,50 @@
1
+ import { BodyType, Vec2 } from 'planck';
2
+ import { NoRenderComponentX } from '..';
3
+ import { PhysicsSprite } from './PhysicsSprite';
4
+ interface RigidBodyProps {
5
+ type?: BodyType;
6
+ density?: Float;
7
+ restitution?: Float;
8
+ friction?: Float;
9
+ gravityScale?: Float;
10
+ }
11
+ export declare class RigidBody extends NoRenderComponentX<RigidBodyProps> {
12
+ body: Box2D.b2Body;
13
+ }
14
+ interface PhysicsMaterialProps {
15
+ friction?: number;
16
+ restitution?: number;
17
+ density?: number;
18
+ }
19
+ export declare class PhysicsMaterial extends NoRenderComponentX<PhysicsMaterialProps> {
20
+ }
21
+ interface ColliderPhysicsProps {
22
+ tag?: number;
23
+ group?: number;
24
+ offset?: Vec2;
25
+ onCollisionEnter?: (other: ColliderPhysics) => void;
26
+ onCollisionExit?: (other: ColliderPhysics) => void;
27
+ onCollisionStay?: (other: ColliderPhysics) => void;
28
+ }
29
+ export declare class ColliderPhysics<T extends ColliderPhysicsProps = ColliderPhysicsProps> extends NoRenderComponentX<T, PhysicsSprite['node']> {
30
+ enabled: boolean;
31
+ instance: PhysicsSprite;
32
+ }
33
+ interface BoxColliderPhysicsProps extends ColliderPhysicsProps {
34
+ width: number;
35
+ height: number;
36
+ }
37
+ export declare class BoxColliderPhysics extends ColliderPhysics<BoxColliderPhysicsProps> {
38
+ }
39
+ interface CircleColliderPhysicsProps extends ColliderPhysicsProps {
40
+ radius: number;
41
+ }
42
+ export declare class CircleColliderPhysics extends ColliderPhysics<CircleColliderPhysicsProps> {
43
+ }
44
+ interface PolygonColliderPhysicsProps extends ColliderPhysicsProps {
45
+ points: Array<Vec2>;
46
+ }
47
+ export declare class PolygonColliderPhysics extends ColliderPhysics<PolygonColliderPhysicsProps> {
48
+ }
49
+ export {};
50
+ //# sourceMappingURL=PhysicsComponent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PhysicsComponent.d.ts","sourceRoot":"","sources":["../../src/box2d-wasm/PhysicsComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,IAAI,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE/C,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,OAAO,CAAC,EAAE,KAAK,CAAA;IACf,WAAW,CAAC,EAAE,KAAK,CAAA;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB,YAAY,CAAC,EAAE,KAAK,CAAA;CACrB;AAED,qBAAa,SAAU,SAAQ,kBAAkB,CAAC,cAAc,CAAC;IAC/D,IAAI,EAAE,KAAK,CAAC,MAAM,CAAA;CAmBnB;AAED,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AACD,qBAAa,eAAgB,SAAQ,kBAAkB,CAAC,oBAAoB,CAAC;CAE5E;AAED,UAAU,oBAAoB;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,IAAI,CAAA;IACb,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IACnD,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IAClD,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;CACnD;AAED,qBAAa,eAAe,CAAC,CAAC,SAAS,oBAAoB,GAAG,oBAAoB,CAAE,SAAQ,kBAAkB,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtI,OAAO,UAAO;IACd,QAAQ,EAAE,aAAa,CAAA;CACxB;AAED,UAAU,uBAAwB,SAAQ,oBAAoB;IAC5D,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AACD,qBAAa,kBAAmB,SAAQ,eAAe,CAAC,uBAAuB,CAAC;CAW/E;AACD,UAAU,0BAA2B,SAAQ,oBAAoB;IAC/D,MAAM,EAAE,MAAM,CAAA;CACf;AACD,qBAAa,qBAAsB,SAAQ,eAAe,CAAC,0BAA0B,CAAC;CACrF;AACD,UAAU,2BAA4B,SAAQ,oBAAoB;IAChE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;CACpB;AACD,qBAAa,sBAAuB,SAAQ,eAAe,CAAC,2BAA2B,CAAC;CACvF"}
@@ -0,0 +1,17 @@
1
+ import { NoRenderComponentX } from '..';
2
+ export class RigidBody extends NoRenderComponentX {
3
+ }
4
+ export class PhysicsMaterial extends NoRenderComponentX {
5
+ }
6
+ export class ColliderPhysics extends NoRenderComponentX {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.enabled = true;
10
+ }
11
+ }
12
+ export class BoxColliderPhysics extends ColliderPhysics {
13
+ }
14
+ export class CircleColliderPhysics extends ColliderPhysics {
15
+ }
16
+ export class PolygonColliderPhysics extends ColliderPhysics {
17
+ }
@@ -0,0 +1,11 @@
1
+ import { Container } from 'pixi.js';
2
+ export declare class PhysicsSprite {
3
+ node: Container;
4
+ physicsBody: Box2D.b2Body;
5
+ constructor(node: Container, body: Box2D.b2Body);
6
+ get x(): number;
7
+ get y(): number;
8
+ get angle(): number;
9
+ addChild(child: Container): void;
10
+ }
11
+ //# sourceMappingURL=PhysicsSprite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PhysicsSprite.d.ts","sourceRoot":"","sources":["../../src/box2d-wasm/PhysicsSprite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAEnC,qBAAa,aAAa;IACxB,IAAI,EAAE,SAAS,CAAA;IACf,WAAW,EAAE,KAAK,CAAC,MAAM,CAAA;gBAEb,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM;IAgB/C,IAAI,CAAC,WAEJ;IAED,IAAI,CAAC,WAEJ;IAMD,IAAI,KAAK,WAER;IAED,QAAQ,CAAC,KAAK,EAAE,SAAS;CAG1B"}
@@ -0,0 +1,30 @@
1
+ export class PhysicsSprite {
2
+ constructor(node, body) {
3
+ this.node = node;
4
+ this.physicsBody = body;
5
+ }
6
+ // set position(val: Box2D.b2Vec2) {
7
+ // this.physicsBody.setPosition(val)
8
+ // }
9
+ // set x(val) {
10
+ // this.physicsBody.setPosition(Vec2(val, this.y))
11
+ // }
12
+ // set y(val) {
13
+ // this.physicsBody.setPosition(Vec2(this.x, val))
14
+ // }
15
+ get x() {
16
+ return this.physicsBody.GetPosition().x;
17
+ }
18
+ get y() {
19
+ return this.physicsBody.GetPosition().x;
20
+ }
21
+ // set angle(val: number) {
22
+ // this.physicsBody.setAngle(val)
23
+ // }
24
+ get angle() {
25
+ return this.physicsBody.GetAngle();
26
+ }
27
+ addChild(child) {
28
+ this.node.addChild(child);
29
+ }
30
+ }
@@ -0,0 +1,17 @@
1
+ import { EntityManager, EventManager, System } from 'entityx-ts';
2
+ import { Graphics, Vec2 } from '..';
3
+ export declare let box2D: typeof Box2D;
4
+ export declare function initBox2d(): Promise<void>;
5
+ export declare function setColliderMatrix(colliderMatrix?: boolean[][]): void;
6
+ export declare class PhysicsSystem implements System {
7
+ world: Box2D.b2World;
8
+ listRemoveBody: Body[];
9
+ listRemoveShape: Box2D.b2Shape[];
10
+ colliderMatrix: boolean[][];
11
+ graphics: Graphics;
12
+ addDebug(): void;
13
+ configure(event_manager: EventManager): void;
14
+ update(entities: EntityManager, events: EventManager, dt: number): void;
15
+ set gravity(val: Vec2);
16
+ }
17
+ //# sourceMappingURL=PhysicsSystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PhysicsSystem.d.ts","sourceRoot":"","sources":["../../src/box2d-wasm/PhysicsSystem.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,EACb,YAAY,EAEZ,MAAM,EACP,MAAM,YAAY,CAAC;AACpB,OAAO,EAAa,QAAQ,EAAyB,IAAI,EAAE,MAAM,IAAI,CAAC;AAoBtE,eAAO,IAAI,KAAK,EAAE,OAAO,KAAK,CAAA;AAC9B,wBAAsB,SAAS,kBAE9B;AAED,wBAAgB,iBAAiB,CAAC,cAAc,cAAW,QAG1D;AAOD,qBAAa,aAAc,YAAW,MAAM;IAC1C,KAAK,EAAE,KAAK,CAAC,OAAO,CAAA;IACpB,cAAc,EAAE,IAAI,EAAE,CAAK;IAC3B,eAAe,EAAE,KAAK,CAAC,OAAO,EAAE,CAAK;IACrC,cAAc,cAAW;IACzB,QAAQ,EAAE,QAAQ,CAAA;IAElB,QAAQ;IAKR,SAAS,CAAC,aAAa,EAAE,YAAY;IAyErC,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM;IAYhE,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,EAIpB;CACF"}
@@ -0,0 +1,145 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __rest = (this && this.__rest) || function (s, e) {
11
+ var t = {};
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
13
+ t[p] = s[p];
14
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
15
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
16
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17
+ t[p[i]] = s[p[i]];
18
+ }
19
+ return t;
20
+ };
21
+ import Box2DFactory from 'box2d-wasm';
22
+ import { EventTypes } from 'entityx-ts';
23
+ import { GameWorld, Graphics, instantiate, NodeComp } from '..';
24
+ import { makeContactListener } from './ContactListener';
25
+ import { makeDebugDraw } from './debugDraw';
26
+ import { BoxColliderPhysics, CircleColliderPhysics, ColliderPhysics, PhysicsMaterial, PolygonColliderPhysics, RigidBody, } from './PhysicsComponent';
27
+ import { PhysicsSprite } from './PhysicsSprite';
28
+ // Box2D.b2Fixture.prototype.shouldCollide = function (other) {
29
+ // const nodeThis: NodeComp = this.getBody().getUserData()
30
+ // const nodeOther = other.getBody().getUserData() as NodeComp
31
+ // const { colliderMatrix } = GameWorld.Instance.systems.get(PhysicsSystem)
32
+ // return colliderMatrix[nodeOther.group][nodeThis.group]
33
+ // }
34
+ export let box2D;
35
+ export function initBox2d() {
36
+ return __awaiter(this, void 0, void 0, function* () {
37
+ box2D = yield Box2DFactory();
38
+ });
39
+ }
40
+ export function setColliderMatrix(colliderMatrix = [[true]]) {
41
+ const physicsSystem = GameWorld.Instance.systems.get(PhysicsSystem);
42
+ physicsSystem.colliderMatrix = colliderMatrix;
43
+ }
44
+ const maxTimeStep = 1 / 60;
45
+ const velocityIterations = 1;
46
+ const positionIterations = 1;
47
+ const metadata = {};
48
+ const pixelsPerMeter = 1;
49
+ export class PhysicsSystem {
50
+ constructor() {
51
+ this.listRemoveBody = [];
52
+ this.listRemoveShape = [];
53
+ this.colliderMatrix = [[true]];
54
+ }
55
+ addDebug() {
56
+ const debugDraw = makeDebugDraw(this.graphics, pixelsPerMeter, box2D);
57
+ this.world.SetDebugDraw(debugDraw);
58
+ }
59
+ configure(event_manager) {
60
+ const { b2BodyDef, b2_dynamicBody, b2_staticBody, b2FixtureDef, b2PolygonShape, b2Vec2, b2World, getPointer, b2ContactListener } = box2D;
61
+ const gravity = new b2Vec2(0, 10);
62
+ this.world = new b2World(gravity);
63
+ console.log('configure world', event_manager.world.app);
64
+ // event_manager.world.physicsManager = this
65
+ const graphics = new Graphics();
66
+ this.graphics = graphics;
67
+ graphics.zIndex = 1000;
68
+ event_manager.world.app.stage.addChild(graphics);
69
+ // event_manager.subscribe(ComponentAddedEvent(RigidBody), this);
70
+ event_manager.subscribe(EventTypes.ComponentAdded, BoxColliderPhysics, ({ entity, component }) => {
71
+ console.log('ComponentAddedEvent BoxColliderPhysics', component);
72
+ let rigidBody = entity.getComponent(RigidBody);
73
+ if (!rigidBody) {
74
+ rigidBody = instantiate(RigidBody);
75
+ entity.assign(rigidBody);
76
+ }
77
+ const { type = 'static', gravityScale = 1, } = rigidBody.props;
78
+ const physicsMaterial = entity.getComponent(PhysicsMaterial);
79
+ const { density = 1, friction = 0.5, restitution = 0.3 } = (physicsMaterial === null || physicsMaterial === void 0 ? void 0 : physicsMaterial.props) || {};
80
+ const box = component;
81
+ const node = entity.getComponent(NodeComp);
82
+ const _a = box.props, { width, height } = _a, colliderProps = __rest(_a, ["width", "height"]);
83
+ // ett.assign(instantiate(ColliderPhysics, { tag, offset }))
84
+ const { x = 0, y = 0 } = colliderProps.offset || {};
85
+ const zero = new b2Vec2(0, 0);
86
+ const position = new b2Vec2(node.posX, node.posY);
87
+ const offset = new b2Vec2(x, y);
88
+ const bd = new b2BodyDef();
89
+ bd.set_type(type === 'dynamic' ? b2_dynamicBody : b2_staticBody);
90
+ bd.set_position(zero);
91
+ bd.set_gravityScale(gravityScale);
92
+ const body = this.world.CreateBody(bd);
93
+ rigidBody.body = body;
94
+ // console.log('body', type, b2_dynamicBody, b2_staticBody, getPointer(body));
95
+ // body.setMassData({ mass: 1 } as any)
96
+ const physicsNode = new PhysicsSprite(node.instance, body);
97
+ const square = new b2PolygonShape();
98
+ square.SetAsBox(width / 2, height / 2);
99
+ const fixtureDef = new b2FixtureDef();
100
+ fixtureDef.set_shape(square);
101
+ fixtureDef.set_density(density);
102
+ fixtureDef.set_friction(friction);
103
+ fixtureDef.set_restitution(restitution);
104
+ body.CreateFixture(fixtureDef);
105
+ body.SetTransform(position, 0);
106
+ body.SetLinearVelocity(zero);
107
+ body.SetAwake(true);
108
+ body.SetEnabled(true);
109
+ metadata[getPointer(body)] = node;
110
+ const physicsCollide = entity.assign(instantiate(ColliderPhysics, colliderProps));
111
+ physicsCollide.instance = physicsNode;
112
+ physicsCollide.node = node;
113
+ box.node = node;
114
+ });
115
+ event_manager.subscribe(EventTypes.ComponentAdded, (CircleColliderPhysics), () => { });
116
+ event_manager.subscribe(EventTypes.ComponentAdded, (PolygonColliderPhysics), () => { });
117
+ event_manager.subscribe(EventTypes.ComponentRemoved, (NodeComp), () => {
118
+ // log('ComponentRemovedEvent NodeComp', event);
119
+ // const node = event.entity.getComponent(NodeComp)
120
+ // if (node.instance instanceof Sprite) {
121
+ // const body = node.instance.getBody()
122
+ // this.listRemoveShape.push(...body.shapeList)
123
+ // this.listRemoveBody.push(body)
124
+ // }
125
+ });
126
+ const listener = makeContactListener(this.world, metadata, box2D);
127
+ this.world.SetContactListener(listener);
128
+ }
129
+ update(entities, events, dt) {
130
+ if (this.world) {
131
+ const clampedDelta = Math.min(dt, maxTimeStep);
132
+ this.world.Step(clampedDelta, velocityIterations, positionIterations);
133
+ this.graphics.clear();
134
+ this.world.DebugDraw();
135
+ this.graphics.fill();
136
+ // this.graphics.stroke();
137
+ // console.log('GetBodyCount', this.world.GetBodyCount());
138
+ }
139
+ }
140
+ set gravity(val) {
141
+ this.world.SetGravity(new box2D.b2Vec2(val.x, val.y));
142
+ // this.world.iterations = 60
143
+ // this.world.collisionSlop = 0.5
144
+ }
145
+ }