defun-games / claylib

A Common Lisp 2D/3D game toolkit built on top of Raylib 4.5.
zlib License
74 stars 4 forks source link

Fonts doesn't load properly second time around..? #62

Closed simendsjo closed 1 year ago

simendsjo commented 1 year ago

Loading examples works fine. I press esc to stop the demo. When running the example again, it looks like fonts isn't loaded. For many examples, the text doesn't show at all, while on raylib-fonts, some "placeholders" are shown. I get no errors.

EDIT: I'm testing commit d0e8e13 on Linux.

image

shelvick commented 1 year ago

Some examples do behave weirdly if you run them twice in a row, due to how we're defining the scenes with defparameter and running GC after. If you load the example again it should work.

Known issue but not a bug in Claylib per se. I'll rework the examples at some point to deal with it.

simendsjo commented 1 year ago

Seems like the current setup is problematic for hotreloading too..? Setting *scene* to a new value breaks, and I guess it's because of the outer with-scenes no longer matches the new *scene* in the game loop. Maybe it should detect changes to scenes and call teardown + setup? This little test works:

(defun main ()
  (with-window (:title "raylib [text] example - raylib fonts")
    (let ((old-scene nil))
      (do-game-loop (:livesupport t)
        ;; First run or scene changed
        (unless (eq old-scene *scene*)
          ;; Scene changed, tear down old
          (when old-scene
            (tear-down-scene old-scene))
          ;; Setup new scene
          (set-up-scene *scene*)
          ;; One-time setup
          (arrange-text (scene-object *scene* 'fonts))
          (setf old-scene *scene*))
        (with-drawing ()
          (draw-scene-all *scene*))))))

The cryptic error:

image

shelvick commented 1 year ago

Yeah, while you can use scenes that way, it wouldn't be my first choice. Scenes in Claylib are kind of like closures. They're meant to be defined upfront, somewhere else in your code, then initialized, and then drawn/manipulated from within your game loop. Anytime you're doing (setf *scene* whatever) you'll need to make sure set-up-scene is called on it before it's drawn. That error you got was because it tried to draw an unyielded future, rather than a game object. If your scene is very simple (no GPU context required, etc.) you can pass :defer-init nil to the scene definition, in which case you don't need set-up-scene.

You might want to look at the basic-screen-manager example. That's probably the simplest example of how to use multiple scenes.

However, the basic-screen-manager example loads every scene upfront. That's fine for a small game but in a large game it will use a lot of memory. So you might need to do something like this:

(with-window ()
  (with-scenes level1 ()
    (do-game-loop ...
  (with-scenes level2 ()
    (do-game-loop ...