描画
シーンは draw を通して描画します。論理単位で扱うイミディエイトモードの API です。バッチ処理された WebGL2 レンダラーの上で動き、WebGL2 が使えない環境では自動で Canvas 2D にフォールバックします。どちらでもコードは同じです。
render(draw) {
draw.withCamera(game.camera, () => {
draw.sprite(heroFrame, hero.x, hero.y, { origin: [0.5, 1], flipX: hero.facingLeft, flash: hero.hurt });
draw.rect(0, groundY, 320, 8, "#2f3a1f");
particles.draw(draw);
});
draw.text(`score ${score}`, 4, 4, { font: "8px monospace", color: "#cffb2d" });
}API
| 呼び出し | 描くもの |
|---|---|
sprite(frame | image, x, y, options?) | 画像、またはスプライトシートのフレーム。オプション:origin、scaleX、scaleY、rotation、flipX、flipY、alpha、tint、flash、smooth |
rect(x, y, w, h, color) | 塗りつぶした矩形 |
circle(x, y, radius, color) | 塗りつぶした、アンチエイリアス付きの円 |
line(x1, y1, x2, y2, width, color) | 線 |
text(string, x, y, options?) | キャッシュされた、くっきりしたテキスト。オプション:font、color、align、baseline、alpha |
push() / pop()、translate、scale、rotate | 変換スタック |
withCamera(camera, fn) | カメラの視点で fn を実行 |
clip(x, y, w, h, fn) | 矩形の内側にだけ描く(UI パネル、リスト、ミニマップ)。入れ子にできます |
alpha、blend("normal" | "add") | 全体のアルファとブレンドモード |
raw | { kind: "webgl2", gl } または { kind: "2d", ctx } の抜け道 |
色は 16 進文字列("#cffb2d"、"#cffb2d80")、任意の CSS カラー、または数値 0xRRGGBBAA で指定します。
なぜ速いのか
すべての呼び出しは GPU バッファの 1 インスタンスになります。1 バッチにつき最大 8 枚のテクスチャをバインドするので、スプライト、テキスト、パーティクルが混ざってもバッチが途切れません。ホットパスではメモリを確保しません。
debuff は spryte で描画しています。レンダラーのベンチマークでは、draw.sprite は PixiJS の Sprite より約 2.8〜3.3 倍速く、50,000〜100,000 個のスプライトを 60 fps で描き続けます。パーティクルや弾幕、群れには draw.sprites(frame, positions, count, options, each?) を使えば、位置を並べた Float32Array を 1 回の呼び出しでまとめて描けます。コピーごとのスケール、回転、色も指定できます。こちらは 60 fps で約 800,000 スプライト を描き、パーティクルごとにすべてのプロパティを変えた場合でも PixiJS の ParticleContainer より 3.8 倍速い 結果です。ノート PC の GPU 1 台での計測なので、目安として見てください(計測方法と注意点)。
バックエンドを選ぶ
new Game({ canvas, width, height, renderer: "auto" }); // デフォルト:WebGL2、なければ Canvas 2D
new Game({ canvas, width, height, renderer: "2d" }); // Canvas 2D を強制game.draw.kind で、どちらが有効かわかります。Canvas 2D では、tint はアルファだけが反映されます。