Android App 源碼分析(貪喫蛇遊戲)

 

——/android-sdk-windows/samples/android-7/Snake


首屆 Google 暑期大學生博客分享大賽——2010 Andriod 篇


Snake源碼由三部分組成:Snake.java,SnakeView.java,TileView.java

1. Snake.java

Snake.java是整個整個貪喫蛇遊戲的主框架;主要負責程序界面的初始化,遊戲的初始化及負責遊戲暫停或載入遊戲的狀態。

a.界面初始化

setContentView(R.layout.snake_layout);

mSnakeView = (SnakeView) findViewById(R.id.snake);

mSnakeView.setTextView((TextView) findViewById(R.id.text));

/** R.layout.snake_layout 指向的snake_layout.xml是遊戲的UI設定,在FrameLayout中包含了兩個元素:com.example.android.snake.SnakeView(這是個畫布)TextView(用來顯示文字)*/

b.遊戲初始化及載入遊戲狀態

if(savedInstanceState == null) {

            mSnakeView.setMode(SnakeView.READY); // 設置新遊戲

         } else {

            //讀取狀態

            Bundle map = savedInstanceState.getBundle(ICICLE_KEY);

            if (map != null) {

                mSnakeView.restoreState(map); //載入狀態

             } else {

                mSnakeView.setMode(SnakeView.PAUSE); //暫停

             }

      }

}

2. TiltView.java

TiltView的基類是View,包含了貪喫蛇遊戲畫面的各個設定參數,主要負責繪製遊戲畫面。

    protected static int mTileSize;//方格的邊長

    protected static int mXTileCount;//X軸上方格的個數

    protected static int mYTileCount;//Y軸上方格的個數

    private static int mXOffset;//繪圖時X軸上的起始座標

 private static int mYOffset;//繪圖時Y軸上的起始座標

private Bitmap[] mTileArray;//位圖數組

private int[][] mTileGrid;//映射整個遊戲畫面的數組

private final Paint mPaint = new Paint();//畫筆

mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);//設置方格的相對大小

public void resetTiles(int tilecount)//重置位圖數組的長度

protected void onSizeChanged(int w, int h, int oldw, int oldh)//適應各種分辨率的屏幕

public void loadTile(int key, Drawable tile)//導入位圖

public void clearTiles()//擦除遊戲畫面

public void setTile(int tileindex, int x, int y)//設置遊戲畫面:tileindex取值爲01230:空白;1:redstar.png;2:yellowstar.png;3:greenstar.png.

public void onDraw(Canvas canvas)//根據mTileGrid數組繪製遊戲畫面

    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);

                   /**自己改的代碼,將不同的位圖替換爲相應顏色的圓形*/

                 switch(mTileGrid[x][y]){               

                 case 1:mPaint.setColor(Color.RED);break;

                 case 2:mPaint.setColor(Color.YELLOW);break;

                 case 3:mPaint.setColor(Color.GREEN);                

                 }

                    canvas.drawCircle(mXOffset + x * mTileSize + mTileSize/2, mYOffset + y * mTileSize + mTileSize/2,

mTileSize/2, mPaint);

                }

            }

         }

 }

不同的界面

3. SnakeView.java

SnakeView的基類是TileView,是整個貪喫蛇遊戲的核心,包含了遊戲的算法及相應的數據。

    貪喫蛇移動的算法很簡單,使用一個隊列保存貪喫蛇身體的每一個節點的座標,移動時只需要根據移動的方向在隊列的頭部加入一個新的節點,同時刪除尾部的節點。

    private void updateSnake() {

        boolean growSnake = false;

        Coordinate head = mSnakeTrail.get(0);

        Coordinate newHead = new Coordinate(1, 1);

        mDirection = mNextDirection;

        switch (mDirection) {

        case EAST: {

            newHead = new Coordinate(head.x + 1, head.y);

            break;

        }

        case WEST: {

            newHead = new Coordinate(head.x - 1, head.y);

            break;

        }

        case NORTH: {

            newHead = new Coordinate(head.x, head.y - 1);

            break;

        }

        case SOUTH: {

            newHead = new Coordinate(head.x, head.y + 1);

            break;

        }

        }//構造新頭

        if ((newHead.x < 1) || (newHead.y < 1) || (newHead.x > mXTileCount - 2) || (newHead.y > mYTileCount - 2)) {

            setMode(LOSE);

            return;

        }//撞牆了

        int snakelength = mSnakeTrail.size();

        for (int snakeindex = 0; snakeindex < snakelength; snakeindex++) {

            Coordinate c = mSnakeTrail.get(snakeindex);

            if (c.equals(newHead)) {

                setMode(LOSE);

                return;

            }

        }//撞到自己了

        int applecount = mAppleList.size();

        for (int appleindex = 0; appleindex < applecount; appleindex++) {

            Coordinate c = mAppleList.get(appleindex);

            if (c.equals(newHead)) {//撞蘋果了

                mAppleList.remove(c);

                addRandomApple();

                

                mScore++;

                mMoveDelay *= 0.9;

                growSnake = true;

            }

        }

        mSnakeTrail.add(0, newHead);//加頭

        if (!growSnake) {

            mSnakeTrail.remove(mSnakeTrail.size() - 1);//去尾

        }

        int index = 0;

        for (Coordinate c : mSnakeTrail) {

            if (index == 0) {

                setTile(YELLOW_STAR, c.x, c.y);

            } else {

                setTile(RED_STAR, c.x, c.y);

            }

            index++;

        }//標記頭部

    }

    隨機生成蘋果的算法:隨機生成蘋果依賴隨機函數Random();算法流程是先隨機生成一個在(1,1)~(mXtileCount,mYtileCount)範圍之內的座標,然後讀取保存有貪喫蛇身體節點座標的隊列,以保證生成的座標不在蛇的身體上。

    private void addRandomApple() {

        Coordinate newCoord = null;

        boolean found = false;

        while (!found) {

            int newX = 1 + RNG.nextInt(mXTileCount - 2);

            int newY = 1 + RNG.nextInt(mYTileCount - 2);

            newCoord = new Coordinate(newX, newY);//隨機生成的座標

            boolean collision = false;

            int snakelength = mSnakeTrail.size();

            for (int index = 0; index < snakelength; index++) {

                if (mSnakeTrail.get(index).equals(newCoord)) {

                    collision = true;//座標在蛇的身上,!found爲真,重新生成座標

                }

            }

            found = !collision;

        }

        if (newCoord == null) {

            Log.e(TAG"Somehow ended up with a null newCoord!");

        }

        mAppleList.add(newCoord);

    }

    處理按鍵事件:這一部分主要分爲兩個小部分;第一部分是處理遊戲的開始及重新開始的按鍵事件;第二部分是處理在遊戲過程中的按鍵事件。第二部分主要是通過前一移動方向(mDirection)和按鍵方向(KeyEvent),推出下一個移動方向(mNextDirection),主要是過濾掉和mDirection相反的方向。

    定時刷新遊戲畫面:定時刷新遊戲畫面通過android.os.handler類實現;

    class RefreshHandler extends Handler {

        @Override

        /**收到消息就執行的動作*/

        public void handleMessage(Message msg) {

            SnakeView.this.update();//計算一幀畫面

            SnakeView.this.invalidate();//更新畫面;調用Draw()

        }

        /**定時發消息*/

        public void sleep(long delayMillis) {

            this.removeMessages(0);

            sendMessageDelayed(obtainMessage(0), delayMillis);

        }

     };

4. View Hiersrchy

  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章