238 lines
7.9 KiB
Clojure
238 lines
7.9 KiB
Clojure
(in-ns 'play-clj.core)
|
|
|
|
(defmacro on-gl
|
|
"Runs the macro body on the GL thread.
|
|
|
|
(on-gl (set-screen! my-game main-screen))"
|
|
[& body]
|
|
`(app! :post-runnable (fn [] ~@body)))
|
|
|
|
(defn bundle
|
|
"Returns an entity containing other entities. This is a useful way to keep
|
|
related entities together. They will be drawn in the order they appear in the
|
|
internal :entities vector. Any keys in the bundle, such as :x and :y, will
|
|
override the equivalent keys in each entity when being drawn.
|
|
|
|
(bundle (shape :filled) (shape :line))
|
|
(assoc (bundle (shape :filled) (shape :line))
|
|
:x 100 :y 100)"
|
|
[& entities]
|
|
(BundleEntity. entities))
|
|
|
|
(defn bundle?
|
|
"Returns true if `entity` is a `bundle`."
|
|
[entity]
|
|
(isa? (type entity) BundleEntity))
|
|
|
|
(defn screenshot!
|
|
"Captures a screenshot and either returns it as a `pixmap` or saves it to the
|
|
specified path.
|
|
|
|
(screenshot!)
|
|
(screenshot! \"out.png\")
|
|
(screenshot! (files! :external \"out.png\"))"
|
|
([]
|
|
(let [^Pixmap$Format pic-f (Pixmap$Format/RGBA8888)
|
|
^Pixmap pic (Pixmap. ^long (game :width) ^long (game :height) pic-f)
|
|
pixel-data (ScreenUtils/getFrameBufferPixels true)
|
|
pixels (.getPixels pic)]
|
|
(doto pixels
|
|
(.clear)
|
|
(.put pixel-data)
|
|
(.position 0))
|
|
pic))
|
|
([path]
|
|
(let [pic (screenshot!)
|
|
handle (if (string? path)
|
|
(files! :local path)
|
|
path)]
|
|
(PixmapIO/writePNG handle pic)
|
|
(pixmap! pic :dispose))))
|
|
|
|
(defmacro pref!
|
|
"Retrieves and stores preferences. The `name` should be a unique string.
|
|
|
|
; define the name we'll be using
|
|
(def ^:const pref-name \"my-game.settings\")
|
|
; store a single preference
|
|
(pref! pref-name :put-float \"player-health\" 40)
|
|
; store multiple preferences
|
|
(pref! pref-name :put {\"player-health\" 40
|
|
\"player-x\" 20
|
|
\"player-y\" 50})
|
|
; save the changes to the disk
|
|
(pref! pref-name :flush)
|
|
; retrieve a single preference
|
|
(pref! pref-name :get-float \"player-health\")"
|
|
[name k & options]
|
|
`(let [^Preferences p# (if (string? ~name)
|
|
(app! :get-preferences ~name)
|
|
~name)]
|
|
(u/call! p# ~k ~@options)))
|
|
|
|
; static fields
|
|
|
|
(defmacro scaling
|
|
"Returns a static field from [Scaling](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/Scaling.html).
|
|
|
|
(scaling :fill)"
|
|
[k]
|
|
`~(u/gdx-field :utils :Scaling k))
|
|
|
|
(defmacro usage
|
|
"Returns a static field in [VertexAttributes.Usage](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/VertexAttributes.Usage.html)."
|
|
[k]
|
|
`~(u/gdx-field :graphics "VertexAttributes$Usage" (u/key->pascal k)))
|
|
|
|
; timers
|
|
|
|
(defn ^:private task*
|
|
[{:keys [execute-fn! on-timer]} id]
|
|
(proxy [Timer$Task] []
|
|
(run []
|
|
(execute-fn! on-timer :id id))))
|
|
|
|
(defn ^:private timer*
|
|
[]
|
|
(some-> (Class/forName "com.badlogic.gdx.utils.Timer")
|
|
(try (catch Exception _))
|
|
.newInstance))
|
|
|
|
(defn ^:private create-and-add-timer!
|
|
[{:keys [update-fn!] :as screen} id]
|
|
(when-let [timer (timer*)]
|
|
(update-fn! assoc-in [[:timers id] timer])
|
|
timer))
|
|
|
|
(defn add-timer!
|
|
"Returns a [Timer](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/Timer.html)
|
|
that runs the :on-timer function according to the given arguments.
|
|
|
|
; wait 2 seconds and run once
|
|
(add-timer! screen :spawn-enemy 2)
|
|
; wait 2 seconds and run forever at 10 second intervals
|
|
(add-timer! screen :spawn-enemy 2 10)
|
|
; wait 2 seconds, run once, and then run 3 more times at 10 second intervals
|
|
(add-timer! screen :spawn-enemy 2 10 3)"
|
|
([screen id delay]
|
|
(doto (create-and-add-timer! screen id)
|
|
(.scheduleTask (task* screen id) delay)))
|
|
([screen id delay interval]
|
|
(doto (create-and-add-timer! screen id)
|
|
(.scheduleTask (task* screen id) delay interval)))
|
|
([screen id delay interval repeat]
|
|
(doto (create-and-add-timer! screen id)
|
|
(.scheduleTask (task* screen id) delay interval repeat))))
|
|
|
|
(defn remove-timer!
|
|
"Stops and removes the timer associated with `id`, returning it or nil if not
|
|
found."
|
|
[{:keys [update-fn!] :as screen} id]
|
|
(when-let [timer (get-in screen [:timers id])]
|
|
(.stop timer)
|
|
(update-fn! update-in [[:timers] dissoc id])
|
|
timer))
|
|
|
|
; assets
|
|
|
|
(defn ^:private loader-class
|
|
[k]
|
|
(cond
|
|
(contains? #{:atlas-tmx-map :tmx-map} k)
|
|
(u/gdx :maps :tiled (str (u/key->pascal k) "Loader"))
|
|
(contains? #{:g3d-model :obj} k)
|
|
(u/gdx :graphics :g3d :loader (str (u/key->pascal k) "Loader"))
|
|
:else
|
|
(u/gdx :assets :loaders (str (u/key->pascal k) "Loader"))))
|
|
|
|
(defmacro loader
|
|
"Returns a subclass of [AssetLoader](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/assets/loaders/AssetLoader.html).
|
|
|
|
(loader :atlas-tmx-map (resolver :internal-file-handle))
|
|
(loader :bitmap-font (resolver :internal-file-handle))
|
|
(loader :g3d-model (resolver :internal-file-handle))
|
|
(loader :model (resolver :internal-file-handle))
|
|
(loader :music (resolver :internal-file-handle))
|
|
(loader :obj (resolver :internal-file-handle))
|
|
(loader :pixmap (resolver :internal-file-handle))
|
|
(loader :skin (resolver :internal-file-handle))
|
|
(loader :sound (resolver :internal-file-handle))
|
|
(loader :texture (resolver :internal-file-handle))
|
|
(loader :tmx-map (resolver :internal-file-handle))
|
|
(loader :tmx-map
|
|
(resolver :internal-file-handle)
|
|
(load [file-name] nil))"
|
|
[type resolver & options]
|
|
`(proxy [~(loader-class type)] [~resolver] ~@options))
|
|
|
|
(defmacro loader!
|
|
"Calls a single method in a subclass of [AsynchronousAssetLoader](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/assets/loaders/AsynchronousAssetLoader.html).
|
|
|
|
(loader! object :tmx-map :load \"map.tmx\")"
|
|
[object type & options]
|
|
`(let [^AsynchronousAssetLoader object# ~object]
|
|
(u/call! object# ~@options)))
|
|
|
|
(defn ^:private resolver-class
|
|
[k]
|
|
(u/gdx :assets :loaders :resolvers (str (u/key->pascal k) "Resolver")))
|
|
|
|
(defmacro resolver
|
|
"Returns an implementation of [FileHandleResolver](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/assets/loaders/FileHandleResolver.html).
|
|
|
|
(resolver :internal-file-handle)
|
|
(resolver :internal-file-handle
|
|
(resolve [file-name]
|
|
(files! :internal file-name)))"
|
|
[type & options]
|
|
`(proxy [~(resolver-class type)] [] ~@options))
|
|
|
|
(defn ^:private set-loaders!
|
|
([am]
|
|
(set-loaders! am (resolver :internal-file-handle)))
|
|
([^AssetManager am res]
|
|
(->> (loader :tmx-map res)
|
|
(.setLoader am TiledMap))
|
|
(->> (loader :particle-effect
|
|
res
|
|
(load [am file-name fh param]
|
|
(doto (ParticleEffect.)
|
|
(.load fh (.parent fh)))))
|
|
(.setLoader am ParticleEffect))))
|
|
|
|
(defn asset-manager*
|
|
([]
|
|
(doto (AssetManager.) set-loaders!))
|
|
([resolver]
|
|
(doto (AssetManager. resolver) (set-loaders! resolver))))
|
|
|
|
(defmacro asset-manager
|
|
"Returns an [AssetManager](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/assets/AssetManager.html).
|
|
|
|
(asset-manager)"
|
|
[& options]
|
|
`(let [^AssetManager object# (asset-manager*)]
|
|
(u/calls! object# ~@options)))
|
|
|
|
(defmacro asset-manager!
|
|
"Calls a single method in an `asset-manager`.
|
|
|
|
(asset-manager! object :clear)"
|
|
[object k & options]
|
|
`(let [^AssetManager object# ~object]
|
|
(u/call! object# ~k ~@options)))
|
|
|
|
(defn set-asset-manager!
|
|
"Sets a global asset manager, which will keep track of objects that need to
|
|
be manually disposed, such as `texture` entities and `pixmap` objects. The
|
|
asset manager will then allow you to dispose them all at once.
|
|
|
|
; create an asset manager
|
|
(defonce manager (asset-manager))
|
|
; set it to be used by play-clj
|
|
(set-asset-manager! manager)
|
|
; dispose all assets at once
|
|
(asset-manager! manager :clear)"
|
|
[am]
|
|
(intern 'play-clj.utils '*asset-manager* am))
|