Эффективный способ запуска нескольких скриптов с использованием javax.script
Я занимаюсь разработкой игры, в которой я хотел бы иметь несколько сценариев, которые реализуют одну и ту же структуру. Каждый сценарий должен быть запущен в отдельной области видимости, чтобы код не перекрывал другие сценарии. Например:
structure.js
function OnInit() {
// Define resources to load, collision vars, etc.
}
function OnLoop() {
// Every loop
}
function ClickEvent() {
// Someone clicked me
}
// Other fun functions
Теперь, допустим, у меня есть: "BadGuy.js", "ReallyReallyBadGuy.js", "OtherBadGuy.js" - все они выглядят как выше с точки зрения структуры. В игре всякий раз, когда происходит событие, я бы хотел вызвать соответствующую функцию.
Проблема сводится к эффективности и скорости. Я нашел рабочее решение, создав механизм для каждого экземпляра скрипта (используя getEngineByName
), но это просто не кажется мне идеальным.
Если нет лучшего решения, я, вероятно, прибегну к каждому сценарию, имеющему свои уникальные имена классов / функций. Т.е.
BadGuy.js
var BadGuy = new Object();
BadGuy.ClickEvent = function() {
}
1 ответ
Я не думаю, что вам нужно создавать новый ScriptEngine для каждого "парня". Вы можете управлять ими в одном движке. Так что с предварительными извинениями за убийство вас сценарий игры.....
- Получить один экземпляр двигателя Rhino.
- Выполните операторы eval(script) для добавления новых JS-объектов в движок вместе с различными режимами поведения (или функциями), которые вы хотите, чтобы эти объекты поддерживали.
- У вас есть несколько вариантов выбора для каждого из них, но если у каждого "парня" есть уникальное имя, вы всегда можете ссылаться на них по имени и вызывать именованный метод против него.
- Для более чувствительных к производительности операций (возможно, своего рода циклический цикл обработки событий) вы можете предварительно скомпилировать скрипт в том же движке, который затем может быть выполнен без необходимости повторной оценки источника.
Вот пример, который я написал в Groovy.
import javax.script.*;
sem = new ScriptEngineManager();
engine = sem.getEngineByExtension("js");
engine.getBindings(ScriptContext.ENGINE_SCOPE).put("out", System.out);
eventLoop = "for(guy in allGuys) { out.println(allGuys[guy].Action(action)); }; "
engine.eval("var allGuys = []");
engine.eval("var BadGuy = new Object(); allGuys.push(BadGuy); BadGuy.ClickEvent = function() { return 'I am a BadGuy' }; BadGuy.Action = function(activity) { return 'I am doing ' + activity + ' in a BAD way' }");
engine.eval("var GoodGuy = new Object(); allGuys.push(GoodGuy); GoodGuy.ClickEvent = function() { return 'I am a GoodGuy' }; GoodGuy.Action = function(activity) { return 'I am doing ' + activity + ' in a GOOD way' }");
CompiledScript executeEvents = engine.compile(eventLoop);
println engine.invokeMethod(engine.get("BadGuy"), "ClickEvent");
println engine.invokeMethod(engine.get("GoodGuy"), "ClickEvent");
engine.getBindings(ScriptContext.ENGINE_SCOPE).put("action", "knitting");
executeEvents.eval();