Android游戏开发之构建游戏框架View与SurFaceView的区别


1.view

view在api中的结构

java.lang.Object

Android.view.View 

直接子类:

AnalogClock, ImageView, KeyboardView, ProgressBar, SurfaceView, TextVie, ViewGroup, ViewStub   

间接子类:

AbsListView, AbsSeekBar, AbsSpinner, AbsoluteLayout, AdapterView<T extends Adapter>, AppWidgetHostView, AutoCompleteTextView, Button, CheckBox, CheckedTextView, Chronometer, CompoundButton, DatePicker, DialerFilter, DigitalClock,EditView, ExpandableListView, ExtractEditText, FrameLayout, GLSurfaceView, Gallery, GestureOverlayView, GridView, HorizontalScrollView, ImageButton, ImageSwitcher, LinearLayout, ListView, MediaController, MultiAutoCompleteTextView, QuickContactBadge, RadioButton, RadioGroup, RatingBar, RelativeLayout, ScrollView, SeekBar, SlidingDrawer, Spinner, TabHost, TabWidget, TableLayout, TableRow, TextSwitcher, TimePicker, ToggleButton, TwoLineListItem, VideoView, ViewAnimator, ViewFlipper, ViewSwitcher, WebView, ZoomButton, ZoomControls


由此可见View类属于Android开发绘制中的显示老大,任何与绘制有关系的控件都是它的子类。在这篇文章中我主要讲View 与SurFaceView 使用线程刷新屏幕绘制方面的知识。开发中如何去选择使用View还是SurFaceView 。我相信读过我前几篇博客的朋友应该知道我在刷新屏幕的时候使用invalidate()方法来重绘,下面我详细的说明一下Andooid刷新屏幕的几种方法。



第一种: 在onDraw方法最后调用invalidate()方法,它会通知View在重新调用onDraw方法,实现刷新屏幕。 这样写看起来代码非常简洁漂亮,但是它也同时存在一个很大的问题,它和游戏主线程是分开的 它违背了单线程模式,这样操作绘制的话是很不安全的,举个例子 比如程序先进在Activity1中 使用invalidate()方法来重绘, 然后我跳到了Activity2这时候Activity1已经finash()掉 可是Activity1中 的invalidate() 的线程还在程序中,Android的虚拟机不可能主动杀死正在运行中的线程所以这样操作是非常危险的。因为它是在UI线程中被动掉用的所以很不安全。

 
  1. public void onDraw(Canvas canvas){    
  2.         DosomeThing();    
  3.         invalidate();    
  4. }    

第二种:使用postInvalidate();方法来刷新屏幕 ,调用后它会用handler通知UI线程重绘屏幕,我们可以 new  Thread(this).start(); 开启一个游戏的主线程 然后在主线程中通过调用postInvalidate();方法来刷新屏幕。它是在我们自己的线程中调用 通过调用它可以通知UI线程刷新屏幕 。由此可见它是主动调用UI线程的。所以建议使用postInvalidate()方法来刷新屏幕。

  1. @Override  
  2. public void run() {  
  3.     while (mIsRunning) {  
  4.     try {  
  5.         Thread.sleep(100);  
  6.                    postInvalidate();  
  7.     } catch (InterruptedException e) {  
  8.         // TODO Auto-generated catch block   
  9.         e.printStackTrace();  
  10.     }  
  11.     }  
  12. }  

View中用到的双缓冲技术

重绘的原理是 程序根据时间来刷新屏幕 如果有一帧图形还没有完全绘制结束 程序就开始刷新屏幕这样就会造成瞬间屏幕闪烁 画面很不美观,所以双缓冲的技术就诞生了。它存在的目的就是解决屏幕闪烁的问题,下面我说说在自定义View中如何实现双缓冲。

首先我们需要创建一张屏幕大小的缓冲图片,我说一下第三个参数 ARGB 分别代表的是 透明度   红色   绿色     蓝色

Bitmap.Config  ARGB_4444              ARGB  分别占四位  
Bitmap.Config  ARGB_8888              ARGB  分别占八位
Bitmap.Config  RGB_565                没有透明度(A)   R占5位   G 占6位   B占5位    

一般情况下我们使用ARGB_8888 因为它的效果是最好了 当然它也是最占内存的。

 
  1. mBufferBitmap = Bitmap.createBitmap(mScreenWidth,mScreenHeight,Config.ARGB_8888);  

创建一个缓冲的画布,将内容绘制在缓冲区mBufferBitmap中

 
  1. Canvas mCanvas = new Canvas();  
  2. mCanvas.setBitmap(mBufferBitmap);  

最后一次性的把缓冲区mBufferBitmap绘制在屏幕上,怎么样 简单吧 呵呵。

 
  1. @Override  
  2. protected void onDraw(Canvas canvas) {  
  3.     /**这里先把所有须要绘制的资源绘制到mBufferBitmap上**/  
  4.     /**绘制地图**/  
  5.     DrawMap(mCanvas,mPaint,mBitmap);  
  6.     /**绘制动画**/  
  7.     RenderAnimation(mCanvas);  
  8.     /**更新动画**/  
  9.     UpdateAnimation();  
  10.       
  11.       
  12.     if(isBorderCollision) {  
  13.     DrawCollision(mCanvas,"与边界发生碰撞");  
  14.     }  
  15.       
  16.     if(isAcotrCollision) {  
  17.     DrawCollision(mCanvas,"与实体层发生碰撞");  
  18.     }  
  19.     if(isPersonCollision) {  
  20.     DrawCollision(mCanvas,"与NPC发生碰撞");  
  21.     }  
  22.       
  23.     /**最后通过canvas一次性的把mBufferBitmap绘制到屏幕上**/  
  24.     canvas.drawBitmap(mBufferBitmap, 0,0, mPaint);  
  25.     super.onDraw(canvas);  
  26. }  

由此可见view属于被动刷新, 因为我们做的任何刷新的操作实际上都是通知UI线程去刷新。所以在做一些不用频繁去刷新绘制的项目可以使用view来操作

  • 1
  • 2
  • 下一页

相关内容