rngine 0.6.0 → 0.7.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 +25 -17
- package/android/CMakeLists.txt +1 -0
- package/android/src/main/cpp/GameLoopJNI.cpp +45 -12
- package/android/src/main/java/com/margelo/nitro/rngine/GameView.kt +110 -56
- package/android/src/main/java/com/margelo/nitro/rngine/Shape.kt +26 -0
- package/android/src/main/java/com/margelo/nitro/rngine/Snapshot.kt +1 -1
- package/android/src/main/java/com/margelo/nitro/rngine/SnapshotSerializer.kt +33 -13
- package/lib/typescript/src/nativeTypes.d.ts +10 -2
- package/lib/typescript/src/nativeTypes.d.ts.map +1 -1
- package/nitrogen/generated/shared/c++/Circle.hpp +83 -0
- package/nitrogen/generated/shared/c++/Entity.hpp +12 -10
- package/nitrogen/generated/shared/c++/EntityUpdate.hpp +12 -10
- package/nitrogen/generated/shared/c++/Rect.hpp +87 -0
- package/package.json +1 -1
- package/shared/CollisionUtils.cpp +67 -0
- package/shared/CollisionUtils.hpp +19 -0
- package/shared/GameLoop.cpp +6 -18
- package/shared/GameMethods.cpp +2 -5
- package/src/nativeTypes.ts +12 -2
- package/android/src/main/java/com/margelo/nitro/rngine/Rect.kt +0 -11
package/README.md
CHANGED
|
@@ -21,28 +21,33 @@ configure({
|
|
|
21
21
|
entities: [
|
|
22
22
|
{
|
|
23
23
|
id: 'player',
|
|
24
|
-
px:
|
|
25
|
-
py:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
px: 420,
|
|
25
|
+
py: 420,
|
|
26
|
+
color: '#0f0',
|
|
27
|
+
shape: {
|
|
28
|
+
radius: 20,
|
|
29
|
+
},
|
|
29
30
|
},
|
|
30
31
|
{
|
|
31
32
|
id: 'enemy_1',
|
|
32
|
-
px:
|
|
33
|
-
py:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
px: 120,
|
|
34
|
+
py: 120,
|
|
35
|
+
color: '#f00',
|
|
36
|
+
shape: {
|
|
37
|
+
width: 40,
|
|
38
|
+
height: 40,
|
|
39
|
+
},
|
|
37
40
|
vx: 1000,
|
|
38
41
|
},
|
|
39
42
|
{
|
|
40
43
|
id: 'enemy_2',
|
|
41
|
-
px:
|
|
42
|
-
py:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
px: 220,
|
|
45
|
+
py: 220,
|
|
46
|
+
color: '#f00',
|
|
47
|
+
shape: {
|
|
48
|
+
width: 40,
|
|
49
|
+
height: 40,
|
|
50
|
+
},
|
|
46
51
|
vx: -1000,
|
|
47
52
|
},
|
|
48
53
|
],
|
|
@@ -53,7 +58,10 @@ configure({
|
|
|
53
58
|
onTick: (enemies) => {
|
|
54
59
|
enemies.forEach((enemy) => {
|
|
55
60
|
// reverse direction when reaching screen edges
|
|
56
|
-
if (
|
|
61
|
+
if (
|
|
62
|
+
enemy.px - enemy.width / 2 <= 0 ||
|
|
63
|
+
enemy.px + enemy.width / 2 >= 800
|
|
64
|
+
) {
|
|
57
65
|
update({ id: enemy.id, vx: -enemy.vx });
|
|
58
66
|
}
|
|
59
67
|
});
|
|
@@ -70,7 +78,7 @@ export default function App() {
|
|
|
70
78
|
|
|
71
79
|
## Concepts
|
|
72
80
|
|
|
73
|
-
**Entities** are the objects in your game world. Each entity has a position,
|
|
81
|
+
**Entities** are the objects in your game world. Each entity has a position, shape, color, and velocity. See [`Entity`](./src/nativeTypes.ts).
|
|
74
82
|
|
|
75
83
|
**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
84
|
|
package/android/CMakeLists.txt
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#include <cstdint>
|
|
4
4
|
#include <jni.h>
|
|
5
5
|
#include <mutex>
|
|
6
|
+
#include <variant>
|
|
6
7
|
|
|
7
8
|
extern "C" {
|
|
8
9
|
JNIEXPORT jbyteArray JNICALL
|
|
@@ -46,14 +47,37 @@ Java_com_margelo_nitro_rngine_GameView_getSnapshot(JNIEnv *env, jobject) {
|
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
for (const auto &[_, entitySnapshot] : entitiesSnapshot) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
uint8_t shapeType{0};
|
|
51
|
+
float entitySnapshotLeft{0}, entitySnapshotRight{0}, entitySnapshotTop{0},
|
|
52
|
+
entitySnapshotBottom{0}, circleRadius{0};
|
|
53
|
+
|
|
54
|
+
std::visit(
|
|
55
|
+
[&](const auto &shape) {
|
|
56
|
+
using T = std::decay_t<decltype(shape)>;
|
|
57
|
+
if constexpr (std::is_same_v<T, margelo::nitro::rngine::Rect>) {
|
|
58
|
+
shapeType = 0;
|
|
59
|
+
entitySnapshotLeft =
|
|
60
|
+
static_cast<float>(entitySnapshot.px - shape.width / 2.0);
|
|
61
|
+
entitySnapshotRight =
|
|
62
|
+
static_cast<float>(entitySnapshot.px + shape.width / 2.0);
|
|
63
|
+
entitySnapshotTop =
|
|
64
|
+
static_cast<float>(entitySnapshot.py - shape.height / 2.0);
|
|
65
|
+
entitySnapshotBottom =
|
|
66
|
+
static_cast<float>(entitySnapshot.py + shape.height / 2.0);
|
|
67
|
+
} else {
|
|
68
|
+
shapeType = 1;
|
|
69
|
+
circleRadius = static_cast<float>(shape.radius);
|
|
70
|
+
entitySnapshotLeft =
|
|
71
|
+
static_cast<float>(entitySnapshot.px - shape.radius);
|
|
72
|
+
entitySnapshotRight =
|
|
73
|
+
static_cast<float>(entitySnapshot.px + shape.radius);
|
|
74
|
+
entitySnapshotTop =
|
|
75
|
+
static_cast<float>(entitySnapshot.py - shape.radius);
|
|
76
|
+
entitySnapshotBottom =
|
|
77
|
+
static_cast<float>(entitySnapshot.py + shape.radius);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
entitySnapshot.shape);
|
|
57
81
|
|
|
58
82
|
if (entitySnapshotRight < 0 || entitySnapshotLeft > screenSnapshot.width ||
|
|
59
83
|
entitySnapshotBottom < 0 || entitySnapshotTop > screenSnapshot.height) {
|
|
@@ -65,10 +89,19 @@ Java_com_margelo_nitro_rngine_GameView_getSnapshot(JNIEnv *env, jobject) {
|
|
|
65
89
|
const auto entitySnapshotAsset =
|
|
66
90
|
static_cast<int32_t>(entitySnapshot.asset.value_or(0));
|
|
67
91
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
92
|
+
buffer.push_back(shapeType);
|
|
93
|
+
|
|
94
|
+
if (shapeType == 0) {
|
|
95
|
+
writeFloat(entitySnapshotLeft);
|
|
96
|
+
writeFloat(entitySnapshotRight);
|
|
97
|
+
writeFloat(entitySnapshotTop);
|
|
98
|
+
writeFloat(entitySnapshotBottom);
|
|
99
|
+
} else {
|
|
100
|
+
writeFloat(static_cast<float>(entitySnapshot.px));
|
|
101
|
+
writeFloat(static_cast<float>(entitySnapshot.py));
|
|
102
|
+
writeFloat(circleRadius);
|
|
103
|
+
}
|
|
104
|
+
|
|
72
105
|
writeU32(entitySnapshotColor);
|
|
73
106
|
writeI32(entitySnapshotAsset);
|
|
74
107
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
package com.margelo.nitro.rngine
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
-
import android.graphics.
|
|
4
|
+
import android.graphics.Canvas
|
|
5
5
|
import android.graphics.Paint
|
|
6
6
|
import android.util.AttributeSet
|
|
7
7
|
import android.view.SurfaceView
|
|
@@ -23,52 +23,93 @@ class GameView(
|
|
|
23
23
|
var onDetached: () -> Unit = {}
|
|
24
24
|
|
|
25
25
|
private val paint = Paint().apply {
|
|
26
|
-
color = Color.TRANSPARENT
|
|
27
26
|
style = Paint.Style.FILL
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
private fun
|
|
31
|
-
canvas:
|
|
29
|
+
private fun drawAsset(
|
|
30
|
+
canvas: Canvas,
|
|
32
31
|
left: Float,
|
|
33
32
|
top: Float,
|
|
34
33
|
right: Float,
|
|
35
34
|
bottom: Float,
|
|
36
|
-
color: Int,
|
|
37
35
|
asset: Int,
|
|
38
36
|
progress: Float?,
|
|
39
|
-
clampedLeft: Float = left,
|
|
40
|
-
clampedTop: Float = top,
|
|
41
|
-
clampedRight: Float = right,
|
|
42
|
-
clampedBottom: Float = bottom,
|
|
43
37
|
) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
(bottom - top) / resolvedAsset.picture.height
|
|
54
|
-
)
|
|
55
|
-
drawPicture(resolvedAsset.picture)
|
|
56
|
-
}
|
|
38
|
+
canvas.withTranslation(left, top) {
|
|
39
|
+
when (val resolvedAsset = GameAssets.getAsset(asset)) {
|
|
40
|
+
is Asset.Svg -> {
|
|
41
|
+
scale(
|
|
42
|
+
(right - left) / resolvedAsset.picture.width,
|
|
43
|
+
(bottom - top) / resolvedAsset.picture.height
|
|
44
|
+
)
|
|
45
|
+
drawPicture(resolvedAsset.picture)
|
|
46
|
+
}
|
|
57
47
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
resolvedAsset.drawable.setBounds(0, 0, (right - left).toInt(), (bottom - top).toInt())
|
|
63
|
-
resolvedAsset.drawable.draw(canvas)
|
|
48
|
+
is Asset.Lottie -> {
|
|
49
|
+
progress?.let {
|
|
50
|
+
resolvedAsset.drawable.progress = it
|
|
64
51
|
}
|
|
65
|
-
|
|
66
|
-
|
|
52
|
+
resolvedAsset.drawable.setBounds(0, 0, (right - left).toInt(), (bottom - top).toInt())
|
|
53
|
+
resolvedAsset.drawable.draw(canvas)
|
|
67
54
|
}
|
|
55
|
+
|
|
56
|
+
null -> {}
|
|
68
57
|
}
|
|
69
58
|
}
|
|
70
59
|
}
|
|
71
60
|
|
|
61
|
+
private fun drawRect(
|
|
62
|
+
canvas: Canvas,
|
|
63
|
+
left: Float,
|
|
64
|
+
top: Float,
|
|
65
|
+
right: Float,
|
|
66
|
+
bottom: Float,
|
|
67
|
+
color: Int,
|
|
68
|
+
asset: Int,
|
|
69
|
+
progress: Float?,
|
|
70
|
+
) {
|
|
71
|
+
paint.color = color
|
|
72
|
+
canvas.drawRect(left, top, right, bottom, paint)
|
|
73
|
+
|
|
74
|
+
drawAsset(
|
|
75
|
+
canvas,
|
|
76
|
+
left,
|
|
77
|
+
top,
|
|
78
|
+
right,
|
|
79
|
+
bottom,
|
|
80
|
+
asset,
|
|
81
|
+
progress
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private fun drawCircle(
|
|
86
|
+
canvas: Canvas,
|
|
87
|
+
cx: Float,
|
|
88
|
+
cy: Float,
|
|
89
|
+
radius: Float,
|
|
90
|
+
color: Int,
|
|
91
|
+
asset: Int,
|
|
92
|
+
progress: Float?,
|
|
93
|
+
) {
|
|
94
|
+
val left = cx - radius
|
|
95
|
+
val top = cy - radius
|
|
96
|
+
val right = cx + radius
|
|
97
|
+
val bottom = cy + radius
|
|
98
|
+
|
|
99
|
+
paint.color = color
|
|
100
|
+
canvas.drawCircle(cx, cy, radius, paint)
|
|
101
|
+
|
|
102
|
+
drawAsset(
|
|
103
|
+
canvas,
|
|
104
|
+
left,
|
|
105
|
+
top,
|
|
106
|
+
right,
|
|
107
|
+
bottom,
|
|
108
|
+
asset,
|
|
109
|
+
progress,
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
72
113
|
init {
|
|
73
114
|
addOnAttachStateChangeListener(
|
|
74
115
|
object : OnAttachStateChangeListener {
|
|
@@ -91,7 +132,7 @@ class GameView(
|
|
|
91
132
|
val screenRight = screenLeft + snapshot.screen.width * scale
|
|
92
133
|
val screenBottom = screenTop + snapshot.screen.height * scale
|
|
93
134
|
|
|
94
|
-
|
|
135
|
+
drawRect(
|
|
95
136
|
canvas,
|
|
96
137
|
screenLeft,
|
|
97
138
|
screenTop,
|
|
@@ -102,31 +143,44 @@ class GameView(
|
|
|
102
143
|
snapshot.screen.progress,
|
|
103
144
|
)
|
|
104
145
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
146
|
+
canvas.withClip(screenLeft, screenTop, screenRight, screenBottom) {
|
|
147
|
+
snapshot.shapes.forEach { shape ->
|
|
148
|
+
when (shape) {
|
|
149
|
+
is Shape.Rect -> {
|
|
150
|
+
val left = shape.left * scale + screenLeft
|
|
151
|
+
val top = shape.top * scale + screenTop
|
|
152
|
+
val right = shape.right * scale + screenLeft
|
|
153
|
+
val bottom = shape.bottom * scale + screenTop
|
|
154
|
+
|
|
155
|
+
drawRect(
|
|
156
|
+
canvas,
|
|
157
|
+
left,
|
|
158
|
+
top,
|
|
159
|
+
right,
|
|
160
|
+
bottom,
|
|
161
|
+
shape.color,
|
|
162
|
+
shape.asset,
|
|
163
|
+
shape.progress,
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
is Shape.Circle -> {
|
|
168
|
+
val cx = shape.px * scale + screenLeft
|
|
169
|
+
val cy = shape.py * scale + screenTop
|
|
170
|
+
val radius = shape.radius * scale
|
|
171
|
+
|
|
172
|
+
drawCircle(
|
|
173
|
+
canvas,
|
|
174
|
+
cx,
|
|
175
|
+
cy,
|
|
176
|
+
radius,
|
|
177
|
+
shape.color,
|
|
178
|
+
shape.asset,
|
|
179
|
+
shape.progress,
|
|
180
|
+
)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
130
184
|
}
|
|
131
185
|
holder.unlockCanvasAndPost(canvas)
|
|
132
186
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package com.margelo.nitro.rngine
|
|
2
|
+
|
|
3
|
+
sealed class Shape(
|
|
4
|
+
val color: Int,
|
|
5
|
+
val asset: Int,
|
|
6
|
+
val progress: Float?,
|
|
7
|
+
) {
|
|
8
|
+
class Rect(
|
|
9
|
+
val left: Float,
|
|
10
|
+
val right: Float,
|
|
11
|
+
val top: Float,
|
|
12
|
+
val bottom: Float,
|
|
13
|
+
color: Int,
|
|
14
|
+
asset: Int,
|
|
15
|
+
progress: Float?,
|
|
16
|
+
) : Shape(color, asset, progress)
|
|
17
|
+
|
|
18
|
+
class Circle(
|
|
19
|
+
val px: Float,
|
|
20
|
+
val py: Float,
|
|
21
|
+
val radius: Float,
|
|
22
|
+
color: Int,
|
|
23
|
+
asset: Int,
|
|
24
|
+
progress: Float?,
|
|
25
|
+
) : Shape(color, asset, progress)
|
|
26
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.margelo.nitro.rngine
|
|
2
2
|
|
|
3
|
+
import android.util.Log
|
|
3
4
|
import java.nio.ByteBuffer
|
|
4
5
|
import java.nio.ByteOrder
|
|
5
6
|
|
|
@@ -14,20 +15,39 @@ object SnapshotSerializer {
|
|
|
14
15
|
val progress = if (asset < 0) buffer.float else null
|
|
15
16
|
|
|
16
17
|
val screen = Screen(width, height, color, asset, progress)
|
|
17
|
-
val
|
|
18
|
-
|
|
19
|
-
while (buffer.
|
|
20
|
-
val
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
val shapes = ArrayList<Shape>()
|
|
19
|
+
|
|
20
|
+
while (buffer.hasRemaining()) {
|
|
21
|
+
when (val shapeType = buffer.get().toInt()) {
|
|
22
|
+
0 -> {
|
|
23
|
+
val left = buffer.float
|
|
24
|
+
val right = buffer.float
|
|
25
|
+
val top = buffer.float
|
|
26
|
+
val bottom = buffer.float
|
|
27
|
+
|
|
28
|
+
val color = buffer.int
|
|
29
|
+
val asset = buffer.int
|
|
30
|
+
val progress = if (asset < 0) buffer.float else null
|
|
31
|
+
|
|
32
|
+
shapes.add(Shape.Rect(left, right, top, bottom, color, asset, progress))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
1 -> {
|
|
36
|
+
val px = buffer.float
|
|
37
|
+
val py = buffer.float
|
|
38
|
+
val radius = buffer.float
|
|
39
|
+
|
|
40
|
+
val color = buffer.int
|
|
41
|
+
val asset = buffer.int
|
|
42
|
+
val progress = if (asset < 0) buffer.float else null
|
|
43
|
+
|
|
44
|
+
shapes.add(Shape.Circle(px, py, radius, color, asset, progress))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
else -> Log.e("SnapshotSerializer", "Unknown shapeType: $shapeType")
|
|
48
|
+
}
|
|
29
49
|
}
|
|
30
50
|
|
|
31
|
-
return Snapshot(screen,
|
|
51
|
+
return Snapshot(screen, shapes)
|
|
32
52
|
}
|
|
33
53
|
}
|
|
@@ -4,12 +4,20 @@ interface Positioned {
|
|
|
4
4
|
/** Y position in game units. */
|
|
5
5
|
py: number;
|
|
6
6
|
}
|
|
7
|
-
interface
|
|
7
|
+
interface Rect {
|
|
8
8
|
/** Width in game units. */
|
|
9
9
|
width: number;
|
|
10
10
|
/** Height in game units. */
|
|
11
11
|
height: number;
|
|
12
12
|
}
|
|
13
|
+
interface Circle {
|
|
14
|
+
/** Radius in game units. */
|
|
15
|
+
radius: number;
|
|
16
|
+
}
|
|
17
|
+
interface Shaped {
|
|
18
|
+
/** Shape of the entity. */
|
|
19
|
+
shape: Rect | Circle;
|
|
20
|
+
}
|
|
13
21
|
interface Renderable {
|
|
14
22
|
/** Fill color as a hex string e.g. `'#00ff00'`. */
|
|
15
23
|
color?: string;
|
|
@@ -24,7 +32,7 @@ interface Kinematic {
|
|
|
24
32
|
/** Velocity on the Y axis in game units per second. */
|
|
25
33
|
vy?: number;
|
|
26
34
|
}
|
|
27
|
-
export interface Screen extends
|
|
35
|
+
export interface Screen extends Rect, Renderable {
|
|
28
36
|
}
|
|
29
37
|
export interface Entity extends Positioned, Shaped, Renderable, Kinematic {
|
|
30
38
|
/** Unique identifier. Use `_` as a separator for group queries e.g. `'enemy_1'`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nativeTypes.d.ts","sourceRoot":"","sources":["../../../src/nativeTypes.ts"],"names":[],"mappings":"AAAA,UAAU,UAAU;IAClB,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,UAAU,
|
|
1
|
+
{"version":3,"file":"nativeTypes.d.ts","sourceRoot":"","sources":["../../../src/nativeTypes.ts"],"names":[],"mappings":"AAAA,UAAU,UAAU;IAClB,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,UAAU,IAAI;IACZ,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,MAAM;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,MAAM;IACd,2BAA2B;IAC3B,KAAK,EAAE,IAAI,GAAG,MAAM,CAAC;CACtB;AAED,UAAU,UAAU;IAClB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,SAAS;IACjB,uDAAuD;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,MAAO,SAAQ,IAAI,EAAE,UAAU;CAAG;AAEnD,MAAM,WAAW,MAAO,SAAQ,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS;IACvE,oFAAoF;IACpF,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAa,SAAQ,OAAO,CAC3C,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAC7C;IACC,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,CAAC,EAAE,MAAM,CAAC;IACV,yDAAyD;IACzD,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,CAAC,EAAE,MAAM,CAAC;IACV,yDAAyD;IACzD,CAAC,EAAE,MAAM,CAAC;IACV,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
///
|
|
2
|
+
/// Circle.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
|
+
|
|
34
|
+
|
|
35
|
+
namespace margelo::nitro::rngine {
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A struct which can be represented as a JavaScript object (Circle).
|
|
39
|
+
*/
|
|
40
|
+
struct Circle final {
|
|
41
|
+
public:
|
|
42
|
+
double radius SWIFT_PRIVATE;
|
|
43
|
+
|
|
44
|
+
public:
|
|
45
|
+
Circle() = default;
|
|
46
|
+
explicit Circle(double radius): radius(radius) {}
|
|
47
|
+
|
|
48
|
+
public:
|
|
49
|
+
friend bool operator==(const Circle& lhs, const Circle& rhs) = default;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
} // namespace margelo::nitro::rngine
|
|
53
|
+
|
|
54
|
+
namespace margelo::nitro {
|
|
55
|
+
|
|
56
|
+
// C++ Circle <> JS Circle (object)
|
|
57
|
+
template <>
|
|
58
|
+
struct JSIConverter<margelo::nitro::rngine::Circle> final {
|
|
59
|
+
static inline margelo::nitro::rngine::Circle fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
|
|
60
|
+
jsi::Object obj = arg.asObject(runtime);
|
|
61
|
+
return margelo::nitro::rngine::Circle(
|
|
62
|
+
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "radius")))
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::Circle& arg) {
|
|
66
|
+
jsi::Object obj(runtime);
|
|
67
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "radius"), JSIConverter<double>::toJSI(runtime, arg.radius));
|
|
68
|
+
return obj;
|
|
69
|
+
}
|
|
70
|
+
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
71
|
+
if (!value.isObject()) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
jsi::Object obj = value.getObject(runtime);
|
|
75
|
+
if (!nitro::isPlainObject(runtime, obj)) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "radius")))) return false;
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
} // namespace margelo::nitro
|
|
@@ -28,9 +28,15 @@
|
|
|
28
28
|
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
29
29
|
#endif
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
// Forward declaration of `Rect` to properly resolve imports.
|
|
32
|
+
namespace margelo::nitro::rngine { struct Rect; }
|
|
33
|
+
// Forward declaration of `Circle` to properly resolve imports.
|
|
34
|
+
namespace margelo::nitro::rngine { struct Circle; }
|
|
32
35
|
|
|
33
36
|
#include <string>
|
|
37
|
+
#include "Rect.hpp"
|
|
38
|
+
#include "Circle.hpp"
|
|
39
|
+
#include <variant>
|
|
34
40
|
#include <optional>
|
|
35
41
|
|
|
36
42
|
namespace margelo::nitro::rngine {
|
|
@@ -43,8 +49,7 @@ namespace margelo::nitro::rngine {
|
|
|
43
49
|
std::string id SWIFT_PRIVATE;
|
|
44
50
|
double px SWIFT_PRIVATE;
|
|
45
51
|
double py SWIFT_PRIVATE;
|
|
46
|
-
|
|
47
|
-
double height SWIFT_PRIVATE;
|
|
52
|
+
std::variant<Rect, Circle> shape SWIFT_PRIVATE;
|
|
48
53
|
std::optional<std::string> color SWIFT_PRIVATE;
|
|
49
54
|
std::optional<double> asset SWIFT_PRIVATE;
|
|
50
55
|
std::optional<double> progress SWIFT_PRIVATE;
|
|
@@ -53,7 +58,7 @@ namespace margelo::nitro::rngine {
|
|
|
53
58
|
|
|
54
59
|
public:
|
|
55
60
|
Entity() = default;
|
|
56
|
-
explicit Entity(std::string id, double px, double py,
|
|
61
|
+
explicit Entity(std::string id, double px, double py, std::variant<Rect, Circle> shape, std::optional<std::string> color, std::optional<double> asset, std::optional<double> progress, std::optional<double> vx, std::optional<double> vy): id(id), px(px), py(py), shape(shape), color(color), asset(asset), progress(progress), vx(vx), vy(vy) {}
|
|
57
62
|
|
|
58
63
|
public:
|
|
59
64
|
friend bool operator==(const Entity& lhs, const Entity& rhs) = default;
|
|
@@ -72,8 +77,7 @@ namespace margelo::nitro {
|
|
|
72
77
|
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "id"))),
|
|
73
78
|
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px"))),
|
|
74
79
|
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "py"))),
|
|
75
|
-
JSIConverter<
|
|
76
|
-
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height"))),
|
|
80
|
+
JSIConverter<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "shape"))),
|
|
77
81
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color"))),
|
|
78
82
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset"))),
|
|
79
83
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress"))),
|
|
@@ -86,8 +90,7 @@ namespace margelo::nitro {
|
|
|
86
90
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "id"), JSIConverter<std::string>::toJSI(runtime, arg.id));
|
|
87
91
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "px"), JSIConverter<double>::toJSI(runtime, arg.px));
|
|
88
92
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "py"), JSIConverter<double>::toJSI(runtime, arg.py));
|
|
89
|
-
obj.setProperty(runtime, PropNameIDCache::get(runtime, "
|
|
90
|
-
obj.setProperty(runtime, PropNameIDCache::get(runtime, "height"), JSIConverter<double>::toJSI(runtime, arg.height));
|
|
93
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "shape"), JSIConverter<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>::toJSI(runtime, arg.shape));
|
|
91
94
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "color"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.color));
|
|
92
95
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "asset"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.asset));
|
|
93
96
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "progress"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.progress));
|
|
@@ -106,8 +109,7 @@ namespace margelo::nitro {
|
|
|
106
109
|
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "id")))) return false;
|
|
107
110
|
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px")))) return false;
|
|
108
111
|
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "py")))) return false;
|
|
109
|
-
if (!JSIConverter<
|
|
110
|
-
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height")))) return false;
|
|
112
|
+
if (!JSIConverter<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "shape")))) return false;
|
|
111
113
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color")))) return false;
|
|
112
114
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset")))) return false;
|
|
113
115
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress")))) return false;
|
|
@@ -28,10 +28,16 @@
|
|
|
28
28
|
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
29
29
|
#endif
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
// Forward declaration of `Rect` to properly resolve imports.
|
|
32
|
+
namespace margelo::nitro::rngine { struct Rect; }
|
|
33
|
+
// Forward declaration of `Circle` to properly resolve imports.
|
|
34
|
+
namespace margelo::nitro::rngine { struct Circle; }
|
|
32
35
|
|
|
33
36
|
#include <string>
|
|
34
37
|
#include <optional>
|
|
38
|
+
#include "Rect.hpp"
|
|
39
|
+
#include "Circle.hpp"
|
|
40
|
+
#include <variant>
|
|
35
41
|
|
|
36
42
|
namespace margelo::nitro::rngine {
|
|
37
43
|
|
|
@@ -43,8 +49,7 @@ namespace margelo::nitro::rngine {
|
|
|
43
49
|
std::string id SWIFT_PRIVATE;
|
|
44
50
|
std::optional<double> px SWIFT_PRIVATE;
|
|
45
51
|
std::optional<double> py SWIFT_PRIVATE;
|
|
46
|
-
std::optional<
|
|
47
|
-
std::optional<double> height SWIFT_PRIVATE;
|
|
52
|
+
std::optional<std::variant<Rect, Circle>> shape SWIFT_PRIVATE;
|
|
48
53
|
std::optional<std::string> color SWIFT_PRIVATE;
|
|
49
54
|
std::optional<double> asset SWIFT_PRIVATE;
|
|
50
55
|
std::optional<double> progress SWIFT_PRIVATE;
|
|
@@ -53,7 +58,7 @@ namespace margelo::nitro::rngine {
|
|
|
53
58
|
|
|
54
59
|
public:
|
|
55
60
|
EntityUpdate() = default;
|
|
56
|
-
explicit EntityUpdate(std::string id, std::optional<double> px, std::optional<double> py, std::optional<
|
|
61
|
+
explicit EntityUpdate(std::string id, std::optional<double> px, std::optional<double> py, std::optional<std::variant<Rect, Circle>> shape, std::optional<std::string> color, std::optional<double> asset, std::optional<double> progress, std::optional<double> vx, std::optional<double> vy): id(id), px(px), py(py), shape(shape), color(color), asset(asset), progress(progress), vx(vx), vy(vy) {}
|
|
57
62
|
|
|
58
63
|
public:
|
|
59
64
|
friend bool operator==(const EntityUpdate& lhs, const EntityUpdate& rhs) = default;
|
|
@@ -72,8 +77,7 @@ namespace margelo::nitro {
|
|
|
72
77
|
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "id"))),
|
|
73
78
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px"))),
|
|
74
79
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "py"))),
|
|
75
|
-
JSIConverter<std::optional<
|
|
76
|
-
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height"))),
|
|
80
|
+
JSIConverter<std::optional<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "shape"))),
|
|
77
81
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color"))),
|
|
78
82
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset"))),
|
|
79
83
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress"))),
|
|
@@ -86,8 +90,7 @@ namespace margelo::nitro {
|
|
|
86
90
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "id"), JSIConverter<std::string>::toJSI(runtime, arg.id));
|
|
87
91
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "px"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.px));
|
|
88
92
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "py"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.py));
|
|
89
|
-
obj.setProperty(runtime, PropNameIDCache::get(runtime, "
|
|
90
|
-
obj.setProperty(runtime, PropNameIDCache::get(runtime, "height"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.height));
|
|
93
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "shape"), JSIConverter<std::optional<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>>::toJSI(runtime, arg.shape));
|
|
91
94
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "color"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.color));
|
|
92
95
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "asset"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.asset));
|
|
93
96
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "progress"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.progress));
|
|
@@ -106,8 +109,7 @@ namespace margelo::nitro {
|
|
|
106
109
|
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "id")))) return false;
|
|
107
110
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px")))) return false;
|
|
108
111
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "py")))) return false;
|
|
109
|
-
if (!JSIConverter<std::optional<
|
|
110
|
-
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height")))) return false;
|
|
112
|
+
if (!JSIConverter<std::optional<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "shape")))) return false;
|
|
111
113
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color")))) return false;
|
|
112
114
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset")))) return false;
|
|
113
115
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress")))) return false;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
///
|
|
2
|
+
/// Rect.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
|
+
|
|
34
|
+
|
|
35
|
+
namespace margelo::nitro::rngine {
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A struct which can be represented as a JavaScript object (Rect).
|
|
39
|
+
*/
|
|
40
|
+
struct Rect final {
|
|
41
|
+
public:
|
|
42
|
+
double width SWIFT_PRIVATE;
|
|
43
|
+
double height SWIFT_PRIVATE;
|
|
44
|
+
|
|
45
|
+
public:
|
|
46
|
+
Rect() = default;
|
|
47
|
+
explicit Rect(double width, double height): width(width), height(height) {}
|
|
48
|
+
|
|
49
|
+
public:
|
|
50
|
+
friend bool operator==(const Rect& lhs, const Rect& rhs) = default;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
} // namespace margelo::nitro::rngine
|
|
54
|
+
|
|
55
|
+
namespace margelo::nitro {
|
|
56
|
+
|
|
57
|
+
// C++ Rect <> JS Rect (object)
|
|
58
|
+
template <>
|
|
59
|
+
struct JSIConverter<margelo::nitro::rngine::Rect> final {
|
|
60
|
+
static inline margelo::nitro::rngine::Rect fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
|
|
61
|
+
jsi::Object obj = arg.asObject(runtime);
|
|
62
|
+
return margelo::nitro::rngine::Rect(
|
|
63
|
+
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "width"))),
|
|
64
|
+
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height")))
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::Rect& arg) {
|
|
68
|
+
jsi::Object obj(runtime);
|
|
69
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "width"), JSIConverter<double>::toJSI(runtime, arg.width));
|
|
70
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "height"), JSIConverter<double>::toJSI(runtime, arg.height));
|
|
71
|
+
return obj;
|
|
72
|
+
}
|
|
73
|
+
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
74
|
+
if (!value.isObject()) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
jsi::Object obj = value.getObject(runtime);
|
|
78
|
+
if (!nitro::isPlainObject(runtime, obj)) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "width")))) return false;
|
|
82
|
+
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height")))) return false;
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
} // namespace margelo::nitro
|
package/package.json
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#include "CollisionUtils.hpp"
|
|
2
|
+
|
|
3
|
+
namespace margelo::nitro::rngine::CollisionUtils {
|
|
4
|
+
std::optional<double> overlap(const Rect &a, double ax, double ay,
|
|
5
|
+
const Rect &b, double bx, double by) {
|
|
6
|
+
|
|
7
|
+
double aLeft = ax - a.width / 2.0, aRight = ax + a.width / 2.0;
|
|
8
|
+
double aTop = ay - a.height / 2.0, aBottom = ay + a.height / 2.0;
|
|
9
|
+
double bLeft = bx - b.width / 2.0, bRight = bx + b.width / 2.0;
|
|
10
|
+
double bTop = by - b.height / 2.0, bBottom = by + b.height / 2.0;
|
|
11
|
+
|
|
12
|
+
double overlapX = std::min(aRight, bRight) - std::max(aLeft, bLeft);
|
|
13
|
+
double overlapY = std::min(aBottom, bBottom) - std::max(aTop, bTop);
|
|
14
|
+
|
|
15
|
+
if (overlapX > 0 && overlapY > 0)
|
|
16
|
+
return std::min(overlapX, overlapY);
|
|
17
|
+
return std::nullopt;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
std::optional<double> overlap(const Circle &a, double ax, double ay,
|
|
21
|
+
const Circle &b, double bx, double by) {
|
|
22
|
+
double dx = bx - ax, dy = by - ay;
|
|
23
|
+
double dist = std::sqrt(dx * dx + dy * dy);
|
|
24
|
+
double depth = (a.radius + b.radius) - dist;
|
|
25
|
+
|
|
26
|
+
if (depth > 0)
|
|
27
|
+
return depth;
|
|
28
|
+
return std::nullopt;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
std::optional<double> overlap(const Rect &a, double ax, double ay,
|
|
32
|
+
const Circle &b, double bx, double by) {
|
|
33
|
+
double left = ax - a.width / 2.0, right = ax + a.width / 2.0;
|
|
34
|
+
double top = ay - a.height / 2.0, bottom = ay + a.height / 2.0;
|
|
35
|
+
|
|
36
|
+
double closestX = std::clamp(bx, left, right);
|
|
37
|
+
double closestY = std::clamp(by, top, bottom);
|
|
38
|
+
|
|
39
|
+
double dx = bx - closestX, dy = by - closestY;
|
|
40
|
+
double distSq = dx * dx + dy * dy;
|
|
41
|
+
|
|
42
|
+
if (distSq >= b.radius * b.radius)
|
|
43
|
+
return std::nullopt;
|
|
44
|
+
|
|
45
|
+
double dist = std::sqrt(distSq);
|
|
46
|
+
return b.radius - dist;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
std::optional<double> overlap(const Circle &a, double ax, double ay,
|
|
50
|
+
const Rect &b, double bx, double by) {
|
|
51
|
+
return overlap(b, bx, by, a, ax, ay);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
std::optional<double> shapeOverlap(const Entity &entityA,
|
|
55
|
+
const Entity &entityB) {
|
|
56
|
+
return std::visit(
|
|
57
|
+
[&](const auto &shapeA) -> std::optional<double> {
|
|
58
|
+
return std::visit(
|
|
59
|
+
[&](const auto &shapeB) -> std::optional<double> {
|
|
60
|
+
return overlap(shapeA, entityA.px, entityA.py, shapeB, entityB.px,
|
|
61
|
+
entityB.py);
|
|
62
|
+
},
|
|
63
|
+
entityB.shape);
|
|
64
|
+
},
|
|
65
|
+
entityA.shape);
|
|
66
|
+
}
|
|
67
|
+
} // namespace margelo::nitro::rngine::CollisionUtils
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "Circle.hpp"
|
|
4
|
+
#include "Entity.hpp"
|
|
5
|
+
#include "Rect.hpp"
|
|
6
|
+
#include <optional>
|
|
7
|
+
|
|
8
|
+
namespace margelo::nitro::rngine::CollisionUtils {
|
|
9
|
+
std::optional<double> overlap(const Rect &a, double ax, double ay,
|
|
10
|
+
const Rect &b, double bx, double by);
|
|
11
|
+
std::optional<double> overlap(const Circle &a, double ax, double ay,
|
|
12
|
+
const Circle &b, double bx, double by);
|
|
13
|
+
std::optional<double> overlap(const Rect &a, double ax, double ay,
|
|
14
|
+
const Circle &b, double bx, double by);
|
|
15
|
+
std::optional<double> overlap(const Circle &a, double ax, double ay,
|
|
16
|
+
const Rect &b, double bx, double by);
|
|
17
|
+
std::optional<double> shapeOverlap(const Entity &entityA,
|
|
18
|
+
const Entity &entityB);
|
|
19
|
+
} // namespace margelo::nitro::rngine::CollisionUtils
|
package/shared/GameLoop.cpp
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include "GameLoop.hpp"
|
|
2
2
|
#include "Collision.hpp"
|
|
3
|
+
#include "CollisionUtils.hpp"
|
|
3
4
|
#include "Entity.hpp"
|
|
4
5
|
#include <android/log.h>
|
|
5
6
|
#include <chrono>
|
|
@@ -113,8 +114,8 @@ void GameLoop::runSystems() {
|
|
|
113
114
|
auto resolvedEntitiesInternalA = resolveEntitiesInternal(a);
|
|
114
115
|
auto resolvedEntitiesInternalB = resolveEntitiesInternal(b);
|
|
115
116
|
|
|
116
|
-
for (auto
|
|
117
|
-
for (auto
|
|
117
|
+
for (const auto &entityA : resolvedEntitiesInternalA) {
|
|
118
|
+
for (const auto &entityB : resolvedEntitiesInternalB) {
|
|
118
119
|
if (entityA == entityB)
|
|
119
120
|
continue;
|
|
120
121
|
|
|
@@ -125,22 +126,9 @@ void GameLoop::runSystems() {
|
|
|
125
126
|
|
|
126
127
|
uniqueEntityIdPairs.insert(uniqueEntityIdPairKey);
|
|
127
128
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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;
|
|
137
|
-
|
|
138
|
-
double overlapX = std::min(aRight, bRight) - std::max(aLeft, bLeft);
|
|
139
|
-
double overlapY = std::min(aBottom, bBottom) - std::max(aTop, bTop);
|
|
140
|
-
|
|
141
|
-
if (overlapX > 0 && overlapY > 0) {
|
|
142
|
-
collisions.push_back(Collision(entityA->id, entityB->id,
|
|
143
|
-
std::min(overlapX, overlapY)));
|
|
129
|
+
if (auto ov = CollisionUtils::shapeOverlap(*entityA, *entityB)) {
|
|
130
|
+
collisions.push_back(
|
|
131
|
+
Collision(entityA->id, entityB->id, ov.value()));
|
|
144
132
|
}
|
|
145
133
|
}
|
|
146
134
|
}
|
package/shared/GameMethods.cpp
CHANGED
|
@@ -127,11 +127,8 @@ void GameMethods::update(const std::vector<EntityUpdate> &updates) {
|
|
|
127
127
|
if (update.py.has_value()) {
|
|
128
128
|
entity->py = update.py.value();
|
|
129
129
|
}
|
|
130
|
-
if (update.
|
|
131
|
-
entity->
|
|
132
|
-
}
|
|
133
|
-
if (update.height.has_value()) {
|
|
134
|
-
entity->height = update.height.value();
|
|
130
|
+
if (update.shape.has_value()) {
|
|
131
|
+
entity->shape = update.shape.value();
|
|
135
132
|
}
|
|
136
133
|
if (update.asset.has_value()) {
|
|
137
134
|
entity->asset = update.asset.value();
|
package/src/nativeTypes.ts
CHANGED
|
@@ -5,13 +5,23 @@ interface Positioned {
|
|
|
5
5
|
py: number;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
interface
|
|
8
|
+
interface Rect {
|
|
9
9
|
/** Width in game units. */
|
|
10
10
|
width: number;
|
|
11
11
|
/** Height in game units. */
|
|
12
12
|
height: number;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
interface Circle {
|
|
16
|
+
/** Radius in game units. */
|
|
17
|
+
radius: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface Shaped {
|
|
21
|
+
/** Shape of the entity. */
|
|
22
|
+
shape: Rect | Circle;
|
|
23
|
+
}
|
|
24
|
+
|
|
15
25
|
interface Renderable {
|
|
16
26
|
/** Fill color as a hex string e.g. `'#00ff00'`. */
|
|
17
27
|
color?: string;
|
|
@@ -28,7 +38,7 @@ interface Kinematic {
|
|
|
28
38
|
vy?: number;
|
|
29
39
|
}
|
|
30
40
|
|
|
31
|
-
export interface Screen extends
|
|
41
|
+
export interface Screen extends Rect, Renderable {}
|
|
32
42
|
|
|
33
43
|
export interface Entity extends Positioned, Shaped, Renderable, Kinematic {
|
|
34
44
|
/** Unique identifier. Use `_` as a separator for group queries e.g. `'enemy_1'`. */
|