/* 定义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();
}
}
}