好记性不如铅笔头

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);

发表评论

1 × 5 =

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