昭和の良さの一つでPCゲームの面白さがあります。夢中になっていた80年代当時は、PCのグラフィックの描画速度がとても遅く、メモリ容量も貧弱でした。ゲーム画面が切り替わる度に、描画し終えるのを待たなければなりませんでしたが、それでも一つ一つのゲームが魅力に溢れ、わくわくするものばかりでした。
当時はプレイだけでなく、ゲームを作るってことにも意欲的でした。ゲームは処理速度が要だったのでアセンブラとICの制御を駆使してアセンブラプログラミングしていました。オールアセンブラってのは、本当に骨の折れる作業です。長く続けられません。作り始めても数週間で飽きてしまって、しかしまたゲームをプレイしているうちに、ゲームを作りたくなり、という連鎖でそうしてプログラミングってものにハマって、スキルアップしていったのかもしれません。
このように私の中でゲームは、プログラミングする際のモチベーションにもなるので、スキルアップ訓練に持ってこいでした。ただ、ゲーム作りで難しいのが「絵」。絵心がないので特にそう思うのですが、絵で行き詰まってしまうと、簡単にやる気が削がれてしまいます。最近の流行のゲームエンジンを使ったゲーム制作なんかは、絵が命なのでうまく描けないとすぐやる気が失せます。その点レトロゲームなら、絵も簡単に描けてしまいますので、絶好の訓練材料になります。
さて、冒頭でも述べましたが、80年代の家庭用PCのグラフィック性能はとても低く、大きな画像を格納するメモリも存在しませんでした。大きな絵を楽しむアドベンチャーゲームでは、点と点を直線でつなげて描く手法が使われることもありました。
タイトルの点と点を繋ぐ描画が終わるまで、じっと待っているわけです。全部の点がつながったら、次は塗り潰し。メモリが少ない時代に試行錯誤した先輩たちの知恵ですね。
これは一つの圧縮技術かな、と思います。当時この技術に名前がついていたかは不明ですが、紛れもなくベクター形式の画像と言えるでしょう。今回はSVGコードを書いてベクター形式の理解を深めたいと思います。
理解するに当たり、まずは手を動かして絵を描いてみます。inkscapeを使います。
inkscapeはSVG形式の画像を扱うことができるツールで、Excelの図形描画を行う感覚で使えます。
Contents
inkscapeインストール
inkscapeは、インストーラーをダウンロードして実行するか、コマンドラインからapt等でインストールする方法でインストールできます。
サイトからダウンロードしてインストール
Windowsなら、インストーラーを使うのが一番簡単です。
https://inkscape.orgからダウンロードできます。
インストーラーをダブルクリック。
インストールが始まります。
Nextをめった打ち。
Setup Typeは、いまどきディスクの容量が気になるPCを探すのが難しいので、豪華にCompleteで。
では、Installボタンをクリックしてインストール開始。
プログレスバーが走ります。
少し待ったら完了です。
ショートカットができます。クラゲみたいですね。
ショートカットをダブルクリックすると、このようなエディタが起動します。
コマンドでインストール
linuxのコマンドでインストールする場合は、apt-get等で。
~$ sudo apt-get install inkscape ~$ inkscape
起動するとLinuxでも同じようなウィンドウが表示されます。
SVGでサラダの国のトマト姫
SVGを理解するため、inkscapeを使って、レトロゲームの「サラダの国のトマト姫」のタイトルを作って見たいと思います。
inkscapeを起動します。
ページを横向きにします。
元絵をリンクで読み込みます。ファイル名を付けておきます。
もう元絵を修正しませんので、新規レイヤーを追加して、お絵かきは新規レイヤーで行います。
矩形ツールを選択して、
枠を描きます。真っ黒になってしまうので、右クリックでフィル/ストロークを選択して、
塗りなしにします。
次はペンツールを選択して海面の線を引きます。
元絵のレイヤーを非表示にして、弾いた線を確認したら、バケツを選択し、
青色で塗ります。
他の海面の線を引いて、山を描きます。
次は、タイトルを描いて、
そのまま塗ろうとすると、海面の直線で分断されてしまうので、タイトルロゴだけ別レイヤにします。
色が濡れたら、全レイヤーを合成して、今回のタイトル絵の完成です。
重ね重ねですが「サラトマ」でも使われている点と点を結ぶ描画技術、貧弱なメモリでたくさんの画像を保存するには、ビットマップ画像ではすぐにメモリ不足に陥りますので、直線と塗りつぶしでグラフィックスを見せるって技が流行っていましたね。ラスタ画像を連想させる技術が使われていたってことに、古くても新しさを感じます。
inkscapeが生成するファイル
サラトマのタイトルを描いて、お絵かきの感触を掴んだところで、SVGの構造に目を向けたいと思います。
ファイル比較で必要な情報取得
inkscapeがどのようなファイルを生成しているか確認するため、何も描かれていないキャンバスで一旦ファイルを保存してみます。
nothing.svgという名前を付けて保存しました。内容は以下の通りです。
~$ cat nothing.svg <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="210mm" height="297mm" id="svg2" version="1.1" inkscape:version="0.48.5 r10040" sodipodi:docname="新規ドキュメント 1"> <defs id="defs4" /> <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="0.35" inkscape:cx="375" inkscape:cy="540" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" inkscape:window-width="874" inkscape:window-height="439" inkscape:window-x="281" inkscape:window-y="204" inkscape:window-maximized="0" /> <metadata id="metadata7"> <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> </cc:Work> </rdf:RDF> </metadata> <g inkscape:label="レイヤー 1" inkscape:groupmode="layer" id="layer1" /> </svg>
次は、円を描いて、それを保存してみます。
上記画像をcircle.svgという名前で保存しました。
何も描かれていないファイル nothing.svgと、
円を描いたファイル circle.svgをdiffコマンドで比較してみます。
~$ diff nothing.svg circle.svg 17c17 < sodipodi:docname="新規ドキュメント 1"> --- > sodipodi:docname="circle.svg"> 53c53,63 < id="layer1" /> --- > id="layer1"> > <path > sodipodi:type="arc" > style="fill:#00ff00" > id="path3007" > sodipodi:cx="367.14285" > sodipodi:cy="526.64789" > sodipodi:rx="150" > sodipodi:ry="140" > d="m 517.14285,526.64789 a 150,140 0 1 1 -300,0 150,140 0 1 1 300,0 z" /> > </g> ~$
差分を見るとよくわかります。円の描画情報だけが残りました。
円を描く単純なsvgファイルを作成
この情報を使って、円を描く単純なsvgファイルを作ってみます。
~$ cat circle.svg <svg width="210mm" height="297mm"> <path type="arc" style="fill:#00ff00" id="path3007" cx="367.14285" cy="526.64789" rx="150" ry="140" d="m 517.14285,526.64789 a 150,140 0 1 1 -300,0 150,140 0 1 1 300,0 z" /> </svg> ~$
できました。
SVGコードを書いて絵を描く
inkscapeでPNGに変換
inkscapeコマンドでPNG画像に変換もできます。
inkscape -z -e circle.png circle.svg Background RRGGBBAA: ffffff00 Area 0:0:744.094:1052.36 exported to 744 x 1052 pixels (90 dpi) Bitmap saved as: circle.png ~$
このような画像になります。
虹の画像を作る
では虹の画像を生成するコマンドです。円を重ねるだけです。
~$ cat <<EOL > tmp.svg <svg width="300" height="300"> <rect x="0" y="0" width="300" height="300" fill="white" /> <circle cx="0" cy="300" r="300" fill="red" /> <circle cx="0" cy="300" r="280" fill="orange" /> <circle cx="0" cy="300" r="260" fill="yellow" /> <circle cx="0" cy="300" r="240" fill="green" /> <circle cx="0" cy="300" r="220" fill="cyan" /> <circle cx="0" cy="300" r="200" fill="blue" /> <circle cx="0" cy="300" r="180" fill="purple" /> <circle cx="0" cy="300" r="160" fill="white" /> </svg> EOL inkscape -z -e tmp.png -w 300 -h 300 tmp.svg
複雑そうに見えても、意外と簡単ですよね。
SVGでテキスト画像
SVGで画像にテキストを埋め込むこともできます。
SVG形式で「あ」をベクタ画像にして、inkscapeでラスタ(PNG)画像にしてみます。
スクリプトはこれです。
~$ cat text.sh cat <<EOL > /tmp/tmp.svg <svg width="640" height="400"> <text x="0" y="400" font-size="400"> あ </text> </svg> EOL inkscape -z -e out.png /tmp/tmp.svg
以下のようにコマンドを実行すると、out.pngができます。
~$ . text.sh
rotateを指定して回転、色も指定できます。
~$ cat text-laydown.sh cat <<EOL > /tmp/tmp.svg <svg width="640" height="400"> <text x="0" y="0" font-size="400" rotate="90" fill="red"> あ </text> </svg> EOL inkscape -z -e out.png /tmp/tmp.svg
縁取りもできます。
~$ cat text-stroke.sh cat <<EOL > /tmp/tmp.svg <svg width="640" height="400"> <text x="0" y="400" font-size="400" stroke="green" stroke-width="10" fill="yellow"> あ </text> </svg> EOL inkscape -z -e out.png /tmp/tmp.svg
ランダムな大きさの文字を埋め込んでみましょう。
a="" colors="red orange yellow green cyan blue purple" for c in $colors;do x=`expr $RANDOM % 200` s=`expr $RANDOM % 300` a=$a`printf "<text x=\"%s\" y=\"200\" font-size=\"%s\" fill=\"%s\">\n" $x $s $c` a=$a`printf "%s</text>\n" $c` done cat <<EOL > /tmp/tmp.svg <svg width="640" height="300"> $a </svg> EOL inkscape -z -e out.png /tmp/tmp.svg
SVG入門は以上になります。実際のコードを書いてみたら、以外と簡単なことがわかりました。
コメント