1. 程式人生 > >在android view中寫坦克大戰

在android view中寫坦克大戰

我是把以前寫在java裡的程式碼直接移植到android上了(後面貼的程式碼有比較的部分)
只改了畫筆的物件,和控制方式
程式碼大致思路

1.畫

我們要畫出坦克,炮彈,爆炸效果

1.1畫坦克

1.1.1畫豎直的坦克

以坦克左上為基本座標x,y 然後畫出坦克的模型(履帶,車身,炮管等)

1.1.2畫水平的坦克

以坦克左上為基本座標x,y 然後畫出坦克的模型(履帶,車身,炮管等)

1.2畫炮彈

炮彈要從炮管口出發沿炮口朝向發射

1.2畫爆炸效果

當判定坦克死亡時畫出坦克爆炸效果.座標起點要求:起碼覆蓋坦克但也不要太大

2.邏輯判斷

我們要判斷坦克是否被炮彈擊中,坦克觸碰問題,坦克血量是否為0

2.1判斷坦克是否被炮彈擊中

2.1.1判敵方豎直的坦克是否被炮彈擊中

炮彈本身的大小也要考慮進去,然後被擊中的話血量減1如果減完血量為0則死亡

2.1.2判敵方斷水平的坦克是否被炮彈擊中

炮彈本身的大小也要考慮進去,然後被擊中的話血量減1如果減完血量為0則死亡

2.1.3判斷我方豎直的坦克是否被炮彈擊中

炮彈本身的大小也要考慮進去,然後被擊中的話血量減1如果減完血量為0則死亡(判斷方式跟敵方坦克不一樣因為敵方坦克子彈和我方坦克子彈判斷方式不一樣)

2.1.4判斷我方水平的坦克是否被炮彈擊中

炮彈本身的大小也要考慮進去,然後被擊中的話血量減1如果減完血量為0則死亡(判斷方式跟敵方坦克不一樣因為敵方坦克子彈和我方坦克子彈判斷方式不一樣)

2.2坦克觸碰問題

2.2.1坦克觸碰螢幕邊緣

    要考慮坦克不能衝出邊緣

2.2.2敵人坦克相互觸碰

    要考慮敵人坦克不能相互穿過身體(2次迴圈判斷就是每一輛敵人坦克與剩餘坦克依次判斷是否下一次前進會觸碰到,觸碰到則回頭)

2.2.3我放坦克與地方坦克觸碰

    我方坦克觸碰到敵方坦克則血量下降(一次迴圈判斷)

2.3判斷坦克是否血量為0

    血量為0 設定坦克死亡

3.下面是具體實現的程式碼

3.1模型

3.1.1BaseTank

public class BaseTank
{
    int boundX ;                                 //
螢幕寬度 int boundY; //螢幕高度 private int size = 1; //坦克放大倍數 private int x = 0; //坦克x座標 private int y = 0; //坦克y座標 private int hp = 0; //坦克血量 private int speed = 0; //坦克速度 private boolean isLive = true; //是否活著 private boolean isVertical = true; //豎直狀態 private boolean isRight = false; //朝右炮管 private boolean isUp = true; //朝上炮管 private Vector<Shell> tankShells = null ; //炮彈組 private Vector<Thread> tankThreads = null; //炮彈執行緒物件組 private Vector<ComputerTank> toucheds = null; //傳入敵人坦克組 用來判斷是否與敵人坦克觸碰 嗎(包括敵人坦克判斷是否與敵人坦克觸碰) public void setLive(boolean live) { isLive = live; } public void setVertical(boolean vertical) { isVertical = vertical; } public void setRight(boolean right) { isRight = right; } public void setUp(boolean up) { isUp = up; } public Vector<Shell> getTankShells() { return tankShells; } public void setTankShells(Vector<Shell> tankShells) { this.tankShells = tankShells; } public Vector<Thread> getTankThreads() { return tankThreads; } public void setTankThreads(Vector<Thread> tankThreads) { this.tankThreads = tankThreads; } public Vector<ComputerTank> getToucheds() { return toucheds; } public void setToucheds(Vector<ComputerTank> toucheds) { this.toucheds = toucheds; } public BaseTank(int x, int y, int hp, int speed, boolean isVertical, boolean isRight, boolean isUp, Vector<ComputerTank> toucheds,int boundX,int boundY ,int size) { super(); this.x = x; this.y = y; this.hp = hp; this.speed = speed*size; this.isVertical = isVertical; this.isRight = isRight; this.isUp = isUp; this.toucheds = toucheds; this.boundX = boundX; this.boundY = boundY; this.size = size; } public BaseTank(){ } //扣血 public void buckleBlood() { if(hp>1) { hp--; } else { isLive = false; } } public boolean isLive() { return isLive; } public void setIsLive(boolean isLive) { this.isLive = isLive; } public boolean isVertical() { return isVertical; } public void setIsVertical(boolean isVertical) { this.isVertical = isVertical; } public boolean isRight() { return isRight; } public void setIsRight(boolean isRight) { this.isRight = isRight; } public boolean isUp() { return isUp; } public void setIsUp(boolean isUp) { this.isUp = isUp; } public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public int getHp() { return hp; } public void setHp(int hp) { this.hp = hp; } // 向右走 public void goRight() { if(x<boundX-36*size) { x+=speed; isVertical = false ; isRight = true; } } // 向左走 public void goLeft() { if(x>speed) { x-=speed; isVertical = false ; isRight = false; } } // 向下走 public void goDown() { if(y<boundY-36*size) { y+=speed; isVertical = true; isUp = false ; } } // 向上走 public void goUp() { if(y>speed) { y-=speed; isVertical = true; isUp = true ; } } //判斷坦克頭是否與其他坦克觸碰 public boolean judgeTankTouch() { if(toucheds != null &&isLive ) { for(int i = 0;i<toucheds.size();i++) { BaseTank touched = toucheds.get(i); if(touched != this) { int xOne,yOne,xTwo,yTwo,edx,edy; //取A坦克頭的2個點 只要這兩個點都不在被B觸碰坦克裡 那麼就知道A坦克沒有被碰到B edx = touched.getX(); edy = touched.getY(); if(isVertical) { if(this.isUp()) { xOne = x; yOne = y; xTwo = x+34*size; yTwo = y; } else { xOne = x; yOne = y+36*size; xTwo = x+34*size; yTwo = y+36*size; } } else { if(isRight) { xOne = x+36*size; yOne = y; xTwo = x+36*size; yTwo = y+34*size; } else { xOne = x; yOne = y; xTwo = x; yTwo = y+34*size; } } if(touched.isVertical()) { //取A坦克頭的2個點 只要這兩個點都不在被B觸碰坦克裡 那麼就知道A坦克沒有被碰到B if( (xOne>=edx&&xOne<=edx+34*size&&yOne>=edy&&yOne<=edy+36*size) || (xTwo>=edx&&xTwo<=edx+34*size&&yTwo>=edy&&yTwo<=edy+36*size) ) { return true; } } else { //取A坦克頭的2個點 只要這兩個點都不在被B觸碰坦克裡 那麼就知道A坦克沒有被碰到B if( (xOne>=edx&&xOne<=edx+36*size&&yOne>=edy&&yOne<=edy+34*size) || (xTwo>=edx&&xTwo<=edx+34*size&&yTwo>=edy&&yTwo<=edy+36*size) ) { return true; } } } } } return false; //若沒有觸碰則輸出false } //發射炮彈 public void shutShell() { if(tankShells == null) { tankShells = new Vector<Shell>(); tankThreads = new Vector<Thread>(); //是炮彈物件與炮彈執行緒物件同步 } if(isVertical) { if(isUp) { tankShells.add(new Shell(x+15*size, y-18*size,15*size, true,1*size,isVertical,isRight,isUp,boundX,boundY,size)); //朝上炮管 } else { tankShells.add(new Shell(x+15*size, y+18*size,15*size, true,1*size,isVertical,isRight,isUp,boundX,boundY,size)); //朝下炮管 } } else { if(isRight) { tankShells.add(new Shell(x+52*size, y+16*size,15*size,true,1, isVertical,isRight,isUp,boundX,boundY,size)); }//朝右炮管 else { tankShells.add(new Shell(x-18*size, y+16*size,15*size,true,1, isVertical,isRight,isUp,boundX,boundY,size)); //朝左炮管 } } //建立炮彈 Thread sheelThread = new Thread(tankShells.get(tankShells.size()-1)); tankThreads.add(sheelThread); sheelThread.start(); } }

3.1.2ComputerTank


public class ComputerTank extends BaseTank implements Runnable
{
    int type = 0;               //坦克型別
    int stay = 100;             //坦克持續一個動作至少走100個畫素
    int any = 0;                //隨機數

    public ComputerTank(int x, int y, int type, Vector<ComputerTank> toucheds,int boundX,int boundY ,int size)
    {
        super(x, y, type, 1,true,false,false,toucheds,boundX,boundY,size);
        this.type = type;
    }

    public int getType()
    {
        return type;
    }

    public void setType(int type)
    {
        this.type = type;
    }



    //讓電腦隨機自動跑,每個動作持續stay個畫素
    public void run()
    {
        while(true)
        {
            if(super.isLive() == false)
            {
                break;
            }
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if(stay<=0)
            {
                any = (int)(Math.random()*10%4);
                stay = 60;
            }
            else if(super.getX()>super.boundX)                             //設定邊界x(也就是右邊界) 680
            {
                any = 1;
            }
            else if(super.getX() <= super.getSpeed())                           //設定x左邊界  0
            {
                any = 0;
            }
            else if(super.getY()>super.boundY)                           //設定Y的邊界  (也就是下邊界)490
            {
                any = 2;
            }
            else if(super.getY() <= super.getSpeed())                          //設定Y上邊界 0
            {
                any = 3;
            }
            if(any == 0)
            {
                goRight();                      //向右跑若觸碰到坦克 則往反方向跑
                if(judgeTankTouch())            //下面也一樣
                {                               //遇到問題先相信自己邏輯沒問題,下去看看是否是低階錯誤
                    goLeft();                   //在去判斷是否是邏輯問題經驗當邏輯沒有問題  日了狗了白浪費30分鐘 錯誤居然是IF後面加了個“;”
                    any = 1;
                }

            }
            else if(any == 1)
            {
                goLeft();
                if(judgeTankTouch())
                {
                    goRight();
                    any = 0;
                }
            }
            else if(any == 2)
            {
                goUp();
                if(judgeTankTouch())
                {
                    goDown();
                    any = 3;
                }
            }
            else if(any == 3)
            {
                goDown();
                if(judgeTankTouch())
                {
                    goUp();
                    any = 2;
                }
            }
            stay --;
            if((int)(Math.random()*100%30) == 1)    //隨機打炮彈
            {
                this.shutShell();
            }

        }

    }

}

3.1.3PlayerTank


public class PlayerTank extends BaseTank
{
    int life = 10;   //命數
    int score = 0;   //分數



    public PlayerTank(int x, int y, int score,Vector<ComputerTank> toucheds,int boundX,int boundY ,int size) {
        super(x, y,4, 7, true, false, true,toucheds,boundX,boundY ,size);
        this.score = score;
    }

    public int getLife()
    {
        return life;
    }

    public void setLife(int life)
    {
        this.life = life;
    }

    public int getScore()
    {
        return score;
    }

    public void setScore(int score)
    {
        this.score = score;
    }


    public void buckleLife()
    {
        this.life --;
    }




}

3.1.4 Shell



public class Shell implements Runnable{

    int x;
    int y;
    int speed;
    boolean isLive;
    int size ;
    boolean vertical ;
    boolean right  ;
    boolean up ;
    int boundX ;
    int boundY;
    int viewSize;
    public Shell(int x, int y, int speed, boolean isLive, int size,
                 boolean isVertical ,boolean isRight , boolean isUp,int boundX,int boundY ,int viewSize)
    {
        this.x = x;
        this.y = y;
        this.speed = speed/3;//
        this.isLive = isLive;
        this.size = size;
        vertical = isVertical;
        right = isRight;
        up = isUp;
        this.boundX = boundX;
        this.boundY = boundY;
        this.viewSize = viewSize;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public boolean isLive() {
        return isLive;
    }

    public void setLive(boolean isLive) {
        this.isLive = isLive;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public void run()
    {

        while(true)
        {
            if(isLive == false||x<0||x>boundX||y<0||y>boundY)      //炮彈判斷是否應該死亡
            {
                isLive = false;
                break;
            }

            if(isLive == false||x<0||x>boundX||y<0||y>boundY)      //炮彈判斷是否應該死亡
            {
                isLive = false;
                break;
            }

            try {
                Thread.sleep(70);
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
            if(vertical)
            {
                if(up)
                    y -= speed*viewSize;                //朝上炮管  放大倍數viewSize
                else
                    y += speed*viewSize;                //朝下炮管
            }
            else
            {
                if(right)
                    x += speed*viewSize;            //朝右炮管
                else
                    x -= speed*viewSize;            //朝左炮管
            }

        }

    }

}

3.1.5 Boom


public class Boom {
    int x;
    int y;
    int time;
    boolean isLive;
    boolean isVertical;
    public Boom(int x, int y,boolean isVertical) {
        super();
        this.x = x;
        this.y = y;
        this.time = 48;
        this.isLive = true;
        this.isVertical = isVertical;
    }

    public boolean isVertical() {
        return isVertical;
    }

    public void setVertical(boolean isVertical) {
        this.isVertical = isVertical;
    }

    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
    public int getTime() {
        return time;
    }
    public void setTime(int time) {
        this.time = time;
    }
    public boolean isLive() {
        return isLive;
    }
    public void setLive(boolean isLive) {
        this.isLive = isLive;
    }


    public void timeGo()
    {
        if(time >0)
            time-=5;
        else isLive = false;
    }


3.2 View

3.2.1 GameView


public  class GameView extends View implements Runnable{

    public static final String TAG = "GameView";



    private final byte  COM_NUMBER = 5;                      //敵人坦克預設最大數量
    private final int    MAJOR_MOVE = 10;
    //定義手勢檢測器例項
    private GestureDetector detector;
    private boolean isFirst = true;
    private int mHeight ;                                    //本view的高度
    private int mWidth ;                                     //本view的寬度

    private int size = 2;                                    //設定物體大小
    private byte nowComNumber;                               //敵人坦克數量

    private Bitmap []pageBooms = null;                       //圖片陣列

    private PlayerTank myTank = null;                        //玩家坦克
    private Vector <ComputerTank>comTanks = null;            //敵人坦克集
    private Vector<Thread> comTankThreads = null;            //敵人坦克執行緒集  (因為考慮到線性所以用了Vector)
    private Vector <Boom>booms = null;                       //爆炸物件集
    private int [] boomBitmapId = {R.mipmap.icon_one,
            R.mipmap.icon_two,R.mipmap.icon_three,
            R.mipmap.icon_four,R.mipmap.icon_five,
            R.mipmap.icon_six,R.mipmap.icon_seven,
            R.mipmap.icon_eight};


    public GameView(Context context, AttributeSet attrs) {
        super(context, attrs);

        //初始化
        nowComNumber = COM_NUMBER;
        //自己的方法,載入影象一專案檔案為根目錄
        pageBooms = new Bitmap[7];
        for(int i =0;i < pageBooms.length;i++)
        {
            pageBooms[i] = BitmapFactory.decodeResource(getResources(), boomBitmapId[i]);
            pageBooms[i] = Bitmap.createScaledBitmap(pageBooms[i], 60*size,80*size, true);

        }
        initGestureDetector(context);
    }


    public GameView(Context context) {
        super(context);


        //初始化
        nowComNumber = COM_NUMBER;
        //自己的方法,載入影象一專案檔案為根目錄
        pageBooms = new Bitmap[7];
        for(int i =0;i < pageBooms.length;i++)
        {
            pageBooms[i] = BitmapFactory.decodeResource(getResources(), boomBitmapId[i]);
            pageBooms[i] = Bitmap.createScaledBitmap(pageBooms[i], 60*size,80*size, true);

        }

        initGestureDetector(context);





    }


    //初始化手指滑動
    private void initGestureDetector(Context context)
    {
        //建立手勢檢測器 手指單下為起點 手指離開為終點

        detector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {

            boolean doRun = false;
            int turn = 0;  // 0 上      1 下         2  左       3  右        -1 停

            Thread thread = new Thread(){
                @Override
                public void run() {
                    super.run();
                    while (true)
                    {
                        try {
                            sleep(80);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        if (!myTank.isLive())
                        {
                            turn = -1;
                        }

                        switch (turn)
                        {
                            case 0:
                                myTank.goUp();
                                break;

                            case 1:
                                myTank.goDown();
                                break;

                            case 2:
                                myTank.goLeft();
                                break;

                            case 3:
                                myTank.goRight();
                                break;


                            default:
                                try {
                                    sleep(30);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                                break;
                        }
                    }
                }
            };
            //在按下被呼叫
            @Override
            public boolean onDown(MotionEvent motionEvent) {
//                turn = -1;
                return false;
            }

            //在按住時被呼叫
            @Override
            public void onShowPress(MotionEvent motionEvent) {

                turn = -1;



            }

            @Override
            public boolean onSingleTapUp(MotionEvent motionEvent) {
                return false;
            }

            //滑動的時候被呼叫
            @Override
            public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
                return false;
            }


            //長按時候被呼叫
            @Override
            public void onLongPress(MotionEvent motionEvent) {

            }

            //在拋擲動作時被呼叫
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                int dx = (int) (e2.getX() - e1.getX()); //計算滑動的距離
                if (Math.abs(dx) > MAJOR_MOVE && Math.abs(velocityX) > Math.abs(velocityY)) { //降噪處理,必須有較大的動作才識別
                    //加入沒有開啟執行緒則開啟執行緒
                    if (!doRun)
                    {
                        thread.start();
                        doRun = true;
                    }

                    if (velocityX > 0) {
//向右邊
                        turn = 3;
                    } else {
//向左邊
                        turn = 2;
                    }
                    return true;
                } else {

                    if (velocityY>0){
//向下邊
                        turn = 1;
                    } else {
//向上邊
                        turn = 0;
                    }
                    return true;
                }
            }
        });
    }

    /**
     * 初始化tank位置 等等屬性
     */
    private void initTank()
    {


        comTanks = new Vector<ComputerTank>();

        comTankThreads = new Vector <Thread>();
        myTank = new PlayerTank(mWidth/2-12*size, mHeight-50*size, 1,comTanks,mWidth,mHeight,size);
        booms =  new Vector <Boom>();
        for(int i = 0;i<nowComNumber;i++)
        {
            ComputerTank comOne= new ComputerTank(mWidth/nowComNumber*i,0,
                    (int)(Math.random()*10/3+1),comTanks,mWidth,mHeight,size);
            comTanks.add(comOne);
            Thread adThread = new Thread(comOne);
            comTankThreads.add(adThread);               //進行同步執行緒同步
            adThread.start();
        }

    }




    @Override
    protected void onDraw(Canvas canvas) {



        //獲取view的高度和寬度
        mHeight = getHeight();
        mWidth = getWidth();


        //未初始化 則初始化
        if (isFirst)
        {
            initTank();
            isFirst = false;

        }


        Paint paint = new Paint();
        ComputerTank comOne = null;
        Shell comShell = null;
        Shell myShell = null;
        Vector<Shell> myShells = myTank.getTankShells();
        if(myShells != null)
        {
            for(int i = 0 ; i<myShells.size();i++)                 //畫我的坦克炮彈
            {
                myShell = myShells.get(i) ;
                paintShell(myShell,myTank,canvas,paint);
            }
        }

        //玩家坦克
        paintTanks(myTank,canvas,paint,true);

        for(int i = 0;i<comTanks.size();i++)
        {


            comOne = comTanks.get(i);
            Vector<Shell> comShells = comOne.getTankShells();
            if(comShells != null)
            {
                for(int j = 0 ; j<comShells.size();j++)                 //畫敵人的坦克炮彈
                {
                    comShell = comShells.get(j) ;
                    paintShell(comShell,comOne,canvas,paint);
                }
            }
    //敵人坦克
            paintTanks(comOne,canvas,paint,false);

        }
        painBoom(booms,canvas,paint);                                                //畫爆炸
    }


    //畫爆炸
    public void painBoom(Vector <Boom>booms,Canvas canvas,Paint paint)
    {
        Boom boom = null;
        if(booms != null)
        {
            for(int i = 0;i<booms.size();i++)
            {
                boom = booms.get(i);

                if(boom != null)
                {
                    if(boom.isVertical())
                    {               //動畫幀數
                        canvas.drawBitmap(pageBooms[boom.getTime()/7],boom.getX(),boom.getY(),paint);
//                        g.drawImage(pageBooms[boom.getTime()/7], boom.getX(),boom.getY(),
//                                51, 54, this);
                    }


                    else
                    {
                        canvas.drawBitmap(pageBooms[boom.getTime()/7],boom.getX(),boom.getY(),paint);
//                        g.drawImage(pageBooms[boom.getTime()/7], boom.getX(),boom.getY(),
//                                54, 51, this);
                    }

                    boom.timeGo();
                    if(boom.isLive() == false)
                    {
                        booms.remove(boom);
                        boom = null;
                    }

                }
            }
        }
    }



    //畫坦克
    public void paintTanks(BaseTank tank,Canvas canvas,Paint paint,boolean isPlayer)
    {


        int x = tank.getX();
        int y = tank.getY();
        int hp = tank.getHp();
        boolean isVertical =tank.isVertical();
        boolean isUp = tank.isUp();
        boolean isRight = tank.isRight();

        boolean isLive = tank.isLive();

        if(isPlayer)
        {
            paint.setColor(Color.BLUE);                      /*g.setColor(Color.yellow);*/
        }
        else {
            switch(hp)
            {
                //不同型別不同顏色    灰1血     白2血    紅3血   黃4血
                case 1 :      paint.setColor(Color.GRAY);      /* g.setColor(Color.red);break;  */
                    break;

                case 2 :      paint.setColor(Color.LTGRAY);    /*g.setColor(Color.cyan);break;  */
                    break;

                case 3 :     paint.setColor(Color.WHITE);      /*g.setColor(Color.white);break; */
                    break;

                case 4 :   paint.setColor(Color.YELLOW);       /*g.setColor(Color.gray);break;  */
                    break;

                default:
                    break;
            }
        }
        if(isLive)
        {
            if(isVertical)
            {
                canvas.drawRect(x, y, x+8*size,y+36*size,paint);
//                g.fill3DRect(x, y, 8,36 ,true);       //左履帶

                canvas.drawRect(x+24*size, y, x+32*size,y+36*size,paint);
//                g.fill3DRect(x+26, y, 8,36 ,true);        //右履帶
                for(int i =0;i < 6;i++)             //履帶條紋
                {
                    canvas.drawRect(x, y+6*i*size, x+7*size, y+6*i*size,paint);
//                    g.drawLine(x, y+6*i, x+7, y+6*i);

                    canvas.drawRect(x, y+6*i*size, x+7*size, y+6*i*size,paint);
//                    g.drawLine(x+26, y+6*i, x+33, y+6*i);
                }

                canvas.drawRect(x+5*size, y+3*size, x+29*size,y+33*size,paint);
//                g.fill3DRect(x+5, y+3, 24,30 ,true);          //車體
                if(isUp)
                {
                    canvas.drawRect(x+14*size, y-18*size, x+18*size,y+17*size,paint);
//                    g.fillRect(x+15, y-18, 4,35 );                //朝上炮管
                }
                else
                {
                    canvas.drawRect(x+14*size, y+18*size, x+18*size,y+53*size,paint);
//                    g.fillRect(x+15, y+18, 4,35 );                //朝下炮管
                }
            }
            else
            {
                canvas.drawRect(x-1*size, y+1*size , x+35*size,y+9*size,paint);
//                g.fill3DRect(x-1, y+1 ,  36 ,8,true);         //上履帶

                canvas.drawRect(x-1*size, y+27*size, x+35*size,y+35*size,paint);
//                g.fill3DRect(x-1, y+27, 36 ,8,true);          //下履帶
                for(int i =0;i < 6;i++)                     //履帶條紋
                {
                    //                  g.drawLine();
                    //                  g.drawLine();
                }

                canvas.drawRect(x+2*size, y+6*size, x+32*size,y+30*size,paint);
//                g.fill3DRect(x+2, y+6,30 , 24,true);          //車體
                if(isRight)
                {
                    canvas.drawRect(x+18*size, y+16*size, x+53*size,y+20*size,paint);
//                    g.fillRect(x+18, y+16, 35,4);             //朝右炮管
                }
                else
                {
                    canvas.drawRect(x-18*size, y+16*size, x+17*size,y+20*size,paint);
//                    g.fillRect(x-18, y+16, 35,4 );                //朝左炮管
                }
            }
            canvas.drawRect(x+7*size, y+8*size, x+27*size,y+28*size,paint);
//            g.fillOval(x+7, y+8, 20, 20);             //蓋子
        }
    }







    //畫炮彈
    public void paintShell(Shell shell,BaseTank tank,Canvas canvas,Paint paint)
    {
        Vector<Shell> shells = tank.getTankShells();

            paint.setColor(Color.YELLOW);
//            g.setColor(Color.yellow);   //玩家子彈和敵人子彈


        if(shell.isLive())
        {
            canvas.drawRect(shell.getX(), shell.getY(),shell.getX()+4*size, shell.getY()+4*size,paint);
//            g.fillRect(shell.getX(), shell.getY(), 4,4 );
        }
        else
        {
            int index = shells.indexOf(shell);

            Thread one = tank.getTankThreads().get(index);
            tank.getTankThreads().remove(one);
            shells.remove(index);          //刪除執行緒物件
            shell = null;
            one = null;
        }


    }




    //判斷敵人的坦克是否玩家被擊中
    public void judgeTankKill(PlayerTank myTank,
                              Vector <ComputerTank> adms)
    {
        ComputerTank comOne = null;
        Shell myShell = null;
        Vector<Shell> shells = myTank.getTankShells();
        int  coX,coY;   //(我方坦克被擊中還未做) 已做
        int myShX,myShY;

        for(int i = 0; i<adms.size();i++)
        {
            comOne = adms.get(i);
            coX = comOne.getX();
            coY = comOne.getY();

            if(shells != null)
            {
                for(int j = 0; j<shells.size();j++)
                {
                    myShell = shells.get(j);
                    if(myShell != null)
                    {
                        myShX = myShell.getX();
                        myShY = myShell.getY();

                        if(myTank.isVertical())        //坦克死亡時是否豎直  size是方大倍數
                        {
                            if(myShX+4*size>coX&&myShX<coX+34*size&&myShY+4*size>coY&&myShY<coY+36*size)
                            {
                                tankHpReduce(comOne,myShell,adms);

                            }
                        }
                        else
                        {
                            if(myShX+4*size>coX&&myShY<coY+34*size&&myShY+4*size>coY&&myShX<coX+36*size)
                            {
                                tankHpReduce(comOne,myShell,adms);
                            }
                        }
                    }
                }
            }
        }
    }


    //作用敵方坦克如果血量減1 如果血量為零則發生爆炸
    private void tankHpReduce(ComputerTank comOne,Shell myShell,Vector <ComputerTank> adms)
    {
        Vector<Shell> shells = myTank.getTankShells();
        comOne.buckleBlood();
        myShell.setLive(false);
        if(!comOne.isLive()) //判斷敵人是否活著
        {
            //產生爆炸
            booms.add(new Boom(comOne.getX()-2*size,
                    comOne.getY()-2*size,comOne.isVertical()));
            //移去敵人坦克
            int index = adms.indexOf(comOne);
            Thread one = comTankThreads.get(index);
            comTankThreads.remove(one);       //移去執行緒敵人坦克物件
            one = null;
            adms.remove(comOne);
            comOne = null;
            //移去我的炮彈
            shells.remove(myShell);
            myShell = null;
            comOne = new ComputerTank(mWidth/2,0,       //產生新的敵人
                    (int)(Math.random()*10/3+1),comTanks,mWidth,mHeight,size) ;
            adms.add(comOne);
            Thread adThread = new Thread(comOne);
            comTankThreads.add(adThread);
            adThread.start();                        //啟動敵人自動走路執行緒

        }
    }

    //判斷玩家的坦克是否被擊中
    public void judgeMyTankKill(PlayerTank myTank,
                                Vector <ComputerTank> adm)
    {

        ComputerTank comOne = null;
        Shell comShell = null;
        int  myX = myTank.getX();
        int  myY = myTank.getY();   //(我方坦克被擊中還未做)
        int comShX,comShY;
        if(myTank.isLive())
        {
            for(int i = 0; i<adm.size();i++)
            {
                comOne = adm.get(i);
                Vector<Shell> shells = comOne.getTankShells();
                if(shells != null)
                {
                    for(int j = 0; j<shells.size();j++)
                    {
                        comShell = shells.get(j);
                        if(comShell != null)
                        {
                            comShX = comShell.getX();
                            comShY = comShell.getY();

                            if(myTank.isVertical())        //坦克死亡時是否豎直
                            {
                                if(comShX+4*size>myX&&comShX<myX+34*size&&comShY+4*size>myY&&comShY<myY+36*size)
                                {
                                    tankHpReduce(comShell,shells);

                                }
                            }
                            else
                            {
                                if(comShX+4*size>myX&&comShY<myY+34*size&&comShY+4*size>myY&&comShX<myX+36*size)
                                {
                                    tankHpReduce(comShell,shells);


                                }
                            }
                        }
                    }
                }
            }
        }
    }






    //作用我方坦克如果血量減1 如果血量為零則發生爆炸
    private void tankHpReduce(Shell comShell,Vector<Shell> shells)
    {
        myTank.buckleBlood();
        comShell.setLive(false);
        //產生爆炸
        booms.add(new Boom(myTank.getX()-20*size,
                myTank.getY()-20*size,myTank.isVertical()));
        //重置玩家坦克,
        myTank.setX(mWidth/2-12*size);
        myTank.setY(mHeight-50*size);

        //移去炮彈
        shells.remove(comShell);
        comShell = null;
    }




    public void judgeMyTankNew()   //判斷遊戲結束是否重新開始
    {
        if(!myTank.isLive())
        {

            //暫時定為重新開始
                myTank = new PlayerTank(mWidth/2-12*size, mHeight-50*size,
                        1,comTanks,mWidth,mHeight,size);

        }
    }







    public void judgeMyTanktouched()   //判斷玩家坦克是否碰到敵人坦克
    {
        if(myTank.judgeTankTouch())
        {
            myTank.buckleBlood();   //產生爆炸等
            booms.add(new Boom(myTank.getX()-2*size,
                    myTank.getY()-2*size,myTank.isVertical()));
            //重置玩家坦克,
            myTank.setX(mWidth/2-12*size);
            myTank.setY(mHeight-50*size);

        }
    }





    //實現重新整理頁面的效果   主要判斷功能都要放在這裡 (是否從新開始,判斷是都擊中)
    @Override
    public void run() {
        int i = 0;
        while(true)
        {
            try {
                Thread.sleep(40);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //第一次初始化 因為一定要經過 測量才能 獲得高度和寬度
            if (!isFirst)
            {
//        //玩家子彈建立

                if (25 == i)
                {
                    if (null != myTank)
                    {
                        myTank.shutShell();
                    }

                    i = 0;
                }else {
                    i++;
                }



                judgeMyTankNew();                                 //當命數用完是否重新開始遊戲
                judgeTankKill(myTank, comTanks);                  //敵人是否擊中
                judgeMyTankKill(myTank, comTanks);                //玩家坦克是都被擊中
                judgeMyTanktouched();                             //玩家坦克是都被敵人坦克觸碰到
            }



            postInvalidate();                                 //重新整理頁面
        }
    }







        @Override
        public boolean onTouchEvent(MotionEvent event) {
            detector.onTouchEvent(event);
            return true;
        }



}

3.3 Demo

3.3.1佈局檔案中定義

    <pers.lijunxue.tankgame.gameview.GameView
        android:id="@+id/game"
        android:background="#000"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

3.3.2activity 中啟動

        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        gameView = (GameView) findViewById(R.id.game);
        OneThread = new Thread(gameView);
        OneThread.start();
    }

3.3.3爆炸圖片自己網上隨便找