游戏效果解密----一维水波效果

来源:互联网 发布:java构造函数执行顺序 编辑:程序博客网 时间:2024/05/17 18:42
============================================================
博文原创,转载请声明出处
电子咖啡(原id蓝岩)
============================================================
感谢开源社区的所有贡献者。

一维水波效果地址:http://www.supersuraccoon-cocos2d.com/2011/09/17/sticky-demo-resource-list-keep-updating/

水波主要有Waves1DNode实现。详情见代码注释。截图如下:


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 水深度 count 水平vertex数目,越大,越逼真 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];}/**屋里引擎算法,牵动运动,参考 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;}//进行阻尼计算-(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 相邻两点的距离(count个点)-(float)dx{return _bounds.size.width/(GLfloat)(_count - 1);}- (void)draw {// It would be better to run these on a fixed timestep.// As an GFX only effect it doesn't really matter though.    //进行verlet和diffuse的simulate计算[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绘制三角形图元,数组绘制可以共用一个顶点,因此只绘制两个顶点,所以*2struct Vertex verts[_count*2];for(int i=0; i<_count; i++){GLfloat x = i*dx;//底部顶点        verts[2*i + 0] = (struct Vertex){x, 0};        // top + _h2[i] 为水深+对应的波浪起伏verts[2*i + 1] = (struct Vertex){x, top + _h2[i]};}        //By default, all client-side capabilities are disabled.    //默认是disable,这里是在cocos2d中enable的//    printf("%s:%d %i,%i,%i,%i\n",__FUNCTION__,__LINE__,glIsEnabled(GL_COLOR_ARRAY),\           glIsEnabled(GL_TEXTURE_COORD_ARRAY),glIsEnabled(GL_TEXTURE_2D),glIsEnabled(GL_VERTEX_ARRAY));        glDisableClientState(GL_COLOR_ARRAY);glDisableClientState(GL_TEXTURE_COORD_ARRAY);glDisable(GL_TEXTURE_2D);    //    glDisableClientState(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);    //制定vertex数组glVertexPointer(2, GL_FLOAT, 0, verts);    //因为后面要进行translate,所有需要push matrixglPushMatrix();    {        //针对retina进行优化glScalef(CC_CONTENT_SCALE_FACTOR(), CC_CONTENT_SCALE_FACTOR(), 1.0);        //平移水面到bound位置,否则在(0,0)处glTranslatef(_bounds.origin.x, _bounds.origin.y, 0.0);//glDrawArrays(GL_TRIANGLE_FAN, 0, _count*2);        //绘制图元glDrawArrays(GL_TRIANGLE_STRIP, 0, _count*2);}    glPopMatrix();glEnableClientState(GL_COLOR_ARRAY);glEnableClientState(GL_TEXTURE_COORD_ARRAY);glEnable(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 effect.int index = MAX(0, MIN((int)(x/[self dx]), _count - 1));_h2[index] += CCRANDOM_MINUS1_1()*20.0;}@end



原创粉丝点击