解いた問題

2/12/2012

k7script.elでもぞもぞ動かす

killer7というゲームソフトがあります。過去にプレイした中でもかなり気に入ってる部類です。
難解なストーリーと変にお洒落な雰囲気が何ともいえません。
このゲームはセリフが英語なので画面下に字幕が出るんですが、少し変わっています。
1. 文字の位置が微妙に動く。
2. 背景に陰影ができる。
3. 特定の文字の形が変化する。
といった謎の挙動。

少しだけ真似てみましょう。emacsで。


できた!駄作!
動作確認はなおざり。使い勝手もいまいち。
カレントバッファの内容をもぞもぞします。



参考にしたモノ
Emacsでドットエディターを作ってみた

上記の記事のdoteditor.elの関数を拝借して、
一定時間おきに画像を表現した16進数を毎回書き換えます。
パフォーマンスがアレ。

30日でできる! OS自作入門という本が手元にあったので
その中で使われてるフォントを改変して作ったデモ。







フォントの内容まで上げるのはアレかと思ったので、ザックリと使い方
コード中の font と adj にそれらしい値を読み込めば、動作します。
font は文字列のリストのリストです。文字列は、描画可能なhexを表しています。
文字コード?A番目には文字Aを描画するためのhexリストです。
例えば、(setq font (list (list hex-for-A0 hex-for-A1 hex-for-A2)
                                  (listhex-for-B0 hex-for-B1 hex-for-B2)))

adj はn番目のhexの次に描画すべきインデックス。
 例えば、(setq adj '((1 7 8)
                                  略
                             (0 2 7 8 9)))
これだと、0番目の次に1番目か7番目か8番目のどれか。デモだとその中からランダムに動きます。


コード
(setq text nil)
(setq buff-name "k7script")
(setq timer nil)
(setq font nil)
(setq adj nil)
(load-file "path/to/file")
(defun k7:rand-walk (pos)
(let (neighbor)
(setq neighbor (nth pos adj))
(nth (random (length neighbor)) neighbor)))
(defun k7:make-line (line)
(let (ret)
(setq ret "")
(while (car line)
(setq ret (concat ret (apply 'concat (mapcar 'car line)) "\n"))
(setq line (mapcar 'cdr line)))
ret))
(defun k7:connect-lines (lines)
(let (ret)
(map nil '(lambda (line)
(setq ret (concat ret (k7:make-line line))))
lines)
ret))
(defun k7:update ()
(setq text (mapcar '(lambda (line)
(mapcar '(lambda (c)
(list (first c)
(k7:rand-walk (car (last c)))))
line))
text)))
(defun k7:make-chars ()
(mapcar '(lambda (line)
(mapcar '(lambda (c)
(split-string (nth (car (last c)) (nth (first c) font)) "\n"))
line))
text))
(defun k7:make-script ()
(k7:update)
(insert (format "%s" (k7:connect-lines (k7:make-chars))))
(create-pbm-from-hex (point-min) (point-max)))
;; http://ynomura.dip.jp/archives/2010/12/emacs_1.html
;; http://ynomura.dip.jp/archives/misc/doteditor.el
(defun create-pbm-from-hex (start end)
"inserts PBM image data of hexified bitmap into the top of temporal buffer"
;; (interactive "r")
;; (when mark-active
(let ((pbm "") (width 0) (height 0))
(while (< start end)
(let (ch1 ch2 n1 n2) ;n: decimal value of a hex char
(setq ch1 (char-after start)) ;ch1: hex char for first 4bit
(setq ch2 (or (char-after (+ start 1)) ?\0)) ;char-after eob is nil
(setq n1 (string-to-number (char-to-string ch1) 16))
(cond ((or (> n1 0) (= ch1 ?0)) ;[1-9a-fA-F] or '0'
(setq n2 (string-to-number (char-to-string ch2) 16))
(when (or (> n2 0) (= ch2 ?0))
(setq start (+ 1 start)))
(setq pbm (concat pbm (format "%c" (logior (lsh n1 4) n2)))))
((= ch1 ?\n)
(if (= ch2 ?\n) nil (setq height (+ 1 height)))
))
(setq start (+ 1 start))
))
(setq width (* 8 (/ (length pbm) height)))
;; (switch-to-buffer "tmp.pbm")
(goto-char 1)
(insert (format "P4 %d %d " width height) pbm))
(if (functionp 'image-mode) (image-mode) nil)
);;)
(defun k7:start ()
(interactive)
(let (lines max-len)
(setq text '())
(setq lines (split-string (buffer-string) "\n"))
(setq max-len (apply 'max (mapcar 'length lines)))
(setq lines (mapcar '(lambda (line)
(while (< (length line) max-len)
(setq line (concat line " ")))
line)
lines))
(setq text (mapcar '(lambda (line)
(mapcar '(lambda (c)
(list c 0))
line))
lines))
(setq timer (run-with-timer 1 0.2 '(lambda ()
(if (buffer-live-p (get-buffer buff-name))
(kill-buffer buff-name))
(switch-to-buffer buff-name)
(k7:make-script))))))
;; (defun k7:stop ()
;; (interactive)
;; (cancel-timer timer))
view raw k7script.el hosted with ❤ by GitHub


意外と見ていて楽しい。
でも、 run-with-idle-timer とかで入力が無い時に動かすような使い方しか思いつかない。

0 件のコメント :

コメントを投稿