Lisp Game Programming 再履修 <その5> Bordeaux-threads トライアル
Bordeaux-threads を sbclrc に書き加え、ライブラリとして使える状況になっているものの、未だ使ったことがない。
ならばと無理矢理使ってみたものの、微妙な結果に終わった。
defpackage の部分に、
;; ----------------------------------------------------------------------------------------------- (defpackage :game (:use :common-lisp :lispbuilder-sdl) (:nicknames :boulderdash) (:export #:Common-boulderdash))
:bordeaux-threads を追加し、
;; ----------------------------------------------------------------------------------------------- (defpackage :game (:use :common-lisp :lispbuilder-sdl :bordeaux-threads) (:nicknames :boulderdash) (:export #:Common-boulderdash))
Draw-game の部分で、
(defun Draw-game (level player-position status) (sdl:clear-display sdl:*black*) (loop for y from (- (cdr player-position) (floor +screen-tile-height+ 2)); player-positon -7 for screen-y from 0 repeat +screen-tile-height+
clear-display を外し、
(defun Draw-game (level player-position status) ; (sdl:clear-display sdl:*black*) (loop for y from (- (cdr player-position) (floor +screen-tile-height+ 2)); player-positon -7 for screen-y from 0 repeat +screen-tile-height+
ここのところを、
;<Draw Game> (Draw-game level player-position status)
clear-display と draw-game をスレッドにしたものに変更してみる。
;<Draw Game> (sdl:clear-display sdl:*black*) (let ((Drawthread (bordeaux-threads:make-thread #'(lambda () ; 1 thread not split screen (Draw-game level player-position status)) :name "Drawthread"))) (bordeaux-threads:join-thread Drawthread)) ; wait for end thread
当然、普通に動く!
じゃあさ。画面を2つに分けて描画する準備として、1つの thread が終わったら 次の thread が動くようにしたらどうよ。
まずは、Draw-game の部分を、
(defun Draw-game (level player-position status) ; (sdl:clear-display sdl:*black*) (loop for y from (- (cdr player-position) (floor +screen-tile-height+ 2)); player-positon -7 for screen-y from 0 repeat +screen-tile-height+ do (loop for x from (- (car player-position) (floor +screen-tile-width+ 2)); player-position -8 for screen-x from 0
画面を2つに分けて描画するため、player の位置を基準として、x-flag = 1 の時は右側とし、x-offset は左側を描画するときのスタート位置としてプログラムコードを変更し、
(defun Draw-game (level player-position status x-flag x-offset) ; (sdl:clear-display sdl:*black*) (loop for y from (- (cdr player-position) (floor +screen-tile-height+ 2)); player-positon -7 for screen-y from 0 repeat +screen-tile-height+ do (loop for x from (if (= x-flag 1) (- (car player-position) (floor +screen-tile-width+ 2)); player-position -8 (car player-position)) for screen-x from x-offset
先に変更したこのコードを、
;<Draw Game> (sdl:clear-display sdl:*black*) (let ((Drawthread (bordeaux-threads:make-thread #'(lambda () ; 1 thread not split screen (Draw-game level player-position status)) :name "Drawthread"))) (bordeaux-threads:join-thread Drawthread)) ; wait for end thread
左右を分割して描画するコードに再変更する。
;<Draw Game> (sdl:clear-display sdl:*black*) (let ((Drawthread1 (bordeaux-threads:make-thread #'(lambda () ; split screen to left or right (Draw-game level player-position status 1 0)) ; 1 -> screen left side 0 -> offset 0 :name "Drawthread1"))) (bordeaux-threads:join-thread Drawthread1)) (let ((Drawthread2 (bordeaux-threads:make-thread #'(lambda () (Draw-game level player-position status 2 8)) ; 2 -> screen right side 8 -> offset 8 :name "Drawthread2"))) (bordeaux-threads:join-thread Drawthread2))
これまた、当然普通に動く!!
では、ここでお立合い。
下のように、1つの thread が終了する前にもう1つの thread を動かして表示したらどうよ。
;<Draw Game> (sdl:clear-display sdl:*black*) (let ((Drawthread1 (bordeaux-threads:make-thread #'(lambda () ; split screen to left or right (Draw-game level player-position status 1 0)) ; 1 -> screen left side 0 -> offset 0 :name "Drawthread1")) (Drawthread2 (bordeaux-threads:make-thread #'(lambda () (Draw-game level player-position status 2 8)) ; 2 -> screen right side 8 -> offset 8 :name "Drawthread2"))) (bordeaux-threads:join-thread Drawthread1) ; wait for end threads (bordeaux-threads:join-thread Drawthread2))
動きます。ただし・・・・・・・・!
画面が「あばれる君」になります。
ニュアンス的には、empty(描画しない部分)が、ランダムな位置に点滅するようなイメージで、目がチカチカすると言えばわかるかな?
本当はこんな感じで描画されるはずが、
こんな感じになる。(左側の wall の位置が欠けている)
いい歳ですが、まだまだ未熟者ということで。