最近需要使用【 opengl 】绘制一个闪电效果,在网上翻了好多资料,最后在一个网站上找到了一个比较好的样子,参考了它的思路。
参考网站链接【 http://krazydad.com/bestiary/bestiary_lightning.html 】。
由于链接中的实现方式采用递归,当点数很多的时候很容易出现堆栈溢出的问题,这里作者修改成了for循环。
下面作者备份下代码,比较简单的一个实现,采用cococs2d-x:
1)首先定义两个类,一个是闪电中的单独线段类,一个是整条闪电类:
class SegmentNode: public cocos2d::CCObject { public: cocos2d::CCPoint start; cocos2d::CCPoint end; float offset; }; class ThunderNode: public cocos2d::CCObject { public: ThunderNode() { _pSegmentNodeArray = new cocos2d::CCArray; lineWidth = 1; } cocos2d::CCArray *_pSegmentNodeArray; int lineWidth; int color[4]; void setColor(int r, int g, int b, int a) { color[0] = r; color[1] = g; color[2] = b; color[3] = a; } ~ThunderNode() { if (_pSegmentNodeArray) { _pSegmentNodeArray->release(); _pSegmentNodeArray = NULL; } } };
2)定义随机数方法,并通过随机数来对Y轴坐标进行随机设置:
#define MY_RAND ((rand()%100 - 50)/50.0f) void ThunderLayer::internelGenerateThunderNode(ThunderNode *_pThunderNode, float x1,float x2,float y,float qiangdu, float offset, float jiange) { float pos_x_last = x1; float pos_y_last = y; for (float pos_x = x1 + jiange; pos_x <= x2; pos_x += jiange) { float pos_y = y + MY_RAND * qiangdu; SegmentNode *pn = new SegmentNode; pn->start = ccp(pos_x_last,pos_y_last); pn->end = ccp(pos_x,pos_y); pn->offset = MY_RAND * offset; _pThunderNode->_pSegmentNodeArray->addObject(pn); pos_x_last = pos_x; pos_y_last = pos_y; } }
3)调用随机数方法来生成闪电数据:
void ThunderLayer::generateThunderNodes(float dt) { while (_pThunderNodeArray->count() > 0) { CCObject *obj = _pThunderNodeArray->lastObject(); _pThunderNodeArray->removeLastObject(false); obj->release(); obj = NULL; } ThunderNode *_pThunderNode = NULL; for (int times = 5; times > 0; times--) { _pThunderNode = new ThunderNode(); _pThunderNode->lineWidth = 2 + MY_RAND * 1; _pThunderNode->setColor(128 + MY_RAND * 127,128 + MY_RAND * 127,128 + MY_RAND * 127,255); internelGenerateThunderNode(_pThunderNode,10,300,100 + MY_RAND * 3, 8, 10,10); _pThunderNodeArray->addObject(_pThunderNode); } }
4)在draw函数中绘制:
void ThunderLayer::draw() { CHECK_GL_ERROR_DEBUG(); CCObject *_pPointNodesObj = NULL; CCARRAY_FOREACH(_pThunderNodeArray, _pPointNodesObj) { ThunderNode *_pThunderNode = (ThunderNode *)_pPointNodesObj; CCObject *pnObj = NULL; ccDrawColor4B(_pThunderNode->color[0],_pThunderNode->color[1],_pThunderNode->color[2],_pThunderNode->color[3]); glLineWidth(_pThunderNode->lineWidth); CCARRAY_FOREACH(_pThunderNode->_pSegmentNodeArray, pnObj) { SegmentNode *pn = dynamic_cast<SegmentNode*>(pnObj); ccDrawLine(pn->start,pn->end); } } }
5)通过不停的调用【 generateThunderNodes 】方法来刷新闪电的数据:
this->schedule(schedule_selector(GameOverLayer::generateThunderNodes),1.0f);
发表评论