好记性不如铅笔头

C && C++, 数据结构与算法, 编程

通过随机数实现一个简单的闪电效果

最近需要使用【 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);

发表评论

3 + 15 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据