官术网_书友最值得收藏!

3.5 游戲框架

大多數(shù)知名企業(yè)的游戲都是基于Apache Struts、Spring和Hibernate等開發(fā)框架的。這些框架都是基于MVC設計模式的,實現(xiàn)了業(yè)務和邏輯的分離,這已經(jīng)成為當前游戲開發(fā)的主流模式。本節(jié)將簡單分析Android平臺提供的View和Surfaceview類的基本知識。

3.5.1 View類

View視圖類是Android系統(tǒng)中的一個超類,在此類中幾乎包含了所有的屏幕類型。每一個View都有一個用于繪圖的畫布,這個畫布可以進行任意擴展。在游戲開發(fā)中也可以自定義View視圖,這個畫布的功能更能滿足我們在游戲開發(fā)中的需要。

在Android系統(tǒng)中,任何一個View類都只需重寫onDraw()方法來實現(xiàn)界面顯示,自定義的視圖可以是復雜的3D實現(xiàn),也可以是非常簡單的文本形式。

在游戲中最重要的就是與玩家的交互,例如,鍵盤輸入、觸筆點擊事件如何來處理呢?在Android中提供了onKeyUp、onKeyDown、onKeyMultiple、onKeyPreIme、onTouchEvent和onTrackballEvent等方法,通過這些方法可以輕松處理游戲中的事件信息。在繼承View時需要重載這幾個方法,當有按鍵按下或彈起事件發(fā)生時,按鍵代碼自動會傳輸給這些相應的方法來處理。

游戲的核心功能是不斷繪圖和刷新界面,視圖可以通過onDraw()方法繪制,接下來重點分析如何刷新界面。在Android中提供了invalidate()方法來刷新界面。不能直接在線程中調用方法invalidate(),特別是不能在子線程中調用,因為這違背了Android單線程模型。Android UI操作并不是線程安全的,并且這些操作必須在UI線程中執(zhí)行,因此Android中最常用的方法就是利用Handler來實現(xiàn)UI線程的更新。

接下來通過一個具體實例,介紹在Android中使用View類實現(xiàn)屏幕更新顯示的方法。

實例3-13 使用View類(daima\3\ViewC)。

在本實例中,要在屏幕上繪制了一個不停變換顏色的矩形,并且定義一些事件來通過模擬器的上下鍵調節(jié)矩形的位置(比如把這個矩形向上移動或者把這個矩形向下移動)。本實例的實現(xiàn)文件是ViewC.java,主要代碼如下所示。

public class ViewC extends View
{
  int  miCount = 0;
  int  y = 0;
  public ViewC(Context context)
  {
      super(context);
  }
  //
  //繪圖處理
  public void onDraw(Canvas canvas)
  {
      if (miCount < 100)
      {
          miCount++;
      }
      else
      {
          miCount = 0;
      }
      //繪圖
      Paint mPaint = new Paint();
      switch (miCount%4)
      {
      case 0:
          mPaint.setColor(Color.BLUE);
          break;
      case 1:
          mPaint.setColor(Color.GREEN);
          break;
      case 2:
          mPaint.setColor(Color.RED);
          break;
      case 3:
          mPaint.setColor(Color.YELLOW);
          break;
    default:
      mPaint.setColor(Color.WHITE);
      break;
    }
    //繪制矩形--后面將詳細講解
    canvas.drawRect((320-80)/2, y, (320-80)/2+80, y+40, mPaint);
  }
}

執(zhí)行后將在屏幕內(nèi)繪制一個矩形,并隨著線程的變化矩形的填充顏色隨之變化,從而實現(xiàn)閃爍效果,如圖3-35所示。通過鍵盤上的上下鍵來移動矩形,如圖3-36所示。

圖3-35 閃爍效果

圖3-36 上下移動矩形

3.5.2 SurfaceView類

類SurfaceView在游戲開發(fā)中有著舉足輕重的作用,它對畫面的控制有更大的自由度。SurfaceView類有個雙緩沖機制,在開發(fā)游戲時經(jīng)常用到,提高整個效率。

1. SurfaceView類基礎

在Android中開發(fā)游戲時,一般來說,要想寫一個復雜一點的游戲,必須使用SurfaceView來實現(xiàn)。SurfaceView可直接訪問一個可畫圖的界面,可以控制在界面頂部的子視圖層。SurfaceView是提供給需要直接畫像素而不是使用窗體部件的應用使用的。Android圖形系統(tǒng)中的一個重要的概念和線索是Surface(界面)、View(視圖)及其子類,如TextView和Button。

要想在Surface上繪圖。則必須為每個Surface創(chuàng)建一個Canvas對象(但屬性時常改變),用來管理View在Surface上的繪圖操作,如畫點與畫線。還要注意的是,在使用SurfaceView的時候,一般都是出現(xiàn)在最頂層。

在使用SurfaceView的時候,一般情況下還要對創(chuàng)建、銷毀、改變時的情況進行監(jiān)視,格式如下所示。

//在 surface的大小發(fā)生改變時激發(fā)
public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}
//在創(chuàng)建時激發(fā),一般在這里調用畫圖的線程
public void surfaceCreated(SurfaceHolder holder){}
//銷毀時激發(fā),一般在這里將畫圖的線程停止、釋放
public void surfaceDestroyed(SurfaceHolder holder) {}

surfaceCreated會首先被調用,然后是surfaceChanged,當程序結束時會調用surfaceDestroyed。

由于SurfaceHolder是一個共享資源,所以在對其操作時應該實行“互斥操作”,即需要使用synchronized的“封鎖”機制。

渲染文字的工作實際上是主線程(也就是LunarView類)的父類View的工作,而并不屬于工作線程LunarThread,在工作線程中是無法控制的,所以改為向主線程發(fā)送一個Message來代替,讓主線程通過Handler對接收到的消息進行處理,從而更新界面文字信息。

接下來將通過一個具體的實例,介紹在Android中使用SurfaceView類實現(xiàn)屏幕更新顯示的流程。

實例3-14 使用SurfaceView類實現(xiàn)屏幕內(nèi)容的閃爍顯示(daima\3\SurfaceC)。

本實例的實現(xiàn)文件是SurfaceC.java,具體代碼如下所示。

package com.SurfaceC;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class SurfaceC extends SurfaceView
implements SurfaceHolder.Callback,Runnable
{
  //控制循環(huán)
  boolean mbLoop = false;
  //定義SurfaceHolder對象
  SurfaceHolder   mSurfaceHolder  = null;
  int             miCount         = 0;
  int             y               = 50;
  public SurfaceC(Context context)
  {
      super(context);
      //實例化SurfaceHolder
      mSurfaceHolder = this.getHolder();
      //添加回調
      mSurfaceHolder.addCallback(this);
      this.setFocusable(true);
      mbLoop = true;
  }
  //在surface的大小發(fā)生改變時激發(fā)
  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
  {
  }
  //在surface創(chuàng)建時激發(fā)
  public void surfaceCreated(SurfaceHolder holder)
  {
      //開啟繪圖線程
      new Thread(this).start();
  }
  //在surface銷毀時激發(fā)
  public void surfaceDestroyed(SurfaceHolder holder)
  {
      //停止循環(huán)
      mbLoop = false;
  }
  //繪圖循環(huán)
  public void run()
  {
      while (mbLoop)
  {
    try
    {
        Thread.sleep(200);
    }
    catch (Exception e)
    {
    }
    synchronized( mSurfaceHolder )
    {
        Draw();
    }
  }
}
//繪圖方法
public void Draw()
{
  //鎖定畫布,得到canvas
  Canvas canvas= mSurfaceHolder.lockCanvas();
  if (mSurfaceHolder==null || canvas == null )
  {
    return;
  }
  if (miCount < 100)
  {
    miCount++;
  }
  else
  {
    miCount = 0;
  }
  //繪圖
  Paint mPaint = new Paint();
  mPaint.setAntiAlias(true);
  mPaint.setColor(Color.BLACK);
  //繪制矩形--清屏作用
  canvas.drawRect(0, 0, 320, 480, mPaint);
  switch (miCount % 4)
  {
  case 0:
    mPaint.setColor(Color.BLUE);
    break;
  case 1:
    mPaint.setColor(Color.GREEN);
    break;
  case 2:
    mPaint.setColor(Color.RED);
    break;
  case 3:
    mPaint.setColor(Color.YELLOW);
    break;
  default:
    mPaint.setColor(Color.WHITE);
    break;
  }
    // 繪制矩形--后面將詳細講解
    canvas.drawCircle((320 - 25) / 2, y, 50, mPaint);
    // 繪制后解鎖,繪制后必須解鎖才能顯示
    mSurfaceHolder.unlockCanvasAndPost(canvas);
  }
}

執(zhí)行后將在屏幕內(nèi)繪制一個圓形,并隨著線程的變化,圓形的填充顏色也隨之變化,從而實現(xiàn)閃爍效果,如圖3-37所示;可以通過鍵盤上的上下鍵來移動圓形,如圖3-38所示。

圖3-37 閃爍效果

圖3-38 上下移動圓形

2. 雙緩沖

雙緩沖的是一種防止動畫閃爍的多線程應用,基于SurfaceView的雙緩沖實現(xiàn)很簡單,只需開一條線程并在其中繪圖即可。Android中的SurfaceView類就基于雙緩沖機制,所以在開發(fā)游戲時應盡量使用SurfaceView而不要使用View,這樣效率會較高,而且SurfaceView的功能也更加完善。

雙緩沖的核心是先通過方法setBitmap()將要繪制的所有圖形繪制到一個Bitmap(圖像對象)上,然后調用方法drawBitmap()繪制這個Bitmap,并在屏幕上顯示出來。下面將通過一個具體的實例,講解在Android中使用SurfaceView類實現(xiàn)雙緩沖。

實例3-15 使用雙緩沖技術在屏幕中顯示一幅圖片(daima\3\shuanghuan)。

本實例的實現(xiàn)文件是shuanghuan.java,具體代碼如下所示。

package com.shuanghuan;
import com.shuanghuan.R;
import Android.content.Context;
import Android.graphics.Bitmap;
import Android.graphics.Canvas;
import Android.graphics.Paint;
import Android.graphics.Bitmap.Config;
import Android.graphics.drawable.BitmapDrawable;
import Android.view.KeyEvent;
import Android.view.MotionEvent;
import Android.view.View;
public class shuanghuan extends View implements Runnable
{
  /* 聲明Bitmap對象 */
  Bitmap  mBitQQ  = null;
  Paint   mPaint = null;
  /* 創(chuàng)建一個緩沖區(qū) */
Bitmap  mSCBitmap = null;
/* 創(chuàng)建Canvas對象 */
Canvas mCanvas = null;
public shuanghuan(Context context)
{
    super(context);
    /* 裝載資源 */
    mBitQQ = ((BitmapDrawable) getResources().getDrawable(R.drawable.qq)).getBitmap();
    /* 創(chuàng)建屏幕大小的緩沖區(qū) */
    mSCBitmap=Bitmap.createBitmap(320, 480, Config.ARGB_8888);
    /* 創(chuàng)建Canvas */
    mCanvas = new Canvas();
    /* 設置將內(nèi)容繪制在mSCBitmap上 */
    mCanvas.setBitmap(mSCBitmap);
    mPaint = new Paint();
    /* 將mBitQQ繪制到mSCBitmap上 */
    mCanvas.drawBitmap(mBitQQ, 0, 0, mPaint);
    /* 開啟線程 */
    new Thread(this).start();
}
public void onDraw(Canvas canvas)
{
    super.onDraw(canvas);
    /* 將mSCBitmap顯示到屏幕上 */
    canvas.drawBitmap(mSCBitmap, 0, 0, mPaint);
}
//觸筆事件
public boolean onTouchEvent(MotionEvent event)
{
    return true;
}
//按鍵按下事件
public boolean onKeyDown(int keyCode, KeyEvent event)
{
    return true;
}
//按鍵彈起事件
public boolean onKeyUp(int keyCode, KeyEvent event)
{
    return false;
}
public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)
{
    return true;
}
/*線程處理*/
public void run()
{
    while (!Thread.currentThread().isInterrupted())
    {
        try
        {
            Thread.sleep(100);
        }
      catch (InterruptedException e)
      {
        Thread.currentThread().interrupt();
      }
      //使用postInvalidate可以直接在線程中更新界面
      postInvalidate();
    }
  }
}

執(zhí)行后將用雙緩沖技術在屏幕中顯示圖片,效果如圖3-39所示。

圖3-39 執(zhí)行效果

主站蜘蛛池模板: 西乌珠穆沁旗| 丰镇市| 那坡县| 小金县| 金川县| 石景山区| 闽清县| 灌阳县| 日土县| 安康市| 巨野县| 贵南县| 龙泉市| 桐乡市| 昌图县| 盐山县| 金华市| 三门峡市| 惠来县| 乾安县| 东城区| 泸溪县| 根河市| 长宁县| 青铜峡市| 陈巴尔虎旗| 旅游| 太康县| 中西区| 张家界市| 河北区| 安西县| 从江县| 工布江达县| 偏关县| 陕西省| 吉木萨尔县| 盐源县| 萨迦县| 同江市| 台南市|