Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
clojure到java与libgdx的互操作_Clojure_Interop_Libgdx - Fatal编程技术网

clojure到java与libgdx的互操作

clojure到java与libgdx的互操作,clojure,interop,libgdx,Clojure,Interop,Libgdx,我正试图在clojure中复制这个示例应用程序,但很难让java互操作部分正常工作 在libgdx中创建桌面游戏的方法是使用实现ApplicationListener接口的对象实例化LwjglApplication类,以及一些配置选项,如: import com.badlogic.gdx.backends.lwjgl.LwjglApplication; public class Main { public static void main(String[] args) { new

我正试图在clojure中复制这个示例应用程序,但很难让java互操作部分正常工作

在libgdx中创建桌面游戏的方法是使用实现
ApplicationListener
接口的对象实例化
LwjglApplication
类,以及一些配置选项,如:

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;

public class Main {

  public static void main(String[] args) {
    new LwjglApplication(new DropGame(), cfg);
  }
  
  public class DropGame implements ApplicationListener {
    Texture dropImage;
    Sound dropSound;     
    ... rest of assets 

    public void create() {
      dropImage = new Texture(Gdx.files.internal("droplet.png"));
      dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));
    }
    ... rest of interface methods

  }
}
在阅读了clojure/java互操作之后,下面是我提出的clojure等价物:

(ns dropgame.core
  (:gen-class)
  (:import (com.badlogic.gdx.backends.lwjgl LwjglApplication))

(defn app-listener [] 
    (reify ApplicationListener
      (create [this] (let [dropImage (Texture.            (.internal Gdx/files "droplet.png"))
                           dropSound (.newSound Gdx/audio (.internal Gdx/files "drop.wav"))])

(defn App [] 
  (LwjglApplication. (app-listener) cfg))
我遗漏了很多代码,但这很好,因为应用程序使用这种结构工作。问题是这段代码并不完全相同。libgdx框架选择全局声明所有资产(本例中为dropImage和dropSound),以便其他方法中的代码可以轻松访问它们,而无需传递它们。如果我试图通过在外部let绑定中声明资产而不是在方法中声明资产来重构代码,那么它将不再有效

这样做会给我一个nullPointerException:

(defn app-listener [] 
  (let [dropImage (Texture.            (.internal Gdx/files "droplet.png"))
        dropSound (.newSound Gdx/audio (.internal Gdx/files "drop.wav"))]
    (reify ApplicationListener
      (create [this] ( ; try accessing dropImage or dropSound)))))
因此let绑定正在创建相同的对象,但是从任何方法内部访问这些对象似乎不再有效。知道我做错了什么吗

编辑:如前所述,我之所以收到nullPointerException,可能是因为在应用程序准备就绪之前加载了资产。但是,正如muhuk所建议的,为简单游戏之外的任何事情加载资产的正确方法是使用AssetManager。因此,我最终为资产做了类似的事情:

(def asset-manager (doto (AssetManager.)
                   (.load "rain.mp3"    Music)
                   (.load "droplet.png" Texture))
但是,除了资产之外,还有其他东西需要全局访问,例如照相机。因此,我所做的是:

(defn app-listener []
  (reify ApplicationListener
    (create [this]
      (def camera (-> (OrthographicCamera.) (.setToOrtho false 800 480)))))) 
虽然这可能会在任何普通clojure代码中引发警报,因为您有一个定义全局值的函数,但在这种特殊情况下,它实际上是有意义的,因为“app listener”只实例化一次,并且指定“create”方法在应用的生命周期中也只调用一次。不过我还是想知道有没有更好的方法

至于使用“deftype”,我的理解是“defrecord”更容易使用,因为它允许传递附加字段的映射,而不必在构造函数中声明它们。但是在这两种情况下,代码看起来都非常混乱,因为您必须将所有资产传递给构造函数。除此之外,定义一个命名类型会模糊代码的作用,并且不适合这个问题


我将完成本教程的其余部分,并在完成后发布clojure代码的链接。谢谢各位。

我猜你们是在libgdx框架允许初始化它们之前尝试对它们进行初始化。如果您发布了堆栈跟踪,将非常有用

作为另一个clojure新手,也许要做的是探索deftype?iirc将为您提供方法和字段,这是您所需要的。let仅将变量初始化为当前范围


另一种方法可能是绑定当前线程的值,但我不确定哪种方法更正确。祝你好运(我还对libgdx和clojure感兴趣)

在创建应用程序实例之前,让
尝试加载资产。libGDX模拟了android应用程序的生命周期,因此在调用
create
之前,您不应该尝试加载资产


由于libGDX是一个Java框架,我们不能期望它与Clojure的纯功能方法相匹配。某个地方一定有某种状态。您可能想看一看。

如果有人在Clojure上遇到问题,并且示例游戏最终出现在这里(就像我所做的那样),这里有一个链接指向一个工作实现(尽管没有音乐/声音):


我还刚刚开始学习Clojure,所以如果实现中的某些事情做得不好,请在评论中告诉我。

是的,这很有意义。我假设我的应用程序侦听器函数在调用时隐式返回“this”对象,并将let绑定变量作为字段,但我想这就是实例化匿名对象的“具体化”和“代理”的意思吧?我没有做太多的java,所以当我读到这一部分时,它没有太多的意义。不管怎样,我要试一下,然后回去报告。堆栈跟踪也启动了。您能解释一下绑定当前线程的值是什么意思吗?谢谢,谢谢,我将尝试一下,看看哪种方法最适合clojure。我会把我找到的贴出来