Android游戏开发----动画SurfaceView详解

SurfaceView在游戏开发中占着举足轻重的地位。今天好好找资料看了看。附带自己写的例子。    
     写变化不太快的画面时,用View就足够了,用View写太快的画面变化时,可能会出现屏幕闪烁。当写如像植物大战僵尸、水果忍者等游戏时,用View就不能满足要求了。Android提供了SurfaceView,它是专门用来做动画,它是View的子类。
    在SurfaceView自带2级缓存,当写变换比较快的游戏时,二级缓存会让游戏画面的变化看起来比较连贯一些。2级缓存的作用就是提前把将要绘制的图片放到内存里面。
一、实现最基本的SurfaceView只需基础即可,再按4个步骤来做即可。直接上代码,详细看代码里里面的注释。
public class GameView extends SurfaceView
{
	SurfaceHolder surfaceHolder;

	public GameView(Context context)
	{
		super(context);
		//1. 获得SurfaceView下是SurfaceHolder, surfaceHolder相当于一个遥控器来控制SurfaceView
		surfaceHolder = this.getHolder();
		//这个是回调方法, 必须有. 否则会报空指针异常. 意思是surface创建, 销毁,改变
		surfaceHolder.addCallback(new Callback()
		{

			@Override
			public void surfaceDestroyed(SurfaceHolder holder)
			{

			}

			@Override
			public void surfaceCreated(SurfaceHolder holder)
			{
				//2. 在surface创建后锁定画布
				Canvas canvas = surfaceHolder.lockCanvas();
				//3. 可以在画布上进行任意的绘画操作( 下面是画一条红色 的线 )
				Paint paint = new Paint();
				paint.setColor(Color.RED);
				canvas.drawLine(0, 0, 100, 100, paint);
				//4. 将画布解锁并显示在屏幕上
				surfaceHolder.unlockCanvasAndPost(canvas);
			}

			@Override
			public void surfaceChanged(SurfaceHolder holder, int format,
					int width, int height)
			{

			}
		});

	}

当然,这样写很明显不是最好的。只有SurfaceView很明显不能实现动画,当然要与线程结合起来。用线程来刷屏。
二、使用SurfaceView来写动画的一般写法。直接上代码,详细解释请看代码里里面的注释。

public class GameViewOK extends SurfaceView implements Callback, Runnable
{
	SurfaceHolder surfaceHolder;
	private boolean isThreadRunning = true;
	Canvas canvas;
	float r = 10;

	public GameViewOK(Context context)
	{
		super(context);
		surfaceHolder = this.getHolder();
		surfaceHolder.addCallback(this);//注册回调方法
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height)
	{

	}

	@Override
	public void surfaceCreated(SurfaceHolder holder)
	{
		//创建surfaceView时启动线程
		new Thread(this).start();
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder)
	{
		//当surfaceView销毁时, 停止线程的运行. 避免surfaceView销毁了线程还在运行而报错.
		isThreadRunning = false;
		//第三种方法防止退出时异常. 当surfaceView销毁时让线程暂停300ms . 醒来再执行run()方法时,isThreadRunning就是false了. 
		try
		{
			Thread.sleep(300);
		} catch (InterruptedException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 将绘图的方法单独写到这个方法里面.
	 */
	private void drawVieW()
	{
		try
		{//第一种方法防止退出时异常: 当isThreadRunning为false时, 最后还是会执行一次drawView方法, 但此时surfaceView已经销毁
			//因此才来判断surfaceHolder
			if (surfaceHolder != null)
			{
				//1. 在surface创建后锁定画布
				canvas = surfaceHolder.lockCanvas();
				//2. 可以在画布上进行任意的绘画操作( 下面是画一条红色 的线 )
				Paint paint = new Paint();
				paint.setColor(Color.BLUE);
				//paint.setStyle(Style.STROKE);//只有边框
				paint.setStrokeWidth(5);
				canvas.drawCircle(100, 100, r++, paint);
			}
		} catch (Exception e)
		{
			e.printStackTrace();
		} finally
		{
			//canvas是根据surfaceHolder得到的, 最后一次surfaceView已经销毁, canvas当然也不存在了.
			if (canvas != null)
				//3. 将画布解锁并显示在屏幕上
				surfaceHolder.unlockCanvasAndPost(canvas);
		}

	}

	@Override
	public void run()
	{
		//每隔100ms刷新屏幕
		while (isThreadRunning)
		{
			drawVieW();
			try
			{
				Thread.sleep(100);
			} catch (Exception e)
			{
				e.printStackTrace();
			}
		}
	}

	/*
	 * 这个是第二种方法解决退出是报错的问题. 当按下返回键时, 提前设置isThreadRunning为false, 让线程结束.
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		if(keyCode == KeyEvent.KEYCODE_BACK)
		{
			isThreadRunning = false;
		}
		return super.onKeyDown(keyCode, event);
	}
	*/
}

运行效果:不断增大的圆形



源码下载地址: http://download.csdn.net/detail/xn4545945/4595694

转载请注明出处: http://blog.csdn.net/xn4545945



你可能感兴趣的:(Android,Android开发点点滴滴)