From 1644012dfefc2118b82da3e4f4e1ddab1f2db66b Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Mon, 20 Aug 2018 18:40:25 +0300 Subject: [PATCH] Simple intersection testing --- dist/dwelibs.min.js | 2 +- src/math.js | 56 ++++++++++++++++++++++++++++++++++++++++++--- src/tiled.js | 23 ++++++++++++++++--- 3 files changed, 74 insertions(+), 7 deletions(-) diff --git a/dist/dwelibs.min.js b/dist/dwelibs.min.js index d0a31f1..1bd3aba 100644 --- a/dist/dwelibs.min.js +++ b/dist/dwelibs.min.js @@ -1 +1 @@ -!function(t){var e={};function n(i){if(e[i])return e[i].exports;var r=e[i]={i:i,l:!1,exports:{}};return t[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=t,n.c=e,n.d=function(t,e,i){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(i,r,function(e){return t[e]}.bind(null,r));return i},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e,n){"use strict";window.DWE={};n(1),n(2),n(3),n(4),n(5),n(6),n(7)},function(t,e,n){"use strict";DWE.context=function(t){return t.star=function(e,n,i,r,o){var a=Math.PI/2*3,s=e,u=n,h=Math.PI/i;t.beginPath(),t.moveTo(e,n-r);for(var l=0;lthis.width/2+t.r)&&(!(e.y>this.height/2+t.r)&&(e.x<=this.width/2||(e.y<=this.height/2||Math.pow(e.x-this.width/2,2)+Math.pow(e.y-this.height/2,2)<=Math.pow(t.r,2))))}}]),t}(),DWE.Math.Circle=function(){function t(e,n,i){r(this,t),this.x=e,this.y=n,this.r=i}return i(t,[{key:"radius",get:function(){return this.r}}]),t}()},function(t,e,n){"use strict";DWE.getMousePosition=function(t,e){var n=void 0,i=void 0;if(t.changedTouches){var r=t.changedTouches[0];r&&(t.pageX=r.pageX,t.pageY=r.pageY)}return t.pageX||t.pageY?(n=t.pageX,i=t.pageY):(n=t.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,i=t.clientY+document.body.scrollTop+document.documentElement.scrollTop),n-=e.offsetLeft,i-=e.offsetTop,new DWE.Math.Vector2(n,i)}},function(t,e,n){"use strict";DWE.Keyboard={};var i={},r={},o={backspace:8,tab:9,enter:13,shift:16,ctrl:17,alt:18,pausebreak:19,capslock:20,escape:27,pgup:33,pgdown:34,end:35,home:36,left:37,up:38,right:39,down:40,insert:45,delete:46,"left-window":91,"right-window":92,select:93,numpad0:96,numpad1:97,numpad2:98,numpad3:99,numpad4:100,numpad5:101,numpad6:102,numpad7:103,numpad8:104,numpad9:105,multiply:106,add:107,subtract:109,decimal:110,divide:111,f1:112,f2:113,f3:114,f4:115,f5:116,f6:117,f7:118,f8:119,f9:120,f10:121,f11:122,f12:123,numlock:144,scrolllock:145,"semi-colon":186,equals:187,comma:188,dash:189,period:190,fwdslash:191,grave:192,"open-bracket":219,bkslash:220,"close-braket":221,"single-quote":222};function a(t){return null!=i[t]&&i[t]}function s(t){return null!=r[t]&&r[t]}DWE.Keyboard.toggleKey=function(t,e){var n=null;for(var r in o){if(t===o[r]){n=r;break}}n||(n=String.fromCharCode(t).toLowerCase()),i[n]=!0===e},DWE.Keyboard.keyDown=function(t){var e;window.event?e=window.event.keyCode:t&&(e=t.which),DWE.Keyboard.toggleKey(e,!0)},DWE.Keyboard.keyUp=function(t){var e;window.event?e=window.event.keyCode:t&&(e=t.which),DWE.Keyboard.toggleKey(e,!1)},DWE.Keyboard.isDown=function(t){return a(t)&&s(t)},DWE.Keyboard.isUp=function(t){return!DWE.Keyboard.isDown(t)},DWE.Keyboard.isPressed=function(t){return!0===a(t)&&!1===s(t)},DWE.Keyboard.nextIteration=function(){for(var t in r={},i)!0===i[t]&&(r[t]=!0)}},function(t,e,n){"use strict";var i=function(){function t(t,e){for(var n=0;n=400&&n(i.responseText)},i.open("GET",t,!0),i.responseType="text",i.send(null)})},DWE.File.loadJson=function(t){return new Promise(function(e,n){DWE.File.httpGET(t).then(function(t){var i;try{i=JSON.parse(t)}catch(t){return n(t)}e(i)},n)})}},function(t,e,n){"use strict";var i=function(){function t(t,e){for(var n=0;n=a.offset&&u.tile<=h&&a.draw(t,u.tile-a.offset,u.x*this.tileWidth*this.scale+e.x+r.x+n.x,u.y*this.tileHeight*this.scale+e.y+r.y+n.y,this.tileWidth*this.scale,this.tileHeight*this.scale)}}}},{key:"collideLayer",value:function(t,e){if(!this.layers[e])return null;this.layers[e];return null}},{key:"setScale",value:function(t){this.scale=t}}]),t}()}]); \ No newline at end of file +!function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e,n){"use strict";window.DWE={};n(1),n(2),n(3),n(4),n(5),n(6),n(7)},function(t,e,n){"use strict";DWE.context=function(t){return t.star=function(e,n,r,i,o){var a=Math.PI/2*3,s=e,u=n,h=Math.PI/r;t.beginPath(),t.moveTo(e,n-i);for(var c=0;cthis.width/2+t.r)&&(!(e.y>this.height/2+t.r)&&(e.x<=this.width/2||(e.y<=this.height/2||Math.pow(e.x-this.width/2,2)+Math.pow(e.y-this.height/2,2)<=Math.pow(t.r,2))))}}]),e}(),DWE.Math.Circle=function(){function t(e,n,r){i(this,t),this.x=e,this.y=n,this.r=r}return r(t,[{key:"radius",get:function(){return this.r}}]),t}()},function(t,e,n){"use strict";DWE.getMousePosition=function(t,e){var n=void 0,r=void 0;if(t.changedTouches){var i=t.changedTouches[0];i&&(t.pageX=i.pageX,t.pageY=i.pageY)}return t.pageX||t.pageY?(n=t.pageX,r=t.pageY):(n=t.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,r=t.clientY+document.body.scrollTop+document.documentElement.scrollTop),n-=e.offsetLeft,r-=e.offsetTop,new DWE.Math.Vector2(n,r)}},function(t,e,n){"use strict";DWE.Keyboard={};var r={},i={},o={backspace:8,tab:9,enter:13,shift:16,ctrl:17,alt:18,pausebreak:19,capslock:20,escape:27,pgup:33,pgdown:34,end:35,home:36,left:37,up:38,right:39,down:40,insert:45,delete:46,"left-window":91,"right-window":92,select:93,numpad0:96,numpad1:97,numpad2:98,numpad3:99,numpad4:100,numpad5:101,numpad6:102,numpad7:103,numpad8:104,numpad9:105,multiply:106,add:107,subtract:109,decimal:110,divide:111,f1:112,f2:113,f3:114,f4:115,f5:116,f6:117,f7:118,f8:119,f9:120,f10:121,f11:122,f12:123,numlock:144,scrolllock:145,"semi-colon":186,equals:187,comma:188,dash:189,period:190,fwdslash:191,grave:192,"open-bracket":219,bkslash:220,"close-braket":221,"single-quote":222};function a(t){return null!=r[t]&&r[t]}function s(t){return null!=i[t]&&i[t]}DWE.Keyboard.toggleKey=function(t,e){var n=null;for(var i in o){if(t===o[i]){n=i;break}}n||(n=String.fromCharCode(t).toLowerCase()),r[n]=!0===e},DWE.Keyboard.keyDown=function(t){var e;window.event?e=window.event.keyCode:t&&(e=t.which),DWE.Keyboard.toggleKey(e,!0)},DWE.Keyboard.keyUp=function(t){var e;window.event?e=window.event.keyCode:t&&(e=t.which),DWE.Keyboard.toggleKey(e,!1)},DWE.Keyboard.isDown=function(t){return a(t)&&s(t)},DWE.Keyboard.isUp=function(t){return!DWE.Keyboard.isDown(t)},DWE.Keyboard.isPressed=function(t){return!0===a(t)&&!1===s(t)},DWE.Keyboard.nextIteration=function(){for(var t in i={},r)!0===r[t]&&(i[t]=!0)}},function(t,e,n){"use strict";var r=function(){function t(t,e){for(var n=0;n=400&&n(r.responseText)},r.open("GET",t,!0),r.responseType="text",r.send(null)})},DWE.File.loadJson=function(t){return new Promise(function(e,n){DWE.File.httpGET(t).then(function(t){var r;try{r=JSON.parse(t)}catch(t){return n(t)}e(r)},n)})}},function(t,e,n){"use strict";var r=function(){function t(t,e){for(var n=0;n=a.offset&&u.tile<=h&&a.draw(t,u.tile-a.offset,u.x*this.tileWidth*this.scale+e.x+i.x+n.x,u.y*this.tileHeight*this.scale+e.y+i.y+n.y,this.tileWidth*this.scale,this.tileHeight*this.scale)}}}},{key:"collideLayer",value:function(t,e,n,r,i){if(!this.layers[r])return null;var o=this.layers[r],a=null,s=new DWE.Math.Box2(t.x*this.scale+e.x+o.x-n.x,t.y*this.scale+e.y+o.y-n.y,t.width,t.height);for(var u in o.tiles){var h=o.tiles[u],c=new DWE.Math.Box2(h.x*this.tileWidth*this.scale+e.x+o.x+n.x,h.y*this.tileHeight*this.scale+e.y+o.y+n.y,this.tileWidth,this.tileHeight);c.distance(s)>i||s.intersectsBox(c)&&(a||(a=[]),a.push(c.subtract(s).normalize()))}return a}},{key:"setScale",value:function(t){this.scale=t}}]),t}()}]); \ No newline at end of file diff --git a/src/math.js b/src/math.js index db07d73..f62a57c 100644 --- a/src/math.js +++ b/src/math.js @@ -42,20 +42,70 @@ DWE.Math.Vector2 = class { var len = this.magnitude this.x /= len this.y /= len + + return this + } + + get isNormal () { + return 1 === Math.floor(this.magnitude) + } + + get angle () { + if (!this.isNormal) return NaN + return Math.atan2(this.x, this.y) } distance (vec) { if (!(vec instanceof DWE.Math.Vector2)) throw new Error('Distance function takes another Vector2 as an argument.') return Math.abs(Math.sqrt(Math.pow(vec.x - this.x, 2) + Math.pow(vec.y - this.y, 2))) } + + add (vec) { + if (!(vec instanceof DWE.Math.Vector2)) throw new Error('Add function takes another Vector2 as an argument.') + this.x += vec.x + this.y += vec.y + return this + } + + subtract (vec) { + if (!(vec instanceof DWE.Math.Vector2)) throw new Error('Subtract function takes another Vector2 as an argument.') + this.x -= vec.x + this.y -= vec.y + return this + } + + multiply (vec) { + if (typeof vec === 'number' && !isNaN(vec)) { + this.x *= vec + this.y *= vec + return this + } + + if (!(vec instanceof DWE.Math.Vector2)) throw new Error('Multiply function takes a Vector2 or Number as an argument.') + this.x *= vec.x + this.y *= vec.y + return this + } + + divide (vec) { + if (typeof vec === 'number' && !isNaN(vec)) { + this.x /= vec + this.y /= vec + return this + } + + if (!(vec instanceof DWE.Math.Vector2)) throw new Error('Division function takes a Vector2 or Number as an argument.') + this.x /= vec.x + this.y /= vec.y + return this + } } // A box. -DWE.Math.Box2 = class { +DWE.Math.Box2 = class Box2 extends DWE.Math.Vector2 { constructor (x, y, w, h) { - this.x = x - this.y = y + super(x, y) this.width = w this.height = h } diff --git a/src/tiled.js b/src/tiled.js index 758c26e..d79b605 100644 --- a/src/tiled.js +++ b/src/tiled.js @@ -144,11 +144,28 @@ DWE.Tiled.Map = class { } } - collideLayer (object, name) { + // object: Object that collides (i.e. a player, monster) + // name: Name of the layer (generally "static") + // effectiveRange: Range around object where tiles are tested for collisions + collideLayer (object, origin, viewport, name, effectiveRange) { if (!this.layers[name]) return null var layer = this.layers[name] - // TODO: Handle object collisions with map tiles - return null + var collisions = null + var posAbs = new DWE.Math.Box2((object.x * this.scale) + origin.x + layer.x - viewport.x, + (object.y * this.scale) + origin.y + layer.y - viewport.y, object.width, object.height) + + for (let i in layer.tiles) { + let tile = layer.tiles[i] + let tilePosAbs = new DWE.Math.Box2((tile.x * this.tileWidth * this.scale) + origin.x + layer.x + viewport.x, + (tile.y * this.tileHeight * this.scale) + origin.y + layer.y + viewport.y, this.tileWidth, this.tileHeight) + if (tilePosAbs.distance(posAbs) > effectiveRange) continue + if (posAbs.intersectsBox(tilePosAbs)) { + if (!collisions) collisions = [] + collisions.push(tilePosAbs.subtract(posAbs).normalize()) + } + } + + return collisions } setScale (scale) {