rngine 0.4.2 → 0.6.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.
Files changed (60) hide show
  1. package/README.md +1 -1
  2. package/android/kls_database.db +0 -0
  3. package/android/src/main/cpp/GameLoopJNI.cpp +84 -27
  4. package/android/src/main/java/com/margelo/nitro/rngine/GameAssets.kt +34 -20
  5. package/android/src/main/java/com/margelo/nitro/rngine/GameView.kt +80 -48
  6. package/android/src/main/java/com/margelo/nitro/rngine/Rect.kt +2 -2
  7. package/android/src/main/java/com/margelo/nitro/rngine/Screen.kt +9 -0
  8. package/android/src/main/java/com/margelo/nitro/rngine/Snapshot.kt +3 -0
  9. package/android/src/main/java/com/margelo/nitro/rngine/SnapshotSerializer.kt +33 -0
  10. package/lib/module/GameAssets.js +41 -0
  11. package/lib/module/GameAssets.js.map +1 -0
  12. package/lib/module/GameEngine.js +1 -1
  13. package/lib/module/GameEngine.js.map +1 -1
  14. package/lib/module/GameMethods.js +43 -0
  15. package/lib/module/GameMethods.js.map +1 -1
  16. package/lib/module/index.js +1 -1
  17. package/lib/module/index.js.map +1 -1
  18. package/lib/typescript/src/GameAssets.d.ts +2 -0
  19. package/lib/typescript/src/GameAssets.d.ts.map +1 -0
  20. package/lib/typescript/src/GameAssets.nitro.d.ts +2 -2
  21. package/lib/typescript/src/GameAssets.nitro.d.ts.map +1 -1
  22. package/lib/typescript/src/GameMethods.d.ts +8 -0
  23. package/lib/typescript/src/GameMethods.d.ts.map +1 -1
  24. package/lib/typescript/src/index.d.ts +2 -1
  25. package/lib/typescript/src/index.d.ts.map +1 -1
  26. package/lib/typescript/src/nativeTypes.d.ts +25 -44
  27. package/lib/typescript/src/nativeTypes.d.ts.map +1 -1
  28. package/lib/typescript/src/types.d.ts +2 -15
  29. package/lib/typescript/src/types.d.ts.map +1 -1
  30. package/nitrogen/generated/android/c++/JHybridGameAssetsSpec.cpp +31 -6
  31. package/nitrogen/generated/android/c++/JHybridGameAssetsSpec.hpp +2 -2
  32. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngine/HybridGameAssetsSpec.kt +3 -2
  33. package/nitrogen/generated/ios/Rngine-Swift-Cxx-Bridge.cpp +16 -0
  34. package/nitrogen/generated/ios/Rngine-Swift-Cxx-Bridge.hpp +65 -6
  35. package/nitrogen/generated/ios/Rngine-Swift-Cxx-Umbrella.hpp +1 -0
  36. package/nitrogen/generated/ios/c++/HybridGameAssetsSpecSwift.hpp +7 -2
  37. package/nitrogen/generated/ios/swift/Func_void.swift +46 -0
  38. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
  39. package/nitrogen/generated/ios/swift/HybridGameAssetsSpec.swift +2 -2
  40. package/nitrogen/generated/ios/swift/HybridGameAssetsSpec_cxx.swift +24 -8
  41. package/nitrogen/generated/shared/c++/HybridGameAssetsSpec.hpp +3 -2
  42. package/package.json +1 -1
  43. package/shared/GameLoop.cpp +11 -38
  44. package/shared/GameLoop.hpp +0 -2
  45. package/shared/GameMethods.cpp +2 -0
  46. package/src/GameAssets.nitro.ts +2 -2
  47. package/src/GameAssets.ts +47 -0
  48. package/src/GameEngine.tsx +1 -1
  49. package/src/GameMethods.ts +48 -0
  50. package/src/index.tsx +8 -1
  51. package/src/nativeTypes.ts +31 -46
  52. package/src/types.ts +3 -19
  53. package/android/src/main/java/com/margelo/nitro/rngine/RectSerializer.kt +0 -25
  54. package/lib/module/Shared.js +0 -85
  55. package/lib/module/Shared.js.map +0 -1
  56. package/lib/typescript/src/Shared.d.ts +0 -8
  57. package/lib/typescript/src/Shared.d.ts.map +0 -1
  58. package/shared/Rect.hpp +0 -16
  59. package/src/Shared.ts +0 -99
  60. /package/{shared → android/src/main/cpp}/ColorUtils.hpp +0 -0
package/README.md CHANGED
@@ -72,7 +72,7 @@ export default function App() {
72
72
 
73
73
  **Entities** are the objects in your game world. Each entity has a position, size, color, and velocity. See [`Entity`](./src/nativeTypes.ts).
74
74
 
75
- **Systems** define your game logic. Each system optionally declares which entities it cares about via `entities`, which collision pairs to watch via `collisions`, or both. Systems run every tick receiving the resolved entities and any active collisions. See [`System`](./src/nativeTypes.ts).
75
+ **Systems** define your game logic. Each system optionally declares which entities it cares about via `entities`, which collision pairs to watch via `collisions`, or both. Systems run every tick receiving the resolved entities and any active collisions. See [`System`](./src/types.ts).
76
76
 
77
77
  **Screen** defines the viewport dimensions and background color. Entities outside the screen bounds are automatically clipped. See [`Screen`](./src/nativeTypes.ts).
78
78
 
Binary file
@@ -1,36 +1,93 @@
1
+ #include "ColorUtils.hpp"
1
2
  #include "GameLoop.hpp"
3
+ #include <cstdint>
2
4
  #include <jni.h>
5
+ #include <mutex>
3
6
 
4
7
  extern "C" {
5
- JNIEXPORT jobject JNICALL
6
- Java_com_margelo_nitro_rngine_GameView_getRectsSnapshot(JNIEnv *env, jobject) {
7
- auto rects =
8
- margelo::nitro::rngine::GameLoop::getInstance().getRectsSnapshot();
9
- const size_t size = rects.size() * margelo::nitro::rngine::RECT_SIZE;
10
-
11
- static std::vector<uint8_t> buffer;
12
- buffer.resize(size);
13
-
14
- uint8_t *data = buffer.data();
15
-
16
- for (const auto &rect : rects) {
17
- memcpy(data, &rect.left, sizeof(float));
18
- data += sizeof(float);
19
- memcpy(data, &rect.right, sizeof(float));
20
- data += sizeof(float);
21
- memcpy(data, &rect.top, sizeof(float));
22
- data += sizeof(float);
23
- memcpy(data, &rect.bottom, sizeof(float));
24
- data += sizeof(float);
25
- memcpy(data, &rect.progress, sizeof(float));
26
- data += sizeof(float);
27
- memcpy(data, &rect.color, sizeof(uint32_t));
28
- data += sizeof(uint32_t);
29
- memcpy(data, &rect.asset, sizeof(int32_t));
30
- data += sizeof(int32_t);
8
+ JNIEXPORT jbyteArray JNICALL
9
+ Java_com_margelo_nitro_rngine_GameView_getSnapshot(JNIEnv *env, jobject) {
10
+ auto &gameLoop = margelo::nitro::rngine::GameLoop::getInstance();
11
+ auto &snapshotMutex = gameLoop.getSnapshotMutexInternal();
12
+
13
+ std::lock_guard<std::mutex> snapshotLock(snapshotMutex);
14
+ auto &screenSnapshot = gameLoop.getScreenSnapshotInternal();
15
+ auto &entitiesSnapshot = gameLoop.getEntitiesSnapshotInternal();
16
+
17
+ std::vector<uint8_t> buffer;
18
+
19
+ auto writeFloat = [&](float v) {
20
+ const auto *bytes = reinterpret_cast<const uint8_t *>(&v);
21
+ buffer.insert(buffer.end(), bytes, bytes + sizeof(float));
22
+ };
23
+ auto writeI32 = [&](int32_t v) {
24
+ const auto *bytes = reinterpret_cast<const uint8_t *>(&v);
25
+ buffer.insert(buffer.end(), bytes, bytes + sizeof(int32_t));
26
+ };
27
+ auto writeU32 = [&](uint32_t v) {
28
+ const auto *bytes = reinterpret_cast<const uint8_t *>(&v);
29
+ buffer.insert(buffer.end(), bytes, bytes + sizeof(uint32_t));
30
+ };
31
+
32
+ const auto screenSnapshotWidth = static_cast<float>(screenSnapshot.width);
33
+ const auto screenSnapshotHeight = static_cast<float>(screenSnapshot.height);
34
+ const auto screenSnapshotColor =
35
+ margelo::nitro::rngine::parseHexColor(screenSnapshot.color);
36
+ const auto screenSnapshotAsset =
37
+ static_cast<int32_t>(screenSnapshot.asset.value_or(0));
38
+
39
+ writeFloat(screenSnapshotWidth);
40
+ writeFloat(screenSnapshotHeight);
41
+ writeU32(screenSnapshotColor);
42
+ writeI32(screenSnapshotAsset);
43
+
44
+ if (screenSnapshotAsset < 0) {
45
+ writeFloat(static_cast<float>(screenSnapshot.progress.value_or(0)));
46
+ }
47
+
48
+ for (const auto &[_, entitySnapshot] : entitiesSnapshot) {
49
+ const auto entitySnapshotLeft =
50
+ static_cast<float>(entitySnapshot.px - (entitySnapshot.width / 2));
51
+ const auto entitySnapshotRight =
52
+ static_cast<float>(entitySnapshot.px + (entitySnapshot.width / 2));
53
+ const auto entitySnapshotTop =
54
+ static_cast<float>(entitySnapshot.py - (entitySnapshot.height / 2));
55
+ const auto entitySnapshotBottom =
56
+ static_cast<float>(entitySnapshot.py + (entitySnapshot.height / 2));
57
+
58
+ if (entitySnapshotRight < 0 || entitySnapshotLeft > screenSnapshot.width ||
59
+ entitySnapshotBottom < 0 || entitySnapshotTop > screenSnapshot.height) {
60
+ continue;
61
+ }
62
+
63
+ const auto entitySnapshotColor =
64
+ margelo::nitro::rngine::parseHexColor(entitySnapshot.color);
65
+ const auto entitySnapshotAsset =
66
+ static_cast<int32_t>(entitySnapshot.asset.value_or(0));
67
+
68
+ writeFloat(entitySnapshotLeft);
69
+ writeFloat(entitySnapshotRight);
70
+ writeFloat(entitySnapshotTop);
71
+ writeFloat(entitySnapshotBottom);
72
+ writeU32(entitySnapshotColor);
73
+ writeI32(entitySnapshotAsset);
74
+
75
+ if (entitySnapshotAsset < 0) {
76
+ writeFloat(static_cast<float>(entitySnapshot.progress.value_or(0)));
77
+ }
31
78
  }
32
79
 
33
- return env->NewDirectByteBuffer(buffer.data(), (jlong)size);
80
+ auto bufferSize = static_cast<jsize>(buffer.size());
81
+ jbyteArray result = env->NewByteArray(bufferSize);
82
+
83
+ if (result == nullptr) {
84
+ return nullptr;
85
+ }
86
+
87
+ env->SetByteArrayRegion(result, 0, bufferSize,
88
+ reinterpret_cast<const jbyte *>(buffer.data()));
89
+
90
+ return result;
34
91
  }
35
92
 
36
93
  JNIEXPORT void JNICALL
@@ -4,7 +4,9 @@ import android.util.Log
4
4
  import com.airbnb.lottie.LottieCompositionFactory
5
5
  import com.airbnb.lottie.LottieDrawable
6
6
  import com.caverock.androidsvg.SVG
7
+ import com.margelo.nitro.core.Promise
7
8
  import java.net.URL
9
+ import com.margelo.nitro.NitroModules
8
10
 
9
11
  class GameAssets : HybridGameAssetsSpec() {
10
12
  private external fun registerLottieDuration(id: Double, duration: Double)
@@ -18,30 +20,42 @@ class GameAssets : HybridGameAssetsSpec() {
18
20
  return id.toInt() in assetCache
19
21
  }
20
22
 
21
- override fun registerSvg(id: Double, uri: String) {
22
- try {
23
- val stream = URL(uri).openStream()
24
- assetCache[id.toInt()] = Asset.Svg(SVG.getFromInputStream(stream).renderToPicture())
25
- Log.d("GameAssets", "assetCache: $assetCache")
26
- } catch (e: Exception) {
27
- Log.e("GameAssets", "Failed to parse SVG: $uri", e)
23
+ override fun registerSvg(id: Double, uri: String): Promise<Unit> {
24
+ return Promise.async {
25
+ try {
26
+ val stream = if (uri.startsWith("http://") || uri.startsWith("https://")) {
27
+ URL(uri).openStream()
28
+ } else {
29
+ val context = NitroModules.applicationContext ?: throw Error("No Context available!")
30
+ val resId = context.resources.getIdentifier(uri, "raw", context.packageName)
31
+ if (resId == 0) {
32
+ throw IllegalStateException("Could not resolve drawable resource for asset: $uri")
33
+ }
34
+ context.resources.openRawResource(resId)
35
+ }
36
+ assetCache[id.toInt()] = Asset.Svg(SVG.getFromInputStream(stream).renderToPicture())
37
+ Log.d("GameAssets", "assetCache: $assetCache")
38
+ } catch (e: Exception) {
39
+ Log.e("GameAssets", "Failed to parse SVG: $uri", e)
40
+ throw e
41
+ }
28
42
  }
29
43
  }
30
44
 
31
- override fun registerLottie(id: Double, json: String) {
32
- try {
33
- val composition = LottieCompositionFactory.fromJsonStringSync(json, null).value
34
- if (composition == null) {
35
- Log.e("GameAssets", "Failed to parse Lottie JSON for id: $id")
36
- return
45
+ override fun registerLottie(id: Double, json: String): Promise<Unit> {
46
+ return Promise.async {
47
+ try {
48
+ val composition = LottieCompositionFactory.fromJsonStringSync(json, null).value
49
+ ?: throw IllegalStateException("Failed to parse Lottie JSON for id: $id")
50
+ val drawable = LottieDrawable()
51
+ drawable.composition = composition
52
+ assetCache[id.toInt()] = Asset.Lottie(drawable)
53
+ registerLottieDuration(id, composition.duration.toDouble() / 1000)
54
+ Log.d("GameAssets", "assetCache: $assetCache")
55
+ } catch (e: Exception) {
56
+ Log.e("GameAssets", "Failed to register Lottie: $id", e)
57
+ throw e
37
58
  }
38
- val drawable = LottieDrawable()
39
- drawable.composition = composition
40
- assetCache[id.toInt()] = Asset.Lottie(drawable)
41
- registerLottieDuration(id, composition.duration.toDouble() / 1000)
42
- Log.d("GameAssets", "assetCache: $assetCache")
43
- } catch (e: Exception) {
44
- Log.e("GameAssets", "Failed to register Lottie: $id", e)
45
59
  }
46
60
  }
47
61
  }
@@ -4,10 +4,8 @@ import android.content.Context
4
4
  import android.graphics.Color
5
5
  import android.graphics.Paint
6
6
  import android.util.AttributeSet
7
- import android.util.Log
8
7
  import android.view.SurfaceView
9
8
  import android.view.View
10
- import java.nio.ByteBuffer
11
9
  import androidx.core.graphics.withTranslation
12
10
  import androidx.core.graphics.withClip
13
11
 
@@ -20,7 +18,7 @@ class GameView(
20
18
  attrs,
21
19
  defStyleAttr,
22
20
  ) {
23
- private external fun getRectsSnapshot(): ByteBuffer
21
+ private external fun getSnapshot(): ByteArray
24
22
  var onAttached: () -> Unit = {}
25
23
  var onDetached: () -> Unit = {}
26
24
 
@@ -29,6 +27,48 @@ class GameView(
29
27
  style = Paint.Style.FILL
30
28
  }
31
29
 
30
+ private fun drawRenderable(
31
+ canvas: android.graphics.Canvas,
32
+ left: Float,
33
+ top: Float,
34
+ right: Float,
35
+ bottom: Float,
36
+ color: Int,
37
+ asset: Int,
38
+ progress: Float?,
39
+ clampedLeft: Float = left,
40
+ clampedTop: Float = top,
41
+ clampedRight: Float = right,
42
+ clampedBottom: Float = bottom,
43
+ ) {
44
+ paint.color = color
45
+ canvas.drawRect(clampedLeft, clampedTop, clampedRight, clampedBottom, paint)
46
+
47
+ canvas.withClip(clampedLeft, clampedTop, clampedRight, clampedBottom) {
48
+ withTranslation(left, top) {
49
+ when (val resolvedAsset = GameAssets.getAsset(asset)) {
50
+ is Asset.Svg -> {
51
+ scale(
52
+ (right - left) / resolvedAsset.picture.width,
53
+ (bottom - top) / resolvedAsset.picture.height
54
+ )
55
+ drawPicture(resolvedAsset.picture)
56
+ }
57
+
58
+ is Asset.Lottie -> {
59
+ progress?.let {
60
+ resolvedAsset.drawable.progress = it
61
+ }
62
+ resolvedAsset.drawable.setBounds(0, 0, (right - left).toInt(), (bottom - top).toInt())
63
+ resolvedAsset.drawable.draw(canvas)
64
+ }
65
+
66
+ null -> {}
67
+ }
68
+ }
69
+ }
70
+ }
71
+
32
72
  init {
33
73
  addOnAttachStateChangeListener(
34
74
  object : OnAttachStateChangeListener {
@@ -40,61 +80,53 @@ class GameView(
40
80
  fun drawFrame() {
41
81
  if (!holder.surface.isValid) return
42
82
  val canvas = holder.lockCanvas() ?: return
83
+ val snapshot = SnapshotSerializer.decode(getSnapshot())
43
84
 
44
- val rects = RectSerializer.decode(getRectsSnapshot())
45
-
46
- val worldRect = rects.first()
47
- val scaleX = canvas.width / worldRect.right
48
- val scaleY = canvas.height / worldRect.bottom
85
+ val scaleX = canvas.width / snapshot.screen.width
86
+ val scaleY = canvas.height / snapshot.screen.height
49
87
  val scale = minOf(scaleX, scaleY)
50
88
 
51
- val offsetX = (canvas.width - worldRect.right * scale) / 2f
52
- val offsetY = (canvas.height - worldRect.bottom * scale) / 2f
89
+ val screenLeft = (canvas.width - snapshot.screen.width * scale) / 2f
90
+ val screenTop = (canvas.height - snapshot.screen.height * scale) / 2f
91
+ val screenRight = screenLeft + snapshot.screen.width * scale
92
+ val screenBottom = screenTop + snapshot.screen.height * scale
93
+
94
+ drawRenderable(
95
+ canvas,
96
+ screenLeft,
97
+ screenTop,
98
+ screenRight,
99
+ screenBottom,
100
+ snapshot.screen.color,
101
+ snapshot.screen.asset,
102
+ snapshot.screen.progress,
103
+ )
53
104
 
54
- rects.forEach { rect ->
55
- val left = rect.left * scale + offsetX
56
- val top = rect.top * scale + offsetY
57
- val right = rect.right * scale + offsetX
58
- val bottom = rect.bottom * scale + offsetY
105
+ snapshot.rects.forEach { rect ->
106
+ val left = rect.left * scale + screenLeft
107
+ val top = rect.top * scale + screenTop
108
+ val right = rect.right * scale + screenLeft
109
+ val bottom = rect.bottom * scale + screenTop
59
110
 
60
- val clampedLeft = left.coerceAtLeast(offsetX)
61
- val clampedTop = top.coerceAtLeast(offsetY)
62
- val clampedRight = right.coerceAtMost(offsetX + worldRect.right * scale)
63
- val clampedBottom = bottom.coerceAtMost(offsetY + worldRect.bottom * scale)
111
+ val clampedLeft = left.coerceAtLeast(screenLeft)
112
+ val clampedTop = top.coerceAtLeast(screenTop)
113
+ val clampedRight = right.coerceAtMost(screenLeft + snapshot.screen.width * scale)
114
+ val clampedBottom = bottom.coerceAtMost(screenTop + snapshot.screen.height * scale)
64
115
 
65
- paint.color = rect.color
66
- canvas.drawRect(
116
+ drawRenderable(
117
+ canvas,
118
+ left,
119
+ top,
120
+ right,
121
+ bottom,
122
+ rect.color,
123
+ rect.asset,
124
+ rect.progress,
67
125
  clampedLeft,
68
126
  clampedTop,
69
127
  clampedRight,
70
- clampedBottom,
71
- paint
128
+ clampedBottom
72
129
  )
73
- when(val asset = GameAssets.getAsset(rect.asset)){
74
- is Asset.Svg -> {
75
- canvas.withClip(clampedLeft, clampedTop, clampedRight, clampedBottom) {
76
- withTranslation(left, top) {
77
- scale(
78
- (right - left) / asset.picture.width,
79
- (bottom - top) / asset.picture.height
80
- )
81
- drawPicture(asset.picture)
82
- }
83
- }
84
- }
85
-
86
- is Asset.Lottie -> {
87
- canvas.withClip(clampedLeft, clampedTop, clampedRight, clampedBottom) {
88
- withTranslation(left, top) {
89
- asset.drawable.progress = rect.progress
90
- asset.drawable.setBounds(0, 0, (right - left).toInt(), (bottom - top).toInt())
91
- asset.drawable.draw(canvas)
92
- }
93
- }
94
- }
95
-
96
- null -> {}
97
- }
98
130
  }
99
131
  holder.unlockCanvasAndPost(canvas)
100
132
  }
@@ -5,7 +5,7 @@ data class Rect(
5
5
  val right: Float,
6
6
  val top: Float,
7
7
  val bottom: Float,
8
- val progress: Float,
9
8
  val color: Int,
10
- val asset: Int
9
+ val asset: Int,
10
+ val progress: Float?,
11
11
  )
@@ -0,0 +1,9 @@
1
+ package com.margelo.nitro.rngine
2
+
3
+ data class Screen(
4
+ val width: Float,
5
+ val height: Float,
6
+ val color: Int,
7
+ val asset: Int,
8
+ val progress: Float?,
9
+ )
@@ -0,0 +1,3 @@
1
+ package com.margelo.nitro.rngine
2
+
3
+ data class Snapshot(val screen: Screen, val rects: List<Rect>)
@@ -0,0 +1,33 @@
1
+ package com.margelo.nitro.rngine
2
+
3
+ import java.nio.ByteBuffer
4
+ import java.nio.ByteOrder
5
+
6
+ object SnapshotSerializer {
7
+ fun decode(bytes: ByteArray): Snapshot {
8
+ val buffer = ByteBuffer.wrap(bytes).order(ByteOrder.nativeOrder())
9
+
10
+ val width = buffer.float
11
+ val height = buffer.float
12
+ val color = buffer.int
13
+ val asset = buffer.int
14
+ val progress = if (asset < 0) buffer.float else null
15
+
16
+ val screen = Screen(width, height, color, asset, progress)
17
+ val rects = ArrayList<Rect>()
18
+
19
+ while (buffer.remaining() >= 24) {
20
+ val left = buffer.float
21
+ val right = buffer.float
22
+ val top = buffer.float
23
+ val bottom = buffer.float
24
+ val color = buffer.int
25
+ val asset = buffer.int
26
+ val progress = if (asset < 0) buffer.float else null
27
+
28
+ rects.add(Rect(left, right, top, bottom, color, asset, progress))
29
+ }
30
+
31
+ return Snapshot(screen, rects)
32
+ }
33
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ import { Image } from 'react-native';
4
+ import { gameAssets } from "./GameAssets.nitro.js";
5
+ const assetCache = new WeakMap();
6
+ let nextId = -1;
7
+ const loadAsset = async asset => {
8
+ switch (typeof asset) {
9
+ case 'object':
10
+ if (asset === null) {
11
+ throw new Error('loadAssets: asset cannot be null');
12
+ }
13
+ if (assetCache.has(asset)) {
14
+ return assetCache.get(asset);
15
+ }
16
+ const assetId = nextId--;
17
+ assetCache.set(asset, assetId);
18
+ await gameAssets.registerLottie(assetId, JSON.stringify(asset));
19
+ return assetId;
20
+ case 'number':
21
+ if (gameAssets.isAssetRegistered(asset)) {
22
+ return asset;
23
+ }
24
+ const assetUri = Image.resolveAssetSource(asset)?.uri;
25
+ if (!assetUri) {
26
+ throw new Error(`loadAssets: could not resolve asset URI for ${asset}`);
27
+ }
28
+ await gameAssets.registerSvg(asset, assetUri);
29
+ return asset;
30
+ }
31
+ throw new Error(`loadAssets: unsupported asset type "${typeof asset}"`);
32
+ };
33
+ export const loadAssets = async assets => {
34
+ const keys = Object.keys(assets);
35
+ const result = {};
36
+ for (const key of keys) {
37
+ result[key] = await loadAsset(assets[key]);
38
+ }
39
+ return result;
40
+ };
41
+ //# sourceMappingURL=GameAssets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Image","gameAssets","assetCache","WeakMap","nextId","loadAsset","asset","Error","has","get","assetId","set","registerLottie","JSON","stringify","isAssetRegistered","assetUri","resolveAssetSource","uri","registerSvg","loadAssets","assets","keys","Object","result","key"],"sourceRoot":"../../src","sources":["GameAssets.ts"],"mappings":";;AAAA,SAASA,KAAK,QAAQ,cAAc;AACpC,SAASC,UAAU,QAAQ,uBAAoB;AAE/C,MAAMC,UAAU,GAAG,IAAIC,OAAO,CAAiB,CAAC;AAChD,IAAIC,MAAM,GAAG,CAAC,CAAC;AAEf,MAAMC,SAAS,GAAG,MAAOC,KAAc,IAAK;EAC1C,QAAQ,OAAOA,KAAK;IAClB,KAAK,QAAQ;MACX,IAAIA,KAAK,KAAK,IAAI,EAAE;QAClB,MAAM,IAAIC,KAAK,CAAC,kCAAkC,CAAC;MACrD;MACA,IAAIL,UAAU,CAACM,GAAG,CAACF,KAAK,CAAC,EAAE;QACzB,OAAOJ,UAAU,CAACO,GAAG,CAACH,KAAK,CAAC;MAC9B;MACA,MAAMI,OAAO,GAAGN,MAAM,EAAE;MACxBF,UAAU,CAACS,GAAG,CAACL,KAAK,EAAEI,OAAO,CAAC;MAC9B,MAAMT,UAAU,CAACW,cAAc,CAACF,OAAO,EAAEG,IAAI,CAACC,SAAS,CAACR,KAAK,CAAC,CAAC;MAC/D,OAAOI,OAAO;IAEhB,KAAK,QAAQ;MACX,IAAIT,UAAU,CAACc,iBAAiB,CAACT,KAAK,CAAC,EAAE;QACvC,OAAOA,KAAK;MACd;MACA,MAAMU,QAAQ,GAAGhB,KAAK,CAACiB,kBAAkB,CAACX,KAAK,CAAC,EAAEY,GAAG;MACrD,IAAI,CAACF,QAAQ,EAAE;QACb,MAAM,IAAIT,KAAK,CAAC,+CAA+CD,KAAK,EAAE,CAAC;MACzE;MACA,MAAML,UAAU,CAACkB,WAAW,CAACb,KAAK,EAAEU,QAAQ,CAAC;MAC7C,OAAOV,KAAK;EAChB;EAEA,MAAM,IAAIC,KAAK,CAAC,uCAAuC,OAAOD,KAAK,GAAG,CAAC;AACzE,CAAC;AAED,OAAO,MAAMc,UAAU,GAAG,MACxBC,MAAS,IAC+B;EACxC,MAAMC,IAAI,GAAGC,MAAM,CAACD,IAAI,CAACD,MAAM,CAAgB;EAC/C,MAAMG,MAAM,GAAG,CAAC,CAA+B;EAE/C,KAAK,MAAMC,GAAG,IAAIH,IAAI,EAAE;IACtBE,MAAM,CAACC,GAAG,CAAC,GAAG,MAAMpB,SAAS,CAACgB,MAAM,CAACI,GAAG,CAAC,CAAC;EAC5C;EAEA,OAAOD,MAAM;AACf,CAAC","ignoreList":[]}
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  import { getHostComponent } from 'react-native-nitro-modules';
4
- const GameEngineConfig = require('../nitrogen/generated/shared/json/GameEngineConfig.json');
4
+ import GameEngineConfig from '../nitrogen/generated/shared/json/GameEngineConfig.json';
5
5
  /**
6
6
  * A game engine view component that renders the game world.
7
7
  * Size it using the style prop like any other React Native view.
@@ -1 +1 @@
1
- {"version":3,"names":["getHostComponent","GameEngineConfig","require"],"sourceRoot":"../../src","sources":["GameEngine.tsx"],"mappings":";;AAAA,SAASA,gBAAgB,QAAQ,4BAA4B;AAC7D,MAAMC,gBAAgB,GAAGC,OAAO,CAAC,yDAAyD,CAAC;AAG3F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAeF,gBAAgB,CAC7B,YAAY,EACZ,MAAMC,gBACR,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["getHostComponent","GameEngineConfig"],"sourceRoot":"../../src","sources":["GameEngine.tsx"],"mappings":";;AAAA,SAASA,gBAAgB,QAAQ,4BAA4B;AAC7D,OAAOC,gBAAgB,MAAM,yDAAyD;AAGtF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAeD,gBAAgB,CAC7B,YAAY,EACZ,MAAMC,gBACR,CAAC","ignoreList":[]}
@@ -1,6 +1,37 @@
1
1
  "use strict";
2
2
 
3
3
  import { gameMethods } from "./GameMethods.nitro.js";
4
+ /** Sets up the game engine with the given configuration. Call this before anything else. */
5
+ export const configure = ({
6
+ tickRate,
7
+ screen,
8
+ entities = [],
9
+ systems = [],
10
+ paused = true
11
+ }) => {
12
+ let nativeSystems = [];
13
+ for (const system of systems) {
14
+ nativeSystems.push({
15
+ entities: system.entities,
16
+ collisions: system.collisions,
17
+ onTick: (e, c) => {
18
+ const start = Date.now();
19
+ system.onTick(e, c);
20
+ const finish = Date.now();
21
+ return finish - start;
22
+ }
23
+ });
24
+ }
25
+ gameMethods.setTickRate(tickRate);
26
+ gameMethods.setScreen(screen);
27
+ gameMethods.setEntities(entities);
28
+ gameMethods.setSystems(nativeSystems);
29
+ if (paused) {
30
+ gameMethods.pause();
31
+ } else {
32
+ gameMethods.resume();
33
+ }
34
+ };
4
35
 
5
36
  /** Pauses the game loop. Systems will stop running. */
6
37
  export const pause = () => gameMethods.pause();
@@ -8,6 +39,18 @@ export const pause = () => gameMethods.pause();
8
39
  /** Resumes the game loop. */
9
40
  export const resume = () => gameMethods.resume();
10
41
 
42
+ /** Spawns one or more entities into the world. Skips duplicates by id. */
43
+ export const spawn = entities => {
44
+ const entityArray = Array.isArray(entities) ? entities : [entities];
45
+ gameMethods.spawn(entityArray);
46
+ };
47
+
11
48
  /** Removes an entity or all entities matching the given id prefix from the world. */
12
49
  export const despawn = id => gameMethods.despawn(id);
50
+
51
+ /** Updates one or more entities. Only the provided fields are changed. */
52
+ export const update = updates => {
53
+ const entityUpdateArray = Array.isArray(updates) ? updates : [updates];
54
+ gameMethods.update(entityUpdateArray);
55
+ };
13
56
  //# sourceMappingURL=GameMethods.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["gameMethods","pause","resume","despawn","id"],"sourceRoot":"../../src","sources":["GameMethods.ts"],"mappings":";;AAAA,SAASA,WAAW,QAAQ,wBAAqB;;AAEjD;AACA,OAAO,MAAMC,KAAK,GAAGA,CAAA,KAAMD,WAAW,CAACC,KAAK,CAAC,CAAC;;AAE9C;AACA,OAAO,MAAMC,MAAM,GAAGA,CAAA,KAAMF,WAAW,CAACE,MAAM,CAAC,CAAC;;AAEhD;AACA,OAAO,MAAMC,OAAO,GAAIC,EAAU,IAAKJ,WAAW,CAACG,OAAO,CAACC,EAAE,CAAC","ignoreList":[]}
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":[]}
@@ -2,7 +2,7 @@
2
2
 
3
3
  import GameEngine from "./GameEngine.js";
4
4
  export * from "./GameMethods.js";
5
- export * from "./Shared.js";
5
+ export * from "./GameAssets.js";
6
6
  export * from "./types.js";
7
7
  export { GameEngine };
8
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["GameEngine"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,UAAU,MAAM,iBAAc;AAErC,cAAc,kBAAe;AAC7B,cAAc,aAAU;AACxB,cAAc,YAAS;AACvB,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;AAQvB,SAASA,UAAU","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ export declare const loadAssets: <T extends Record<string, unknown>>(assets: T) => Promise<{ [K in keyof T]: number; }>;
2
+ //# sourceMappingURL=GameAssets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GameAssets.d.ts","sourceRoot":"","sources":["../../../src/GameAssets.ts"],"names":[],"mappings":"AAmCA,eAAO,MAAM,UAAU,GAAU,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,QAAQ,CAAC,KACR,OAAO,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,GAAE,CASpC,CAAC"}
@@ -4,8 +4,8 @@ interface GameAssets extends HybridObject<{
4
4
  android: 'kotlin';
5
5
  }> {
6
6
  isAssetRegistered(id: number): boolean;
7
- registerSvg(id: number, uri: string): void;
8
- registerLottie(id: number, json: string): void;
7
+ registerSvg(id: number, uri: string): Promise<void>;
8
+ registerLottie(id: number, json: string): Promise<void>;
9
9
  }
10
10
  export declare const gameAssets: GameAssets;
11
11
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"GameAssets.nitro.d.ts","sourceRoot":"","sources":["../../../src/GameAssets.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG/D,UAAU,UAAW,SAAQ,YAAY,CAAC;IACxC,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;CACnB,CAAC;IACA,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAChD;AAED,eAAO,MAAM,UAAU,YACoC,CAAC"}
1
+ {"version":3,"file":"GameAssets.nitro.d.ts","sourceRoot":"","sources":["../../../src/GameAssets.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG/D,UAAU,UAAW,SAAQ,YAAY,CAAC;IACxC,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;CACnB,CAAC;IACA,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED,eAAO,MAAM,UAAU,YACoC,CAAC"}
@@ -1,7 +1,15 @@
1
+ import type { Entity, EntityUpdate } from './nativeTypes';
2
+ import type { Config } from './types';
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;
1
5
  /** Pauses the game loop. Systems will stop running. */
2
6
  export declare const pause: () => void;
3
7
  /** Resumes the game loop. */
4
8
  export declare const resume: () => void;
9
+ /** Spawns one or more entities into the world. Skips duplicates by id. */
10
+ export declare const spawn: (entities: Entity | Entity[]) => void;
5
11
  /** Removes an entity or all entities matching the given id prefix from the world. */
6
12
  export declare const despawn: (id: string) => void;
13
+ /** Updates one or more entities. Only the provided fields are changed. */
14
+ export declare const update: (updates: EntityUpdate | EntityUpdate[]) => void;
7
15
  //# sourceMappingURL=GameMethods.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GameMethods.d.ts","sourceRoot":"","sources":["../../../src/GameMethods.ts"],"names":[],"mappings":"AAEA,uDAAuD;AACvD,eAAO,MAAM,KAAK,YAA4B,CAAC;AAE/C,6BAA6B;AAC7B,eAAO,MAAM,MAAM,YAA6B,CAAC;AAEjD,qFAAqF;AACrF,eAAO,MAAM,OAAO,GAAI,IAAI,MAAM,SAA4B,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,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,6 +1,7 @@
1
1
  import GameEngine from './GameEngine';
2
2
  export * from './GameMethods';
3
- export * from './Shared';
3
+ export * from './GameAssets';
4
4
  export * from './types';
5
+ export type { Screen, Entity, CollisionPair, Collision, EntityUpdate, } from './nativeTypes';
5
6
  export { GameEngine };
6
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,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,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,MAAM,EACN,MAAM,EACN,aAAa,EACb,SAAS,EACT,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,UAAU,EAAE,CAAC"}