SurfaceView的应用
来源:互联网 发布:软件授权许可协议 编辑:程序博客网 时间:2024/06/11 02:48
一,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 { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); View view = new TextSurfaceView(this); view.setOnClickListener(new View.OnClickListener() { @Override public 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); } @Override public void surfaceCreated(SurfaceHolder holder) { textThread.isRun = true; textThread.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { textThread.isRun = false; } @Override protected 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; } @Override public 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 { @Override protected 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);//图片的rect private boolean canDrag = false;//判断是否点击在图片上,否则拖动无效 private int offsetX = 0, offsetY = 0;//点击点离图片左上角的距离 public DragImage(Context context) { super(context); this.context = context; holder = this.getHolder();//获取holder holder.addCallback(this); this.setOnTouchListener(this); } @Override public void surfaceCreated(SurfaceHolder holder) { icon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.e); paint = new Paint(); running = true; new Thread(this).start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { running = false; } @Override public 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(); } } @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub switch (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 implements SurfaceHolder.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() { <span style="color:#6600CC;"> <strong> Bitmap[][] spriteImgs = generateBitmapArray(mContext, R.drawable.sprite, row, col);</strong></span> 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 block e.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); }}
这里是源码~_~
若不是情到深处难自禁
又怎会柔肠百转冷如霜
0 0
- SurfaceView的简单应用
- SurfaceView 的应用
- SurfaceView的应用
- SurfaceView的应用
- Android SurfaceView 的基本应用
- Android SurfaceView 的基本应用
- SurfaceView的介绍和应用
- Surfaceview的绘制与应用
- Android 的 SurfaceView 双缓冲应用
- Android 的 SurfaceView 双缓冲应用
- Android 的 SurfaceView 双缓冲应用
- Android 的 SurfaceView 双缓冲应用
- Android 的 SurfaceView 双缓冲应用
- SurfaceView的一个小应用:开发示波器
- Android 的 SurfaceView 双缓冲应用
- SurfaceView 和View 的应用场景
- 17、Android之SurfaceView实例自定义SurfaceView的应用——小球跟着手指移动
- surfaceview简单应用
- leetcode_c++:ZigZag Conversion(006)
- zookeeper原理(转)
- Ceph Rest Api 文档
- 《Java源码分析》:ReadWriteLock(第二部分)
- 前端开发人员必须了解的七大技能图谱
- SurfaceView的应用
- fileBeat和Elk整合的问题
- Linux 安装 域名服务
- 大数相减
- PropertyUtils.copyProperties()方法的理解
- redis之安装与远程连接配置
- 单例模式的七种写法
- Best Reward
- PAT准备——题目训练