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