グラフィックスのコンテキスト
HCに対して直接描画を行うわけではありません。次に示すように、キャンバス(canvas)から2Dグラフィックスのコンテキストを取得し、そのコンテキストに対して描画を行います。
var context = canvas.getContext( "2d" ); context.fillStyle = "#fff"; context.strokeRect( 20, 20, 60, 60 );
最初の1行でグラフィックスのコンテキストを取得しています("2d"という指定に注意してください。"3d"コンテキストは現在まだ提供されていません)。2行目で現在の色を設定し、3行目で四角形を描画しています。
HC要素の2通りの作り方
他の多くのHTML要素と同様、HCにも2通りの作り方があります。その1つは、次のようにマークアップで宣言する方法です。
<canvas id="canvas" style="border: solid 1px" width="400" height="400"> </canvas>
この方法を用いた場合は、getElementById()呼び出しでcanvasオブジェクトを取得する必要があります。
var canvas = document.getElementById( "canvas" );
もう1つは、JavaScriptでプログラム的に作る方法です。
var canvas = document.createElement( "canvas" ); canvas.style.border = "1px solid"; canvas.width = 400; canvas.height = 400; canvas.style.width = 400; canvas.style.height = 400; document.documentElement.appendChild( canvas );
どちらの方法も得られる結果は同じなので、都合に応じて使い分ければよいでしょう。本稿の3Dゲームでは2番目の方法を使用しています。
3Dレンダリング
さて、HTML Canvasによる描画の基本が理解できたところで、ダウンロードしたソースコードに含まれている3Dレンダリングゲームに話を移しましょう。詳細は本稿の範囲を超えるので、重要な点のみをかいつまんで説明します。
この3Dワールドはグリッドで構成されます。グリッドの各要素は、塗り潰された状態か空の状態のどちらかを取ります。このグリッドをレンダリングするということは、各面を3Dポリゴンに変換し、それらの3Dポリゴンを2Dに投影し、2DポリゴンをHCで描画することを意味します。
これをサポートするため、ダウンロードしたソースコード内の3Dゲームには2Dおよび3Dの点を表すクラス(P2およびP3)とポリゴンクラス(Polygon2およびPolygon3)が存在します。Polygon3.project()メソッドは、ポリゴンを2D平面に投影して Polygon2を生成します。そしてPolygon2が、moveToメソッドとlineToメソッドによりHCに描画されます。
ポリゴンの塗り潰しという力仕事がHC側で処理されるため、この3Dコードは、Cのような昔からよく使われてきたグラフィックス言語でなくJavaScriptで記述されているにもかかわらず、かなり高速です。
変換
グラフィックスのプログラミングでは2次元の空間変換が非常に重要な意味を持ちます。これにより任意の図形を任意の尺度で拡大/縮小、回転、平行移動することが可能となります。変換でレンダリングの質が低下することはないので、これは特にベクタグラフィックスで効果を発揮します。
変換は状態マシンモデルにも従うので、当然、save()およびrestore()と共に使用します。次のコードは、3Dシステムのマップウィンドウで視点の矢印をレンダリングする例です。
function render_arrow( ctx, x, y, scale, rot ) {
// Save the current graphics state, including transformation state.
ctx.save();
// Move the arrow into place.
ctx.translate( x, y );
ctx.scale( scale, scale );
ctx.rotate( rot );
// Draw the arrow.
ctx.strokeStyle = "#aaa";
arrow.fill( ctx );
// Restore the original graphics state
ctx.restore();
}
スクリーンショットのキャプチャ
HCの素晴らしい点は、レンダリング画像の各ピクセルを読み書きできることです。この機能の利用法の1つがスクリーンショットのキャプチャです。 context.toDataURL()メソッドは、PNG形式でエンコードされた画像を含む次のようなdata URLを返します。
data:image/png;base64,iVBORw0KGgoAAAANSUh[... much more data removed ...]
このURLは、他のどんなものとしても使えます。例えば、これで新しいウィンドウを開き、そのウィンドウに画像が表示されるようにできます。本稿の3Dゲームでは、ビューとマップの四角形の下に特別な四角形があります。[Shift]+[S]キーを押すと、スクリーンショットがキャプチャされ、この四角形の中にそれが表示されます。ここから画像を保存したり、独自のウィンドウで表示したり、(OSがサポートしていれば)デスクトップにドラッグしたりできます。
HTMLとピクセルを橋渡しするHTML Canvas
長年にわたってWebデザイナーとプログラマは、ピクセル精度のレイアウトという名目のもと、HTML要素やCSSスタイルの宣言を裏技的に使って、普通ではできないようなことをすることに多大な努力を重ねてきました。HTMLはもともと保護の目的でレイアウトの細部を分離するように作られているため、ピクセルレベルの精度を達成することは常に大変な作業でした。本稿の例を見て分かるように、HTML CanvasによってHTMLマークアップと個々のピクセル間のギャップを埋めることが可能になります。
