みかづきブログ その3

3ヶ月つづけてみました。

JavaScriptであたり判定をつくろう その5

前回 までで想定していた機能は実装しきったのですが、今回はレンダリングの部分をcanvasに差し替えてみたいと思います。


canvasの作成

HTML

<canvas id="canvas"></canvas>

CSS

* {
    margin: 0; padding: 0;
}

html {
    height: 100%;
}

body {
    height: 100%;
    overflow: hidden;
}

とりあえずcanvasを1つつくります。
大きさはウィンドウサイズいっぱいにする予定です。


canvasサイズの調整

JavaScript

var canvas = doc.getElementById("canvas"),
    ctx = canvas.getContext("2d");

canvas.width  = win.innerWidth;
canvas.height = win.innerHeight;

DOMのロードが終わったらcanvasのサイズをウィンドウサイズと一緒にします。


あたり判定のDOM削除

JavaScript

function HitArea(obj) {
    var that = this;

    this.name   = obj.name     || "gonbei";
    that.top    = obj.top      || 0;
    that.left   = obj.left     || 0;
    that.width  = obj.width    || 100;
    that.height = obj.height   || 100;
    that.stride = obj.stride   || 10;
    that.color  = obj.color    || "rgba(0, 0, 0, .1)"; // 追加
    this.hit    = obj.callback || function() {};
}
var me = new HitArea({
    name   : "me",
    top    : 10,
    left   : 10,
    width  : 100,
    height : 100,
    color  : "rgba(255, 0, 0, .1)",
    stride : 10
});

DOMを自動で生成するのをやめました。
あと、色を受け取れるように改修しています。


レンダリングアルゴリズムの修正

JavaScript

setInterval(function() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    ctx.save();
        ctx.fillStyle = me.color;
        ctx.fillRect(me.left, me.top, me.width, me.height);
    ctx.restore();

    ctx.save();
        ctx.fillStyle = target.color;
        ctx.fillRect(target.left, target.top, target.width, target.height);
    ctx.restore();

    me.isHit(target);
}, 100);

これで完成です。


DEMO

JavaScript

(function(win, doc) {

"use strict";

// あたり判定
function HitArea(obj) {
    var that = this;

    this.name   = obj.name     || "gonbei";
    that.top    = obj.top      || 0;
    that.left   = obj.left     || 0;
    that.width  = obj.width    || 100;
    that.height = obj.height   || 100;
    that.stride = obj.stride   || 10;
    that.color  = obj.color    || "rgba(0, 0, 0, .1)";
    this.hit    = obj.callback || function() {};
}

HitArea.prototype._setPosition = function(obj) {
    this.top  = (typeof obj.top  === "number") ? obj.top  : this.top;
    this.left = (typeof obj.left === "number") ? obj.left : this.left;
};

HitArea.prototype.stepForTop = function() {
    this._setPosition({top: this.top - this.stride});
};

HitArea.prototype.stepForBottom = function() {
    this._setPosition({top: this.top + this.stride});
};

HitArea.prototype.stepForLeft = function() {
    this._setPosition({left: this.left - this.stride});
};

HitArea.prototype.stepForRight = function() {
    this._setPosition({left: this.left + this.stride});
};

HitArea.prototype.isHit = function(targetArea) {
    if (this.top + this.height > targetArea.top && this.top < targetArea.top + targetArea.height) {
        if (this.left + this.width > targetArea.left && this.left < targetArea.left + targetArea.width) {
            this.hit();
            targetArea.hit();
        }
    }
};

HitArea.prototype.render = function() {
    this.elm.style.top    = this.top    + "px";
    this.elm.style.left   = this.left   + "px";
    this.elm.style.width  = this.width  + "px";
    this.elm.style.height = this.height + "px";
};

var canvas = doc.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    me = new HitArea({
        name   : "me",
        top    : 10,
        left   : 10,
        width  : 100,
        height : 100,
        color  : "rgba(255, 0, 0, .1)",
        stride : 10
    }),
    target = new HitArea({
        name     : "target",
        top      : 200,
        left     : 200,
        width    : 100,
        height   : 100,
        color  : "rgba(0, 0, 255, .1)",
        stride   : 10,
        callback : function() {
            console.log("HIT: " + this.name + "!");
        }
    });

canvas.width  = win.innerWidth;
canvas.height = win.innerHeight;

// キーボードイベント
(function() {
    var TOP_KEY_INDEX    = 38,
        BOTTOM_KEY_INDEX = 40,
        LEFT_KEY_INDEX   = 37,
        RIGHT_KEY_INDEX  = 39;

    doc.addEventListener("keyup", function(evt) {
        switch(evt.keyCode) {
            case TOP_KEY_INDEX:
                me.stepForTop();
                break;
            case BOTTOM_KEY_INDEX:
                me.stepForBottom();
                break;
            case LEFT_KEY_INDEX:
                me.stepForLeft();
                break;
            case RIGHT_KEY_INDEX:
                me.stepForRight();
                break;
        }
    }, false);
})();


// 定期的にオブジェクトを表示
setInterval(function() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    ctx.save();
        ctx.fillStyle = me.color;
        ctx.fillRect(me.left, me.top, me.width, me.height);
    ctx.restore();

    ctx.save();
        ctx.fillStyle = target.color;
        ctx.fillRect(target.left, target.top, target.width, target.height);
    ctx.restore();

    me.isHit(target);
}, 100);

})(this, document);



つづきは こちら

kimizuka.hatenablog.com