スプライト
draw.sprite(frameOrImage, x, y, options?) は、画像またはその一部を指定した位置に描きます。たいていのゲームで一番よく呼ぶ関数で、アロケーションを起こしません。
// 画像全体を (160, 90) を中心に
draw.sprite(hero, 160, 90);
draw.sprite(hero, 160, 90, { rotation: 0.3, tint: "#f0f" }); // 回転してティント画像とフレーム
第1引数は画像(HTMLImageElement、HTMLCanvasElement、OffscreenCanvas、ImageBitmap、またはレンダーターゲット)か、画像の矩形を表す Frame({ image, x, y, w, h })です。
import type { Frame } from "spryte";
const sheet = await load("/hero-sheet.png"); // load() は「はじめる」のもの
// 16×16 グリッド上の4フレームの歩行サイクル
const walk: Frame[] = [0, 1, 2, 3].map((i) => ({ image: sheet, x: i * 16, y: 0, w: 16, h: 16 }));
function render(time: number) {
const frame = walk[Math.floor(time / 100) % walk.length]!;
draw.sprite(frame, player.x, player.y);
}テクスチャアトラスも同じです。アトラスのデータから領域ごとに Frame を1つずつ作り、すべて同じ image を指すようにします。
オプション
| オプション | デフォルト | |
|---|---|---|
origin | [0.5, 0.5] | フレームサイズに対する割合で指定するアンカー。[0, 0] は左上、[0.5, 1] は下端の中央です。 |
scaleX、scaleY | 1 | 各軸の拡大率。 |
rotation | 0 | 原点を中心とした回転(ラジアン)。 |
flipX、flipY | false | 原点を中心に軸で反転。 |
alpha | 1 | 不透明度。グローバルな draw.alpha と掛け合わされます。 |
tint | 白 | 乗算する色。 |
flash | 0 | 白へ寄せる度合い(0〜1)。被弾時のフラッシュ用です。 |
smooth | draw.smooth | このスプライトだけのリニアフィルタリング。 |
// 地面に立ち、左を向き、被弾後にフラッシュするキャラクター
draw.sprite(frame, x, groundY, {
origin: [0.5, 1],
flipX: facing < 0,
flash: hitTimer > 0 ? 1 : 0,
});
// 脈打つコイン
const pulse = 1 + Math.sin(t * 8) * 0.1;
draw.sprite(coin, x, y, { scaleX: pulse, scaleY: pulse });
// 幽霊:半透明で青くティント
draw.sprite(ghost, x, y, { alpha: 0.5, tint: "#88aaff" });tint には spryte のどの色形式も使えます。"#rgb"、"#rgba"、"#rrggbb"、"#rrggbbaa"、数値 0xRRGGBBAA、または任意の CSS カラーです。色を参照してください。
オプションオブジェクトを使い回す
sprite() はオプションを読むだけで保持しないので、ホットループではスプライトごとに作らず、1つのオブジェクトを使い回してください。
import type { SpriteDrawOptions } from "spryte";
const opts: SpriteDrawOptions = { rotation: 0, alpha: 1 };
for (const enemy of enemies) {
opts.rotation = enemy.angle;
opts.alpha = enemy.fade;
draw.sprite(enemyFrame, enemy.x, enemy.y, opts);
}オプションなしの draw.sprite(img, x, y) もアロケーションを起こしません。
描画順
呼び出し順がそのまま描画順です。後の呼び出しが前のものの上に描かれます。z-index もシーングラフもないので、描きたいレイヤーの順に描いてください。
draw.begin("#000", 320, 180, scale);
drawBackground();
for (const e of enemies) draw.sprite(enemyFrame, e.x, e.y);
draw.sprite(playerFrame, player.x, player.y);
drawHud();
draw.end();奥行きでソートしたいなら、ループの前に自分の配列をソートします。呼び出しは spryte が自動でバッチ処理します。1フレームに何回 GPU 呼び出しをしたかは draw.drawCalls でわかります。
ピクセルスナップ
smooth がオフのとき、回転していないスプライトは整数ピクセル上に配置されます。小数の位置で最近傍サンプリングをすると、フレームごとに輪郭が1ピクセル増えたり減ったりして、ちらつきに見えるからです。回転したスプライトはスナップされません。詳しくはドット絵を参照してください。
ピクセルの変更
canvas から描画していて、そのピクセルを変えた場合は、draw.invalidate(canvas) を呼んで再アップロードします。変化しない画像には何も必要ありません。
次へ:一括スプライト