========================================================== =============================== Original blog, reprinted please declare the source of Electronic coffee (original id blue rock) ========================================================== ================================
Thanks to all the contributors to the open-source community.
One-dimensional water wave effect, address: http://www.supersuraccoon-cocos2d.com/2011/09/17/sticky-demo-resource-list-keep-updating/
Water Waves are mainly implemented by waves1dnode. For more information, see code comments. As follows:
Waves1dnode. h
#import "cocos2d.h"@interface Waves1DNode : CCNode {CGRect _bounds;float _diffusion;float _damping;int _count;// Heightfields that the simulation verlet integrates between.float *_h1, *_h2;}// 'bounds' are the rectangle to draw for the water. The top of the bounds is the rest height for the water, it wil wave above and below it.// 'count' is the number of slices to simulate. One per 10-20 pixels is usually sufficient.// 'damping' is how fast the water settles back to rest. 1.0 is never (bad), 0.0 is immediately (also bad). 0.99 is a decent damping amount.// 'diffusion' is how fast the waves spread to neighbors. Values outside of 0.6 - 0.9 can become unstable.-(id)initWithBounds:(CGRect)bounds count:(int)count damping:(float)damping diffusion:(float)diffusion;-(void)makeSplashAt:(float)x;
Waves1dnode. m
# Import "waves1dnode. H "@ implementation waves1dnode/** bounds water depth count horizontal vertex number. The larger the number, the more realistic the damping */-(ID) initwithbounds :( cgrect) bounds count :( INT) count damping :( float) damping diffusion :( float) diffusion; {If (Self = [Super init]) {_ bounds = bounds; _ COUNT = count; _ damping = damping; _ diffusion = diffusion; _ H1 = calloc (_ count, sizeof (float); _ H2 = calloc (_ count, sizeof (float);} return self ;} -(void) dealloc {free (_ H1); free (_ H2); [Super dealloc];}/** in-house engine algorithms that affect Motion, reference http://en.wikipedia.org/wiki/Verlet_integration */-(void) verlet {for (INT I = 0; I <_ count; I ++) {_ H1 [I] = 2.0 * _ H2 [I]-_ H1 [I];} float * temp = _ H2; _ H2 = _ H1; _ H1 = temp;} static inline floatdiffuse (float diff, float damp, float Prev, float curr, float next) {return (curr * diff + (prev + next) * 0.5f) * (1.0f-diff) * damp;} // conduct damping calculation-(void) Diffuse {float Prev = _ H2 [0]; float curr = _ H2 [0]; float next = _ H2 [1]; _ H2 [0] = diffuse (_ diffusion, _ damping, Prev, curr, next ); for (INT I = 1; I <(_ count-1); ++ I) {Prev = curr; curr = next; next = _ H2 [I + 1]; _ H2 [I] = diffuse (_ diffusion, _ damping, Prev, curr, next);} Prev = curr; curr = next; _ H2 [_ count-1] = diffuse (_ diffusion, _ damping, Prev, curr, next);} // DX distance between two adjacent points (count points) -(float) dx {return _ bounds. size. width/(glfloat) (_ count-1);}-(void) Draw {// It wocould be better to run these on a fixed timestep. // as an GFX only effect it doesn' t really matter though. // perform the simulate calculation of verlet and diffuse [self verlet]; [self diffuse]; glfloat dx = [self dx]; glfloat Top = _ bounds. size. height; // build a vertex array and render it. struct vertex {glfloat X, Y ;}; // OpenGL draws triangle elements. array painting can share one vertex. Therefore, only two vertices are drawn, so * 2 struct vertex Verts [_ count * 2]; for (INT I = 0; I <_ count; I ++) {glfloat x = I * DX; // Verts at the bottom [2 * I + 0] = (struct vertex) {X, 0 }; // top + _ H2 [I] is the water depth + corresponding wave fluctuations Verts [2 * I + 1] = (struct vertex) {X, top + _ H2 [I] };}// by default, all client-side capabilities are disabled. // The default value is disable. In cocos2d, enable // printf ("% s: % d % I, % I \ n ", __function __,__ line __, glisenabled (gl_color_array), \ glisenabled (Enabled), glisenabled (Enabled), glisenabled (gl_vertex_array); Disabled (gl_color_array); Disabled (enabled ); gldisable (random); // random (gl_vertex_array); glfloat r = 105.0f/255.0f; glfloat G = 193.0f/255.0f; glfloat B = 212.0f/255.0f; glfloat A = 0.3f; glcolor4f (R * a, G * a, B * a, a); // specify the vertex array glvertexpointer (2, gl_float, 0, Verts ); // because translate is to be performed later, push matrixglpushmatrix (); {// optimize glscalef (cc_content_scale_factor (), cc_content_scale_factor (), 1.0) for retina ); // translate the water to the bound position; otherwise, gltranslatef (_ bounds) at (0, 0. origin. x, _ bounds. origin. y, 0.0); // gldrawarrays (gl_triangle_fan, 0, _ count * 2); // draw the gldrawarrays (gl_triangle_strip, 0, _ count * 2);} glpopmatrix (); glableclientstate (gl_color_array); glableclientstate (gradient); gl_texture_2d); glcolor4f (1.0f, 1.0f, 1.0f, 1.0f);}-(void) makesplashat :( float) X; {// changing the values of heightfield in H2 will make the waves move. // here I only change one column, but you get the idea. // change a bunch of the heights using a nice smoothing function for a better before t.int Index = max (0, min (INT) (X/[self dx]), _ count-1); _ H2 [Index] + = ccrandom_minus1_1 () * 20.0;} @ end