From 6f9c8a4ebd400b5ab444ef969de598375a34a9cc Mon Sep 17 00:00:00 2001 From: oakes Date: Fri, 17 Jan 2014 14:17:47 -0500 Subject: [PATCH] Automatically add box2d contact listener --- src/play_clj/core.clj | 32 +++++++++++++++++--------------- src/play_clj/core_graphics.clj | 29 ++++++++++++++++------------- src/play_clj/g2d_physics.clj | 26 +++++++++++++++++++------- src/play_clj/ui.clj | 2 +- 4 files changed, 53 insertions(+), 36 deletions(-) diff --git a/src/play_clj/core.clj b/src/play_clj/core.clj index ec8dc52..56aa59b 100644 --- a/src/play_clj/core.clj +++ b/src/play_clj/core.clj @@ -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] diff --git a/src/play_clj/core_graphics.clj b/src/play_clj/core_graphics.clj index 4b5700e..f2b4fc4 100644 --- a/src/play_clj/core_graphics.clj +++ b/src/play_clj/core_graphics.clj @@ -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* diff --git a/src/play_clj/g2d_physics.clj b/src/play_clj/g2d_physics.clj index da93a27..d755357 100644 --- a/src/play_clj/g2d_physics.clj +++ b/src/play_clj/g2d_physics.clj @@ -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)))) diff --git a/src/play_clj/ui.clj b/src/play_clj/ui.clj index 4077278..164f710 100644 --- a/src/play_clj/ui.clj +++ b/src/play_clj/ui.clj @@ -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!)