岁月温柔 發表於 2025-9-29 11:42:00

Manim实现闪电特效

<p>本文将详细介绍如何使用<code>Manim</code>框架来实现一个逼真的闪电特效。</p>
<h1 id="1-实现原理">1. 实现原理</h1>
<p>闪电特效通过<code>LightningAnimation</code>类实现,该类继承自Manim的基础<code>Animation</code>类,</p>
<p>主要基于以下几个核心原理:</p>
<h2 id="11-折线生成与随机偏移">1.1. 折线生成与随机偏移</h2>
<p>闪电的基本形状是通过在起点和终点之间创建多个带有随机偏移的转折点来实现的:</p>
<pre><code class="language-python"># 初始化闪电的转折点
def initialize_points(self):
    # 在起点和终点之间均匀分布转折点
    for i in range(1, self.num_points + 1):
      t = i / (self.num_points + 1)
      # 基础位置
      self.points = self.start_point + t * self.vector
      # 添加随机偏移
      perpendicular = np.array([-self.direction, self.direction, 0])
      offset_strength = self.distance * 0.1
      random_offset = np.random.uniform(-offset_strength, offset_strength)
      self.points += random_offset * perpendicular
</code></pre>
<p>这段代码首先在起点和终点之间均匀分布转折点,然后对每个转折点添加垂直于闪电方向的随机偏移,从而模拟闪电不规则的锯齿形状。</p>
<h2 id="12-分叉闪电系统">1.2. 分叉闪电系统</h2>
<p>为了增强真实感,代码实现了分叉闪电系统:</p>
<pre><code class="language-python"># 初始化分叉点
for f in range(self.num_forks):
    # 随机选择分叉点在主闪电上的位置
    fork_start_index = np.random.randint(2, self.num_points - 2)
    fork_start_point = self.points
   
    # 计算分叉方向
    fork_direction = self.direction + np.array(
      
    )
    fork_direction = fork_direction / np.linalg.norm(fork_direction)
   
    # 计算分叉终点和转折点
    # ...省略部分代码...
</code></pre>
<p>系统会随机选择主闪电上的点作为分叉起点,然后生成带有随机方向和长度的分叉闪电。每个分叉也有自己的随机转折点,使其看起来更加自然。</p>
<h2 id="13-动态变化效果">1.3. 动态变化效果</h2>
<p>闪电效果的动态变化主要通过<code>interpolate_mobject</code>方法实现,该方法在动画过程中不断更新闪电的形状、颜色和透明度:</p>
<pre><code class="language-python">def interpolate_mobject(self, alpha):
    # 计算时间参数,使用正弦波来创造闪烁效果
    time = self.speed * alpha
   
    # 动态调整转折点位置
    # ...省略部分代码...
   
    # 动态调整透明度,创造闪烁效果
    alpha_value = self.alpha_range + (
      self.alpha_range - self.alpha_range
    ) * (0.5 + 0.5 * np.sin(time * 20))
    self.lightning_line.set_stroke(opacity=alpha_value)
   
    # 动态调整粗细
    thickness = self.thickness_range + (
      self.thickness_range - self.thickness_range
    ) * (0.5 + 0.5 * np.sin(time * 15))
    self.lightning_line.set_stroke(width=thickness)
   
    # ...省略部分代码...
</code></pre>
<p>代码使用正弦函数创造闪电的闪烁和粗细变化效果,结合随机因素使每次播放的闪电效果都略有不同,增强了视觉真实感。</p>
<h2 id="14-lightninganimation-类的参数">1.4. LightningAnimation 类的参数</h2>
<p><code>LightningAnimation</code> 类提供了丰富的参数选项,可以灵活调整闪电效果的各种特性。</p>
<pre><code class="language-python">class LightningAnimation(Animation):
    """
    闪电特效动画类
    通过创建多个带有尖锐转折的折线,并动态调整折线的形状、颜色和透明度来模拟闪电的效果
    包含主闪电和分叉闪电效果
    """

    def __init__(
      self,
      start_point,
      end_point,
      num_points=10,
      thickness_range=(0.1, 0.5),
      color=YELLOW,
      alpha_range=(0.5, 1),
      speed=1,
      num_forks=3,
      fork_probability=0.3,
      **kwargs
    ):
      """
      初始化闪电动画

      参数:
      - start_point: 闪电起点坐标
      - end_point: 闪电终点坐标
      - num_points: 闪电中的转折点数量
      - thickness_range: 闪电粗细范围 (最小值, 最大值)
      - color: 闪电颜色
      - alpha_range: 透明度范围 (最小值, 最大值)
      - speed: 动画速度
      - num_forks: 分叉闪电的数量
      - fork_probability: 分叉闪电出现的概率
      """
      pass # 省略... ...
</code></pre>
<p>参数主要含义:</p>
<ol>
<li><strong>位置参数</strong>:</li>
</ol>
<ul>
<li><code>start_point</code> : 闪电的起点坐标,使用 NumPy 数组表示 (x, y, z)</li>
<li><code>end_point</code> : 闪电的终点坐标,同样使用 NumPy 数组表示 (x, y, z)</li>
</ul>
<ol start="2">
<li><strong>形状与复杂度参数</strong>:</li>
</ol>
<ul>
<li><code>num_points</code> : 闪电中的转折点数量,默认为 10
<ul>
<li>数值越大,闪电的路径越复杂,锯齿状越明显</li>
<li>数值越小,闪电越接近直线</li>
</ul>
</li>
<li><code>num_forks</code> : 分叉闪电的数量,默认为 3
<ul>
<li>决定了闪电会产生多少个分支</li>
</ul>
</li>
<li><code>fork_probability</code> : 分叉闪电出现的概率,默认为 0.3
<ul>
<li>控制每次动画播放时,实际显示的分叉数量</li>
<li>值为 0 时不会显示分叉,值为 1 时所有分叉都会显示</li>
</ul>
</li>
</ul>
<ol start="3">
<li><strong>视觉效果参数</strong>:</li>
</ol>
<ul>
<li><code>thickness_range</code> : 闪电粗细范围,格式为 (最小值, 最大值),默认为 (0.1, 0.5)
<ul>
<li>控制闪电的最大和最小宽度</li>
<li>闪电在动画过程中会在此范围内动态变化</li>
</ul>
</li>
<li><code>color</code> : 闪电颜色,默认为 YELLOW
<ul>
<li>可以使用 Manim 提供的颜色常量,如 YELLOW、WHITE、BLUE 等</li>
</ul>
</li>
<li><code>alpha_range</code> : 透明度范围,格式为 (最小值, 最大值),默认为 (0.5, 1)
<ul>
<li>控制闪电的透明度变化范围</li>
<li>值越小,闪电越透明</li>
</ul>
</li>
</ul>
<ol start="4">
<li><strong>动画参数</strong>:</li>
</ol>
<ul>
<li><code>speed</code> : 动画速度,默认为 1
<ul>
<li>控制闪电闪烁和动态变化的速率</li>
<li>数值越大,闪电变化越快</li>
</ul>
</li>
</ul>
<h1 id="2-使用示例">2. 使用示例</h1>
<p><code>LightningAnimation</code>类提供了丰富的参数,可以灵活调整闪电效果。下面是几个不同场景的使用示例:</p>
<h2 id="21-示例1黄色对角闪电">2.1. 示例1:黄色对角闪电</h2>
<pre><code class="language-python">class Example01(Scene):
    def construct(self):
      # 设置背景色为深色,以突出闪电效果
      self.camera.background_color = "#0d0d1a"# 深蓝色背景
      
      # 创建闪电:从左上角到右下角,带分叉效果
      start_point = np.array([-5, 3, 0])
      end_point = np.array()
      lightning = LightningAnimation(
            start_point,
            end_point,
            num_points=15,         # 转折点数量
            color=YELLOW,          # 闪电颜色
            thickness_range=(0.15, 0.6),# 粗细范围
            speed=2,               # 动画速度
            num_forks=5,         # 分叉数量
            fork_probability=0.4   # 分叉出现概率
      )

      # 播放闪电动画
      self.play(lightning, run_time=2)
      self.wait()
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/83005/202509/83005-20250929113950604-563382699.gif" alt="" loading="lazy"></p>
<h2 id="22-示例2白色对角闪电">2.2. 示例2:白色对角闪电</h2>
<pre><code class="language-python">class Example02(Scene):
    def construct(self):
      self.camera.background_color = "#0d0d1a"
      
      # 创建闪电:从右上角到左下角
      start_point = np.array()
      end_point = np.array([-5, -3, 0])
      lightning = LightningAnimation(
            start_point,
            end_point,
            num_points=12,
            color=WHITE,
            thickness_range=(0.25, 0.7),
            speed=1.5,
            num_forks=4,
            fork_probability=0.3,
      )

      self.play(lightning, run_time=2)
      self.wait()
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/83005/202509/83005-20250929113950558-867829108.gif" alt="" loading="lazy"></p>
<h2 id="23-示例3蓝色垂直闪电">2.3. 示例3:蓝色垂直闪电</h2>
<pre><code class="language-python">class Example03(Scene):
    def construct(self):
      self.camera.background_color = "#0d0d1a"
      
      # 创建闪电:较短的垂直闪电
      start_point = np.array()
      end_point = np.array()
      lightning = LightningAnimation(
            start_point,
            end_point,
            num_points=8,
            color=BLUE,
            alpha_range=(0.7, 1),
            thickness_range=(0.1, 0.4),
            speed=3,
            num_forks=3,
            fork_probability=0.5,
      )

      self.play(lightning, run_time=1.5)
      self.wait()
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/83005/202509/83005-20250929113950572-900896112.gif" alt="" loading="lazy"></p>
<p>这些示例展示了如何通过调整参数来创建不同形状、颜色和特性的闪电效果,以适应不同的场景需求。</p>
<h1 id="3-总结">3. 总结</h1>
<h2 id="31-特效特点">3.1. 特效特点</h2>
<ol>
<li><strong>高度可定制</strong>:通过调整参数可以创建各种不同类型的闪电效果</li>
<li><strong>真实感强</strong>:结合随机因素和动态变化,模拟真实闪电的不规则性和闪烁效果</li>
<li><strong>层次丰富</strong>:主闪电和分叉闪电系统共同作用,创造出复杂而自然的闪电效果</li>
<li><strong>易于集成</strong>:作为Manim的Animation子类,可以方便地与其他Manim动画元素结合使用</li>
</ol>
<h2 id="32-使用场景">3.2. 使用场景</h2>
<ol>
<li><strong>天气现象模拟</strong>:在气象相关的可视化中展示雷电现象</li>
<li><strong>科幻与奇幻场景</strong>:为魔法效果、能量释放或科幻场景增添视觉冲击力</li>
<li><strong>强调与过渡</strong>:作为场景转换或重点内容强调的动态效果</li>
<li><strong>教育演示</strong>:在物理课程中演示电场放电等相关概念</li>
<li><strong>艺术创作</strong>:用于抽象动画和视觉艺术作品</li>
</ol>
<p>通过这个<code>LightningAnimation</code>类,我们可以在<code>Manim</code>项目中轻松实现逼真的闪电特效,为动画作品增添生动的视觉元素。</p><br><br>
来源:https://www.cnblogs.com/wang_yb/p/19118455
頁: [1]
查看完整版本: Manim实现闪电特效