#javax.script
#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();