03.画像出力
いわゆるアスキーアート的なもの
画像といっても文字コンソールを対象にしていますので、文字で作った絵のことです。
データは画面のときと同じように文字列の配列をデータとしましょう。
今後のことを考えて、オブジェクトを生成できるように関数化しておきます。
/* 前略 */
function createImageData(dataCharArray, transChar = ' ') {
const img = {
transChar: transChar,
dataArray: dataCharArray,
};
img.height = dataCharArray.length;
img.width = dataCharArray.map((s) => s.length).reduce((a, b) => Math.max(a, b));
return img;
}
/* 以下略 */
画像ということから、普通は文字列の幅も決まっているとは思いますが、念のため最大長を幅として考えることにしました。
あとゲームを作る以上は背景描画して自分描画してといった擬似的なレイヤなども考えることになるので、透明扱いにできる文字の指定も考慮。
描画処理
データ構造は整理できた、といっても画面のときと対して変わりませんが、透明の考慮を入れて描画処理を作ります。
/* 前略 */
function drawImageData(x, y, imgData) {
let c;
for (let i = 0; i < imgData.height; i++) {
for (let j = 0; j < imgData.width; j++) {
c = imgData.dataArray[i].charAt(j);
if (c !== '' && c !== imgData.transChar) {
if (x + j >= 0 && x + j < screen.width && y + i >= 0 && y + i < screen.height) {
screen.setData(x + j, y + i, c);
}
}
}
}
}
/* 以下略 */
若干ネストが気持ち悪いですが、要は1文字ずつデータを見ながら、描画できる座標なら描画しようっていう処理です。
(追記)screen.setDataの関数内部でクリッピングするような作りのほうが処理の受け持ちとしては正しいですね。
表示
無限ループのときと同じような動きで、今度は1文字ではない感じで表示します。
/* 前略 */
const img = createImageData([
'#A#',
'XoX',
], '#');
let px = -2, py = -1;
function gameFrame() {
const t = performance.now();
px ++;
if (px >= screen.width) {
px = -2;
py++;
if (py >= screen.height) {
py = -1;
}
}
screen.clear();
drawImageData(px, py, img);
const delta = performance.now() - t;
setTimeout(gameFrame, spf - delta);
}
setTimeout(gameFrame, spf);
/* 以下略 */
リソース
gconsole.css
gconsole.js
g03.js
関連
00.画面表示
01.文字出力
02.無限ループ
04.キー操作
05.速度を調整
06.敵の配置
07.ゲームにする
08.ゲームパッド