From e45a929b00bf11cf8ebabff8701b05ff12757098 Mon Sep 17 00:00:00 2001 From: photonstorm Date: Fri, 28 Feb 2014 05:46:02 +0000 Subject: [PATCH] Body.loadPolygon now parses all shapes that may exist in a JSON data file, and re-creates them all on the Body. Assumes shapes are CCW + Convex (tested working with Lime Exportor). Almost fixes #449 but Body rotation seems to screw orientation of shapes. --- examples/assets/physics/sprites.json | 157 +++++++++++++++++++++++++++ examples/assets/physics/sprites.pes | Bin 0 -> 3558 bytes examples/wip/loadPolygon.js | 44 ++++++++ src/loader/Cache.js | 2 +- src/physics/Body.js | 44 +++++++- 5 files changed, 244 insertions(+), 3 deletions(-) create mode 100644 examples/assets/physics/sprites.json create mode 100644 examples/assets/physics/sprites.pes create mode 100644 examples/wip/loadPolygon.js diff --git a/examples/assets/physics/sprites.json b/examples/assets/physics/sprites.json new file mode 100644 index 00000000..6feeaf94 --- /dev/null +++ b/examples/assets/physics/sprites.json @@ -0,0 +1,157 @@ + { + + "contra2": [ + + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 10, 191 , 26, 158 , 25, 186 , 13, 204 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 116, 186 , 114, 165 , 130, 199 , 123, 203 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 115, 64 , 128, 91 , 132, 114 , 114, 165 , 8, 107 , 12, 85 , 25, 64 , 71, 47 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 138, 64 , 128, 91 , 115, 64 , 124, 10 , 137, 0 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 8, 107 , 114, 165 , 26, 158 , 11, 131 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 25, 64 , 12, 85 , 4, 67 , 0, 4 , 10, 0 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 114, 165 , 116, 186 , 25, 186 , 26, 158 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 116, 186 , 117, 206 , 20, 210 , 25, 186 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 142, 222 , 2, 222 , 20, 210 , 117, 206 ] + } + ] + + , + "bunny": [ + + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 140, 298 , 192, 248 , 224, 304 , 208, 318 , 164, 328 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 16, 196 , 60, 182 , 48, 246 , 10, 244 , 0, 218 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 224, 304 , 192, 248 , 224, 272 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 74, 4 , 104, 36 , 110, 58 , 64, 78 , 44, 72 , 32, 60 , 32, 30 , 48, 8 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 46, 262 , 116, 294 , 86, 336 , 46, 340 , 36, 334 , 22, 308 , 20, 284 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 172, 40 , 148, 74 , 110, 58 , 114, 22 , 128, 4 , 162, 0 , 174, 12 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 246, 230 , 238, 240 , 200, 240 , 186, 174 , 228, 184 , 244, 204 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 32, 110 , 40, 94 , 64, 78 , 110, 58 , 148, 74 , 60, 182 , 32, 146 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 194, 162 , 186, 174 , 46, 262 , 48, 246 , 148, 74 , 158, 78 , 188, 114 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 116, 294 , 46, 262 , 186, 174 , 200, 240 , 140, 298 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 148, 74 , 48, 246 , 60, 182 ] + } + ] + + , + "tetrisblock1": [ + + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 48, 0 , 96, 0 , 96, 144 , 48, 144 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 0, 48 , 48, 48 , 48, 96 , 0, 96 ] + } + ] + + , + "tetrisblock2": [ + + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 0, 144 , 0, 48 , 48, 48 , 48, 144 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 48, 0 , 96, 0 , 96, 96 , 48, 96 ] + } + ] + + , + "tetrisblock3": [ + + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 144, 0 , 144, 96 , 96, 48 , 96, 0 ] + } , + { + "density": 2, "friction": 0, "bounce": 0, + "filter": { "categoryBits": 1, "maskBits": 65535 }, + "shape": [ 96, 48 , 144, 96 , 0, 96 , 0, 48 ] + } + ] + + } \ No newline at end of file diff --git a/examples/assets/physics/sprites.pes b/examples/assets/physics/sprites.pes new file mode 100644 index 0000000000000000000000000000000000000000..7421a26b562a7321f501b8249fe8daab58b74e12 GIT binary patch literal 3558 zcmd5;-A+?M5FQ8+f(aoeCWLU&3q$Y^5C}$Z9FZR}4K1P~^5Z$Q6$+&mS`zi@Jc02M zc$D)bhR5*IZ+B*DTPzf%iJR>C_M6$AnLRVR=cL!?=ZL5a{U#MCPluGF2eeOR`b0%Y zM=7b&1l^+qJ%{|*>q4+mdP%F4qGh^+xgF@kSpS(yepZDRu(klnGKJnUQ6J{eAk3Fw zCQlV8%QRNwuzNN&w~jg8=soDY2%~OsKV`iC3Jioai7EY*r7t=y53P&D#gf4I1hbCe zqzG3_h#{oi^YM%zf-xFLOm2A@qk0!(&=j%IMN`I{uP{M$3!T29|3Dvx-cb3b@}y$GUcrw%5O2rAr<89g+WXvM(NCy6jAfwDnxoSV z(Yd43hhjWIDHMGfw0t~9^?1}D+VL7=7aWkEs2x|3?L8n@39OCL#>H6BYPl2$U+_R&iiNZCqo|&j1K}?`5LaU1uOh({55(^k-35Wh8z{*xmb8563i(c$HI4%mrjLSt=s-~RbODy?Nwllb>{Eg}d zl&f4A;xj*ksy9EZd|EN7Xm(d4FJR06nsU1{-^qM?^0w+HM8Z3Y%ZipKR<3!u?2Z`3 z_aKMvzRqPF@d7?&89JbcFw^plG1KJ6XlD9?`y+tg@96ElKmI=8f4WV2xiPDneQemb zYBe;GSLdmn>ikA-)nRhwHPz4sTj#zQ&8oqD(A!iElc=4hzgq$PN;S0j=XABi*80Al z#8wkx$GQQrp9`B6NY#!d(Cl2E*lsvzIk8ii+@{1%U6fdt)Byc|I_9+j*H=R)BE7!< U>K<78V{4jpD+0qNMPNpM0Uz?Es{jB1 literal 0 HcmV?d00001 diff --git a/examples/wip/loadPolygon.js b/examples/wip/loadPolygon.js new file mode 100644 index 00000000..2c9336f5 --- /dev/null +++ b/examples/wip/loadPolygon.js @@ -0,0 +1,44 @@ + +var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render }); + +function preload() { + + game.load.image('contra2', 'assets/pics/contra2.png'); + game.load.image('bunny', 'assets/sprites/bunny.png'); + game.load.image('tetrisblock1', 'assets/sprites/tetrisblock1.png'); + game.load.image('tetrisblock2', 'assets/sprites/tetrisblock2.png'); + game.load.image('tetrisblock3', 'assets/sprites/tetrisblock3.png'); + + // Load our physcs data exported from PhysicsEditor + game.load.physics('physicsData', 'assets/physics/sprites.json'); + +} + +var contra; +var start = false; + +function create() { + + contra = game.add.sprite(400, 300, 'contra2'); + contra.physicsEnabled = true; + contra.body.clearShapes(); + contra.body.loadPolygon('physicsData', 'contra2'); + + game.input.onDown.add(function() { start = true; }, this); + +} + +function update() { + + if (start) + { + contra.body.rotateLeft(5); + } + +} + +function render() { + + game.debug.renderPhysicsBody(contra.body, '#00ffff'); + +} diff --git a/src/loader/Cache.js b/src/loader/Cache.js index 37ca004a..51bbe8fc 100644 --- a/src/loader/Cache.js +++ b/src/loader/Cache.js @@ -607,7 +607,7 @@ Phaser.Cache.prototype = { { if (this._physics[key] && this._physics[key].data[object]) { - return this._physics[key].data[object][0]; + return this._physics[key].data[object]; } else { diff --git a/src/physics/Body.js b/src/physics/Body.js index a800f720..70dc7cf8 100644 --- a/src/physics/Body.js +++ b/src/physics/Body.js @@ -986,7 +986,7 @@ Phaser.Physics.Body.prototype = { * @method Phaser.Physics.Body#loadPolygon * @param {string} key - The key of the Physics Data file as stored in Game.Cache. * @param {string} object - The key of the object within the Physics data file that you wish to load the shape data from. - * @param {object} options - An object containing the build options: + * @param {object} options - An object containing the build options. Note that this isn't used if the data file contains multiple shapes. * @param {boolean} [options.optimalDecomp=false] - Set to true if you need optimal decomposition. Warning: very slow for polygons with more than 10 vertices. * @param {boolean} [options.skipSimpleCheck=false] - Set to true if you already know that the path is not intersecting itself. * @param {boolean|number} [options.removeCollinearPoints=false] - Set to a number (angle threshold value) to remove collinear points, or false to keep all points. @@ -996,7 +996,7 @@ Phaser.Physics.Body.prototype = { var data = this.game.cache.getPhysicsData(key, object); - if (data && data.shape) + if (data.length === 1) { var temp = []; @@ -1008,6 +1008,46 @@ Phaser.Physics.Body.prototype = { return this.addPolygon(options, temp); } + else + { + // We've multiple Convex shapes, they should be CCW automatically + var cm = p2.vec2.create(); + + for (var i = 0; i < data.length; i++) + { + var vertices = []; + + for (var s = 0; s < data[i].shape.length; s += 2) + { + vertices.push([ this.px2pi(data[i].shape[s]), this.px2pi(data[i].shape[s + 1]) ]); + } + + var c = new p2.Convex(vertices); + + // Move all vertices so its center of mass is in the local center of the convex + for (var j = 0; j !== c.vertices.length; j++) + { + var v = c.vertices[j]; + p2.vec2.sub(v, v, c.centerOfMass); + } + + p2.vec2.scale(cm, c.centerOfMass, 1); + + cm[0] -= this.px2pi(this.sprite.width / 2); + cm[1] -= this.px2pi(this.sprite.height / 2); + + c.updateTriangles(); + c.updateCenterOfMass(); + c.updateBoundingRadius(); + + this.data.addShape(c, cm); + } + + // this.data.adjustCenterOfMass(); + this.data.aabbNeedsUpdate = true; + + return true; + } return false;