Android 粒子喷泉动效
一、前言:
在学习open gl es实现动效的时候,打算回顾了一下用普通的2D坐标系实现粒子效果和 open gl 3d 坐标系的区别,以及难易程度,因此本篇以Canvas 2D坐标系实现了一个简单的demo。


粒子动效原理:
粒子动效本质上是一种知道起点和各个坐标轴方向速度的无规则运动,这种动效的实现的算法确实有规则的。
我们以物理学公式为例,本质上是一种匀加速矢量方程,至于为什么忽快忽慢,也是从该类方程延伸出来的新算法。
x = startX + (Vx*t + 1/2*aX*t * t)
y = startY + (Vy * t + 1/2*aY*t * t)
t: 时间 ,vY,vX 各个方向的速度,aX,aY各个方向的加速度
当然,用向量解释就是向量A到向量B各个分量的运动学公式。
粒子动效的特点:
-
具备起点位置
-
需要计算出速度和运动角度,当然,难点也是速度的计算和定义。
-
符合运动学方程,但与现实规律有区别,因为在手机中使用的单位和重力加速度都是有一定区别的。
二、代码实现
2.1 构建粒子对象,在open gl中由于没有对象化的概念,绘制时通过数组的偏移实现,当然后果是代码可读性差一些。
public class Particle {private float speedZ = 0;private float x;private float y;private float speedX;private float speedY;int color;long startTime;private float radius = 10;public Particle(float x, float y, float speedX, float speedY, int color,float speedZ,long clockTime) {this.x = x;this.y = y;this.speedX = speedX;this.speedY = speedY;this.speedZ = speedZ;this.color = color;this.startTime = clockTime;}public void draw(Canvas canvas, long clockTime, Paint paint) {long costTime = (clockTime - startTime)/2;float gravityY = costTime * costTime / 3000f; //重力加速度float dx = costTime * speedX;float dy = costTime * speedY + gravityY;float v = costTime / 500f;float ty = y + dy; // vt + t*t/2*gfloat tx = x + dx;int paintColor = paint.getColor();if(v > 1f && speedZ != 1) {//非z轴正半轴的降低透明度int argb = argb((int) (Color.alpha(color) /v), Color.red(color), Color.green(color), Color.blue(color));paint.setColor(argb);}else {paint.setColor(color);}float tRadius = radius;//这只Blend叠加效果,这个api版本较高 paint.setBlendMode(BlendMode.DIFFERENCE); canvas.drawCircle(tx,ty,tRadius,paint);paint.setColor(paintColor);if(ty > radius){reset(clockTime);}}private void reset(long clockTime) {startTime = clockTime;}public static int argb(@IntRange(from = 0, to = 255) int alpha,@IntRange(from = 0, to = 255) int red,@IntRange(from = 0, to = 255) int green,@IntRange(from = 0, to = 255) int blue) {return (alpha << 24) | (red << 16) | (green << 8) | blue;}
}
2.2 构建粒子系统
public class CanvasParticleSystem {private Particle[] particles;private int maxParticleCount = 500;private Random random = new Random();private final float angle = 30f; //x轴的活动范围private int index = 0;private float radius = 60; //x轴和y轴不能超过的边界public void addParticle(float centerX,float centerY,float maxWidth,float maxHeight,long clockTime){if(particles == null){particles = new Particle[maxParticleCount];}if(index >= particles.length) {return;}float degree = (float) Math.toRadians((270 - angle) + 2f * angle * random.nextFloat());float dx = (float) (radius * Math.cos(degree)) * 2f; //计算初目标位置x的随机点float dy = -(float) ((maxHeight * 1f / 2 - radius * 2f) * random.nextFloat()) - maxHeight / 2f;//计算目标y的随机点float dt = 1000; //时间按1s计算// dx = speedx * dt + centerX;// dy = speedy * dt + centerY;float sx = (dx - centerX) / dt; // x轴方向的速度float sy = (dy - centerY) / dt; //y轴方向的速度int num = (int) (random.nextFloat() * 100);float sz = 0;if(num % 5 == 0) {sz = random.nextBoolean() ? -1 : 1;}int argb = argb(random.nextFloat(), random.nextFloat(), random.nextFloat());// argb = argb(210, 110, 80);Particle p = new Particle(centerX,centerY,sx,sy, argb,sz,clockTime);particles[index++] = p;}public void drawFrame(Canvas canvas, Paint paint,long clockTime) {for (int i = 0; i < particles.length;i++) {Particle particle = particles[i];if(particle == null) continue;particle.draw(canvas,clockTime,paint);}}public int argb( float red, float green, float blue) {return ((int) (1 * 255.0f + 0.5f) << 24) |((int) (red * 255.0f + 0.5f) << 16) |((int) (green * 255.0f + 0.5f) << 8) |(int) (blue * 255.0f + 0.5f);}
}
2.3 粒子View实现
public class PracticeView extends View {Paint paint;CanvasParticleSystem particleSystem;private long clockTime = 0L; //自定义时钟,防止粒子堆积long startTimeout = 0; public PracticeView(Context context) {super(context);init();}public PracticeView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init();}public PracticeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}public void init(){paint = new Paint();paint.setAntiAlias(true);paint.setDither(false);paint.setStrokeWidth(2f);particleSystem = new CanvasParticleSystem();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);int width = getWidth();int height = getHeight();if (width <= 10 || height <= 10) {return;}int save = canvas.save();canvas.translate(width/2,height);fillParticles(5,width, height);particleSystem.drawFrame(canvas,paint,getClockTime());canvas.restoreToCount(save);clockTime += 32;postInvalidateDelayed(16);}private void fillParticles(int size,int width, int height) {if(SystemClock.uptimeMillis() - startTimeout > 60) {for (int i = 0; i < size; i++) {particleSystem.addParticle(0, 0, width, height,getClockTime());}startTimeout = SystemClock.uptimeMillis();}}private long getClockTime() {return clockTime;}
}
三、总结
总体上使用Canvas 绘制高帧率的粒子动效,其对比open gl肯定有很多差距,甚至有一些天然缺陷比如Z轴的处理。当然,易用性肯定是Canvas 2D的优势了。
相关文章:
Android 粒子喷泉动效
一、前言: 在学习open gl es实现动效的时候,打算回顾了一下用普通的2D坐标系实现粒子效果和 open gl 3d 坐标系的区别,以及难易程度,因此本篇以Canvas 2D坐标系实现了一个简单的demo。 粒子动效原理: 粒子动效本质上…...
fast.ai 深度学习笔记(一)
深度学习 2:第 1 部分第 1 课 原文:medium.com/hiromi_suenaga/deep-learning-2-part-1-lesson-1-602f73869197 译者:飞龙 协议:CC BY-NC-SA 4.0 来自 fast.ai 课程的个人笔记。随着我继续复习课程以“真正”理解它,这…...
【机器学习】Ubuntu系统下CUDA驱动卸载及重装
目录 背景 驱动卸载 驱动安装 CUDA驱动安装 安装nvidia-smi 背景 这里包含显卡驱动和CUDA驱动,在如下场景下,我们需要卸载显卡驱动并重新安装。 在某些情况下需要对显卡驱动进行升级某些情况下(如重启,或者调整系统配置等&a…...
相机图像质量研究(8)常见问题总结:光学结构对成像的影响--工厂调焦
系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结:光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结:光学结构对成…...
【MySQL】数据库基础 -- 详解
一、什么是数据库 存储数据用文件就可以了,为什么还要弄个数据库? 一般的文件确实提供了数据的存储功能,但是文件并没有提供非常好的数据(内容)的管理能力(用户角度)。 文件保存数据有以下几个缺点&…...
零基础学Python之整合MySQL
Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口。 不同的数据库你需要下载不同的DB API模块,例如你需要访问Oracle数据库和Mysql数据,你需要下载Oracle和MySQL数据库模块。 DB-API 是一个规范. 它…...
股票均线的使用方法和实战技术,看涨看空的均线形态与案例教学
一、教程描述 本套教程讲解了14种均线的特殊形态,通过直观图形以及大量案例的教学,将深奥、繁琐的均线变得生动与具体,广大投资者在认真学习以后,可以学会均线的使用方法,掌握最强的均线应用实战技术。本套教程不仅适…...
服务器被黑,安装Linux RootKit木马
前言 疫情还没有结束,放假只能猫家里继续分析和研究最新的攻击技术和样本了,正好前段时间群里有人说服务器被黑,然后扔了个样本在群里,今天咱就拿这个样本开刀,给大家研究一下这个样本究竟是个啥,顺便也给…...
【数据结构与算法】【腾讯阿里链表面试题】算法题--链表易懂版讲解
🎉🎉欢迎光临🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟特别推荐给大家我的最新专栏《Spring 狂野之旅:底层原理高级进阶》 🚀…...
3d渲染100农场如何使用?渲染100邀请码1a12
3d渲染农场通常用于电影、动画或视觉效果的渲染,本文以广受好评的渲染100农场为例,来讲解它的使用方法。 1、注册账号 前往渲染100官网(http://www.xuanran100.com/?ycode1a12)注册账号, 新用户注册记得填邀请码1a12,有30元大礼…...
【数据结构和算法】--- 基于c语言排序算法的实现(2)
目录 一、交换排序1.1 冒泡排序1.2 快速排序1.2.1 hoare法1.2.2 挖坑法1.2.3 前后指针法 1.3 快速排序优化1.3.1 三数取中法选key1.3.2 递归到小的子区间使用插入排序 1.4 快排非递归版 二、归并排序2.1 归并排序2.1.1 递归版2.1.2 非递归版 一、交换排序 基本思想:…...
ORACLE的 软 软 软 解析!
在海鲨数据库架构师精英群里,有位朋友说ORACLE 有 软软软解析. 就是把执行计划缓存在客户端里,从而避免去服务端找执行计划. 他给了个设置方法, Weblogic console->datasource->connectionPool Statement Cache Type >LRU Statement Cache Size100 CURSOR_NUMBER …...
【模板】k 短路 / [SDOI2010] 魔法猪学院
题目背景 注:对于 k k k 短路问题,A* 算法的最坏时间复杂度是 O ( n k log n ) O(nk \log n) O(nklogn) 的。虽然 A* 算法可以通过本题原版数据,但可以构造数据,使得 A* 算法在原题的数据范围内无法通过。事实上,…...
【Make编译控制 08】CMake动静态库
目录 一、编译动静态库 二、链接静态库 三、链接动态库 前情提示:【Make编译控制 07】CMake常用命令-CSDN博客 有些时候我们编写的源代码并不需要将他们编译生成可执行程序,而是生成一些静态库或动态库提供给第三方使用,所以我们需要用到…...
05 06 Verilog基础语法与应用讲解
05. 1. 位操作 计数器实验升级,设计8个LED灯以每个0.5s的速率循环闪烁(跑马灯) 1.1 方法1:使用移位操作符<<来控制led灯的循环亮灭 设计代码 Verilog中,判断操作的时候不加位宽限定是可以的,比如i…...
css2复合选择器
一.后代(包含)选择器(一样的标签可以用class命名以分别) 空格表示 全部后代 应用 二.子类选择器 >表示 只要子不要孙 应用 三.并集选择器 ,表示 代表和 一般竖着写 应用 四.伪类选择器(包括伪链接…...
新版MQL语言程序设计:键盘快捷键交易的设计与实现
文章目录 一、什么是快捷键交易二、使用快捷键交易的好处三、键盘快捷键交易程序设计思路四、键盘快捷键交易程序具体实现1.界面设计2.键盘交易事件机制的代码实现 一、什么是快捷键交易 操盘中按快捷键交易是指在股票或期货交易中,通过使用快捷键来进行交易操作的…...
数据结构之基数排序
基数排序的思想是按组成关键字的各个数位的值进行排序,它是分配排序的一种。在该排序方法中把一个关键字 Ki看成一个 d 元组,即 K1i,K2i,,Kdi 其中,0≤ Kji<r,i1~ n,j1~d。这里的r 称为基数。若关键字是…...
区间dp 笔记
区间dp一般是先枚举区间长度,再枚举左端点,再枚举分界点,时间复杂度为 环形石子合并 将 n 堆石子绕圆形操场排放,现要将石子有序地合并成一堆。 规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数记做该…...
MySQL-SQL优化
文章目录 1. SQL性能分析1.1 SQL执行频率1.2 慢查询日志1.3 profile详情1.4 explain 2. SQL优化2.1 Insert 优化2.2 Group By 优化2.3 Order By 优化2.4 Limit 优化2.5 Count() 优化2.6 Update 优化 3. 拓展3.1 请你说一下MySQL中的性能调优的方法?3.2 执行 SQL 响应…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...
