java - programacion - ¿Es posible ejecutar una sola instrucción lua desde un programa host?
lua tutorial español (2)
Intento incorporar un sistema de script basado en lua en mi motor de juego. Me gustaría que las secuencias de comandos puedan tener comandos de bloqueo y de no bloqueo, por ejemplo:
character.walkTo(24, 359); // Blocks until character arrives
c = 35; // Non blocking, execution goes on to the next statement
Como el "walkTo" necesita estar "activo" durante más de 1 fotograma de ejecución, me gustaría poder ejecutar 1 declaración al momento desde el host de Java en lugar de ejecutar la función completa. Esto se debe a que sería excesivo tener multihilo real, que no es necesario.
Si pudiera ejecutar solo 1 enunciado y mantener el estado de ejecución "en pausa" hasta la siguiente ejecución de enunciado, podría implementar comandos de bloqueo como "walkTo" comprobando si el comando está terminado en el host, y si lo está, vaya en la siguiente instrucción, de lo contrario, espere hasta la siguiente iteración de cuadro.
¿Hay alguna forma de ejecutar 1 instrucción por vez desde el host de Java con LuaJ (o con cualquier otra aplicación de Lua), o me veo obligado a desarrollar mi propio motor de scripts con lex y yacc?
Cualquier buena idea es bienvenida, ¡gracias!
Parece que te falta un patrón asíncrono. Si c=35
tiene que ejecutarse una vez que el character
aparece en (24,359)
, la forma correcta es pasar la function() c=35 end
como tercer argumento al método de walk
y su motor (que realiza ''andar'') llamará eso devolución de llamada cuando sea apropiado.
character.walkTo(24, 359, function ()
c = 35
end)
De lo contrario, walk
puede programar caminar al motor y ceder inmediatamente, reanudar el evento correcto. En este caso, debe configurar el script worker-coroutine (no puede ceder en estado principal).
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
Puede cancelar el script en cualquier momento con script=nil
.
yield () tiene algunas limitaciones, consulte el manual.
La respuesta de bonificación para todos los que se quedan con este problema.
Aquí está mi solución exacta:
- 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);
}
}
- Salida -
Comenzó a caminar
(2 segundos después)
¡Llegado!
Una cosa que debes tener mucho cuidado:
- NO use la interfaz ScriptEngine de Java si desea lograr esto. La interfaz ScriptEngine no proporciona API para obtener la instancia Globals implícitamente asignada que necesita para ceder, y hacer una nueva instancia de Globals y usar eso para ceder es obviamente inútil.