rngine 0.5.0 → 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.
- package/android/kls_database.db +0 -0
- package/android/src/main/cpp/GameLoopJNI.cpp +84 -27
- package/android/src/main/java/com/margelo/nitro/rngine/GameAssets.kt +11 -1
- package/android/src/main/java/com/margelo/nitro/rngine/GameView.kt +80 -48
- package/android/src/main/java/com/margelo/nitro/rngine/Rect.kt +2 -2
- package/android/src/main/java/com/margelo/nitro/rngine/Screen.kt +9 -0
- package/android/src/main/java/com/margelo/nitro/rngine/Snapshot.kt +3 -0
- package/android/src/main/java/com/margelo/nitro/rngine/SnapshotSerializer.kt +33 -0
- package/lib/typescript/src/nativeTypes.d.ts +25 -44
- package/lib/typescript/src/nativeTypes.d.ts.map +1 -1
- package/package.json +1 -1
- package/shared/GameLoop.cpp +11 -38
- package/shared/GameLoop.hpp +0 -2
- package/src/nativeTypes.ts +31 -46
- package/android/src/main/java/com/margelo/nitro/rngine/RectSerializer.kt +0 -25
- package/shared/Rect.hpp +0 -16
- /package/{shared → android/src/main/cpp}/ColorUtils.hpp +0 -0
package/android/kls_database.db
CHANGED
|
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
|
|
6
|
-
|
|
7
|
-
auto
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
uint8_t
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
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
|
|
@@ -6,6 +6,7 @@ import com.airbnb.lottie.LottieDrawable
|
|
|
6
6
|
import com.caverock.androidsvg.SVG
|
|
7
7
|
import com.margelo.nitro.core.Promise
|
|
8
8
|
import java.net.URL
|
|
9
|
+
import com.margelo.nitro.NitroModules
|
|
9
10
|
|
|
10
11
|
class GameAssets : HybridGameAssetsSpec() {
|
|
11
12
|
private external fun registerLottieDuration(id: Double, duration: Double)
|
|
@@ -22,7 +23,16 @@ class GameAssets : HybridGameAssetsSpec() {
|
|
|
22
23
|
override fun registerSvg(id: Double, uri: String): Promise<Unit> {
|
|
23
24
|
return Promise.async {
|
|
24
25
|
try {
|
|
25
|
-
val stream =
|
|
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
|
+
}
|
|
26
36
|
assetCache[id.toInt()] = Asset.Svg(SVG.getFromInputStream(stream).renderToPicture())
|
|
27
37
|
Log.d("GameAssets", "assetCache: $assetCache")
|
|
28
38
|
} catch (e: Exception) {
|
|
@@ -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
|
|
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
|
|
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
|
|
52
|
-
val
|
|
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 +
|
|
56
|
-
val top = rect.top * scale +
|
|
57
|
-
val right = rect.right * scale +
|
|
58
|
-
val bottom = rect.bottom * scale +
|
|
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(
|
|
61
|
-
val clampedTop = top.coerceAtLeast(
|
|
62
|
-
val clampedRight = right.coerceAtMost(
|
|
63
|
-
val clampedBottom = bottom.coerceAtMost(
|
|
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
|
-
|
|
66
|
-
|
|
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
|
}
|
|
@@ -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
|
+
}
|
|
@@ -1,79 +1,60 @@
|
|
|
1
|
-
|
|
2
|
-
/** Width of the screen in game units. */
|
|
3
|
-
width: number;
|
|
4
|
-
/** Height of the screen in game units. */
|
|
5
|
-
height: number;
|
|
6
|
-
/** Background color of the screen as a hex string e.g. `'#1a1a1a'`. */
|
|
7
|
-
color?: string;
|
|
8
|
-
/** Asset to render, use `require` with the file path to get the id. */
|
|
9
|
-
asset?: number;
|
|
10
|
-
/** Animation progress between 0 and 1, automatically advanced each tick for Lottie assets. */
|
|
11
|
-
progress?: number;
|
|
12
|
-
};
|
|
13
|
-
export type Entity = {
|
|
14
|
-
/** Unique identifier. Use `_` as a separator for group queries e.g. `'enemy_1'`. */
|
|
15
|
-
id: string;
|
|
1
|
+
interface Positioned {
|
|
16
2
|
/** X position in game units. */
|
|
17
3
|
px: number;
|
|
18
4
|
/** Y position in game units. */
|
|
19
5
|
py: number;
|
|
6
|
+
}
|
|
7
|
+
interface Shaped {
|
|
20
8
|
/** Width in game units. */
|
|
21
9
|
width: number;
|
|
22
10
|
/** Height in game units. */
|
|
23
11
|
height: number;
|
|
12
|
+
}
|
|
13
|
+
interface Renderable {
|
|
24
14
|
/** Fill color as a hex string e.g. `'#00ff00'`. */
|
|
25
15
|
color?: string;
|
|
26
16
|
/** Asset to render, use `require` with the file path to get the id. */
|
|
27
17
|
asset?: number;
|
|
28
18
|
/** Animation progress between 0 and 1, automatically advanced each tick for Lottie assets. */
|
|
29
19
|
progress?: number;
|
|
20
|
+
}
|
|
21
|
+
interface Kinematic {
|
|
30
22
|
/** Velocity on the X axis in game units per second. */
|
|
31
23
|
vx?: number;
|
|
32
24
|
/** Velocity on the Y axis in game units per second. */
|
|
33
25
|
vy?: number;
|
|
34
|
-
}
|
|
35
|
-
export
|
|
26
|
+
}
|
|
27
|
+
export interface Screen extends Shaped, Renderable {
|
|
28
|
+
}
|
|
29
|
+
export interface Entity extends Positioned, Shaped, Renderable, Kinematic {
|
|
30
|
+
/** Unique identifier. Use `_` as a separator for group queries e.g. `'enemy_1'`. */
|
|
31
|
+
id: string;
|
|
32
|
+
}
|
|
33
|
+
export interface EntityUpdate extends Partial<Positioned & Shaped & Renderable & Kinematic> {
|
|
34
|
+
/** Unique identifier or prefix of the entities to update. */
|
|
35
|
+
id: string;
|
|
36
|
+
}
|
|
37
|
+
export interface CollisionPair {
|
|
36
38
|
/** Entity id or prefix of the first entity to watch. */
|
|
37
39
|
a: string;
|
|
38
40
|
/** Entity id or prefix of the second entity to watch. */
|
|
39
41
|
b: string;
|
|
40
|
-
}
|
|
41
|
-
export
|
|
42
|
+
}
|
|
43
|
+
export interface Collision {
|
|
42
44
|
/** Id of the first entity involved in the collision. */
|
|
43
45
|
a: string;
|
|
44
46
|
/** Id of the second entity involved in the collision. */
|
|
45
47
|
b: string;
|
|
46
48
|
/** Penetration depth of the collision. */
|
|
47
49
|
depth: number;
|
|
48
|
-
}
|
|
49
|
-
export
|
|
50
|
+
}
|
|
51
|
+
export interface System {
|
|
50
52
|
/** Entity ids or prefixes this system subscribes to. */
|
|
51
53
|
entities?: string[];
|
|
52
54
|
/** Collision pairs to watch for every tick. */
|
|
53
55
|
collisions?: CollisionPair[];
|
|
54
56
|
/** Called every tick with the resolved entities and collisions. */
|
|
55
57
|
onTick: (entities: Entity[], collisions: Collision[]) => number;
|
|
56
|
-
}
|
|
57
|
-
export
|
|
58
|
-
/** Unique identifier or prefix of the entities to update. */
|
|
59
|
-
id: string;
|
|
60
|
-
/** X position in game units. */
|
|
61
|
-
px?: number;
|
|
62
|
-
/** Y position in game units. */
|
|
63
|
-
py?: number;
|
|
64
|
-
/** Width in game units. */
|
|
65
|
-
width?: number;
|
|
66
|
-
/** Height in game units. */
|
|
67
|
-
height?: number;
|
|
68
|
-
/** Fill color as a hex string e.g. `'#00ff00'`. */
|
|
69
|
-
color?: string;
|
|
70
|
-
/** Asset to render, use `require` with the file path to get the id. */
|
|
71
|
-
asset?: number;
|
|
72
|
-
/** Animation progress between 0 and 1, automatically advanced each tick for Lottie assets. */
|
|
73
|
-
progress?: number;
|
|
74
|
-
/** Velocity on the X axis in game units per second. */
|
|
75
|
-
vx?: number;
|
|
76
|
-
/** Velocity on the Y axis in game units per second. */
|
|
77
|
-
vy?: number;
|
|
78
|
-
};
|
|
58
|
+
}
|
|
59
|
+
export {};
|
|
79
60
|
//# sourceMappingURL=nativeTypes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nativeTypes.d.ts","sourceRoot":"","sources":["../../../src/nativeTypes.ts"],"names":[],"mappings":"AAAA,
|
|
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,MAAM;IACd,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;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,uDAAuD;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,MAAO,SAAQ,MAAM,EAAE,UAAU;CAAG;AAErD,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;CACf;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"}
|
package/package.json
CHANGED
package/shared/GameLoop.cpp
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#include "GameLoop.hpp"
|
|
2
2
|
#include "Collision.hpp"
|
|
3
|
-
#include "ColorUtils.hpp"
|
|
4
3
|
#include "Entity.hpp"
|
|
5
4
|
#include <android/log.h>
|
|
6
5
|
#include <chrono>
|
|
@@ -60,37 +59,6 @@ void GameLoop::registerLottieDuration(double id, double duration) {
|
|
|
60
59
|
id, duration);
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
std::vector<Rect> GameLoop::getRectsSnapshot() {
|
|
64
|
-
std::lock_guard<std::mutex> snapshotLock(_snapshotMutex);
|
|
65
|
-
std::vector<Rect> rects;
|
|
66
|
-
rects.reserve(_entitiesSnapshot.size() + 1);
|
|
67
|
-
|
|
68
|
-
rects.push_back({0, static_cast<float>(_screenSnapshot.width), 0,
|
|
69
|
-
static_cast<float>(_screenSnapshot.height),
|
|
70
|
-
static_cast<float>(_screenSnapshot.progress.value_or(0)),
|
|
71
|
-
parseHexColor(_screenSnapshot.color),
|
|
72
|
-
static_cast<int32_t>(_screenSnapshot.asset.value_or(0))});
|
|
73
|
-
|
|
74
|
-
for (const auto &[id, entitySnapshot] : _entitiesSnapshot) {
|
|
75
|
-
if (entitySnapshot.px + entitySnapshot.width < 0 ||
|
|
76
|
-
entitySnapshot.px > _screenSnapshot.width ||
|
|
77
|
-
entitySnapshot.py + entitySnapshot.height < 0 ||
|
|
78
|
-
entitySnapshot.py > _screenSnapshot.height) {
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
rects.push_back(
|
|
83
|
-
{static_cast<float>(entitySnapshot.px),
|
|
84
|
-
static_cast<float>(entitySnapshot.px + entitySnapshot.width),
|
|
85
|
-
static_cast<float>(entitySnapshot.py),
|
|
86
|
-
static_cast<float>(entitySnapshot.py + entitySnapshot.height),
|
|
87
|
-
static_cast<float>(entitySnapshot.progress.value_or(0)),
|
|
88
|
-
parseHexColor(entitySnapshot.color),
|
|
89
|
-
static_cast<int32_t>(entitySnapshot.asset.value_or(0))});
|
|
90
|
-
}
|
|
91
|
-
return rects;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
62
|
void GameLoop::runGameLoop() {
|
|
95
63
|
using namespace std::chrono;
|
|
96
64
|
|
|
@@ -157,13 +125,18 @@ void GameLoop::runSystems() {
|
|
|
157
125
|
|
|
158
126
|
uniqueEntityIdPairs.insert(uniqueEntityIdPairKey);
|
|
159
127
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
128
|
+
double aLeft = entityA->px - entityA->width / 2.0;
|
|
129
|
+
double aRight = entityA->px + entityA->width / 2.0;
|
|
130
|
+
double aTop = entityA->py - entityA->height / 2.0;
|
|
131
|
+
double aBottom = entityA->py + entityA->height / 2.0;
|
|
132
|
+
|
|
133
|
+
double bLeft = entityB->px - entityB->width / 2.0;
|
|
134
|
+
double bRight = entityB->px + entityB->width / 2.0;
|
|
135
|
+
double bTop = entityB->py - entityB->height / 2.0;
|
|
136
|
+
double bBottom = entityB->py + entityB->height / 2.0;
|
|
164
137
|
|
|
165
|
-
|
|
166
|
-
|
|
138
|
+
double overlapX = std::min(aRight, bRight) - std::max(aLeft, bLeft);
|
|
139
|
+
double overlapY = std::min(aBottom, bBottom) - std::max(aTop, bTop);
|
|
167
140
|
|
|
168
141
|
if (overlapX > 0 && overlapY > 0) {
|
|
169
142
|
collisions.push_back(Collision(entityA->id, entityB->id,
|
package/shared/GameLoop.hpp
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
#include "Entity.hpp"
|
|
4
4
|
#include "GameStats.hpp"
|
|
5
|
-
#include "Rect.hpp"
|
|
6
5
|
#include "Screen.hpp"
|
|
7
6
|
#include "System.hpp"
|
|
8
7
|
#include <atomic>
|
|
@@ -34,7 +33,6 @@ public:
|
|
|
34
33
|
|
|
35
34
|
std::vector<Entity *> resolveEntitiesInternal(const std::string &prefix);
|
|
36
35
|
void registerLottieDuration(double, double);
|
|
37
|
-
std::vector<Rect> getRectsSnapshot();
|
|
38
36
|
|
|
39
37
|
void setTickRate(double tickRate) { _tickRate.store(tickRate); };
|
|
40
38
|
|
package/src/nativeTypes.ts
CHANGED
|
@@ -1,83 +1,68 @@
|
|
|
1
|
-
|
|
2
|
-
/** Width of the screen in game units. */
|
|
3
|
-
width: number;
|
|
4
|
-
/** Height of the screen in game units. */
|
|
5
|
-
height: number;
|
|
6
|
-
/** Background color of the screen as a hex string e.g. `'#1a1a1a'`. */
|
|
7
|
-
color?: string;
|
|
8
|
-
/** Asset to render, use `require` with the file path to get the id. */
|
|
9
|
-
asset?: number;
|
|
10
|
-
/** Animation progress between 0 and 1, automatically advanced each tick for Lottie assets. */
|
|
11
|
-
progress?: number;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export type Entity = {
|
|
15
|
-
/** Unique identifier. Use `_` as a separator for group queries e.g. `'enemy_1'`. */
|
|
16
|
-
id: string;
|
|
1
|
+
interface Positioned {
|
|
17
2
|
/** X position in game units. */
|
|
18
3
|
px: number;
|
|
19
4
|
/** Y position in game units. */
|
|
20
5
|
py: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface Shaped {
|
|
21
9
|
/** Width in game units. */
|
|
22
10
|
width: number;
|
|
23
11
|
/** Height in game units. */
|
|
24
12
|
height: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface Renderable {
|
|
25
16
|
/** Fill color as a hex string e.g. `'#00ff00'`. */
|
|
26
17
|
color?: string;
|
|
27
18
|
/** Asset to render, use `require` with the file path to get the id. */
|
|
28
19
|
asset?: number;
|
|
29
20
|
/** Animation progress between 0 and 1, automatically advanced each tick for Lottie assets. */
|
|
30
21
|
progress?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface Kinematic {
|
|
31
25
|
/** Velocity on the X axis in game units per second. */
|
|
32
26
|
vx?: number;
|
|
33
27
|
/** Velocity on the Y axis in game units per second. */
|
|
34
28
|
vy?: number;
|
|
35
|
-
}
|
|
29
|
+
}
|
|
36
30
|
|
|
37
|
-
export
|
|
31
|
+
export interface Screen extends Shaped, Renderable {}
|
|
32
|
+
|
|
33
|
+
export interface Entity extends Positioned, Shaped, Renderable, Kinematic {
|
|
34
|
+
/** Unique identifier. Use `_` as a separator for group queries e.g. `'enemy_1'`. */
|
|
35
|
+
id: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface EntityUpdate extends Partial<
|
|
39
|
+
Positioned & Shaped & Renderable & Kinematic
|
|
40
|
+
> {
|
|
41
|
+
/** Unique identifier or prefix of the entities to update. */
|
|
42
|
+
id: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface CollisionPair {
|
|
38
46
|
/** Entity id or prefix of the first entity to watch. */
|
|
39
47
|
a: string;
|
|
40
48
|
/** Entity id or prefix of the second entity to watch. */
|
|
41
49
|
b: string;
|
|
42
|
-
}
|
|
50
|
+
}
|
|
43
51
|
|
|
44
|
-
export
|
|
52
|
+
export interface Collision {
|
|
45
53
|
/** Id of the first entity involved in the collision. */
|
|
46
54
|
a: string;
|
|
47
55
|
/** Id of the second entity involved in the collision. */
|
|
48
56
|
b: string;
|
|
49
57
|
/** Penetration depth of the collision. */
|
|
50
58
|
depth: number;
|
|
51
|
-
}
|
|
59
|
+
}
|
|
52
60
|
|
|
53
|
-
export
|
|
61
|
+
export interface System {
|
|
54
62
|
/** Entity ids or prefixes this system subscribes to. */
|
|
55
63
|
entities?: string[];
|
|
56
64
|
/** Collision pairs to watch for every tick. */
|
|
57
65
|
collisions?: CollisionPair[];
|
|
58
66
|
/** Called every tick with the resolved entities and collisions. */
|
|
59
67
|
onTick: (entities: Entity[], collisions: Collision[]) => number;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export type EntityUpdate = {
|
|
63
|
-
/** Unique identifier or prefix of the entities to update. */
|
|
64
|
-
id: string;
|
|
65
|
-
/** X position in game units. */
|
|
66
|
-
px?: number;
|
|
67
|
-
/** Y position in game units. */
|
|
68
|
-
py?: number;
|
|
69
|
-
/** Width in game units. */
|
|
70
|
-
width?: number;
|
|
71
|
-
/** Height in game units. */
|
|
72
|
-
height?: number;
|
|
73
|
-
/** Fill color as a hex string e.g. `'#00ff00'`. */
|
|
74
|
-
color?: string;
|
|
75
|
-
/** Asset to render, use `require` with the file path to get the id. */
|
|
76
|
-
asset?: number;
|
|
77
|
-
/** Animation progress between 0 and 1, automatically advanced each tick for Lottie assets. */
|
|
78
|
-
progress?: number;
|
|
79
|
-
/** Velocity on the X axis in game units per second. */
|
|
80
|
-
vx?: number;
|
|
81
|
-
/** Velocity on the Y axis in game units per second. */
|
|
82
|
-
vy?: number;
|
|
83
|
-
};
|
|
68
|
+
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
package com.margelo.nitro.rngine
|
|
2
|
-
|
|
3
|
-
import java.nio.ByteBuffer
|
|
4
|
-
import java.nio.ByteOrder
|
|
5
|
-
|
|
6
|
-
object RectSerializer {
|
|
7
|
-
private const val RECT_SIZE = 4 * 5 + 4 * 2
|
|
8
|
-
fun decode(buffer: ByteBuffer): ArrayList<Rect> {
|
|
9
|
-
buffer.order(ByteOrder.nativeOrder())
|
|
10
|
-
val rects = ArrayList<Rect>()
|
|
11
|
-
|
|
12
|
-
while (buffer.remaining() >= RECT_SIZE) {
|
|
13
|
-
val left = buffer.float
|
|
14
|
-
val right = buffer.float
|
|
15
|
-
val top = buffer.float
|
|
16
|
-
val bottom = buffer.float
|
|
17
|
-
val progress = buffer.float
|
|
18
|
-
val color = buffer.int
|
|
19
|
-
val asset = buffer.int
|
|
20
|
-
|
|
21
|
-
rects.add(Rect(left, right, top, bottom, progress, color, asset))
|
|
22
|
-
}
|
|
23
|
-
return rects
|
|
24
|
-
}
|
|
25
|
-
}
|
package/shared/Rect.hpp
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
namespace margelo::nitro::rngine {
|
|
4
|
-
static constexpr int RECT_SIZE =
|
|
5
|
-
sizeof(float) * 5 + sizeof(uint32_t) + sizeof(int32_t);
|
|
6
|
-
|
|
7
|
-
struct Rect {
|
|
8
|
-
float left;
|
|
9
|
-
float right;
|
|
10
|
-
float top;
|
|
11
|
-
float bottom;
|
|
12
|
-
float progress;
|
|
13
|
-
uint32_t color;
|
|
14
|
-
int32_t asset;
|
|
15
|
-
};
|
|
16
|
-
} // namespace margelo::nitro::rngine
|
|
File without changes
|