前回 までで想定していた機能は実装しきったのですが、今回はレンダリングの部分を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);
つづきは こちら 。