我正在尝试将基于lua的脚本系统嵌入到我的游戏引擎中。 我希望脚本能够同时具有阻塞和非阻塞命令,例如:
character.walkTo(24, 359); // Blocks until character arrives
c = 35; // Non blocking, execution goes on to the next statement
自" walkTo"需要活跃"对于超过1帧的执行,我希望能够从Java主机而不是整个函数运行1个语句。这是因为真正的多线程是不合适的,这是不需要的。
如果我只能执行1条语句,并保持执行状态"暂停"直到下一个语句执行,我才能实现阻塞命令,如" walkTo"通过检查 如果命令在主机中完成,如果是,则继续执行下一个语句,否则,等到下一帧迭代。
有没有办法从带有LuaJ的Java主机(或任何其他Lua api)执行1个语句,或者我被迫用lex和yacc开发自己的脚本引擎?
欢迎任何好主意, 谢谢!
答案 0 :(得分:4)
为所有坚持这个问题的人提供奖励。
这是我的确切解决方案:
- test.lua -
onLookAt = function()
character:walkTo(234, 35)
print("Arrived!")
end
- LuaTest.java -
public static void luaTest() {
Globals g = JsePlatform.standardGlobals();
g.load(new CoroutineLib());
g.set("character", CoerceJavaToLua.coerce(new Character(g)));
g.load(Gdx.files.internal("test.lua").reader(), "test.lua").call();
g.load("co = coroutine.wrap(onLookAt)").call();
g.get("co").call();
try {
// Simulate time that passes while the script is paused
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
g.get("co").call();
}
public static class Character{
Globals g;
public Character(Globals g){
this.g = g;
}
public void walkTo(int x, int y) {
System.out.println("Started walking.");
g.yield(LuaValue.NONE);
}
}
- 输出 -
开始行走。
(2秒钟后)
到达!
你应该非常小心的一件事:
答案 1 :(得分:3)
好像你缺少异步模式。如果在c=35
character
发生(24,359)
后必须执行function() c=35 end
,那么正确的方法是将walk
作为第三个参数传递给character.walkTo(24, 359, function ()
c = 35
end)
方法和您的引擎(执行实际行走时,会在适当的时候调用该回调。
walk
否则,script = coroutine.wrap(function ()
character.walkTo(24, 359) -- will yield and leave callable global 'script'
c = 35
end)
script() -- resume first time
-- here script is over
...
-- this wrapper may be implemented in Lua or host language
function character.walkTo(x, y)
engine.startActualWalkingTo(x, y)
coroutine.yield() -- yields to host
-- coroutine.resume() will continue here
end
...
-- somewhere in engine code (pseudo-code here)
for event in eventLoop do
if character.x == endPoint.x and character.y == endPoint.y then
script() -- resume again at c=35
end
end
可能会安排步行到引擎并立即屈服,恢复正确的事件。在这种情况下,您必须设置脚本worker-coroutine(您无法在主状态下生成)。
script=nil
您可以随时使用{{1}}取消脚本。
yield()有一些限制,请参阅手册。