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 响应…...
终极Python GUI设计器:Pygubu Designer完全指南
终极Python GUI设计器:Pygubu Designer完全指南 【免费下载链接】pygubu-designer A simple GUI designer for the python tkinter module 项目地址: https://gitcode.com/gh_mirrors/py/pygubu-designer 还在为Python GUI开发而烦恼吗?厌倦了手写…...
如何构建高效科研知识库:Obsidian文献管理系统的3种创新策略
如何构建高效科研知识库:Obsidian文献管理系统的3种创新策略 【免费下载链接】obsidian_vault_template_for_researcher This is an vault template for researchers using obsidian. 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian_vault_template_for_r…...
对AI工程问题的一些思考
AI Agent 编程正在重塑软件工程的底层逻辑 过去三到五年,AI 编程工具经历了从「辅助插件」到「协作主体」的范式迁移。 最早以 GitHub Copilot 为代表的产品,本质上是一种上下文感知的智能补全引擎——它能根据当前文件的光标位置,预测并生成…...
任天堂Switch游戏备份终极指南:nxdumptool完全解析
任天堂Switch游戏备份终极指南:nxdumptool完全解析 【免费下载链接】nxdumptool Generates XCI/NSP/HFS0/ExeFS/RomFS/Certificate/Ticket dumps from Nintendo Switch gamecards and installed SD/eMMC titles. 项目地址: https://gitcode.com/gh_mirrors/nx/nxd…...
5分钟解锁学术付费墙:Unpaywall浏览器扩展让你的研究之路畅通无阻
5分钟解锁学术付费墙:Unpaywall浏览器扩展让你的研究之路畅通无阻 【免费下载链接】unpaywall-extension Firefox/Chrome extension that gives you a link to a free PDF when you view scholarly articles 项目地址: https://gitcode.com/gh_mirrors/un/unpaywa…...
Kubernetes 网络与服务发现:从原理到实战避坑指南
摘要K8s 网络是很多人眼中的"黑盒"。本文深入剖析 Pod 通信、Service 发现、Ingress 网关的核心原理,结合真实生产环境的踩坑经验,带你彻底搞懂 K8s 网络模型。看完这篇,你再也不会被"服务找不到"、"跨节点通信失败…...
别再到处搜了!高德、百度、ArcGIS地图瓦片URL,我帮你整理好了(附Leaflet加载代码)
地图瓦片集成实战:从URL解析到Leaflet高效加载 1. 地图瓦片服务的选择与评估 在WebGIS开发中,选择合适的瓦片地图服务是项目成功的第一步。主流服务商提供的地图瓦片各有特点,开发者需要根据项目需求进行综合评估。 高德地图瓦片以其丰富的图…...
Inter字体终极指南:为什么这款开源字体能重新定义数字界面设计
Inter字体终极指南:为什么这款开源字体能重新定义数字界面设计 【免费下载链接】inter The Inter font family 项目地址: https://gitcode.com/gh_mirrors/in/inter Inter字体是一款专为现代数字屏幕设计的开源无衬线字体,通过科学优化的字形设计…...
overwrite
编写overwrite.c程序#inlcude<stdio.h> int main() {int b 123;int c 789;int a 456;char s[100];printf("%p\n", &a);scanf("%s", s);printf(s);if (a 16){puts("my name is c");}else if (a 2){puts("my name is small&qu…...
【linux学习】linux的一些奇怪知识,方便日常使用
我是程序员小青蛙,下面介绍关于linux的知识。前言一些基本知识,方便利用,比如热键[tab],[ctrl]-c,[ctrl]-d,粘滞位,权限等;xshell中的复制粘贴,Ctrlinsert,复制shiftinsert->粘贴一、重要的几…...
