rngine 0.7.2 → 0.8.0

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.
package/README.md CHANGED
@@ -16,7 +16,7 @@ npm install rngine react-native-nitro-modules
16
16
  import { GameEngine, configure, update } from 'rngine';
17
17
 
18
18
  configure({
19
- tickRate: 60,
19
+ world: { tickRate: 60 },
20
20
  screen: { width: 800, height: 800, color: '#1a1a1a' },
21
21
  entities: [
22
22
  {
@@ -3,7 +3,7 @@
3
3
  import { gameMethods } from "./GameMethods.nitro.js";
4
4
  /** Sets up the game engine with the given configuration. Call this before anything else. */
5
5
  export const configure = ({
6
- tickRate,
6
+ world,
7
7
  screen,
8
8
  entities = [],
9
9
  systems = [],
@@ -22,7 +22,7 @@ export const configure = ({
22
22
  }
23
23
  });
24
24
  }
25
- gameMethods.setTickRate(tickRate);
25
+ gameMethods.setWorld(world);
26
26
  gameMethods.setScreen(screen);
27
27
  gameMethods.setEntities(entities);
28
28
  gameMethods.setSystems(nativeSystems);
@@ -1 +1 @@
1
- {"version":3,"names":["gameMethods","configure","tickRate","screen","entities","systems","paused","nativeSystems","system","push","collisions","onTick","e","c","start","Date","now","finish","setTickRate","setScreen","setEntities","setSystems","pause","resume","spawn","entityArray","Array","isArray","despawn","id","update","updates","entityUpdateArray"],"sourceRoot":"../../src","sources":["GameMethods.ts"],"mappings":";;AAAA,SAASA,WAAW,QAAQ,wBAAqB;AAIjD;AACA,OAAO,MAAMC,SAAS,GAAGA,CAAC;EACxBC,QAAQ;EACRC,MAAM;EACNC,QAAQ,GAAG,EAAE;EACbC,OAAO,GAAG,EAAE;EACZC,MAAM,GAAG;AACH,CAAC,KAAK;EACZ,IAAIC,aAAuB,GAAG,EAAE;EAEhC,KAAK,MAAMC,MAAM,IAAIH,OAAO,EAAE;IAC5BE,aAAa,CAACE,IAAI,CAAC;MACjBL,QAAQ,EAAEI,MAAM,CAACJ,QAAQ;MACzBM,UAAU,EAAEF,MAAM,CAACE,UAAU;MAC7BC,MAAM,EAAEA,CAACC,CAAC,EAAEC,CAAC,KAAK;QAChB,MAAMC,KAAK,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC;QACxBR,MAAM,CAACG,MAAM,CAACC,CAAC,EAAEC,CAAC,CAAC;QACnB,MAAMI,MAAM,GAAGF,IAAI,CAACC,GAAG,CAAC,CAAC;QACzB,OAAOC,MAAM,GAAGH,KAAK;MACvB;IACF,CAAC,CAAC;EACJ;EAEAd,WAAW,CAACkB,WAAW,CAAChB,QAAQ,CAAC;EACjCF,WAAW,CAACmB,SAAS,CAAChB,MAAM,CAAC;EAC7BH,WAAW,CAACoB,WAAW,CAAChB,QAAQ,CAAC;EACjCJ,WAAW,CAACqB,UAAU,CAACd,aAAa,CAAC;EACrC,IAAID,MAAM,EAAE;IACVN,WAAW,CAACsB,KAAK,CAAC,CAAC;EACrB,CAAC,MAAM;IACLtB,WAAW,CAACuB,MAAM,CAAC,CAAC;EACtB;AACF,CAAC;;AAED;AACA,OAAO,MAAMD,KAAK,GAAGA,CAAA,KAAMtB,WAAW,CAACsB,KAAK,CAAC,CAAC;;AAE9C;AACA,OAAO,MAAMC,MAAM,GAAGA,CAAA,KAAMvB,WAAW,CAACuB,MAAM,CAAC,CAAC;;AAEhD;AACA,OAAO,MAAMC,KAAK,GAAIpB,QAA2B,IAAK;EACpD,MAAMqB,WAAW,GAAGC,KAAK,CAACC,OAAO,CAACvB,QAAQ,CAAC,GAAGA,QAAQ,GAAG,CAACA,QAAQ,CAAC;EACnEJ,WAAW,CAACwB,KAAK,CAACC,WAAW,CAAC;AAChC,CAAC;;AAED;AACA,OAAO,MAAMG,OAAO,GAAIC,EAAU,IAAK7B,WAAW,CAAC4B,OAAO,CAACC,EAAE,CAAC;;AAE9D;AACA,OAAO,MAAMC,MAAM,GAAIC,OAAsC,IAAK;EAChE,MAAMC,iBAAiB,GAAGN,KAAK,CAACC,OAAO,CAACI,OAAO,CAAC,GAAGA,OAAO,GAAG,CAACA,OAAO,CAAC;EACtE/B,WAAW,CAAC8B,MAAM,CAACE,iBAAiB,CAAC;AACvC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["gameMethods","configure","world","screen","entities","systems","paused","nativeSystems","system","push","collisions","onTick","e","c","start","Date","now","finish","setWorld","setScreen","setEntities","setSystems","pause","resume","spawn","entityArray","Array","isArray","despawn","id","update","updates","entityUpdateArray"],"sourceRoot":"../../src","sources":["GameMethods.ts"],"mappings":";;AAAA,SAASA,WAAW,QAAQ,wBAAqB;AAIjD;AACA,OAAO,MAAMC,SAAS,GAAGA,CAAC;EACxBC,KAAK;EACLC,MAAM;EACNC,QAAQ,GAAG,EAAE;EACbC,OAAO,GAAG,EAAE;EACZC,MAAM,GAAG;AACH,CAAC,KAAK;EACZ,IAAIC,aAAuB,GAAG,EAAE;EAEhC,KAAK,MAAMC,MAAM,IAAIH,OAAO,EAAE;IAC5BE,aAAa,CAACE,IAAI,CAAC;MACjBL,QAAQ,EAAEI,MAAM,CAACJ,QAAQ;MACzBM,UAAU,EAAEF,MAAM,CAACE,UAAU;MAC7BC,MAAM,EAAEA,CAACC,CAAC,EAAEC,CAAC,KAAK;QAChB,MAAMC,KAAK,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC;QACxBR,MAAM,CAACG,MAAM,CAACC,CAAC,EAAEC,CAAC,CAAC;QACnB,MAAMI,MAAM,GAAGF,IAAI,CAACC,GAAG,CAAC,CAAC;QACzB,OAAOC,MAAM,GAAGH,KAAK;MACvB;IACF,CAAC,CAAC;EACJ;EAEAd,WAAW,CAACkB,QAAQ,CAAChB,KAAK,CAAC;EAC3BF,WAAW,CAACmB,SAAS,CAAChB,MAAM,CAAC;EAC7BH,WAAW,CAACoB,WAAW,CAAChB,QAAQ,CAAC;EACjCJ,WAAW,CAACqB,UAAU,CAACd,aAAa,CAAC;EACrC,IAAID,MAAM,EAAE;IACVN,WAAW,CAACsB,KAAK,CAAC,CAAC;EACrB,CAAC,MAAM;IACLtB,WAAW,CAACuB,MAAM,CAAC,CAAC;EACtB;AACF,CAAC;;AAED;AACA,OAAO,MAAMD,KAAK,GAAGA,CAAA,KAAMtB,WAAW,CAACsB,KAAK,CAAC,CAAC;;AAE9C;AACA,OAAO,MAAMC,MAAM,GAAGA,CAAA,KAAMvB,WAAW,CAACuB,MAAM,CAAC,CAAC;;AAEhD;AACA,OAAO,MAAMC,KAAK,GAAIpB,QAA2B,IAAK;EACpD,MAAMqB,WAAW,GAAGC,KAAK,CAACC,OAAO,CAACvB,QAAQ,CAAC,GAAGA,QAAQ,GAAG,CAACA,QAAQ,CAAC;EACnEJ,WAAW,CAACwB,KAAK,CAACC,WAAW,CAAC;AAChC,CAAC;;AAED;AACA,OAAO,MAAMG,OAAO,GAAIC,EAAU,IAAK7B,WAAW,CAAC4B,OAAO,CAACC,EAAE,CAAC;;AAE9D;AACA,OAAO,MAAMC,MAAM,GAAIC,OAAsC,IAAK;EAChE,MAAMC,iBAAiB,GAAGN,KAAK,CAACC,OAAO,CAACI,OAAO,CAAC,GAAGA,OAAO,GAAG,CAACA,OAAO,CAAC;EACtE/B,WAAW,CAAC8B,MAAM,CAACE,iBAAiB,CAAC;AACvC,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["NitroModules","gameMethods","createHybridObject"],"sourceRoot":"../../src","sources":["GameMethods.nitro.ts"],"mappings":";;AAEA,SAASA,YAAY,QAAQ,4BAA4B;AAiBzD,OAAO,MAAMC,WAAW,GACtBD,YAAY,CAACE,kBAAkB,CAAc,aAAa,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["NitroModules","gameMethods","createHybridObject"],"sourceRoot":"../../src","sources":["GameMethods.nitro.ts"],"mappings":";;AAQA,SAASA,YAAY,QAAQ,4BAA4B;AAiBzD,OAAO,MAAMC,WAAW,GACtBD,YAAY,CAACE,kBAAkB,CAAc,aAAa,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["GameEngine"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,UAAU,MAAM,iBAAc;AAErC,cAAc,kBAAe;AAC7B,cAAc,iBAAc;AAC5B,cAAc,YAAS;AAQvB,SAASA,UAAU","ignoreList":[]}
1
+ {"version":3,"names":["GameEngine"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,UAAU,MAAM,iBAAc;AAErC,cAAc,kBAAe;AAC7B,cAAc,iBAAc;AAC5B,cAAc,YAAS;AASvB,SAASA,UAAU","ignoreList":[]}
@@ -1,7 +1,7 @@
1
1
  import type { Entity, EntityUpdate } from './nativeTypes';
2
2
  import type { Config } from './types';
3
3
  /** Sets up the game engine with the given configuration. Call this before anything else. */
4
- export declare const configure: ({ tickRate, screen, entities, systems, paused, }: Config) => void;
4
+ export declare const configure: ({ world, screen, entities, systems, paused, }: Config) => void;
5
5
  /** Pauses the game loop. Systems will stop running. */
6
6
  export declare const pause: () => void;
7
7
  /** Resumes the game loop. */
@@ -1 +1 @@
1
- {"version":3,"file":"GameMethods.d.ts","sourceRoot":"","sources":["../../../src/GameMethods.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAU,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,4FAA4F;AAC5F,eAAO,MAAM,SAAS,GAAI,kDAMvB,MAAM,SAyBR,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,KAAK,YAA4B,CAAC;AAE/C,6BAA6B;AAC7B,eAAO,MAAM,MAAM,YAA6B,CAAC;AAEjD,0EAA0E;AAC1E,eAAO,MAAM,KAAK,GAAI,UAAU,MAAM,GAAG,MAAM,EAAE,SAGhD,CAAC;AAEF,qFAAqF;AACrF,eAAO,MAAM,OAAO,GAAI,IAAI,MAAM,SAA4B,CAAC;AAE/D,0EAA0E;AAC1E,eAAO,MAAM,MAAM,GAAI,SAAS,YAAY,GAAG,YAAY,EAAE,SAG5D,CAAC"}
1
+ {"version":3,"file":"GameMethods.d.ts","sourceRoot":"","sources":["../../../src/GameMethods.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAU,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,4FAA4F;AAC5F,eAAO,MAAM,SAAS,GAAI,+CAMvB,MAAM,SAyBR,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,KAAK,YAA4B,CAAC;AAE/C,6BAA6B;AAC7B,eAAO,MAAM,MAAM,YAA6B,CAAC;AAEjD,0EAA0E;AAC1E,eAAO,MAAM,KAAK,GAAI,UAAU,MAAM,GAAG,MAAM,EAAE,SAGhD,CAAC;AAEF,qFAAqF;AACrF,eAAO,MAAM,OAAO,GAAI,IAAI,MAAM,SAA4B,CAAC;AAE/D,0EAA0E;AAC1E,eAAO,MAAM,MAAM,GAAI,SAAS,YAAY,GAAG,YAAY,EAAE,SAG5D,CAAC"}
@@ -1,10 +1,10 @@
1
1
  import type { HybridObject } from 'react-native-nitro-modules';
2
- import type { Entity, EntityUpdate, System, Screen } from './nativeTypes';
2
+ import type { Entity, EntityUpdate, System, Screen, World } from './nativeTypes';
3
3
  interface GameMethods extends HybridObject<{
4
4
  ios: 'c++';
5
5
  android: 'c++';
6
6
  }> {
7
- setTickRate(tickRate: number): void;
7
+ setWorld(world: World): void;
8
8
  setScreen(screen: Screen): void;
9
9
  setEntities(entities: Entity[]): void;
10
10
  setSystems(systems: System[]): void;
@@ -1 +1 @@
1
- {"version":3,"file":"GameMethods.nitro.d.ts","sourceRoot":"","sources":["../../../src/GameMethods.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAG1E,UAAU,WAAY,SAAQ,YAAY,CAAC;IACzC,GAAG,EAAE,KAAK,CAAC;IACX,OAAO,EAAE,KAAK,CAAC;CAChB,CAAC;IACA,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACtC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;CACvC;AAED,eAAO,MAAM,WAAW,aACqC,CAAC"}
1
+ {"version":3,"file":"GameMethods.nitro.d.ts","sourceRoot":"","sources":["../../../src/GameMethods.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EACZ,MAAM,EACN,MAAM,EACN,KAAK,EACN,MAAM,eAAe,CAAC;AAGvB,UAAU,WAAY,SAAQ,YAAY,CAAC;IACzC,GAAG,EAAE,KAAK,CAAC;IACX,OAAO,EAAE,KAAK,CAAC;CAChB,CAAC;IACA,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACtC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;CACvC;AAED,eAAO,MAAM,WAAW,aACqC,CAAC"}
@@ -2,6 +2,6 @@ import GameEngine from './GameEngine';
2
2
  export * from './GameMethods';
3
3
  export * from './GameAssets';
4
4
  export * from './types';
5
- export type { Screen, Entity, CollisionPair, Collision, EntityUpdate, } from './nativeTypes';
5
+ export type { World, Screen, Entity, CollisionPair, Collision, EntityUpdate, } from './nativeTypes';
6
6
  export { GameEngine };
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,cAAc,CAAC;AAEtC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,YAAY,EACV,MAAM,EACN,MAAM,EACN,aAAa,EACb,SAAS,EACT,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,cAAc,CAAC;AAEtC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,YAAY,EACV,KAAK,EACL,MAAM,EACN,MAAM,EACN,aAAa,EACb,SAAS,EACT,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -17,6 +17,8 @@ interface Circle {
17
17
  interface Shaped {
18
18
  /** Shape of the entity. */
19
19
  shape: Rect | Circle;
20
+ /** Indicates whether the entity is a sensor. Sensors trigger collision events but don't react physically. */
21
+ isSensor?: boolean;
20
22
  }
21
23
  interface Renderable {
22
24
  /** Fill color as a hex string e.g. `'#00ff00'`. */
@@ -35,6 +37,16 @@ interface Kinematic {
35
37
  ax?: number;
36
38
  /** Vertical acceleration in game units per second squared. */
37
39
  ay?: number;
40
+ /** Mass in arbitrary units. */
41
+ mass?: number;
42
+ }
43
+ export interface World {
44
+ /** Number of game logic updates per second. */
45
+ tickRate: number;
46
+ /** Horizontal gravitational acceleration in game units per second squared. */
47
+ gx?: number;
48
+ /** Vertical gravitational acceleration in game units per second squared. */
49
+ gy?: number;
38
50
  }
39
51
  export interface Screen extends Rect, Renderable {
40
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"nativeTypes.d.ts","sourceRoot":"","sources":["../../../src/nativeTypes.ts"],"names":[],"mappings":"AAAA,UAAU,UAAU;IAClB,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,UAAU,IAAI;IACZ,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,MAAM;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,MAAM;IACd,2BAA2B;IAC3B,KAAK,EAAE,IAAI,GAAG,MAAM,CAAC;CACtB;AAED,UAAU,UAAU;IAClB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,SAAS;IACjB,oDAAoD;IACpD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,MAAO,SAAQ,IAAI,EAAE,UAAU;CAAG;AAEnD,MAAM,WAAW,MAAO,SAAQ,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS;IACvE,oFAAoF;IACpF,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAa,SAAQ,OAAO,CAC3C,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAC7C;IACC,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,CAAC,EAAE,MAAM,CAAC;IACV,yDAAyD;IACzD,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,CAAC,EAAE,MAAM,CAAC;IACV,yDAAyD;IACzD,CAAC,EAAE,MAAM,CAAC;IACV,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,qIAAqI;IACrI,EAAE,EAAE,MAAM,CAAC;IACX,qIAAqI;IACrI,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,MAAM;IACrB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,mEAAmE;IACnE,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,MAAM,CAAC;CACjE"}
1
+ {"version":3,"file":"nativeTypes.d.ts","sourceRoot":"","sources":["../../../src/nativeTypes.ts"],"names":[],"mappings":"AAAA,UAAU,UAAU;IAClB,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,UAAU,IAAI;IACZ,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,MAAM;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,MAAM;IACd,2BAA2B;IAC3B,KAAK,EAAE,IAAI,GAAG,MAAM,CAAC;IACrB,6GAA6G;IAC7G,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,UAAU;IAClB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,SAAS;IACjB,oDAAoD;IACpD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,KAAK;IACpB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,4EAA4E;IAC5E,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,MAAO,SAAQ,IAAI,EAAE,UAAU;CAAG;AAEnD,MAAM,WAAW,MAAO,SAAQ,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS;IACvE,oFAAoF;IACpF,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAa,SAAQ,OAAO,CAC3C,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAC7C;IACC,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,CAAC,EAAE,MAAM,CAAC;IACV,yDAAyD;IACzD,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,CAAC,EAAE,MAAM,CAAC;IACV,yDAAyD;IACzD,CAAC,EAAE,MAAM,CAAC;IACV,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,qIAAqI;IACrI,EAAE,EAAE,MAAM,CAAC;IACX,qIAAqI;IACrI,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,MAAM;IACrB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,mEAAmE;IACnE,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,MAAM,CAAC;CACjE"}
@@ -1,21 +1,18 @@
1
- import type { System as NativeSystem, Collision, Screen, Entity } from './nativeTypes';
1
+ import type { System as NativeSystem, Collision, Screen, Entity, World } from './nativeTypes';
2
2
  export type System = Omit<NativeSystem, 'onTick'> & {
3
3
  /** Called every tick with the resolved entities and collisions. */
4
4
  onTick: (entities: Entity[], collisions: Collision[]) => void;
5
5
  };
6
6
  export type Config = {
7
- /** Number of game logic updates per second. */
8
- tickRate: number;
9
- /** Screen dimensions and background color. */
7
+ /** World settings: tick rate and gravity. */
8
+ world: World;
9
+ /** Screen dimensions and background. */
10
10
  screen: Screen;
11
- /** Initial entities to spawn. */
11
+ /** Entities to spawn when the game starts. */
12
12
  entities?: Entity[];
13
- /**
14
- * Systems that define the game logic. Each system runs every tick
15
- * and receives the entities matching its ids.
16
- */
13
+ /** Systems that define game logic, each running every tick against its subscribed entities and collisions. */
17
14
  systems?: System[];
18
- /** Whether to start paused. Defaults to true. */
15
+ /** Whether the game starts paused. Defaults to true. */
19
16
  paused?: boolean;
20
17
  };
21
18
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,IAAI,YAAY,EACtB,SAAS,EACT,MAAM,EACN,MAAM,EACP,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG;IAClD,mEAAmE;IACnE,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,iDAAiD;IACjD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,IAAI,YAAY,EACtB,SAAS,EACT,MAAM,EACN,MAAM,EACN,KAAK,EACN,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG;IAClD,mEAAmE;IACnE,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,6CAA6C;IAC7C,KAAK,EAAE,KAAK,CAAC;IACb,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,8GAA8G;IAC9G,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,wDAAwD;IACxD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC"}
@@ -50,6 +50,7 @@ namespace margelo::nitro::rngine {
50
50
  double px SWIFT_PRIVATE;
51
51
  double py SWIFT_PRIVATE;
52
52
  std::variant<Rect, Circle> shape SWIFT_PRIVATE;
53
+ std::optional<bool> isSensor SWIFT_PRIVATE;
53
54
  std::optional<std::string> color SWIFT_PRIVATE;
54
55
  std::optional<double> asset SWIFT_PRIVATE;
55
56
  std::optional<double> progress SWIFT_PRIVATE;
@@ -57,10 +58,11 @@ namespace margelo::nitro::rngine {
57
58
  std::optional<double> vy SWIFT_PRIVATE;
58
59
  std::optional<double> ax SWIFT_PRIVATE;
59
60
  std::optional<double> ay SWIFT_PRIVATE;
61
+ std::optional<double> mass SWIFT_PRIVATE;
60
62
 
61
63
  public:
62
64
  Entity() = default;
63
- explicit Entity(std::string id, double px, double py, std::variant<Rect, Circle> shape, std::optional<std::string> color, std::optional<double> asset, std::optional<double> progress, std::optional<double> vx, std::optional<double> vy, std::optional<double> ax, std::optional<double> ay): id(id), px(px), py(py), shape(shape), color(color), asset(asset), progress(progress), vx(vx), vy(vy), ax(ax), ay(ay) {}
65
+ explicit Entity(std::string id, double px, double py, std::variant<Rect, Circle> shape, std::optional<bool> isSensor, std::optional<std::string> color, std::optional<double> asset, std::optional<double> progress, std::optional<double> vx, std::optional<double> vy, std::optional<double> ax, std::optional<double> ay, std::optional<double> mass): id(id), px(px), py(py), shape(shape), isSensor(isSensor), color(color), asset(asset), progress(progress), vx(vx), vy(vy), ax(ax), ay(ay), mass(mass) {}
64
66
 
65
67
  public:
66
68
  friend bool operator==(const Entity& lhs, const Entity& rhs) = default;
@@ -80,13 +82,15 @@ namespace margelo::nitro {
80
82
  JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px"))),
81
83
  JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "py"))),
82
84
  JSIConverter<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "shape"))),
85
+ JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "isSensor"))),
83
86
  JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color"))),
84
87
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset"))),
85
88
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress"))),
86
89
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vx"))),
87
90
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy"))),
88
91
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ax"))),
89
- JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ay")))
92
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ay"))),
93
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "mass")))
90
94
  );
91
95
  }
92
96
  static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::Entity& arg) {
@@ -95,6 +99,7 @@ namespace margelo::nitro {
95
99
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "px"), JSIConverter<double>::toJSI(runtime, arg.px));
96
100
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "py"), JSIConverter<double>::toJSI(runtime, arg.py));
97
101
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "shape"), JSIConverter<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>::toJSI(runtime, arg.shape));
102
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "isSensor"), JSIConverter<std::optional<bool>>::toJSI(runtime, arg.isSensor));
98
103
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "color"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.color));
99
104
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "asset"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.asset));
100
105
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "progress"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.progress));
@@ -102,6 +107,7 @@ namespace margelo::nitro {
102
107
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "vy"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.vy));
103
108
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "ax"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.ax));
104
109
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "ay"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.ay));
110
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "mass"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.mass));
105
111
  return obj;
106
112
  }
107
113
  static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
@@ -116,6 +122,7 @@ namespace margelo::nitro {
116
122
  if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px")))) return false;
117
123
  if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "py")))) return false;
118
124
  if (!JSIConverter<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "shape")))) return false;
125
+ if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "isSensor")))) return false;
119
126
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color")))) return false;
120
127
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset")))) return false;
121
128
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress")))) return false;
@@ -123,6 +130,7 @@ namespace margelo::nitro {
123
130
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy")))) return false;
124
131
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ax")))) return false;
125
132
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ay")))) return false;
133
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "mass")))) return false;
126
134
  return true;
127
135
  }
128
136
  };
@@ -50,6 +50,7 @@ namespace margelo::nitro::rngine {
50
50
  std::optional<double> px SWIFT_PRIVATE;
51
51
  std::optional<double> py SWIFT_PRIVATE;
52
52
  std::optional<std::variant<Rect, Circle>> shape SWIFT_PRIVATE;
53
+ std::optional<bool> isSensor SWIFT_PRIVATE;
53
54
  std::optional<std::string> color SWIFT_PRIVATE;
54
55
  std::optional<double> asset SWIFT_PRIVATE;
55
56
  std::optional<double> progress SWIFT_PRIVATE;
@@ -57,10 +58,11 @@ namespace margelo::nitro::rngine {
57
58
  std::optional<double> vy SWIFT_PRIVATE;
58
59
  std::optional<double> ax SWIFT_PRIVATE;
59
60
  std::optional<double> ay SWIFT_PRIVATE;
61
+ std::optional<double> mass SWIFT_PRIVATE;
60
62
 
61
63
  public:
62
64
  EntityUpdate() = default;
63
- explicit EntityUpdate(std::string id, std::optional<double> px, std::optional<double> py, std::optional<std::variant<Rect, Circle>> shape, std::optional<std::string> color, std::optional<double> asset, std::optional<double> progress, std::optional<double> vx, std::optional<double> vy, std::optional<double> ax, std::optional<double> ay): id(id), px(px), py(py), shape(shape), color(color), asset(asset), progress(progress), vx(vx), vy(vy), ax(ax), ay(ay) {}
65
+ explicit EntityUpdate(std::string id, std::optional<double> px, std::optional<double> py, std::optional<std::variant<Rect, Circle>> shape, std::optional<bool> isSensor, std::optional<std::string> color, std::optional<double> asset, std::optional<double> progress, std::optional<double> vx, std::optional<double> vy, std::optional<double> ax, std::optional<double> ay, std::optional<double> mass): id(id), px(px), py(py), shape(shape), isSensor(isSensor), color(color), asset(asset), progress(progress), vx(vx), vy(vy), ax(ax), ay(ay), mass(mass) {}
64
66
 
65
67
  public:
66
68
  friend bool operator==(const EntityUpdate& lhs, const EntityUpdate& rhs) = default;
@@ -80,13 +82,15 @@ namespace margelo::nitro {
80
82
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px"))),
81
83
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "py"))),
82
84
  JSIConverter<std::optional<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "shape"))),
85
+ JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "isSensor"))),
83
86
  JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color"))),
84
87
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset"))),
85
88
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress"))),
86
89
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vx"))),
87
90
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy"))),
88
91
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ax"))),
89
- JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ay")))
92
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ay"))),
93
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "mass")))
90
94
  );
91
95
  }
92
96
  static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::EntityUpdate& arg) {
@@ -95,6 +99,7 @@ namespace margelo::nitro {
95
99
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "px"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.px));
96
100
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "py"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.py));
97
101
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "shape"), JSIConverter<std::optional<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>>::toJSI(runtime, arg.shape));
102
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "isSensor"), JSIConverter<std::optional<bool>>::toJSI(runtime, arg.isSensor));
98
103
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "color"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.color));
99
104
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "asset"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.asset));
100
105
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "progress"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.progress));
@@ -102,6 +107,7 @@ namespace margelo::nitro {
102
107
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "vy"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.vy));
103
108
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "ax"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.ax));
104
109
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "ay"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.ay));
110
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "mass"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.mass));
105
111
  return obj;
106
112
  }
107
113
  static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
@@ -116,6 +122,7 @@ namespace margelo::nitro {
116
122
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px")))) return false;
117
123
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "py")))) return false;
118
124
  if (!JSIConverter<std::optional<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "shape")))) return false;
125
+ if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "isSensor")))) return false;
119
126
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color")))) return false;
120
127
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset")))) return false;
121
128
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress")))) return false;
@@ -123,6 +130,7 @@ namespace margelo::nitro {
123
130
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy")))) return false;
124
131
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ax")))) return false;
125
132
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ay")))) return false;
133
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "mass")))) return false;
126
134
  return true;
127
135
  }
128
136
  };
@@ -14,7 +14,7 @@ namespace margelo::nitro::rngine {
14
14
  HybridObject::loadHybridMethods();
15
15
  // load custom methods/properties
16
16
  registerHybrids(this, [](Prototype& prototype) {
17
- prototype.registerHybridMethod("setTickRate", &HybridGameMethodsSpec::setTickRate);
17
+ prototype.registerHybridMethod("setWorld", &HybridGameMethodsSpec::setWorld);
18
18
  prototype.registerHybridMethod("setScreen", &HybridGameMethodsSpec::setScreen);
19
19
  prototype.registerHybridMethod("setEntities", &HybridGameMethodsSpec::setEntities);
20
20
  prototype.registerHybridMethod("setSystems", &HybridGameMethodsSpec::setSystems);
@@ -13,6 +13,8 @@
13
13
  #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
14
  #endif
15
15
 
16
+ // Forward declaration of `World` to properly resolve imports.
17
+ namespace margelo::nitro::rngine { struct World; }
16
18
  // Forward declaration of `Screen` to properly resolve imports.
17
19
  namespace margelo::nitro::rngine { struct Screen; }
18
20
  // Forward declaration of `Entity` to properly resolve imports.
@@ -22,6 +24,7 @@ namespace margelo::nitro::rngine { struct System; }
22
24
  // Forward declaration of `EntityUpdate` to properly resolve imports.
23
25
  namespace margelo::nitro::rngine { struct EntityUpdate; }
24
26
 
27
+ #include "World.hpp"
25
28
  #include "Screen.hpp"
26
29
  #include "Entity.hpp"
27
30
  #include <vector>
@@ -60,7 +63,7 @@ namespace margelo::nitro::rngine {
60
63
 
61
64
  public:
62
65
  // Methods
63
- virtual void setTickRate(double tickRate) = 0;
66
+ virtual void setWorld(const World& world) = 0;
64
67
  virtual void setScreen(const Screen& screen) = 0;
65
68
  virtual void setEntities(const std::vector<Entity>& entities) = 0;
66
69
  virtual void setSystems(const std::vector<System>& systems) = 0;
@@ -0,0 +1,91 @@
1
+ ///
2
+ /// World.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/JSIConverter.hpp>)
11
+ #include <NitroModules/JSIConverter.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+ #if __has_include(<NitroModules/NitroDefines.hpp>)
16
+ #include <NitroModules/NitroDefines.hpp>
17
+ #else
18
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19
+ #endif
20
+ #if __has_include(<NitroModules/JSIHelpers.hpp>)
21
+ #include <NitroModules/JSIHelpers.hpp>
22
+ #else
23
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
24
+ #endif
25
+ #if __has_include(<NitroModules/PropNameIDCache.hpp>)
26
+ #include <NitroModules/PropNameIDCache.hpp>
27
+ #else
28
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
29
+ #endif
30
+
31
+
32
+
33
+ #include <optional>
34
+
35
+ namespace margelo::nitro::rngine {
36
+
37
+ /**
38
+ * A struct which can be represented as a JavaScript object (World).
39
+ */
40
+ struct World final {
41
+ public:
42
+ double tickRate SWIFT_PRIVATE;
43
+ std::optional<double> gx SWIFT_PRIVATE;
44
+ std::optional<double> gy SWIFT_PRIVATE;
45
+
46
+ public:
47
+ World() = default;
48
+ explicit World(double tickRate, std::optional<double> gx, std::optional<double> gy): tickRate(tickRate), gx(gx), gy(gy) {}
49
+
50
+ public:
51
+ friend bool operator==(const World& lhs, const World& rhs) = default;
52
+ };
53
+
54
+ } // namespace margelo::nitro::rngine
55
+
56
+ namespace margelo::nitro {
57
+
58
+ // C++ World <> JS World (object)
59
+ template <>
60
+ struct JSIConverter<margelo::nitro::rngine::World> final {
61
+ static inline margelo::nitro::rngine::World fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
62
+ jsi::Object obj = arg.asObject(runtime);
63
+ return margelo::nitro::rngine::World(
64
+ JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "tickRate"))),
65
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "gx"))),
66
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "gy")))
67
+ );
68
+ }
69
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::World& arg) {
70
+ jsi::Object obj(runtime);
71
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "tickRate"), JSIConverter<double>::toJSI(runtime, arg.tickRate));
72
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "gx"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.gx));
73
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "gy"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.gy));
74
+ return obj;
75
+ }
76
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
77
+ if (!value.isObject()) {
78
+ return false;
79
+ }
80
+ jsi::Object obj = value.getObject(runtime);
81
+ if (!nitro::isPlainObject(runtime, obj)) {
82
+ return false;
83
+ }
84
+ if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "tickRate")))) return false;
85
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "gx")))) return false;
86
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "gy")))) return false;
87
+ return true;
88
+ }
89
+ };
90
+
91
+ } // namespace margelo::nitro
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rngine",
3
- "version": "0.7.2",
3
+ "version": "0.8.0",
4
4
  "description": "React Native 2D game engine powered by Nitro Modules",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -5,7 +5,6 @@
5
5
  #include <android/log.h>
6
6
  #include <chrono>
7
7
  #include <cinttypes>
8
- #include <set>
9
8
 
10
9
  namespace margelo::nitro::rngine {
11
10
 
@@ -32,6 +31,11 @@ GameLoop::~GameLoop() {
32
31
  __android_log_print(ANDROID_LOG_INFO, "GameLoop", "Destructor - Complete");
33
32
  }
34
33
 
34
+ bool GameLoop::entityIdMatches(const std::string &entityId,
35
+ const std::string &prefix) {
36
+ return entityId == prefix || entityId.starts_with(prefix + "_");
37
+ }
38
+
35
39
  std::vector<Entity *>
36
40
  GameLoop::resolveEntitiesInternal(const std::string &prefix) {
37
41
  std::vector<Entity *> results;
@@ -69,7 +73,11 @@ void GameLoop::runGameLoop() {
69
73
  double accumulator = 0.0;
70
74
 
71
75
  while (_isRunning) {
72
- double targetDeltaTime = 1.0 / _tickRate.load();
76
+ double targetDeltaTime;
77
+ {
78
+ std::lock_guard<std::mutex> lock(_worldMutex);
79
+ targetDeltaTime = 1.0 / _world.tickRate;
80
+ }
73
81
  auto currentTime = steady_clock::now();
74
82
  double frameTime = duration<double>(currentTime - previousTime).count();
75
83
  previousTime = currentTime;
@@ -108,28 +116,14 @@ void GameLoop::runSystems() {
108
116
  }
109
117
 
110
118
  if (system.collisions.has_value()) {
111
- std::set<std::pair<std::string, std::string>> uniqueEntityIdPairs;
112
-
113
- for (const auto &[a, b] : system.collisions.value()) {
114
- auto resolvedEntitiesInternalA = resolveEntitiesInternal(a);
115
- auto resolvedEntitiesInternalB = resolveEntitiesInternal(b);
116
-
117
- for (const auto &entityA : resolvedEntitiesInternalA) {
118
- for (const auto &entityB : resolvedEntitiesInternalB) {
119
- if (entityA == entityB)
120
- continue;
121
-
122
- auto uniqueEntityIdPairKey = std::minmax(entityA->id, entityB->id);
123
-
124
- if (uniqueEntityIdPairs.count(uniqueEntityIdPairKey))
125
- continue;
126
-
127
- uniqueEntityIdPairs.insert(uniqueEntityIdPairKey);
128
-
129
- if (auto collision =
130
- CollisionUtils::shapeOverlap(*entityA, *entityB)) {
131
- collisions.push_back(collision.value());
132
- }
119
+ for (const auto &pair : system.collisions.value()) {
120
+ for (const auto &c : _collisions) {
121
+ bool matchesForward =
122
+ entityIdMatches(c.a, pair.a) && entityIdMatches(c.b, pair.b);
123
+ bool matchesReverse =
124
+ entityIdMatches(c.a, pair.b) && entityIdMatches(c.b, pair.a);
125
+ if (matchesForward || matchesReverse) {
126
+ collisions.push_back(c);
133
127
  }
134
128
  }
135
129
  }
@@ -161,6 +155,8 @@ void GameLoop::captureSnapshot() {
161
155
  void GameLoop::update(double deltaTime) {
162
156
  updateStats(deltaTime);
163
157
  updateEntities(deltaTime);
158
+ computeCollisions();
159
+ resolveCollisions();
164
160
  runSystems();
165
161
  captureSnapshot();
166
162
  }
@@ -189,10 +185,20 @@ void GameLoop::updateStats(double deltaTime) {
189
185
  }
190
186
 
191
187
  void GameLoop::updateEntities(double deltaTime) {
188
+ std::lock_guard<std::mutex> worldLock(_worldMutex);
192
189
  std::lock_guard<std::mutex> lock(_mutex);
193
190
 
194
191
  for (auto &[id, entity] : _entities) {
195
192
 
193
+ if (entity.mass.has_value() && entity.mass.value() > 0.0) {
194
+ if (_world.gx.has_value()) {
195
+ entity.vx = entity.vx.value_or(0.0) + _world.gx.value() * deltaTime;
196
+ }
197
+ if (_world.gy.has_value()) {
198
+ entity.vy = entity.vy.value_or(0.0) + _world.gy.value() * deltaTime;
199
+ }
200
+ }
201
+
196
202
  if (entity.ax.has_value()) {
197
203
  entity.vx = entity.vx.value_or(0.0) + entity.ax.value() * deltaTime;
198
204
  }
@@ -216,4 +222,77 @@ void GameLoop::updateEntities(double deltaTime) {
216
222
  }
217
223
  }
218
224
  }
225
+
226
+ void GameLoop::computeCollisions() {
227
+ std::lock_guard<std::mutex> lock(_mutex);
228
+ _collisions.clear();
229
+
230
+ std::vector<Entity *> entities;
231
+ entities.reserve(_entities.size());
232
+ for (auto &[id, entity] : _entities) {
233
+ entities.push_back(&entity);
234
+ }
235
+
236
+ for (size_t i = 0; i < entities.size(); ++i) {
237
+ for (size_t j = i + 1; j < entities.size(); ++j) {
238
+ auto result = CollisionUtils::shapeOverlap(*entities[i], *entities[j]);
239
+ if (result.has_value()) {
240
+ _collisions.push_back(result.value());
241
+ }
242
+ }
243
+ }
244
+ }
245
+
246
+ void GameLoop::resolveCollisions() {
247
+ std::lock_guard<std::mutex> lock(_mutex);
248
+
249
+ const double percent = 0.8;
250
+ const double slop = 0.01;
251
+
252
+ for (const auto &c : _collisions) {
253
+ auto itA = _entities.find(c.a);
254
+ auto itB = _entities.find(c.b);
255
+ if (itA == _entities.end() || itB == _entities.end())
256
+ continue;
257
+
258
+ Entity &a = itA->second;
259
+ Entity &b = itB->second;
260
+
261
+ if (a.isSensor.value_or(false) || b.isSensor.value_or(false))
262
+ continue;
263
+
264
+ double inverseMassA = (a.mass.has_value() && a.mass.value() > 0.0)
265
+ ? 1.0 / a.mass.value()
266
+ : 0.0;
267
+ double inverseMassB = (b.mass.has_value() && b.mass.value() > 0.0)
268
+ ? 1.0 / b.mass.value()
269
+ : 0.0;
270
+ double totalInverseMass = inverseMassA + inverseMassB;
271
+ if (totalInverseMass == 0.0)
272
+ continue;
273
+
274
+ double correctionDepth = std::max(c.depth - slop, 0.0);
275
+ double correction = (correctionDepth / totalInverseMass) * percent;
276
+ a.px -= c.nx * correction * inverseMassA;
277
+ a.py -= c.ny * correction * inverseMassA;
278
+ b.px += c.nx * correction * inverseMassB;
279
+ b.py += c.ny * correction * inverseMassB;
280
+
281
+ double avx = a.vx.value_or(0.0), avy = a.vy.value_or(0.0);
282
+ double bvx = b.vx.value_or(0.0), bvy = b.vy.value_or(0.0);
283
+ double relativeVx = bvx - avx, relativeVy = bvy - avy;
284
+ double velocityAlongNormal = relativeVx * c.nx + relativeVy * c.ny;
285
+ if (velocityAlongNormal > 0)
286
+ continue;
287
+
288
+ double restitution = 0.0;
289
+ double impulse =
290
+ -(1 + restitution) * velocityAlongNormal / totalInverseMass;
291
+
292
+ a.vx = avx - impulse * c.nx * inverseMassA;
293
+ a.vy = avy - impulse * c.ny * inverseMassA;
294
+ b.vx = bvx + impulse * c.nx * inverseMassB;
295
+ b.vy = bvy + impulse * c.ny * inverseMassB;
296
+ }
297
+ }
219
298
  } // namespace margelo::nitro::rngine
@@ -4,6 +4,7 @@
4
4
  #include "GameStats.hpp"
5
5
  #include "Screen.hpp"
6
6
  #include "System.hpp"
7
+ #include "World.hpp"
7
8
  #include <atomic>
8
9
  #include <memory>
9
10
  #include <thread>
@@ -20,6 +21,7 @@ public:
20
21
 
21
22
  ~GameLoop();
22
23
 
24
+ std::mutex &getWorldMutexInternal() { return _worldMutex; };
23
25
  std::mutex &getMutexInternal() { return _mutex; };
24
26
  std::mutex &getSnapshotMutexInternal() { return _snapshotMutex; };
25
27
  std::map<string, Entity> &getEntitiesInternal() { return _entities; };
@@ -28,25 +30,27 @@ public:
28
30
  };
29
31
  std::vector<System> &getSystemsInternal() { return _systems; };
30
32
  std::atomic<bool> &getIsPausedInternal() { return _isPaused; };
33
+ World &getWorldInternal() { return _world; };
31
34
  Screen &getScreenInternal() { return _screen; };
32
35
  Screen &getScreenSnapshotInternal() { return _screenSnapshot; };
33
36
 
37
+ bool entityIdMatches(const std::string &entityId, const std::string &prefix);
34
38
  std::vector<Entity *> resolveEntitiesInternal(const std::string &prefix);
35
39
  void registerLottieDuration(double, double);
36
40
 
37
- void setTickRate(double tickRate) { _tickRate.store(tickRate); };
38
-
39
41
  private:
40
42
  explicit GameLoop();
43
+ std::mutex _worldMutex;
41
44
  std::mutex _mutex;
42
45
  std::mutex _snapshotMutex;
43
46
  std::map<std::string, Entity> _entities;
44
47
  std::map<std::string, Entity> _entitiesSnapshot;
45
48
  std::map<double, double> _lottieDurations;
49
+ std::vector<Collision> _collisions{};
46
50
  std::vector<System> _systems{};
47
51
  std::atomic<bool> _isRunning{true};
48
52
  std::atomic<bool> _isPaused{true};
49
- std::atomic<double> _tickRate{60.0};
53
+ World _world;
50
54
  Screen _screen;
51
55
  Screen _screenSnapshot;
52
56
  GameStats _gameStats;
@@ -54,6 +58,8 @@ private:
54
58
 
55
59
  void runGameLoop();
56
60
  void runSystems();
61
+ void computeCollisions();
62
+ void resolveCollisions();
57
63
  void captureSnapshot();
58
64
  void update(double deltaTime);
59
65
  void updateStats(double deltaTime);
@@ -4,11 +4,12 @@
4
4
  #include <android/log.h>
5
5
 
6
6
  namespace margelo::nitro::rngine {
7
- void GameMethods::setTickRate(double tickRate) {
7
+ void GameMethods::setWorld(const World &world) {
8
8
  auto &instance = GameLoop::getInstance();
9
- instance.setTickRate(tickRate);
9
+ std::lock_guard<std::mutex> lock(instance.getWorldMutexInternal());
10
+ instance.getWorldInternal() = world;
10
11
  __android_log_print(ANDROID_LOG_INFO, "GameMethods",
11
- "setTickRate: tickRate=%.1f", tickRate);
12
+ "setWorld: tickRate=%.1f", world.tickRate);
12
13
  }
13
14
 
14
15
  void GameMethods::setScreen(const Screen &screen) {
@@ -19,7 +20,7 @@ void GameMethods::setScreen(const Screen &screen) {
19
20
  instance.getScreenSnapshotInternal() = screen;
20
21
 
21
22
  __android_log_print(ANDROID_LOG_INFO, "GameMethods",
22
- "setWorld: width=%.0f height=%.0f", screen.width,
23
+ "setScreen: width=%.0f height=%.0f", screen.width,
23
24
  screen.height);
24
25
  }
25
26
 
@@ -130,6 +131,9 @@ void GameMethods::update(const std::vector<EntityUpdate> &updates) {
130
131
  if (update.shape.has_value()) {
131
132
  entity->shape = update.shape.value();
132
133
  }
134
+ if (update.isSensor.has_value()) {
135
+ entity->isSensor = update.isSensor.value();
136
+ }
133
137
  if (update.asset.has_value()) {
134
138
  entity->asset = update.asset.value();
135
139
  }
@@ -151,6 +155,9 @@ void GameMethods::update(const std::vector<EntityUpdate> &updates) {
151
155
  if (update.ay.has_value()) {
152
156
  entity->ay = update.ay.value();
153
157
  }
158
+ if (update.mass.has_value()) {
159
+ entity->mass = update.mass.value();
160
+ }
154
161
  }
155
162
 
156
163
  __android_log_print(ANDROID_LOG_INFO, "GameMethods",
@@ -1,12 +1,13 @@
1
1
  #pragma once
2
2
 
3
3
  #include "HybridGameMethodsSpec.hpp"
4
+ #include "World.hpp"
4
5
 
5
6
  namespace margelo::nitro::rngine {
6
7
  class GameMethods : public HybridGameMethodsSpec {
7
8
  public:
8
9
  GameMethods() : HybridObject(TAG) {}
9
- void setTickRate(double tickRate) override;
10
+ void setWorld(const World &world) override;
10
11
  void setScreen(const Screen &screen) override;
11
12
  void setEntities(const std::vector<Entity> &entities) override;
12
13
  void setSystems(const std::vector<System> &systems) override;
@@ -1,12 +1,18 @@
1
1
  import type { HybridObject } from 'react-native-nitro-modules';
2
- import type { Entity, EntityUpdate, System, Screen } from './nativeTypes';
2
+ import type {
3
+ Entity,
4
+ EntityUpdate,
5
+ System,
6
+ Screen,
7
+ World,
8
+ } from './nativeTypes';
3
9
  import { NitroModules } from 'react-native-nitro-modules';
4
10
 
5
11
  interface GameMethods extends HybridObject<{
6
12
  ios: 'c++';
7
13
  android: 'c++';
8
14
  }> {
9
- setTickRate(tickRate: number): void;
15
+ setWorld(world: World): void;
10
16
  setScreen(screen: Screen): void;
11
17
  setEntities(entities: Entity[]): void;
12
18
  setSystems(systems: System[]): void;
@@ -4,7 +4,7 @@ import type { Config } from './types';
4
4
 
5
5
  /** Sets up the game engine with the given configuration. Call this before anything else. */
6
6
  export const configure = ({
7
- tickRate,
7
+ world,
8
8
  screen,
9
9
  entities = [],
10
10
  systems = [],
@@ -25,7 +25,7 @@ export const configure = ({
25
25
  });
26
26
  }
27
27
 
28
- gameMethods.setTickRate(tickRate);
28
+ gameMethods.setWorld(world);
29
29
  gameMethods.setScreen(screen);
30
30
  gameMethods.setEntities(entities);
31
31
  gameMethods.setSystems(nativeSystems);
package/src/index.tsx CHANGED
@@ -4,6 +4,7 @@ export * from './GameMethods';
4
4
  export * from './GameAssets';
5
5
  export * from './types';
6
6
  export type {
7
+ World,
7
8
  Screen,
8
9
  Entity,
9
10
  CollisionPair,
@@ -20,6 +20,8 @@ interface Circle {
20
20
  interface Shaped {
21
21
  /** Shape of the entity. */
22
22
  shape: Rect | Circle;
23
+ /** Indicates whether the entity is a sensor. Sensors trigger collision events but don't react physically. */
24
+ isSensor?: boolean;
23
25
  }
24
26
 
25
27
  interface Renderable {
@@ -40,6 +42,17 @@ interface Kinematic {
40
42
  ax?: number;
41
43
  /** Vertical acceleration in game units per second squared. */
42
44
  ay?: number;
45
+ /** Mass in arbitrary units. */
46
+ mass?: number;
47
+ }
48
+
49
+ export interface World {
50
+ /** Number of game logic updates per second. */
51
+ tickRate: number;
52
+ /** Horizontal gravitational acceleration in game units per second squared. */
53
+ gx?: number;
54
+ /** Vertical gravitational acceleration in game units per second squared. */
55
+ gy?: number;
43
56
  }
44
57
 
45
58
  export interface Screen extends Rect, Renderable {}
package/src/types.ts CHANGED
@@ -3,6 +3,7 @@ import type {
3
3
  Collision,
4
4
  Screen,
5
5
  Entity,
6
+ World,
6
7
  } from './nativeTypes';
7
8
 
8
9
  export type System = Omit<NativeSystem, 'onTick'> & {
@@ -11,17 +12,14 @@ export type System = Omit<NativeSystem, 'onTick'> & {
11
12
  };
12
13
 
13
14
  export type Config = {
14
- /** Number of game logic updates per second. */
15
- tickRate: number;
16
- /** Screen dimensions and background color. */
15
+ /** World settings: tick rate and gravity. */
16
+ world: World;
17
+ /** Screen dimensions and background. */
17
18
  screen: Screen;
18
- /** Initial entities to spawn. */
19
+ /** Entities to spawn when the game starts. */
19
20
  entities?: Entity[];
20
- /**
21
- * Systems that define the game logic. Each system runs every tick
22
- * and receives the entities matching its ids.
23
- */
21
+ /** Systems that define game logic, each running every tick against its subscribed entities and collisions. */
24
22
  systems?: System[];
25
- /** Whether to start paused. Defaults to true. */
23
+ /** Whether the game starts paused. Defaults to true. */
26
24
  paused?: boolean;
27
25
  };