android遊戲開發的技術實現分析

來源:互聯網
上載者:User

標籤:android開發   android遊戲   thread   surface   布局   

       在android開發中,你可能會有想要開發一個小遊戲的衝動,那麼用android來開發遊戲如何?呢?幸運的是,google提供了一些已經開發好的遊戲執行個體.我們從他的兩個遊戲執行個體入手來探究探究.

      對於輕量級的小遊戲,其遊戲的核心顯示內容,我們可以寫一個自己的view來實現!然後以一定的頻率重新整理這個view,我們調用view的invalidate()來實現.具體的我們來看看一個大家常見的遊戲:Snake(貪吃蛇),下面來分析一些實現這個遊戲的關鍵代碼.

      和其他app一樣,Snake也由一個Activity開始的,同樣的通過setContentView(R.layout.snake_layout);這行代碼來確定顯示內容的布局,這裡有必要看看這個布局檔案的內容(如下):

<merge xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:app="http://schemas.android.com/apk/res/com.example.android.snake">  <com.example.android.snake.BackgroundView    android:id="@+id/background"    android:layout_width="match_parent"    android:layout_height="match_parent"    app:colorSegmentOne="@color/muted_red"    app:colorSegmentTwo="@color/muted_yellow"    app:colorSegmentThree="@color/muted_blue"    app:colorSegmentFour="@color/muted_green"     />  <com.example.android.snake.SnakeView    android:id="@+id/snake"    android:background="@android:color/transparent"    android:layout_width="match_parent"    android:layout_height="match_parent"    app:tileSize="24dp" />  <TextView android:id="@+id/text"  android:layout_width="match_parent"    android:layout_height="match_parent"    android:layout_gravity="center"    android:gravity="center"    android:textColor="@color/text_violet"    android:textSize="24sp"    android:visibility="visible" />  <RelativeLayout android:id="@+id/arrowContainer"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:visibility="gone">    <ImageView android:id="@+id/imageUp"    android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:layout_alignParentTop="true"      android:layout_centerHorizontal="true"      android:padding="20dp"      android:src="@drawable/dpad_up" />    <ImageView android:id="@+id/imageLeft"      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:layout_alignParentLeft="true"      android:layout_centerVertical="true"      android:padding="20dp"      android:src="@drawable/dpad_left" />    <ImageView android:id="@+id/imageRight"      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:layout_alignParentRight="true"      android:layout_centerVertical="true"      android:padding="20dp"      android:src="@drawable/dpad_right" />    <ImageView android:id="@+id/imageDown"      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:layout_alignParentBottom="true"      android:layout_centerHorizontal="true"      android:padding="20dp"      android:src="@drawable/dpad_down" />  </RelativeLayout></merge>
        上面的代碼,我們首先需要注意的是這個布局檔案採用了merge來限定:因為我們的布局是framelayout,所以這裡就採用了merge,因為任何加入activity的view的父groupview都是framelayout.

         這裡我們重點關注的時SnakeView,這個view就是實現這個遊戲的核心.這裡需要注意這一行代碼:app:tileSize="24dp".這是SnakeView自己定義的一個屬性,用於定義貪吃蛇的大小.能夠這樣使用,你需要先在attrs.xml裡面為SnakeView定義這樣的屬性,看看這裡時如何定義的:

  <declare-styleable name="TileView">    <attr name="tileSize" format="dimension" />  </declare-styleable>
          你肯定會奇怪,怎麼是TileView呢? 其實SnakeView是TileView的子類,而TileView是view的子類.

        所以我們重點來看看SnakeView的實現.(貪吃蛇的具體實現就不設計,這裡只是介紹一個遊戲開發的實現核心).其實遊戲的動畫效果就是反覆的調用invalidate來促使view重現繪製,通過重寫View的onDraw(Canvas canvas)來實現.這樣以來,當調用invalidate(),就會觸發view自己回調onDraw(Canvas canvas),而遊戲每一次需要顯示的內容都由onDraw來繪製.

         下面是定時重新整理view的代碼:

    class RefreshHandler extends Handler {        @Override        public void handleMessage(Message msg) {            SnakeView.this.update();            SnakeView.this.invalidate();        }        public void sleep(long delayMillis) {            this.removeMessages(0);            sendMessageDelayed(obtainMessage(0), delayMillis);        }    };

       上面定義的是一個handle,該handle起到一個定時器的作用,每隔delayMillis這麼長的時間,來更新update()需要下次繪製的內容,然後invalidate()來重新整理.

        下面是他的onDraw的實現:

    @Override    public void onDraw(Canvas canvas) {        super.onDraw(canvas);        for (int x = 0; x < mXTileCount; x += 1) {            for (int y = 0; y < mYTileCount; y += 1) {                if (mTileGrid[x][y] > 0) {                    canvas.drawBitmap(mTileArray[mTileGrid[x][y]], mXOffset + x * mTileSize,                            mYOffset + y * mTileSize, mPaint);                }            }        }    }
        通過上面代碼可以知道,其實就繪製了一些圖片,這些圖片按照一定的座標就組成來一條蛇.所以每次只要mTileGrid裡面的資訊準確其繪製出的映像就是準確的.

         對於像貪吃蛇/象棋等這樣的輕量級遊戲我們可以這麼做,不過對於一些格鬥類的遊戲就不太實用了,當要繪製大量的圖片資源/鈴聲資源的時候就滿足不了需要.這個時候我們需要用到一個特殊的view:SurfaceView

           還好,google給我提供了一個執行個體:JetBoy.下面我們來看看如何使用SurfaceView.

           (1)首先,你寫的SurfaceView需要實現這個介面SurfaceHolder.Callback, 其目的是我們需要擷取我們的SurfaceView的狀態變化(建立成功/大小變化/銷毀).如下代碼:

public class JetBoyView extends SurfaceView implements SurfaceHolder.Callback {
          (2)  我們需要得到  SurfaceView的SurfaceHolder,並且使用SurfaceHolder.Callback,你需要在構造方法裡面完成,如下代碼:

    public JetBoyView(Context context, AttributeSet attrs) {        super(context, attrs);        // register our interest in hearing about changes to our surface        SurfaceHolder holder = getHolder();        holder.addCallback(this);

            (3)由於,我們需要繪製大量的內容,所以我們一般需要開啟一個線程來做這些工作.下面來詳細介紹其中緣由: 我們通過上面獲得的SurfaceHolder就可以獲得這個SurfaceView的Canvas,所以只要我們用這個Canvas來繪製我們需要的東西即可,這些工作我們都是在我們定義的線程裡面來完成的,當然這一切都應該在SurfaceView建立完成以後(surfaceCreated(SurfaceHolder arg0) 回調以後)才能完成.下面來看thread裡面的run裡面核心代碼:

        public void run() {            // while running do stuff in this loop...bzzz!            while (mRun) {                Canvas c = null;                .........                try {                    c = mSurfaceHolder.lockCanvas(null);                    // synchronized (mSurfaceHolder) {                    doDraw(c);                    // }                } finally {                    // do this in a finally so that if an exception is thrown                    // during the above, we don't leave the Surface in an                    // inconsistent state                    if (c != null) {                        mSurfaceHolder.unlockCanvasAndPost(c);                    }                }// end finally block            }// end while mrun block        }

           上面代碼通過mSurfaceHolder.lockCanvas(null);來擷取我們SurfaceView的canvas, 然後繪製內容,繪製完成指向這行代碼mSurfaceHolder.unlockCanvasAndPost(c);

          (4)所以我們需要在surfaceCreated的時候開始我們的遊戲:

    public void surfaceCreated(SurfaceHolder arg0) {        // start the thread here so that we don't busy-wait in run()        // waiting for the surface to be created        thread.setRunning(true);        thread.start();    }
          在surfaceDestroyed的時候結束我們的線程:

    public void surfaceDestroyed(SurfaceHolder arg0) {        boolean retry = true;        thread.setRunning(false);        while (retry) {            try {                thread.join();                retry = false;            } catch (InterruptedException e) {            }        }    }

其實都很簡單的大家使用一下就明白的.

         

android遊戲開發的技術實現分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.