1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3 
  4  http://www.cocos2d-x.org
  5 
  6  Permission is hereby granted, free of charge, to any person obtaining a copy
  7  of this software and associated documentation files (the "Software"), to deal
  8  in the Software without restriction, including without limitation the rights
  9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10  copies of the Software, and to permit persons to whom the Software is
 11  furnished to do so, subject to the following conditions:
 12 
 13  The above copyright notice and this permission notice shall be included in
 14  all copies or substantial portions of the Software.
 15 
 16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22  THE SOFTWARE.
 23  ****************************************************************************/
 24 ccs.PT_RATIO = 32;
 25 /**
 26  * Base class for ccs.ColliderFilter
 27  * @class
 28  * @extends ccs.Class
 29  */
 30 ccs.ColliderFilter = ccs.Class.extend(/** @lends ccs.ColliderFilter# */{
 31     _collisionType: 0,
 32     _group: 0,
 33     ctor: function (collisionType, group) {
 34         this._collisionType = collisionType || 0;
 35         this._group = group || 0;
 36     },
 37     updateShape: function (shape) {
 38         shape.collision_type = this._collisionType;
 39         shape.group = this._group;
 40     }
 41 });
 42 /**
 43  * Base class for ccs.ColliderBody
 44  * @class
 45  * @extends ccs.Class
 46  */
 47 ccs.ColliderBody = ccs.Class.extend(/** @lends ccs.ColliderBody# */{
 48     _shape: null,
 49     _contourData: null,
 50     _filter:null,
 51     _calculatedVertexList:null,
 52     ctor: function (contourData) {
 53         this._shape = null;
 54         this._contourData = contourData;
 55         this._filter = new ccs.ColliderFilter();
 56         if(ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX){
 57             this._calculatedVertexList = [];
 58         }
 59     },
 60 
 61     /**
 62      * contourData getter
 63      * @returns {ccs.ContourData}
 64      */
 65     getContourData: function () {
 66         return this._contourData;
 67     },
 68 
 69     /**
 70      * contourData setter
 71      * @param {ccs.ContourData}contourData
 72      */
 73     setContourData: function (contourData) {
 74         this._contourData = contourData;
 75     },
 76 
 77     /**
 78      * shape setter
 79      * @param {cs.Shape}contourData
 80      */
 81     getShape: function () {
 82         return this._shape;
 83     },
 84 
 85     /**
 86      * shape getter
 87      * @param {cs.Shape} shage
 88      */
 89     setShape: function (shage) {
 90         this._shape = shage;
 91     },
 92 
 93     /**
 94      * colliderFilter getter
 95      * @returns {ccs.ColliderFilter}
 96      */
 97     getColliderFilter: function () {
 98         return this._filter;
 99     },
100 
101     /**
102      * colliderFilter setter
103      * @param {ccs.ColliderFilter} filter
104      */
105     setColliderFilter: function (filter) {
106         this._filter = filter;
107     },
108 
109     /**
110      * get calculated vertex list
111      * @returns {Array}
112      */
113     getCalculatedVertexList:function(){
114         return this._calculatedVertexList;
115     }
116 });
117 
118 /**
119  * Base class for ccs.ColliderDetector
120  * @class
121  * @extends ccs.Class
122  */
123 ccs.ColliderDetector = ccs.Class.extend(/** @lends ccs.ColliderDetector# */{
124     _colliderBodyList: null,
125     _bone: null,
126     _body: null,
127     _active: false,
128     _filter: null,
129     ctor: function () {
130         this._colliderBodyList = [];
131         this._bone = null;
132         this._body = null;
133         this._active = false;
134         this._filter = null;
135     },
136     init: function (bone) {
137         this._colliderBodyList = [];
138         if (bone)
139             this._bone = bone;
140         this._filter = new ccs.ColliderFilter();
141         return true;
142     },
143 
144     /**
145      *  add contourData
146      * @param {ccs.ContourData} contourData
147      */
148     addContourData: function (contourData) {
149         var colliderBody = new ccs.ColliderBody(contourData);
150         this._colliderBodyList.push(colliderBody);
151         if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
152             var calculatedVertexList = colliderBody.getCalculatedVertexList();
153             var vertexList = contourData.vertexList;
154             for (var i = 0; i < vertexList.length; i++) {
155                 var newVertex = new ccs.ContourVertex2(0, 0);
156                 calculatedVertexList.push(newVertex);
157             }
158         }
159     },
160 
161     /**
162      * add contourData
163      * @param {Array} contourDataList
164      */
165     addContourDataList: function (contourDataList) {
166         for (var i = 0; i < contourDataList.length; i++) {
167             this.addContourData(contourDataList[i]);
168         }
169     },
170 
171     /**
172      * remove contourData
173      * @param contourData
174      */
175     removeContourData: function (contourData) {
176         var locColliderBodyList = this._colliderBodyList;
177         for (var i = 0; i < locColliderBodyList.length; i++) {
178             if(locColliderBodyList[i].getContourData()==contourData){
179                 locColliderBodyList.splice(i, 1);
180                 return;
181             }
182         }
183     },
184 
185     /**
186      * remove all body
187      */
188     removeAll: function () {
189         this._colliderBodyList = [];
190     },
191 
192     /**
193      * set colliderFilter
194      * @param {ccs.ColliderFilter} filter
195      */
196     setColliderFilter: function (filter) {
197         this._filter = filter;
198         for (var i = 0; i < this._colliderBodyList.length; i++) {
199             var colliderBody = this._colliderBodyList[i];
200             colliderBody.setColliderFilter(filter);
201             if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT) {
202                 if (colliderBody.getShape()) {
203                     colliderBody.getColliderFilter().updateShape(colliderBody.getShape());
204                 }
205             }
206         }
207     },
208 
209     /**
210      * get colliderFilter
211      * @returns {ccs.ColliderFilter}
212      */
213     getColliderFilter:function(){
214         return this._filter;
215     },
216 
217     setActive: function (active) {
218         if (this._active == active)
219             return;
220         this._active = active;
221         var locBody = this._body;
222         var locShape;
223         if (locBody) {
224             var colliderBody = null;
225             if (this._active) {
226                 for (var i = 0; i < this._colliderBodyList.length; i++) {
227                     colliderBody = this._colliderBodyList[i];
228                     locShape = colliderBody.getShape();
229                     locBody.space.addShape(locShape);
230                 }
231             }
232             else {
233                 for (var i = 0; i < this._colliderBodyList.length; i++) {
234                     colliderBody = this._colliderBodyList[i];
235                     locShape = colliderBody.getShape();
236                     locBody.space.removeShape(locShape);
237                 }
238             }
239         }
240     },
241     getActive: function () {
242         return this._active;
243     },
244     getColliderBodyList: function () {
245         return this._colliderBodyList;
246     },
247     helpPoint: cc.p(0, 0),
248     updateTransform: function (t) {
249         if (!this._active)
250             return;
251 
252         var colliderBody = null;
253         var locBody = this._body;
254         var locHelpPoint = this.helpPoint;
255         for (var i = 0; i < this._colliderBodyList.length; i++) {
256             colliderBody = this._colliderBodyList[i];
257             var contourData = colliderBody.getContourData();
258             var shape = null;
259             if (locBody) {
260                 shape = colliderBody.getShape();
261                 locBody.p.x = t.tx;
262                 locBody.p.y = t.ty;
263                 locBody.p.a = t.a;
264             }
265             var vs = contourData.vertexList;
266             var cvs = colliderBody.getCalculatedVertexList();
267             for (var i = 0; i < vs.length; i++) {
268                 locHelpPoint.x = vs[i].x;
269                 locHelpPoint.y = vs[i].y;
270                 locHelpPoint = cc.PointApplyAffineTransform(locHelpPoint, t);
271                 if (shape) {
272                     shape.verts[i * 2] = locHelpPoint.x - t.tx;
273                     shape.verts[i * 2 + 1] = locHelpPoint.y - t.ty;
274                 }
275                 if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
276                     var v =  cc.p(0, 0);
277                     v.x = locHelpPoint.x;
278                     v.y = locHelpPoint.y;
279                     cvs[i] = v;
280                 }
281             }
282         }
283     },
284     getBody: function () {
285         return this._body;
286     },
287     setBody: function (body) {
288         this._body = body;
289         var colliderBody;
290         for (var i = 0; i < this._colliderBodyList.length; i++) {
291             colliderBody = this._colliderBodyList[i];
292             var contourData = colliderBody.getContourData();
293             var verts = [];
294             var vs = contourData.vertexList;
295             for (var i = 0; i < vs.length; i++) {
296                 var v = vs[i];
297                 verts.push(v.x);
298                 verts.push(v.y);
299             }
300             var shape = new cp.PolyShape(this._body, verts, cp.vzero);
301             shape.sensor = true;
302             shape.data = this._bone;
303             if (this._active){
304                 this._body.space.addShape(shape);
305             }
306             colliderBody.setShape(shape);
307             colliderBody.getColliderFilter().updateShape(shape);
308         }
309     }
310 });
311 ccs.ColliderDetector.create = function (bone) {
312     var colliderDetector = new ccs.ColliderDetector();
313     if (colliderDetector && colliderDetector.init(bone)) {
314         return colliderDetector;
315     }
316     return null;
317 };