刚才我们学习了如何给鱼加上波光的效果。这一节,我们将学习怎样制作攻击时的闪电特效,看一下华丽的闪电魔法是怎么来的。

     《捕鱼达人》中的闪电,是通过以下几个步骤来实现的:

一、构建三角形条带。

二、采用随机函数来扰动条带顶点。

三、快速反复循环一,二步骤。


      这个过程主要使用到以下三个类:

(1)VertexVector:用于存储顶点和索引的类。

(2)Noise:噪音处理类,用于进行顶点扰动,使顶点不断的小幅变化。

(3)LightLineRender:实现闪电效果的类。


       具体的代码实现,可以参看注释。我们要关心的是LightLineRender类,它封装了闪电效果,并提供了相应的参数调节选项,我们学会了使用它就可以做出闪电链的效果。


我们打开cpp-empty-test,在HelloWorld::init函数中加入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//线条容器
std::vector<LightLineRender::Line> lines;
//设置线条位置
//第一段闪电的起点和终点
Vec3 segStart = Vec3(-50,-50,-8);
Vec3 segEnd   = Vec3(50,50,-8);
lines.push_back( LightLineRender::Line( segStart, segEnd, 0 ) );
//第二段闪电的起点和终点
segStart = Vec3(50,50,-8);
segEnd   = Vec3(-50,50,-8);
lines.push_back( LightLineRender::Line( segStart, segEnd, 0 ) );
//第三段闪电的起点和终点
segStart = Vec3(-50,50,-8);
segEnd   = Vec3(50,-50,-8);
lines.push_back( LightLineRender::Line( segStart, segEnd, 0 ) );
//第四段闪电的起点和终点
segStart = Vec3(50,-50,-8);
segEnd   = Vec3(0,100,-8);
lines.push_back( LightLineRender::Line( segStart, segEnd, 0 ) );
//第五段闪电的起点和终点
segStart = Vec3(0,100,-8);
segEnd   = Vec3(-50,-50,-8);
lines.push_back( LightLineRender::Line( segStart, segEnd, 0 ) );
//创建出闪光链
LightLineRender*    _lighting = LightLineRender::create();
//设置不需要强制纹理循环
_lighting->setForceTexLoop( false );
//设置宽
_lighting->setWidth( 80 );
//设置 单张纹理长度,调整这个数值可以避免纹理过度拉伸或挤压
_lighting->setTextueLength( 100 );
//设置单个面片网格长,越小曲线越平滑,数值过于小可能带来效率问题
_lighting->setStep( 10 );
//设置振幅1
_lighting->setAmplitude0( 4 );
//设置频率1
_lighting->setFrequency0( 500 );
//设置振幅2
_lighting->setAmplitude1( 1 );
//设置频率2
_lighting->setFrequency1( 400 );
//设置产生噪音的时间系数
_lighting->setTimeFactor( 0.5 );
//使用线段容器创建闪电链
_lighting->setLines( lines );
//使用柏林噪音算法
_lighting->setLineType( LineType::LT_PerlinNosie );
//设置每帧强制更新重建模型
_lighting->setForceUpdate(true);
//设置位置
_lighting->setPosition(Vec2(visibleSize.width / 4 + origin.x,visibleSize.height / 2 + origin.y));
//将闪电链加入到当前层中。
this->addChild(_lighting,0,10);


这样我们完成了使用了五条闪电组成一个五星闪电链不断的闪动。运行后的效果如图所示:

1.jpg


       然后我们希望在触屏时能够有一条闪电链击中屏幕中央的乌龟,乌龟被击中后翻个身,闪电链渐渐消失,我们可以这样做:


       首先我们在FishLayer这个层里将乌龟循环播放的游泳与被击中的两个动作改为只播放游泳,然后我们增加两个函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//击中乌龟
void    FishLayer::AttackWuGui()
{
    if (m_Animation3D)
    {
        //从1.933秒到2.8秒截取为受伤的动作
        m_Hurt = Animate3D::create(m_Animation3D, 1.933f, 2.8f);
        m_Hurt->retain();
 
        m_Sprite->stopAllActions();
        //让精灵循环播放游泳和的受伤动作
        Sequence*   pSequence = Sequence::create(m_Hurt,CallFunc::create( std::bind(&FishLayer::ContinueSwim, this) ),NULL);
        m_Sprite->runAction(pSequence);
 
    }
 
}
//继续游动
void    FishLayer::ContinueSwim()
{
    if (m_Animation3D)
    {
        //从起始到1.933秒截取为游泳动作
        m_Swim = Animate3D::create(m_Animation3D, 0.f, 1.933f);
        m_Swim->retain();
 
        m_Sprite->stopAllActions();
        //让精灵循环播放游泳和的受伤动作
        Sequence*   pSequence = Sequence::create(m_Swim,NULL);
        m_Sprite->runAction(RepeatForever::create(pSequence));
    }
}


然后在HelloWorld的init函数尾部增加代码:

1
2
//设置可以点击
setTouchEnabled( true );



最后,我们重载一下onToucesBegan函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
0