rngine 0.8.3 → 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.
- package/README.md +28 -21
- package/android/CMakeLists.txt +5 -2
- package/lib/module/GameMethods.js +20 -7
- package/lib/module/GameMethods.js.map +1 -1
- package/lib/module/GameMethods.nitro.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/GameMethods.d.ts +11 -4
- package/lib/typescript/src/GameMethods.d.ts.map +1 -1
- package/lib/typescript/src/GameMethods.nitro.d.ts +8 -2
- package/lib/typescript/src/GameMethods.nitro.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/nativeTypes.d.ts +12 -2
- package/lib/typescript/src/nativeTypes.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +2 -2
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/nitrogen/generated/shared/c++/HybridGameMethodsSpec.cpp +2 -1
- package/nitrogen/generated/shared/c++/HybridGameMethodsSpec.hpp +5 -1
- package/nitrogen/generated/shared/c++/Screen.hpp +9 -1
- package/nitrogen/generated/shared/c++/ScreenUpdate.hpp +120 -0
- package/nitrogen/generated/shared/c++/System.hpp +8 -11
- package/nitrogen/generated/shared/c++/SystemContext.hpp +99 -0
- package/package.json +1 -1
- package/shared/GameLoop.cpp +16 -33
- package/shared/GameMethods.cpp +50 -52
- package/shared/GameMethods.hpp +3 -1
- package/shared/GameRenderer.cpp +26 -131
- package/shared/GameRenderer.hpp +2 -2
- package/shared/utils/AssetUtils.cpp +92 -0
- package/shared/utils/AssetUtils.hpp +11 -0
- package/shared/{CollisionUtils.cpp → utils/CollisionUtils.cpp} +9 -8
- package/shared/utils/CollisionUtils.hpp +10 -0
- package/src/GameMethods.nitro.ts +11 -1
- package/src/GameMethods.ts +20 -8
- package/src/index.tsx +1 -0
- package/src/nativeTypes.ts +13 -2
- package/src/types.ts +2 -2
- package/shared/CollisionUtils.hpp +0 -21
- /package/shared/{ColorUtils.cpp → utils/ColorUtils.cpp} +0 -0
- /package/shared/{ColorUtils.hpp → utils/ColorUtils.hpp} +0 -0
|
@@ -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 `
|
|
34
|
-
namespace margelo::nitro::rngine { struct
|
|
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 "
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
package/shared/GameLoop.cpp
CHANGED
|
@@ -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
|
-
|
|
109
|
-
|
|
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(),
|
|
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()
|
|
183
|
-
|
|
184
|
-
|
|
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()
|
|
228
|
-
|
|
229
|
-
|
|
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
|
}
|
package/shared/GameMethods.cpp
CHANGED
|
@@ -106,73 +106,71 @@ void GameMethods::despawn(const std::string &id) {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
void
|
|
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) {
|
|
110
117
|
auto &instance = GameLoop::getInstance();
|
|
111
118
|
std::lock_guard<std::mutex> lock(instance.getMutexInternal());
|
|
112
|
-
for (const auto &
|
|
119
|
+
for (const auto &entityUpdate : entityUpdates) {
|
|
113
120
|
auto resolvedEntitiesInternals =
|
|
114
|
-
instance.resolveEntitiesInternal(
|
|
121
|
+
instance.resolveEntitiesInternal(entityUpdate.id);
|
|
115
122
|
if (resolvedEntitiesInternals.empty()) {
|
|
116
123
|
__android_log_print(ANDROID_LOG_WARN, "GameMethods",
|
|
117
|
-
"
|
|
118
|
-
|
|
124
|
+
"entityUpdate: no entity found for id=%s",
|
|
125
|
+
entityUpdate.id.c_str());
|
|
119
126
|
continue;
|
|
120
127
|
}
|
|
121
128
|
|
|
122
129
|
for (auto *entity : resolvedEntitiesInternals) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (update.progress.has_value()) {
|
|
139
|
-
entity->progress = update.progress.value();
|
|
140
|
-
}
|
|
141
|
-
if (update.speed.has_value()) {
|
|
142
|
-
entity->speed = update.speed.value();
|
|
143
|
-
}
|
|
144
|
-
if (update.color.has_value()) {
|
|
145
|
-
entity->color = update.color.value();
|
|
146
|
-
}
|
|
147
|
-
if (update.flipH.has_value()) {
|
|
148
|
-
entity->flipH = update.flipH.value();
|
|
149
|
-
}
|
|
150
|
-
if (update.flipV.has_value()) {
|
|
151
|
-
entity->flipV = update.flipV.value();
|
|
152
|
-
}
|
|
153
|
-
if (update.vx.has_value()) {
|
|
154
|
-
entity->vx = update.vx.value();
|
|
155
|
-
}
|
|
156
|
-
if (update.vy.has_value()) {
|
|
157
|
-
entity->vy = update.vy.value();
|
|
158
|
-
}
|
|
159
|
-
if (update.ax.has_value()) {
|
|
160
|
-
entity->ax = update.ax.value();
|
|
161
|
-
}
|
|
162
|
-
if (update.ay.has_value()) {
|
|
163
|
-
entity->ay = update.ay.value();
|
|
164
|
-
}
|
|
165
|
-
if (update.mass.has_value()) {
|
|
166
|
-
entity->mass = update.mass.value();
|
|
167
|
-
}
|
|
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);
|
|
168
145
|
}
|
|
169
146
|
|
|
170
147
|
__android_log_print(ANDROID_LOG_INFO, "GameMethods",
|
|
171
|
-
"
|
|
172
|
-
resolvedEntitiesInternals.size(),
|
|
148
|
+
"entityUpdateEntities: patched %zu entities for id=%s",
|
|
149
|
+
resolvedEntitiesInternals.size(),
|
|
150
|
+
entityUpdate.id.c_str());
|
|
173
151
|
}
|
|
174
152
|
}
|
|
175
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
|
+
|
|
176
174
|
bool GameMethods::isAssetLoaded(double id) {
|
|
177
175
|
auto &gameRenderer = GameRenderer::getInstance();
|
|
178
176
|
|
package/shared/GameMethods.hpp
CHANGED
|
@@ -24,7 +24,9 @@ public:
|
|
|
24
24
|
|
|
25
25
|
void despawn(const std::string &id) override;
|
|
26
26
|
|
|
27
|
-
void
|
|
27
|
+
void updateEntities(const std::vector<EntityUpdate> &entityUpdates) override;
|
|
28
|
+
|
|
29
|
+
void updateScreen(const ScreenUpdate &screenUpdate) override;
|
|
28
30
|
|
|
29
31
|
bool isAssetLoaded(double id) override;
|
|
30
32
|
|
package/shared/GameRenderer.cpp
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#include "GameRenderer.hpp"
|
|
2
|
+
#include "AssetUtils.hpp"
|
|
2
3
|
#include "ColorUtils.hpp"
|
|
3
4
|
#include "Rect.hpp"
|
|
4
5
|
|
|
@@ -20,7 +21,6 @@
|
|
|
20
21
|
|
|
21
22
|
#include "include/gpu/ganesh/gl/GrGLDirectContext.h"
|
|
22
23
|
#include "include/gpu/ganesh/gl/GrGLInterface.h"
|
|
23
|
-
#include "modules/svg/include/SkSVGDOM.h"
|
|
24
24
|
|
|
25
25
|
#include <EGL/egl.h>
|
|
26
26
|
#include <GLES3/gl3.h>
|
|
@@ -135,15 +135,20 @@ void GameRenderer::render(const Screen &screen,
|
|
|
135
135
|
|
|
136
136
|
float scale = std::min(scaleX, scaleY);
|
|
137
137
|
|
|
138
|
-
float offsetX =
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
float offsetX =
|
|
139
|
+
static_cast<float>(_width) * 0.5f - static_cast<float>(screen.px) * scale;
|
|
140
|
+
float offsetY = static_cast<float>(_height) * 0.5f -
|
|
141
|
+
static_cast<float>(screen.py) * scale;
|
|
141
142
|
|
|
142
143
|
canvas->save();
|
|
143
144
|
canvas->translate(offsetX, offsetY);
|
|
144
145
|
canvas->scale(scale, scale);
|
|
145
146
|
|
|
146
|
-
SkRect gameBounds =
|
|
147
|
+
SkRect gameBounds =
|
|
148
|
+
SkRect::MakeXYWH(static_cast<float>(screen.px) - virtualWidth * 0.5f,
|
|
149
|
+
static_cast<float>(screen.py) - virtualHeight * 0.5f,
|
|
150
|
+
virtualWidth, virtualHeight);
|
|
151
|
+
|
|
147
152
|
canvas->clipRect(gameBounds);
|
|
148
153
|
|
|
149
154
|
if (screen.color.has_value()) {
|
|
@@ -151,73 +156,16 @@ void GameRenderer::render(const Screen &screen,
|
|
|
151
156
|
}
|
|
152
157
|
|
|
153
158
|
if (screen.asset.has_value() && screen.asset.value() != 0) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
using T = std::decay_t<decltype(image)>;
|
|
161
|
-
if constexpr (std::is_same_v<T, sk_sp<SkSVGDOM>>) {
|
|
162
|
-
SkSize intrinsicSize = image->containerSize();
|
|
163
|
-
|
|
164
|
-
if (intrinsicSize.isEmpty()) {
|
|
165
|
-
image->setContainerSize(
|
|
166
|
-
SkSize::Make(virtualWidth, virtualHeight));
|
|
167
|
-
intrinsicSize = SkSize::Make(virtualWidth, virtualHeight);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
float scaleX = virtualWidth / intrinsicSize.width();
|
|
171
|
-
float scaleY = virtualHeight / intrinsicSize.height();
|
|
172
|
-
|
|
173
|
-
canvas->save();
|
|
174
|
-
if (screen.flipH.has_value() || screen.flipV.has_value()) {
|
|
175
|
-
canvas->translate(virtualWidth / 2.f, virtualHeight / 2.f);
|
|
176
|
-
canvas->scale(screen.flipH.value_or(false) ? -1.f : 1.f,
|
|
177
|
-
screen.flipV.value_or(false) ? -1.f : 1.f);
|
|
178
|
-
canvas->translate(-virtualWidth / 2.f, -virtualHeight / 2.f);
|
|
179
|
-
}
|
|
180
|
-
canvas->scale(scaleX, scaleY);
|
|
181
|
-
image->render(canvas);
|
|
182
|
-
canvas->restore();
|
|
183
|
-
} else {
|
|
184
|
-
float intrinsicW = static_cast<float>(image->width());
|
|
185
|
-
float intrinsicH = static_cast<float>(image->height());
|
|
186
|
-
if (intrinsicW <= 0.f || intrinsicH <= 0.f)
|
|
187
|
-
return;
|
|
188
|
-
|
|
189
|
-
float scaleX = virtualWidth / intrinsicW;
|
|
190
|
-
float scaleY = virtualHeight / intrinsicH;
|
|
191
|
-
|
|
192
|
-
canvas->save();
|
|
193
|
-
if (screen.flipH.has_value() || screen.flipV.has_value()) {
|
|
194
|
-
canvas->translate(virtualWidth / 2.f, virtualHeight / 2.f);
|
|
195
|
-
canvas->scale(screen.flipH.value_or(false) ? -1.f : 1.f,
|
|
196
|
-
screen.flipV.value_or(false) ? -1.f : 1.f);
|
|
197
|
-
canvas->translate(-virtualWidth / 2.f, -virtualHeight / 2.f);
|
|
198
|
-
}
|
|
199
|
-
canvas->scale(scaleX, scaleY);
|
|
200
|
-
|
|
201
|
-
SkSamplingOptions sampling(SkFilterMode::kLinear,
|
|
202
|
-
SkMipmapMode::kLinear);
|
|
203
|
-
canvas->drawImage(image, 0.f, 0.f, sampling);
|
|
204
|
-
canvas->restore();
|
|
205
|
-
}
|
|
206
|
-
},
|
|
207
|
-
imageIt->second);
|
|
208
|
-
} else {
|
|
209
|
-
auto lottieIt = _lottieCache.find(assetId);
|
|
210
|
-
if (lottieIt != _lottieCache.end() && lottieIt->second) {
|
|
211
|
-
auto &lottie = lottieIt->second;
|
|
212
|
-
lottie->seek(screen.progress.value_or(0.0));
|
|
213
|
-
SkRect dstBounds = SkRect::MakeWH(virtualWidth, virtualHeight);
|
|
214
|
-
lottie->render(canvas, &dstBounds);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
159
|
+
SkAutoCanvasRestore restore(canvas, true);
|
|
160
|
+
canvas->translate(gameBounds.left(), gameBounds.top());
|
|
161
|
+
AssetUtils::drawAsset(canvas, screen.asset.value(), virtualWidth,
|
|
162
|
+
virtualHeight, screen.flipH.value_or(false),
|
|
163
|
+
screen.flipV.value_or(false),
|
|
164
|
+
screen.progress.value_or(0.0));
|
|
217
165
|
}
|
|
218
166
|
|
|
219
167
|
for (const auto &[id, entity] : entities) {
|
|
220
|
-
if (!isEntityVisible(entity,
|
|
168
|
+
if (!isEntityVisible(entity, gameBounds)) {
|
|
221
169
|
continue;
|
|
222
170
|
}
|
|
223
171
|
|
|
@@ -250,8 +198,6 @@ void GameRenderer::render(const Screen &screen,
|
|
|
250
198
|
}
|
|
251
199
|
|
|
252
200
|
if ((entity.asset.has_value() && entity.asset.value() != 0)) {
|
|
253
|
-
double assetId = entity.asset.value();
|
|
254
|
-
|
|
255
201
|
float width = 0.f, height = 0.f;
|
|
256
202
|
std::visit(
|
|
257
203
|
[&](const auto &shape) {
|
|
@@ -270,59 +216,10 @@ void GameRenderer::render(const Screen &screen,
|
|
|
270
216
|
SkAutoCanvasRestore autoRestore(canvas, true);
|
|
271
217
|
canvas->translate(px - width / 2, py - height / 2);
|
|
272
218
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
canvas->translate(-width / 2.f, -height / 2.f);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
auto imageIt = _imageCache.find(assetId);
|
|
281
|
-
if (imageIt != _imageCache.end()) {
|
|
282
|
-
std::visit(
|
|
283
|
-
[&](const auto image) {
|
|
284
|
-
using T = std::decay_t<decltype(image)>;
|
|
285
|
-
if constexpr (std::is_same_v<T, sk_sp<SkSVGDOM>>) {
|
|
286
|
-
SkSize intrinsicSize = image->containerSize();
|
|
287
|
-
if (intrinsicSize.isEmpty()) {
|
|
288
|
-
image->setContainerSize(SkSize::Make(width, height));
|
|
289
|
-
intrinsicSize = SkSize::Make(width, height);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
float scaleX = width / intrinsicSize.width();
|
|
293
|
-
float scaleY = height / intrinsicSize.height();
|
|
294
|
-
|
|
295
|
-
canvas->save();
|
|
296
|
-
canvas->scale(scaleX, scaleY);
|
|
297
|
-
image->render(canvas);
|
|
298
|
-
canvas->restore();
|
|
299
|
-
} else {
|
|
300
|
-
float intrinsicW = static_cast<float>(image->width());
|
|
301
|
-
float intrinsicH = static_cast<float>(image->height());
|
|
302
|
-
if (intrinsicW <= 0.f || intrinsicH <= 0.f)
|
|
303
|
-
return;
|
|
304
|
-
|
|
305
|
-
float scaleX = width / intrinsicW;
|
|
306
|
-
float scaleY = height / intrinsicH;
|
|
307
|
-
|
|
308
|
-
canvas->save();
|
|
309
|
-
canvas->scale(scaleX, scaleY);
|
|
310
|
-
SkSamplingOptions sampling(SkFilterMode::kLinear,
|
|
311
|
-
SkMipmapMode::kLinear);
|
|
312
|
-
canvas->drawImage(image, 0.f, 0.f, sampling);
|
|
313
|
-
canvas->restore();
|
|
314
|
-
}
|
|
315
|
-
},
|
|
316
|
-
imageIt->second);
|
|
317
|
-
} else {
|
|
318
|
-
auto lottieIt = _lottieCache.find(assetId);
|
|
319
|
-
if (lottieIt != _lottieCache.end() && lottieIt->second) {
|
|
320
|
-
auto &lottie = lottieIt->second;
|
|
321
|
-
lottie->seek(entity.progress.value_or(0.0));
|
|
322
|
-
SkRect dstBounds = SkRect::MakeWH(width, height);
|
|
323
|
-
lottie->render(canvas, &dstBounds);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
219
|
+
AssetUtils::drawAsset(canvas, entity.asset.value(), width, height,
|
|
220
|
+
entity.flipH.value_or(false),
|
|
221
|
+
entity.flipV.value_or(false),
|
|
222
|
+
entity.progress.value_or(0.0));
|
|
326
223
|
}
|
|
327
224
|
}
|
|
328
225
|
}
|
|
@@ -335,15 +232,13 @@ void GameRenderer::render(const Screen &screen,
|
|
|
335
232
|
__android_log_print(ANDROID_LOG_DEBUG, "GameRenderer", "render: complete");
|
|
336
233
|
}
|
|
337
234
|
|
|
338
|
-
bool GameRenderer::isEntityVisible(const Entity &entity,
|
|
339
|
-
|
|
340
|
-
float width = 0.f;
|
|
341
|
-
float height = 0.f;
|
|
235
|
+
bool GameRenderer::isEntityVisible(const Entity &entity,
|
|
236
|
+
const SkRect &viewBounds) {
|
|
237
|
+
float width = 0.f, height = 0.f;
|
|
342
238
|
|
|
343
239
|
std::visit(
|
|
344
240
|
[&](const auto &shape) {
|
|
345
241
|
using T = std::decay_t<decltype(shape)>;
|
|
346
|
-
|
|
347
242
|
if constexpr (std::is_same_v<T, Rect>) {
|
|
348
243
|
width = static_cast<float>(shape.width);
|
|
349
244
|
height = static_cast<float>(shape.height);
|
|
@@ -358,8 +253,8 @@ bool GameRenderer::isEntityVisible(const Entity &entity, float screenWidth,
|
|
|
358
253
|
float top = static_cast<float>(entity.py) - height / 2.f;
|
|
359
254
|
float bottom = static_cast<float>(entity.py) + height / 2.f;
|
|
360
255
|
|
|
361
|
-
return right >
|
|
362
|
-
top <
|
|
256
|
+
return right > viewBounds.left() && left < viewBounds.right() &&
|
|
257
|
+
bottom > viewBounds.top() && top < viewBounds.bottom();
|
|
363
258
|
}
|
|
364
259
|
|
|
365
260
|
bool GameRenderer::initializeEGL() {
|
package/shared/GameRenderer.hpp
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#include "Entity.hpp"
|
|
3
3
|
#include "Screen.hpp"
|
|
4
4
|
#include "include/core/SkImage.h"
|
|
5
|
+
#include "include/core/SkRect.h"
|
|
5
6
|
#include "include/core/SkSurface.h"
|
|
6
7
|
#include "include/gpu/ganesh/GrDirectContext.h"
|
|
7
8
|
#include "modules/skottie/include/Skottie.h"
|
|
@@ -58,8 +59,7 @@ private:
|
|
|
58
59
|
std::map<double, sk_sp<skottie::Animation>> _lottieCache;
|
|
59
60
|
std::map<double, std::variant<sk_sp<SkSVGDOM>, sk_sp<SkImage>>> _imageCache;
|
|
60
61
|
|
|
61
|
-
bool isEntityVisible(const Entity &entity,
|
|
62
|
-
float screenHeight);
|
|
62
|
+
bool isEntityVisible(const Entity &entity, const SkRect &viewBounds);
|
|
63
63
|
|
|
64
64
|
bool initializeEGL();
|
|
65
65
|
bool createEGLSurface();
|