From 07c296fee645501a04676a4db357b414cf6d440c Mon Sep 17 00:00:00 2001 From: oakes Date: Sat, 15 Mar 2014 20:29:36 -0400 Subject: [PATCH] Draw entities with a protocol instead of a multi-method --- src/play_clj/core.clj | 8 ++-- src/play_clj/core_graphics.clj | 68 ++++++---------------------------- src/play_clj/utils.clj | 62 +++++++++++++++++++++++++++---- 3 files changed, 70 insertions(+), 68 deletions(-) diff --git a/src/play_clj/core.clj b/src/play_clj/core.clj index c1ea03f..932d321 100644 --- a/src/play_clj/core.clj +++ b/src/play_clj/core.clj @@ -7,9 +7,8 @@ [com.badlogic.gdx.assets AssetManager] [com.badlogic.gdx.graphics Camera Color GL20 OrthographicCamera PerspectiveCamera Texture VertexAttributes$Usage] - [com.badlogic.gdx.graphics.g2d NinePatch ParticleEffect SpriteBatch - TextureRegion] - [com.badlogic.gdx.graphics.g3d Environment ModelBatch ModelInstance] + [com.badlogic.gdx.graphics.g2d SpriteBatch] + [com.badlogic.gdx.graphics.g3d ModelBatch] [com.badlogic.gdx.input GestureDetector GestureDetector$GestureListener] [com.badlogic.gdx.maps MapLayer MapLayers MapProperties] @@ -25,7 +24,8 @@ [com.badlogic.gdx.scenes.scene2d Actor Stage] [com.badlogic.gdx.scenes.scene2d.utils ActorGestureListener Align ChangeListener ClickListener DragListener FocusListener] - [com.badlogic.gdx.utils Timer$Task])) + [com.badlogic.gdx.utils Timer$Task] + [play_clj.utils Entity])) (load "core_global") (load "core_graphics") diff --git a/src/play_clj/core_graphics.clj b/src/play_clj/core_graphics.clj index d7065bf..8451c32 100644 --- a/src/play_clj/core_graphics.clj +++ b/src/play_clj/core_graphics.clj @@ -236,56 +236,12 @@ with the tiled map file at `path` and `unit` scale `(let [^Stage object# (u/get-obj ~screen :renderer)] (u/call! object# ~k ~@options))) -; draw-entity - -(defmulti draw-entity! - "Internal use only" - (fn [_ entity] (:type entity))) - -(defmethod draw-entity! nil [_ _]) - -(defmethod draw-entity! :texture - [^SpriteBatch batch {:keys [^TextureRegion object x y width height]}] - (let [x (float (or x 0)) - y (float (or y 0)) - width (float (or width (.getRegionWidth object))) - height (float (or height (.getRegionHeight object)))] - (.draw batch object x y width height))) - -(defmethod draw-entity! :nine-patch - [^SpriteBatch batch {:keys [^NinePatch object x y width height]}] - (let [x (float (or x 0)) - y (float (or y 0)) - width (float (or width (.getTotalWidth object))) - height (float (or height (.getTotalHeight object)))] - (.draw object batch x y width height))) - -(defmethod draw-entity! :particle-effect - [^SpriteBatch batch {:keys [^ParticleEffect object x y delta-time]}] - (let [x (float (or x 0)) - y (float (or y 0)) - delta-time (float (or delta-time (graphics! :get-delta-time)))] - (.setPosition object x y) - (.draw object batch delta-time))) - -(defmethod draw-entity! :actor - [^SpriteBatch batch {:keys [^Actor object] :as entity}] - (doseq [[k v] entity] - (case k - :x (.setX object v) - :y (.setY object v) - :width (.setWidth object v) - :height (.setHeight object v) - nil)) - (.draw object batch 1)) - -(defmethod draw-entity! :model - [{:keys [^ModelBatch renderer ^Environment attributes]} - {:keys [^ModelInstance object]}] - (.render renderer object attributes)) - ; draw +(defn filter-entities + [entities] + (filter #(isa? (type %) Entity) entities)) + (defmulti draw! "Internal use only" (fn [screen _] (-> screen :renderer class))) @@ -294,8 +250,8 @@ with the tiled map file at `path` and `unit` scale [{:keys [^BatchTiledMapRenderer renderer]} entities] (let [^SpriteBatch batch (.getSpriteBatch renderer)] (.begin batch) - (doseq [entity entities] - (draw-entity! batch entity)) + (doseq [entity (filter-entities entities)] + (u/draw-entity! entity batch)) (.end batch)) entities) @@ -303,16 +259,16 @@ with the tiled map file at `path` and `unit` scale [{:keys [^Stage renderer]} entities] (let [^SpriteBatch batch (.getSpriteBatch renderer)] (.begin batch) - (doseq [entity entities] - (draw-entity! batch entity)) + (doseq [entity (filter-entities entities)] + (u/draw-entity! entity batch)) (.end batch)) entities) (defmethod draw! ModelBatch [{:keys [^ModelBatch renderer ^Camera camera] :as screen} entities] (.begin renderer camera) - (doseq [entity entities] - (draw-entity! screen entity)) + (doseq [entity (filter-entities entities)] + (u/draw-entity! entity screen)) (.end renderer) entities) @@ -421,11 +377,11 @@ specify which layers to render with or without (let [^SpriteBatch batch (.getSpriteBatch renderer)] (.begin batch) (doseq [entity (->> (map #(get-in screen [:layers %]) layer-names) - (apply concat entities) + (apply concat (filter-entities entities)) (sort-by :y #(compare %2 %1)))] (if-let [layer (:layer entity)] (.renderTileLayer renderer layer) - (draw-entity! batch entity))) + (u/draw-entity! entity batch))) (.end batch)) entities) diff --git a/src/play_clj/utils.clj b/src/play_clj/utils.clj index 27c7c68..2cc5f24 100644 --- a/src/play_clj/utils.clj +++ b/src/play_clj/utils.clj @@ -1,8 +1,8 @@ (ns play-clj.utils (:require [clojure.string :as s]) - (:import [com.badlogic.gdx.graphics.g2d NinePatch ParticleEffect + (:import [com.badlogic.gdx.graphics.g2d NinePatch ParticleEffect SpriteBatch TextureRegion] - [com.badlogic.gdx.graphics.g3d ModelInstance] + [com.badlogic.gdx.graphics.g3d Environment ModelBatch ModelInstance] [com.badlogic.gdx.scenes.scene2d Actor] [com.badlogic.gdx.utils Array ArrayMap])) @@ -172,7 +172,53 @@ new object to be created each time a field is set) [object k & options] `(call! ^ArrayMap ~object ~k ~@options)) -; entities +; entity protocol/records + +(defprotocol Entity + "Internal use only" + (draw-entity! [this batch] "Draws the entity")) + +(defrecord TextureEntity [object] Entity + (draw-entity! [{:keys [^TextureRegion object x y width height]} batch] + (let [x (float (or x 0)) + y (float (or y 0)) + width (float (or width (.getRegionWidth object))) + height (float (or height (.getRegionHeight object)))] + (.draw ^SpriteBatch batch object x y width height)))) + +(defrecord NinePatchEntity [object] Entity + (draw-entity! [{:keys [^NinePatch object x y width height]} batch] + (let [x (float (or x 0)) + y (float (or y 0)) + width (float (or width (.getTotalWidth object))) + height (float (or height (.getTotalHeight object)))] + (.draw object ^SpriteBatch batch x y width height)))) + +(defrecord ParticleEffectEntity [object] Entity + (draw-entity! [{:keys [^ParticleEffect object x y delta-time]} batch] + (let [x (float (or x 0)) + y (float (or y 0)) + delta-time (float delta-time)] + (.setPosition object x y) + (.draw object ^SpriteBatch batch delta-time)))) + +(defrecord ActorEntity [object] Entity + (draw-entity! [{:keys [^Actor object] :as entity} batch] + (doseq [[k v] entity] + (case k + :x (.setX object v) + :y (.setY object v) + :width (.setWidth object v) + :height (.setHeight object v) + nil)) + (.draw object ^SpriteBatch batch 1))) + +(defrecord ModelEntity [object] Entity + (draw-entity! [{:keys [^ModelInstance object]} + {:keys [^ModelBatch renderer ^Environment attributes]}] + (.render renderer object attributes))) + +; create-entity (defmulti create-entity "Internal use only" @@ -180,20 +226,20 @@ new object to be created each time a field is set) (defmethod create-entity TextureRegion [obj] - {:type :texture :object obj}) + (TextureEntity. obj)) (defmethod create-entity NinePatch [obj] - {:type :nine-patch :object obj}) + (NinePatchEntity. obj)) (defmethod create-entity ParticleEffect [obj] - {:type :particle-effect :object obj}) + (ParticleEffectEntity. obj)) (defmethod create-entity Actor [obj] - {:type :actor :object obj}) + (ActorEntity. obj)) (defmethod create-entity ModelInstance [obj] - {:type :model :object obj}) + (ModelEntity. obj))