rngine 0.6.0 → 0.7.1
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 +16 -4
- 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 +21 -11
- package/nitrogen/generated/shared/c++/EntityUpdate.hpp +21 -11
- 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 +19 -24
- package/shared/GameMethods.cpp +8 -5
- package/src/nativeTypes.ts +18 -4
- 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;
|
|
@@ -19,12 +27,16 @@ interface Renderable {
|
|
|
19
27
|
progress?: number;
|
|
20
28
|
}
|
|
21
29
|
interface Kinematic {
|
|
22
|
-
/**
|
|
30
|
+
/** Horizontal velocity in game units per second. */
|
|
23
31
|
vx?: number;
|
|
24
|
-
/**
|
|
32
|
+
/** Vertical velocity in game units per second. */
|
|
25
33
|
vy?: number;
|
|
34
|
+
/** Horizontal acceleration in game units per second squared. */
|
|
35
|
+
ax?: number;
|
|
36
|
+
/** Vertical acceleration in game units per second squared. */
|
|
37
|
+
ay?: number;
|
|
26
38
|
}
|
|
27
|
-
export interface Screen extends
|
|
39
|
+
export interface Screen extends Rect, Renderable {
|
|
28
40
|
}
|
|
29
41
|
export interface Entity extends Positioned, Shaped, Renderable, Kinematic {
|
|
30
42
|
/** 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,oDAAoD;IACpD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,MAAO,SAAQ,IAAI,EAAE,UAAU;CAAG;AAEnD,MAAM,WAAW,MAAO,SAAQ,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS;IACvE,oFAAoF;IACpF,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAa,SAAQ,OAAO,CAC3C,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAC7C;IACC,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,CAAC,EAAE,MAAM,CAAC;IACV,yDAAyD;IACzD,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,CAAC,EAAE,MAAM,CAAC;IACV,yDAAyD;IACzD,CAAC,EAAE,MAAM,CAAC;IACV,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;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,17 +49,18 @@ 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;
|
|
51
56
|
std::optional<double> vx SWIFT_PRIVATE;
|
|
52
57
|
std::optional<double> vy SWIFT_PRIVATE;
|
|
58
|
+
std::optional<double> ax SWIFT_PRIVATE;
|
|
59
|
+
std::optional<double> ay SWIFT_PRIVATE;
|
|
53
60
|
|
|
54
61
|
public:
|
|
55
62
|
Entity() = default;
|
|
56
|
-
explicit Entity(std::string id, double px, double py,
|
|
63
|
+
explicit Entity(std::string id, double px, double py, std::variant<Rect, Circle> shape, std::optional<std::string> color, std::optional<double> asset, std::optional<double> progress, std::optional<double> vx, std::optional<double> vy, std::optional<double> ax, std::optional<double> ay): id(id), px(px), py(py), shape(shape), color(color), asset(asset), progress(progress), vx(vx), vy(vy), ax(ax), ay(ay) {}
|
|
57
64
|
|
|
58
65
|
public:
|
|
59
66
|
friend bool operator==(const Entity& lhs, const Entity& rhs) = default;
|
|
@@ -72,13 +79,14 @@ namespace margelo::nitro {
|
|
|
72
79
|
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "id"))),
|
|
73
80
|
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px"))),
|
|
74
81
|
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"))),
|
|
82
|
+
JSIConverter<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "shape"))),
|
|
77
83
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color"))),
|
|
78
84
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset"))),
|
|
79
85
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress"))),
|
|
80
86
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vx"))),
|
|
81
|
-
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy")))
|
|
87
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy"))),
|
|
88
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ax"))),
|
|
89
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ay")))
|
|
82
90
|
);
|
|
83
91
|
}
|
|
84
92
|
static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::Entity& arg) {
|
|
@@ -86,13 +94,14 @@ namespace margelo::nitro {
|
|
|
86
94
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "id"), JSIConverter<std::string>::toJSI(runtime, arg.id));
|
|
87
95
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "px"), JSIConverter<double>::toJSI(runtime, arg.px));
|
|
88
96
|
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));
|
|
97
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "shape"), JSIConverter<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>::toJSI(runtime, arg.shape));
|
|
91
98
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "color"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.color));
|
|
92
99
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "asset"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.asset));
|
|
93
100
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "progress"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.progress));
|
|
94
101
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "vx"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.vx));
|
|
95
102
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "vy"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.vy));
|
|
103
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "ax"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.ax));
|
|
104
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "ay"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.ay));
|
|
96
105
|
return obj;
|
|
97
106
|
}
|
|
98
107
|
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
@@ -106,13 +115,14 @@ namespace margelo::nitro {
|
|
|
106
115
|
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "id")))) return false;
|
|
107
116
|
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px")))) return false;
|
|
108
117
|
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;
|
|
118
|
+
if (!JSIConverter<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "shape")))) return false;
|
|
111
119
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color")))) return false;
|
|
112
120
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset")))) return false;
|
|
113
121
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress")))) return false;
|
|
114
122
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vx")))) return false;
|
|
115
123
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy")))) return false;
|
|
124
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ax")))) return false;
|
|
125
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ay")))) return false;
|
|
116
126
|
return true;
|
|
117
127
|
}
|
|
118
128
|
};
|
|
@@ -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,17 +49,18 @@ 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;
|
|
51
56
|
std::optional<double> vx SWIFT_PRIVATE;
|
|
52
57
|
std::optional<double> vy SWIFT_PRIVATE;
|
|
58
|
+
std::optional<double> ax SWIFT_PRIVATE;
|
|
59
|
+
std::optional<double> ay SWIFT_PRIVATE;
|
|
53
60
|
|
|
54
61
|
public:
|
|
55
62
|
EntityUpdate() = default;
|
|
56
|
-
explicit EntityUpdate(std::string id, std::optional<double> px, std::optional<double> py, std::optional<
|
|
63
|
+
explicit EntityUpdate(std::string id, std::optional<double> px, std::optional<double> py, std::optional<std::variant<Rect, Circle>> shape, std::optional<std::string> color, std::optional<double> asset, std::optional<double> progress, std::optional<double> vx, std::optional<double> vy, std::optional<double> ax, std::optional<double> ay): id(id), px(px), py(py), shape(shape), color(color), asset(asset), progress(progress), vx(vx), vy(vy), ax(ax), ay(ay) {}
|
|
57
64
|
|
|
58
65
|
public:
|
|
59
66
|
friend bool operator==(const EntityUpdate& lhs, const EntityUpdate& rhs) = default;
|
|
@@ -72,13 +79,14 @@ namespace margelo::nitro {
|
|
|
72
79
|
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "id"))),
|
|
73
80
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px"))),
|
|
74
81
|
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"))),
|
|
82
|
+
JSIConverter<std::optional<std::variant<margelo::nitro::rngine::Rect, margelo::nitro::rngine::Circle>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "shape"))),
|
|
77
83
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color"))),
|
|
78
84
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset"))),
|
|
79
85
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress"))),
|
|
80
86
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vx"))),
|
|
81
|
-
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy")))
|
|
87
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy"))),
|
|
88
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ax"))),
|
|
89
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ay")))
|
|
82
90
|
);
|
|
83
91
|
}
|
|
84
92
|
static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::EntityUpdate& arg) {
|
|
@@ -86,13 +94,14 @@ namespace margelo::nitro {
|
|
|
86
94
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "id"), JSIConverter<std::string>::toJSI(runtime, arg.id));
|
|
87
95
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "px"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.px));
|
|
88
96
|
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));
|
|
97
|
+
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
98
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "color"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.color));
|
|
92
99
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "asset"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.asset));
|
|
93
100
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "progress"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.progress));
|
|
94
101
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "vx"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.vx));
|
|
95
102
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "vy"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.vy));
|
|
103
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "ax"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.ax));
|
|
104
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "ay"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.ay));
|
|
96
105
|
return obj;
|
|
97
106
|
}
|
|
98
107
|
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
@@ -106,13 +115,14 @@ namespace margelo::nitro {
|
|
|
106
115
|
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "id")))) return false;
|
|
107
116
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px")))) return false;
|
|
108
117
|
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;
|
|
118
|
+
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
119
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color")))) return false;
|
|
112
120
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset")))) return false;
|
|
113
121
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress")))) return false;
|
|
114
122
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vx")))) return false;
|
|
115
123
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "vy")))) return false;
|
|
124
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ax")))) return false;
|
|
125
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "ay")))) return false;
|
|
116
126
|
return true;
|
|
117
127
|
}
|
|
118
128
|
};
|
|
@@ -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
|
}
|
|
@@ -204,16 +192,23 @@ void GameLoop::updateEntities(double deltaTime) {
|
|
|
204
192
|
std::lock_guard<std::mutex> lock(_mutex);
|
|
205
193
|
|
|
206
194
|
for (auto &[id, entity] : _entities) {
|
|
207
|
-
|
|
208
|
-
|
|
195
|
+
|
|
196
|
+
if (entity.ax.has_value()) {
|
|
197
|
+
entity.vx = entity.vx.value_or(0.0) + entity.ax.value() * deltaTime;
|
|
198
|
+
}
|
|
199
|
+
if (entity.ay.has_value()) {
|
|
200
|
+
entity.vy = entity.vy.value_or(0.0) + entity.ay.value() * deltaTime;
|
|
209
201
|
}
|
|
210
202
|
|
|
211
|
-
if (entity.
|
|
212
|
-
entity.
|
|
203
|
+
if (entity.vx.has_value()) {
|
|
204
|
+
entity.px += entity.vx.value() * deltaTime;
|
|
205
|
+
}
|
|
206
|
+
if (entity.vy.has_value()) {
|
|
207
|
+
entity.py += entity.vy.value() * deltaTime;
|
|
213
208
|
}
|
|
214
209
|
|
|
215
|
-
if (entity.asset && entity.asset < 0) {
|
|
216
|
-
auto it = _lottieDurations.find(
|
|
210
|
+
if (entity.asset.has_value() && entity.asset.value() < 0) {
|
|
211
|
+
auto it = _lottieDurations.find(entity.asset.value());
|
|
217
212
|
if (it != _lottieDurations.end() && it->second > 0.0) {
|
|
218
213
|
entity.progress =
|
|
219
214
|
fmod(entity.progress.value_or(0.0) + deltaTime / it->second, 1.0);
|
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();
|
|
@@ -148,6 +145,12 @@ void GameMethods::update(const std::vector<EntityUpdate> &updates) {
|
|
|
148
145
|
if (update.vy.has_value()) {
|
|
149
146
|
entity->vy = update.vy.value();
|
|
150
147
|
}
|
|
148
|
+
if (update.ax.has_value()) {
|
|
149
|
+
entity->ax = update.ax.value();
|
|
150
|
+
}
|
|
151
|
+
if (update.ay.has_value()) {
|
|
152
|
+
entity->ay = update.ay.value();
|
|
153
|
+
}
|
|
151
154
|
}
|
|
152
155
|
|
|
153
156
|
__android_log_print(ANDROID_LOG_INFO, "GameMethods",
|
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;
|
|
@@ -22,13 +32,17 @@ interface Renderable {
|
|
|
22
32
|
}
|
|
23
33
|
|
|
24
34
|
interface Kinematic {
|
|
25
|
-
/**
|
|
35
|
+
/** Horizontal velocity in game units per second. */
|
|
26
36
|
vx?: number;
|
|
27
|
-
/**
|
|
37
|
+
/** Vertical velocity in game units per second. */
|
|
28
38
|
vy?: number;
|
|
39
|
+
/** Horizontal acceleration in game units per second squared. */
|
|
40
|
+
ax?: number;
|
|
41
|
+
/** Vertical acceleration in game units per second squared. */
|
|
42
|
+
ay?: number;
|
|
29
43
|
}
|
|
30
44
|
|
|
31
|
-
export interface Screen extends
|
|
45
|
+
export interface Screen extends Rect, Renderable {}
|
|
32
46
|
|
|
33
47
|
export interface Entity extends Positioned, Shaped, Renderable, Kinematic {
|
|
34
48
|
/** Unique identifier. Use `_` as a separator for group queries e.g. `'enemy_1'`. */
|