日曜プログラミング

休日趣味でやってるプログラミング関連記事をダラダラと

cider で play-clj 触り始めました

libGDX を Clojure 上でより使い易くされた play-clj 触り始めました。

github.com

まだサンプル触ってる段階だけど REPL で起動したままいじれるのは 非ゲーム分野では経験済みとは言えゲームでも可能なのが改めて新鮮。

今日は 公式チュートリアル ではフォローされてない emacs+cider 使った時の補足事項みたいなのをいくつか。

cider で REPL

公式チュートリアルで流れは書かれてるがもう少し細かく言えば ソースをいじって REPL から起動したゲーム画面に反映させるには、

  1. namespace をプロジェクトのコアに移動(チュートリアルで言う hello-world.core)
  2. ソースをセーブ
  3. ソースの評価
  4. OpenGL コンテキストスレッドへの再描画命令

の作業が必要で、1. は1回でいいが、2~4 は繰り返す事になり、 これをコマンド+タイピングで毎度やるのはさすがに煩わしい。

なので emacs にコマンドとしてキー1発で呼び出せるものをてきとーに書いた。

(require 'cider)
(defun play-clj-reload ()
  "REPL へ play-clj への反映コマンドを投げる。
   hello-world-game と mainscreen は適時書き換える事。"
  (interactive)
  (cider-interactive-eval
   "(on-gl (set-screen! hello-world-game main-screen))"))

(defun save->eval->reload ()
  "play-clj での開発用。バッファセーブ→バッファ評価→play-cljのリロードのコンボをまとめて実行する。
   sit-for で wait かましているのはあんまり意味ないかも。"
  (interactive)
  (save-buffer)
  (sit-for 1)
  (cider-load-buffer)
  (sit-for 1)
  (play-clj-reload))
(define-key cider-mode-map (kbd "<f5>") 'save->eval->reload)

docstring にも書いたが sit-for は別になくてもいいかも。 まあけどこれでF5一発で画面反映までしてくれるようになるので結構楽になる。

cider-jack-in だとランタイムエラーが出ない?

play-clj(と言うか libGDX) は GL スレッドを 1 個作ってそこでイベントハンドリングするという まあ Swing や JavaFX などと同じような手法を取ってるのだが、この手のものは cider-jack-in した場合別スレッドを立ち上げる為か(詳しくは調べてない)、 例外のメッセージを吐き出さずに止まってしまう事がある。

play-clj はその場合にも対応できる方法を用意してて、set-screen-wrapper! を使って 例外時は printStackTrace して空の画面を出させるようにするというスニペットチュートリアルの 一番最後に載せてあり、それを core.clj の一番最後に入れておけば大抵 REPL を再起動せずとも 復帰できるようになる。

ただ、それでも cider-jack-in でコンソールを立ち上げずに REPL 起動した場合だと エラー時もやはりメッセージが出てくれない。

ウィンドウは増えてしまうがコマンドプロンプトから REPL 立ち上げるとエラーメッセージは 出るので個人的にはこちらの方をオススメする。

ちなみにここでも前述した emacs コマンド(F5) で復帰できて便利。