Checkpoint 2: integrate native Editor, MCP, gameplay builds and standalone export

This commit is contained in:
Emil
2026-09-18 03:40:15 +03:00
parent 5c6b24d34d
commit 999686a896
125 changed files with 16086 additions and 1714 deletions
+43
View File
@@ -0,0 +1,43 @@
#include "Gameplay.hpp"
namespace faset::gameplay {
void registerGameplay(runtime::Runtime& world) {
runtime::Behavior motion;
motion.fixedUpdate = [](runtime::Runtime& game, runtime::EntityHandle self, double delta) {
auto pose = game.transform(self);
pose.position[0] += game.fields(self, "tutorial.fixed_move").value("speed", 2.0f) *
static_cast<float>(delta);
game.setTransform(self, pose);
};
world.registerBehavior("tutorial.fixed_move", std::move(motion));
runtime::Behavior follow;
follow.lateUpdate = [](runtime::Runtime& game, runtime::EntityHandle self, double) {
const auto settings = game.fields(self, "tutorial.follow");
const auto target = game.find(settings.value("target", std::string{}));
if (!game.valid(target))
return; // Target may be absent or destroyed.
const auto targetPose = game.presentation(target); // Already interpolated.
const auto offset = settings.at("offset").get<runtime::Vec3>();
auto cameraPose = game.presentation(self);
for (int axis = 0; axis < 3; ++axis)
cameraPose.position[axis] = targetPose.position[axis] + offset[axis];
game.setPresentation(self, cameraPose); // Does not write the simulation pose.
};
world.registerBehavior("tutorial.follow", std::move(follow));
}
nlohmann::json schema() {
return nlohmann::json::array(
{{{"id", "tutorial.fixed_move"},
{"version", 1},
{"name", "Fixed movement"},
{"fields", {{"speed", {{"id", "speed"}, {"type", "number"}, {"default", 2.0}}}}}},
{{"id", "tutorial.follow"},
{"version", 1},
{"name", "Follow presentation"},
{"fields",
{{"target", {{"id", "target"}, {"type", "entity_ref"}, {"default", "actor"}}},
{"offset", {{"id", "offset"}, {"type", "vec3"}, {"default", {0, 0, 10}}}}}}}});
}
} // namespace faset::gameplay
@@ -0,0 +1,7 @@
#pragma once
#include <faset/runtime/Runtime.hpp>
namespace faset::gameplay {
void registerGameplay(runtime::Runtime& world);
nlohmann::json schema();
} // namespace faset::gameplay
+126
View File
@@ -0,0 +1,126 @@
{
"format": "faset.scene",
"version": 1,
"id": "tutorial-following",
"name": "Following tutorial",
"dimension": 2,
"simulation": {
"fixed_delta": 0.016666666666666666,
"max_catch_up_ticks": 4,
"physics_substeps": 4,
"gravity": [
0,
-9.81,
0
]
},
"entities": [
{
"id": "actor",
"name": "actor",
"parent": null,
"components": [
{
"id": "actor-faset.transform",
"type": "faset.transform",
"version": 1,
"fields": {
"position": [
0,
0,
0
],
"rotation": [
0,
0,
0
],
"scale": [
1,
1,
1
]
}
},
{
"id": "actor-faset.sprite",
"type": "faset.sprite",
"version": 1,
"fields": {
"color": [
0.2,
0.7,
0.9,
1
],
"size": [
1,
1
]
}
},
{
"id": "actor-tutorial.fixed_move",
"type": "tutorial.fixed_move",
"version": 1,
"fields": {
"speed": 2
}
}
]
},
{
"id": "camera",
"name": "camera",
"parent": null,
"components": [
{
"id": "camera-faset.transform",
"type": "faset.transform",
"version": 1,
"fields": {
"position": [
0,
0,
10
],
"rotation": [
0,
0,
0
],
"scale": [
1,
1,
1
]
}
},
{
"id": "camera-faset.camera",
"type": "faset.camera",
"version": 1,
"fields": {
"fov": 60,
"near": 0.1,
"far": 100
}
},
{
"id": "camera-tutorial.follow",
"type": "tutorial.follow",
"version": 1,
"fields": {
"target": "actor",
"offset": [
0,
0,
10
]
}
}
]
}
],
"instances": []
}