先上下最終實作的效果圖:
制作的gif效果有點閃哈,真機上效果要好一點的 接下來進入正題:
1.繪制波浪
主要利用斐波那契函數繪制二條曲線,然後不停地偏移一些距離實作波浪移動的效果 以下代碼是直接使用某位大神的代碼進行的修改
protected void onDraw(Canvas canvas) {
canvas.setDrawFilter(mDrawFilter);
mAbovePath.reset();
mBelowWavePath.reset();
φ -= 0.1f;
float y, y2;
ω = 2 * Math.PI / getWidth();
mAbovePath.moveTo(getLeft(), getBottom());
mBelowWavePath.moveTo(getLeft(), getBottom());
for (float x = 0; x <= getWidth(); x += 20) {
/**
* y=Asin(ωx+φ)+k
* A—振幅越大,波形在y軸上最大與最小值的內插補點越大
* ω—角速度, 控制正弦周期(機關角度内震動的次數)
* φ—初相,反映在坐标系上則為圖像的左右移動。這裡通過不斷改變φ,達到波浪移動效果
* k—偏距,反映在坐标系上則為圖像的上移或下移。
*/
y = (float) (height / 8 * Math.cos(ω * x + φ) + height / 8 * 3 + height / 2);
y2 = (float) (height / 8 * Math.sin(ω * x + φ) + height / 2);
mAbovePath.lineTo(x, y);
mBelowWavePath.lineTo(x, y2);
//回調 把y坐标的值傳出去(在activity裡面接收讓小機器人随波浪一起搖擺)
mWaveAnimationListener.OnWaveAnimation(y);
}
for(int i=0;i<boards.size();i++){
boards.get(i).drawBoard(canvas);
}
mAbovePath.lineTo(getRight(), getBottom());
mBelowWavePath.lineTo(getRight(), getBottom());
canvas.drawPath(mAbovePath, mAboveWavePaint);
canvas.drawPath(mBelowWavePath, mBelowWavePaint);
postInvalidateDelayed(20);
}
2.繪制小船
建立一個小船類,根據x,y坐标在上面繪制一個bitmap,然後每次随機的向左偏移一段距離,實作移動。
public class Board {
int width;Context context;int type;
int left;
public Board(int width,Context context, int type) {
this.width = width;
this.left=(int)(r.nextInt(100)*width/100);
this.context = context;
this.type = type;
}
Random r=new Random();
public void drawBoard(Canvas canvas) {
Paint paint = new Paint();
int resource=R.mipmap.board1;
switch (type){
case 0:
resource=R.mipmap.board1;
break;
case 1:
resource=R.mipmap.board2;
break;
case 2:
resource=R.mipmap.board3;
break;
case 3:
resource=R.mipmap.board4;
break;
case 4:
resource=R.mipmap.board5;
break;
case 5:
resource=R.mipmap.board6;
break;
}
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resource);
canvas.drawBitmap(bitmap, left, WaveView.getHeight(left)-bitmap.getHeight()/6*5, paint);
left-=r.nextInt(3)*width/1000;
if(left<=-bitmap.getWidth()){
left=width;
}
}
}
在WaveView中提供根據X坐标擷取Y坐标的方法
public static float getHeight(int left) {
return (float) (height / 8 * Math.cos(ω * left + φ) + height / 8 * 3 + height / 2);
}
最後再WaveView的OnDraw方法中同時繪制所有的小船
for(int i=0;i<boards.size();i++){
boards.get(i).drawBoard(canvas);
}
3.繪制小魚
小魚繪制比較複雜,是直接照搬國外大牛做的,我稍微修改了下,給魚随機産生顔色和移動速度
fishDrawable = new FishDrawable(context, random.nextInt(255), random.nextInt(255), random.nextInt(255));
然後在布局中添加10條
RelativeLayout fishpool= (RelativeLayout) findViewById(R.id.fishpool);
int i=0;
do{
fishpool.addView(new FishDrawableView(this));
i++;
}while (i<10);
到此,就完工了!
感興趣的可以在下方連結進行下載下傳,感覺還可以,幫忙給個star吧!