先日は、
で、動きについて書きましたが、今回はグラフィックについて書こうかなと思います。
グラフィックですが、グラフィックだけでなく動画や写真には解像度があります。これは、縦横のドットの数で構成されていますが、この仕様もゲームも映像の解像度とアスペクト比が基準になっています。この辺りは、家庭用ゲーム機については、テレビが基準なので、映像用の解像度が使用できます。その為、480pのようなSD解像度や、720p/180/pなどのようなハイビジョンの解像度もありますが、近年ではPCだと4Kの出力ができる仕様が当たり前なので、2160pなどの選択肢もあります。ただし、PCの場合、1440pのような特殊な解像度(これは、720pを4つ並べた解像度になります。)もありますが、こうしたドットの総数で解像度が違っています。物の見え方については、解像度だけでなく、画素密度で見え方が違うので、印刷と全く考え方は同じですが、PPIと言う単位を基準にして考えます。これは、Picel / inchなので、1インチの中にどれだけ画素があるのか?を示したものになります。同じ解像度でも、インチ数が大きくなれば、画素は荒くなるので、PPIの数値は下がります。アップルのRETINAディスプレイでは、PPI数が維持された状態でインチ数を上げているので、インチ数が大きくなるほど画素数も増える仕様になっています。
ディスプレイの場合、PPIがどの程度の物なのかで判断しますが、印刷の場合は、Dot / Inchなので、1インチの中にインクのドットがどの程度含まれるのか?で印刷の密度を指定します。この印刷と全く同じ条件で物の見え方が変わりますが、映像・画像についてはひょじ機材のドットに色彩情報を割り当てて表示しているので、基本的に表示檀家ではラスターグラフィックとして表示しています。ゲームも同様に解像度がありますから、表示段階ではラスターグラフィックになっています。
ラ スターグラフィックでの動きの表現
ラスターグラフィックはドットの制御になりますから、もっとも単純な変化は、電球のオンとオフをするのと同じで、二値での制御になります。
基本的に、ドット(ピクセル)は、一つづつに異なる情報を記録できるので、最小構成は、オンとオフのみの二値になります。この状態だと、
■ オフの状態 : 0
■ オンの状態 : 1
なので、 【 有無 】 という変化はしていますが、移動はしていません。ラスターグラフィックは解像度分だけ平面にドットが敷き詰められた物ですから、二値で移動の表現をしようとすると、
■ 元の位置のドットを0にする
■ 移動先の位置にあるドットを1にする
事で、座標の変化が出たように見えます。左右の移動が解り易いのですが、
【 左へ移動 】
【 00100 】
【 01000 】
【 10000 】
【 右へ移動 】
【 00100 】
【 00010 】
【 00001 】
となります。つまり、1ドットを基準に考えると、周辺のドットの信号を反転させるとそれになるので、この状態で解像度分だけ並べたLEDを移動しているように表示したい場合には、それをそのまま行う事で実現できます。
この二値の判定と言うのは、5x5のLEDと同じなので、Micro:BitのLED操作と同じ考え方になります。
■ Micro:Bit
https://makecode.microbit.org/
基本的に、ドット絵についても、シルエット部分は1bitのオンとオフの信号の集合体ですから、Micro:bitの表示を作るのと同じですが、二値の場合だと、移動の表現の場合、対象のドットと近接するドットの情報の変化で表現をすることができます。二値の判定だとそれがブール値で、信号のオンとオフになります。
これが基準なので、オブジェクトの解像度が2x2のようにサイズが4倍になっても考え方は同じで、
【 左へ移動 】
【 001100 】
【 001100 】
【 011000 】
【 011000 】
【 110000 】
【 110000 】
【 右へ移動 】
【 001100 】
【 001100 】
【 000110 】
【 000110 】
【 000011 】
【 000011 】
のようになります。これが上下方向への移動でも同じようになりますが、この2x2のドットの集合体をキャラクターのシルエットにした場合も、二値の表示の場合には考え方は全く同じです。
■ ラスターグラフィックで制御できる物
ラスターグラフィックは平面のドットの集合体なので、直線的な物は得意ですが、曲線や斜線は苦手としています。前述の表記だと、最初物のだと、左右に動く場合だと、算数で登場する数列と考え方は同じなので、 【 左がマイナスで右がプラス 】 になります。PCでのプログラミングの場合だと、データの読み込み方で違いますし、組み込み機材のセグメントの多いLEDの場合だと番号の振り方で変わってきますが、このデータが、 (’00100’)のような物で、変数に対してループで二次元配列のドットの集合体を適応するような物だと、一番左が1で最後が5になります。
この状態だと、3回目のループで読み込んでいる数値が1で、それ以外は0という事になりますが、左だとこれが2番目で、右だとこれが4番目になります。このように直線移動だと問題がないのですが、中学校の数学では平方根が登場しますが、その中で、正方形の斜線の長さを学びますが、これが、√2であることを学びます、これは無理数になりますが、 1.142135623730956488016887242....のような感じで延々と続く数値になります。円周率と同じように割り切る事ができない数値ですが、斜線は√2なので、斜めに移動しようと思った場合に、XとYを+1してしまうと移動距離が√2になってしまうという問題が出てしまいます。その為、こうした処理を行う場合、原点からの二軸の距離が1になるようにして考えることになります。そうすると、全ての辺が常に1になる条件ですから、斜め45度でも1位度するという条件になりますから、この状態だと、原点を中心とした円が生成されます。この半径1の円の中で、どの角度に向かって動くのか?を指定する訳ですから、変化の基準は角度になります。この時の角度をΘとした場合、移動方向は三角関数のサイン(sin)とコサイン(cos)で導き出す事ができます。
これについては、
で紹介していますが、斜めの場合だと、基本軸から角度分だけラジアンで回転させるとその方向になります。
基本的に、座標については、直線なので、ドット絵と言うのはマイクラでブロックを置いていくイメージになりますから、二値のシルエットで表現すると、直線は、
11111
となりますが、斜線は、
1
1
1
1
1
や
11111
11111
11111
のような感じになります。また、
111111
111
11
11
1
1
1
11
11
111
111111
のような形で曲線を描くことになるので、境界がギザギザした状態になります。これをジャギーと呼びますが、ラスターグラフィックを使った場合、二値での表示を行うと、必ず斜線と直線ではジャギーが出ます。
基本的に、移動については、ラジアンで回すのと三角関数で移動させることができるので、
■ X軸とY軸の平行移動
■ 平面的な回転
は行えます。その為、奥行きはパースで疑似表現を用いることになります。遠近感のコントロールは、拡大縮小になります。
■ 拡大・縮小
拡大・縮小の場合、ドットで考えると解り易いのですが、縦・横の比率を合わせてドットを増やす処理になります。とりあえず、
【 拡大 】
【 010000 】
【 000000 】
【 000000 】
【 011000 】
【 011000 】
【 000000 】
【 011100 】
【 011100 】
【 011100 】
【 拡大 】
【 011100 】
【 011100 】
【 011100 】
【 011000 】
【 011000 】
【 000000 】
【 010000 】
【 000000 】
【 000000 】
のような感じになります。ドットで見ると、倍数分だけ、ドットが増えていますが、位置の移動がないので、センターから拡大する場合だと基数だと合わせやすく偶数だと合わせにくくなります。
拡大縮小の疑似イメージだと
【 , 】 【 ・ 】 【 O 】 【 ( ) 】
のような感じだと思いますが、小さなのが大きくなると近づいたように見えその逆に大きなものが小さくなると遠ざかったように見えます。特に、パースのない一点透視図法で奥行きのない物だと純粋に面ですから、面のサイズで奥行きが変化したように見えます。
基本的に、3Dを2Dで表現する場合には、パースがどうつくのかを考えることになりますが、そのパースに見合った状態だと立体に見えます。
レトロゲームだと
のような処理がされていますが、スプライトの拡大縮小は、セガのマスターシステム辺りで使用できるようになり、スーパーファミコンだとラスタースクロールなども使えるようになりますが、大昔のハードウェアではキャラクターのパターンを変更してて立体にするしかないので、こうした処理も実装されていないのでそうなるような処理を考える必要がありました。
その為、奥行きは放射状に移動して拡大すると近づいているように見えるので、パースw基準とした移動と拡大処理か、もしくは、タイルを複数組み合わせてサイズの大きなスプライトを用意してその異なるスプライトを移動に連動させて変化させると、そうした挙動に見えます。
その為、ピクセルの取り扱いでは、軸移動と平面的な回転のみが標準で行える機能になります。
ラ スターグラフィックと色彩
ドットには表示の有無を指定する二値の判定がありますが、LEDではなくカラーディスプレイの場合、色彩の情報を持たせる必要があります。ライトは、発光すると白く光り、消灯すると暗くなるので黒くなります。つまり、二値というのは、白と黒の変化という事になります。
光の三原色については、
で触れていますが、白色と言うのは、RGBの三原色で構成されています。
ちなみに、光の三原色を合成すると、二色の混ざった色は、
■ シアン
■ マゼンタ
■ イエロー
になるので、CMYの組み合わせになります。これにキープレートを合わせたものが印刷で使用するCMYKになります。
この状態になると、表示は、ブール値ではなく、カラー情報になりますから、単体の二値の変数ではなく、RGBの3つの変数を用意する必要が出てきます。
大昔はカラーパレットがなく8色表示の時代だった李、ゲーム機の色数も結構酷く画面内で使える色数もほとんどない時代もありましたが、現在はJPEGやコンシューマのカメラで撮影できる動画については、RGBの各色に8bitの階調を割り当てて撮影ができます。
その為、2の8乗分だけの階調があるので、256階調の明暗の変化を入れる事ができます。8bitの色深度では、0-255までの数値で表現できますが、これは16の2乗なので、16進数で表記ができるので、各色は00~FFで指定する事ができます。それが、3色ですから、00 00 00の状態で、黒(背景が黒だと非表示)になり、FF FF FFだと白になります。
この三つの16進数を組み合わせることで、色を調整するのが、現在のピクセルの色彩情報のコントロールになります。
この表記ですが、#000000~#FFFFFFで表記されますが、この16進数の成り立ちが、RGBで2桁づつ並んでいるので、#000000の状態からグレースケールで1段階階調を上げる場合だと、#010101になります。
これは8bitの階調が3色なので、24になるので、この8bitの色深度のカラーを24bitカラーとも呼びます。その為、カラーの総数で表記してあるのか、動画や写真のように色深度でbit数を表記しているのかで内容が異なります。
基本的に、24bitのように色の総数でカラーが表記されている場合、3で割り切れない32bitカラーと言う物が存在します。これは8x4と言う構成なので、32bitになりますが、色彩は光の三原色で構成されていますから、それ以外の色はありません。その為、これは色以外をコントロールする階調が実装されています。
32bitの画像や動画は、RGBではなくRGBAの素材になりますが、このAと言う表記はアルファチャンネルです。
■ アルファチャンネル
アルファチャンネルというのは、 【 透過 】 を指定するもので、これは色深度のビット数と同じ会長で指定します。その為、8bitの色深度の場合だと、アルファチェンネルも256階調になります。
画像の場合、 【 透過素材 】 がRGBAの素材になりますが、現在ではスマホやタブレットでも画像処理ができる時代ですから、こうした素材も作れますが、アルファチャンネル指定で0にした場所は下位レイヤーの素材が表示されます。その為、画像に階層を持たせて表示した際に、透過部分はその素材の色ではなく、背景素材の情報が占有して表示されます。つまり、RGBAの素材が#FFFFFFFFの場合、そのピクセルは、白色になりますが、#FFFFFF00の場合だと、その素材は色彩情報が存在してもアルファチャンネルのほうが優先されますから、透過されます。
この項目も00~FFまでの指定ができるので、半透明の表現が可能で、半透明で重なった場合、透明度が濃度のように働くので後ろの色に対して影響を与える事ができます。その為、白いキャンバスに単色で色を乗せると水彩画のような色の乗り方になります。
二値の場合だと変数は一つですが、これに色彩情報が加わった場合、RGBAで処理を行いますから、この条件だと、変数の数は4つに増え、そこで判定を行う数値は8bitの場合だと、0-255の範囲を用いることになります。これが、10bitになると、2の10乗なので、1024階調になりますが、この色の情報はスーパーハイビジョンや今年の年末に出る予定の次世代ゲーム機で標準実装となっているUltra HD Blu-Rayで使用されれています。その為、今後は10bitの色深度の映像を見る機会も増えると思いますし、近い未来ではコンテンツの記録に使っているのではないかな?と思いますが、色彩の情報についてはそう言った形で実装することになります。
ラ スターグラフィックと疑似立体
ラスターグラフィックは平面なので、アナログで絵を描く時のキャンバスと大差がありませんから、奥行きと言いう概念がありません。その為、この平面空間で立体を表現する場合、パースを用意する必要があります。
その為、立体に感じる物を作る場合には、パースを用意したり陰影を追加することで、立体に見せることになります。大昔のハードウェアでは疑似的な立体処理をするのが難しいので、3Dダンジョンの扱いだと、パターンを用意してそれを差し替えることで立体迷路を歩くように見えます。つまり、パターンが立体でパースのあるようなグラフィックを表示することでそれっぽく見えるわけですが、初期はそうした処理でしたが、後に、始点の回転できる物へとシフトしていきます。
これは、一点透視図法だからできる事とも言えますが、
\
\ ___
|_ /|
| | \ _ / |
| | |_| |
| | / \ |
| \|___
/
/
のようなものと、
____
/| |
___ / | |
| | | | |
| | | | |
|__ | \ | |
\|____|
では、見え方が異なると思いますが、奥に向かう大径が存在するので、パターン的に透視図法を用いたパースとして認識できます。
上のパターンは手前と少し奥に脇道のある通路で奥は行き止まりで、した物のは、奥に延びていて、左側に少し広い空間があり、右側にもスペースがあるような物に見えます。
アスキーアートでこうしたパターンを作る場合、三ブロック位を表現したほうがいいので、奥が空白なしで、その手前が1つで、その手前を3つの空白を開けて、その前の物は、5以上で、ウインドウからフレームアウトするような配置死にます。するとマップの構成において、4ブロックの奥行の直線のひな型が作れますから、グリッドを用意して作ったマップを通路の位置から、どのパターンを選択すれば、それになるのか?を考えて割り当てることになります。
その為、立体に見える物を扱う方法は色々あります。
現在のように速度が出る環境だと、立体になる処理を実装してそう言った表示を行ってリアルタイム処理を行う方法もありますが、基本的に、ドットの集合体を扱うだけだと、平面の画像制作と同じなので、立体の表現は絵を描く時のパースの考え方をそのまま用いて実装することになります。
ラ スターグラフィックとレイヤー
ラスターグラフィックでは、素材に階層を持たせることで、重ね合わせる事ができます。これを用いることで、単純なオブジェクトの移動も奥行きを与える事ができます。レイヤーと動作のコントロールですが、レトロゲームではシューティングゲームで実装されている手法ですが、背景に多重の層を用意して、異なるスクロールを実装することで、奥行きを与えるような処理が実装されています。これは個別の素材の座標変動ですから、単一の層だと不可能なので、複数の層を背景だけで実装している事になります。ゲームは複数の素材で構成されているので、階層が複数ありますが、ドット絵で作田tゲームで、シーン内の前後関係を表現しようと思うと、アニメの素材の前後関係とかデジ絵を描く時の素材の切り分けと同じような考え方です。シューティングゲームだと磁気の前面にある物と背後にあるものでは意味合いが変わってきますし、トップビューのゲームだと、プレイヤーの上に被るような物がある場合、プレイヤーの操作するオブジェクトのレイヤーよりも上の階層に別のレイヤーを設ける必要があります。その為、プレイヤーが操作するオブジェクトの層とは別に背景のように全く関係しない物やプレイヤーの接触判定のあるスクロール蛾は池とは異なるオブジェクトのレイヤーなど作りによって複数の層を持たせることになります。また、平面の処理というのは、ノンリニア編集と考え方が同じなので、この条件でカメラから見た場合の前後というのは、表示が優先されているか隠れるかの違いになります。そうなると、その条件を満たす場合には、対象物の前後に1枚づつのレイヤーを設ける必要が出てきます。
そこで移動をして対象物を通過した場合、移動しているオブジェクトが対象物よりも手前を通過したのか、それとも奥を通過したのかを決定する事ができます。その為、ドット絵で奥行きを冠がる場合、遮蔽物が存在しない場合だと、単一のレイヤーの拡大縮小やパースと陰影の追加で立体的に見せ得ることはできますが、 【 干渉 】 と言う条件が発生すると、複数のレイヤーを用いなければその挙動を実装する事ができません。