• 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 , "线程运行结束");
            }
        }

  • 相关阅读:
    【Django】django 处理request流程细节(转)
    【Django】request 处理流程(转)
    【Django】中间件
    【HTML】DocType
    【CSS】伪类与伪元素
    【nodejs】nodejs 的linux安装(转)
    【chrome】 chrome 开发者工具
    【samba】samba 用户权限配置(转)
    form表单组件
    自定义分页器
  • 原文地址:https://www.cnblogs.com/bokeofzp/p/6699281.html
Copyright © 2020-2023  润新知