SurfaceView 游戏开发的一些基础知识和注意事项

 

  surfaceview 是游戏开发和视频播放常用的控件,因此我们要自己开发一些小游戏或者视频播放器多用来继承该view,并添加自己的独特功能。下面就以做游戏的框架来介绍:

先介绍一些基础知识:

1、继承surfaceview的view(就简称MyView),要想在布局文件中能使用,我们要覆写surfacview的构造方法:

 public MySurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

2、当系统在加载游戏时候,比如初始化MyView的时候需要时间,为了去掉游戏开始前短暂的黑屏情况,我们通常写一个欢迎界面,或者写一个关级等,方法有很多,我们可以用一个比较简单的方法:
 在布局文件里加上我们的surfacview和关级或者图片的控件。初始的时候将Myview设置为Gone , 其他的设置为Visibale。在resume里面开始准备我们的MyView游戏里面图片、声音等素材的加载(注意设置标志位,否则home再次进入的时候会又初始化导致游戏数据混乱)。然后在利用handler异步发送消息,当我们的MyView的游戏素材加载完了,就发送消息,将Myview设置为Visiable,将其他的设置为Gone。(在刚开始没有想到思路的时候利用setContentView()2次,发现就是resume()设置的一次生效,主要是我们的界面显示是在Onresume()方法执行完后,因此前面我们设置布局文件只是加载进资源初始化一些数据)。

3、surfacview占用系统资源比较大,当应用失去屏幕焦点的时候,如:按下home键,电源键、back键时候就会回收,且surfaceView的显示主要是通过surfacHolder来锁定和绘画画布来控制的,而为了更好的控制surfacview的画面通常添加一个回调方法来处理事情:addCallback(new CallBack()),而实现callBack得实现它的三个方法:

 class MyCallBack implements SurfaceHolder.Callback
   {
       @Override
       public void surfaceCreated(SurfaceHolder holder) {
                         }

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

       @Override
       public void surfaceDestroyed(SurfaceHolder holder) {
               }
   }

  为了让我们的游戏在后台运行后重新进入时能够继续,就得了解我们按下home、电源键后的生命周期:(只要不重新执行view的构造函数我们的游戏就可以继续玩,前提是我们的绘画线程中的数据不能乱

程序第一次启动时,调用view的构造函数->surfaceCreated->surfaceChanged

按下home键时:执行surfaceDestroyed;点击图标返回程序时,调用surfaceCreated->surfaceChanged

  解决办法:发现surfacview并不会重新执行构造函数,因此只要我们的绘图线程重新启动,且之前的游戏数据不乱就可以继续玩了: (后面的解决办法都是基于满足home键解决方案上)  

    (1)将线程设为view的成员

    (2)在surfaceCreated中把线程new出来,并设置运行标志true、调用线程的start(不要在构造函数中new)

    (3)在surfaceDestroyed中将运行标志设为false

按返回键时,调用surfaceDestroyed;点击图标返回程序时,调用view的构造函数->调用surfaceCreated->surfaceChanged

   解决办法:back键默认是退出游戏,若想按下back键后台运行就得覆写OnBackPressed() 方法里写moveTaskToBack()。

  效果:surfaceDestroyed ;点击图标进入时候:surfaceCreated->surfaceChanged

按下电源键锁频时:surfaceDestroyed,解锁进入游戏时:surfaceCreated->surfaceChanged

  解决办法:1、为了锁屏时,不重新初始化surfacview,我们可以在清单文件activity里添加:android:configChanges="orientation|keyboardHidden|screenSize" ,因为锁屏引起的也是screenSize的变化导致,添加后就是屏幕的变化不影响游戏。

  效果:按电源键时 surfaceChanged,点击进入时:surfaceChanged

 

 Node: 1、有时候我们玩游戏的时候,想要休息一会就暂停了,等几分钟玩的时候会发现屏幕黑了,因此我们可以在activity里用 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 让屏幕长亮)

     2、 为了在绘图的时候后台运行等不相互影响,在构造函数的时候需要init()游戏里的所有素材。

class MyCallBack implements SurfaceHolder.Callback
   {
       @Override
       public void surfaceCreated(SurfaceHolder holder) {
           isRunning = true;
           drawThread = new Thread(new MyRunnable());
           drawThread.start();
           log("surfaceCreated");
       }

       @Override
       public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
           log("surfaceChanged");
       }

       @Override
       public void surfaceDestroyed(SurfaceHolder holder) {
           isRunning = false;
           log("surfaceDestroyed");
       }
   }

4、画图

画图的时候我们先锁住画布,然后绘图,绘图完了就解除锁定并传递显示:这里是一个线程画图对一个surfacview绘图,若涉及多线程最好是在锁定屏幕到绘图完成解锁 实行同步.

class MyRunnable implements  Runnable
    {
        @Override
        public void run() {
            paint = new Paint();
            paint.setColor(Color.RED);
            while(isRunning)
            {
            canvas = surfaceHolder.lockCanvas();
                if(canvas!= null)
                {
                    canvas.drawColor(Color.WHITE);//设置背景
                    drawTanks(canvas, tanks, paint);
                    checkState(myTank , tanks);
                    canvas.drawBitmap(directionBt , 0 ,directionBtCenter.y -r ,paint);
                    canvas.drawBitmap(directionCenterBt , directionCenterBtCenter.x - r3 ,directionCenterBtCenter.y -r3 ,paint);
                    canvas.drawBitmap(boomBt , boomCenter.x -r2,boomCenter.y - r2,paint);
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }

            }
            Log.d( Logcat , "线程运行结束");
        }
    }

 

 

 

 

 

转载于:https://www.cnblogs.com/bokeofzp/p/6699281.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值