/* 定义DisplayMetrics对象 */ DisplayMetrics dm = new DisplayMetrics(); /* 取得窗口属性 */ getWindowManager().getDefaultDisplay().getMetrics(dm); 1.基本图像绘制 /* 创建两个图片对象 */ Bitmap mBitQQ = null; Bitmap mBitDestTop = null;
int miDTX = 0;
public GameView(Context context) { super(context); mPaint = new Paint(); miDTX = 0; /* 从资源文件中装载图片 */ //getResources()->得到Resources //getDrawable()->得到资源中的Drawable对象,参数为资源索引ID //getBitmap()->得到Bitmap mBitQQ = ((BitmapDrawable) getResources().getDrawable(R.drawable.qq)).getBitmap(); mBitDestTop = ((BitmapDrawable) getResources().getDrawable(R.drawable.desktop)).getBitmap(); new Thread(this).start(); } public void onDraw(Canvas canvas) { super.onDraw(canvas); /* 清屏效果 */ canvas.drawColor(Color.GRAY); /* 在屏幕(0,0)处绘制图片mBitQQ */ GameView.drawImage(canvas, mBitQQ, 0, 0); /* 在制定位置按指定裁剪的渔区进行绘制 */ //getWidth()->得到图片的宽度 //getHeight()->得到图片的高度 GameView.drawImage(canvas, mBitDestTop, miDTX, mBitQQ.getHeight(), mBitDestTop.getWidth(), mBitDestTop.getHeight()/2, 0, 0); }
2。旋转图片 public void onDraw(Canvas canvas) { super.onDraw(canvas); /* 重置mMatrix */ mMatrix.reset(); /* 设置旋转 */ mMatrix.setRotate(Angle); /* 按mMatrix得旋转构建新的Bitmap */ Bitmap mBitQQ2 = Bitmap.createBitmap(mBitQQ, 0, 0, BitQQwidth,BitQQheight, mMatrix, true);
/* 绘制旋转之后的图片 */ GameView.drawImage(canvas, mBitQQ2, (320-BitQQwidth)/2, 10); mBitQQ2 = null; } 3。缩放图片 public void onDraw(Canvas canvas) { super.onDraw(canvas); /* 重置mMatrix */ mMatrix.reset(); /* 设置缩放 */ mMatrix.postScale(Scale,Scale); /* 按mMatrix得旋转构建新的Bitmap */ Bitmap mBitQQ2 = Bitmap.createBitmap(mBitQQ, 0, 0, BitQQwidth,BitQQheight, mMatrix, true);
/* 绘制旋转之后的图片 */ GameView.drawImage(canvas, mBitQQ2, (320-BitQQwidth)/2, 10); mBitQQ2 = null; } 4。混合渲染 /* 得到图片的宽度和高度 */ BitQQwidth = mBitQQ.getWidth(); BitQQheight = mBitQQ.getHeight(); /* 创建BitmapShader对象 */ mBitmapShader = new BitmapShader(mBitQQ,Shader.TileMode.REPEAT,Shader.TileMode.MIRROR); /* 创建LinearGradient并设置渐变的颜色数组 */ mLinearGradient = new LinearGradient(0,0,100,100, new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.WHITE}, null,Shader.TileMode.REPEAT); /* 这里笔者理解为“混合渲染”--大家可以有自己的理解,能明白这个意思就好*/ mComposeShader = new ComposeShader(mBitmapShader,mLinearGradient,PorterDuff.Mode.DARKEN); /* 构建RadialGradient对象,设置半径的属性 */ //这里使用了BitmapShader和LinearGradient进行混合 //当然也可以使用其他的组合 //混合渲染的模式很多,可以根据自己需要来选择 mRadialGradient = new RadialGradient(50,200,50, new int[]{Color.GREEN,Color.RED,Color.BLUE,Color.WHITE}, null,Shader.TileMode.REPEAT); /* 构建SweepGradient对象 */ mSweepGradient = new SweepGradient(30,30,new int[]{Color.GREEN,Color.RED,Color.BLUE,Color.WHITE},null);
mPaint = new Paint(); /* 开启线程 */ new Thread(this).start(); } public void onDraw(Canvas canvas) { super.onDraw(canvas); //将图片裁剪为椭圆形 /* 构建ShapeDrawable对象并定义形状为椭圆 */ mShapeDrawableQQ = new ShapeDrawable(new OvalShape());
/* 设置要绘制的椭圆形的东西为ShapeDrawable图片 */ mShapeDrawableQQ.getPaint().setShader(mBitmapShader); /* 设置显示区域 */ mShapeDrawableQQ.setBounds(0,0, BitQQwidth, BitQQheight); /* 绘制ShapeDrawableQQ */ mShapeDrawableQQ.draw(canvas); //绘制渐变的矩形 mPaint.setShader(mLinearGradient); canvas.drawRect(BitQQwidth, 0, 320, 156, mPaint); //显示混合渲染效果 mPaint.setShader(mComposeShader); canvas.drawRect(0, 300, BitQQwidth, 300+BitQQheight, mPaint); //绘制环形渐变 mPaint.setShader(mRadialGradient); canvas.drawCircle(50, 200, 50, mPaint); //绘制梯度渐变 mPaint.setShader(mSweepGradient); canvas.drawRect(150, 160, 300, 300, mPaint); } 5。图片水纹处理 public class GameView extends View implements Runnable { int BACKWIDTH;
int BACKHEIGHT;
short[] buf2;
short[] buf1;
int[] Bitmap2;
int[] Bitmap1; public GameView(Context context) { super(context); /* 装载图片 */ Bitmap image = BitmapFactory.decodeResource(this.getResources(),R.drawable.qq); BACKWIDTH = image.getWidth(); BACKHEIGHT = image.getHeight(); buf2 = new short[BACKWIDTH * BACKHEIGHT]; buf1 = new short[BACKWIDTH * BACKHEIGHT]; Bitmap2 = new int[BACKWIDTH * BACKHEIGHT]; Bitmap1 = new int[BACKWIDTH * BACKHEIGHT];
/* 加载图片的像素到数组中 */ image.getPixels(Bitmap1, 0, BACKWIDTH, 0, 0, BACKWIDTH, BACKHEIGHT); new Thread(this).start(); } void DropStone(int x,// x坐标 int y,// y坐标 int stonesize,// 波源半径 int stoneweight)// 波源能量 { for (int posx = x - stonesize; posx < x + stonesize; posx++) for (int posy = y - stonesize; posy < y + stonesize; posy++) if ((posx - x) * (posx - x) + (posy - y) * (posy - y) < stonesize * stonesize) buf1[BACKWIDTH * posy + posx] = (short) -stoneweight; } void RippleSpread() { for (int i = BACKWIDTH; i < BACKWIDTH * BACKHEIGHT - BACKWIDTH; i++) { // 波能扩散 buf2[i] = (short) (((buf1[i - 1] + buf1[i + 1] + buf1[i - BACKWIDTH] + buf1[i + BACKWIDTH]) >> 1) - buf2[i]); // 波能衰减 buf2[i] -= buf2[i] >> 5; }
// 交换波能数据缓冲区 short[] ptmp = buf1; buf1 = buf2; buf2 = ptmp; }
/* 渲染你水纹效果 */ void render() { int xoff, yoff; int k = BACKWIDTH; for (int i = 1; i < BACKHEIGHT - 1; i++) { for (int j = 0; j < BACKWIDTH; j++) { // 计算偏移量 xoff = buf1[k - 1] - buf1[k + 1]; yoff = buf1[k - BACKWIDTH] - buf1[k + BACKWIDTH];
// 判断坐标是否在窗口范围内 if ((i + yoff) < 0) { k++; continue; } if ((i + yoff) > BACKHEIGHT) { k++; continue; } if ((j + xoff) < 0) { k++; continue; } if ((j + xoff) > BACKWIDTH) { k++; continue; }
// 计算出偏移象素和原始象素的内存地址偏移量 int pos1, pos2; pos1 = BACKWIDTH * (i + yoff) + (j + xoff); pos2 = BACKWIDTH * i + j; Bitmap2[pos2++] = Bitmap1[pos1++]; k++; } } } public void onDraw(Canvas canvas) { super.onDraw(canvas); /* 绘制经过处理的图片效果 */ canvas.drawBitmap(Bitmap2, 0, BACKWIDTH, 0, 0, BACKWIDTH, BACKHEIGHT, false, null); } // 触笔事件 public boolean onTouchEvent(MotionEvent event) { return true; }
// 按键按下事件 public boolean onKeyDown(int keyCode, KeyEvent event) { return true; }
// 按键弹起事件 public boolean onKeyUp(int keyCode, KeyEvent event) { DropStone(BACKWIDTH/2, BACKHEIGHT/2, 10, 30); return false; }
public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { return true; } /** * 线程处理 */ public void run() { while (!Thread.currentThread().isInterrupted()) { try { Thread.sleep(50); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } RippleSpread(); render(); //使用postInvalidate可以直接在线程中更新界面 postInvalidate(); } } }