rngine 0.3.1 → 0.4.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 +19 -16
- package/android/build.gradle +6 -4
- package/android/kls_database.db +0 -0
- package/android/src/main/cpp/GameLoopJNI.cpp +20 -9
- package/android/src/main/java/com/margelo/nitro/rngine/Asset.kt +9 -0
- package/android/src/main/java/com/margelo/nitro/rngine/GameAssets.kt +47 -0
- package/android/src/main/java/com/margelo/nitro/rngine/GameView.kt +46 -8
- package/android/src/main/java/com/margelo/nitro/rngine/Rect.kt +7 -5
- package/android/src/main/java/com/margelo/nitro/rngine/RectSerializer.kt +8 -6
- package/lib/module/GameAssets.nitro.js +5 -0
- package/lib/module/GameAssets.nitro.js.map +1 -0
- package/lib/module/GameMethods.js +1 -31
- package/lib/module/GameMethods.js.map +1 -1
- package/lib/module/GameMethods.nitro.js +2 -1
- package/lib/module/GameMethods.nitro.js.map +1 -1
- package/lib/module/Shared.js +72 -0
- package/lib/module/Shared.js.map +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/nativeTypes.js +2 -0
- package/lib/module/nativeTypes.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/typescript/src/GameAssets.nitro.d.ts +12 -0
- package/lib/typescript/src/GameAssets.nitro.d.ts.map +1 -0
- package/lib/typescript/src/GameMethods.d.ts +0 -7
- package/lib/typescript/src/GameMethods.d.ts.map +1 -1
- package/lib/typescript/src/GameMethods.nitro.d.ts +5 -3
- package/lib/typescript/src/GameMethods.nitro.d.ts.map +1 -1
- package/lib/typescript/src/Shared.d.ts +8 -0
- package/lib/typescript/src/Shared.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/nativeTypes.d.ts +79 -0
- package/lib/typescript/src/nativeTypes.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +13 -49
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/nitro.json +10 -0
- package/nitrogen/generated/android/c++/JHybridGameAssetsSpec.cpp +61 -0
- package/nitrogen/generated/android/c++/JHybridGameAssetsSpec.hpp +65 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngine/HybridGameAssetsSpec.kt +62 -0
- package/nitrogen/generated/android/rngine+autolinking.cmake +2 -0
- package/nitrogen/generated/android/rngineOnLoad.cpp +16 -0
- package/nitrogen/generated/ios/Rngine-Swift-Cxx-Bridge.cpp +17 -0
- package/nitrogen/generated/ios/Rngine-Swift-Cxx-Bridge.hpp +37 -0
- package/nitrogen/generated/ios/Rngine-Swift-Cxx-Umbrella.hpp +8 -0
- package/nitrogen/generated/ios/RngineAutolinking.mm +8 -0
- package/nitrogen/generated/ios/RngineAutolinking.swift +12 -0
- package/nitrogen/generated/ios/c++/HybridGameAssetsSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridGameAssetsSpecSwift.hpp +94 -0
- package/nitrogen/generated/ios/swift/HybridGameAssetsSpec.swift +57 -0
- package/nitrogen/generated/ios/swift/HybridGameAssetsSpec_cxx.swift +160 -0
- package/nitrogen/generated/shared/c++/{World.hpp → Collision.hpp} +23 -23
- package/nitrogen/generated/shared/c++/CollisionPair.hpp +87 -0
- package/nitrogen/generated/shared/c++/Entity.hpp +13 -5
- package/nitrogen/generated/shared/c++/EntityUpdate.hpp +9 -1
- package/nitrogen/generated/shared/c++/HybridGameAssetsSpec.cpp +23 -0
- package/nitrogen/generated/shared/c++/HybridGameAssetsSpec.hpp +64 -0
- package/nitrogen/generated/shared/c++/HybridGameMethodsSpec.cpp +1 -1
- package/nitrogen/generated/shared/c++/HybridGameMethodsSpec.hpp +4 -4
- package/nitrogen/generated/shared/c++/Screen.hpp +100 -0
- package/nitrogen/generated/shared/c++/System.hpp +20 -9
- package/package.json +1 -1
- package/shared/ColorUtils.hpp +29 -17
- package/shared/GameLoop.cpp +77 -14
- package/shared/GameLoop.hpp +5 -3
- package/shared/GameMethods.cpp +24 -11
- package/shared/GameMethods.hpp +1 -1
- package/shared/Rect.hpp +8 -5
- package/src/GameAssets.nitro.ts +14 -0
- package/src/GameMethods.nitro.ts +7 -3
- package/src/GameMethods.ts +1 -34
- package/src/Shared.ts +83 -0
- package/src/index.tsx +2 -0
- package/src/nativeTypes.ts +83 -0
- package/src/types.ts +19 -51
|
@@ -15,7 +15,7 @@ namespace margelo::nitro::rngine {
|
|
|
15
15
|
// load custom methods/properties
|
|
16
16
|
registerHybrids(this, [](Prototype& prototype) {
|
|
17
17
|
prototype.registerHybridMethod("setTickRate", &HybridGameMethodsSpec::setTickRate);
|
|
18
|
-
prototype.registerHybridMethod("
|
|
18
|
+
prototype.registerHybridMethod("setScreen", &HybridGameMethodsSpec::setScreen);
|
|
19
19
|
prototype.registerHybridMethod("setEntities", &HybridGameMethodsSpec::setEntities);
|
|
20
20
|
prototype.registerHybridMethod("setSystems", &HybridGameMethodsSpec::setSystems);
|
|
21
21
|
prototype.registerHybridMethod("pause", &HybridGameMethodsSpec::pause);
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
14
14
|
#endif
|
|
15
15
|
|
|
16
|
-
// Forward declaration of `
|
|
17
|
-
namespace margelo::nitro::rngine { struct
|
|
16
|
+
// Forward declaration of `Screen` to properly resolve imports.
|
|
17
|
+
namespace margelo::nitro::rngine { struct Screen; }
|
|
18
18
|
// Forward declaration of `Entity` to properly resolve imports.
|
|
19
19
|
namespace margelo::nitro::rngine { struct Entity; }
|
|
20
20
|
// Forward declaration of `System` to properly resolve imports.
|
|
@@ -22,7 +22,7 @@ namespace margelo::nitro::rngine { struct System; }
|
|
|
22
22
|
// Forward declaration of `EntityUpdate` to properly resolve imports.
|
|
23
23
|
namespace margelo::nitro::rngine { struct EntityUpdate; }
|
|
24
24
|
|
|
25
|
-
#include "
|
|
25
|
+
#include "Screen.hpp"
|
|
26
26
|
#include "Entity.hpp"
|
|
27
27
|
#include <vector>
|
|
28
28
|
#include "System.hpp"
|
|
@@ -61,7 +61,7 @@ namespace margelo::nitro::rngine {
|
|
|
61
61
|
public:
|
|
62
62
|
// Methods
|
|
63
63
|
virtual void setTickRate(double tickRate) = 0;
|
|
64
|
-
virtual void
|
|
64
|
+
virtual void setScreen(const Screen& screen) = 0;
|
|
65
65
|
virtual void setEntities(const std::vector<Entity>& entities) = 0;
|
|
66
66
|
virtual void setSystems(const std::vector<System>& systems) = 0;
|
|
67
67
|
virtual void pause() = 0;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
///
|
|
2
|
+
/// Screen.hpp
|
|
3
|
+
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
+
/// https://github.com/mrousavy/nitro
|
|
5
|
+
/// Copyright © Marc Rousavy @ Margelo
|
|
6
|
+
///
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#if __has_include(<NitroModules/JSIConverter.hpp>)
|
|
11
|
+
#include <NitroModules/JSIConverter.hpp>
|
|
12
|
+
#else
|
|
13
|
+
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
14
|
+
#endif
|
|
15
|
+
#if __has_include(<NitroModules/NitroDefines.hpp>)
|
|
16
|
+
#include <NitroModules/NitroDefines.hpp>
|
|
17
|
+
#else
|
|
18
|
+
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
19
|
+
#endif
|
|
20
|
+
#if __has_include(<NitroModules/JSIHelpers.hpp>)
|
|
21
|
+
#include <NitroModules/JSIHelpers.hpp>
|
|
22
|
+
#else
|
|
23
|
+
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
24
|
+
#endif
|
|
25
|
+
#if __has_include(<NitroModules/PropNameIDCache.hpp>)
|
|
26
|
+
#include <NitroModules/PropNameIDCache.hpp>
|
|
27
|
+
#else
|
|
28
|
+
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
#include <string>
|
|
34
|
+
#include <optional>
|
|
35
|
+
|
|
36
|
+
namespace margelo::nitro::rngine {
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A struct which can be represented as a JavaScript object (Screen).
|
|
40
|
+
*/
|
|
41
|
+
struct Screen final {
|
|
42
|
+
public:
|
|
43
|
+
double width SWIFT_PRIVATE;
|
|
44
|
+
double height SWIFT_PRIVATE;
|
|
45
|
+
std::optional<std::string> color SWIFT_PRIVATE;
|
|
46
|
+
std::optional<double> asset SWIFT_PRIVATE;
|
|
47
|
+
std::optional<double> progress SWIFT_PRIVATE;
|
|
48
|
+
|
|
49
|
+
public:
|
|
50
|
+
Screen() = default;
|
|
51
|
+
explicit Screen(double width, double height, std::optional<std::string> color, std::optional<double> asset, std::optional<double> progress): width(width), height(height), color(color), asset(asset), progress(progress) {}
|
|
52
|
+
|
|
53
|
+
public:
|
|
54
|
+
friend bool operator==(const Screen& lhs, const Screen& rhs) = default;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
} // namespace margelo::nitro::rngine
|
|
58
|
+
|
|
59
|
+
namespace margelo::nitro {
|
|
60
|
+
|
|
61
|
+
// C++ Screen <> JS Screen (object)
|
|
62
|
+
template <>
|
|
63
|
+
struct JSIConverter<margelo::nitro::rngine::Screen> final {
|
|
64
|
+
static inline margelo::nitro::rngine::Screen fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
|
|
65
|
+
jsi::Object obj = arg.asObject(runtime);
|
|
66
|
+
return margelo::nitro::rngine::Screen(
|
|
67
|
+
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "width"))),
|
|
68
|
+
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height"))),
|
|
69
|
+
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color"))),
|
|
70
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset"))),
|
|
71
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress")))
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::Screen& arg) {
|
|
75
|
+
jsi::Object obj(runtime);
|
|
76
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "width"), JSIConverter<double>::toJSI(runtime, arg.width));
|
|
77
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "height"), JSIConverter<double>::toJSI(runtime, arg.height));
|
|
78
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "color"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.color));
|
|
79
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "asset"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.asset));
|
|
80
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "progress"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.progress));
|
|
81
|
+
return obj;
|
|
82
|
+
}
|
|
83
|
+
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
84
|
+
if (!value.isObject()) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
jsi::Object obj = value.getObject(runtime);
|
|
88
|
+
if (!nitro::isPlainObject(runtime, obj)) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "width")))) return false;
|
|
92
|
+
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height")))) return false;
|
|
93
|
+
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color")))) return false;
|
|
94
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset")))) return false;
|
|
95
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress")))) return false;
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
} // namespace margelo::nitro
|
|
@@ -28,12 +28,19 @@
|
|
|
28
28
|
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
29
29
|
#endif
|
|
30
30
|
|
|
31
|
+
// Forward declaration of `CollisionPair` to properly resolve imports.
|
|
32
|
+
namespace margelo::nitro::rngine { struct CollisionPair; }
|
|
31
33
|
// Forward declaration of `Entity` to properly resolve imports.
|
|
32
34
|
namespace margelo::nitro::rngine { struct Entity; }
|
|
35
|
+
// Forward declaration of `Collision` to properly resolve imports.
|
|
36
|
+
namespace margelo::nitro::rngine { struct Collision; }
|
|
33
37
|
|
|
34
38
|
#include <string>
|
|
35
39
|
#include <vector>
|
|
40
|
+
#include <optional>
|
|
41
|
+
#include "CollisionPair.hpp"
|
|
36
42
|
#include "Entity.hpp"
|
|
43
|
+
#include "Collision.hpp"
|
|
37
44
|
#include <functional>
|
|
38
45
|
|
|
39
46
|
namespace margelo::nitro::rngine {
|
|
@@ -43,12 +50,13 @@ namespace margelo::nitro::rngine {
|
|
|
43
50
|
*/
|
|
44
51
|
struct System final {
|
|
45
52
|
public:
|
|
46
|
-
std::vector<std::string
|
|
47
|
-
std::
|
|
53
|
+
std::optional<std::vector<std::string>> entities SWIFT_PRIVATE;
|
|
54
|
+
std::optional<std::vector<CollisionPair>> collisions SWIFT_PRIVATE;
|
|
55
|
+
std::function<void(const std::vector<Entity>& /* entities */, const std::vector<Collision>& /* collisions */)> onTick SWIFT_PRIVATE;
|
|
48
56
|
|
|
49
57
|
public:
|
|
50
58
|
System() = default;
|
|
51
|
-
explicit System(std::vector<std::string
|
|
59
|
+
explicit System(std::optional<std::vector<std::string>> entities, std::optional<std::vector<CollisionPair>> collisions, std::function<void(const std::vector<Entity>& /* entities */, const std::vector<Collision>& /* collisions */)> onTick): entities(entities), collisions(collisions), onTick(onTick) {}
|
|
52
60
|
|
|
53
61
|
public:
|
|
54
62
|
// System is not equatable because these properties are not equatable: onTick
|
|
@@ -64,14 +72,16 @@ namespace margelo::nitro {
|
|
|
64
72
|
static inline margelo::nitro::rngine::System fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
|
|
65
73
|
jsi::Object obj = arg.asObject(runtime);
|
|
66
74
|
return margelo::nitro::rngine::System(
|
|
67
|
-
JSIConverter<std::vector<std::string
|
|
68
|
-
JSIConverter<std::
|
|
75
|
+
JSIConverter<std::optional<std::vector<std::string>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "entities"))),
|
|
76
|
+
JSIConverter<std::optional<std::vector<margelo::nitro::rngine::CollisionPair>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "collisions"))),
|
|
77
|
+
JSIConverter<std::function<void(const std::vector<margelo::nitro::rngine::Entity>&, const std::vector<margelo::nitro::rngine::Collision>&)>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "onTick")))
|
|
69
78
|
);
|
|
70
79
|
}
|
|
71
80
|
static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::System& arg) {
|
|
72
81
|
jsi::Object obj(runtime);
|
|
73
|
-
obj.setProperty(runtime, PropNameIDCache::get(runtime, "
|
|
74
|
-
obj.setProperty(runtime, PropNameIDCache::get(runtime, "
|
|
82
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "entities"), JSIConverter<std::optional<std::vector<std::string>>>::toJSI(runtime, arg.entities));
|
|
83
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "collisions"), JSIConverter<std::optional<std::vector<margelo::nitro::rngine::CollisionPair>>>::toJSI(runtime, arg.collisions));
|
|
84
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "onTick"), JSIConverter<std::function<void(const std::vector<margelo::nitro::rngine::Entity>&, const std::vector<margelo::nitro::rngine::Collision>&)>>::toJSI(runtime, arg.onTick));
|
|
75
85
|
return obj;
|
|
76
86
|
}
|
|
77
87
|
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
@@ -82,8 +92,9 @@ namespace margelo::nitro {
|
|
|
82
92
|
if (!nitro::isPlainObject(runtime, obj)) {
|
|
83
93
|
return false;
|
|
84
94
|
}
|
|
85
|
-
if (!JSIConverter<std::vector<std::string
|
|
86
|
-
if (!JSIConverter<std::
|
|
95
|
+
if (!JSIConverter<std::optional<std::vector<std::string>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "entities")))) return false;
|
|
96
|
+
if (!JSIConverter<std::optional<std::vector<margelo::nitro::rngine::CollisionPair>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "collisions")))) return false;
|
|
97
|
+
if (!JSIConverter<std::function<void(const std::vector<margelo::nitro::rngine::Entity>&, const std::vector<margelo::nitro::rngine::Collision>&)>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "onTick")))) return false;
|
|
87
98
|
return true;
|
|
88
99
|
}
|
|
89
100
|
};
|
package/package.json
CHANGED
package/shared/ColorUtils.hpp
CHANGED
|
@@ -1,25 +1,37 @@
|
|
|
1
1
|
#pragma once
|
|
2
|
-
#include <stdexcept>
|
|
3
2
|
#include <string>
|
|
4
3
|
|
|
5
4
|
namespace margelo::nitro::rngine {
|
|
6
5
|
|
|
7
|
-
inline uint32_t parseHexColor(const std::string &color) {
|
|
8
|
-
if (color.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
6
|
+
inline uint32_t parseHexColor(const std::optional<std::string> &color) {
|
|
7
|
+
if (!color.has_value())
|
|
8
|
+
return 0x00000000;
|
|
9
|
+
const std::string &c = color.value();
|
|
10
|
+
if (!c.empty() && c[0] == '#') {
|
|
11
|
+
std::string hex = c.substr(1);
|
|
12
|
+
|
|
13
|
+
if (hex.size() == 3 || hex.size() == 4) {
|
|
14
|
+
std::string expanded;
|
|
15
|
+
expanded.reserve(hex.size() * 2);
|
|
16
|
+
for (char c : hex) {
|
|
17
|
+
expanded += c;
|
|
18
|
+
expanded += c;
|
|
19
|
+
}
|
|
20
|
+
hex = std::move(expanded);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (hex.size() == 6) {
|
|
24
|
+
return 0xFF000000 | std::stoul(hex, nullptr, 16);
|
|
25
|
+
} else if (hex.size() == 8) {
|
|
26
|
+
uint32_t rgba = std::stoul(hex, nullptr, 16);
|
|
27
|
+
uint32_t r = (rgba >> 24) & 0xFF;
|
|
28
|
+
uint32_t g = (rgba >> 16) & 0xFF;
|
|
29
|
+
uint32_t b = (rgba >> 8) & 0xFF;
|
|
30
|
+
uint32_t a = rgba & 0xFF;
|
|
31
|
+
return (a << 24) | (r << 16) | (g << 8) | b;
|
|
32
|
+
}
|
|
21
33
|
}
|
|
22
|
-
throw std::invalid_argument("Invalid hex color: " + color);
|
|
23
|
-
}
|
|
24
34
|
|
|
35
|
+
return 0x00000000;
|
|
36
|
+
}
|
|
25
37
|
} // namespace margelo::nitro::rngine
|
package/shared/GameLoop.cpp
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#include "GameLoop.hpp"
|
|
2
|
+
#include "Collision.hpp"
|
|
2
3
|
#include "ColorUtils.hpp"
|
|
3
4
|
#include "Entity.hpp"
|
|
4
5
|
#include <android/log.h>
|
|
5
6
|
#include <chrono>
|
|
6
7
|
#include <cinttypes>
|
|
8
|
+
#include <set>
|
|
7
9
|
|
|
8
10
|
namespace margelo::nitro::rngine {
|
|
9
11
|
|
|
@@ -50,25 +52,38 @@ GameLoop::resolveEntitiesInternal(const std::string &prefix) {
|
|
|
50
52
|
return results;
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
void GameLoop::registerLottieDuration(double id, double duration) {
|
|
56
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
|
57
|
+
_lottieDurations[id] = duration;
|
|
58
|
+
__android_log_print(ANDROID_LOG_DEBUG, "GameLoop",
|
|
59
|
+
"Registered lottie duration: id: %.0f, duration: %.4f",
|
|
60
|
+
id, duration);
|
|
61
|
+
}
|
|
62
|
+
|
|
53
63
|
std::vector<Rect> GameLoop::getRectsSnapshot() {
|
|
54
64
|
std::lock_guard<std::mutex> lock(_mutex);
|
|
55
65
|
std::vector<Rect> rects;
|
|
56
66
|
rects.reserve(_entities.size() + 1);
|
|
57
67
|
|
|
58
|
-
rects.push_back(
|
|
59
|
-
|
|
68
|
+
rects.push_back({0, static_cast<float>(_screen.width), 0,
|
|
69
|
+
static_cast<float>(_screen.height),
|
|
70
|
+
static_cast<float>(_screen.progress.value_or(0)),
|
|
71
|
+
parseHexColor(_screen.color),
|
|
72
|
+
static_cast<int32_t>(_screen.asset.value_or(0))});
|
|
60
73
|
|
|
61
74
|
for (const auto &[id, entity] : _entities) {
|
|
62
|
-
if (entity.px + entity.width < 0 || entity.px >
|
|
63
|
-
entity.py + entity.height < 0 || entity.py >
|
|
75
|
+
if (entity.px + entity.width < 0 || entity.px > _screen.width ||
|
|
76
|
+
entity.py + entity.height < 0 || entity.py > _screen.height) {
|
|
64
77
|
continue;
|
|
65
78
|
}
|
|
66
79
|
|
|
67
|
-
rects.push_back({
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
80
|
+
rects.push_back({static_cast<float>(entity.px),
|
|
81
|
+
static_cast<float>(entity.px + entity.width),
|
|
82
|
+
static_cast<float>(entity.py),
|
|
83
|
+
static_cast<float>(entity.py + entity.height),
|
|
84
|
+
static_cast<float>(entity.progress.value_or(0)),
|
|
85
|
+
parseHexColor(entity.color),
|
|
86
|
+
static_cast<int32_t>(entity.asset.value_or(0))});
|
|
72
87
|
}
|
|
73
88
|
return rects;
|
|
74
89
|
}
|
|
@@ -109,14 +124,53 @@ void GameLoop::runGameLoop() {
|
|
|
109
124
|
void GameLoop::runSystems() {
|
|
110
125
|
for (auto &system : _systems) {
|
|
111
126
|
std::vector<Entity> entities;
|
|
127
|
+
std::vector<Collision> collisions;
|
|
112
128
|
|
|
113
|
-
|
|
114
|
-
auto
|
|
115
|
-
|
|
116
|
-
|
|
129
|
+
if (system.entities.has_value()) {
|
|
130
|
+
for (const auto &id : system.entities.value()) {
|
|
131
|
+
auto resolvedEntitiesInternal = resolveEntitiesInternal(id);
|
|
132
|
+
for (auto *entity : resolvedEntitiesInternal)
|
|
133
|
+
entities.push_back(*entity);
|
|
134
|
+
}
|
|
117
135
|
}
|
|
118
136
|
|
|
119
|
-
system.
|
|
137
|
+
if (system.collisions.has_value()) {
|
|
138
|
+
std::set<std::pair<std::string, std::string>> uniqueEntityIdPairs;
|
|
139
|
+
|
|
140
|
+
for (const auto &[a, b] : system.collisions.value()) {
|
|
141
|
+
auto resolvedEntitiesInternalA = resolveEntitiesInternal(a);
|
|
142
|
+
auto resolvedEntitiesInternalB = resolveEntitiesInternal(b);
|
|
143
|
+
|
|
144
|
+
for (auto *entityA : resolvedEntitiesInternalA) {
|
|
145
|
+
for (auto *entityB : resolvedEntitiesInternalB) {
|
|
146
|
+
if (entityA == entityB)
|
|
147
|
+
continue;
|
|
148
|
+
|
|
149
|
+
auto uniqueEntityIdPairKey = std::minmax(entityA->id, entityB->id);
|
|
150
|
+
|
|
151
|
+
if (uniqueEntityIdPairs.count(uniqueEntityIdPairKey))
|
|
152
|
+
continue;
|
|
153
|
+
|
|
154
|
+
uniqueEntityIdPairs.insert(uniqueEntityIdPairKey);
|
|
155
|
+
|
|
156
|
+
float aLeft = entityA->px, aRight = entityA->px + entityA->width;
|
|
157
|
+
float aTop = entityA->py, aBottom = entityA->py + entityA->height;
|
|
158
|
+
float bLeft = entityB->px, bRight = entityB->px + entityB->width;
|
|
159
|
+
float bTop = entityB->py, bBottom = entityB->py + entityB->height;
|
|
160
|
+
|
|
161
|
+
float overlapX = std::min(aRight, bRight) - std::max(aLeft, bLeft);
|
|
162
|
+
float overlapY = std::min(aBottom, bBottom) - std::max(aTop, bTop);
|
|
163
|
+
|
|
164
|
+
if (overlapX > 0 && overlapY > 0) {
|
|
165
|
+
collisions.push_back(Collision(entityA->id, entityB->id,
|
|
166
|
+
std::min(overlapX, overlapY)));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
system.onTick(entities, collisions);
|
|
120
174
|
}
|
|
121
175
|
}
|
|
122
176
|
|
|
@@ -156,9 +210,18 @@ void GameLoop::updateEntities(double deltaTime) {
|
|
|
156
210
|
if (entity.vx) {
|
|
157
211
|
entity.px += *entity.vx * deltaTime;
|
|
158
212
|
}
|
|
213
|
+
|
|
159
214
|
if (entity.vy) {
|
|
160
215
|
entity.py += *entity.vy * deltaTime;
|
|
161
216
|
}
|
|
217
|
+
|
|
218
|
+
if (entity.asset && entity.asset < 0) {
|
|
219
|
+
auto it = _lottieDurations.find(*entity.asset);
|
|
220
|
+
if (it != _lottieDurations.end() && it->second > 0.0) {
|
|
221
|
+
entity.progress =
|
|
222
|
+
fmod(entity.progress.value_or(0.0) + deltaTime / it->second, 1.0);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
162
225
|
}
|
|
163
226
|
}
|
|
164
227
|
} // namespace margelo::nitro::rngine
|
package/shared/GameLoop.hpp
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
#include "Entity.hpp"
|
|
4
4
|
#include "GameStats.hpp"
|
|
5
5
|
#include "Rect.hpp"
|
|
6
|
+
#include "Screen.hpp"
|
|
6
7
|
#include "System.hpp"
|
|
7
|
-
#include "World.hpp"
|
|
8
8
|
#include <atomic>
|
|
9
9
|
#include <memory>
|
|
10
10
|
#include <thread>
|
|
@@ -25,9 +25,10 @@ public:
|
|
|
25
25
|
std::map<string, Entity> &getEntitiesInternal() { return _entities; };
|
|
26
26
|
std::vector<System> &getSystemsInternal() { return _systems; };
|
|
27
27
|
std::atomic<bool> &getIsPausedInternal() { return _isPaused; };
|
|
28
|
-
|
|
28
|
+
Screen &getScreenInternal() { return _screen; };
|
|
29
29
|
|
|
30
30
|
std::vector<Entity *> resolveEntitiesInternal(const std::string &prefix);
|
|
31
|
+
void registerLottieDuration(double, double);
|
|
31
32
|
std::vector<Rect> getRectsSnapshot();
|
|
32
33
|
|
|
33
34
|
void setTickRate(double tickRate) { _tickRate = tickRate; };
|
|
@@ -36,11 +37,12 @@ private:
|
|
|
36
37
|
explicit GameLoop();
|
|
37
38
|
std::mutex _mutex;
|
|
38
39
|
std::map<std::string, Entity> _entities;
|
|
40
|
+
std::map<double, double> _lottieDurations;
|
|
39
41
|
std::vector<System> _systems{};
|
|
40
42
|
std::atomic<bool> _isRunning{true};
|
|
41
43
|
std::atomic<bool> _isPaused{true};
|
|
42
44
|
double _tickRate{60.0};
|
|
43
|
-
|
|
45
|
+
Screen _screen;
|
|
44
46
|
GameStats _gameStats;
|
|
45
47
|
std::unique_ptr<std::thread> _gameThread;
|
|
46
48
|
|
package/shared/GameMethods.cpp
CHANGED
|
@@ -12,13 +12,13 @@ void GameMethods::setTickRate(double tickRate) {
|
|
|
12
12
|
"setTickRate: tickRate=%.1f", tickRate);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
void GameMethods::
|
|
15
|
+
void GameMethods::setScreen(const Screen &screen) {
|
|
16
16
|
auto &instance = GameLoop::getInstance();
|
|
17
17
|
std::lock_guard<std::mutex> lock(instance.getMutexInternal());
|
|
18
|
-
instance.
|
|
18
|
+
instance.getScreenInternal() = screen;
|
|
19
19
|
__android_log_print(ANDROID_LOG_INFO, "GameMethods",
|
|
20
|
-
"setWorld: width=%.0f height=%.0f",
|
|
21
|
-
|
|
20
|
+
"setWorld: width=%.0f height=%.0f", screen.width,
|
|
21
|
+
screen.height);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
void GameMethods::setEntities(const std::vector<Entity> &entities) {
|
|
@@ -114,20 +114,33 @@ void GameMethods::update(const std::vector<EntityUpdate> &updates) {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
for (auto *entity : resolvedEntitiesInternals) {
|
|
117
|
-
if (update.px.has_value())
|
|
117
|
+
if (update.px.has_value()) {
|
|
118
118
|
entity->px = update.px.value();
|
|
119
|
-
|
|
119
|
+
}
|
|
120
|
+
if (update.py.has_value()) {
|
|
120
121
|
entity->py = update.py.value();
|
|
121
|
-
|
|
122
|
+
}
|
|
123
|
+
if (update.width.has_value()) {
|
|
122
124
|
entity->width = update.width.value();
|
|
123
|
-
|
|
125
|
+
}
|
|
126
|
+
if (update.height.has_value()) {
|
|
124
127
|
entity->height = update.height.value();
|
|
125
|
-
|
|
128
|
+
}
|
|
129
|
+
if (update.asset.has_value()) {
|
|
130
|
+
entity->asset = update.asset.value();
|
|
131
|
+
}
|
|
132
|
+
if (update.progress.has_value()) {
|
|
133
|
+
entity->progress = update.progress.value();
|
|
134
|
+
}
|
|
135
|
+
if (update.color.has_value()) {
|
|
126
136
|
entity->color = update.color.value();
|
|
127
|
-
|
|
137
|
+
}
|
|
138
|
+
if (update.vx.has_value()) {
|
|
128
139
|
entity->vx = update.vx.value();
|
|
129
|
-
|
|
140
|
+
}
|
|
141
|
+
if (update.vy.has_value()) {
|
|
130
142
|
entity->vy = update.vy.value();
|
|
143
|
+
}
|
|
131
144
|
}
|
|
132
145
|
|
|
133
146
|
__android_log_print(ANDROID_LOG_INFO, "GameMethods",
|
package/shared/GameMethods.hpp
CHANGED
|
@@ -7,7 +7,7 @@ class GameMethods : public HybridGameMethodsSpec {
|
|
|
7
7
|
public:
|
|
8
8
|
GameMethods() : HybridObject(TAG) {}
|
|
9
9
|
void setTickRate(double tickRate) override;
|
|
10
|
-
void
|
|
10
|
+
void setScreen(const Screen &screen) override;
|
|
11
11
|
void setEntities(const std::vector<Entity> &entities) override;
|
|
12
12
|
void setSystems(const std::vector<System> &systems) override;
|
|
13
13
|
void pause() override;
|
package/shared/Rect.hpp
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
namespace margelo::nitro::rngine {
|
|
4
|
-
static constexpr int RECT_SIZE =
|
|
4
|
+
static constexpr int RECT_SIZE =
|
|
5
|
+
sizeof(float) * 5 + sizeof(uint32_t) + sizeof(int32_t);
|
|
5
6
|
|
|
6
7
|
struct Rect {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
float left;
|
|
9
|
+
float right;
|
|
10
|
+
float top;
|
|
11
|
+
float bottom;
|
|
12
|
+
float progress;
|
|
11
13
|
uint32_t color;
|
|
14
|
+
int32_t asset;
|
|
12
15
|
};
|
|
13
16
|
} // namespace margelo::nitro::rngine
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { HybridObject } from 'react-native-nitro-modules';
|
|
2
|
+
import { NitroModules } from 'react-native-nitro-modules';
|
|
3
|
+
|
|
4
|
+
interface GameAssets extends HybridObject<{
|
|
5
|
+
ios: 'swift';
|
|
6
|
+
android: 'kotlin';
|
|
7
|
+
}> {
|
|
8
|
+
isAssetRegistered(id: number): boolean;
|
|
9
|
+
registerSvg(id: number, uri: string): void;
|
|
10
|
+
registerLottie(id: number, json: string): void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const gameAssets =
|
|
14
|
+
NitroModules.createHybridObject<GameAssets>('GameAssets');
|
package/src/GameMethods.nitro.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { HybridObject } from 'react-native-nitro-modules';
|
|
2
|
-
import type { Entity, EntityUpdate, System,
|
|
2
|
+
import type { Entity, EntityUpdate, System, Screen } from './nativeTypes';
|
|
3
|
+
import { NitroModules } from 'react-native-nitro-modules';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
interface GameMethods extends HybridObject<{
|
|
5
6
|
ios: 'c++';
|
|
6
7
|
android: 'c++';
|
|
7
8
|
}> {
|
|
8
9
|
setTickRate(tickRate: number): void;
|
|
9
|
-
|
|
10
|
+
setScreen(screen: Screen): void;
|
|
10
11
|
setEntities(entities: Entity[]): void;
|
|
11
12
|
setSystems(systems: System[]): void;
|
|
12
13
|
pause(): void;
|
|
@@ -15,3 +16,6 @@ export interface GameMethods extends HybridObject<{
|
|
|
15
16
|
despawn(id: string): void;
|
|
16
17
|
update(updates: EntityUpdate[]): void;
|
|
17
18
|
}
|
|
19
|
+
|
|
20
|
+
export const gameMethods =
|
|
21
|
+
NitroModules.createHybridObject<GameMethods>('GameMethods');
|
package/src/GameMethods.ts
CHANGED
|
@@ -1,27 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { GameMethods } from './GameMethods.nitro';
|
|
3
|
-
import type { Config, Entity, EntityUpdate } from './types';
|
|
4
|
-
|
|
5
|
-
const gameMethods = NitroModules.createHybridObject<GameMethods>('GameMethods');
|
|
6
|
-
|
|
7
|
-
/** Sets up the game engine with the given configuration. Call this before anything else. */
|
|
8
|
-
export function configure({
|
|
9
|
-
tickRate,
|
|
10
|
-
world,
|
|
11
|
-
entities = [],
|
|
12
|
-
systems = [],
|
|
13
|
-
paused = true,
|
|
14
|
-
}: Config) {
|
|
15
|
-
gameMethods.setTickRate(tickRate);
|
|
16
|
-
gameMethods.setWorld(world);
|
|
17
|
-
gameMethods.setEntities(entities);
|
|
18
|
-
gameMethods.setSystems(systems);
|
|
19
|
-
if (paused) {
|
|
20
|
-
gameMethods.pause();
|
|
21
|
-
} else {
|
|
22
|
-
gameMethods.resume();
|
|
23
|
-
}
|
|
24
|
-
}
|
|
1
|
+
import { gameMethods } from './GameMethods.nitro';
|
|
25
2
|
|
|
26
3
|
/** Pauses the game loop. Systems will stop running. */
|
|
27
4
|
export const pause = () => gameMethods.pause();
|
|
@@ -29,15 +6,5 @@ export const pause = () => gameMethods.pause();
|
|
|
29
6
|
/** Resumes the game loop. */
|
|
30
7
|
export const resume = () => gameMethods.resume();
|
|
31
8
|
|
|
32
|
-
/** Spawns one or more entities into the world. Skips duplicates by id. */
|
|
33
|
-
export const spawn = (entities: Entity | Entity[]) => {
|
|
34
|
-
gameMethods.spawn(Array.isArray(entities) ? entities : [entities]);
|
|
35
|
-
};
|
|
36
|
-
|
|
37
9
|
/** Removes an entity or all entities matching the given id prefix from the world. */
|
|
38
10
|
export const despawn = (id: string) => gameMethods.despawn(id);
|
|
39
|
-
|
|
40
|
-
/** Updates one or more entities. Only the provided fields are changed. */
|
|
41
|
-
export const update = (updates: EntityUpdate | EntityUpdate[]) => {
|
|
42
|
-
gameMethods.update(Array.isArray(updates) ? updates : [updates]);
|
|
43
|
-
};
|