4

我最近一直在尝试使用 lwjgl 库在 Clojure 中测试 OpenGL。我从这段代码开始:

(ns test.core
  (:import [org.lwjgl.opengl Display DisplayMode GL11]))

(defn init-window
  [width height title]
  (Display/setDisplayMode (DisplayMode. width height))
  (Display/setTitle title)
  (Display/create))

(defn update
  []
  (GL11/glClearColor 0 0 0 0)
  (GL11/glClear GL11/GL_COLOR_BUFFER_BIT))

(defn run
  []
  (init-window 800 600 "test")
  (while (not (Display/isCloseRequested))
    (update)
    (Display/update))
  (Display/destroy))

(defn -main
  [& args]
  (.start (Thread. run)))

这在 emacs 中运行良好,使用 nREPL 插件,我可以启动它并在它运行时更改某些内容(例如调用glClearColor)。

我决定把它分成两个单独的文件,这样我就可以重用这个init-window函数:

(ns copengl.core
  (:import [org.lwjgl.opengl Display DisplayMode GL11]))
(defn init-window
  [width height title]
  (Display/setDisplayMode (DisplayMode. width height))
  (Display/setTitle title)
  (Display/create))

(defn mainloop
  [{:keys [update-fn]}]
  (while (not (Display/isCloseRequested))
    (update-fn)
    (Display/update))
  (Display/destroy)) 

(defn run
  [data]
  (init-window (:width data) (:height data) (:title data))
  (mainloop data))

(defn start
  [data]
  (.start (Thread. (partial run data))))

然后在一个单独的文件中

(ns test.core
  (:import [org.lwjgl.opengl Display DisplayMode GL11])
  (:require [copengl.core :as starter]))

(def -main
  [& args]
  (starter/start {:width 800 :height 600 :title "Test" :update-fn update})

然而,这并不能让我在跑步时改变。我必须关闭窗口然后-main再次执行以查看更改。

到目前为止,我已经尝试将最后两个代码摘录放入一个文件中,但也没有成功。但是,如果我将调用从更改update-fn为我的更新函数 ( update) 的名称,而它们在同一个文件中,我可以在它运行时进行更改。

我猜这是因为当我创建带有更新函数的地图时,它传递了实际函数,所以如果我update通过使用 nREPL 插件重新定义来评估它,则没有效果,因为该mainloop函数正在使用该函数 - 不查找符号update并使用它。

有没有办法在两个文件之间拆分代码,同时仍然能够在运行时更改代码?

4

1 回答 1

3

通过放在#'var 名称前面,将 var update 而不是当前包含在 var update 中的函数传递给它。这将导致每次调用更新函数时都在 var 中查找它的内容。

(def -main
  [& args]
  (starter/start {:width 800 :height 600 :title "Test" :update-fn #'update})

这对性能的影响很小,这就是为什么它不是默认设置,尽管它在这种情况下非常有用并且成本很低。

于 2013-02-20T21:46:35.287 回答