1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 /**
 28  * get a random number from 0 to 0xffffff
 29  * @function
 30  * @returns {number}
 31  */
 32 cc.rand = function () {
 33     return Math.random() * 0xffffff;
 34 };
 35 /**
 36  * cc.Waves3D action
 37  * @class
 38  * @extends cc.Grid3DAction
 39  */
 40 cc.Waves3D = cc.Grid3DAction.extend(/** @lends cc.Waves3D# */{
 41     _waves:null,
 42     _amplitude:null,
 43     _amplitudeRate:null,
 44 
 45     ctor:function () {
 46         cc.GridAction.prototype.ctor.call(this);
 47 
 48         this._waves = 0;
 49         this._amplitude = 0;
 50         this._amplitudeRate = 0;
 51     },
 52 
 53     /**
 54      * get Amplitude
 55      * @return {Number}
 56      */
 57     getAmplitude:function () {
 58         return this._amplitude;
 59     },
 60 
 61     /**
 62      * set Amplitude
 63      * @param {Number} amplitude
 64      */
 65     setAmplitude:function (amplitude) {
 66         this._amplitude = amplitude;
 67     },
 68 
 69     /**
 70      * get Amplitude Rate
 71      * @return {Number}
 72      */
 73     getAmplitudeRate:function () {
 74         return this._amplitudeRate;
 75     },
 76 
 77     /**
 78      * set Amplitude Rate
 79      * @param {Number} amplitudeRate
 80      */
 81     setAmplitudeRate:function (amplitudeRate) {
 82         this._amplitudeRate = amplitudeRate;
 83     },
 84 
 85     /**
 86      * initializes an action with duration, grid size, waves and amplitude
 87      * @param {Number} duration
 88      * @param {cc.Size} gridSize
 89      * @param {Number} waves
 90      * @param {Number} amplitude
 91      * @return {Boolean}
 92      */
 93     initWithDuration:function (duration, gridSize, waves, amplitude) {
 94         if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
 95             this._waves = waves;
 96             this._amplitude = amplitude;
 97             this._amplitudeRate = 1.0;
 98             return true;
 99         }
100         return false;
101     },
102 
103     update:function (time) {
104         var locGridSize = this._gridSize;
105         var locAmplitude = this._amplitude, locPos = cc.p(0, 0);
106         var locAmplitudeRate = this._amplitudeRate, locWaves = this._waves;
107         for (var i = 0; i < locGridSize.width + 1; ++i) {
108             for (var j = 0; j < locGridSize.height + 1; ++j) {
109                 locPos.x = i;
110                 locPos.y = j;
111                 var v = this.originalVertex(locPos);
112                 v.z += (Math.sin(Math.PI * time * locWaves * 2 + (v.y + v.x) * 0.01) * locAmplitude * locAmplitudeRate);
113                 //cc.log("v.z offset is" + (Math.sin(Math.PI * time * this._waves * 2 + (v.y + v.x) * 0.01) * this._amplitude * this._amplitudeRate));
114                 this.setVertex(locPos, v);
115             }
116         }
117     }
118 });
119 
120 /**
121  * creates an action with duration, grid size, waves and amplitude
122  * @param {Number} duration
123  * @param {cc.Size} gridSize
124  * @param {Number} waves
125  * @param {Number} amplitude
126  * @return {cc.Waves3D}
127  */
128 cc.Waves3D.create = function (duration, gridSize, waves, amplitude) {
129     var action = new cc.Waves3D();
130     action.initWithDuration(duration, gridSize, waves, amplitude);
131     return action;
132 };
133 
134 /**
135  * cc.FlipX3D action
136  * @class
137  * @extends cc.Grid3DAction
138  */
139 cc.FlipX3D = cc.Grid3DAction.extend(/** @lends cc.FlipX3D# */{
140     /**
141      * initializes the action with duration
142      * @param {Number} duration
143      * @return {Boolean}
144      */
145     initWithDuration:function (duration) {
146         return cc.Grid3DAction.prototype.initWithDuration.call(this, duration, cc.size(1, 1));
147     },
148 
149     /**
150      * initializes the action with gridSize and duration
151      * @param {cc.Size} gridSize
152      * @param {Number} duration
153      * @return {Boolean}
154      */
155     initWithSize:function (gridSize, duration) {
156         if (gridSize.width != 1 || gridSize.height != 1) {
157             // Grid size must be (1,1)
158             cc.log("Grid size must be (1,1)");
159             return false;
160         }
161         return  cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize);
162     },
163 
164     update:function (time) {
165         var angle = Math.PI * time; // 180 degrees
166         var mz = Math.sin(angle);
167         angle = angle / 2.0; // x calculates degrees from 0 to 90
168         var mx = Math.cos(angle);
169 
170         var diff = new cc.Vertex3F();
171         var tempVer = cc.p(0, 0);
172         tempVer.x = tempVer.y = 1;
173         var v0 = this.originalVertex(tempVer);
174         tempVer.x = tempVer.y = 0;
175         var v1 = this.originalVertex(tempVer);
176 
177         var x0 = v0.x;
178         var x1 = v1.x;
179         var x;
180         var a, b, c, d;
181 
182         if (x0 > x1) {
183             // Normal Grid
184             a = cc.p(0, 0);
185             b = cc.p(0, 1);
186             c = cc.p(1, 0);
187             d = cc.p(1, 1);
188             x = x0;
189         } else {
190             // Reversed Grid
191             c = cc.p(0, 0);
192             d = cc.p(0, 1);
193             a = cc.p(1, 0);
194             b = cc.p(1, 1);
195             x = x1;
196         }
197 
198         diff.x = ( x - x * mx );
199         diff.z = Math.abs(parseFloat((x * mz) / 4.0));
200 
201         // bottom-left
202         var v = this.originalVertex(a);
203         v.x = diff.x;
204         v.z += diff.z;
205         this.setVertex(a, v);
206 
207         // upper-left
208         v = this.originalVertex(b);
209         v.x = diff.x;
210         v.z += diff.z;
211         this.setVertex(b, v);
212 
213         // bottom-right
214         v = this.originalVertex(c);
215         v.x -= diff.x;
216         v.z -= diff.z;
217         this.setVertex(c, v);
218 
219         // upper-right
220         v = this.originalVertex(d);
221         v.x -= diff.x;
222         v.z -= diff.z;
223         this.setVertex(d, v);
224     }
225 });
226 
227 /**
228  * creates FlipX3D action with duration
229  * @param {Number} duration
230  * @return {cc.FlipX3D}
231  */
232 cc.FlipX3D.create = function (duration) {
233     var action = new cc.FlipX3D();
234     action.initWithDuration(duration);
235     return action;
236 };
237 
238 /**
239  * cc.FlipY3D action
240  * @class
241  * @extends cc.FlipX3D
242  */
243 cc.FlipY3D = cc.FlipX3D.extend(/** @lends cc.FlipY3D# */{
244     update:function (time) {
245         var angle = Math.PI * time; // 180 degrees
246         var mz = Math.sin(angle);
247         angle = angle / 2.0;     // x calculates degrees from 0 to 90
248         var my = Math.cos(angle);
249 
250         var diff = new cc.Vertex3F();
251 
252         var tempP = cc.p(0, 0);
253         tempP.x = tempP.y = 1;
254         var v0 = this.originalVertex(tempP);
255         tempP.x = tempP.y = 0;
256         var v1 = this.originalVertex(tempP);
257 
258         var y0 = v0.y;
259         var y1 = v1.y;
260         var y;
261         var a, b, c, d;
262 
263         if (y0 > y1) {
264             // Normal Grid
265             a = cc.p(0, 0);
266             b = cc.p(0, 1);
267             c = cc.p(1, 0);
268             d = cc.p(1, 1);
269             y = y0;
270         } else {
271             // Reversed Grid
272             b = cc.p(0, 0);
273             a = cc.p(0, 1);
274             d = cc.p(1, 0);
275             c = cc.p(1, 1);
276             y = y1;
277         }
278 
279         diff.y = y - y * my;
280         diff.z = Math.abs(parseFloat(y * mz) / 4.0);
281 
282         // bottom-left
283         var v = this.originalVertex(a);
284         v.y = diff.y;
285         v.z += diff.z;
286         this.setVertex(a, v);
287 
288         // upper-left
289         v = this.originalVertex(b);
290         v.y -= diff.y;
291         v.z -= diff.z;
292         this.setVertex(b, v);
293 
294         // bottom-right
295         v = this.originalVertex(c);
296         v.y = diff.y;
297         v.z += diff.z;
298         this.setVertex(c, v);
299 
300         // upper-right
301         v = this.originalVertex(d);
302         v.y -= diff.y;
303         v.z -= diff.z;
304         this.setVertex(d, v);
305     }
306 });
307 
308 /**
309  * creates the action with duration
310  * @param {Number} duration
311  * @return {cc.FlipY3D}
312  */
313 cc.FlipY3D.create = function (duration) {
314     var action = new cc.FlipY3D();
315     action.initWithDuration(duration);
316     return action;
317 };
318 
319 /**
320  * cc.Lens3D action
321  * @class
322  * @extends cc.FlipX3D
323  */
324 cc.Lens3D = cc.Grid3DAction.extend(/** @lends cc.Lens3D# */{
325     /* lens center position */
326     _position:null,
327     _radius:0,
328     /** lens effect. Defaults to 0.7 - 0 means no effect, 1 is very strong effect */
329     _lensEffect:0,
330     /** lens is concave. (true = concave, false = convex) default is convex i.e. false */
331     _concave:false,
332     _dirty:false,
333 
334     ctor:function () {
335         cc.GridAction.prototype.ctor.call(this);
336 
337         this._position = cc.p(0, 0);
338         this._radius = 0;
339         this._lensEffect = 0;
340         this._concave = false;
341         this._dirty = false;
342     },
343 
344     /**
345      * Get lens center position
346      * @return {Number}
347      */
348     getLensEffect:function () {
349         return this._lensEffect;
350     },
351 
352     /**
353      * Set lens center position
354      * @param {Number} lensEffect
355      */
356     setLensEffect:function (lensEffect) {
357         this._lensEffect = lensEffect;
358     },
359 
360     /**
361      * Set whether lens is concave
362      * @param {Boolean} concave
363      */
364     setConcave:function (concave) {
365         this._concave = concave;
366     },
367 
368     /**
369      * get Position
370      * @return {cc.Point}
371      */
372     getPosition:function () {
373         return this._position;
374     },
375 
376     /**
377      * set Position
378      * @param {cc.Point} position
379      */
380     setPosition:function (position) {
381         if (!cc.pointEqualToPoint(position, this._position)) {
382             this._position.x = position.x;
383             this._position.y = position.y;
384             this._dirty = true;
385         }
386     },
387 
388     /**
389      * initializes the action with center position, radius, a grid size and duration
390      * @param {Number} duration
391      * @param {cc.Size} gridSize
392      * @param {cc.Point} position
393      * @param {Number} radius
394      * @return {Boolean}
395      */
396     initWithDuration:function (duration, gridSize, position, radius) {
397         if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
398             this.setPosition(position);
399             this._radius = radius;
400             this._lensEffect = 0.7;
401             this._dirty = true;
402             return true;
403         }
404         return false;
405     },
406 
407     update:function (time) {
408         if (this._dirty) {
409             var locGridSizeWidth = this._gridSize.width, locGridSizeHeight = this._gridSize.height;
410             var locRadius = this._radius, locLensEffect = this._lensEffect;
411             var locPos = cc.p(0, 0);
412             var vect = cc.p(0, 0);
413             var v, r, l, new_r, pre_log;
414             for (var i = 0; i < locGridSizeWidth + 1; ++i) {
415                 for (var j = 0; j < locGridSizeHeight + 1; ++j) {
416                     locPos.x = i;
417                     locPos.y = j;
418                     v = this.originalVertex(locPos);
419                     vect.x = this._position.x - v.x;
420                     vect.y = this._position.y - v.y;
421                     r = cc.pLength(vect);
422 
423                     if (r < locRadius) {
424                         r = locRadius - r;
425                         pre_log = r / locRadius;
426                         if (pre_log == 0)
427                             pre_log = 0.001;
428 
429                         l = Math.log(pre_log) * locLensEffect;
430                         new_r = Math.exp(l) * locRadius;
431 
432                         r = cc.pLength(vect);
433                         if (r > 0) {
434                             vect.x = vect.x / r;
435                             vect.y = vect.y / r;
436 
437                             vect.x = vect.x * new_r;
438                             vect.y = vect.y * new_r;
439                             v.z += cc.pLength(vect) * locLensEffect;
440                         }
441                     }
442                     this.setVertex(locPos, v);
443                 }
444             }
445             this._dirty = false;
446         }
447     }
448 });
449 
450 /**
451  * creates the action with center position, radius, a grid size and duration
452  * @param {Number} duration
453  * @param {cc.Size} gridSize
454  * @param {cc.Point} position
455  * @param {Number} radius
456  * @return {cc.Lens3D}
457  */
458 cc.Lens3D.create = function (duration, gridSize, position, radius) {
459     var action = new cc.Lens3D();
460     action.initWithDuration(duration, gridSize, position, radius);
461     return action;
462 };
463 
464 /**
465  * cc.Ripple3D action
466  * @class
467  * @extends cc.Grid3DAction
468  */
469 cc.Ripple3D = cc.Grid3DAction.extend(/** @lends cc.Ripple3D# */{
470     /* center position */
471     _position:null,
472     _radius:null,
473     _waves:null,
474     _amplitude:null,
475     _amplitudeRate:null,
476 
477     ctor:function () {
478         cc.GridAction.prototype.ctor.call(this);
479 
480         this._position = cc.p(0, 0);
481         this._radius = 0;
482         this._waves = 0;
483         this._amplitude = 0;
484         this._amplitudeRate = 0;
485     },
486 
487     /**
488      * get center position
489      * @return {cc.Point}
490      */
491     getPosition:function () {
492         return this._position;
493     },
494 
495     /**
496      * set center position
497      * @param {cc.Point} position
498      */
499     setPosition:function (position) {
500         this._position.x = position.x;
501         this._position.y = position.y;
502     },
503 
504     /**
505      * get Amplitude
506      * @return {Number}
507      */
508     getAmplitude:function () {
509         return this._amplitude;
510     },
511 
512     /**
513      * set Amplitude
514      * @param {Number} amplitude
515      */
516     setAmplitude:function (amplitude) {
517         this._amplitude = amplitude;
518     },
519 
520     /**
521      * get Amplitude rate
522      * @return {*}
523      */
524     getAmplitudeRate:function () {
525         return this._amplitudeRate;
526     },
527 
528     /**
529      * get amplitude rate
530      * @param {Number} amplitudeRate
531      */
532     setAmplitudeRate:function (amplitudeRate) {
533         this._amplitudeRate = amplitudeRate;
534     },
535 
536     /**
537      * initializes the action with radius, number of waves, amplitude, a grid size and duration
538      * @param {Number} duration
539      * @param {cc.Size} gridSize
540      * @param {cc.Point} position
541      * @param {Number} radius
542      * @param {Number} waves
543      * @param {Number} amplitude
544      * @return {Boolean}
545      */
546     initWithDuration:function (duration, gridSize, position, radius, waves, amplitude) {
547         if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
548             this.setPosition(position);
549             this._radius = radius;
550             this._waves = waves;
551             this._amplitude = amplitude;
552             this._amplitudeRate = 1.0;
553             return true;
554         }
555         return false;
556     },
557 
558     update:function (time) {
559         var locGridSizeWidth = this._gridSize.width, locGridSizeHeight = this._gridSize.height;
560         var locPos = cc.p(0, 0), locRadius = this._radius;
561         var locWaves = this._waves, locAmplitude = this._amplitude, locAmplitudeRate = this._amplitudeRate;
562         var v, r, tempPos = cc.p(0, 0);
563         for (var i = 0; i < (locGridSizeWidth + 1); ++i) {
564             for (var j = 0; j < (locGridSizeHeight + 1); ++j) {
565                 locPos.x = i;
566                 locPos.y = j;
567                 v = this.originalVertex(locPos);
568 
569                 tempPos.x = this._position.x - v.x;
570                 tempPos.y = this._position.y - v.y;
571                 r = cc.pLength(tempPos);
572 
573                 if (r < locRadius) {
574                     r = locRadius - r;
575                     var rate = Math.pow(r / locRadius, 2);
576                     v.z += (Math.sin(time * Math.PI * locWaves * 2 + r * 0.1) * locAmplitude * locAmplitudeRate * rate);
577                 }
578                 this.setVertex(locPos, v);
579             }
580         }
581     }
582 });
583 
584 /**
585  * creates the action with radius, number of waves, amplitude, a grid size and duration
586  * @param {Number} duration
587  * @param {cc.Size} gridSize
588  * @param {cc.Point} position
589  * @param {Number} radius
590  * @param {Number} waves
591  * @param {Number} amplitude
592  * @return {cc.Ripple3D}
593  */
594 cc.Ripple3D.create = function (duration, gridSize, position, radius, waves, amplitude) {
595     var action = new cc.Ripple3D();
596     action.initWithDuration(duration, gridSize, position, radius, waves, amplitude);
597     return action;
598 };
599 
600 /**
601  * cc.Shaky3D action
602  * @class
603  * @extends cc.Grid3DAction
604  */
605 cc.Shaky3D = cc.Grid3DAction.extend(/** @lends cc.Shaky3D# */{
606     _randRange:null,
607     _shakeZ:null,
608 
609     ctor:function () {
610         cc.GridAction.prototype.ctor.call(this);
611 
612         this._randRange = 0;
613         this._shakeZ = false;
614     },
615 
616     /**
617      * initializes the action with a range, shake Z vertices, a grid and duration
618      * @param {Number} duration
619      * @param {cc.Size} gridSize
620      * @param {Number} range
621      * @param {Boolean} shakeZ
622      * @return {Boolean}
623      */
624     initWithDuration:function (duration, gridSize, range, shakeZ) {
625         if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
626             this._randRange = range;
627             this._shakeZ = shakeZ;
628             return true;
629         }
630         return false;
631     },
632 
633     update:function (time) {
634         var locGridSizeWidth = this._gridSize.width, locGridSizeHeight = this._gridSize.height;
635         var locRandRange = this._randRange, locShakeZ = this._shakeZ, locP = cc.p(0, 0);
636         var v;
637         for (var i = 0; i < (locGridSizeWidth + 1); ++i) {
638             for (var j = 0; j < (locGridSizeHeight + 1); ++j) {
639                 locP.x = i;
640                 locP.y = j;
641                 v = this.originalVertex(locP);
642                 v.x += (cc.rand() % (locRandRange * 2)) - locRandRange;
643                 v.y += (cc.rand() % (locRandRange * 2)) - locRandRange;
644                 if (locShakeZ)
645                     v.z += (cc.rand() % (locRandRange * 2)) - locRandRange;
646                 this.setVertex(locP, v);
647             }
648         }
649     }
650 });
651 
652 /**
653  * creates the action with a range, shake Z vertices, a grid and duration
654  * @param {Number} duration
655  * @param {cc.Size} gridSize
656  * @param {Number} range
657  * @param {Boolean} shakeZ
658  * @return {cc.Shaky3D}
659  */
660 cc.Shaky3D.create = function (duration, gridSize, range, shakeZ) {
661     var action = new cc.Shaky3D();
662     action.initWithDuration(duration, gridSize, range, shakeZ);
663     return action;
664 };
665 
666 /**
667  * cc.Liquid action
668  * @class
669  * @extends cc.Grid3DAction
670  */
671 cc.Liquid = cc.Grid3DAction.extend(/** @lends cc.Liquid# */{
672     _waves:null,
673     _amplitude:null,
674     _amplitudeRate:null,
675 
676     ctor:function () {
677         cc.GridAction.prototype.ctor.call(this);
678 
679         this._waves = 0;
680         this._amplitude = 0;
681         this._amplitudeRate = 0;
682     },
683 
684     /**
685      * get amplitude
686      * @return {Number}
687      */
688     getAmplitude:function () {
689         return this._amplitude;
690     },
691 
692     /**
693      * set amplitude
694      * @param {Number} amplitude
695      */
696     setAmplitude:function (amplitude) {
697         this._amplitude = amplitude;
698     },
699 
700     /**
701      * get amplitude rate
702      * @return {Number}
703      */
704     getAmplitudeRate:function () {
705         return this._amplitudeRate;
706     },
707 
708     /**
709      * set amplitude rate
710      * @param {Number} amplitudeRate
711      */
712     setAmplitudeRate:function (amplitudeRate) {
713         this._amplitudeRate = amplitudeRate;
714     },
715 
716     /**
717      * initializes the action with amplitude, a grid and duration
718      * @param {Number} duration
719      * @param {cc.Size} gridSize
720      * @param {Number} waves
721      * @param {Number} amplitude
722      * @return {Boolean}
723      */
724     initWithDuration:function (duration, gridSize, waves, amplitude) {
725         if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
726             this._waves = waves;
727             this._amplitude = amplitude;
728             this._amplitudeRate = 1.0;
729             return true;
730         }
731         return false;
732     },
733 
734     update:function (time) {
735         var locSizeWidth = this._gridSize.width, locSizeHeight = this._gridSize.height, locPos = cc.p(0, 0);
736         var locWaves = this._waves, locAmplitude = this._amplitude, locAmplitudeRate = this._amplitudeRate;
737         var v;
738         for (var i = 1; i < locSizeWidth; ++i) {
739             for (var j = 1; j < locSizeHeight; ++j) {
740                 locPos.x = i;
741                 locPos.y = j;
742                 v = this.originalVertex(locPos);
743                 v.x = (v.x + (Math.sin(time * Math.PI * locWaves * 2 + v.x * .01) * locAmplitude * locAmplitudeRate));
744                 v.y = (v.y + (Math.sin(time * Math.PI * locWaves * 2 + v.y * .01) * locAmplitude * locAmplitudeRate));
745                 this.setVertex(locPos, v);
746             }
747         }
748     }
749 });
750 
751 /**
752  * creates the action with amplitude, a grid and duration
753  * @param {Number} duration
754  * @param {cc.Size} gridSize
755  * @param {Number} waves
756  * @param {Number} amplitude
757  * @return {cc.Liquid}
758  */
759 cc.Liquid.create = function (duration, gridSize, waves, amplitude) {
760     var action = new cc.Liquid();
761     action.initWithDuration(duration, gridSize, waves, amplitude);
762     return action;
763 };
764 
765 /**
766  * cc.Waves action
767  * @class
768  * @extends cc.Grid3DAction
769  */
770 cc.Waves = cc.Grid3DAction.extend(/** @lends cc.Waves# */{
771     _waves:null,
772     _amplitude:null,
773     _amplitudeRate:null,
774     _vertical:null,
775     _horizontal:null,
776 
777     ctor:function () {
778         cc.GridAction.prototype.ctor.call(this);
779 
780         this._waves = 0;
781         this._amplitude = 0;
782         this._amplitudeRate = 0;
783         this._vertical = false;
784         this._horizontal = false;
785     },
786 
787     /**
788      * get amplitude
789      * @return {Number}
790      */
791     getAmplitude:function () {
792         return this._amplitude;
793     },
794 
795     /**
796      * set amplitude
797      * @param {Number} amplitude
798      */
799     setAmplitude:function (amplitude) {
800         this._amplitude = amplitude;
801     },
802 
803     /**
804      * get amplitude rate
805      * @return {Number}
806      */
807     getAmplitudeRate:function () {
808         return this._amplitudeRate;
809     },
810 
811     /**
812      * set amplitude rate
813      * @param {Number} amplitudeRate
814      */
815     setAmplitudeRate:function (amplitudeRate) {
816         this._amplitudeRate = amplitudeRate;
817     },
818 
819     /**
820      * initializes the action with amplitude, horizontal sin, vertical sin, a grid and duration
821      * @param {Number} duration
822      * @param {cc.Size} gridSize
823      * @param {Number} waves
824      * @param {Number} amplitude
825      * @param {Boolean} horizontal
826      * @param {Boolean} vertical
827      * @return {Boolean}
828      */
829     initWithDuration:function (duration, gridSize, waves, amplitude, horizontal, vertical) {
830         if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
831             this._waves = waves;
832             this._amplitude = amplitude;
833             this._amplitudeRate = 1.0;
834             this._horizontal = horizontal;
835             this._vertical = vertical;
836             return true;
837         }
838         return false;
839     },
840 
841     update:function (time) {
842         var locSizeWidth = this._gridSize.width, locSizeHeight = this._gridSize.height, locPos = cc.p(0, 0);
843         var locVertical = this._vertical, locHorizontal = this._horizontal;
844         var locWaves = this._waves, locAmplitude = this._amplitude, locAmplitudeRate = this._amplitudeRate;
845         var v;
846         for (var i = 0; i < locSizeWidth + 1; ++i) {
847             for (var j = 0; j < locSizeHeight + 1; ++j) {
848                 locPos.x = i;
849                 locPos.y = j;
850                 v = this.originalVertex(locPos);
851                 if (locVertical)
852                     v.x = (v.x + (Math.sin(time * Math.PI * locWaves * 2 + v.y * .01) * locAmplitude * locAmplitudeRate));
853                 if (locHorizontal)
854                     v.y = (v.y + (Math.sin(time * Math.PI * locWaves * 2 + v.x * .01) * locAmplitude * locAmplitudeRate));
855                 this.setVertex(locPos, v);
856             }
857         }
858     }
859 });
860 
861 /**
862  * initializes the action with amplitude, horizontal sin, vertical sin, a grid and duration
863  * @param {Number} duration
864  * @param {cc.Size} gridSize
865  * @param {Number} waves
866  * @param {Number} amplitude
867  * @param {Boolean} horizontal
868  * @param {Boolean} vertical
869  * @return {cc.Waves}
870  */
871 cc.Waves.create = function (duration, gridSize, waves, amplitude, horizontal, vertical) {
872     var action = new cc.Waves();
873     action.initWithDuration(duration, gridSize, waves, amplitude, horizontal, vertical);
874     return action;
875 };
876 
877 /** @brief  */
878 /**
879  * cc.Twirl action
880  * @class
881  * @extends cc.Grid3DAction
882  */
883 cc.Twirl = cc.Grid3DAction.extend(/** @lends cc.Twirl# */{
884     /* twirl center */
885     _position:null,
886     _twirls:null,
887     _amplitude:null,
888     _amplitudeRate:null,
889 
890     ctor:function () {
891         cc.GridAction.prototype.ctor.call(this);
892 
893         this._position = cc.p(0, 0);
894         this._twirls = 0;
895         this._amplitude = 0;
896         this._amplitudeRate = 0;
897     },
898 
899     /**
900      * get twirl center
901      * @return {cc.Point}
902      */
903     getPosition:function () {
904         return this._position;
905     },
906 
907     /**
908      * set twirl center
909      * @param {cc.Point} position
910      */
911     setPosition:function (position) {
912         this._position.x = position.x;
913         this._position.y = position.y;
914     },
915 
916     /**
917      * get amplitude
918      * @return {Number}
919      */
920     getAmplitude:function () {
921         return this._amplitude;
922     },
923 
924     /**
925      * set amplitude
926      * @param {Number} amplitude
927      */
928     setAmplitude:function (amplitude) {
929         this._amplitude = amplitude;
930     },
931 
932     /**
933      * get amplitude rate
934      * @return {Number}
935      */
936     getAmplitudeRate:function () {
937         return this._amplitudeRate;
938     },
939 
940     /**
941      * set amplitude rate
942      * @param {Number} amplitudeRate
943      */
944     setAmplitudeRate:function (amplitudeRate) {
945         this._amplitudeRate = amplitudeRate;
946     },
947 
948     /** initializes the action with center position, number of twirls, amplitude, a grid size and duration */
949     initWithDuration:function (duration, gridSize, position, twirls, amplitude) {
950         if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
951             this.setPosition(position);
952             this._twirls = twirls;
953             this._amplitude = amplitude;
954             this._amplitudeRate = 1.0;
955             return true;
956         }
957         return false;
958     },
959 
960     update:function (time) {
961         var c = this._position;
962         var locSizeWidth = this._gridSize.width, locSizeHeight = this._gridSize.height, locPos = cc.p(0, 0);
963         var amp = 0.1 * this._amplitude * this._amplitudeRate;
964         var locTwirls = this._twirls;
965         var v, a, dX, dY, avg = cc.p(0, 0);
966         for (var i = 0; i < (locSizeWidth + 1); ++i) {
967             for (var j = 0; j < (locSizeHeight + 1); ++j) {
968                 locPos.x = i;
969                 locPos.y = j;
970                 v = this.originalVertex(locPos);
971 
972                 avg.x = i - (locSizeWidth / 2.0);
973                 avg.y = j - (locSizeHeight / 2.0);
974 
975                 a = cc.pLength(avg) * Math.cos(Math.PI / 2.0 + time * Math.PI * locTwirls * 2) * amp;
976 
977                 dX = Math.sin(a) * (v.y - c.y) + Math.cos(a) * (v.x - c.x);
978                 dY = Math.cos(a) * (v.y - c.y) - Math.sin(a) * (v.x - c.x);
979 
980                 v.x = c.x + dX;
981                 v.y = c.y + dY;
982 
983                 this.setVertex(locPos, v);
984             }
985         }
986     }
987 });
988 
989 /**
990  * creates the action with center position, number of twirls, amplitude, a grid size and duration
991  * @param {Number} duration
992  * @param {cc.Size} gridSize
993  * @param {cc.Point} position
994  * @param {Number} twirls
995  * @param {Number} amplitude
996  * @return {cc.Twirl}
997  */
998 cc.Twirl.create = function (duration, gridSize, position, twirls, amplitude) {
999     var action = new cc.Twirl();
1000     action.initWithDuration(duration, gridSize, position, twirls, amplitude);
1001     return action;
1002 };
1003