rngine 0.8.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +28 -21
  2. package/android/CMakeLists.txt +5 -2
  3. package/android/kls_database.db +0 -0
  4. package/android/src/main/java/com/margelo/nitro/rngine/ImageLoaderHelper.kt +56 -0
  5. package/lib/module/GameMethods.js +23 -10
  6. package/lib/module/GameMethods.js.map +1 -1
  7. package/lib/module/GameMethods.nitro.js.map +1 -1
  8. package/lib/module/index.js.map +1 -1
  9. package/lib/typescript/src/GameMethods.d.ts +11 -4
  10. package/lib/typescript/src/GameMethods.d.ts.map +1 -1
  11. package/lib/typescript/src/GameMethods.nitro.d.ts +9 -3
  12. package/lib/typescript/src/GameMethods.nitro.d.ts.map +1 -1
  13. package/lib/typescript/src/index.d.ts +1 -1
  14. package/lib/typescript/src/index.d.ts.map +1 -1
  15. package/lib/typescript/src/nativeTypes.d.ts +12 -2
  16. package/lib/typescript/src/nativeTypes.d.ts.map +1 -1
  17. package/lib/typescript/src/types.d.ts +2 -2
  18. package/lib/typescript/src/types.d.ts.map +1 -1
  19. package/nitrogen/generated/shared/c++/HybridGameMethodsSpec.cpp +3 -2
  20. package/nitrogen/generated/shared/c++/HybridGameMethodsSpec.hpp +6 -2
  21. package/nitrogen/generated/shared/c++/Screen.hpp +9 -1
  22. package/nitrogen/generated/shared/c++/ScreenUpdate.hpp +120 -0
  23. package/nitrogen/generated/shared/c++/System.hpp +8 -11
  24. package/nitrogen/generated/shared/c++/SystemContext.hpp +99 -0
  25. package/package.json +1 -1
  26. package/shared/GameLoop.cpp +16 -33
  27. package/shared/GameMethods.cpp +124 -92
  28. package/shared/GameMethods.hpp +5 -3
  29. package/shared/GameRenderer.cpp +27 -81
  30. package/shared/GameRenderer.hpp +8 -5
  31. package/shared/utils/AssetUtils.cpp +92 -0
  32. package/shared/utils/AssetUtils.hpp +11 -0
  33. package/shared/{CollisionUtils.cpp → utils/CollisionUtils.cpp} +9 -8
  34. package/shared/utils/CollisionUtils.hpp +10 -0
  35. package/src/GameMethods.nitro.ts +12 -2
  36. package/src/GameMethods.ts +23 -11
  37. package/src/index.tsx +1 -0
  38. package/src/nativeTypes.ts +13 -2
  39. package/src/types.ts +2 -2
  40. package/android/src/main/java/com/margelo/nitro/rngine/SvgLoaderHelper.kt +0 -24
  41. package/shared/CollisionUtils.hpp +0 -21
  42. /package/shared/{ColorUtils.cpp → utils/ColorUtils.cpp} +0 -0
  43. /package/shared/{ColorUtils.hpp → utils/ColorUtils.hpp} +0 -0
@@ -0,0 +1,120 @@
1
+ ///
2
+ /// ScreenUpdate.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 <optional>
34
+ #include <string>
35
+
36
+ namespace margelo::nitro::rngine {
37
+
38
+ /**
39
+ * A struct which can be represented as a JavaScript object (ScreenUpdate).
40
+ */
41
+ struct ScreenUpdate final {
42
+ public:
43
+ std::optional<double> px SWIFT_PRIVATE;
44
+ std::optional<double> py SWIFT_PRIVATE;
45
+ std::optional<double> width SWIFT_PRIVATE;
46
+ std::optional<double> height SWIFT_PRIVATE;
47
+ std::optional<std::string> color SWIFT_PRIVATE;
48
+ std::optional<double> asset SWIFT_PRIVATE;
49
+ std::optional<bool> flipH SWIFT_PRIVATE;
50
+ std::optional<bool> flipV SWIFT_PRIVATE;
51
+ std::optional<double> progress SWIFT_PRIVATE;
52
+ std::optional<double> speed SWIFT_PRIVATE;
53
+
54
+ public:
55
+ ScreenUpdate() = default;
56
+ explicit ScreenUpdate(std::optional<double> px, std::optional<double> py, std::optional<double> width, std::optional<double> height, std::optional<std::string> color, std::optional<double> asset, std::optional<bool> flipH, std::optional<bool> flipV, std::optional<double> progress, std::optional<double> speed): px(px), py(py), width(width), height(height), color(color), asset(asset), flipH(flipH), flipV(flipV), progress(progress), speed(speed) {}
57
+
58
+ public:
59
+ friend bool operator==(const ScreenUpdate& lhs, const ScreenUpdate& rhs) = default;
60
+ };
61
+
62
+ } // namespace margelo::nitro::rngine
63
+
64
+ namespace margelo::nitro {
65
+
66
+ // C++ ScreenUpdate <> JS ScreenUpdate (object)
67
+ template <>
68
+ struct JSIConverter<margelo::nitro::rngine::ScreenUpdate> final {
69
+ static inline margelo::nitro::rngine::ScreenUpdate fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
70
+ jsi::Object obj = arg.asObject(runtime);
71
+ return margelo::nitro::rngine::ScreenUpdate(
72
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px"))),
73
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "py"))),
74
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "width"))),
75
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height"))),
76
+ JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color"))),
77
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset"))),
78
+ JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "flipH"))),
79
+ JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "flipV"))),
80
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress"))),
81
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "speed")))
82
+ );
83
+ }
84
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::ScreenUpdate& arg) {
85
+ jsi::Object obj(runtime);
86
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "px"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.px));
87
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "py"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.py));
88
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "width"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.width));
89
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "height"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.height));
90
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "color"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.color));
91
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "asset"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.asset));
92
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "flipH"), JSIConverter<std::optional<bool>>::toJSI(runtime, arg.flipH));
93
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "flipV"), JSIConverter<std::optional<bool>>::toJSI(runtime, arg.flipV));
94
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "progress"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.progress));
95
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "speed"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.speed));
96
+ return obj;
97
+ }
98
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
99
+ if (!value.isObject()) {
100
+ return false;
101
+ }
102
+ jsi::Object obj = value.getObject(runtime);
103
+ if (!nitro::isPlainObject(runtime, obj)) {
104
+ return false;
105
+ }
106
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "px")))) return false;
107
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "py")))) return false;
108
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "width")))) return false;
109
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "height")))) return false;
110
+ if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "color")))) return false;
111
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "asset")))) return false;
112
+ if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "flipH")))) return false;
113
+ if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "flipV")))) return false;
114
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "progress")))) return false;
115
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "speed")))) return false;
116
+ return true;
117
+ }
118
+ };
119
+
120
+ } // namespace margelo::nitro
@@ -30,18 +30,15 @@
30
30
 
31
31
  // Forward declaration of `CollisionPair` to properly resolve imports.
32
32
  namespace margelo::nitro::rngine { struct CollisionPair; }
33
- // Forward declaration of `Entity` to properly resolve imports.
34
- namespace margelo::nitro::rngine { struct Entity; }
35
- // Forward declaration of `Collision` to properly resolve imports.
36
- namespace margelo::nitro::rngine { struct Collision; }
33
+ // Forward declaration of `SystemContext` to properly resolve imports.
34
+ namespace margelo::nitro::rngine { struct SystemContext; }
37
35
 
38
36
  #include <string>
39
37
  #include <vector>
40
38
  #include <optional>
41
39
  #include "CollisionPair.hpp"
42
40
  #include <NitroModules/Promise.hpp>
43
- #include "Entity.hpp"
44
- #include "Collision.hpp"
41
+ #include "SystemContext.hpp"
45
42
  #include <functional>
46
43
 
47
44
  namespace margelo::nitro::rngine {
@@ -53,11 +50,11 @@ namespace margelo::nitro::rngine {
53
50
  public:
54
51
  std::optional<std::vector<std::string>> entities SWIFT_PRIVATE;
55
52
  std::optional<std::vector<CollisionPair>> collisions SWIFT_PRIVATE;
56
- std::function<std::shared_ptr<Promise<double>>(const std::vector<Entity>& /* entities */, const std::vector<Collision>& /* collisions */)> onTick SWIFT_PRIVATE;
53
+ std::function<std::shared_ptr<Promise<double>>(const SystemContext& /* systemContext */)> onTick SWIFT_PRIVATE;
57
54
 
58
55
  public:
59
56
  System() = default;
60
- explicit System(std::optional<std::vector<std::string>> entities, std::optional<std::vector<CollisionPair>> collisions, std::function<std::shared_ptr<Promise<double>>(const std::vector<Entity>& /* entities */, const std::vector<Collision>& /* collisions */)> onTick): entities(entities), collisions(collisions), onTick(onTick) {}
57
+ explicit System(std::optional<std::vector<std::string>> entities, std::optional<std::vector<CollisionPair>> collisions, std::function<std::shared_ptr<Promise<double>>(const SystemContext& /* systemContext */)> onTick): entities(entities), collisions(collisions), onTick(onTick) {}
61
58
 
62
59
  public:
63
60
  // System is not equatable because these properties are not equatable: onTick
@@ -75,14 +72,14 @@ namespace margelo::nitro {
75
72
  return margelo::nitro::rngine::System(
76
73
  JSIConverter<std::optional<std::vector<std::string>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "entities"))),
77
74
  JSIConverter<std::optional<std::vector<margelo::nitro::rngine::CollisionPair>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "collisions"))),
78
- JSIConverter<std::function<std::shared_ptr<Promise<double>>(const std::vector<margelo::nitro::rngine::Entity>&, const std::vector<margelo::nitro::rngine::Collision>&)>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "onTick")))
75
+ JSIConverter<std::function<std::shared_ptr<Promise<double>>(const margelo::nitro::rngine::SystemContext&)>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "onTick")))
79
76
  );
80
77
  }
81
78
  static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::System& arg) {
82
79
  jsi::Object obj(runtime);
83
80
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "entities"), JSIConverter<std::optional<std::vector<std::string>>>::toJSI(runtime, arg.entities));
84
81
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "collisions"), JSIConverter<std::optional<std::vector<margelo::nitro::rngine::CollisionPair>>>::toJSI(runtime, arg.collisions));
85
- obj.setProperty(runtime, PropNameIDCache::get(runtime, "onTick"), JSIConverter<std::function<std::shared_ptr<Promise<double>>(const std::vector<margelo::nitro::rngine::Entity>&, const std::vector<margelo::nitro::rngine::Collision>&)>>::toJSI(runtime, arg.onTick));
82
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "onTick"), JSIConverter<std::function<std::shared_ptr<Promise<double>>(const margelo::nitro::rngine::SystemContext&)>>::toJSI(runtime, arg.onTick));
86
83
  return obj;
87
84
  }
88
85
  static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
@@ -95,7 +92,7 @@ namespace margelo::nitro {
95
92
  }
96
93
  if (!JSIConverter<std::optional<std::vector<std::string>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "entities")))) return false;
97
94
  if (!JSIConverter<std::optional<std::vector<margelo::nitro::rngine::CollisionPair>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "collisions")))) return false;
98
- if (!JSIConverter<std::function<std::shared_ptr<Promise<double>>(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;
95
+ if (!JSIConverter<std::function<std::shared_ptr<Promise<double>>(const margelo::nitro::rngine::SystemContext&)>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "onTick")))) return false;
99
96
  return true;
100
97
  }
101
98
  };
@@ -0,0 +1,99 @@
1
+ ///
2
+ /// SystemContext.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
+ // Forward declaration of `Screen` to properly resolve imports.
32
+ namespace margelo::nitro::rngine { struct Screen; }
33
+ // Forward declaration of `Entity` to properly resolve imports.
34
+ namespace margelo::nitro::rngine { struct Entity; }
35
+ // Forward declaration of `Collision` to properly resolve imports.
36
+ namespace margelo::nitro::rngine { struct Collision; }
37
+
38
+ #include "Screen.hpp"
39
+ #include "Entity.hpp"
40
+ #include <vector>
41
+ #include "Collision.hpp"
42
+
43
+ namespace margelo::nitro::rngine {
44
+
45
+ /**
46
+ * A struct which can be represented as a JavaScript object (SystemContext).
47
+ */
48
+ struct SystemContext final {
49
+ public:
50
+ Screen screen SWIFT_PRIVATE;
51
+ std::vector<Entity> entities SWIFT_PRIVATE;
52
+ std::vector<Collision> collisions SWIFT_PRIVATE;
53
+
54
+ public:
55
+ SystemContext() = default;
56
+ explicit SystemContext(Screen screen, std::vector<Entity> entities, std::vector<Collision> collisions): screen(screen), entities(entities), collisions(collisions) {}
57
+
58
+ public:
59
+ friend bool operator==(const SystemContext& lhs, const SystemContext& rhs) = default;
60
+ };
61
+
62
+ } // namespace margelo::nitro::rngine
63
+
64
+ namespace margelo::nitro {
65
+
66
+ // C++ SystemContext <> JS SystemContext (object)
67
+ template <>
68
+ struct JSIConverter<margelo::nitro::rngine::SystemContext> final {
69
+ static inline margelo::nitro::rngine::SystemContext fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
70
+ jsi::Object obj = arg.asObject(runtime);
71
+ return margelo::nitro::rngine::SystemContext(
72
+ JSIConverter<margelo::nitro::rngine::Screen>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "screen"))),
73
+ JSIConverter<std::vector<margelo::nitro::rngine::Entity>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "entities"))),
74
+ JSIConverter<std::vector<margelo::nitro::rngine::Collision>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "collisions")))
75
+ );
76
+ }
77
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rngine::SystemContext& arg) {
78
+ jsi::Object obj(runtime);
79
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "screen"), JSIConverter<margelo::nitro::rngine::Screen>::toJSI(runtime, arg.screen));
80
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "entities"), JSIConverter<std::vector<margelo::nitro::rngine::Entity>>::toJSI(runtime, arg.entities));
81
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "collisions"), JSIConverter<std::vector<margelo::nitro::rngine::Collision>>::toJSI(runtime, arg.collisions));
82
+ return obj;
83
+ }
84
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
85
+ if (!value.isObject()) {
86
+ return false;
87
+ }
88
+ jsi::Object obj = value.getObject(runtime);
89
+ if (!nitro::isPlainObject(runtime, obj)) {
90
+ return false;
91
+ }
92
+ if (!JSIConverter<margelo::nitro::rngine::Screen>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "screen")))) return false;
93
+ if (!JSIConverter<std::vector<margelo::nitro::rngine::Entity>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "entities")))) return false;
94
+ if (!JSIConverter<std::vector<margelo::nitro::rngine::Collision>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "collisions")))) return false;
95
+ return true;
96
+ }
97
+ };
98
+
99
+ } // namespace margelo::nitro
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rngine",
3
- "version": "0.8.2",
3
+ "version": "0.9.0",
4
4
  "description": "React Native 2D game engine powered by Nitro Modules",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -1,8 +1,10 @@
1
1
  #include "GameLoop.hpp"
2
+ #include "AssetUtils.hpp"
2
3
  #include "Collision.hpp"
3
4
  #include "CollisionUtils.hpp"
4
5
  #include "Entity.hpp"
5
6
  #include "GameRenderer.hpp"
7
+ #include "SystemContext.hpp"
6
8
  #include <android/log.h>
7
9
  #include <chrono>
8
10
  #include <cinttypes>
@@ -105,14 +107,15 @@ void GameLoop::runGameLoop() {
105
107
  void GameLoop::runSystems() {
106
108
  for (size_t systemIndex = 0; systemIndex < _systems.size(); ++systemIndex) {
107
109
  auto &system = _systems[systemIndex];
108
- std::vector<Entity> entities;
109
- std::vector<Collision> collisions;
110
+ SystemContext systemContext;
111
+
112
+ systemContext.screen = _screen;
110
113
 
111
114
  if (system.entities.has_value()) {
112
115
  for (const auto &id : system.entities.value()) {
113
116
  auto resolvedEntitiesInternal = resolveEntitiesInternal(id);
114
117
  for (auto *entity : resolvedEntitiesInternal)
115
- entities.push_back(*entity);
118
+ systemContext.entities.push_back(*entity);
116
119
  }
117
120
  }
118
121
 
@@ -124,7 +127,7 @@ void GameLoop::runSystems() {
124
127
  bool matchesReverse =
125
128
  entityIdMatches(c.a, pair.b) && entityIdMatches(c.b, pair.a);
126
129
  if (matchesForward || matchesReverse) {
127
- collisions.push_back(c);
130
+ systemContext.collisions.push_back(c);
128
131
  }
129
132
  }
130
133
  }
@@ -133,10 +136,10 @@ void GameLoop::runSystems() {
133
136
  __android_log_print(
134
137
  ANDROID_LOG_DEBUG, "GameLoop",
135
138
  "System Index: %zu, Entities: %zu, Collisions: %zu, Calling onTick",
136
- systemIndex, entities.size(), collisions.size());
139
+ systemIndex, systemContext.entities.size(),
140
+ systemContext.collisions.size());
137
141
 
138
- std::shared_ptr<Promise<double>> promise =
139
- system.onTick(entities, collisions);
142
+ std::shared_ptr<Promise<double>> promise = system.onTick(systemContext);
140
143
  std::future<double> future = promise->await();
141
144
  double duration = future.get();
142
145
 
@@ -179,19 +182,9 @@ void GameLoop::updateStats(double deltaTime) {
179
182
 
180
183
  void GameLoop::updateScreen(double deltaTime) {
181
184
  std::lock_guard<std::mutex> lock(_mutex);
182
- if (_screen.asset.has_value() && _screen.asset.value() < 0) {
183
- auto &lottieCache = GameRenderer::getInstance().getLottieCacheInternal();
184
- auto it = lottieCache.find(_screen.asset.value());
185
- if (it != lottieCache.end() && it->second) {
186
- if (_screen.speed.has_value() && _screen.speed.value() > 0) {
187
- _screen.progress = fmod(_screen.progress.value_or(0.0) +
188
- (deltaTime * _screen.speed.value()) /
189
- it->second->duration(),
190
- 1.0);
191
- }
192
- }
193
- } else if (_screen.progress.has_value()) {
194
- _screen.progress.reset();
185
+ if (_screen.asset.has_value()) {
186
+ AssetUtils::updateProgress(_screen.progress, _screen.speed,
187
+ _screen.asset.value(), deltaTime);
195
188
  }
196
189
  }
197
190
 
@@ -224,19 +217,9 @@ void GameLoop::updateEntities(double deltaTime) {
224
217
  entity.py += entity.vy.value() * deltaTime;
225
218
  }
226
219
 
227
- if (entity.asset.has_value() && entity.asset.value() < 0) {
228
- auto &lottieCache = GameRenderer::getInstance().getLottieCacheInternal();
229
- auto it = lottieCache.find(entity.asset.value());
230
- if (it != lottieCache.end() && it->second) {
231
- if (entity.speed.has_value() && entity.speed.value() > 0) {
232
- entity.progress = fmod(entity.progress.value_or(0.0) +
233
- (deltaTime * entity.speed.value()) /
234
- it->second->duration(),
235
- 1.0);
236
- }
237
- }
238
- } else if (entity.progress.has_value()) {
239
- entity.progress.reset();
220
+ if (entity.asset.has_value()) {
221
+ AssetUtils::updateProgress(entity.progress, entity.speed,
222
+ entity.asset.value(), deltaTime);
240
223
  }
241
224
  }
242
225
  }
@@ -2,6 +2,7 @@
2
2
  #include "EntityUpdate.hpp"
3
3
  #include "GameLoop.hpp"
4
4
  #include "GameRenderer.hpp"
5
+ #include "include/core/SkImage.h"
5
6
  #include "include/core/SkStream.h"
6
7
  #include <android/log.h>
7
8
  #include <fbjni/fbjni.h>
@@ -105,80 +106,78 @@ void GameMethods::despawn(const std::string &id) {
105
106
  }
106
107
  }
107
108
 
108
- void GameMethods::update(const std::vector<EntityUpdate> &updates) {
109
+ static void patch(const auto &field, auto &target) {
110
+ if (field.has_value()) {
111
+ target = field.value();
112
+ }
113
+ }
114
+
115
+ void GameMethods::updateEntities(
116
+ const std::vector<EntityUpdate> &entityUpdates) {
109
117
  auto &instance = GameLoop::getInstance();
110
118
  std::lock_guard<std::mutex> lock(instance.getMutexInternal());
111
- for (const auto &update : updates) {
119
+ for (const auto &entityUpdate : entityUpdates) {
112
120
  auto resolvedEntitiesInternals =
113
- instance.resolveEntitiesInternal(update.id);
121
+ instance.resolveEntitiesInternal(entityUpdate.id);
114
122
  if (resolvedEntitiesInternals.empty()) {
115
123
  __android_log_print(ANDROID_LOG_WARN, "GameMethods",
116
- "update: no entity found for id=%s",
117
- update.id.c_str());
124
+ "entityUpdate: no entity found for id=%s",
125
+ entityUpdate.id.c_str());
118
126
  continue;
119
127
  }
120
128
 
121
129
  for (auto *entity : resolvedEntitiesInternals) {
122
- if (update.px.has_value()) {
123
- entity->px = update.px.value();
124
- }
125
- if (update.py.has_value()) {
126
- entity->py = update.py.value();
127
- }
128
- if (update.shape.has_value()) {
129
- entity->shape = update.shape.value();
130
- }
131
- if (update.isSensor.has_value()) {
132
- entity->isSensor = update.isSensor.value();
133
- }
134
- if (update.asset.has_value()) {
135
- entity->asset = update.asset.value();
136
- }
137
- if (update.progress.has_value()) {
138
- entity->progress = update.progress.value();
139
- }
140
- if (update.speed.has_value()) {
141
- entity->speed = update.speed.value();
142
- }
143
- if (update.color.has_value()) {
144
- entity->color = update.color.value();
145
- }
146
- if (update.flipH.has_value()) {
147
- entity->flipH = update.flipH.value();
148
- }
149
- if (update.flipV.has_value()) {
150
- entity->flipV = update.flipV.value();
151
- }
152
- if (update.vx.has_value()) {
153
- entity->vx = update.vx.value();
154
- }
155
- if (update.vy.has_value()) {
156
- entity->vy = update.vy.value();
157
- }
158
- if (update.ax.has_value()) {
159
- entity->ax = update.ax.value();
160
- }
161
- if (update.ay.has_value()) {
162
- entity->ay = update.ay.value();
163
- }
164
- if (update.mass.has_value()) {
165
- entity->mass = update.mass.value();
166
- }
130
+ patch(entityUpdate.px, entity->px);
131
+ patch(entityUpdate.py, entity->py);
132
+ patch(entityUpdate.shape, entity->shape);
133
+ patch(entityUpdate.isSensor, entity->isSensor);
134
+ patch(entityUpdate.asset, entity->asset);
135
+ patch(entityUpdate.progress, entity->progress);
136
+ patch(entityUpdate.speed, entity->speed);
137
+ patch(entityUpdate.color, entity->color);
138
+ patch(entityUpdate.flipH, entity->flipH);
139
+ patch(entityUpdate.flipV, entity->flipV);
140
+ patch(entityUpdate.vx, entity->vx);
141
+ patch(entityUpdate.vy, entity->vy);
142
+ patch(entityUpdate.ax, entity->ax);
143
+ patch(entityUpdate.ay, entity->ay);
144
+ patch(entityUpdate.mass, entity->mass);
167
145
  }
168
146
 
169
147
  __android_log_print(ANDROID_LOG_INFO, "GameMethods",
170
- "update: patched %zu entities for id=%s",
171
- resolvedEntitiesInternals.size(), update.id.c_str());
148
+ "entityUpdateEntities: patched %zu entities for id=%s",
149
+ resolvedEntitiesInternals.size(),
150
+ entityUpdate.id.c_str());
172
151
  }
173
152
  }
174
153
 
154
+ void GameMethods::updateScreen(const ScreenUpdate &screenUpdate) {
155
+ auto &instance = GameLoop::getInstance();
156
+ std::lock_guard<std::mutex> lock(instance.getMutexInternal());
157
+ auto &screen = instance.getScreenInternal();
158
+
159
+ patch(screenUpdate.px, screen.px);
160
+ patch(screenUpdate.py, screen.py);
161
+ patch(screenUpdate.width, screen.width);
162
+ patch(screenUpdate.height, screen.height);
163
+ patch(screenUpdate.asset, screen.asset);
164
+ patch(screenUpdate.progress, screen.progress);
165
+ patch(screenUpdate.speed, screen.speed);
166
+ patch(screenUpdate.color, screen.color);
167
+ patch(screenUpdate.flipH, screen.flipH);
168
+ patch(screenUpdate.flipV, screen.flipV);
169
+
170
+ __android_log_print(ANDROID_LOG_INFO, "GameMethods",
171
+ "updateScreen: patched screen");
172
+ }
173
+
175
174
  bool GameMethods::isAssetLoaded(double id) {
176
175
  auto &gameRenderer = GameRenderer::getInstance();
177
176
 
178
177
  if (id > 0) {
179
- auto &svgCache = gameRenderer.getSvgCacheInternal();
180
- auto it = svgCache.find(id);
181
- return it != svgCache.end();
178
+ auto &imageCache = gameRenderer.getImageCacheInternal();
179
+ auto it = imageCache.find(id);
180
+ return it != imageCache.end();
182
181
  }
183
182
 
184
183
  if (id < 0) {
@@ -213,53 +212,86 @@ GameMethods::loadLottie(double id, const std::string &jsonStr) {
213
212
  });
214
213
  };
215
214
 
216
- std::shared_ptr<Promise<bool>> GameMethods::loadSvg(double id,
217
- const std::string &svgUri) {
215
+ std::shared_ptr<Promise<bool>>
216
+ GameMethods::loadImage(double id, const std::string &imageUri) {
218
217
  return Promise<bool>::async([=]() -> bool {
219
- std::string svgStr;
218
+ __android_log_print(ANDROID_LOG_DEBUG, "GameMethods",
219
+ "loadImage: start id=%.0f uri=%s", id,
220
+ imageUri.c_str());
221
+ std::string imageStr;
220
222
 
221
223
  using namespace facebook::jni;
222
224
 
223
- ThreadScope::WithClassLoader([&] {
224
- static const auto helperClass =
225
- findClassStatic("com/margelo/nitro/rngine/SvgLoaderHelper");
226
-
227
- local_ref<JArrayByte> byteArray;
228
-
229
- if (svgUri.rfind("http://", 0) == 0 || svgUri.rfind("https://", 0) == 0) {
230
- static const auto method =
231
- helperClass->getStaticMethod<JArrayByte(local_ref<JString>)>(
232
- "loadFromUrl");
233
- byteArray = method(helperClass, make_jstring(svgUri));
234
- } else {
235
- static const auto method =
236
- helperClass->getStaticMethod<JArrayByte(local_ref<JString>)>(
237
- "loadFromResource");
238
- byteArray = method(helperClass, make_jstring(svgUri));
239
- }
240
-
241
- if (!byteArray) {
242
- throw std::runtime_error("Failed to load SVG bytes for: " + svgUri);
243
- }
244
-
245
- size_t len = byteArray->size();
246
- svgStr.resize(len);
247
- byteArray->getRegion(0, len, reinterpret_cast<int8_t *>(svgStr.data()));
248
- });
249
-
250
- auto stream = SkMemoryStream::MakeDirect(svgStr.data(), svgStr.size());
251
- auto svgDom = SkSVGDOM::MakeFromStream(*stream);
252
-
253
- if (!svgDom) {
225
+ try {
226
+ ThreadScope::WithClassLoader([&] {
227
+ static const auto helperClass =
228
+ findClassStatic("com/margelo/nitro/rngine/ImageLoaderHelper");
229
+
230
+ local_ref<JArrayByte> byteArray;
231
+
232
+ if (imageUri.rfind("http://", 0) == 0 ||
233
+ imageUri.rfind("https://", 0) == 0) {
234
+ static const auto method =
235
+ helperClass->getStaticMethod<JArrayByte(local_ref<JString>)>(
236
+ "loadFromUrl");
237
+ byteArray = method(helperClass, make_jstring(imageUri));
238
+ } else {
239
+ static const auto method =
240
+ helperClass->getStaticMethod<JArrayByte(local_ref<JString>)>(
241
+ "loadFromResource");
242
+ byteArray = method(helperClass, make_jstring(imageUri));
243
+ }
244
+
245
+ if (!byteArray) {
246
+ throw std::runtime_error("Failed to load image bytes for: " +
247
+ imageUri);
248
+ }
249
+
250
+ size_t len = byteArray->size();
251
+ imageStr.resize(len);
252
+ byteArray->getRegion(0, len,
253
+ reinterpret_cast<int8_t *>(imageStr.data()));
254
+ });
255
+ } catch (const std::exception &e) {
256
+ __android_log_print(ANDROID_LOG_ERROR, "GameMethods",
257
+ "loadImage: JNI fetch failed id=%.0f: %s", id,
258
+ e.what());
254
259
  return false;
255
260
  }
256
261
 
262
+ __android_log_print(ANDROID_LOG_DEBUG, "GameMethods",
263
+ "loadImage: fetched %zu bytes id=%.0f", imageStr.size(),
264
+ id);
265
+
257
266
  auto &gameRenderer = GameRenderer::getInstance();
258
- auto &svgCache = gameRenderer.getSvgCacheInternal();
267
+ auto &imageCache = gameRenderer.getImageCacheInternal();
259
268
 
260
- svgCache[id] = std::move(svgDom);
269
+ auto stream = SkMemoryStream::MakeDirect(imageStr.data(), imageStr.size());
270
+ auto svgDom = SkSVGDOM::MakeFromStream(*stream);
261
271
 
262
- return true;
272
+ if (svgDom) {
273
+ __android_log_print(ANDROID_LOG_DEBUG, "GameMethods",
274
+ "loadImage: parsed as SVG id=%.0f", id);
275
+ imageCache[id] = std::move(svgDom);
276
+ return true;
277
+ }
278
+
279
+ auto data = SkData::MakeWithCopy(imageStr.data(), imageStr.size());
280
+ auto raster = SkImages::DeferredFromEncodedData(std::move(data));
281
+
282
+ if (raster) {
283
+ __android_log_print(ANDROID_LOG_DEBUG, "GameMethods",
284
+ "loadImage: parsed as raster id=%.0f", id);
285
+ imageCache[id] = std::move(raster);
286
+ return true;
287
+ }
288
+
289
+ __android_log_print(ANDROID_LOG_ERROR, "GameMethods",
290
+ "loadImage: both SVG parse and raster decode failed "
291
+ "id=%.0f",
292
+ id);
293
+
294
+ return false;
263
295
  });
264
296
  };
265
297
  } // namespace margelo::nitro::rngine