《捕鱼达人》教程3:闪电特效

2015年03月16日 11:49 0 点赞 0 评论 更新于 2025-11-21 17:08

在上一节中,我们学习了如何为鱼添加波光效果。在本节教程中,我们将深入探讨如何制作攻击时的闪电特效,揭开华丽闪电魔法背后的技术奥秘。

闪电特效的实现步骤

《捕鱼达人》中的闪电特效通过以下三个主要步骤实现:

  1. 构建三角形条带:这是闪电特效的基础几何结构,为后续的顶点操作提供框架。
  2. 采用随机函数扰动条带顶点:使用随机函数对条带的顶点进行扰动,使顶点产生不断的小幅变化,从而模拟出闪电的不规则形状。
  3. 快速反复循环前两个步骤:通过快速循环构建三角形条带和扰动顶点的操作,实现闪电的动态闪烁效果。

主要使用的类

在实现闪电特效的过程中,主要使用了以下三个类:

  1. VertexVector:用于存储顶点和索引的类,为后续的图形渲染提供数据支持。
  2. Noise:噪音处理类,负责对顶点进行扰动,使顶点不断产生小幅变化,模拟闪电的不规则形状。
  3. LightLineRender:实现闪电效果的核心类,封装了闪电效果的实现细节,并提供了相应的参数调节选项,通过使用该类,我们可以轻松实现闪电链的效果。

具体代码实现

创建五星闪电链

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

// 线条容器
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. 修改乌龟动作:在 FishLayer 层里,将乌龟循环播放的游泳与被击中的两个动作改为只播放游泳。
  2. 增加两个函数
    // 击中乌龟
    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)); } }

3. **在 `HelloWorld` 的 `init` 函数尾部增加代码**:

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

4. **重载 `onToucesBegan` 函数**:

// 重载 onToucesBegan 函数的具体实现代码 // 这里需要根据实际情况补充完整函数体 bool HelloWorld::onTouchesBegan(const std::vector<Touch>& touches, Event event) { // 实现触屏触发闪电击中乌龟的逻辑 return true; }


通过以上步骤,我们就实现了在触屏时闪电链击中乌龟,乌龟被击中后翻个身,闪电链渐渐消失的效果。

作者信息

boke

boke

共发布了 3994 篇文章