Git Product home page Git Product logo

play-clj's Introduction

Note: I am focusing my efforts on play-cljc, a library for games that run on both the desktop and the web.

Introduction

A Clojure library that provides a wrapper for libGDX, allowing you to write 2D and 3D games that run on desktop OSes (Windows, OS X, and Linux) and Android with the same Clojure codebase.

Getting Started

There are a few ways to create a project:

Justification

The best thing about making a game in Clojure is that you can modify it in a REPL while it's running. By simply reloading a namespace, your code will be injected into the game, uninhibited by the restrictions posed by tools like HotSwap. Additionally, a REPL lets you read and modify the state of your game at runtime, so you can quickly experiment and diagnose problems.

Clojure also brings the benefits of functional programming. This is becoming a big topic of discussion in gamedev circles, including by John Carmack. Part of this is due to the prevalence of multi-core hardware, making concurrency more important. Additionally, there is a general difficulty of maintaining object-oriented game codebases as they grow, due to complicated class hierarchies and state mutations.

Documentation

(ns game-test.core
  (:require [play-clj.core :refer :all]
            [play-clj.g2d :refer :all]))

; define a screen, where all the action takes place
(defscreen main-screen
  ; all the screen functions get a map called "screen" containing various
  ; important values, and a vector called "entities" for storing game objects
  
  ; the entities vector is immutable, so in order to update it you must simply
  ; return a new vector at the end of each screen function
  
  ; this function runs only once, when the screen is first shown
  :on-show
  (fn [screen entities]
    ; update the screen map to hold a tiled map renderer and a camera
    (update! screen
             :renderer (orthogonal-tiled-map "level1.tmx" (/ 1 8))
             :camera (orthographic))
    (let [; load a sprite sheet from your resources dir
          sheet (texture "tiles.png")
          ; split the sheet into 16x16 tiles
          ; (the texture! macro lets you call TextureRegion methods directly)
          tiles (texture! sheet :split 16 16)
          ; get the tile at row 6, col 0
          player-image (texture (aget tiles 6 0))
          ; add position and size to the player-image map so it can be drawn
          player-image (assoc player-image :x 0 :y 0 :width 2 :height 2)]
      ; return a new entities vector with player-image inside of it
      [player-image]))
  
  ; this function runs every time a frame must be drawn (about 60 times per sec)
  :on-render
  (fn [screen entities]
    ; make the screen completely black
    (clear!)
    ; render the tiled map, draw the entities and return them
    (render! screen entities))
  
  ; this function runs when the screen dimensions change
  :on-resize
  (fn [screen entities]
    ; make the camera 20 tiles high, while maintaining the aspect ratio
    (height! screen 20)
    ; you can return nil if you didn't change any entities
    nil))

; define the game itself, and immediately hand off to the screen
(defgame game-test
  :on-create
  (fn [this]
    (set-screen! this main-screen)))

Licensing

All files that originate from this project are dedicated to the public domain. I would love pull requests, and will assume that they are also dedicated to the public domain.

play-clj's People

Contributors

boriskourt avatar briancain avatar danjohansson avatar floybix avatar janavpetrova avatar kamn avatar kul avatar mk12 avatar nblumoe avatar oakes avatar the2bears avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

play-clj's Issues

LWJGL Exceptions disconnect the game window while live editing

Using a LightTable repl connection: Basically anything breaks the code will throw an exception after running

(app! :post-runnable #(set-screen! mental-math fight-screen))

Then after re-evaling the fixed code and :post-runnable the window stays broken. Currently I'm just disconnecting/reconnecting

"Exception in thread \"LWJGL Application\" "
"clojure.lang.ArityException: Wrong number of args (2) passed to: core$assoc"
"\tat clojure.lang.AFn.throwArity(AFn.java:437)"
"\tat clojure.lang.RestFn.invoke(RestFn.java:427)"
"\tat mental_math.core$create_circle_entity.invoke(/Users/mjr/Documents/code/clojure/mental-math/desktop/src-common/mental_math/core.clj:19)"
"\tat mental_math.core$fn__86$fn__106.invoke(core.clj:54)"
"\tat clojure.lang.Var.invoke(Var.java:419)"
"\tat play_clj.core$defscreen_STAR_$execute_fn_BANG___666$G__668__669.invoke(core.clj:56)"
"\tat play_clj.core$wrapper.invoke(core.clj:46)"
"\tat play_clj.core$defscreen_STAR_$execute_fn_BANG___666.doInvoke(core.clj:57)"
"\tat clojure.lang.RestFn.invoke(RestFn.java:410)"
"\tat play_clj.core$defscreen_STAR_$fn__688.invoke(core.clj:79)"
"\tat clojure.lang.AFn.applyToHelper(AFn.java:159)"
"\tat clojure.lang.AFn.applyTo(AFn.java:151)"
"\tat clojure.core$apply.invoke(core.clj:617)"
"\tat play_clj.core$set_screen_BANG_$run_fn_BANG___733.doInvoke(core.clj:138)"
"\tat clojure.lang.RestFn.invoke(RestFn.java:410)"
"\tat play_clj.core$set_screen_BANG_$reify__741.show(core.clj:140)"
"\tat com.badlogic.gdx.Game.setScreen(Game.java:62)"
"\tat play_clj.core.proxy$com.badlogic.gdx.Game$0.setScreen(Unknown Source)"
"\tat play_clj.core$set_screen_BANG_.doInvoke(core.clj:139)"
"\tat clojure.lang.RestFn.invoke(RestFn.java:423)"
"\tat mental_math.core$eval6683$fn__6684.invoke(/Users/mjr/Documents/code/clojure/mental-math/desktop/src-common/mental_math/core.clj:91)"
"\tat clojure.lang.AFn.run(AFn.java:24)"
"\tat com.badlogic.gdx.backends.lwjgl.LwjglApplication.executeRunnables(LwjglApplication.java:238)"
"\tat com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:193)"
"\tat com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)"

What if I have my custom built entity system?

Hello! Thanks for the work on this awesome lib. I did small toy project on it and it was nice and clean.

But then I have decided to do my custom object for managing Entity-components system, maps, etc. Everything is stored in big hash-map. My whole game logic does work fine, but it's completely not fitting concept of play-clj entities which are placed in the vector.

Is there a clean way to ignore vector based entities concept of play-clj and fit the other parts easily? E.g rendering part troubling me.

It would be awesome to have this kind of functionality in play-clj as optional since vector based entities system imposing some limitation on performance when I have about thousands of entities in the system...

Thanks again!

about DOCS page

Ey recently i've been on play-clj DOCS page a lot. And i find the behaviour of the page mighty annoying. Say, i wanna look at --> play-clj.math section --> i scroll to it --> open vector-3 for example --> and immediately the whole list scrolls all the way up. Means that i have to open each page to a new tab OR i have to keep scrolling the list just so i can return to the section i was just looking at. I could possibly come up with some css / js to make it a lil more user-friendly..

Different coordinates system for texture and screen?

Have I understood correctly that texture considers [0,0] as bottom-left and screen considers [0,0] to be top-left? If so, why the different systems?

In my current game I'm doing mouse/touch selection of the game entities, which means I have to invert the :y I get from screen before doing a :contains check on my texture hit-boxes. Is there a better approach?

Cheers,
James

input->screen throws an exception if no :camera is defined

"java.lang.Exception: The keyword :camera is not found."
"play_clj.utils$throw_key_not_found.invoke(utils.clj:9)"
"play_clj.utils$get_obj.invoke(utils.clj:15)"
"play_clj.core$input__GT_screen.invoke(core_graphics.clj:281)"
"play_clj.core$input__GT_screen.invoke(core_graphics.clj:289)"
"elemental.elements$get_element_at_cursor.invoke(elements.clj:27)"
"elemental.core$eval6822$fn__6852.invoke(/Users/jamtru/Projects/clojure/elemental/desktop/src-common/elemental/core.clj:29)"
"clojure.lang.Var.invoke(Var.java:383)"
"play_clj.core$defscreen_STAR_$execute_fn_BANG___827$G__829__830.invoke(core.clj:57)"
"elemental.core$eval6899$fn__6900.invoke(/Users/jamtru/Projects/clojure/elemental/desktop/src-common/elemental/core.clj:45)"
"play_clj.core$defscreen_STAR_$execute_fn_BANG___827.doInvoke(core.clj:58)"
"clojure.lang.RestFn.invoke(RestFn.java:713)"
"play_clj.core$input_processor$reify__643.touchDown(core_listeners.clj:26)"
"com.badlogic.gdx.InputMultiplexer.touchDown(InputMultiplexer.java:88)"
"com.badlogic.gdx.backends.lwjgl.LwjglInput.processEvents(LwjglInput.java:302)"
"com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:199)"
"com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)"

This probably isn't a big problem, as I'm sure most people are defining their :camera straight away. However, I thought I'd let you know about it anyway.

Isometric artifacts

Firstly, as an intro - thanks for opening the possibilities of live game coding using Clojure - love the idea.

I started off having a look at the diablo style isometric example using nightmod on windows 8 64 bit.
It's giving me anomalies on the tile edges - jagged black dots / lines.
(example pic : image )

I suspect the answer lies in the answer to this post: https://www.opengl.org/discussion_boards/showthread.php/167808-2D-texture-problem-lines-between-textures

.. where it says to add this after glEnable(GL_TEXTURE2D) ...
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

I would give you a pull request.
But unfortunately my Java knowledge is non-existent (I'm an accomplished dot net dev, aspiring to Clojure)

Testing strategy

I'm trying to figure out the best way to write tests for main game functionality, i.e. for functions that manipulate entities, rather than isolated helper functions.

I create a simplified list of entities that I pass into the function I'm testing, and I want to check that the expected game state is returned. But I get the following exception on running the test:

java.lang.NullPointerException: null
        ShaderProgram.java:196 com.badlogic.gdx.graphics.glutils.ShaderProgram.loadShader
        ShaderProgram.java:178 com.badlogic.gdx.graphics.glutils.ShaderProgram.compileShaders
        ShaderProgram.java:161 com.badlogic.gdx.graphics.glutils.ShaderProgram.<init>
ImmediateModeRenderer20.java:219 com.badlogic.gdx.graphics.glutils.ImmediateModeRenderer20.createDefaultShader
ImmediateModeRenderer20.java:55 com.badlogic.gdx.graphics.glutils.ImmediateModeRenderer20.<init>
        ShapeRenderer.java:114 com.badlogic.gdx.graphics.glutils.ShapeRenderer.<init>
        ShapeRenderer.java:110 com.badlogic.gdx.graphics.glutils.ShapeRenderer.<init>
          core_graphics.clj:34 play-clj.core/shape*
/Users/jamtru/Projects/clojure/elemental/desktop/src-common/elemental/hexagon.clj:22 elemental.hexagon/create-hexagon
/Users/jamtru/Projects/clojure/elemental/desktop/test/elemental/movement_test.clj:15 elemental.movement-test/fn
                 core.clj:2557 clojure.core/map[fn]
               LazySeq.java:40 clojure.lang.LazySeq.sval
               LazySeq.java:49 clojure.lang.LazySeq.seq
                   RT.java:484 clojure.lang.RT.seq
                  core.clj:133 clojure.core/seq
             core_print.clj:46 clojure.core/print-sequential
            core_print.clj:147 clojure.core/fn
              MultiFn.java:231 clojure.lang.MultiFn.invoke
                 core.clj:3392 clojure.core/pr-on
             core_print.clj:53 clojure.core/print-sequential
            core_print.clj:198 clojure.core/fn
              MultiFn.java:231 clojure.lang.MultiFn.invoke
                 core.clj:3392 clojure.core/pr-on
                 core.clj:3404 clojure.core/pr
                  AFn.java:154 clojure.lang.AFn.applyToHelper
               RestFn.java:132 clojure.lang.RestFn.applyTo
                  core.clj:624 clojure.core/apply
                 core.clj:4373 clojure.core/pr-str
               RestFn.java:408 clojure.lang.RestFn.invoke
                   eval.clj:69 lighttable.nrepl.eval/clean-serialize
               RestFn.java:423 clojure.lang.RestFn.invoke
                   eval.clj:82 lighttable.nrepl.eval/->result
                  AFn.java:156 clojure.lang.AFn.applyToHelper
                  AFn.java:144 clojure.lang.AFn.applyTo
                  core.clj:626 clojure.core/apply
                 core.clj:2468 clojure.core/partial[fn]
               RestFn.java:408 clojure.lang.RestFn.invoke
                 core.clj:2559 clojure.core/map[fn]
               LazySeq.java:40 clojure.lang.LazySeq.sval
               LazySeq.java:49 clojure.lang.LazySeq.seq
                   RT.java:484 clojure.lang.RT.seq
                  core.clj:133 clojure.core/seq
                 core.clj:2595 clojure.core/filter[fn]
               LazySeq.java:40 clojure.lang.LazySeq.sval
               LazySeq.java:49 clojure.lang.LazySeq.seq
                  Cons.java:39 clojure.lang.Cons.next
                   RT.java:598 clojure.lang.RT.next
                   core.clj:64 clojure.core/next
                 core.clj:2856 clojure.core/dorun
                 core.clj:2871 clojure.core/doall
                  eval.clj:126 lighttable.nrepl.eval/eval-clj
               RestFn.java:442 clojure.lang.RestFn.invoke
                  eval.clj:192 lighttable.nrepl.eval/eval2659[fn]
                  AFn.java:152 clojure.lang.AFn.applyToHelper
                  AFn.java:144 clojure.lang.AFn.applyTo
                  core.clj:624 clojure.core/apply
                 core.clj:1862 clojure.core/with-bindings*
               RestFn.java:425 clojure.lang.RestFn.invoke
                  eval.clj:177 lighttable.nrepl.eval/eval2659[fn]
                  eval.clj:176 lighttable.nrepl.eval/eval2659[fn]
              MultiFn.java:227 clojure.lang.MultiFn.invoke
                   core.clj:98 lighttable.nrepl.core/queued[fn]
                 core.clj:2402 clojure.core/comp[fn]
    interruptible_eval.clj:138 clojure.tools.nrepl.middleware.interruptible-eval/run-next[fn]
                   AFn.java:22 clojure.lang.AFn.run
   ThreadPoolExecutor.java:895 java.util.concurrent.ThreadPoolExecutor$Worker.runTask
   ThreadPoolExecutor.java:918 java.util.concurrent.ThreadPoolExecutor$Worker.run
               Thread.java:695 java.lang.Thread.run

I'm guessing it's because the test is outside of the openGL context of the game?

Is there a strategy I can use to get around this? Perhaps defscreening a test-screen? Some other approach?

Integrated CES to replace entities?

Hey @oakes, first off, thanks for all your work on play-clj! I've been hoping to dive into a game side-project for a while and was happy to see a decent Clojure wrapper ready to use.

That said, I'd like to model my game using a component-entity system like brute. I've looked over the code for Mark's brute-play-pong project and while it looks fairly straightforward to integrate play-clj and brute, I thought it might be possible to integrate the two libraries further.

Do you have any interest in seeing brute integrated into play-clj upstream? I can't think of a way to do it that wouldn't break backwards compatibility, but the actual changes to play-clj don't seem like they'd be terrible. Brute uses records/types/maps/etc to define components, so a brute entity could have a component defined by an existing play-clj entity record (ActorEntity, ModelEntity, etc). Any place a play-clj function takes an play-clj entity, you'd just have to pass in the proper brute component instance for that brute entity. I think with some careful renaming/refactoring, code changes might be minimal.

At that point, instead of vectors of entities, screen functions could take and return brute system maps. This seems like a clean way to integrate the two, though it would obviously break existing entity semantics in existing projects. Not sure if that's something you'd ever consider at this point.

I'd love to hear any thoughts you might have. If this is of no interest to you, no problem! 😄

Thanks again for your efforts!

Disposables and possible memory leaks

I've been looking through the classes that implement Disposable, and it seems like there are some functions to instantiate objects which could lead to memory leaks.

It would be nice to just leave warnings in the docs like the ones for Pixmap and screenshot!. The problem is some Disposables can be managed (ex: Cubemap, Texture), so they will automatically be disposed/could cause problems if dispose is called on them.

Edit: It seems that management is defined by GLTexture and might be unrelated to disposing.

Here's a (non-exhaustive) list of possible offenders I've gathered from searching the repo:

I'm not sure how we should solve this due to the number of classes that need to be disposed. I could add a dispose! function in the utils namespace, but users would still need to be diligent enough to call it. It could use reflection to make sure the object is a Disposable instance else no-op. Another thing dispose! could do is check if the object is managed and also no-op then. It might be nice to have that utility so you can pass around Disposables and have a unified way to free their memory.

I wouldn't mind going through to add warnings the docs of individual functions as well.

Independent rotation for entities within a bundle?

I have a bundle entity where I'd like both sub-entities to move in unison, but for only one of them to rotate when I change :angle. Is that doable?

To give an example: imagine a game with tanks that can only move backwards and forwards, but with rotating gun turrets. Would that be achievable with a bundle, or would it need to be handled in another way?

Schema ?

Hi,

Since the screen and entities are maps or vector of maps or records, do you consider using Prismatic/schema or something similar ? It would at least provide a good and always up-to-date documentation, and could also be used for testing.

Persistent SIGSEGV error

I have tried this in Java 6, 7 and 8. I am running play-clj 0.3.5 on Mac OS 10.9. Each time I run lein run in desktop, I get an error. In Java 8 it looks like this:

desktop pmm21$ lein run
Compiling our-first-game.core.desktop-launcher
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fff92023acf, pid=26865, tid=39427
#
# JRE version: Java(TM) SE Runtime Environment (8.0_05-b13) (build 1.8.0_05-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.5-b02 mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# C  [CoreFoundation+0x12acf]  CFStringGetLength+0xf
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /Users/pmm21/my_apps/our-first-game/desktop/hs_err_pid26865.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.

In Java 6, the error displays a little differently, as invalid memory access.

Sorry if this is not enough information; I am not experienced debugging this kind of issue with Java.

REPL development in Light Table

I know that play-clj is built to work out-of-the-box in Nightcode, but I've been trying to get the REPL workflow up-and-running in Light Table. So far I haven't been successful.

I can connect a lein-light-nrepl within LT (by evaluating a play-clj CLJ file), which launches the game window, but when I make code changes and re-evaluate them, the game isn't updated. I have to close the game window and relaunch it with another evaluation to see the changes.

REPL development works when I launch the project from a terminal using lein repl, so I think the problem is specific to Light Table. Do you know what I'm missing to get it working there?

Cheers,
James

Use cases for on-gl

When should on-gl be used? I've noticed that you need to use it from the repl to call screenshot! and set-screen!.

Do the functions given to defscreen get executed in the gl context automatically? If so, how? If not, calls to screenshot! will need to be wrapped in on-gl or it with throw an exception due to not having the gl context (from the call to ScreenUtils/get...Pixels). I thought I would ask, because I'm not sure how to test it other than building an uberjar for play-clj and running one of the example projects with it.

Is there a way to tell which functions will need the gl context without trying them manually?

Reflection warnings + UnsatisfiedLinkError, possible Java8 + OS X 10.9 issue

This is what happens when I try to build/run super-koalio, but the same thing happens for e.g. dungeon-crawler. I'm filing it here instead of on play-clj-examples because I'm convinced it's a general libgdx issue (and therefore perhaps not even a good issue for play-clj...). I think this might be a consequence of JRE8, but I'm not sure, and I don't know if it means my box is just messed up:

[desktop] lein uberjar                                                                                                                                                                11:45:56  ☁  master ☀
Compiling super-koalio.core.desktop-launcher
Reflection warning, play_clj/core_utils.clj:36:3 - reference to field newInstance can't be resolved.
Reflection warning, play_clj/core_utils.clj:58:5 - call to scheduleTask can't be resolved.
Reflection warning, play_clj/core_utils.clj:61:5 - call to scheduleTask can't be resolved.
Reflection warning, play_clj/core_utils.clj:64:5 - call to scheduleTask can't be resolved.
Reflection warning, play_clj/core_utils.clj:72:5 - reference to field stop can't be resolved.
Reflection warning, play_clj/g2d.clj:62:7 - call to com.badlogic.gdx.graphics.g2d.NinePatch ctor can't be resolved.
Reflection warning, play_clj/g2d.clj:66:9 - call to com.badlogic.gdx.graphics.g2d.NinePatch ctor can't be resolved.
Reflection warning, play_clj/ui.clj:170:17 - call to com.badlogic.gdx.scenes.scene2d.ui.CheckBox ctor can't be resolved.
Reflection warning, play_clj/ui.clj:192:17 - call to com.badlogic.gdx.scenes.scene2d.ui.Dialog ctor can't be resolved.
Reflection warning, play_clj/ui.clj:242:7 - call to com.badlogic.gdx.scenes.scene2d.ui.Image ctor can't be resolved.
Reflection warning, play_clj/ui.clj:263:17 - call to com.badlogic.gdx.scenes.scene2d.ui.ImageButton ctor can't be resolved.
Reflection warning, play_clj/ui.clj:285:17 - call to com.badlogic.gdx.scenes.scene2d.ui.ImageTextButton ctor can't be resolved.
Reflection warning, play_clj/ui.clj:311:7 - call to com.badlogic.gdx.scenes.scene2d.ui.Label ctor can't be resolved.
Reflection warning, play_clj/ui.clj:334:17 - call to com.badlogic.gdx.scenes.scene2d.ui.ScrollPane ctor can't be resolved.
Reflection warning, play_clj/ui.clj:356:17 - call to com.badlogic.gdx.scenes.scene2d.ui.SelectBox ctor can't be resolved.
Reflection warning, play_clj/ui.clj:382:5 - call to com.badlogic.gdx.scenes.scene2d.ui.Slider ctor can't be resolved.
Reflection warning, play_clj/ui.clj:446:17 - call to com.badlogic.gdx.scenes.scene2d.ui.TextButton ctor can't be resolved.
Reflection warning, play_clj/ui.clj:468:17 - call to com.badlogic.gdx.scenes.scene2d.ui.TextField ctor can't be resolved.
Reflection warning, play_clj/ui.clj:490:17 - call to com.badlogic.gdx.scenes.scene2d.ui.Tree ctor can't be resolved.
Reflection warning, play_clj/ui.clj:533:17 - call to com.badlogic.gdx.scenes.scene2d.ui.Window ctor can't be resolved.
Compiling super-koalio.core.desktop-launcher
Created /Users/lvh/Code/play-clj-examples/super-koalio/desktop/target/super-koalio-0.0.1-SNAPSHOT.jar
Created /Users/lvh/Code/play-clj-examples/super-koalio/desktop/target/super-koalio-0.0.1-SNAPSHOT-standalone.jar
[desktop] java -jar target/super-koalio-0.0.1-SNAPSHOT-standalone.jar                                                                                                                 11:46:12  ☁  master ☀
Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't load library: /var/folders/dd/lh02zlnn1hg7cgs85w8qq6c00000gn/T/libgdxlvh/75260a42/liblwjgl.dylib
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1817)
    at java.lang.Runtime.load0(Runtime.java:809)
    at java.lang.System.load(System.java:1083)
    at org.lwjgl.Sys$1.run(Sys.java:70)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.lwjgl.Sys.doLoadLibrary(Sys.java:66)
    at org.lwjgl.Sys.loadLibrary(Sys.java:95)
    at org.lwjgl.Sys.<clinit>(Sys.java:112)
    at org.lwjgl.openal.AL.<clinit>(AL.java:59)
    at com.badlogic.gdx.backends.openal.OpenALAudio.<init>(OpenALAudio.java:70)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication.<init>(LwjglApplication.java:82)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication.<init>(LwjglApplication.java:64)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication.<init>(LwjglApplication.java:56)
    at super_koalio.core.desktop_launcher$_main.invoke(desktop_launcher.clj:7)
    at clojure.lang.AFn.applyToHelper(AFn.java:159)
    at clojure.lang.AFn.applyTo(AFn.java:151)
    at super_koalio.core.desktop_launcher.main(Unknown Source)

I found someone with a similar setup who appears to have the same problem on StackOverflow: https://stackoverflow.com/questions/21028507/libgdx-project-cant-load-library-liblwjgl-dylib

Missing hook to manage fading out during render ?

Hi,

I wanted to use Batch.setColor() with the alpha paramter to make an entity fade out. When reading the code in play-clj, I noticed that the draw method lacks a hook the manipulate the Batch. As I don't want to use this method for all entities but only some of them, I can't just retrieve the batch from the renderer then set its color. Am I right ?

NPE when trying to load texture

I've tried this in 0.3.10-SNAPSHOT and 0.3.9 with the same effect. Here are the steps to reproduce the issue:

  • lein new play-clj projectname
  • copy the png-file with texture to projectname/desktop/resources/filename.png
  • fire up the REPL (tried this in both CIDER and lein repl)
  • (texture "filename.png")
  • NullPointerException com.badlogic.gdx.graphics.Texture.<init> (Texture.java:88)

When I try to set up an asset-manager using the following code:

(set-asset-manager! (asset-manager))
(texture "filename.png")

the error message looks like this:

NullPointerException   com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver.resolve (InternalFileHandleResolver.java:26)

hello-world tutorial: move command not found

In the hello-world tutorial created using Leiningen, when I add the move commands under :on-key-down, the error is

clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Unable to      resolve symbol: move in this context

The header is

(ns hello-world.core
  (:require [play-clj.core :refer :all]
            [play-clj.g2d :refer :all]
            [play-clj.ui :refer :all]))

Vsync is not found

(graphics! :set-vsync false)

causes this:

Exception in thread "LWJGL Application" java.lang.IllegalArgumentException: No matching method found: setVsync for class com.badlogic.gdx.backends.lwjgl.LwjglGraphics

Stopping shapes rotating every frame

I would like to initialise some of my shapes with a rotation of 180 degrees, but constructing a shape with :rotate 0 0 1 180 causes it to rotate 180 degrees every frame.

Is it possible to just apply an initial rotation?

java.lang.ExceptionInInitializerError (probably OS X + JRE8 again)

Just reporting these here even though I have my doubts it's actually a play-clj bug. I guess I'm downgrading to a JDK/JRE that works...

[minimal-3d] cd desktop                                                                                                                                                               15:08:35  ☁  master ☀
[desktop] lein run                                                                                                                                                                    15:08:38  ☁  master ☀
Reflection warning, play_clj/core_utils.clj:36:3 - reference to field newInstance can't be resolved.
Reflection warning, play_clj/core_utils.clj:58:5 - call to scheduleTask can't be resolved.
Reflection warning, play_clj/core_utils.clj:61:5 - call to scheduleTask can't be resolved.
Reflection warning, play_clj/core_utils.clj:64:5 - call to scheduleTask can't be resolved.
Reflection warning, play_clj/core_utils.clj:72:5 - reference to field stop can't be resolved.
Reflection warning, play_clj/math.clj:51:5 - call to com.badlogic.gdx.math.Bezier ctor can't be resolved.
Reflection warning, play_clj/math.clj:318:5 - call to com.badlogic.gdx.math.Plane ctor can't be resolved.
Reflection warning, play_clj/g2d.clj:62:7 - call to com.badlogic.gdx.graphics.g2d.NinePatch ctor can't be resolved.
Reflection warning, play_clj/g2d.clj:66:9 - call to com.badlogic.gdx.graphics.g2d.NinePatch ctor can't be resolved.
Reflection warning, play_clj/ui.clj:170:17 - call to com.badlogic.gdx.scenes.scene2d.ui.CheckBox ctor can't be resolved.
Reflection warning, play_clj/ui.clj:192:17 - call to com.badlogic.gdx.scenes.scene2d.ui.Dialog ctor can't be resolved.
Reflection warning, play_clj/ui.clj:242:7 - call to com.badlogic.gdx.scenes.scene2d.ui.Image ctor can't be resolved.
Reflection warning, play_clj/ui.clj:263:17 - call to com.badlogic.gdx.scenes.scene2d.ui.ImageButton ctor can't be resolved.
Reflection warning, play_clj/ui.clj:285:17 - call to com.badlogic.gdx.scenes.scene2d.ui.ImageTextButton ctor can't be resolved.
Reflection warning, play_clj/ui.clj:311:7 - call to com.badlogic.gdx.scenes.scene2d.ui.Label ctor can't be resolved.
Reflection warning, play_clj/ui.clj:334:17 - call to com.badlogic.gdx.scenes.scene2d.ui.ScrollPane ctor can't be resolved.
Reflection warning, play_clj/ui.clj:356:17 - call to com.badlogic.gdx.scenes.scene2d.ui.SelectBox ctor can't be resolved.
Reflection warning, play_clj/ui.clj:382:5 - call to com.badlogic.gdx.scenes.scene2d.ui.Slider ctor can't be resolved.
Reflection warning, play_clj/ui.clj:446:17 - call to com.badlogic.gdx.scenes.scene2d.ui.TextButton ctor can't be resolved.
Reflection warning, play_clj/ui.clj:468:17 - call to com.badlogic.gdx.scenes.scene2d.ui.TextField ctor can't be resolved.
Reflection warning, play_clj/ui.clj:490:17 - call to com.badlogic.gdx.scenes.scene2d.ui.Tree ctor can't be resolved.
Reflection warning, play_clj/ui.clj:533:17 - call to com.badlogic.gdx.scenes.scene2d.ui.Window ctor can't be resolved.
Exception in thread "main" java.lang.ExceptionInInitializerError
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:340)
    at clojure.lang.RT.loadClassForName(RT.java:2098)
    at clojure.lang.RT.load(RT.java:430)
    at clojure.lang.RT.load(RT.java:411)
    at clojure.core$load$fn__5018.invoke(core.clj:5530)
    at clojure.core$load.doInvoke(core.clj:5529)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$load_one.invoke(core.clj:5336)
    at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
    at clojure.core$load_lib.doInvoke(core.clj:5374)
    at clojure.lang.RestFn.applyTo(RestFn.java:142)
    at clojure.core$apply.invoke(core.clj:619)
    at clojure.core$load_libs.doInvoke(core.clj:5413)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.core$apply.invoke(core.clj:619)
    at clojure.core$require.doInvoke(core.clj:5496)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at minimal_3d.core.desktop_launcher$loading__4910__auto__.invoke(desktop_launcher.clj:1)
    at minimal_3d.core.desktop_launcher__init.load(Unknown Source)
    at minimal_3d.core.desktop_launcher__init.<clinit>(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:340)
    at clojure.lang.RT.loadClassForName(RT.java:2098)
    at clojure.lang.RT.load(RT.java:430)
    at clojure.lang.RT.load(RT.java:411)
    at clojure.core$load$fn__5018.invoke(core.clj:5530)
    at clojure.core$load.doInvoke(core.clj:5529)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$load_one.invoke(core.clj:5336)
    at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
    at clojure.core$load_lib.doInvoke(core.clj:5374)
    at clojure.lang.RestFn.applyTo(RestFn.java:142)
    at clojure.core$apply.invoke(core.clj:619)
    at clojure.core$load_libs.doInvoke(core.clj:5413)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.core$apply.invoke(core.clj:619)
    at clojure.core$require.doInvoke(core.clj:5496)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at user$eval5$fn__7.invoke(form-init8116214386238851599.clj:1)
    at user$eval5.invoke(form-init8116214386238851599.clj:1)
    at clojure.lang.Compiler.eval(Compiler.java:6619)
    at clojure.lang.Compiler.eval(Compiler.java:6609)
    at clojure.lang.Compiler.load(Compiler.java:7064)
    at clojure.lang.Compiler.loadFile(Compiler.java:7020)
    at clojure.main$load_script.invoke(main.clj:294)
    at clojure.main$init_opt.invoke(main.clj:299)
    at clojure.main$initialize.invoke(main.clj:327)
    at clojure.main$null_opt.invoke(main.clj:362)
    at clojure.main$main.doInvoke(main.clj:440)
    at clojure.lang.RestFn.invoke(RestFn.java:421)
    at clojure.lang.Var.invoke(Var.java:419)
    at clojure.lang.AFn.applyToHelper(AFn.java:163)
    at clojure.lang.Var.applyTo(Var.java:532)
    at clojure.main.main(main.java:37)
Caused by: java.lang.NullPointerException
    at clojure.core$add_watch.invoke(core.clj:1967)
    at play_clj.core$defscreen_STAR_.invoke(core.clj:64)
    at minimal_3d.core$fn__915.invoke(core.clj:9)
    at minimal_3d.core__init.load(Unknown Source)
    at minimal_3d.core__init.<clinit>(Unknown Source)
    ... 55 more

A better approach for rotating bundled shapes?

I have an entity that is comprised of three shapes and a label bundled together with bundle that looks like this (ignore the hexagon board underneath):

Entity

To rotate the entity I'm doing:

(shape! (first (:entities rotated-element)) :rotate 0 0 1 rotation)
(shape! (second (:entities rotated-element)) :rotate 0 0 1 rotation)
(shape! (nth (:entities rotated-element) 2) :rotate 0 0 1 rotation)

Is there a better approach, which avoids this ugly repetition?

Also, is there a way to enable MSAA or some other form of anti-aliasing to make the shape edges look better?

Combining :line and :filled shapes

Is it possible to combine :line and :filled shapes in one shape entity?

I'd like to create a hexagon with a :line :polygon border and then use multiple :filled :triangles to create the fill. However, when I try and combine the two I get: "java.lang.IllegalArgumentException: No matching field found: filled for class com.badlogic.gdx.graphics.glutils.ShapeRenderer"

Do I need to keep the two types of shapes as separate entities, or am I just trying to combine them incorrectly?

key-pressed? macro

Hi,
i am asking myself, why is 'key-pressed?' a macro? I'm not very familiar with clojure macro's and therefore i wasn't able to get code like this to run.

(key-pressed? (:my-key {:my-key :a} ) )

Is there a workaround?

Basic Changelog

This is under pretty active development which is awesome, but it'd be cool to get a brief overview of any major / breaking changes between snapshots.

(box-2d) taking too long ?

We're initiliazing a game with a Box2d world, then creating a body. Problem : when creating the body with (add-body screen (body-def :dynamic)), this function needs a :world in the screen map, but (box-2d) did not return one yet and the following exception occurs java.lang.Exception: The keyword :world is not found.. Only when our screen-wrapper function launches, sleeps a bit then re-run our the game the :world key is not empty.

I tried playing with the third param of (box-2d) (sleep) with no success. Adding a dumb (Thread/sleep 5000) changes nothing.

Strange, changing an atom is synchronous, but it appears to be asynchronous and taking too long, so the code following executes with an empty :world key.

Code that produces the bug : https://github.com/LD30-Lions/con-world/blob/bf505ca0ffebeb4ea9618bbff9c6604c31350605/desktop/src-common/con_world/core.clj#L17
Bug happens in 2 machines, one OSX, on Linux Arch. Both on IntelliJ with Cursive.

Building for HTML5

Hello,

I'm just starting to checkout play-clj. Can I build for HTML too? It seams to be possible from libgdx.

Thanks,

Tiled ObjectLayers not implemented correctly

I was looking into spawning enemies based on objects placed via an object layer in tiled. It appears that when the tiled map is loaded, the object layer gets created as a MapLayer, not a TiledMapTileLayer.

Because of this, it's not possible to use the object layer via any of the play-clj methods. The following works:

(tiled-map-layer (-> main-screen :screen deref) "entities")

However, it doesn't return a TiledMapTileLayer per the docs, but a MapLayer. Thus, the following errors out:

(tiled-map-layer! (tiled-map-layer (-> main-screen :screen deref) "entities") :get-properties) 

[none of the TiledMapTileLayer methods work. error: Cannot cast com.badlogic.gdx.maps.MapLayer to com.badlogic.gdx.maps.tiled.TiledMapTileLayer]

Additionally it causes even more generic methods to fail, such as:

(tiled-map-layer-names (-> main-screen :screen deref))

which crashes once it gets to the object layer.

Labels always rendering beneath shapes?

I'd like to add some text on top of my shape entities, but when I bundle a label with the shapes, the label renders beneath the shapes (even though it's last in the bundle's :entities vector).

To see if this was just a problem with bundle, I also added a label to the end of main-screen's elements vector - same deal there, the label renders beneath the shapes.

Is this a bug, am I doing something wrong, or is rendering labels in a separate screen the right way to get them above the shapes?

Re-evaluating defscreen within a REPL session

Is it possible to re-evaluate defscreen within a REPL session in a way that newly added functions (:on-key-down, :on-timer, etc.) are evaluated and the game doesn't need to be restarted?

To clarify a little: I'm using Light Table, and re-evaluating core.clj works perfectly when I make changes to my helper functions, or even to existing defscreen functions (like :on-show). But when I add a new function to defscreen, such as :on-timer, no amount of re-evaluating the namespace seems to enable the new function within the current REPL session. However, as soon as I stop and re-launch the game the new function is enabled as expected.

I'm guessing this might have something to do with defscreen being a macro? But I think the most likely scenario is that I'm making a mistake with my workflow. What might I be doing wrong?

Y-Coordinate of on-touch-down events is inverted on android but not on linux desktop

Attaching a listener to :on-touch-down and logging the output Y coordinate from the event on an Ubuntu 14.04 running Oracle JVM 7 and on Android reveals that in the former case, the y coordinate is zero at the top of the screen and increases towards the bottom of the screen, while on android, the Y coordinate is maximal at the top of the screen and decreases as one moves down.

Presumably this is a bug in the desktop play-clj, since the documentation indicates that coordinates should start at 0,0 at the bottom left. Rendering does seem to respect this coordinate system on the desktop, but mouse clicks are not translated.

Is there a quick fix I can put it? For instance, a function I can invoke to detect the platform from Clojure?

Uninformative documentation

Awesome library. However, the docstring "Internal use only," isn't very informative as to what the function actually does, and ignores the (safer) clojure function

(defn- ...)

which actually makes the defined function non-public. I'll submit a patch with my modifications, but please change the docstrings to reflect their actual operation.

Emacs workflow questions

I have been using emacs messing around with play-clj, and a pretty basic question has come up. All do respect to the Nightmod and Nightcode editors, I am a bit more familiar with emacs and I feel like the answers to these questions may be useful to others as well.

When using cider repl and eval-ing (-main) it boots up the app, but I find that if I make a change, I don't know how to get that change to update in the launched app. If I eval (-main) in the cider repl again, I get an error. IllegalStateException Only one OpenAL context may be instantiated at any one time. org.lwjgl.openal.AL.create (AL.java:113), I have tried C-c C-k on both the desktop launcher and the src-common/hello_world/core.clj. This doesn't seem to update the app either.

:on-timer only passes initial entities?

I'm using 0.3.5-SNAPSHOT and have a problem where the :on-timer function appears to be passing the initial entities vector, rather than the current state (like I was expecting). Is this a bug with :on-timer, or a misunderstanding on my part?

Is this correct?

Sorry if I put this in the wrong place, I'm currently having some issues with: https://gist.github.com/zackp30/8d128f8c6317f982f8bb

Exception in thread "LWJGL Application" com.badlogic.gdx.utils.GdxRuntimeException: java.lang.Exception: The keyword :align is not found.
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:120)
Caused by: java.lang.Exception: The keyword :align is not found.
    at play_clj.utils$throw_key_not_found.invoke(utils.clj:10)
    at play_clj.ui$eval1741$fn__1743.invoke(ui.clj:139)
    at clojure.lang.MultiFn.invoke(MultiFn.java:227)
    at play_clj.ui$add_BANG_.doInvoke(ui.clj:165)
    at clojure.lang.RestFn.applyTo(RestFn.java:139)
    at clojure.core$apply.invoke(core.clj:626)
    at play_clj.ui$create_group.invoke(ui.clj:170)
    at play_clj.ui$table_STAR_.invoke(ui.clj:525)
    at numberz.core$eval2052$fn__2072.invoke(core.clj:10)
    at clojure.lang.Var.invoke(Var.java:383)
    at play_clj.core$defscreen_STAR_$execute_fn_BANG___1471$fn__1474.invoke(core.clj:83)
    at clojure.lang.AFn.applyToHelper(AFn.java:152)
    at clojure.lang.AFn.applyTo(AFn.java:144)
    at clojure.lang.AFunction$1.doInvoke(AFunction.java:29)
    at clojure.lang.RestFn.invoke(RestFn.java:397)
    at play_clj.core$wrapper.invoke(core.clj:56)
    at play_clj.core$defscreen_STAR_$execute_fn_BANG___1471.doInvoke(core.clj:85)
    at clojure.lang.RestFn.invoke(RestFn.java:410)
    at play_clj.core$defscreen_STAR_$fn__1497.invoke(core.clj:113)
    at clojure.lang.AFn.applyToHelper(AFn.java:152)
    at clojure.lang.AFn.applyTo(AFn.java:144)
    at clojure.core$apply.invoke(core.clj:624)
    at play_clj.core$set_screen_BANG_$run_fn_BANG___1527.doInvoke(core.clj:523)
    at clojure.lang.RestFn.invoke(RestFn.java:410)
    at play_clj.core$set_screen_BANG_$reify__1535.show(core.clj:528)
    at com.badlogic.gdx.Game.setScreen(Game.java:61)
    at play_clj.core.proxy$com.badlogic.gdx.Game$ff19274a.setScreen(Unknown Source)
    at play_clj.core$set_screen_BANG_.doInvoke(core.clj:524)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at numberz.core$eval2090$fn__2091.invoke(core.clj:20)
    at play_clj.core$defgame_STAR_$fn__1516.invoke(core.clj:508)
    at play_clj.core.proxy$com.badlogic.gdx.Game$ff19274a.create(Unknown Source)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:136)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)


on-touch-down y coordinate for mouse position is zero at top of screen

While the primitives for specifying position in the rest of play-clj are in a coordinate system where zero is the bottom of the screen, mouse coordinates arrive from :on-touch-down event listener such that zero is at the top of the screen.

This should probably be at least documented somewhere, but ideally the coordinates should match those used for drawing.

Creating tiled maps in-memory, instead of from paths?

I'm trying to create a hex map. I can't do so from a file, because the versions of Tiled that actually supported hex map editing appear to have been lost in history. If I want to create a regular tiled map (not from a file), do I just use clojure's java interop to create these objects and pass them along? It appears tiled-map*, which all the helper functions use, was written with this in mind, because it acts as the identity function when its argument isn't a string. This just isn't the standard documented way of using those functions. Right?

Would there be any desire perhaps to just have nullary versions of the same functions create empty maps? That does leave us with the issue of the scale argument... I was kind of expecting it to work more like:

(orthogonal-tiled-map (load-map "level1.tmx") (/ 1 8))

rather than:

(orthogonal-tiled-map "level1.tmx" (/ 1 8))

But perhaps it is too late to mess with these APIs?

[request] add support for the (pixmap) and (width height format) constructors for pixmaps.

It's not insurmountable, but it's unpleasant to have to dive into native to create a pixmap from scratch, and it's really unpleasant to have to call operations one at a time with pixmap! since you can't feed an existing one in. How do you feel about adding support for this to bring pixmaps up to par with textures? If you think it's generally a good idea but don't have the free time, I can take a stab at it. Thanks!

on-key-typed not ongoing

Hi,
i am using a windows pc with nightcode 0.1.1 and i have the problem, that :on-key-typed does not react properly.
This means: When holding a button, this key-event is realized. But just once! After a short time my program notices that the button is still pressed and continues.

My Code:

  :on-key-typed 
  (fn [screen entities]
    (print (key-pressed? :m)) ;when m is pressed you can read "true"!
    (move-ball entities))

'move-ball' just moves a circle from left to right, when m is pressed

(defn move-ball [entities]
         (for [entitie entities]
           (if (:ball? entitie)
             (assoc entitie :x (mod (+ (:x entitie) 10) 300))
             e)))

When i hit (and hold) 'm' the ball makes a little move and after a short time it starts moving constantly. But the hole time you can read "true".

Is this some kind of windows problem?

Creating a filled polygon

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!

Bug on timer resume ?

Hi,

I noticed something strange while developping on desktop. In a game where I have a timer, when the game loses focus the :on-pause function gets called (for instance when I go back to my editor). Then I click in the game window and the :on-resume function gets called. Let's call the delta of time between losing focus and regaining focus D. When the :on-resume is called, the timer is not resumed instantly. Instead it's started after the delta D. Weird, huh ?

By the way, the generated docs of play-clj mentions that :on-pause and :on-resume are called only on mobile but they're called on my desktop environment during dev.

game example doesn't work with lein uberjar

I downloaded the zip file from play-clj-examples and extracted a game example. While I was able to run the platform game in lein repl or lein run, I couldn't get it to run after executing lein uberjar. Instead, I receive this error:

C:...platform game> java -jar target\super-koalio-0.0.1-SNAPSHOT.jar
Exception in thread "main" java.lang.NoClassDefFoundError: clojure/lang/IFn
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2531)
        at java.lang.Class.getMethod0(Class.java:2774)
        at java.lang.Class.getMethod(Class.java:1663)
        at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:494)
        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:486)
Caused by: java.lang.ClassNotFoundException: clojure.lang.IFn
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        ... 6 more

Greg

draw!

I can't find a description of (draw! screen entities) in the docs at oakes.github.io/play-clj or nightmod. Draw! is referenced within the description of (render! screen entities).

Screenshots

I would like to submit an enhancement to add support for screen shots. I have a basic proof of concept to show that it is possible, but I've hit a couple of roadblocks:

First of all, ScreenUtils/getFrameBufferPixmap dumps the framebuffer upside down:
Screenshot of Super Koalio
I thought I might be able to get around this by using ScreenUtils/getFrameBufferTexture (which automatically flips it), but I just ended up freezing the connected game.

My approach was something along these lines:

  1. Get the TextureRegion from ScreenUtils/get...Texture
  2. TextureRegion/getTexture
  3. Texture/getTextureData
    4a. TextureData/prepare (required call before calling consumePixmap)
    4b. TextureData/consumePixmap
  4. PixmapIO/writePNG (same as the first PoC)

The obstacle here is that Textures and Pixmaps are stored on the native heap (which I think also means the working part of the PoC has a memory leak because of the Pixmap). The Texture returned from TextureRegion/getTexture is not a managed Texture, so we manually have to call Texture/dispose to free the memory. The same goes for Pixmap, because they both implement Disposable.

I was attempting to return the Texture and Pixmap in a Clojure map from the the second version of capture-screen!, so they could be disposed after the screenshot was written to disk. May be due to this running on the gl thread a Clojure map can't be used? I'm relatively new to Clojure so I'm not sure if I'm doing the Java interop correctly, and I'm not sure how to get error messages out of the gl thread. Something that I'm doing differently in the second attempt is causing the gl thread to freeze.

Here are steps to run the working screenshot PoC at the repl from within the super-koalio example game:
Steps to reproduce at repl

Using the gesture functions in defscreen

Before I knew about the gesture functions I was using :on-touch-down and :on-touch-up with some custom timing code to see if the user had done a tap or a long-press. It worked well, but the extra code and complexity was a little ugly. Now that I've discovered and switched to :on-tap and :on-long-press I'm happy about the cleaner code, but I have a couple of problems:

  1. I can't figure out how to change the timing for a long-press. I found GestureDetector, whose setLongPressSeconds() looks promising. Is there a nice way to access this via play-clj?

  2. I was expecting that :on-tap and :on-long-press would be mutually exclusive, i.e. that either one or the other would fire, but not both. However, after lifting from a long press, the :on-tap function also gets called. I found this discussion which indicates that returning true from touch events marks it as "handled", so it doesn't get passed onto peer handlers. It that something I can make use of with play-clj, or is there another approach?

Wrong coordinate system in :on-touch-down

I tried to draw shapes directly under the cursor when mouse is clicked, with the following code in my defscreen function:

    :on-touch-down
    (fn [screen entities]
      (println "added new shape")
      (let [x (:input-x screen)
            y (:input-y screen)]
        (conj entities (assoc (shape :filled
                                     :set-color (color :green)
                                     :rect 0 0 10 10)
                         :x x
                         :y y)))))

But it seems that input and screen coordinate systems differ - when I click in the bottom of the screen, the squares are appearing in the top, and vice versa. The 0, 0 point in input coordinate system is different than in drawing one.

Could not load template, failed with: java.lang.ExceptionInInitializerError, compiling:(leiningen/droid/manifest.clj:1:1)

Hi guys, I didn't know where to put this given I finally solved my issue, but I thought it might be helpful for others clojure beginners out there, by having the error indexed in google by posting it here :)

$ lein new play-clj apples
Could not load template, failed with: java.lang.ExceptionInInitializerError, compiling:(leiningen/droid/manifest.clj:1:1)

Took me some time but I finally thought of updating leiningen by running lein upgrade which solved the issue and I now have my project generated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.