13

Luaスクリプトを使用するJavaでAndroidゲームを開発しています。これらのスクリプトを実行するために、私はJavaのScriptEngineクラスでLuaJを使用しています。例えば...

ScriptEngineManager sem = new ScriptEngineManager();
scriptEngine = sem.getEngineByExtension(".lua");
script = ((Compilable)scriptEngine).compile("some lua here");

ただし、これはAndroidでは明らかにサポートされていません(Androidに本格的なJVMがないことと関係があります。どこかで読んでいます)。AndroidでLuaスクリプトを使用する方法はありますか?たぶんLuaJの代替手段がありますか?おそらく、LuaJを直接使用してLuaスクリプトをコンパイルおよび実行する方法があります(方法はわかりませんが)。

参考までに、Androidでこのコードを実行しようとすると、次のエラーが表示されます。

05-06 16:12:32.870: E/dalvikvm(17509): Could not find class 'javax.script.ScriptEngineManager', referenced from method unearth.levels.LevelReader.<init>
05-06 16:12:32.870: W/dalvikvm(17509): VFY: unable to resolve new-instance 787 (Ljavax/script/ScriptEngineManager;) in Lunearth/levels/LevelReader;
05-06 16:12:32.870: D/dalvikvm(17509): VFY: replacing opcode 0x22 at 0x0018
05-06 16:12:32.875: E/dalvikvm(17509): Could not find class 'javax.script.Compilable', referenced from method unearth.levels.LevelReader.parseScript
05-06 16:12:32.875: W/dalvikvm(17509): VFY: unable to resolve check-cast 782 (Ljavax/script/Compilable;) in Lunearth/levels/LevelReader;
05-06 16:12:32.875: D/dalvikvm(17509): VFY: replacing opcode 0x1f at 0x0047
05-06 16:12:32.875: W/dalvikvm(17509): VFY: unable to resolve exception class 788 (Ljavax/script/ScriptException;)
05-06 16:12:32.875: W/dalvikvm(17509): VFY: unable to find exception handler at addr 0x51
05-06 16:12:32.875: W/dalvikvm(17509): VFY:  rejected Lunearth/levels/LevelReader;.parseScript (Lorg/w3c/dom/Element;Lunearth/levels/Level;)V
05-06 16:12:32.875: W/dalvikvm(17509): VFY:  rejecting opcode 0x0d at 0x0051
05-06 16:12:32.875: W/dalvikvm(17509): VFY:  rejected Lunearth/levels/LevelReader;.parseScript (Lorg/w3c/dom/Element;Lunearth/levels/Level;)V
05-06 16:12:32.875: W/dalvikvm(17509): Verifier rejected class Lunearth/levels/LevelReader;
05-06 16:12:32.890: W/dalvikvm(17509): threadid=11: thread exiting with uncaught exception (group=0x40c331f8)
05-06 16:12:32.895: E/AndroidRuntime(17509): FATAL EXCEPTION: GLThread 1062
05-06 16:12:32.895: E/AndroidRuntime(17509): java.lang.VerifyError: unearth/levels/LevelReader
05-06 16:12:32.895: E/AndroidRuntime(17509):    at unearth.Game.startGame(Game.java:201)
05-06 16:12:32.895: E/AndroidRuntime(17509):    at unearth.Game.update(Game.java:713)
05-06 16:12:32.895: E/AndroidRuntime(17509):    at unearth.screens.LoadScreen.update(LoadScreen.java:56)
05-06 16:12:32.895: E/AndroidRuntime(17509):    at unearth.UnearthListener.render(UnearthListener.java:71)
05-06 16:12:32.895: E/AndroidRuntime(17509):    at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:423)
05-06 16:12:32.895: E/AndroidRuntime(17509):    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1462)
05-06 16:12:32.895: E/AndroidRuntime(17509):    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1216)
05-06 16:12:58.600: D/dalvikvm(17509): GC_CONCURRENT freed 334K, 3% free 16196K/16647K, paused 2ms+6ms

アップデート:

たぶん、このプロジェクトにはいくつかの便利なコードがありますか?http://code.google.com/p/android-scripting/

4

4 に答える 4

13

AndroidでLuaJを使用する方法を見つけました!:-)

重要なのは、を介してではなく、LuaJAPIを直接使用することjavax.scriptです。チュートリアルがないため、理解するのは少し難しいので、他の人がLuaJソースコードとJavaDocを選択する必要がないように、前後を示します。それが私をばかげたものにしたので、これが誰かに役立つことを本当に願っています!

注:「secretgame」は私のゲームの実際の名前ではありません;-)

後:

package secretgame.scripting;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.jse.CoerceJavaToLua;
import org.luaj.vm2.lib.jse.JsePlatform;

import secretgame.SecretGameException;
import secretgame.events.EventArgs;
import secretgame.levels.Level;

public class DirectLuaj implements Lua
{
  private final Level level;
  private final ScriptTools scriptTools;
  private final ScriptEvents scriptEvents;
  private int nextId = 0;
  private ArrayList<LuaClosure> scripts = new ArrayList<LuaClosure>();

  public DirectLuaj(Level level, ScriptTools scriptTools,
      ScriptEvents scriptEvents)
  {
    this.level = level;
    this.scriptTools = scriptTools;
    this.scriptEvents = scriptEvents;
  }

  @Override
  public int add(String scriptText) throws SecretGameException
  {
    try {
      InputStream input = new ByteArrayInputStream(scriptText.getBytes());
      Prototype p = LuaC.compile(input, "script");
      LuaValue g = JsePlatform.standardGlobals();
      LuaClosure c = new LuaClosure(p, g);
      scripts.add(c);
    }
    catch (IOException e) {
      throw new SecretGameException("compile failed", e);
    }

    return nextId++;
  }

  @Override
  public void run(int id, EventArgs args) throws SecretGameException
  {
    LuaClosure script = scripts.get(id);

    LuaTable bindings = new LuaTable();

    bindings.set("java", toLua(scriptTools));
    bindings.set("level", toLua(level));
    bindings.set("args", toLua(args));
    bindings.set("events", toLua(scriptEvents));

    script.setfenv(bindings);

    script.call();
  }

  private LuaValue toLua(Object javaValue) {
    return javaValue == null? LuaValue.NIL:
            javaValue instanceof LuaValue? (LuaValue) javaValue:
            CoerceJavaToLua.coerce(javaValue);
  }
}

前:

package secretgame.scripting;

import java.util.ArrayList;

import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import secretgame.SecretGameException;
import secretgame.events.EventArgs;
import secretgame.levels.Level;

// sadly this won't work on Android because there's no such thing
// as javax.script in Dalvik ... dumb Android java :|
public class JavaxScriptingLua implements Lua
{
  private ScriptEngine scriptEngine;
  private final Level level;
  private final ScriptTools scriptTools;
  private final ScriptEvents scriptEvents;
  private int nextId = 0;
  private ArrayList<CompiledScript> scripts = new ArrayList<CompiledScript>();

  public JavaxScriptingLua(Level level, ScriptTools scriptTools, ScriptEvents scriptEvents)
  {
    this.level = level;
    this.scriptTools = scriptTools;
    this.scriptEvents = scriptEvents;

    ScriptEngineManager sem = new ScriptEngineManager();
    scriptEngine = sem.getEngineByExtension(".lua");
  }

  public int add(String scriptText) throws SecretGameException
  {
    try {
      CompiledScript script = ((Compilable)scriptEngine).compile(scriptText);
      scripts.add(script);
    }
    catch (ScriptException e) {
      throw new SecretGameException("could not compile lua.", e);
    }

    return nextId++;
  }

  public void run(int id, EventArgs args) throws SecretGameException
  {    
    Bindings bindings = scriptEngine.createBindings();

    bindings.put("java", scriptTools);
    bindings.put("level", level);
    bindings.put("args", args);
    bindings.put("events", scriptEvents);

    try {
      scripts.get(id).eval(bindings);
    }
    catch (ScriptException e) {
      throw new SecretGameException("could not run script.", e);
    }
  }
}
于 2012-05-10T00:39:33.157 に答える
4

LuaJの代わりに、NDKを使用してAndroid用にコンパイルされたLuaと一緒にLuaJavaを使用することもできます。これにより、LuaはJavaから利用可能なものすべてにフルアクセスできます。この例を見て、開始方法を確認してください。

Lua 5.1.4 +コンパイルされたLuaJavaは、NDKをいじりたくない場合はlibsディレクトリ(単一のlibluajava.soファイル)で提供されますが、とにかくセットアップは比較的簡単です。

于 2012-05-06T22:30:56.310 に答える
1

ただし、これは明らかにAndroidではサポートされていません

正しい。

本格的なJVMを持たないAndroidと関係がある、私はどこかで読んだ

正しい。JavaDocsを見ると、AndroidSDKにjavax.scriptは存在しないことがわかります。

たぶん私はこれを試してみます:https ://github.com/damonkohler/sl4a

それは1つのオプションです。もう1つは、このサンプルアプリケーションのように、NDKを介してLuaインタープリターをアプリに埋め込むことです。

于 2012-05-06T15:25:11.523 に答える
1

AndroidでLuaを使用するには、JNLua + Lua 5.2(Cで実装)を使用できます。JSR 223(javax.script)をサポートする唯一のAndroidポートはここにあります:https ://github.com/danke-sra/jnlua-android

このポートを使用して、必要なことを実行できます。

ScriptEngine scriptEngine = new LuaScriptEngineFactory().getEngine(); scriptEngine.eval("lua statements");

于 2016-01-20T06:02:45.017 に答える