Android 星体动效实现

的基础上,进行了部分优化,源码在http://download.csdn.net/detail/xiaomu123456/9685975,主要看StarActivity就行了
实际效果如下:


首先,要实现这样一幅动效图,基本上就是两个步骤:
  第一,在背景上确定物体(图片中的星体,流星)的初始位置
  第二,使物体进行移动,在此过程中要实时更新物体的参数信息,比如大小,亮度等

其次,对于图中的每一个实体对象,都需要以下基本信息
   1.方向2.速度3.形态4.大小5.位置6.物体宽度,高度7透明度等

具体定义如下:
public class StarInfo {

    //方向
    public final static int LEFT = 0;
    public final static int RIGHT = 1;
    public final static int TOP = 2;
    public final static int BOTTOM = 3;
    public static final int RIGHT_BOTTOM = 4;

    //速度,实际上相当于在背景上移动的距离(像素)
    public static final int LOW_SPEED = 1;
    public static final int MID_SPEED = 2;
    public static final int HIGTH_SPEED = 3;

    public Bitmap mBitmap;//形态
    public int mWidth;//物体宽度
    public int mHeight;//物体高度
    public Rect mSrcRect;//自身所占的矩形区域

    // 大小
    float sizePercent;
    // x位置
    int xLocation;
    // y位置
    int yLocation;
    // 透明度
    float alpha;
    // 漂浮方向
    int direction;
    // 漂浮速度
    int speed;
}

在图中第一种对象为星体,定义如下:

public class CircleStar extends StarInfo {

    public static final int STAR_TYPE_1 = 101;
    public static final int STAR_TYPE_2 = 102;
    public static final int STAR_TYPE_3 = 103;

    private Context mContext;

    public CircleStar(Context context,int type){
        this.mContext = context;
        initBitmap(type);
    }

    public void initBitmap( int type ){
        switch (type){
            case STAR_TYPE_1:
                mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_start1))
                        .getBitmap();
                break;
            case STAR_TYPE_2:
                mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_star2))
                        .getBitmap();
                break;
            case STAR_TYPE_3:
                mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_star2))
                        .getBitmap();
                break;
            default:
                mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_start1))
                        .getBitmap();
                break;
        }
        mWidth = mBitmap.getWidth();
        mHeight = mBitmap.getHeight();
        mSrcRect = new Rect(0,0, mWidth, mHeight);
    }

}

在图中第二种对象为流星,定义如下:

public class FallingStar extends StarInfo {

    private Context mContext;

    public FallingStar(Context context){
        this.mContext = context;
        initBitmap();
    }

    public void initBitmap(){
        mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.light_star_1))
                .getBitmap();
        mWidth = mBitmap.getWidth();
        mHeight = mBitmap.getHeight();
        mSrcRect = new Rect(0,0, mWidth, mHeight);
    }
}
最后在view中展示动画效果:

public class StarView extends View {

    private final static int mStarCount = 200;//背景图添加了200个实体对象
    private List<StarInfo> mStarInfos = new ArrayList();
    private Bitmap mBackgoundBitmap;//背景图片
    private int mBackgoundWidth;
    private int mBackgoundHeight;
    private int mTotalWidth,mTotalHeight;//实际上是背景宽度和高度
    private Paint mPaint;

    public StarView(Context context) {
        this(context,null);
    }

    public StarView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public StarView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData();
        initStarInfo();
    }

    private void initData() {
        //背景
        mBackgoundBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.bg_star))
                .getBitmap();
        mBackgoundWidth = mBackgoundBitmap.getWidth();
        mBackgoundHeight = mBackgoundBitmap.getHeight();
        mTotalWidth = mBackgoundWidth;
        mTotalHeight = mBackgoundHeight;
        this.setBackgroundResource(R.drawable.bg_star);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setFilterBitmap(true);
        mPaint.setDither(true);
    }

    /**
     * 获取星球大小
     */
    private float getStarSize(float start, float end) {
        float nextFloat = (float) Math.random();
        if (start < nextFloat && nextFloat < end) {
            return nextFloat;
        } else {
            // 如果不处于想要的数据段,则再随机一次,因为不断递归有风险
            return (float) Math.random();
        }
    }

    /**
     * 初始化星球信息
     */
    private void initStarInfo() {

        StarInfo starInfo = null;
        for (int i = 0; i < mStarCount; i++) {

            if( i % 2 == 0 ){
                starInfo = new CircleStar(getContext(),CircleStar.STAR_TYPE_1);//星体1
            }else if(i % 3 == 0){
                starInfo = new CircleStar(getContext(),CircleStar.STAR_TYPE_2);//星体2
            }else{
                starInfo = new FallingStar(getContext());//流星
            }

            //共有属性
            starInfo.sizePercent = getStarSize(0.1f, 0.2f);
            getStarSpeed(starInfo);
            starInfo.alpha = getStarSize(0.3f, 0.5f);
            starInfo.xLocation = (int) (getStarSize(0f,1f) * mTotalWidth);
            starInfo.yLocation = (int) (getStarSize(0f,1f) * mTotalHeight);

            if( starInfo instanceof FallingStar ){
                starInfo.direction = StarInfo.RIGHT_BOTTOM;
            }else {
                starInfo.direction = getStarDirection();
            }
            mStarInfos.add(starInfo);
        }
    }

    /**
     *在画布上画出star
     */
    private void drawStarDynamic(StarInfo starInfo, Canvas canvas, Paint paint) {
        int xLocation = (int) ( starInfo.xLocation / starInfo.sizePercent);
        int yLocation = (int) ( starInfo.yLocation / starInfo.sizePercent);

        Bitmap bitmap = starInfo.mBitmap;
        Rect srcRect = starInfo.mSrcRect;
        Rect destRect = new Rect();
        destRect.set(xLocation, yLocation, xLocation + starInfo.mWidth, yLocation + starInfo.mHeight);

        paint.setAlpha((int) (starInfo.alpha * 255));
        canvas.save();
        canvas.scale(starInfo.sizePercent, starInfo.sizePercent);
        canvas.drawBitmap(bitmap, srcRect, destRect, paint);
        canvas.restore();

    }

    /**
     *改变star的参数信息(比如速度,透明度,大小等),在画布上移动star
     */
    private void resetStarFloat(StarInfo starInfo) {
        switch (starInfo.direction) {
            case StarInfo.LEFT:
                starInfo.xLocation -= starInfo.speed;
                if( starInfo.xLocation <= 0 ){
                    starInfo.direction = StarInfo.RIGHT;
                }
                break;
            case StarInfo.RIGHT:
                starInfo.xLocation += starInfo.speed;
                if( starInfo.xLocation >= mTotalWidth ){
                    starInfo.direction = StarInfo.LEFT;
                }
                break;
            case StarInfo.TOP:
                starInfo.yLocation -= starInfo.speed;
                if( starInfo.yLocation <= 0 ){
                    starInfo.direction = StarInfo.BOTTOM;
                }
                break;
            case StarInfo.BOTTOM:
                starInfo.yLocation += starInfo.speed;
                if( starInfo.yLocation >= mTotalHeight ){
                    starInfo.direction = StarInfo.TOP;
                }
                break;
            case StarInfo.RIGHT_BOTTOM:
                starInfo.xLocation += starInfo.speed;
                starInfo.yLocation += starInfo.speed;
                starInfo.alpha += 0.003;
                starInfo.sizePercent += 0.003;
                if( starInfo.xLocation  >= mTotalWidth ){
                    starInfo.xLocation = 0;
                    starInfo.sizePercent = 0.1f;
                    starInfo.alpha = getStarSize(0.0f,0.3f);
                }else if( starInfo.yLocation >= mTotalHeight ){
                    starInfo.yLocation = 0;
                    starInfo.sizePercent = 0.1f;
                    starInfo.alpha = getStarSize(0.0f,0.3f);
                }
                if( starInfo.alpha >= 1.0 ){
                    starInfo.alpha = 1;
                }
                if( starInfo.sizePercent >= 0.6 ){
                    starInfo.sizePercent = 0.6f;
                }

                break;
            default:
                break;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < mStarInfos.size(); i++) {
            drawStarDynamic(mStarInfos.get(i), canvas, mPaint);
            resetStarFloat(mStarInfos.get(i));
        }
        postInvalidate();
    }

    /**
     * 初始化漂浮速度
     */
    private int getStarSpeed(StarInfo starInfo){
        Random random = new Random();
        int randomSpeed = random.nextInt(3);
        switch (randomSpeed) {
            case 0:
                starInfo.speed = StarInfo.LOW_SPEED;
                break;
            case 1:
                starInfo.speed = StarInfo.MID_SPEED;
                break;
            case 2:
                starInfo.speed = StarInfo.HIGTH_SPEED;
                break;
            default:
                starInfo.speed = StarInfo.MID_SPEED;
                break;
        }
        return starInfo.speed;
    }

    /**
     * 初始化星球运行方向
     */
    public int getStarDirection() {
        Random random = new Random();
        int randomInt = random.nextInt(4);
        int direction = 0;
        switch (randomInt) {
            case 0:
                direction = StarInfo.LEFT;
                break;
            case 1:
                direction = StarInfo.RIGHT;
                break;
            case 2:
                direction = StarInfo.TOP;
                break;
            case 3:
                direction = StarInfo.BOTTOM;
                break;

            default:
                break;
        }
        return direction;
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值