当前位置: 首页 > 科技观察

春节玩得开心,写个烟花动画效果

时间:2023-03-17 14:16:32 科技观察

2022虎年快乐。祝大家新年快乐。本文教你如何在Canvas中实现高性能的烟花粒子效果。通过使用Canvas+BitmapShader+GestureDetector技术栈,可以实现一个有趣的2D春节烟花特效页面。速度和加速度显示模型速度变化和PVector2D简单动画效果等。每次点击屏幕都会产生烟花,烟花飞到高空时会爆炸成60~100个碎片。同一屏幕上可能有数千个粒子。更新它的位置,希望能给你带来一些好玩有趣的东西!工作演示代码分析先看工程结构└─fireworksColorfullView.java-自定义视图Firework.java-为烟花构建模型MainActivity.javaParticle.java-粒子PContext.java-工具类PVector.java-Vector类XML代码Java代码自定义ColorfullView使用GestureDetector处理用户输入,每次点击时在当前位置创建烟花mGesture=newGestureDetectorCompat(getContext(),newGestureDetector.SimpleOnGestureListener(){@OverridepublicbooleanonDown(MotionEvente){fireworks.add(newFirework(e.getX(),e.getY()));ViewCompat.postInvalidateOnAnimation(ColorfullView.this)复制代码;返回真;}});FireWork类包含两个属性,分别包含爆炸前的“种子”信息和爆炸后发射的粒子信息。由于爆炸后的每个粒子也有对应的位置和速度信息,所以这些粒子被视为属于一束烟花的“种子”,这些粒子的信息被统一封装到Bean类Particle中;ArrayList粒子;//爆破后的粒子烟花;//Explosion打开前的粒子类,颜色、大小、速度都是随机的,接近真实。同时设置烟花种子的初始位置坐标、半径等信息。每个烟花种子发射的粒子位置将根据种子最终爆炸的位置来确定。类粒子{PVector位置;向量速度;向量加速;浮动半径;//粒子(floatx,floaty,floathue){this.hu=hue;加速度=新PVector(0,0);velocity=newPVector(0,PContext.random(-20,-10));location=newPVector(x,y);种子=真;life=PContext.random(350.0f,555.0f);this.radius=PContext.random(10,20);}//烟花粒子Particle(PVectorloc,floathue){this.hu=hue;加速度=新PVector(0,0);velocity=PVector.random2D();velocity.mult(PCContext.random(4,8));位置=loc.get();life=PContext.random(350.0f,555.0f);this.radius=PContext.random(10,20);每次绘制一帧都会调用FireWork的run方法,在视图的onDraw回调中会不断调用当前粒子的更新和显示方法;update方法用于更新每个粒子的速度、加速度和位置坐标,display方法用于根据粒子位置绘制;voidrun(Canvascanvas,Paintpaint){if(firework!=null){//firework.applyForce(gravity);烟花.更新();firework.display(画布,画);if(firework.explode()){intfragments=(int)random(60,100);//碎片数量for(inti=0;i=0;i--){粒子p=粒子。得到(我);p.applyForce(重力);p.update();p.display(画布,油漆);如果(p.isDead()){粒子。删除(i);}}}}性能优化这时候功能基本实现了,剩下的就是在canvas上绘制每一个烟花,通常我们会这样写@OverrideprotectedvoidonDraw(Canvascanvas){canvas.drawColor(Color.TRANSPARENT,PorterDuff.Mode.CLEAR);for(inti=fireworks.size()-1;i>=0;i--){烟花f=fireworks.get(i);F。运行(画布,mParticlePaint);如果(f.done()){fireworks.remove(i);}}//canvas.drawBitmap(canvasBitmap,0,0,mBitmapPaint);如果(!fireworks.isEmpty()){ViewCompat.postInvalidateOnAnimation(this);但是,你会发现性能很糟糕,帧数会随着粒子数的增加而下降到个位数。优化如下:@OverrideprotectedvoidonDraw(Canvascanvas){if(canvasBitmap==null||canvasBitmap.isRecycled()){canvasBitmap=Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);bitmapCanvas=newCanvas(canvasBitmap);mBitmapShader=newBitmapShader(canvasBitmap,Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);mBitmapPaint.setShader(mBitmapShader);mBitmapPaint.setDither(false);}bitmapCanvas.drawColor(Color.TRANSPARENT,PorterDuff.Mode.CLEAR);for(inti=fireworks.size()-1;i>=0;i--){烟花f=fireworks.get(i);f.run(bitmapCanvas,mParticlePaint);如果(f.done()){fireworks.remove(i);}}canvas.drawPaint(mBitmapPaint);如果(!fireworks.isEmpty()){ViewCompat.postInvalidateOnAnimation(this);}}写到最后,烟花的整个动画效果到这里就完成了。由于篇幅有限,实在不可能每一个细节都一一详解。在此提前向大家拜年!祝大家工作顺利,身体健康,家庭和睦美满,万事如意!