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 /** 32 * Base class for ccs.ColliderFilter 33 * @class 34 * @extends ccs.Class 35 */ 36 ccs.ColliderFilter = ccs.Class.extend(/** @lends ccs.ColliderFilter# */{ 37 _collisionType: 0, 38 _group: 0, 39 _categoryBits: 0, 40 _groupIndex: 0, 41 _maskBits: 0, 42 43 ctor: function (collisionType, group) { 44 this._collisionType = collisionType || 0; 45 this._group = group || 0; 46 }, 47 48 updateShape: function (shape) { 49 if(shape instanceof cp.Shape){ 50 shape.collision_type = this._collisionType; 51 shape.group = this._group; 52 }else if(shape instanceof Box2D.b2FilterData){ 53 var filter = new Box2D.b2FilterData(); 54 filter.categoryBits = this._categoryBits; 55 filter.groupIndex = this._groupIndex; 56 filter.maskBits = this._maskBits; 57 58 shape.SetFilterData(filter); 59 } 60 } 61 }); 62 63 /** 64 * Base class for ccs.ColliderBody 65 * @class 66 * @extends ccs.Class 67 * 68 * @property {ccs.ContourData} contourData - The contour data of collider body 69 * @property {ccs.Shape} shape - The shape of collider body 70 * @property {ccs.ColliderFilter} colliderFilter - The collider filter of collider body 71 * 72 */ 73 ccs.ColliderBody = ccs.Class.extend(/** @lends ccs.ColliderBody# */{ 74 shape: null, 75 coutourData: null, 76 colliderFilter: null, 77 _calculatedVertexList: null, 78 ctor: function (contourData) { 79 this.shape = null; 80 this.coutourData = contourData; 81 this.colliderFilter = new ccs.ColliderFilter(); 82 if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) { 83 this._calculatedVertexList = []; 84 } 85 }, 86 87 /** 88 * contourData getter 89 * @returns {ccs.ContourData} 90 */ 91 getContourData: function () { 92 return this.coutourData; 93 }, 94 95 /** 96 * colliderFilter setter 97 * @param {ccs.ColliderFilter} colliderFilter 98 */ 99 setColliderFilter: function (colliderFilter) { 100 this.colliderFilter = colliderFilter; 101 }, 102 103 /** 104 * get calculated vertex list 105 * @returns {Array} 106 */ 107 getCalculatedVertexList: function () { 108 return this._calculatedVertexList; 109 }, 110 111 setB2Fixture: function(fixture){ 112 this._fixture = fixture; 113 }, 114 115 getB2Fixture: function(){ 116 return this._fixture; 117 }, 118 119 /** 120 * shape getter 121 * @param {ccs.Shape} shape 122 */ 123 setShape: function (shape) { 124 this.shape = shape; 125 }, 126 127 /** 128 * shape setter 129 * @return {ccs.Shape} 130 */ 131 getShape: function () { 132 return this.shape; 133 }, 134 135 /** 136 * contourData setter 137 * @param {ccs.ContourData} contourData 138 */ 139 setContourData: function (contourData) { 140 this.coutourData = contourData; 141 }, 142 143 /** 144 * colliderFilter getter 145 * @returns {ccs.ColliderFilter} 146 */ 147 getColliderFilter: function () { 148 return this.colliderFilter; 149 } 150 }); 151 152 /** 153 * Base class for ccs.ColliderDetector 154 * @class 155 * @extends ccs.Class 156 * 157 * @param {ccs.Bone} [bone] 158 * 159 * @property {ccs.ColliderFilter} colliderFilter - The collider filter of the collider detector 160 * @property {Boolean} active - Indicate whether the collider detector is active 161 * @property {Object} body - The collider body 162 */ 163 ccs.ColliderDetector = ccs.Class.extend(/** @lends ccs.ColliderDetector# */{ 164 _colliderBodyList: null, 165 _bone: null, 166 _body: null, 167 _active: false, 168 _filter: null, 169 helpPoint: cc.p(0, 0), 170 171 ctor: function (bone) { 172 this._colliderBodyList = []; 173 this._bone = null; 174 this._body = null; 175 this._active = false; 176 this._filter = null; 177 178 ccs.ColliderDetector.prototype.init.call(this, bone); 179 }, 180 init: function (bone) { 181 this._colliderBodyList.length = 0; 182 if (bone) 183 this._bone = bone; 184 this._filter = new ccs.ColliderFilter(); 185 return true; 186 }, 187 188 /** 189 * add contourData 190 * @param {ccs.ContourData} contourData 191 */ 192 addContourData: function (contourData) { 193 var colliderBody = new ccs.ColliderBody(contourData); 194 this._colliderBodyList.push(colliderBody); 195 196 if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) { 197 var calculatedVertexList = colliderBody.getCalculatedVertexList(); 198 var vertexList = contourData.vertexList; 199 for (var i = 0; i < vertexList.length; i++) { 200 var newVertex = new ccs.ContourVertex2(0, 0); 201 calculatedVertexList.push(newVertex); 202 } 203 } 204 }, 205 206 /** 207 * add contourData 208 * @param {Array} contourDataList 209 */ 210 addContourDataList: function (contourDataList) { 211 for (var i = 0; i < contourDataList.length; i++) { 212 this.addContourData(contourDataList[i]); 213 } 214 }, 215 216 /** 217 * remove contourData 218 * @param contourData 219 */ 220 removeContourData: function (contourData) { 221 var eraseList = [], i, locBodyList = this._colliderBodyList; 222 for (i = 0; i < locBodyList.length; i++) { 223 var body = locBodyList[i]; 224 if (body && body.getContourData() === contourData) 225 eraseList.push(body); 226 } 227 228 for (i=0; i<eraseList.length; i++) 229 cc.arrayRemoveObject(locBodyList, eraseList[i]); 230 }, 231 232 /** 233 * remove all body 234 */ 235 removeAll: function () { 236 this._colliderBodyList.length = 0; 237 }, 238 239 setActive: function (active) { 240 if (this._active === active) 241 return; 242 this._active = active; 243 244 var locBody = this._body; 245 var locShape; 246 if (locBody) { 247 var colliderBody = null; 248 if (this._active) { 249 for (var i = 0; i < this._colliderBodyList.length; i++) { 250 colliderBody = this._colliderBodyList[i]; 251 locShape = colliderBody.getShape(); 252 locBody.space.addShape(locShape); 253 } 254 } else { 255 for (var i = 0; i < this._colliderBodyList.length; i++) { 256 colliderBody = this._colliderBodyList[i]; 257 locShape = colliderBody.getShape(); 258 locBody.space.removeShape(locShape); 259 } 260 } 261 } 262 }, 263 264 getActive: function () { 265 return this._active; 266 }, 267 268 getColliderBodyList: function(){ 269 return this._colliderBodyList; 270 }, 271 272 /** 273 * set colliderFilter 274 * @param {ccs.ColliderFilter} filter 275 */ 276 setColliderFilter: function (filter) { 277 this._filter = filter; 278 var locBodyList = this._colliderBodyList; 279 for(var i=0; i< locBodyList.length; i++){ 280 var colliderBody = locBodyList[i]; 281 colliderBody.setColliderFilter(filter); 282 if (colliderBody.getShape()) 283 colliderBody.getColliderFilter().updateShape(colliderBody.getShape()); 284 } 285 }, 286 287 /** 288 * get colliderFilter 289 * @returns {ccs.ColliderFilter} 290 */ 291 getColliderFilter: function () { 292 return this._filter; 293 }, 294 295 updateTransform: function (t) { 296 if (!this._active) 297 return; 298 299 var colliderBody = null; 300 var locBody = this._body; 301 var locHelpPoint = this.helpPoint; 302 for (var i = 0; i < this._colliderBodyList.length; i++) { 303 304 colliderBody = this._colliderBodyList[i]; 305 var contourData = colliderBody.getContourData(); 306 307 //default physics engine: Chipmunk 308 var shape = null; 309 if (locBody) { 310 //Box2d shape = (b2PolygonShape *)colliderBody->getB2Fixture()->GetShape(); 311 shape = colliderBody.getShape(); 312 } 313 314 var vs = contourData.vertexList; 315 var cvs = colliderBody.getCalculatedVertexList(); 316 317 for (var j = 0; j < vs.length; j++) { 318 locHelpPoint.x = vs[j].x; 319 locHelpPoint.y = vs[j].y; 320 locHelpPoint = cc.pointApplyAffineTransform(locHelpPoint, t); 321 322 if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) { 323 var v = cc.p(0, 0); 324 v.x = locHelpPoint.x; 325 v.y = locHelpPoint.y; 326 cvs[j] = v; 327 } 328 329 if (shape) { 330 shape.verts[j * 2] = locHelpPoint.x; 331 shape.verts[j * 2 + 1] = locHelpPoint.y; 332 } 333 } 334 if (shape) { 335 for (var j = 0; j < vs.length; j++) { 336 var b = shape.verts[(j + 1) % shape.verts.length]; 337 var n = cp.v.normalize(cp.v.perp(cp.v.sub(b, shape.verts[j]))); 338 339 if(shape.planes){ 340 shape.planes[j].n = n; 341 shape.planes[j].d = cp.v.dot(n, shape.verts[j]); 342 } 343 // var b = shape.verts[(i + 1) % shape.numVerts]; 344 // var n = cp.v.normalize(cp.v.perp(cp.v.sub(b, shape.verts[i]))); 345 // 346 // shape.planes[i].n = n; 347 // shape.planes[i].d = cp.v.dot(n, shape.verts[i]); 348 } 349 } 350 } 351 }, 352 353 setBody: function (body) { 354 this._body = body; 355 var colliderBody, locBodyList = this._colliderBodyList; 356 for (var i = 0; i < locBodyList.length; i++) { 357 colliderBody = locBodyList[i]; 358 var contourData = colliderBody.getContourData(), verts = []; 359 var vs = contourData.vertexList; 360 for (var j = 0; j < vs.length; j++) { 361 var v = vs[j]; 362 verts.push(v.x); 363 verts.push(v.y); 364 } 365 var shape = new cp.PolyShape(this._body, verts, cp.vzero); 366 shape.sensor = true; 367 shape.data = this._bone; 368 if (this._active) 369 this._body.space.addShape(shape); 370 colliderBody.setShape(shape); 371 colliderBody.getColliderFilter().updateShape(shape); 372 } 373 }, 374 375 getBody: function () { 376 return this._body; 377 } 378 }); 379 380 var _p = ccs.ColliderDetector.prototype; 381 382 // Extended properties 383 /** @expose */ 384 _p.colliderFilter; 385 cc.defineGetterSetter(_p, "colliderFilter", _p.getColliderFilter, _p.setColliderFilter); 386 /** @expose */ 387 _p.active; 388 cc.defineGetterSetter(_p, "active", _p.getActive, _p.setActive); 389 /** @expose */ 390 _p.body; 391 cc.defineGetterSetter(_p, "body", _p.getBody, _p.setBody); 392 393 _p = null; 394 395 ccs.ColliderDetector.create = function (bone) { 396 return new ccs.ColliderDetector(bone); 397 };