その2 描画システム編
今回は今までの胡散臭い話からちょっと離れて描画システムを考える。
前回の話で、入力リストに対して[IO()]でも返しとけやということになったのであるが、
IO()では自由すぎるので描画に関して一つ考えてみることにする。
なお、今回のキーワードはgraphics combinator。
またわかる人にはわかってしまうと思うが…
IOなものを直接組み立ててもいいのだが、「画面」というものを表すものを考え、
それの間に演算を作ることによりもっと定義的なものが作れる。
実はそのようなものはHaskellのライブラリにも結構あって、
以前書いていたparser combinatorもそうだし
HTMLドキュメントを構築するためのライブラリ、Text.HTML、
テキスト画面向けcombinator library、Text.PrettyPrint.HughesPJ
のようなものもある。
それをとりあえず画面にも応用できないかと考えたのである。
以下、具体的手法。
- データタイプ
data Scr = ...
画面はScrという型で表される。
Scrがどうなっているかは興味が無いので、
抽象データ型にしておく。
画面をSurfaceにレンダリングするような関数も用意しておく。
drawScr :: Surface -> Scr -> IO ()
- プリミティブスクリーン
まず、いつもどおり?空のスクリーンを定義。
emptyScr :: Scr
次にサーフェース一つのみからなるスクリーン。
これは指定したSurfaceを(0,0)に描画するだけ。
img :: Surface -> Scr subImg :: Surface -> Rect -> Scr
subImgのほうはSurfaceの一部が転送できるように。
trans :: Point -> Scr -> Scr
指定したスクリーンを指定しただけ平行移動したスクリーン。
alpha :: Double -> Scr -> Scr
指定したスクリーンを指定した透明度にしたスクリーンを返す。
alpha値は[0,1]
infixr 4 <$$> (<$$>) :: Scr -> Scr -> Scr
一つ目のスクリーンに二つ目のスクリーンをかぶせたスクリーンを返す。
おまけ。
scrs :: [Scr] -> Scr scrs = foldl (<$$>) emptyScr
非常に荒削りであるが、これで大体普通の2D画面は構成できるのではなかろうか?
これ以上はとりあえず必要に応じて。
(なんか思ったよりあっさりした説明になってしまった…
実装例&使用例はまた今度)