您的位置:首页 > 移动开发 > Android开发

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

2014-03-08 13:16 776 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐