完整烟花效果,Compose + 协程 + Flow + Channel 轻松实现

动画特效里面,烟花是比较常见的一种,特别是在做夜间背景或者节日活动的时候。

一、前言:

新一代烟花效果实现方式:Compose + 协程 + Flow + Channel + 实现

  • 核心逻辑设计:
  1. 采用三层设计结构来完成:数据层即:粒子模型、逻辑层即:协程更新、视图层即:Compose渲染
  2. 采用响应式编程:通过State和Flow实现数据驱动UI
  3. 采用新一代声明式UI Compose来完成展示烟花效果。

二、 烟花粒子系统模型设计

Firework:烟花数据模型
launchTime:一次烟花的绽放,需要烟花绽放时间,方便短时间后清楚计算时间
particles:一次的烟花总共需要多少个微粒子组成,具体生产那边是随机生产
color:烟花绽放的粒子基础颜色,具体到每个烟花微粒上面的颜色根据透明度和衰减计算:具体方法: color = firework.color.copy(alpha = particle.alpha * particle.life)

Particle : 烟花微粒子模型:
position:具体到一堆粒子中每个微粒的位置
velocity:每个微粒子受到的空气阻力
size:每个微粒子大小
alpha:每个微粒子透明度
life:每个微粒子生命周期衰减,直到完全消失

kotlin 复制代码
//烟花模型
data class Firework(
    val particles: List<Particle>,//一次的烟花总共需要多少个微粒子组成
    val color: Color, //烟花颜色
    val launchTime: Long = System.currentTimeMillis()//烟花绽放时间,方便短时间后清楚计算时间
)

//微粒子
data class Particle(
    val position: Offset,  //展示位置
    val velocity: Offset, // 空气阻力
    val size: Float, //烟花大小
    val alpha: Float, //透明度
    val life: Float = 1f // 生命周期衰减
)

三、烟花粒子控制器:

  • 1、设置控制粒子命令:密封类FireworkCommand:包含,执行开始(开始执行时,带有烟花绽放基础位置),执行清除两个命令。
kotlin 复制代码
sealed class FireworkCommand {
    data class Launch(val position: Offset) : FireworkCommand()
    object Clear : FireworkCommand()
}
  • 2、初始化开始:粒子系统使用协程Flow实现高性能更新,通过Channel处理用户交互命令,性能优化确保60fps流畅运行,createFirework :开始产生烟花粒子,对外提供两方法:执行烟花启动开始的 launch(position: Offset) 方法和 清除烟花 fun clear()方法和 停止方法fun stop()
kotlin 复制代码
private val scope = CoroutineScope(Dispatchers.Default)
private val _fireworks = mutableStateListOf<Firework>()
val fireworks: List<Firework> get() = _fireworks

private val commandChannel = Channel<FireworkCommand>()


fun start() {
    scope.launch {
        commandChannel.consumeAsFlow().collect { command ->
            when (command) {
                is FireworkCommand.Launch -> createFirework(command.position)//
                FireworkCommand.Clear -> _fireworks.clear()
            }
        }
    }

    scope.launch {
        while (true) {
            updateFireworks()
            delay(16) // ~60fps
        }
    }
}

//执行烟花启动开始
fun launch(position: Offset) {
    scope.launch {
        commandChannel.send(FireworkCommand.Launch(position))
    }
}

//清除烟花
fun clear() {
    scope.launch {
        commandChannel.send(FireworkCommand.Clear)
    }
}

//停止
fun stop() {
    scope.cancel()
}
  • 3、每个烟花爆炸生成 80-130 个随机运动轨迹的粒子,通过 Color.hsl(色调, 饱和度%, 亮度%)``模拟每个粒子颜色渐变,这样就可以模拟出真实物理效果:
scss 复制代码
private fun createFirework(position: Offset) {
    val particleCount = 80 + Random.nextInt(50)
    val color = Color.hsl(
        Random.nextFloat() * 360f, 1f, 0.7f
    )

    _fireworks.add(
        Firework(
            particles = List(particleCount) {
                val angle = Random.nextFloat() * 2f * PI.toFloat()
                val speed = 2f + Random.nextFloat() * 5f
                Particle(
                    position = position, velocity = Offset(
                        cos(angle) * speed, sin(angle) * speed
                    ), size = 3f + Random.nextFloat() * 5f, alpha = 0.9f + Random.nextFloat() * 0.1f
                )
            }, color = color
        )
    )
}
  • 4、粒子包含生命周期衰减和速度衰减,实现自然消失效果,其中:采用了物理模拟包含速度衰减(0.98系数)和重力影响粒子生命周期线性衰减(1.0→0.0), 通过System.currentTimeMillis()管理烟花存活时间(3秒)
ini 复制代码
private fun updateFireworks() {
    val currentTime = System.currentTimeMillis()
    val updatedFireworks = _fireworks.map { firework ->
        val updatedParticles = firework.particles.map { particle ->
            if (particle.life > 0) {
                val newVelocity = particle.velocity * 0.98f
                particle.copy(
                    position = particle.position + newVelocity, velocity = newVelocity, life = particle.life - 0.01f
                )
            } else particle
        }
        firework.copy(particles = updatedParticles)
    }

    _fireworks.clear()
    _fireworks.addAll(updatedFireworks.filter {
        currentTime - it.launchTime <= 3000 && it.particles.any { p -> p.life > 0 }
    })
}

四、烟花展示UI Compose 设计

通过 ComposeCanvasdrawCircle绘制圆圈点来展示烟花微粒,采用混合模式(BlendMode)增强视觉效果,包含粒子光晕和拖尾,烟花颜色通过基础颜色,外加微粒子的透明度alpha和微粒子的衰减life,组合成渐变的烟花效果,即: color = firework.color.copy(alpha = particle.alpha * particle.life)

ini 复制代码
@Composable
fun FireworkDisplay(
    modifier: Modifier = Modifier,
    controller: FireworkController = remember { FireworkController().apply { start() } }
) {
    Canvas(
        modifier = modifier
            .fillMaxSize()
            .pointerInput(Unit) {
                detectTapGestures { offset ->
                    controller.launch(offset)//点击屏幕任意位置发送烟花效果
                }
            }
    ) {
        controller.fireworks.forEach { firework ->
            firework.particles.forEach { particle ->
                if (particle.life > 0) {
                    drawCircle(
                        color = firework.color.copy(alpha = particle.alpha * particle.life),
                        radius = particle.size * particle.life,
                        center = particle.position,
                        blendMode = BlendMode.Plus
                    )

                    // 拖尾效果
                    drawCircle(
                        brush = Brush.radialGradient(
                            colors = listOf(
                                firework.color.copy(alpha = 0.3f * particle.life),
                                Color.Transparent
                            ),
                            radius = particle.size * 2f
                        ),
                        radius = particle.size * 4f,
                        center = particle.position,
                        blendMode = BlendMode.Screen
                    )
                }
            }
        }
    }
}

五、总结

本文重点介绍了:新一代烟花效果实现方式:Compose + 协程 + Flow + Channel + 实现 主要涉及到了:

  1. 烟花堆中的微粒子系统使用协程Flow实现高性能更新,通过Channel处理用户交互命令
  2. 每个烟花爆炸的生成主要是由80-130个随机运动轨迹的粒子,通过 Color.hsl(色调, 饱和度%, 亮度%)``模拟每个粒子颜色渐变,模拟真实物理效果
  3. 烟花堆中的每个微粒子包含生命周期衰减和速度衰减,实现自然消失效果
  4. 为了达到更加逼真效果,采用混合模式(BlendMode)增强视觉效果,包含粒子光晕和拖尾
  5. 支持点击屏幕任意位置发射随机颜色烟花。
  6. UI方面主要通过 ComposeCanvasdrawCircle绘制圆圈点来展示烟花微粒。

感谢阅读:

欢迎用你发财的小手 关注,点赞、收藏

这里你会学到不一样的东西

相关推荐
bobuddy1 小时前
射频收发机架构简介
架构·射频工程
桌面运维家1 小时前
vDisk考试环境IO性能怎么优化?VOI架构实战指南
架构
JMchen1231 小时前
Android后台服务与网络保活:WorkManager的实战应用
android·java·网络·kotlin·php·android-studio
crmscs2 小时前
剪映永久解锁版/电脑版永久会员VIP/安卓SVIP手机永久版下载
android·智能手机·电脑
localbob2 小时前
杀戮尖塔 v6 MOD整合版(Slay the Spire)安卓+PC端免安装中文版分享 卡牌肉鸽神作!杀戮尖塔中文版,电脑和手机都能玩!杀戮尖塔.exe 杀戮尖塔.apk
android·杀戮尖塔apk·杀戮尖塔exe·游戏分享
机建狂魔2 小时前
手机秒变电影机:Blackmagic Camera + LUT滤镜包的专业级视频解决方案
android·拍照·摄影·lut滤镜·拍摄·摄像·录像
hudawei9962 小时前
flutter和Android动画的对比
android·flutter·动画
一个骇客3 小时前
让你的数据成为“操作日志”和“模型饲料”:事件溯源、CQRS与DataFrame漫谈
架构
鹏北海-RemHusband3 小时前
从零到一:基于 micro-app 的企业级微前端模板完整实现指南
前端·微服务·架构
lxysbly4 小时前
md模拟器安卓版带金手指2026
android