2012-05-06 42 views
11

Tôi đang phát triển trò chơi Android bằng Java sử dụng tập lệnh Lua. Để thực hiện các kịch bản này, tôi đang sử dụng LuaJ với lớp ScriptEngine của Java. Ví dụ:Làm cách nào để chạy tập lệnh Lua trên Android trong ứng dụng Java?

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

Tuy nhiên, điều này dường như không được hỗ trợ trên Android (liên quan đến Android không có JVM toàn diện), tôi đọc ở đâu đó). Có cách nào tôi có thể sử dụng kịch bản Lua trên Android? Có lẽ có một lựa chọn thay thế LuaJ? Có lẽ có một cách để biên dịch và thực thi các kịch bản lệnh Lua bằng cách sử dụng LuaJ trực tiếp (mặc dù tôi không thể nhìn thấy như thế nào).

FYI, tôi thấy lỗi này khi tôi cố gắng chạy mã này trên 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 

Cập nhật:

Có lẽ dự án này có một số mã hữu ích? http://code.google.com/p/android-scripting/

Trả lời

11

Tôi đã tìm thấy cách sử dụng LuaJ trên Android! :-)

Điều quan trọng là sử dụng API LuaJ trực tiếp thay vì thông qua javax.script. Đó là một chút khó khăn để tìm ra vì không có hướng dẫn, vì vậy đây là một trước và sau để những người khác không phải đi qua chọn qua mã nguồn LuaJ và JavaDoc. Tôi thực sự hy vọng điều này sẽ giúp một người nào đó vì nó khiến tôi điên cuồng!

Lưu ý: "secretgame" không phải là tên thực tế của trò chơi của tôi ;-)

Sau:

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); 
    } 
} 

Trước:

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); 
    } 
    } 
} 
1

Tuy nhiên, điều này là rõ ràng không được hỗ trợ trên Android

đúng.

một cái gì đó để làm với Android không có một thổi JVM đầy đủ, tôi đọc ở đâu đó

đúng. Nếu bạn nhìn vào the JavaDocs, bạn sẽ thấy rằng javax.script không tồn tại trong SDK Android.

Có lẽ tôi sẽ cung cấp cho một thử này: https://github.com/damonkohler/sl4a

Đó là một lựa chọn. Một cách khác là nhúng trình thông dịch Lua vào ứng dụng của bạn thông qua NDK, như trong this sample application.

+0

Cảm ơn cho câu trả lời - nhưng tôi cố gắng nhận LuaJ làm việc trên Android. Xem câu trả lời của tôi nếu bạn quan tâm. –

4

Thay vì LuaJ bạn có thể (cũng) sử dụng LuaJava cùng với Lua được biên dịch cho Android bằng NDK. Điều này cho phép Lua truy cập đầy đủ mọi thứ có sẵn từ Java. Hãy xem this example để xem cách bắt đầu.

Lua 5.1.4 + LuaJava được biên soạn được cung cấp trong thư mục libs (một tệp libluajava.so) nếu bạn không muốn fiddle với NDK, nhưng nó là tương đối dễ dàng để thiết lập anyway.

+0

Kudo trên AndroLua nhưng tôi đã tìm thấy cách sử dụng LuaJ trên Android, vì vậy theo cách đó tôi không phải viết lại mã hiện có của mình. Xem câu trả lời của tôi cho cách tôi giải quyết vấn đề. –

0

Để sử dụng Lua trên Android, bạn có thể sử dụng JNLua + Lua 5.2 (được triển khai trong C). Cổng Android chỉ với JSR 223 (javax.script) hỗ trợ là ở đây: https://github.com/danke-sra/jnlua-android

Sử dụng cổng này, bạn có thể làm những gì bạn muốn:

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

Các vấn đề liên quan