Gauche-SDLでライフゲーム
最近になってGauche用のSDLラッパーを作成しているので、ここで一つ宣伝をしておきます。
SDLの詳細に関しては本家とかウィキペディアとかで。
作成しているGauche-SDLはこちらのgithub上にあります。
インストール方法などもろもろは同じくgithub上のWikiにあるので参照してください。
Windows上での動作も確認できていますが、コンパイルにはMinGWが必要です。気が向いたらコンパイル済みのバイナリもどこかで配布するかも。
最後に一つサンプルを載せておきます。
こちらのサイトを参考にして、ライフゲームをGauche-SDLを利用して書いてみました。
(use sdl) (use sdl.gfx) (use math.mt-random) (use gauche.uvector) (define screen #f) (define-constant stride 100) (define world (make-u8vector (* stride stride) 0)) (define-macro (world-ref world y x) `(ref ,world (+ (* ,y ,stride) ,x))) (define-macro (world-set! world y x val) `(set! (ref ,world (+ (* ,y ,stride) ,x)) ,val)) (define (count-neighboring-individual y x world) (let ([next-y (if (eq? y (- stride 1)) 0 (+ y 1))] [prev-y (if (zero? y) (- stride 1) (- y 1))] [next-x (if (eq? x (- stride 1)) 0 (+ x 1))] [prev-x (if (zero? x) (- stride 1) (- x 1))]) (+ (world-ref world prev-y prev-x) (world-ref world prev-y x) (world-ref world prev-y next-x) (world-ref world y prev-x) (world-ref world y next-x) (world-ref world next-y prev-x) (world-ref world next-y x) (world-ref world next-y next-x)))) (define (update-next-generation world) (let ([w (u8vector-copy world)]) (dotimes [y stride #f] (dotimes [x stride #f] (let ([count (count-neighboring-individual y x world)]) (cond [(zero? (world-ref world y x)) (when (eq? count 3) (world-set! w y x 1))] [(or (>= count 4) (<= count 1)) (world-set! w y x 0)])))) w)) (define (initialize-world) (let ([m (make <mersenne-twister>)]) (dotimes [y stride #f] (dotimes [x stride #f] (world-set! world y x (if (< (mt-random-integer m 10) 1) 1 0)))))) (define update (let ([wait (/ 1000 3)] [next 0]) (lambda () (set! next (if (>= (sdl-get-ticks) next) (begin (set! world (update-next-generation world)) (+ next wait)) next))))) (define (draw) (let ([white (make-sdl-color 255 255 255)] [black (make-sdl-color 0 0 0)]) (dotimes [y stride #f] (dotimes [x stride #f] (gfx-box-color screen (* x 4) (* y 4) (+ (* x 4) 4) (+ (* y 4) 4) (if (zero? (world-ref world y x)) black white))))) (sdl-update-rect screen 0 0 0 0)) (define (initialize) (sdl-init SDL_INIT_VIDEO) (sdl-wm-set-caption "LifeGame -Gauche SDL-" #f) (set! screen (sdl-set-video-mode 400 400 32 SDL_SWSURFACE)) (initialize-world) ) (define-constant wait (/ 1000 60)) (define (main-loop) (let loop ([next-frame (sdl-get-ticks)]) (unless (let proc-event ([event (sdl-poll-event)]) (and event (or (eq? (ref event 'type) SDL_QUIT) (and (eq? (ref event 'type) SDL_KEYUP) (eq? (ref (ref event 'keysym) 'sym) SDLK_ESCAPE)) (proc-event (sdl-poll-event))))) (let ([next (if (>= (sdl-get-ticks) next-frame) (begin (update) (when (< (sdl-get-ticks) (+ next-frame wait)) (draw)) (+ next-frame wait)) next-frame)]) (sdl-delay 0) (loop next))))) (define (finalize) (sdl-quit)) (initialize) (main-loop) (finalize)
サンプルを作ってみて気付いたけど、薄いラッパーだけだとどうもSchemeっぽいコードにならない。
もうちょっと抽象度を上げたレイヤもつくりたいなぁ。