使用 javax.script 运行多个脚本的有效方法

发布于 2024-10-31 07:50:17 字数 687 浏览 1 评论 0原文

我正在开发一个游戏,我希望有多个脚本都实现相同的结构。每个脚本都需要在自己的范围内运行,以便代码不会与其他脚本重叠。例如:

struction.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() {
}

I am developing a game where I'd like to have multiple scripts that all implement the same structure. Each script would need to be run in its own scope so that code doesn't overlap other scripts. For example:

structure.js

function OnInit() {
    // Define resources to load, collision vars, etc.
}

function OnLoop() {
    // Every loop
}

function ClickEvent() {
   // Someone clicked me
}

// Other fun functions

Now, lets say I have: "BadGuy.js", "ReallyReallyBadGuy.js", "OtherBadGuy.js" - They all look like the above in terms of structure. Within the game whenever an event takes place, I'd like to invoke the appropriate function.

The problem comes down to efficiency and speed. I found a working solution by creating an engine for each script instance (using getEngineByName), but that just doesn't seem ideal to me.

If there isn't a better solution, I'll probably resort to each script having its own unique class / function names. I.e.

BadGuy.js

var BadGuy = new Object();

BadGuy.ClickEvent = function() {
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

薄荷港 2024-11-07 07:50:17

我认为您不需要为每个“家伙”创建一个新的 ScriptEngine。您可以在一个引擎中管理它们。因此,对于屠杀你的游戏场景提前表示歉意……

  1. 获取 Rhino 引擎的一个实例。
  2. 发出 eval(script) 语句以将新的 JS 对象以及您希望这些对象支持的不同行为(或功能)添加到引擎中。
  3. 您有几种不同的选择来调用每个“人”,但只要每个“人”都有唯一的名称,您始终可以通过名称引用它们并针对它调用命名方法。
  4. 对于对性能更敏感的操作(可能是某种基于轮的事件循环),您可以在同一引擎中预编译脚本,然后可以执行该脚本,而无需重新评估源。

这是我用 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();

I don't think you need to create a new ScriptEngine for every "Guy". You can manage them all in one engine. So with advance apologies for butchering you game scenario.....

  1. Get one instance of the Rhino engine.
  2. Issue eval(script) statements to add new JS Objects to the engine, along with the different behaviours (or functions) that you want these Objects to support.
  3. You have a couple of different choices for invoking against each one, but as long as each "guy" has a unique name, you can always reference them by name and invoke a named method against it.
  4. For more performance sensitive operations (perhaps some sort of round based event loop) you can precompile a script in the same engine which can then be executed without having to re-evaluate the source.

Here's a sample I wrote in 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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文