Android粒子系统
来源:互联网 发布:风险评价指数矩阵法 编辑:程序博客网 时间:2024/06/08 06:21
一、粒子属性
粒子图片,粒子大小,粒子缩放比例,粒子位置(X,Y),粒子移动方向与速度(X,Y坐标与时间t的关系)
计算粒子所处位置,绘制渲染
粒子系统,是大量基础图元构成的具有一定规律的不规律渲染图像。即要够成粒子系统,需要有基本图元,保持基本图元的一定规律性,并细化不规律性。
一个基本图元即是粒子系统中展示的一个粒子,有以下基本属性:粒子纹理【图片】,粒子的大小,粒子缩放,粒子的位置【平面坐标系中只有X,Y】,粒子移动方向与速度(X,Y坐标与时间T的关系)。
粒子属性基本信息保持一致,在各个变量细化时加入随机变量震动,从而实现统一大规律下不统一。
准备好所有粒子信息后,先检查粒子当前所处的位置,超出范围部分强制修改,然后绘制渲染粒子。
二、控件实现
构造方法,初始化基本数据:
public ParticleView(Context context) { super(context); } public ParticleView(Context context, AttributeSet attrs) { super(context, attrs); initData(context); initBitmapInfo(); initPaint(); } public ParticleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
/** * 初始化绘制笔 */ private void initPaint() { paint = new Paint(Paint.ANTI_ALIAS_FLAG); // 防抖动 paint.setDither(true); // 开启图像过滤 paint.setFilterBitmap(true); } /** * 初始化粒子纹理 */ private void initBitmapInfo() { mStarOne = ((BitmapDrawable) mResources.getDrawable(R.drawable.star2)).getBitmap();// mStarOne = ((BitmapDrawable) mResources.getDrawable(R.drawable.snow1)).getBitmap(); mStarOneWidth = mStarOne.getWidth(); mStarOneHeight = mStarOne.getHeight();// mStarTwo = ((BitmapDrawable) mResources.getDrawable(R.drawable.star1)).getBitmap(); mStarTwo = ((BitmapDrawable) mResources.getDrawable(R.drawable.snow2)).getBitmap(); mStarTwoWidth = mStarTwo.getWidth(); mStarTwoHeight = mStarTwo.getHeight();// mStarThree = ((BitmapDrawable) mResources.getDrawable(R.drawable.star3)).getBitmap(); mStarThree = ((BitmapDrawable) mResources.getDrawable(R.drawable.snow3)).getBitmap(); mStarThreeWidth = mStarThree.getWidth(); mStarThreeHeight = mStarThree.getHeight(); } /** * 初始化数据 * * @param context */ private void initData(Context context) { mResources = getResources(); DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); mTotalWidth = dm.widthPixels; mTotalHeight = dm.heightPixels; Log.i(TAG, "mTotalWidth=" + mTotalWidth + "--1--mTotalHeight=" + mTotalHeight); //设置三个不同大小的速度值 mFloatTransLowSpeed = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0.5f, mResources.getDisplayMetrics()); mFloatTransMidSpeed = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0.75f, mResources.getDisplayMetrics()); mFloatTransFastSpeed = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1f, mResources.getDisplayMetrics()); }
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mCenterX = mTotalWidth / 2; mCenterY = mTotalHeight / 2; mSrcRect = new Rect(); mDestRect = new Rect(0, 0, mTotalWidth, mTotalHeight); mStarOneSrcRect = new Rect(0, 0, mStarOneWidth, mStarOneHeight); mStarTwoSrcRect = new Rect(0, 0, mStarTwoWidth, mStarTwoHeight); mStarThreeSrcRect = new Rect(0, 0, mStarThreeWidth, mStarThreeHeight); Log.i(TAG, "mTotalWidth=" + mTotalWidth + "---2-mTotalHeight=" + mTotalHeight); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); initParticleInfo(); }
/** * 初始化所有粒子数据 */ private void initParticleInfo() { Particle starInfo = null; Random random = new Random(); for (int i = 0; i < mFloatCount; i++) { // 获取星星大小比例 float starSize = initParticleSize(0.4f, 0.8f); //小球的坐标 float[] starLocation = STAR_LOCATION[i]; starInfo = new Particle(); // 初始化星星大小 starInfo.sizePercent = starSize; // 初始化漂浮速度 int randomSpeed = random.nextInt(3); switch (randomSpeed) { case 0: starInfo.speed = mFloatTransLowSpeed; break; case 1: starInfo.speed = mFloatTransMidSpeed; break; case 2: starInfo.speed = mFloatTransFastSpeed; break; default: starInfo.speed = mFloatTransMidSpeed; break; } // 初始化星星透明度 starInfo.alpha = initParticleSize(0.3f, 0.8f); // 初始化星星位置 starInfo.xLocation = (int) (starLocation[0] * mTotalWidth); starInfo.yLocation = (int) (starLocation[1] * mTotalHeight); Log.i(TAG, "xLocation = " + starInfo.xLocation + "--yLocation = " + starInfo.yLocation); Log.i(TAG, "stoneSize = " + starSize + "---stoneAlpha = " + starInfo.alpha); // 初始化星星位置 starInfo.direction = getParticleDirection(); mStarInfos.add(starInfo); } }
/** * 获取粒子当前运动方向 * * @return */ private int getParticleDirection() { int randomInt; Random random = new Random(); if (floatTyep == 100) { randomInt = random.nextInt(3); } else { randomInt = floatTyep; } int direction = 0; switch (randomInt) { case 0: direction = LEFT; break; case 1: direction = RIGHT; break; case 2: direction = TOP; break; case 3: direction = BOTTOM; break; case 4: direction = FREE_POINT; break; default: break; } return direction; } /** * 对粒子进行缩放 * * @param start 缩放最小值 * @param end 缩放最大值 * @return */ private float initParticleSize(float start, float end) { float nextFloat = (float) Math.random(); if (start < nextFloat && nextFloat < end) { return nextFloat; } else { // 如果不处于想要的数据段,则再随机一次,因为不断递归有风险 return (float) Math.random(); } }
绘制粒子系统:【先检查粒子位置,再渲染】
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (int i = 0; i < mStarInfos.size(); i++) { Particle starInfo = mStarInfos.get(i); drawParticleDynamic(i, starInfo, canvas, paint); } }
private void drawParticleDynamic(int count, Particle starInfo, Canvas canvas, Paint paint) { //绘制前重置区域 resetParticleFloat(starInfo); float starAlpha = starInfo.alpha; int xLocation = starInfo.xLocation; int yLocation = starInfo.yLocation; float sizePercent = starInfo.sizePercent; xLocation = (int) (xLocation / sizePercent); yLocation = (int) (yLocation / sizePercent); Bitmap bitmap = null; Rect srcRect = null; Rect destRect = new Rect(); mStarOneSrcRect = new Rect(0, 0, mStarOneWidth, mStarOneHeight); if (count % 3 == 0) { bitmap = mStarOne; srcRect = mStarOneSrcRect; destRect.set(xLocation, yLocation, xLocation + mStarOneWidth, yLocation + mStarOneHeight); } else if (count % 2 == 0) { bitmap = mStarThree; srcRect = mStarThreeSrcRect; destRect.set(xLocation, yLocation, xLocation + mStarThreeWidth, yLocation + mStarThreeHeight); } else { bitmap = mStarTwo; srcRect = mStarTwoSrcRect; destRect.set(xLocation, yLocation, xLocation + mStarTwoWidth, yLocation + mStarTwoHeight); } paint.setAlpha((int) (starAlpha * 255)); canvas.save(); canvas.scale(sizePercent, sizePercent); canvas.drawBitmap(bitmap, srcRect, destRect, paint); canvas.restore(); } /** * 区域外检测 * * @param starInfo */ private void resetParticleFloat(Particle starInfo) { switch (starInfo.direction) { case LEFT: if (starInfo.xLocation < -20) { starInfo.xLocation = mTotalWidth; } else { starInfo.xLocation -= starInfo.speed; } break; case RIGHT: if (starInfo.xLocation > mTotalWidth + 20) { starInfo.xLocation = 0; } else { starInfo.xLocation += starInfo.speed; } break; case TOP: if (starInfo.yLocation < -20) { starInfo.yLocation = mTotalHeight; } else { starInfo.yLocation -= starInfo.speed; } break; case BOTTOM: if (starInfo.yLocation > mTotalHeight + 30) { starInfo.yLocation = 0; } else { starInfo.yLocation += starInfo.speed; } break; case FREE_POINT://斜线运动,可扩展成为曲线运动 if (starInfo.yLocation > mTotalHeight + 30) { starInfo.yLocation = 0; } else { starInfo.yLocation += starInfo.speed; } if (starInfo.xLocation < -20) { starInfo.xLocation = mTotalWidth; } else { starInfo.xLocation -= starInfo.speed; } break; default: break; } }
管理控制动画的开始结束:
Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (isRuning) { postInvalidate(); handler.sendMessageDelayed(Message.obtain(), 50); } } };
public void startAnimationFloat() { isRuning = true; handler.sendMessage(Message.obtain()); } public void stopAnimationFloat() { isRuning = false; } public void restartAnimationFloat() { startAnimationFloat(); } public void setFloatType(int floatType) { this.floatTyep = floatType; }
三、展示效果
叠加效果【扩展背景】
使用:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@mipmap/phone_bg" android:orientation="vertical"> <com.future.particlesystemdemo.view.ParticleView android:id="@+id/particle_view" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>
public class ShowActivity extends Activity { /** * 粒子系统 */ private ParticleView particleView; /** * 粒子系统运动类型 */ private int type = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_show); particleView = (ParticleView) findViewById(R.id.particle_view); try {//防止无传参跳入 type = getIntent().getIntExtra("type", 100); } catch (Exception e) { e.printStackTrace(); } particleView.setFloatType(ParticleView.DEFAULT_TYPE); switch (type) { case 1: particleView.setFloatType(ParticleView.DEFAULT_TYPE); break; case 2: particleView.setFloatType(ParticleView.FREE_POINT); break; case 3: particleView.setFloatType(ParticleView.TOP); break; case 4: particleView.setFloatType(ParticleView.BOTTOM); break; case 5: particleView.setFloatType(ParticleView.LEFT); break; case 6: particleView.setFloatType(ParticleView.RIGHT); break; } particleView.startAnimationFloat(); }}
源码
百花开时我不开,我若开时百花杀,若与西风战一场,满城尽带黄金甲!
0 0
- android-粒子系统
- android粒子系统
- Android粒子系统
- android opengl es 粒子系统
- android 游戏开发之粒子系统应用
- Android粒子系统库——DroidParticle
- 粒子系统
- 粒子系统
- 粒子系统
- 粒子系统
- 粒子系统
- 粒子系统
- 粒子系统。
- 粒子系统
- 粒子系统
- 粒子系统
- 粒子系统
- 粒子系统
- Word 分节符的删除(不改变文章格式)
- ListView的item间距、横竖屏切换activity生命周期
- 2017年计划
- Linux C语言调用C++动态链接库
- jQueryUI 小结
- Android粒子系统
- 读取文件,打印制定的行
- 最全JAVA地球上两点间的距离算法!包含球体、椭球体、百度算法
- 查看Linux系统版本与位数
- javaweb常见错误及解决办法
- Java递归相关题目
- select a process to debug android 调试模式的两种方式
- AE 统计分析
- linux下查看文件内容工具