SurfaceView的应用
一,SurfaceView的初识
android游戏开发中常用的三种视图是:view、SurfaceView和GLSurfaceView
View:显示视图,内置画布,提供图形绘制函数、触屏事件、按键事件函数等;必须在UI主线程内更新画面,速度较慢。
SurfaceView:基于view视图进行拓展的视图类,更适合2D游戏的开发;是view的子类,类似使用双缓机制,在新的线程中更新画面所以刷新界面速度比view快。
GLSurfaceView:基于SurfaceView视图再次进行拓展的视图类,专用于3D游戏开发的视图;是SurfaceView的子类,openGL专用。
View可以在UI的主线程中更新画面,但可能存在无法响应按键,触屏等消息。使用surfaceView 不会阻塞UI线程,但涉及到线程同步。
二,SurfaceView的使用
1,核心类:
a.继承SurfaceView
b.实现SurfaceHolder.Callback接口
2,重写方法:
(1)public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}
//在surface的大小发生改变时激发(2)public void surfaceCreated(SurfaceHolder holder){}
//在创建时激发,一般在这里调用画图的线程。(3)public void surfaceDestroyed(SurfaceHolder holder) {}
//销毁时激发,一般在这里将画图的线程停止、释放。
3,主业务逻辑实现--SurfaceHolder
SurfaceHolder:surface的控制器,用来控制surface。处理Holder上Canvas的效果和动画,控制表面,大小,像素等。
(1)、abstract void addCallback(SurfaceHolder.Callback callback);
// 给SurfaceView当前的持有者一个回调对象。(2)、abstract Canvas lockCanvas();
// 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。(3)、abstract Canvas lockCanvas(Rect dirty);
// 锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost来改变显示内容。
// 相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素,可以提高速度。(4)、abstract void unlockCanvasAndPost(Canvas canvas);
// 结束锁定画图,并提交改变。
4,整理整体使用步骤:
继承SurfaceView并实现SurfaceHolder.Callback接口SurfaceView.getHolder()获得SurfaceHolder对象SurfaceHolder.addCallback(callback)添加回调函数【子线程中优化实现】SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布Canvas绘画SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。
三、基础使用 --- 绘制文字、圆形、矩形【基础实现】
public class TestSurfaceViewActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);View view = new TextSurfaceView(this);view.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startActivity(new Intent(TestSurfaceViewActivity.this, VideoPlayorActivity.class));}});setContentView(view);}/*** 继承SurfaceView并实现SurfaceHolder.Callback接口*/class TextSurfaceView extends SurfaceView implements SurfaceHolder.Callback {/*** 控制器*/SurfaceHolder holder = null;/*** 子线程,用于更新界面内容*/TextThread textThread;public TextSurfaceView(Context context) {super(context);holder = getHolder();holder.addCallback(this);textThread = new TextThread(holder);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {textThread.isRun = true;textThread.start();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {textThread.isRun = false;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas = holder.lockCanvas();Paint paint = new Paint();
// paint.setColor(Color.GREEN);paint.setColor(Color.argb(1, (int) (Math.random()), (int) (Math.random()), (int) (Math.random())));canvas.drawColor(Color.BLUE);canvas.drawCircle(50, 100, 80, paint);holder.unlockCanvasAndPost(canvas);}}class TextThread extends Thread {/*** 是否正在运行*/private boolean isRun;/*** 控制器*/private final SurfaceHolder holder;/*** 左上角坐标点位*/private int x = 0;private int y = 0;public TextThread(SurfaceHolder holder) {this.holder = holder;isRun = true;}@Overridepublic void run() {super.run();int count = 0;while (isRun) {/*** 子线程具体实现,修改界面内容*/Canvas canvas = null;try {synchronized (holder) {canvas = holder.lockCanvas();canvas.drawColor(Color.BLACK);Paint paint = new Paint();paint.setColor(Color.RED);canvas.drawRect(x, y, x + 100, y + 200, paint);
// canvas.drawRect(0, 0f, 100f, 200f, paint);paint.setTextSize(40);canvas.drawText("这是第" + (count++) + "秒", x + 160, y + 260, paint);move();Thread.sleep(1000);}} catch (Exception e) {e.printStackTrace();} finally {if (canvas != null) {holder.unlockCanvasAndPost(canvas);}}}}/*** 目标对象运动轨迹控制*/private void move() {if (x > 480) {x = 10;} else {x += 10;}if (y > 720) {y = 20;} else {y = x + y - 5;}}}}
四、拖拽图片实现【触控事件】
/*** 功能描述:拖动展示图片* 时间:2016/8/4* 作者:vision*/
public class DragActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);DragImage view = new DragImage(this);setContentView(view);}private class DragImage extends SurfaceView implements SurfaceHolder.Callback, Runnable, View.OnTouchListener {private Context context;private SurfaceHolder holder;private Bitmap icon;private Paint paint;private boolean running = true;// Region region=new Region();private Point point = new Point();//点击点private Rect rect = new Rect(40, 40, 200, 200);//图片的rectprivate boolean canDrag = false;//判断是否点击在图片上,否则拖动无效private int offsetX = 0, offsetY = 0;//点击点离图片左上角的距离public DragImage(Context context) {super(context);this.context = context;holder = this.getHolder();//获取holderholder.addCallback(this);this.setOnTouchListener(this);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {icon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.e);paint = new Paint();running = true;new Thread(this).start();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {running = false;}@Overridepublic void run() {int SLEEP_TIME = 100;while (running) {//开始画的时间 long start=System.currentTimeMillis();Canvas canvas = holder.lockCanvas();//获取画布canvas.drawColor(Color.BLACK);canvas.drawBitmap(icon, rect.left, rect.top, null);holder.unlockCanvasAndPost(canvas);// 解锁画布,提交画好的图像//结束的时间 long end=System.currentTimeMillis();}}@Overridepublic boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubswitch (event.getAction()) {//手按下的时候case MotionEvent.ACTION_DOWN:point.x = (int) event.getX();point.y = (int) event.getY();if (rect.contains(point.x, point.y)) {canDrag = true;offsetX = point.x - rect.left;offsetY = point.y - rect.top;}break;//移动的时候case MotionEvent.ACTION_MOVE:if (canDrag) {/*** 控制不出边框*/rect.left = (int) event.getX() - offsetX;rect.top = (int) event.getY() - offsetY;rect.right = rect.left + icon.getWidth();rect.bottom = rect.top + icon.getHeight();if (rect.left < 0) {rect.left = 0;rect.right = rect.left + icon.getWidth();}if (rect.right > getMeasuredWidth()) {rect.right = getMeasuredWidth();rect.left = rect.right - icon.getWidth();}if (rect.top < 0) {rect.top = 0;rect.bottom = rect.top + icon.getHeight();}if (rect.bottom > getMeasuredHeight()) {rect.bottom = getMeasuredHeight();rect.top = rect.bottom - icon.getHeight();}}break;case MotionEvent.ACTION_UP:canDrag = false;break;default:break;}return true;}}
}
五、游戏动画实现
借鉴网络信息,实现基本控制。
具体实现如源码,其中推荐实现,通过JPG图片加载运行动画的不同状态。
其下部分所需图片原件,下载即可使用。
public class GameSurfaceView extends SurfaceView implementsSurfaceHolder.Callback {//屏幕宽高public static int SCREEN_WIDTH;public static int SCREEN_HEIGHT;private Context mContext;private SurfaceHolder mHolder;//最大帧数 (1000 / 30)private static final int DRAW_INTERVAL = 30;private DrawThread mDrawThread;private FrameAnimation[] spriteAnimations;private Sprite mSprite;private int spriteWidth = 0;private int spriteHeight = 0;private float spriteSpeed = (float) ((500 * SCREEN_WIDTH / 480) * 0.001);private int row = 4;private int col = 4;public GameSurfaceView(Context context) {super(context);this.mContext = context;mHolder = this.getHolder();mHolder.addCallback(this);initResources();mSprite = new Sprite(spriteAnimations, 0, 0, spriteWidth, spriteHeight, spriteSpeed);}private void initResources() { Bitmap[][] spriteImgs = generateBitmapArray(mContext, R.drawable.sprite, row, col);spriteAnimations = new FrameAnimation[row];for (int i = 0; i < row; i++) {Bitmap[] spriteImg = spriteImgs[i];FrameAnimation spriteAnimation = new FrameAnimation(spriteImg, new int[]{150, 150, 150, 150}, true);spriteAnimations[i] = spriteAnimation;}}public Bitmap decodeBitmapFromRes(Context context, int resourseId) {BitmapFactory.Options opt = new BitmapFactory.Options();opt.inPreferredConfig = Bitmap.Config.RGB_565;opt.inPurgeable = true;opt.inInputShareable = true;InputStream is = context.getResources().openRawResource(resourseId);return BitmapFactory.decodeStream(is, null, opt);}public Bitmap createBitmap(Context context, Bitmap source, int row,int col, int rowTotal, int colTotal) {Bitmap bitmap = Bitmap.createBitmap(source,(col - 1) * source.getWidth() / colTotal,(row - 1) * source.getHeight() / rowTotal, source.getWidth()/ colTotal, source.getHeight() / rowTotal);return bitmap;}public Bitmap[][] generateBitmapArray(Context context, int resourseId,int row, int col) {Bitmap bitmaps[][] = new Bitmap[row][col];Bitmap source = decodeBitmapFromRes(context, resourseId);this.spriteWidth = source.getWidth() / col;this.spriteHeight = source.getHeight() / row;for (int i = 1; i <= row; i++) {for (int j = 1; j <= col; j++) {bitmaps[i - 1][j - 1] = createBitmap(context, source, i, j,row, col);}}if (source != null && !source.isRecycled()) {source.recycle();source = null;}return bitmaps;}public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}public void surfaceCreated(SurfaceHolder holder) {if (null == mDrawThread) {mDrawThread = new DrawThread();mDrawThread.start();}}public void surfaceDestroyed(SurfaceHolder holder) {if (null != mDrawThread) {mDrawThread.stopThread();}}private class DrawThread extends Thread {public boolean isRunning = false;public DrawThread() {isRunning = true;}public void stopThread() {isRunning = false;boolean workIsNotFinish = true;while (workIsNotFinish) {try {this.join();// 保证run方法执行完毕} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}workIsNotFinish = false;}}public void run() {long deltaTime = 0;long tickTime = 0;tickTime = System.currentTimeMillis();while (isRunning) {Canvas canvas = null;try {synchronized (mHolder) {canvas = mHolder.lockCanvas();//设置方向mSprite.setDirection();//更新精灵位置mSprite.updatePosition(deltaTime);drawSprite(canvas);}} catch (Exception e) {e.printStackTrace();} finally {if (null != mHolder) {mHolder.unlockCanvasAndPost(canvas);}}deltaTime = System.currentTimeMillis() - tickTime;if (deltaTime < DRAW_INTERVAL) {try {Thread.sleep(DRAW_INTERVAL - deltaTime);} catch (InterruptedException e) {e.printStackTrace();}}tickTime = System.currentTimeMillis();}}}private void drawSprite(Canvas canvas) {//清屏操作canvas.drawColor(Color.BLACK);mSprite.draw(canvas);}}
这里是源码~_~
若不是情到深处难自禁
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
