oakes / play-clj

A Clojure game library
The Unlicense
940 stars 72 forks source link

Render Strokes Out - Goes Blue Screen #72

Closed Yoshiyuka closed 9 years ago

Yoshiyuka commented 9 years ago

Hello again. I've come across another "issue" which I'm perceiving to be a bug of some sort. In my current project I'm working on the UI of my game and I have things set up so that the namespaces get reloaded whenever a save is detected. I create new UI entities every render frame to see these changes happen in the game window immediately without any input from me after saving the file.

I haven't determined the cause, but certain UI elements will suddenly disappear (for instance, the label I've added to the table element). There's no rhyme or reason to it and I've tried to reproduce it.

My code:

(ns closure.core
  (:require [clojure.pprint :refer [pprint]]
            [play-clj.core :refer :all]
            [play-clj.ui :refer :all]
            [ns-tracker.core :refer :all]
            [cheshire.core :refer :all]
            [closure.ui.main-screen :refer :all]))

(def modified-namespaces
  (ns-tracker ["src" "src-common"]))

(defscreen main-screen
  :on-show
  (fn [screen entities]
    (update! screen :renderer (stage))
    (statistics-table))

  :on-render
  (fn [screen entities]
    (clear!)
    (doseq [ns-sym (modified-namespaces)]
      (require ns-sym :reload))

    (render! screen entities)
    (statistics-table))

  :on-resize
  (fn [screen entities]
    (height! screen (:height screen)))

  :on-key-down
  (fn [screen entities]
    )
  )

(defgame closure
  :on-create
  (fn [this]
    (set-screen! this main-screen)))

(defscreen blank-screen
  :on-render
  (fn [screen entities]
    (clear!)))

(set-screen-wrapper! (fn [screen screen-fn]
                       (try (screen-fn)
                         (catch Exception e
                           (.printStackTrace e)
                           (set-screen! closure blank-screen)))))
(ns closure.ui.main-screen
  (:require [play-clj.core :refer :all]
            [play-clj.ui :refer :all]))

 (defn statistics-table
   []
   (let [title (label "Title" (skin "uiskin.json"))
         charName (label "Name:" (skin "uiskin.json")) 
         body (table [title charName] 
                     :align (align :top-left) 
                     :set-height 600
                     :set-width 125 
                     :debug-all)]
     ;Title Cell
     (label! title :set-alignment (align :center))
     (-> (first (table! body :get-cells))
         (cell! :expand-x)
         (cell! :fill-x))

     body))

After an element disappears, I decided to try resizing the game window to see what happens. I get a blue screen (clear color is black though). I attempt to restart from the repl with (on-gl (set-screen! closure main-screen)) and get the following error dump:

closure.core=> java.lang.Exception: The keyword :camera is not found.
        at play_clj.utils$throw_key_not_found.invoke(utils.clj:10)
        at play_clj.utils$get_obj.invoke(utils.clj:16)
        at play_clj.core$size_BANG_.invoke(core_cameras.clj:47)
        at play_clj.core$height_BANG_.invoke(core_cameras.clj:90)
        at closure.core$eval1660$fn__1693.invoke(core.clj:48)
        at clojure.lang.Var.invoke(Var.java:383)
        at play_clj.core$defscreen_STAR_$execute_fn_BANG___903$fn__906.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 closure.core$eval1740$fn__1741.invoke(core.clj:66)
        at play_clj.core$defscreen_STAR_$execute_fn_BANG___903.doInvoke(core.clj:85)
        at clojure.lang.RestFn.invoke(RestFn.java:486)
        at play_clj.core$defscreen_STAR_$fn__915.invoke(core.clj:125)
        at clojure.lang.AFn.applyToHelper(AFn.java:156)
        at clojure.lang.AFn.applyTo(AFn.java:144)
        at clojure.core$apply.invoke(core.clj:626)
        at play_clj.core$set_screen_BANG_$run_fn_BANG___960.doInvoke(core.clj:517)
        at clojure.lang.RestFn.invoke(RestFn.java:439)
        at play_clj.core$set_screen_BANG_$reify__968.resize(core.clj:529)
        at com.badlogic.gdx.Game.setScreen(Game.java:62)
        at play_clj.core.proxy$com.badlogic.gdx.Game$ff19274a.setScreen(UnknownSource)
        at play_clj.core$set_screen_BANG_.doInvoke(core.clj:518)
        at clojure.lang.RestFn.invoke(RestFn.java:423)
        at closure.core$eval1744$fn__1745.invoke(form-init6236742245141421072.clj:1)
        at clojure.lang.AFn.run(AFn.java:22)
        at com.badlogic.gdx.backends.lwjgl.LwjglApplication.executeRunnables(LwjglApplication.java:240)
        at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:193)
        at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)

Here's a screenshot of the end result: BSOD

Yoshiyuka commented 9 years ago

I've resolved the "missing :camera" error by doing the following (update! screen :camera (orthographic) :renderer (stage))

I'm not sure if this should be necessary though as from what I'm reading in the libgdx docs about Stage, shouldn't it have a camera associated with it already that could be used?

Thanks!

oakes commented 9 years ago

I don't currently use the camera built into the stage, so you must create it explicitly. As for the issue regarding table contents disappearing, I am confused. I cloned your project and ran it, and I see the word "Title". I do not see anything appear and then disappear. Perhaps if you can narrow it down to a smaller amount of code, it would help. Right now, there is a lot of stuff going on.

Yoshiyuka commented 9 years ago

That's the confusing thing for me as well. It might happen or it might not. There's nothing that indicates when or why its going to happen. This is what it looks like when the labels disappear from the table with :debug-all set for the table: Debug

I've removed :on-resize completely and this still happens. Puzzling.

Yoshiyuka commented 9 years ago

Further investigation reveals that the GC is having a heart attack. It's probably not the smartest thing to create a new object every render frame. My guess is that the labels disappear when there's limited-to-no memory left.

oakes commented 9 years ago

Thanks for the follow up.