oakes / play-clj

A Clojure game library
The Unlicense
939 stars 73 forks source link

Creating a filled polygon #19

Closed Misophistful closed 10 years ago

Misophistful commented 10 years ago

I'm trying to create a filled polygon (a hexagon to be exact) using :polygon, but I get a ClassCastException when passing it a standard Clojure vector.

"java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to [F"
"\tat elemental.hexagon$create_hexagon$fn__8055.invoke(/Users/jamtru/Projects/clojure/elemental/desktop/src-common/elemental/hexagon.clj:16)"
"\tat play_clj.entities.ShapeEntity.draw_entity_BANG_(entities.clj:79)"
"\tat play_clj.core$fn__535.invoke(core_graphics.clj:458)"
"\tat clojure.lang.MultiFn.invoke(MultiFn.java:231)"
"\tat play_clj.core$render_BANG_.invoke(core_graphics.clj:518)"
"\tat elemental.core$eval133$fn__158.invoke(core.clj:20)"

The docs say that the expected type is an array of floats (:polygon ^float[] vertices) so I also tried converting the Clojure vector into a Java one with into-array, and tried coercing the doubles into Java floats with float, but then I just get a different ClassCastException:

"java.lang.ClassCastException: [Ljava.lang.Float; cannot be cast to [F"
"\tat elemental.hexagon$create_hexagon$fn__8007.invoke(/Users/jamtru/Projects/clojure/elemental/desktop/src-common/elemental/hexagon.clj:16)"
"\tat play_clj.entities.ShapeEntity.draw_entity_BANG_(entities.clj:79)"
"\tat play_clj.core$fn__535.invoke(core_graphics.clj:458)"
"\tat clojure.lang.MultiFn.invoke(MultiFn.java:231)"
"\tat play_clj.core$render_BANG_.invoke(core_graphics.clj:518)"
"\tat elemental.core$eval133$fn__158.invoke(core.clj:20)"

What data structure and contents is :polygon expecting?

Thanks!

oakes commented 10 years ago

I think float-array should work, have you tried that?

Misophistful commented 10 years ago

float-array works, I don't know why I didn't think to try it. Thanks!

Though, now I'm getting a GdxRuntimeException:

"com.badlogic.gdx.utils.GdxRuntimeException: Must call begin(ShapeType.Line)"
"\tat com.badlogic.gdx.graphics.glutils.ShapeRenderer.polygon(ShapeRenderer.java:1030)"
"\tat com.badlogic.gdx.graphics.glutils.ShapeRenderer.polygon(ShapeRenderer.java:1023)"
"\tat elemental.hexagon$create_hexagon$fn__8103.invoke(/Users/jamtru/Projects/clojure/elemental/desktop/src-common/elemental/hexagon.clj:16)"
"\tat play_clj.entities.ShapeEntity.draw_entity_BANG_(entities.clj:79)"
"\tat play_clj.core$fn__535.invoke(core_graphics.clj:458)"
"\tat clojure.lang.MultiFn.invoke(MultiFn.java:231)"
"\tat play_clj.core$render_BANG_.invoke(core_graphics.clj:518)"
"\tat elemental.core$eval133$fn__158.invoke(core.clj:20)"
"\tat clojure.lang.Var.invoke(Var.java:383)"
"\tat play_clj.core$defscreen_STAR_$execute_fn_BANG___827$G__829__830.invoke(core.clj:57)"
"\tat elemental.core$eval222$fn__223.invoke(core.clj:54)"
"\tat play_clj.core$defscreen_STAR_$execute_fn_BANG___827.doInvoke(core.clj:58)"
"\tat clojure.lang.RestFn.invoke(RestFn.java:439)"
"\tat play_clj.core$defscreen_STAR_$fn__841.invoke(core.clj:85)"
"\tat clojure.lang.AFn.applyToHelper(AFn.java:154)"
"\tat clojure.lang.AFn.applyTo(AFn.java:144)"
"\tat clojure.core$apply.invoke(core.clj:624)"
"\tat play_clj.core$set_screen_BANG_$run_fn_BANG___894.doInvoke(core.clj:135)"
"\tat clojure.lang.RestFn.invoke(RestFn.java:423)"
"\tat play_clj.core$set_screen_BANG_$reify__902.render(core.clj:138)"
"\tat com.badlogic.gdx.Game.render(Game.java:46)"
"\tat play_clj.core.proxy$com.badlogic.gdx.Game$ff19274a.render(Unknown Source)"
"\tat com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:206)"
"\tat com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)"

Here's my code, if it helps:

(defn create-hexagon [coords]
  (let [[x y] (c/coords->xy coords (game :width) (game :height))]
    (-> (shape :filled
               :set-color (color :dark-gray)
               :polygon (float-array (flatten (for [vertex-index (range 6)]
                                               (calculate-vertex x y 100 vertex-index)))))
        (assoc :hexagon? true))))
oakes commented 10 years ago

It appears that LibGDX requires polygons to be lines, not filled, so you'll need to pass :line as the first arg. To achieve a filled shape you may need to make your desired shape out of simpler shapes like rects and triangles.

Misophistful commented 10 years ago

Switching to :line works, and they'll do for now until I figure out how to create filled ones using triangles.

Thanks again for your help.

oakes commented 10 years ago

No problem! Keep in mind there is currently a bug I didn't catch, preventing you from displaying shapes and textures in the same screen. It will be fixed in the next release, maybe this week.