LoginSignup
14
18

More than 5 years have passed since last update.

canvasにゲームテーブルを描画する(HTML5でブラウザゲームを作る)

Last updated at Posted at 2017-08-21

ゲーム画面の背景は事前にグラフィックソフト等を使って画像ファイル化して読み込むという手法もありますが、模様の類であればプログラムでリアルタイムで描画するほうが通信量が大幅に減り、試行錯誤の調整もやりやすくメンテナンスがかなり楽になります。

以下が実際にゲーム内で使用されている背景です。

HMG大富豪
https://hasemonmon.net/df5/
Screenshot from 2017-08-22 02-13-53-min.png

フエルト地のようなテーブル表面

canvasにベースとなる色を塗ります。

// キャンバス

var w = 320, h = 320;    // キャンバスのサイズ
var cv = document.createElement("canvas");
cv.setAttribute("width", w);
cv.setAttribute("height", h);
var ctx = cv.getContext('2d');
ctx.fillStyle = "#45cc82";  // 単色塗り
ctx.fillRect(0, 0, w, h);

加工のためにcanvasからピクセルデータ配列を取得します。
1ピクセル毎にR,G,B,Aの4データが有りますので、配列サイズはピクセル数*4になります。

// キャンバスからピクセルデータ配列を取得
var imageData = ctx.getImageData(0, 0, w, h);
var arrRGBA = imageData.data;

ピクセル単位でノイズを加えていきます。
ノイズは元の画像の色に対し色の濃さを%で変化させたものになります。
1ピクセル毎に4つのデータですのでforループは4カウントアップしていきます。

// ピクセルデータ配列を加工
for (var i = 0, l = arrRGBA.length; i < l; i += 4) {
    var per = 0;
    // 色を変化させる%を乱数で決定(実際の出力を見ながらここで微調整を加えていく)
    var rnd = Math.random();
    if (rnd < 0.2) {
        per = Math.random() * 5 + 3;
    } else if (rnd > 0.8) {
        per = Math.random() * -2 - 1;
    }
    // 色を%変化させる
    arrRGBA[i + 0] = colorPer(arrRGBA[i + 0], per);
    arrRGBA[i + 1] = colorPer(arrRGBA[i + 1], per);
    arrRGBA[i + 2] = colorPer(arrRGBA[i + 2], per);
    arrRGBA[i + 3] = arrRGBA[i + 3];
}
// 色を%で変化させる関数
function colorPer(value, per) {
    if (per === 0) return value;
    var newValue = value + Math.floor(value * per / 100);
    newValue = (newValue > 255) ? 255 : newValue;
    newValue = (newValue < 0) ? 0 : newValue;
    return newValue;
}

キャンバスへピクセルデータを書き戻します。

ctx.putImageData(imageData, 0, 0);

出力結果
Screenshot from 2017-08-22 02-41-26-min.png

これでフエルト地の立体的な表面が表現できました。

ライティングによる明暗

先ほどの処理ループ部分にライティングによる明暗処理を追加します。


var iy = 4 * 320;   // y毎の配列要素数
var cx = 160;   // グラデーションの中心x座標
var cy = 160;   // グラデーションの中心y座標

for (var i = 0, l = arrRGBA.length; i < l; i += 4) {
    var per = 0;
    var rnd = Math.random();
    if (rnd < 0.2) {
        per = Math.random() * 5 + 3;
    } else if (rnd > 0.8) {
        per = Math.random() * -2 - 1;
    }

    // 円グラデーション
    var x = (i % iy) / 4;       // iからピクセル座標xを計算
    var y = Math.floor(i / iy); // iからピクセル座標yを計算
    var r = Math.sqrt(Math.pow(cx - x, 2) + Math.pow(cy - y, 2));   // グラデーションの中心からの距離を計算
    per += -((r - 40) / 5); // 距離により色を変化させる%を変化させる

    arrRGBA[i + 0] = colorPer(arrRGBA[i + 0], per);
    arrRGBA[i + 1] = colorPer(arrRGBA[i + 1], per);
    arrRGBA[i + 2] = colorPer(arrRGBA[i + 2], per);
    arrRGBA[i + 3] = arrRGBA[i + 3];
}

出力結果
Screenshot from 2017-08-22 04-03-19-min.png

これでライティングの明暗が表現できました。

14
18
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
18