Added more scripts

This commit is contained in:
Vladislav Khorev 2026-04-03 20:06:33 +03:00
parent 63c9d7b35b
commit 403b93e7f5
5 changed files with 47 additions and 13 deletions

View File

@ -1,4 +1,15 @@
import game_api import game_api
# Tell NPC 0 to walk to the origin (0, 0, 0) when the game starts. # Chain of waypoints for NPC 0.
game_api.npc_walk_to(0, 10.0, 0.0, 0.0) # Each on_arrived callback issues the next walk command.
def step3():
game_api.npc_walk_to(0, 0.0, 0.0, -30.0, on_arrived=step1)
def step2():
game_api.npc_walk_to(0, -2.0, 0.0, -2.0, on_arrived=step3)
def step1():
game_api.npc_walk_to(0, 2.0, 0.0, -2.0, on_arrived=step2)
step1()

View File

@ -17,8 +17,10 @@ void Character::setTexture(std::shared_ptr<Texture> tex) {
texture = tex; texture = tex;
} }
void Character::setTarget(const Eigen::Vector3f& target) { void Character::setTarget(const Eigen::Vector3f& target,
std::function<void()> onArrived) {
walkTarget = target; walkTarget = target;
onArrivedCallback = std::move(onArrived);
} }
AnimationState Character::resolveActiveState() const { AnimationState Character::resolveActiveState() const {
@ -45,6 +47,11 @@ void Character::update(int64_t deltaMs) {
currentState = AnimationState::WALK; currentState = AnimationState::WALK;
} else { } else {
currentState = AnimationState::IDLE; currentState = AnimationState::IDLE;
if (onArrivedCallback) {
auto cb = std::move(onArrivedCallback);
onArrivedCallback = nullptr;
cb();
}
} }
// Rotate toward target facing angle at constant angular speed // Rotate toward target facing angle at constant angular speed

View File

@ -2,6 +2,7 @@
#include "BoneAnimatedModel.h" #include "BoneAnimatedModel.h"
#include "render/Renderer.h" #include "render/Renderer.h"
#include "render/TextureManager.h" #include "render/TextureManager.h"
#include <functional>
#include <memory> #include <memory>
#include <map> #include <map>
#include <string> #include <string>
@ -19,7 +20,10 @@ public:
void loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile = ""); void loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile = "");
void setTexture(std::shared_ptr<Texture> texture); void setTexture(std::shared_ptr<Texture> texture);
void update(int64_t deltaMs); void update(int64_t deltaMs);
void setTarget(const Eigen::Vector3f& target); // onArrived is called once when the character reaches this target.
// From Python you can chain further commands (walk, wait, trigger others).
void setTarget(const Eigen::Vector3f& target,
std::function<void()> onArrived = nullptr);
void draw(Renderer& renderer); void draw(Renderer& renderer);
// Public: read by Game for camera tracking and ray-cast origin // Public: read by Game for camera tracking and ray-cast origin
@ -48,6 +52,7 @@ private:
Eigen::Vector3f walkTarget = Eigen::Vector3f(0.f, 0.f, 0.f); Eigen::Vector3f walkTarget = Eigen::Vector3f(0.f, 0.f, 0.f);
float targetFacingAngle = 0.0f; float targetFacingAngle = 0.0f;
std::function<void()> onArrivedCallback;
static constexpr float WALK_THRESHOLD = 0.05f; static constexpr float WALK_THRESHOLD = 0.05f;

View File

@ -183,12 +183,10 @@ namespace ZL
npc01->loadAnimation(AnimationState::WALK, "resources/w/default_walk001.txt", CONST_ZIP_FILE); npc01->loadAnimation(AnimationState::WALK, "resources/w/default_walk001.txt", CONST_ZIP_FILE);
npc01->setTexture(defaultTexture); npc01->setTexture(defaultTexture);
npc01->walkSpeed = 1.5f; npc01->walkSpeed = 1.5f;
npc01->rotationSpeed = 2.0f; npc01->rotationSpeed = 8.0f;
npc01->modelScale = 0.01f; npc01->modelScale = 0.01f;
npc01->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY())); npc01->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY()));
/*
Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5f, Eigen::Vector3f::UnitX())) *
Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitZ()));*/
npc01->position = Eigen::Vector3f(0.f, 0.f, -45.f); npc01->position = Eigen::Vector3f(0.f, 0.f, -45.f);
npc01->setTarget(npc01->position); npc01->setTarget(npc01->position);
npcs.push_back(std::move(npc01)); npcs.push_back(std::move(npc01));

View File

@ -14,9 +14,11 @@ static ZL::Game* s_game = nullptr;
PYBIND11_EMBEDDED_MODULE(game_api, m) { PYBIND11_EMBEDDED_MODULE(game_api, m) {
m.doc() = "Game scripting API"; m.doc() = "Game scripting API";
// npc_walk_to(index, x, y, z) // npc_walk_to(index, x, y, z, on_arrived=None)
// Tells the NPC at `index` in Game::npcs to walk to world position (x,y,z). // Tells the NPC at `index` to walk to (x,y,z).
m.def("npc_walk_to", [](int index, float x, float y, float z) { // on_arrived is an optional Python callable invoked once when the NPC arrives.
// It can call npc_walk_to again (or anything else) to chain behaviour.
m.def("npc_walk_to", [](int index, float x, float y, float z, py::object on_arrived) {
if (!s_game) { if (!s_game) {
std::cerr << "[script] game_api.npc_walk_to: engine not ready\n"; std::cerr << "[script] game_api.npc_walk_to: engine not ready\n";
return; return;
@ -27,10 +29,21 @@ PYBIND11_EMBEDDED_MODULE(game_api, m) {
<< " out of range (0.." << npcs.size() - 1 << ")\n"; << " out of range (0.." << npcs.size() - 1 << ")\n";
return; return;
} }
npcs[index]->setTarget(Eigen::Vector3f(x, y, z)); std::function<void()> cb;
if (!on_arrived.is_none()) {
cb = [on_arrived]() {
try {
on_arrived();
} catch (const py::error_already_set& e) {
std::cerr << "[script] on_arrived callback error:\n" << e.what() << "\n";
}
};
}
npcs[index]->setTarget(Eigen::Vector3f(x, y, z), std::move(cb));
}, },
py::arg("index"), py::arg("x"), py::arg("y"), py::arg("z"), py::arg("index"), py::arg("x"), py::arg("y"), py::arg("z"),
"Command NPC[index] to walk to world position (x, y, z)."); py::arg("on_arrived") = py::none(),
"Command NPC[index] to walk to (x,y,z). on_arrived is called when the NPC arrives.");
} }
namespace ZL { namespace ZL {