rngine 0.2.1 → 0.3.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 +9 -16
- package/lib/module/GameMethods.js +4 -5
- package/lib/module/GameMethods.js.map +1 -1
- package/lib/module/index.js +2 -2
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/GameMethods.d.ts +3 -5
- package/lib/typescript/src/GameMethods.d.ts.map +1 -1
- package/lib/typescript/src/GameMethods.nitro.d.ts +2 -3
- package/lib/typescript/src/GameMethods.nitro.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +20 -2
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/nitrogen/generated/shared/c++/Entity.hpp +10 -9
- package/nitrogen/generated/shared/c++/EntityUpdate.hpp +112 -0
- package/nitrogen/generated/shared/c++/HybridGameMethodsSpec.cpp +1 -2
- package/nitrogen/generated/shared/c++/HybridGameMethodsSpec.hpp +4 -2
- package/package.json +2 -2
- package/shared/GameLoop.cpp +11 -8
- package/shared/GameMethods.cpp +30 -29
- package/shared/GameMethods.hpp +1 -2
- package/src/GameMethods.nitro.ts +2 -3
- package/src/GameMethods.ts +5 -8
- package/src/index.tsx +2 -12
- package/src/types.ts +21 -2
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Rngine
|
|
2
2
|
|
|
3
3
|
A React Native game engine for building 2D games, powered by [Nitro Modules](https://nitro.margelo.com/) for high-performance C++ game logic.
|
|
4
4
|
|
|
@@ -13,7 +13,7 @@ npm install rngine react-native-nitro-modules
|
|
|
13
13
|
## Usage
|
|
14
14
|
|
|
15
15
|
```tsx
|
|
16
|
-
import { GameEngine, configure,
|
|
16
|
+
import { GameEngine, configure, update } from 'rngine';
|
|
17
17
|
|
|
18
18
|
configure({
|
|
19
19
|
tickRate: 60,
|
|
@@ -26,8 +26,6 @@ configure({
|
|
|
26
26
|
width: 40,
|
|
27
27
|
height: 40,
|
|
28
28
|
color: '#00ff00',
|
|
29
|
-
vx: 0,
|
|
30
|
-
vy: 0,
|
|
31
29
|
},
|
|
32
30
|
{
|
|
33
31
|
id: 'enemy_1',
|
|
@@ -37,7 +35,6 @@ configure({
|
|
|
37
35
|
height: 40,
|
|
38
36
|
color: '#ff0000',
|
|
39
37
|
vx: 1000,
|
|
40
|
-
vy: 0,
|
|
41
38
|
},
|
|
42
39
|
{
|
|
43
40
|
id: 'enemy_2',
|
|
@@ -47,7 +44,6 @@ configure({
|
|
|
47
44
|
height: 40,
|
|
48
45
|
color: '#ff0000',
|
|
49
46
|
vx: -1000,
|
|
50
|
-
vy: 0,
|
|
51
47
|
},
|
|
52
48
|
],
|
|
53
49
|
systems: [
|
|
@@ -58,7 +54,7 @@ configure({
|
|
|
58
54
|
enemies.forEach((enemy) => {
|
|
59
55
|
// reverse direction when reaching world edges
|
|
60
56
|
if (enemy.px <= 0 || enemy.px + enemy.width >= 800) {
|
|
61
|
-
|
|
57
|
+
update({ id: enemy.id, vx: -enemy.vx });
|
|
62
58
|
}
|
|
63
59
|
});
|
|
64
60
|
},
|
|
@@ -82,7 +78,7 @@ export default function App() {
|
|
|
82
78
|
|
|
83
79
|
## Entity Querying
|
|
84
80
|
|
|
85
|
-
Entity ids use `_` as a hierarchy separator, which enables prefix matching in systems and functions like `
|
|
81
|
+
Entity ids use `_` as a hierarchy separator, which enables prefix matching in systems and functions like `update`. Querying `'enemy'` matches all entities whose id starts with `enemy_`. So `enemy_1`, `enemy_magician_1`, and `enemy_warrior_2` are all returned. Querying `'enemy_magician'` narrows it down to only magician entities. Querying `'enemy_magician_1'` is an exact match.
|
|
86
82
|
|
|
87
83
|
This makes it easy to build entity groups naturally through naming. No extra configuration needed.
|
|
88
84
|
|
|
@@ -105,8 +101,8 @@ Sets up the game engine. Call this before anything else.
|
|
|
105
101
|
|
|
106
102
|
| param | required | type | default | description |
|
|
107
103
|
| ---------- | -------- | ---------- | ------- | ------------------------------------- |
|
|
108
|
-
| `tickRate` | ✓ | `number` |
|
|
109
|
-
| `world` | ✓ | `World` |
|
|
104
|
+
| `tickRate` | ✓ | `number` | - | Game logic updates per second |
|
|
105
|
+
| `world` | ✓ | `World` | - | World dimensions and background color |
|
|
110
106
|
| `entities` | | `Entity[]` | `[]` | Initial entities to spawn |
|
|
111
107
|
| `systems` | | `System[]` | `[]` | Systems to run each tick |
|
|
112
108
|
| `paused` | | `boolean` | `true` | Whether to start paused |
|
|
@@ -119,13 +115,10 @@ Spawns one or more entities into the world. Skips duplicates by id.
|
|
|
119
115
|
|
|
120
116
|
Removes the entity with the given id, or all entities matching the given prefix.
|
|
121
117
|
|
|
122
|
-
### `
|
|
118
|
+
### `update(entityUpdate | entityUpdate[])`
|
|
123
119
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
### `setVelocity(id, vx, vy)`
|
|
127
|
-
|
|
128
|
-
Sets the velocity of all entities matching the given id or prefix.
|
|
120
|
+
Updates one or more entities. Only the provided fields are changed.
|
|
121
|
+
Matches entities by exact id or prefix.
|
|
129
122
|
|
|
130
123
|
### `pause()`
|
|
131
124
|
|
|
@@ -36,9 +36,8 @@ export const spawn = entities => {
|
|
|
36
36
|
/** Removes an entity or all entities matching the given id prefix from the world. */
|
|
37
37
|
export const despawn = id => gameMethods.despawn(id);
|
|
38
38
|
|
|
39
|
-
/**
|
|
40
|
-
export const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
export const setVelocity = (id, vx, vy) => gameMethods.setV(id, vx, vy);
|
|
39
|
+
/** Updates one or more entities. Only the provided fields are changed. */
|
|
40
|
+
export const update = updates => {
|
|
41
|
+
gameMethods.update(Array.isArray(updates) ? updates : [updates]);
|
|
42
|
+
};
|
|
44
43
|
//# sourceMappingURL=GameMethods.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NitroModules","gameMethods","createHybridObject","configure","tickRate","world","entities","systems","paused","setTickRate","setWorld","setEntities","setSystems","pause","resume","spawn","Array","isArray","despawn","id","
|
|
1
|
+
{"version":3,"names":["NitroModules","gameMethods","createHybridObject","configure","tickRate","world","entities","systems","paused","setTickRate","setWorld","setEntities","setSystems","pause","resume","spawn","Array","isArray","despawn","id","update","updates"],"sourceRoot":"../../src","sources":["GameMethods.ts"],"mappings":";;AAAA,SAASA,YAAY,QAAQ,4BAA4B;AAIzD,MAAMC,WAAW,GAAGD,YAAY,CAACE,kBAAkB,CAAc,aAAa,CAAC;;AAE/E;AACA,OAAO,SAASC,SAASA,CAAC;EACxBC,QAAQ;EACRC,KAAK;EACLC,QAAQ,GAAG,EAAE;EACbC,OAAO,GAAG,EAAE;EACZC,MAAM,GAAG;AACH,CAAC,EAAE;EACTP,WAAW,CAACQ,WAAW,CAACL,QAAQ,CAAC;EACjCH,WAAW,CAACS,QAAQ,CAACL,KAAK,CAAC;EAC3BJ,WAAW,CAACU,WAAW,CAACL,QAAQ,CAAC;EACjCL,WAAW,CAACW,UAAU,CAACL,OAAO,CAAC;EAC/B,IAAIC,MAAM,EAAE;IACVP,WAAW,CAACY,KAAK,CAAC,CAAC;EACrB,CAAC,MAAM;IACLZ,WAAW,CAACa,MAAM,CAAC,CAAC;EACtB;AACF;;AAEA;AACA,OAAO,MAAMD,KAAK,GAAGA,CAAA,KAAMZ,WAAW,CAACY,KAAK,CAAC,CAAC;;AAE9C;AACA,OAAO,MAAMC,MAAM,GAAGA,CAAA,KAAMb,WAAW,CAACa,MAAM,CAAC,CAAC;;AAEhD;AACA,OAAO,MAAMC,KAAK,GAAIT,QAA2B,IAAK;EACpDL,WAAW,CAACc,KAAK,CAACC,KAAK,CAACC,OAAO,CAACX,QAAQ,CAAC,GAAGA,QAAQ,GAAG,CAACA,QAAQ,CAAC,CAAC;AACpE,CAAC;;AAED;AACA,OAAO,MAAMY,OAAO,GAAIC,EAAU,IAAKlB,WAAW,CAACiB,OAAO,CAACC,EAAE,CAAC;;AAE9D;AACA,OAAO,MAAMC,MAAM,GAAIC,OAAsC,IAAK;EAChEpB,WAAW,CAACmB,MAAM,CAACJ,KAAK,CAACC,OAAO,CAACI,OAAO,CAAC,GAAGA,OAAO,GAAG,CAACA,OAAO,CAAC,CAAC;AAClE,CAAC","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import GameEngine from "./GameEngine.js";
|
|
4
|
-
import { configure, pause, resume, spawn, despawn,
|
|
5
|
-
export { GameEngine, configure, pause, resume, spawn, despawn,
|
|
4
|
+
import { configure, pause, resume, spawn, despawn, update } from "./GameMethods.js";
|
|
5
|
+
export { GameEngine, configure, pause, resume, spawn, despawn, update };
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["GameEngine","configure","pause","resume","spawn","despawn","
|
|
1
|
+
{"version":3,"names":["GameEngine","configure","pause","resume","spawn","despawn","update"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,UAAU,MAAM,iBAAc;AACrC,SACEC,SAAS,EACTC,KAAK,EACLC,MAAM,EACNC,KAAK,EACLC,OAAO,EACPC,MAAM,QACD,kBAAe;AAEtB,SAASN,UAAU,EAAEC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAEC,KAAK,EAAEC,OAAO,EAAEC,MAAM","ignoreList":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Config, Entity } from './types';
|
|
1
|
+
import type { Config, Entity, EntityUpdate } from './types';
|
|
2
2
|
/** Sets up the game engine with the given configuration. Call this before anything else. */
|
|
3
3
|
export declare function configure({ tickRate, world, entities, systems, paused, }: Config): void;
|
|
4
4
|
/** Pauses the game loop. Systems will stop running. */
|
|
@@ -9,8 +9,6 @@ export declare const resume: () => void;
|
|
|
9
9
|
export declare const spawn: (entities: Entity | Entity[]) => void;
|
|
10
10
|
/** Removes an entity or all entities matching the given id prefix from the world. */
|
|
11
11
|
export declare const despawn: (id: string) => void;
|
|
12
|
-
/**
|
|
13
|
-
export declare const
|
|
14
|
-
/** Sets the velocity of all entities matching the given id or prefix. */
|
|
15
|
-
export declare const setVelocity: (id: string, vx: number, vy: number) => void;
|
|
12
|
+
/** Updates one or more entities. Only the provided fields are changed. */
|
|
13
|
+
export declare const update: (updates: EntityUpdate | EntityUpdate[]) => void;
|
|
16
14
|
//# sourceMappingURL=GameMethods.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameMethods.d.ts","sourceRoot":"","sources":["../../../src/GameMethods.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"GameMethods.d.ts","sourceRoot":"","sources":["../../../src/GameMethods.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI5D,4FAA4F;AAC5F,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EACR,KAAK,EACL,QAAa,EACb,OAAY,EACZ,MAAa,GACd,EAAE,MAAM,QAUR;AAED,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,SAEhD,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,SAE5D,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { HybridObject } from 'react-native-nitro-modules';
|
|
2
|
-
import type { Entity, System, World } from './types';
|
|
2
|
+
import type { Entity, EntityUpdate, System, World } from './types';
|
|
3
3
|
export interface GameMethods extends HybridObject<{
|
|
4
4
|
ios: 'c++';
|
|
5
5
|
android: 'c++';
|
|
@@ -12,7 +12,6 @@ export interface GameMethods extends HybridObject<{
|
|
|
12
12
|
resume(): void;
|
|
13
13
|
spawn(entities: Entity[]): void;
|
|
14
14
|
despawn(id: string): void;
|
|
15
|
-
|
|
16
|
-
setV(id: string, vx: number, vy: number): void;
|
|
15
|
+
update(updates: EntityUpdate[]): void;
|
|
17
16
|
}
|
|
18
17
|
//# sourceMappingURL=GameMethods.nitro.d.ts.map
|
|
@@ -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,MAAM,EAAE,KAAK,EAAE,MAAM,SAAS,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,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEnE,MAAM,WAAW,WAAY,SAAQ,YAAY,CAAC;IAChD,GAAG,EAAE,KAAK,CAAC;IACX,OAAO,EAAE,KAAK,CAAC;CAChB,CAAC;IACA,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import GameEngine from './GameEngine';
|
|
2
|
-
import { configure, pause, resume, spawn, despawn,
|
|
3
|
-
export { GameEngine, configure, pause, resume, spawn, despawn,
|
|
2
|
+
import { configure, pause, resume, spawn, despawn, update } from './GameMethods';
|
|
3
|
+
export { GameEngine, configure, pause, resume, spawn, despawn, update };
|
|
4
4
|
//# 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;AACtC,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,KAAK,EACL,OAAO,EACP,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,cAAc,CAAC;AACtC,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,KAAK,EACL,OAAO,EACP,MAAM,EACP,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -20,9 +20,9 @@ export type Entity = {
|
|
|
20
20
|
/** Fill color as a hex string e.g. `'#00ff00'`. */
|
|
21
21
|
color: string;
|
|
22
22
|
/** Velocity on the X axis in game units per second. */
|
|
23
|
-
vx
|
|
23
|
+
vx?: number;
|
|
24
24
|
/** Velocity on the Y axis in game units per second. */
|
|
25
|
-
vy
|
|
25
|
+
vy?: number;
|
|
26
26
|
};
|
|
27
27
|
export type System = {
|
|
28
28
|
/** Entity ids or prefixes this system subscribes to. */
|
|
@@ -30,6 +30,24 @@ export type System = {
|
|
|
30
30
|
/** Called every tick with the resolved entities. */
|
|
31
31
|
onTick: (entities: Entity[]) => void;
|
|
32
32
|
};
|
|
33
|
+
export type EntityUpdate = {
|
|
34
|
+
/** Unique identifier or prefix of the entities to update. */
|
|
35
|
+
id: string;
|
|
36
|
+
/** X position in game units. */
|
|
37
|
+
px?: number;
|
|
38
|
+
/** Y position in game units. */
|
|
39
|
+
py?: number;
|
|
40
|
+
/** Width in game units. */
|
|
41
|
+
width?: number;
|
|
42
|
+
/** Height in game units. */
|
|
43
|
+
height?: number;
|
|
44
|
+
/** Fill color as a hex string e.g. `'#00ff00'`. */
|
|
45
|
+
color?: string;
|
|
46
|
+
/** Velocity on the X axis in game units per second. */
|
|
47
|
+
vx?: number;
|
|
48
|
+
/** Velocity on the Y axis in game units per second. */
|
|
49
|
+
vy?: number;
|
|
50
|
+
};
|
|
33
51
|
export type Config = {
|
|
34
52
|
/** Number of game logic updates per second. */
|
|
35
53
|
tickRate: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG;IAClB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,oFAAoF;IACpF,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,EAAE,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG;IAClB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,oFAAoF;IACpF,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,wDAAwD;IACxD,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,oDAAoD;IACpD,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gCAAgC;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,KAAK,EAAE,KAAK,CAAC;IACb,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"}
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
#include <string>
|
|
34
|
+
#include <optional>
|
|
34
35
|
|
|
35
36
|
namespace margelo::nitro::rngine {
|
|
36
37
|
|
|
@@ -45,12 +46,12 @@ namespace margelo::nitro::rngine {
|
|
|
45
46
|
double width SWIFT_PRIVATE;
|
|
46
47
|
double height SWIFT_PRIVATE;
|
|
47
48
|
std::string color SWIFT_PRIVATE;
|
|
48
|
-
double vx SWIFT_PRIVATE;
|
|
49
|
-
double vy SWIFT_PRIVATE;
|
|
49
|
+
std::optional<double> vx SWIFT_PRIVATE;
|
|
50
|
+
std::optional<double> vy SWIFT_PRIVATE;
|
|
50
51
|
|
|
51
52
|
public:
|
|
52
53
|
Entity() = default;
|
|
53
|
-
explicit Entity(std::string id, double px, double py, double width, double height, std::string color, double vx, double vy): id(id), px(px), py(py), width(width), height(height), color(color), vx(vx), vy(vy) {}
|
|
54
|
+
explicit Entity(std::string id, double px, double py, double width, double height, std::string color, std::optional<double> vx, std::optional<double> vy): id(id), px(px), py(py), width(width), height(height), color(color), vx(vx), vy(vy) {}
|
|
54
55
|
|
|
55
56
|
public:
|
|
56
57
|
friend bool operator==(const Entity& lhs, const Entity& rhs) = default;
|
|
@@ -72,8 +73,8 @@ namespace margelo::nitro {
|
|
|
72
73
|
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "width"))),
|
|
73
74
|
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height"))),
|
|
74
75
|
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color"))),
|
|
75
|
-
JSIConverter<double
|
|
76
|
-
JSIConverter<double
|
|
76
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vx"))),
|
|
77
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy")))
|
|
77
78
|
);
|
|
78
79
|
}
|
|
79
80
|
static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::Entity& arg) {
|
|
@@ -84,8 +85,8 @@ namespace margelo::nitro {
|
|
|
84
85
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "width"), JSIConverter<double>::toJSI(runtime, arg.width));
|
|
85
86
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "height"), JSIConverter<double>::toJSI(runtime, arg.height));
|
|
86
87
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "color"), JSIConverter<std::string>::toJSI(runtime, arg.color));
|
|
87
|
-
obj.setProperty(runtime, PropNameIDCache::get(runtime, "vx"), JSIConverter<double
|
|
88
|
-
obj.setProperty(runtime, PropNameIDCache::get(runtime, "vy"), JSIConverter<double
|
|
88
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "vx"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.vx));
|
|
89
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "vy"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.vy));
|
|
89
90
|
return obj;
|
|
90
91
|
}
|
|
91
92
|
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
@@ -102,8 +103,8 @@ namespace margelo::nitro {
|
|
|
102
103
|
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "width")))) return false;
|
|
103
104
|
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height")))) return false;
|
|
104
105
|
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color")))) return false;
|
|
105
|
-
if (!JSIConverter<double
|
|
106
|
-
if (!JSIConverter<double
|
|
106
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vx")))) return false;
|
|
107
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy")))) return false;
|
|
107
108
|
return true;
|
|
108
109
|
}
|
|
109
110
|
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
///
|
|
2
|
+
/// EntityUpdate.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 <string>
|
|
34
|
+
#include <optional>
|
|
35
|
+
|
|
36
|
+
namespace margelo::nitro::rngine {
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A struct which can be represented as a JavaScript object (EntityUpdate).
|
|
40
|
+
*/
|
|
41
|
+
struct EntityUpdate final {
|
|
42
|
+
public:
|
|
43
|
+
std::string id SWIFT_PRIVATE;
|
|
44
|
+
std::optional<double> px SWIFT_PRIVATE;
|
|
45
|
+
std::optional<double> py SWIFT_PRIVATE;
|
|
46
|
+
std::optional<double> width SWIFT_PRIVATE;
|
|
47
|
+
std::optional<double> height SWIFT_PRIVATE;
|
|
48
|
+
std::optional<std::string> color SWIFT_PRIVATE;
|
|
49
|
+
std::optional<double> vx SWIFT_PRIVATE;
|
|
50
|
+
std::optional<double> vy SWIFT_PRIVATE;
|
|
51
|
+
|
|
52
|
+
public:
|
|
53
|
+
EntityUpdate() = default;
|
|
54
|
+
explicit EntityUpdate(std::string id, std::optional<double> px, std::optional<double> py, std::optional<double> width, std::optional<double> height, std::optional<std::string> color, std::optional<double> vx, std::optional<double> vy): id(id), px(px), py(py), width(width), height(height), color(color), vx(vx), vy(vy) {}
|
|
55
|
+
|
|
56
|
+
public:
|
|
57
|
+
friend bool operator==(const EntityUpdate& lhs, const EntityUpdate& rhs) = default;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
} // namespace margelo::nitro::rngine
|
|
61
|
+
|
|
62
|
+
namespace margelo::nitro {
|
|
63
|
+
|
|
64
|
+
// C++ EntityUpdate <> JS EntityUpdate (object)
|
|
65
|
+
template <>
|
|
66
|
+
struct JSIConverter<margelo::nitro::rngine::EntityUpdate> final {
|
|
67
|
+
static inline margelo::nitro::rngine::EntityUpdate fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
|
|
68
|
+
jsi::Object obj = arg.asObject(runtime);
|
|
69
|
+
return margelo::nitro::rngine::EntityUpdate(
|
|
70
|
+
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "id"))),
|
|
71
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px"))),
|
|
72
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "py"))),
|
|
73
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "width"))),
|
|
74
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height"))),
|
|
75
|
+
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color"))),
|
|
76
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vx"))),
|
|
77
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy")))
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::EntityUpdate& arg) {
|
|
81
|
+
jsi::Object obj(runtime);
|
|
82
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "id"), JSIConverter<std::string>::toJSI(runtime, arg.id));
|
|
83
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "px"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.px));
|
|
84
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "py"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.py));
|
|
85
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "width"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.width));
|
|
86
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "height"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.height));
|
|
87
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "color"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.color));
|
|
88
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "vx"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.vx));
|
|
89
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "vy"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.vy));
|
|
90
|
+
return obj;
|
|
91
|
+
}
|
|
92
|
+
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
93
|
+
if (!value.isObject()) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
jsi::Object obj = value.getObject(runtime);
|
|
97
|
+
if (!nitro::isPlainObject(runtime, obj)) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "id")))) return false;
|
|
101
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px")))) return false;
|
|
102
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "py")))) return false;
|
|
103
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "width")))) return false;
|
|
104
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height")))) return false;
|
|
105
|
+
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color")))) return false;
|
|
106
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vx")))) return false;
|
|
107
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy")))) return false;
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
} // namespace margelo::nitro
|
|
@@ -22,8 +22,7 @@ namespace margelo::nitro::rngine {
|
|
|
22
22
|
prototype.registerHybridMethod("resume", &HybridGameMethodsSpec::resume);
|
|
23
23
|
prototype.registerHybridMethod("spawn", &HybridGameMethodsSpec::spawn);
|
|
24
24
|
prototype.registerHybridMethod("despawn", &HybridGameMethodsSpec::despawn);
|
|
25
|
-
prototype.registerHybridMethod("
|
|
26
|
-
prototype.registerHybridMethod("setV", &HybridGameMethodsSpec::setV);
|
|
25
|
+
prototype.registerHybridMethod("update", &HybridGameMethodsSpec::update);
|
|
27
26
|
});
|
|
28
27
|
}
|
|
29
28
|
|
|
@@ -19,12 +19,15 @@ namespace margelo::nitro::rngine { struct World; }
|
|
|
19
19
|
namespace margelo::nitro::rngine { struct Entity; }
|
|
20
20
|
// Forward declaration of `System` to properly resolve imports.
|
|
21
21
|
namespace margelo::nitro::rngine { struct System; }
|
|
22
|
+
// Forward declaration of `EntityUpdate` to properly resolve imports.
|
|
23
|
+
namespace margelo::nitro::rngine { struct EntityUpdate; }
|
|
22
24
|
|
|
23
25
|
#include "World.hpp"
|
|
24
26
|
#include "Entity.hpp"
|
|
25
27
|
#include <vector>
|
|
26
28
|
#include "System.hpp"
|
|
27
29
|
#include <string>
|
|
30
|
+
#include "EntityUpdate.hpp"
|
|
28
31
|
|
|
29
32
|
namespace margelo::nitro::rngine {
|
|
30
33
|
|
|
@@ -65,8 +68,7 @@ namespace margelo::nitro::rngine {
|
|
|
65
68
|
virtual void resume() = 0;
|
|
66
69
|
virtual void spawn(const std::vector<Entity>& entities) = 0;
|
|
67
70
|
virtual void despawn(const std::string& id) = 0;
|
|
68
|
-
virtual void
|
|
69
|
-
virtual void setV(const std::string& id, double vx, double vy) = 0;
|
|
71
|
+
virtual void update(const std::vector<EntityUpdate>& updates) = 0;
|
|
70
72
|
|
|
71
73
|
protected:
|
|
72
74
|
// Hybrid Setup
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rngine",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "React
|
|
3
|
+
"version": "0.3.0",
|
|
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",
|
|
7
7
|
"exports": {
|
package/shared/GameLoop.cpp
CHANGED
|
@@ -64,12 +64,11 @@ std::vector<Rect> GameLoop::getRectsSnapshot() {
|
|
|
64
64
|
continue;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
rects.push_back(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
parseHexColor(entity.color)});
|
|
67
|
+
rects.push_back({std::clamp(entity.px, 0.0, _world.width),
|
|
68
|
+
std::clamp(entity.px + entity.width, 0.0, _world.width),
|
|
69
|
+
std::clamp(entity.py, 0.0, _world.height),
|
|
70
|
+
std::clamp(entity.py + entity.height, 0.0, _world.height),
|
|
71
|
+
parseHexColor(entity.color)});
|
|
73
72
|
}
|
|
74
73
|
return rects;
|
|
75
74
|
}
|
|
@@ -154,8 +153,12 @@ void GameLoop::updateEntities(double deltaTime) {
|
|
|
154
153
|
std::lock_guard<std::mutex> lock(_mutex);
|
|
155
154
|
|
|
156
155
|
for (auto &[id, entity] : _entities) {
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
if (entity.vx) {
|
|
157
|
+
entity.px += *entity.vx * deltaTime;
|
|
158
|
+
}
|
|
159
|
+
if (entity.vy) {
|
|
160
|
+
entity.py += *entity.vy * deltaTime;
|
|
161
|
+
}
|
|
159
162
|
}
|
|
160
163
|
}
|
|
161
164
|
} // namespace margelo::nitro::rngine
|
package/shared/GameMethods.cpp
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#include "GameMethods.hpp"
|
|
2
|
+
#include "EntityUpdate.hpp"
|
|
2
3
|
#include "GameLoop.hpp"
|
|
3
4
|
#include <android/log.h>
|
|
4
5
|
|
|
@@ -99,39 +100,39 @@ void GameMethods::despawn(const std::string &id) {
|
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
|
|
102
|
-
void GameMethods::
|
|
103
|
+
void GameMethods::update(const std::vector<EntityUpdate> &updates) {
|
|
103
104
|
auto &instance = GameLoop::getInstance();
|
|
104
105
|
std::lock_guard<std::mutex> lock(instance.getMutexInternal());
|
|
105
|
-
auto &
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
"setP: entity found, setting px=%f py=%f", px, py);
|
|
115
|
-
it->second.px = px;
|
|
116
|
-
it->second.py = py;
|
|
117
|
-
}
|
|
106
|
+
for (const auto &update : updates) {
|
|
107
|
+
auto resolvedEntitiesInternals =
|
|
108
|
+
instance.resolveEntitiesInternal(update.id);
|
|
109
|
+
if (resolvedEntitiesInternals.empty()) {
|
|
110
|
+
__android_log_print(ANDROID_LOG_WARN, "GameMethods",
|
|
111
|
+
"update: no entity found for id=%s",
|
|
112
|
+
update.id.c_str());
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
118
115
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
116
|
+
for (auto *entity : resolvedEntitiesInternals) {
|
|
117
|
+
if (update.px.has_value())
|
|
118
|
+
entity->px = update.px.value();
|
|
119
|
+
if (update.py.has_value())
|
|
120
|
+
entity->py = update.py.value();
|
|
121
|
+
if (update.width.has_value())
|
|
122
|
+
entity->width = update.width.value();
|
|
123
|
+
if (update.height.has_value())
|
|
124
|
+
entity->height = update.height.value();
|
|
125
|
+
if (update.color.has_value())
|
|
126
|
+
entity->color = update.color.value();
|
|
127
|
+
if (update.vx.has_value())
|
|
128
|
+
entity->vx = update.vx.value();
|
|
129
|
+
if (update.vy.has_value())
|
|
130
|
+
entity->vy = update.vy.value();
|
|
131
|
+
}
|
|
123
132
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
for (auto *entity : resolvedEntitiesInternals) {
|
|
130
|
-
entity->vx = vx;
|
|
131
|
-
entity->vy = vy;
|
|
133
|
+
__android_log_print(ANDROID_LOG_INFO, "GameMethods",
|
|
134
|
+
"update: patched %zu entities for id=%s",
|
|
135
|
+
resolvedEntitiesInternals.size(), update.id.c_str());
|
|
132
136
|
}
|
|
133
|
-
__android_log_print(ANDROID_LOG_INFO, "GameMethods",
|
|
134
|
-
"setV: set vx=%f vy=%f for %zu entities matching id=%s",
|
|
135
|
-
vx, vy, resolvedEntitiesInternals.size(), id.c_str());
|
|
136
137
|
}
|
|
137
138
|
} // namespace margelo::nitro::rngine
|
package/shared/GameMethods.hpp
CHANGED
|
@@ -14,7 +14,6 @@ public:
|
|
|
14
14
|
void resume() override;
|
|
15
15
|
void spawn(const std::vector<Entity> &entities) override;
|
|
16
16
|
void despawn(const std::string &id) override;
|
|
17
|
-
void
|
|
18
|
-
void setV(const std::string &id, double vx, double vy) override;
|
|
17
|
+
void update(const std::vector<EntityUpdate> &updates) override;
|
|
19
18
|
};
|
|
20
19
|
} // namespace margelo::nitro::rngine
|
package/src/GameMethods.nitro.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { HybridObject } from 'react-native-nitro-modules';
|
|
2
|
-
import type { Entity, System, World } from './types';
|
|
2
|
+
import type { Entity, EntityUpdate, System, World } from './types';
|
|
3
3
|
|
|
4
4
|
export interface GameMethods extends HybridObject<{
|
|
5
5
|
ios: 'c++';
|
|
@@ -13,6 +13,5 @@ export interface GameMethods extends HybridObject<{
|
|
|
13
13
|
resume(): void;
|
|
14
14
|
spawn(entities: Entity[]): void;
|
|
15
15
|
despawn(id: string): void;
|
|
16
|
-
|
|
17
|
-
setV(id: string, vx: number, vy: number): void;
|
|
16
|
+
update(updates: EntityUpdate[]): void;
|
|
18
17
|
}
|
package/src/GameMethods.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
2
2
|
import type { GameMethods } from './GameMethods.nitro';
|
|
3
|
-
import type { Config, Entity } from './types';
|
|
3
|
+
import type { Config, Entity, EntityUpdate } from './types';
|
|
4
4
|
|
|
5
5
|
const gameMethods = NitroModules.createHybridObject<GameMethods>('GameMethods');
|
|
6
6
|
|
|
@@ -37,10 +37,7 @@ export const spawn = (entities: Entity | Entity[]) => {
|
|
|
37
37
|
/** Removes an entity or all entities matching the given id prefix from the world. */
|
|
38
38
|
export const despawn = (id: string) => gameMethods.despawn(id);
|
|
39
39
|
|
|
40
|
-
/**
|
|
41
|
-
export const
|
|
42
|
-
gameMethods.
|
|
43
|
-
|
|
44
|
-
/** Sets the velocity of all entities matching the given id or prefix. */
|
|
45
|
-
export const setVelocity = (id: string, vx: number, vy: number) =>
|
|
46
|
-
gameMethods.setV(id, vx, vy);
|
|
40
|
+
/** Updates one or more entities. Only the provided fields are changed. */
|
|
41
|
+
export const update = (updates: EntityUpdate | EntityUpdate[]) => {
|
|
42
|
+
gameMethods.update(Array.isArray(updates) ? updates : [updates]);
|
|
43
|
+
};
|
package/src/index.tsx
CHANGED
|
@@ -5,17 +5,7 @@ import {
|
|
|
5
5
|
resume,
|
|
6
6
|
spawn,
|
|
7
7
|
despawn,
|
|
8
|
-
|
|
9
|
-
setVelocity,
|
|
8
|
+
update,
|
|
10
9
|
} from './GameMethods';
|
|
11
10
|
|
|
12
|
-
export {
|
|
13
|
-
GameEngine,
|
|
14
|
-
configure,
|
|
15
|
-
pause,
|
|
16
|
-
resume,
|
|
17
|
-
spawn,
|
|
18
|
-
despawn,
|
|
19
|
-
setPosition,
|
|
20
|
-
setVelocity,
|
|
21
|
-
};
|
|
11
|
+
export { GameEngine, configure, pause, resume, spawn, despawn, update };
|
package/src/types.ts
CHANGED
|
@@ -21,9 +21,9 @@ export type Entity = {
|
|
|
21
21
|
/** Fill color as a hex string e.g. `'#00ff00'`. */
|
|
22
22
|
color: string;
|
|
23
23
|
/** Velocity on the X axis in game units per second. */
|
|
24
|
-
vx
|
|
24
|
+
vx?: number;
|
|
25
25
|
/** Velocity on the Y axis in game units per second. */
|
|
26
|
-
vy
|
|
26
|
+
vy?: number;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
export type System = {
|
|
@@ -33,6 +33,25 @@ export type System = {
|
|
|
33
33
|
onTick: (entities: Entity[]) => void;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
+
export type EntityUpdate = {
|
|
37
|
+
/** Unique identifier or prefix of the entities to update. */
|
|
38
|
+
id: string;
|
|
39
|
+
/** X position in game units. */
|
|
40
|
+
px?: number;
|
|
41
|
+
/** Y position in game units. */
|
|
42
|
+
py?: number;
|
|
43
|
+
/** Width in game units. */
|
|
44
|
+
width?: number;
|
|
45
|
+
/** Height in game units. */
|
|
46
|
+
height?: number;
|
|
47
|
+
/** Fill color as a hex string e.g. `'#00ff00'`. */
|
|
48
|
+
color?: string;
|
|
49
|
+
/** Velocity on the X axis in game units per second. */
|
|
50
|
+
vx?: number;
|
|
51
|
+
/** Velocity on the Y axis in game units per second. */
|
|
52
|
+
vy?: number;
|
|
53
|
+
};
|
|
54
|
+
|
|
36
55
|
export type Config = {
|
|
37
56
|
/** Number of game logic updates per second. */
|
|
38
57
|
tickRate: number;
|