1 /**************************************************************************** 2 Copyright (c) 2011-2012 cocos2d-x.org 3 Copyright (c) 2013-2014 Chukong Technologies Inc. 4 5 http://www.cocos2d-x.org 6 7 Permission is hereby granted, free of charge, to any person obtaining a copy 8 of this software and associated documentation files (the "Software"), to deal 9 in the Software without restriction, including without limitation the rights 10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 copies of the Software, and to permit persons to whom the Software is 12 furnished to do so, subject to the following conditions: 13 14 The above copyright notice and this permission notice shall be included in 15 all copies or substantial portions of the Software. 16 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 THE SOFTWARE. 24 ****************************************************************************/ 25 26 /** 27 * @ignore 28 */ 29 ccs.PT_RATIO = 32; 30 /** 31 * Base class for ccs.ColliderFilter 32 * @class 33 * @extends ccs.Class 34 */ 35 ccs.ColliderFilter = ccs.Class.extend(/** @lends ccs.ColliderFilter# */{ 36 _collisionType: 0, 37 _group: 0, 38 _categoryBits: 0, 39 _groupIndex: 0, 40 _maskBits: 0, 41 ctor: function (collisionType, group) { 42 this._collisionType = collisionType || 0; 43 this._group = group || 0; 44 }, 45 updateShape: function (shape) { 46 if(shape instanceof cp.Shape){ 47 shape.collision_type = this._collisionType; 48 shape.group = this._group; 49 }else if(shape instanceof Box2D.b2FilterData){ 50 51 var filter = new Box2D.b2FilterData(); 52 filter.categoryBits = this._categoryBits; 53 filter.groupIndex = this._groupIndex; 54 filter.maskBits = this._maskBits; 55 56 shape.SetFilterData(filter); 57 } 58 } 59 }); 60 /** 61 * Base class for ccs.ColliderBody 62 * @class 63 * @extends ccs.Class 64 * 65 * @property {ccs.ContourData} contourData - The contour data of collider body 66 * @property {ccs.Shape} shape - The shape of collider body 67 * @property {ccs.ColliderFilter} colliderFilter - The collider filter of collider body 68 * 69 */ 70 ccs.ColliderBody = ccs.Class.extend(/** @lends ccs.ColliderBody# */{ 71 shape: null, 72 coutourData: null, 73 colliderFilter: null, 74 _calculatedVertexList: null, 75 ctor: function (contourData) { 76 this.shape = null; 77 this.coutourData = contourData; 78 this.colliderFilter = new ccs.ColliderFilter(); 79 if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) { 80 this._calculatedVertexList = []; 81 } 82 }, 83 84 /** 85 * contourData getter 86 * @returns {ccs.ContourData} 87 */ 88 getContourData: function () { 89 return this.coutourData; 90 }, 91 92 /** 93 * colliderFilter setter 94 * @param {ccs.ColliderFilter} colliderFilter 95 */ 96 setColliderFilter: function (colliderFilter) { 97 this.colliderFilter = colliderFilter; 98 }, 99 100 /** 101 * get calculated vertex list 102 * @returns {Array} 103 */ 104 getCalculatedVertexList: function () { 105 return this._calculatedVertexList; 106 }, 107 108 setB2Fixture: function(fixture){ 109 this._fixture = fixture; 110 }, 111 112 getB2Fixture: function(){ 113 return this._fixture; 114 }, 115 116 /** 117 * shape getter 118 * @param {ccs.Shape} shape 119 */ 120 setShape: function (shape) { 121 this.shape = shape; 122 }, 123 124 /** 125 * shape setter 126 * @return {ccs.Shape} 127 */ 128 getShape: function () { 129 return this.shape; 130 }, 131 132 /** 133 * contourData setter 134 * @param {ccs.ContourData} contourData 135 */ 136 setContourData: function (contourData) { 137 this.coutourData = contourData; 138 }, 139 140 /** 141 * colliderFilter getter 142 * @returns {ccs.ColliderFilter} 143 */ 144 getColliderFilter: function () { 145 return this.colliderFilter; 146 } 147 }); 148 149 /** 150 * Base class for ccs.ColliderDetector 151 * @class 152 * @extends ccs.Class 153 * 154 * @property {ccs.ColliderFilter} colliderFilter - The collider filter of the collider detector 155 * @property {Boolean} active - Indicate whether the collider detector is active 156 * @property {Object} body - The collider body 157 */ 158 ccs.ColliderDetector = ccs.Class.extend(/** @lends ccs.ColliderDetector# */{ 159 _colliderBodyList: null, 160 _bone: null, 161 _body: null, 162 _active: false, 163 _filter: null, 164 helpPoint: cc.p(0, 0), 165 ctor: function () { 166 this._colliderBodyList = []; 167 this._bone = null; 168 this._body = null; 169 this._active = false; 170 this._filter = null; 171 }, 172 init: function (bone) { 173 this._colliderBodyList.length = 0; 174 if (bone) 175 this._bone = bone; 176 this._filter = new ccs.ColliderFilter(); 177 return true; 178 }, 179 180 /** 181 * add contourData 182 * @param {ccs.ContourData} contourData 183 */ 184 addContourData: function (contourData) { 185 var colliderBody = new ccs.ColliderBody(contourData); 186 this._colliderBodyList.push(colliderBody); 187 188 if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) { 189 var calculatedVertexList = colliderBody.getCalculatedVertexList(); 190 var vertexList = contourData.vertexList; 191 for (var i = 0; i < vertexList.length; i++) { 192 var newVertex = new ccs.ContourVertex2(0, 0); 193 calculatedVertexList.push(newVertex); 194 } 195 } 196 }, 197 198 /** 199 * add contourData 200 * @param {Array} contourDataList 201 */ 202 addContourDataList: function (contourDataList) { 203 for (var i = 0; i < contourDataList.length; i++) { 204 this.addContourData(contourDataList[i]); 205 } 206 }, 207 208 /** 209 * remove contourData 210 * @param contourData 211 */ 212 removeContourData: function (contourData) { 213 var eraseList = [], i, locBodyList = this._colliderBodyList; 214 for (i = 0; i < locBodyList.length; i++) { 215 var body = locBodyList[i]; 216 if (body && body.getContourData() == contourData) 217 eraseList.push(body); 218 } 219 220 for (i=0; i<eraseList.length; i++) 221 cc.arrayRemoveObject(locBodyList, eraseList[i]); 222 }, 223 224 /** 225 * remove all body 226 */ 227 removeAll: function () { 228 this._colliderBodyList.length = 0; 229 }, 230 231 setActive: function (active) { 232 if (this._active == active) 233 return; 234 this._active = active; 235 236 var locBody = this._body; 237 var locShape; 238 if (locBody) { 239 var colliderBody = null; 240 if (this._active) { 241 for (var i = 0; i < this._colliderBodyList.length; i++) { 242 colliderBody = this._colliderBodyList[i]; 243 locShape = colliderBody.getShape(); 244 locBody.space.addShape(locShape); 245 } 246 } else { 247 for (var i = 0; i < this._colliderBodyList.length; i++) { 248 colliderBody = this._colliderBodyList[i]; 249 locShape = colliderBody.getShape(); 250 locBody.space.removeShape(locShape); 251 } 252 } 253 } 254 }, 255 256 getActive: function () { 257 return this._active; 258 }, 259 260 getColliderBodyList: function(){ 261 return this._colliderBodyList; 262 }, 263 264 /** 265 * set colliderFilter 266 * @param {ccs.ColliderFilter} filter 267 */ 268 setColliderFilter: function (filter) { 269 this._filter = filter; 270 var locBodyList = this._colliderBodyList; 271 for(var i=0; i< locBodyList.length; i++){ 272 var colliderBody = locBodyList[i]; 273 colliderBody.setColliderFilter(filter); 274 if (colliderBody.getShape()) 275 colliderBody.getColliderFilter().updateShape(colliderBody.getShape()); 276 } 277 }, 278 279 /** 280 * get colliderFilter 281 * @returns {ccs.ColliderFilter} 282 */ 283 getColliderFilter: function () { 284 return this._filter; 285 }, 286 287 updateTransform: function (t) { 288 if (!this._active) 289 return; 290 291 var colliderBody = null; 292 var locBody = this._body; 293 var locHelpPoint = this.helpPoint; 294 for (var i = 0; i < this._colliderBodyList.length; i++) { 295 296 colliderBody = this._colliderBodyList[i]; 297 var contourData = colliderBody.getContourData(); 298 299 //default physics engine: Chipmunk 300 var shape = null; 301 if (locBody) { 302 //Box2d shape = (b2PolygonShape *)colliderBody->getB2Fixture()->GetShape(); 303 shape = colliderBody.getShape(); 304 } 305 306 var vs = contourData.vertexList; 307 var cvs = colliderBody.getCalculatedVertexList(); 308 309 for (var j = 0; j < vs.length; j++) { 310 locHelpPoint.x = vs[j].x; 311 locHelpPoint.y = vs[j].y; 312 locHelpPoint = cc.pointApplyAffineTransform(locHelpPoint, t); 313 314 if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) { 315 var v = cc.p(0, 0); 316 v.x = locHelpPoint.x; 317 v.y = locHelpPoint.y; 318 cvs[j] = v; 319 } 320 321 if (shape) { 322 shape.verts[j * 2] = locHelpPoint.x; 323 shape.verts[j * 2 + 1] = locHelpPoint.y; 324 } 325 } 326 if (shape) { 327 for (var j = 0; j < vs.length; j++) { 328 var b = shape.verts[(j + 1) % shape.verts.length]; 329 var n = cp.v.normalize(cp.v.perp(cp.v.sub(b, shape.verts[j]))); 330 331 shape.axes[j].n = n; 332 shape.axes[j].d = cp.v.dot(n, shape.verts[j]); 333 // var b = shape.verts[(i + 1) % shape.numVerts]; 334 // var n = cp.v.normalize(cp.v.perp(cp.v.sub(b, shape.verts[i]))); 335 // 336 // shape.planes[i].n = n; 337 // shape.planes[i].d = cp.v.dot(n, shape.verts[i]); 338 } 339 } 340 } 341 }, 342 343 setBody: function (body) { 344 this._body = body; 345 var colliderBody, locBodyList = this._colliderBodyList; 346 for (var i = 0; i < locBodyList.length; i++) { 347 colliderBody = locBodyList[i]; 348 var contourData = colliderBody.getContourData(), verts = []; 349 var vs = contourData.vertexList; 350 for (var j = 0; j < vs.length; j++) { 351 var v = vs[j]; 352 verts.push(v.x); 353 verts.push(v.y); 354 } 355 var shape = new cp.PolyShape(this._body, verts, cp.vzero); 356 shape.sensor = true; 357 shape.data = this._bone; 358 if (this._active) 359 this._body.space.addShape(shape); 360 colliderBody.setShape(shape); 361 colliderBody.getColliderFilter().updateShape(shape); 362 } 363 }, 364 365 getBody: function () { 366 return this._body; 367 } 368 }); 369 370 var _p = ccs.ColliderDetector.prototype; 371 372 // Extended properties 373 /** @expose */ 374 _p.colliderFilter; 375 cc.defineGetterSetter(_p, "colliderFilter", _p.getColliderFilter, _p.setColliderFilter); 376 /** @expose */ 377 _p.active; 378 cc.defineGetterSetter(_p, "active", _p.getActive, _p.setActive); 379 /** @expose */ 380 _p.body; 381 cc.defineGetterSetter(_p, "body", _p.getBody, _p.setBody); 382 383 _p = null; 384 385 ccs.ColliderDetector.create = function (bone) { 386 var colliderDetector = new ccs.ColliderDetector(); 387 if (colliderDetector && colliderDetector.init(bone)) 388 return colliderDetector; 389 return null; 390 };