Automatically add box2d contact listener

This commit is contained in:
oakes
2014-01-17 14:17:47 -05:00
parent 7d9ceaa752
commit 6f9c8a4ebd
4 changed files with 53 additions and 36 deletions

View File

@@ -1,5 +1,6 @@
(ns play-clj.core
(:require [clojure.set :as set]
[play-clj.g2d-physics :as g2dp]
[play-clj.ui :as ui]
[play-clj.utils :as u])
(:import [com.badlogic.gdx Application Audio Files Game Gdx Graphics Input
@@ -18,12 +19,13 @@
IsometricStaggeredTiledMapRenderer
IsometricTiledMapRenderer
OrthogonalTiledMapRenderer]
[com.badlogic.gdx.physics.box2d World]
[com.badlogic.gdx.scenes.scene2d Actor Stage]))
(load "core_global")
(load "core_graphics")
(defn ^:private reset-if-changed!
(defn ^:private reset-changed!
[e-atom e-old e-new]
(when (not= e-old e-new)
(compare-and-set! e-atom e-old e-new)))
@@ -33,10 +35,6 @@
:as options}]
(let [screen (atom {})
entities (atom '())
_ (add-watch entities
:changed
(fn [_ _ _ new-entities]
(refresh-renderer! @screen new-entities)))
execute-fn! (fn [func & {:keys [] :as options}]
(when func
(let [old-entities @entities]
@@ -44,18 +42,21 @@
list
flatten
(remove nil?)
(reset-if-changed! entities old-entities)))))
listeners [(input-processor options execute-fn!)
(gesture-detector options execute-fn!)]
ui-listeners (ui/create-listeners options execute-fn!)
update-fn! #(swap! screen merge %)]
(reset-changed! entities old-entities)))))]
; update screen when either the screen or entities are changed
(add-watch screen :changed (fn [_ _ _ new-screen]
(update-screen! new-screen)))
(add-watch entities :changed (fn [_ _ _ new-entities]
(update-screen! @screen new-entities)))
; return a map with all values related to the screen
{:screen screen
:entities entities
:show (fn []
(swap! screen assoc
:total-time 0
:update-fn! update-fn!
:ui-listeners ui-listeners)
:update-fn! #(swap! screen merge %)
:ui-listeners (ui/ui-listeners options execute-fn!)
:g2dp-listener (g2dp/contact-listener options execute-fn!))
(execute-fn! on-show))
:render (fn [d]
(swap! screen #(assoc % :total-time (+ (:total-time %) d)))
@@ -64,7 +65,8 @@
:pause #(execute-fn! on-pause)
:resize #(execute-fn! on-resize :width %1 :height %2)
:resume #(execute-fn! on-resume)
:listeners listeners}))
:input-listeners [(input-processor options execute-fn!)
(gesture-detector options execute-fn!)]}))
(defmacro defscreen
[n & {:keys [] :as options}]
@@ -88,8 +90,8 @@
[^Game game & screens]
(let [add-inputs! (fn []
(input! :set-input-processor (InputMultiplexer.))
(doseq [{:keys [listeners]} screens]
(doseq [listener listeners]
(doseq [{:keys [input-listeners]} screens]
(doseq [listener input-listeners]
(add-input! listener))))
run-fn! (fn [k & args]
(doseq [screen screens]

View File

@@ -1,5 +1,21 @@
(in-ns 'play-clj.core)
(defn ^:private update-screen!
([{:keys [world g2dp-listener]}]
(when (isa? (type world) World)
(.setContactListener ^World world g2dp-listener)))
([{:keys [renderer ui-listeners]} entities]
(when (isa? (type renderer) Stage)
(doseq [^Actor a (.getActors ^Stage renderer)]
(.remove a))
(doseq [{:keys [object]} entities]
(when (isa? (type object) Actor)
(.addActor ^Stage renderer object)
(doseq [listener ui-listeners]
(.addListener ^Actor object listener))))
(remove-input! renderer)
(add-input! renderer))))
; tiled maps
(defn tiled-map*
@@ -197,19 +213,6 @@
(render! screen)
(draw! screen entities)))
(defn ^:private refresh-renderer!
[{:keys [renderer ui-listeners]} entities]
(when (isa? (type renderer) Stage)
(doseq [^Actor a (.getActors ^Stage renderer)]
(.remove a))
(doseq [{:keys [object]} entities]
(when (isa? (type object) Actor)
(.addActor ^Stage renderer object)
(doseq [listener ui-listeners]
(.addListener ^Actor object listener))))
(remove-input! renderer)
(add-input! renderer)))
; cameras
(defn orthographic*

View File

@@ -1,22 +1,34 @@
(ns play-clj.g2d-physics
(:require [play-clj.math :as m]
[play-clj.utils :as u])
(:import [com.badlogic.gdx.physics.box2d World]))
(:import [com.badlogic.gdx.physics.box2d ContactListener World]))
(defn box2d*
(defn box-2d*
([]
(box2d* 0 0 true))
(box-2d* 0 0 true))
([gravity-x gravity-y]
(box2d* gravity-x gravity-y true))
(box-2d* gravity-x gravity-y true))
([gravity-x gravity-y sleep?]
(World. (m/vector-2 gravity-x gravity-y) sleep?)))
(defmacro box2d
(defmacro box-2d
[gravity-x gravity-y & options]
`(let [object# (box2d* ~gravity-x ~gravity-y)]
`(let [object# (box-2d* ~gravity-x ~gravity-y)]
(u/calls! ^World object# ~@options)
object#))
(defmacro box2d!
(defmacro box-2d!
[{:keys [^World world]} k & options]
`(u/call! ^World ~world ~k ~@options))
(defn contact-listener
[{:keys [on-begin-contact on-end-contact on-post-solve on-pre-solve]} execute-fn!]
(reify ContactListener
(beginContact [this c]
(execute-fn! on-begin-contact :contact c))
(endContact [this c]
(execute-fn! on-end-contact :contact c))
(postSolve [this c i]
(execute-fn! on-post-solve :contact c :impulse i))
(preSolve [this c m]
(execute-fn! on-pre-solve :contact c :old-manifold m))))

View File

@@ -476,7 +476,7 @@
(scrollFocusChanged [e a f]
(execute-fn! on-ui-scroll-focus-changed :event e :actor a :focused? f))))
(defn create-listeners
(defn ui-listeners
[options execute-fn!]
[(gesture-listener options execute-fn!)
(change-listener options execute-fn!)