ちょっと期間が空いてしまいましたが、前々々回 、 前々回 、前回 のつづきです。
今回はいよいよあたり判定の部分を実装していきます。
インスタンスを複数つくれるようにする
まずはhitAreaを複数描画できるように、DOMにクラス名を渡せるように変更してみます。
JavaScript
function HitArea(obj) { var that = this; _init(); function _init() { var elm = doc.createElement("div"); elm.className = "hitarea " + obj.name || ""; // 追加 elm.style.position = "absolute"; that.elm = elm; } that.name = obj.name || ""; // 追加 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; }
これでhitAreaを複数つくってもCSSで見た目を変更できるようになりました。
JavaScript
var me = new HitArea({ name : "me", top : 10, left : 10, width : 100, height : 100, stride : 10 }), target = new HitArea({ name : "target", top : 200, left : 200, width : 100, height : 100, stride : 10, });
CSS
.hitarea.me { background: rgba(255, 0, 0, .1); } .hitarea.target { background: rgba(0, 255, 0, .1); }
あたりを判定する
自分と引数で渡された相手が重なっているかを判定する isHitメソッド を実装します。
JavaScript
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) { console.log("HIT!"); } } };
で、重なった際に自分と相手の hitメソッド を実行するようにしておきましょう。
JavaScript
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(); } } };
コールバックを登録できるようにする
あとは hitメソッド にコールバックを登録できるように改修すれば完成です。
JavaScript
function HitArea(obj) { var that = this; _init(); function _init() { var elm = doc.createElement("div"); elm.className = "hitarea " + obj.name || ""; elm.style.position = "absolute"; that.elm = elm; } that.name = obj.name || ""; 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; this.hit = obj.callback || function() {}; // 追加 }
インスタンスをつくるときにコールバックを渡す設計にしてみました。
JavaScript
var target = new HitArea({ name : "target", top : 200, left : 200, width : 100, height : 100, stride : 10, callback : function() { console.log("HIT: " + this.name + "!"); } });
domo
JavaScript
(function(win, doc) { "use strict"; // あたり判定 function HitArea(obj) { var that = this; _init(); function _init() { var elm = doc.createElement("div"); elm.className = "hitarea " + obj.name || ""; elm.style.position = "absolute"; that.elm = elm; } that.name = obj.name || ""; 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; 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.appendTo = function(elm) { elm.appendChild(this.elm); }; 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 me = new HitArea({ name : "me", top : 10, left : 10, width : 100, height : 100, stride : 10 }), target = new HitArea({ name : "target", top : 200, left : 200, width : 100, height : 100, stride : 10, callback : function() { console.log("HIT: " + this.name + "!"); } }); me.appendTo(doc.body); target.appendTo(doc.body); // キーボードイベント (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() { me.render(); me.isHit(target); target.render(); }, 100); })(this, document);
後半駆け足になってしまいましたが、こんな感じで完成です。
続きは こちら 。