package com.tomandjerry.coolanim.lib.pellet; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.Log; import com.tomandjerry.coolanim.lib.Config; /** * 小球运动过程中是椭圆的 * Created by yanxing on 16/1/31. */ public class SmallYellowBall { private static SmallYellowBall mBall; private boolean isShow = false; private Paint mPaint; private int mRadius; private float mCurX; private int mOriginX; private float mCurY; private int mOriginY; // 两球的距离 private float mDistance; // 地面距离中心的距离 public static int HEIGHT = 50; // 重力加速度 public static float gravity = 9.8f / (1000 * 1000); // x方向的速度 private float mSpeedX; private float mDuration; // 当前运动的距离 private float curDistance; // 当前时间 private float curTime; private float mFiRate; // 椭圆绘制区域 private RectF mRectF; // y方向的速度 private float mSpeedY; // y方向的最大速度 private float maxSpeedY; // 球的偏移角度 private float mAngle; // 球的压缩 private float mShift; private boolean isStart = false; public SmallYellowBall() { initConfig(); } protected void initConfig() { mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(Config.YELLOW); mRadius = 15; mDistance = 120; mDuration = 2000; mSpeedX = mDistance / mDuration; mFiRate = HEIGHT * 4 / mDuration; // 初始化重力加速度 gravity = (float) (3 * HEIGHT / Math.pow(mDuration / 4f, 2)); maxSpeedY = gravity * mDuration / 4; mRectF = new RectF(mCurX - mRadius, mCurY - mRadius, mCurX + mRadius, mCurY + mRadius); mShift = mRadius / 6; } // 获取单实例的球 // public synchronized static SmallYellowBall getInstance() { // if (mBall == null) { // mBall = new SmallYellowBall(); // } // return mBall; // } /** * 分开四个段区域 */ public void throwOut() { if (isStart) { return; } ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mDuration); valueAnimator.setDuration((long) mDuration); // 3个节点 final float fiv = mDistance / 4; final float sev = mDistance / 2; final float thv = mDistance * 3 / 4; valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { curTime = (float) animation.getAnimatedValue(); curDistance = curTime * mSpeedX; mRectF.set(mCurX - mRadius, mCurY - mRadius, mCurX + mRadius, mCurY + mRadius); if (curDistance <= fiv) { mCurY = mOriginY + curTime * mFiRate; mAngle = 0; if (curDistance >= 5 && curDistance < fiv - 2) { mRectF.set(mCurX - mRadius + mShift, mCurY - mRadius, mCurX + mRadius - mShift, mCurY + mRadius); mAngle = -45; } // 掷地一刻压扁效果 if (curDistance >= fiv - 2) { mRectF.set(mCurX - mRadius, mCurY - mRadius + 10, mCurX + mRadius, mCurY + mRadius); mAngle = 0; } } else if (curDistance <= sev) { curTime -= mDuration / 4; mSpeedY = maxSpeedY - gravity * curTime; mAngle = (float) (Math.atan(mSpeedY / mSpeedX) * 180 / Math.PI); mCurY = mOriginY + HEIGHT - 0.5f * (maxSpeedY + mSpeedY) * curTime; if (mAngle < 15) { mRectF.set(mCurX - mRadius, mCurY - mRadius, mCurX + mRadius, mCurY + mRadius); } else { mRectF.set(mCurX - mRadius + mShift, mCurY - mRadius, mCurX + mRadius - mShift, mCurY + mRadius); } } else if (curDistance <= thv) { curTime -= mDuration / 2; mSpeedY = gravity * curTime; mAngle = -(float) (Math.atan(mSpeedX / mSpeedY) * 180 / Math.PI); mCurY = mOriginY - 0.5f * HEIGHT + 0.5f * mSpeedY * curTime; if (mAngle > -15) { mRectF.set(mCurX - mRadius, mCurY - mRadius, mCurX + mRadius, mCurY + mRadius); } else { mRectF.set(mCurX - mRadius + mShift, mCurY - mRadius, mCurX + mRadius - mShift, mCurY + mRadius); } // 掷地一刻压扁效果 if (curDistance >= thv - 2) { mRectF.set(mCurX - mRadius, mCurY - mRadius + 10, mCurX + mRadius, mCurY + mRadius); mAngle = 0; } } else { curTime -= mDuration * 3 / 4; mCurY = mOriginY + HEIGHT - curTime * mFiRate; mRectF.set(mCurX - mRadius, mCurY - mRadius, mCurX + mRadius, mCurY + mRadius); if (curDistance >= thv + 5 && curDistance < mDistance - 10) { mRectF.set(mCurX - mRadius + mShift, mCurY - mRadius, mCurX + mRadius - mShift, mCurY + mRadius); mAngle = 45; } } mCurX = mOriginX + curDistance; } }); valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { isStart = true; } @Override public void onAnimationEnd(Animator animation) { isStart = false; initConfig(); } }); valueAnimator.start(); } public void drawSelf(Canvas canvas) { if (isShow) { canvas.save(); canvas.rotate(mAngle, mCurX, mCurY); canvas.drawOval(mRectF, mPaint); canvas.restore(); } } public void setShow(boolean show) { this.isShow = show; } public boolean isShow() { return isShow; } public void setCurY(int y) { mCurY = y; mOriginY = y; } public void setCurX(int x) { mCurX = x; mOriginX = x; } }