[英]clojure to java interop with libgdx
我试图从Clojure的libgdx教程中重现示例应用程序,并且很难使Java互操作部件正常工作。
在libgdx中创建桌面游戏的方式是通过实例化LwjglApplication
类,该对象实现了ApplicationListener
接口以及一些配置选项,例如:
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 interop之后,这是我想出的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感兴趣)
这let
想尝试创建一个应用程序实例之前加载的资产。 libGDX模仿了android应用程序的生命周期,因此您不应在调用create
之前尝试加载资产。
由于libGDX是Java框架,我们不能期望它与Clojure的纯功能方法相匹配。 某处必须有某种状态。 您可能想看看AssetManager 。
如果有人对Clojure有麻烦,并且示例游戏到这里结束了(就像我所做的那样),这是一个可行的实现的链接(尽管没有音乐/声音):
http://clojuregames.blogspot.com/2013/10/the-libgdx-simple-game-demo-in-clojure.html
我仍然还只是开始学习Clojure,所以如果实现中的某些事情做得不好,请在评论中告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.