clojure到java与libgdx的互操作
我正试图在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
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。我会把我找到的贴出来