Android-貪喫蛇(二)-自定義的view

package com.example.administrator.eatingjj;



import android.app.TimePickerDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TimePicker;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Created by Administrator on 2017/7/22.
 */


public class Eating extends View {

    private static final int UP = 2;      //蛇頭移動四個方向
    private static final int DOWN = 3;
    private static final int LEFT = 1;
    private static final int RIGHT = 0;

    private int x1 = 0, y1 = 0, x2 = 0, y2 = 0;    //在touch事件中用來記錄按下點和擡起點的座標
    private int MoveLength = 100;      //當移動的的距離超過100時,滑屏轉彎纔有效
    private int time = 300;       //handle事件的週期,也可理解爲蛇移動的速度

    private int panWidth;     //遊戲區域寬
    private int panHidth;       //遊戲區域高
    private float panLineHeight;   //格子高
    private float panLineWidth;   //格子寬
    private float rare=(3*1.0f/4);   //Bitmap的size與格子的size的比例

    private int MAX_LINE =14;   //橫向格子個數
    private int MAXLONG_LINE=25;  //縱向格子個數

    private List<Point> mSnakeArray = new ArrayList<>();  //蛇身的鏈表

    private Bitmap SnakeHead;
    private Bitmap SnakeBody;
    private Bitmap SnakeBody_rirht;   //蛇身的四個朝向
    private Bitmap SnakeBody_left;
    private Bitmap SnakeBody_up;
    private Bitmap SnakeBody_down;

    private Bitmap Snakefood; //食物的圖像
    private int Director=DOWN;   //蛇頭前進的方向
    private Point food;    //食物的座標


    private boolean mIsGameover;   //判斷遊戲是否結束

    private Paint paint = new Paint();  //畫筆

    private Handler handler = new Handler() {

        public void handleMessage(Message message) {
            Moving();
        }
    };

    //具體實現蛇的移動,更新蛇的鏈表,喫豆子,判斷遊戲是否結束,重繪
    public void SnakeMove() {
        Point snakehead = mSnakeArray.get(mSnakeArray.size() - 1);
        Point next = null;
        int x = snakehead.x;
        int y = snakehead.y;
        switch (Director) {

            case UP: {
                next = new Point(x, (y - 1 + MAXLONG_LINE) % MAXLONG_LINE);
                break;
            }
            case DOWN: {
                next = new Point(x, (y + 1) % MAXLONG_LINE);
                break;
            }
            case RIGHT: {
                next = new Point((x + 1) % MAX_LINE, y);
                break;
            }
            case LEFT: {
                next = new Point((x - 1 + MAX_LINE) % MAX_LINE, y);
                break;
            }
        }

        if (mSnakeArray.contains(next)) {
            mIsGameover=true;
        }
        mSnakeArray.add(next);
        mSnakeArray.remove(0);
        if (mSnakeArray.contains(food)) {
            mSnakeArray.add(0,food);
            creatfood();
            if(time>50)   time-=5;   //每喫一個豆子,速度提升
        }
        invalidate();
    }

    //handle週期調用的函數,用來實現蛇的自動移動,以及檢測遊戲是否結束
    private void Moving() {
        SnakeMove();
       if(mIsGameover)
       {
           GameOver();
       }
       else
       {
           handler.sendEmptyMessageDelayed(1, time);
       }
    }

    //遊戲結束時產生的對話框,退出遊戲或再來一局
    private void GameOver()
    {
        AlertDialog.Builder builder=new AlertDialog.Builder(this.getContext());

        builder.setTitle("GAME OVER");
        builder.setMessage("你的長度爲 "+mSnakeArray.size()+" !  是否重新開局?");
        builder.setNegativeButton("是的", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                GameAgain();
            }
        });
        builder.setPositiveButton("退出遊戲", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                System.exit(0);
            }
        });
        AlertDialog modalDialog=builder.create();
        modalDialog.show();
    }


    //初始化畫筆
    public Eating(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setBackgroundColor(0x22000000);
        init();
        handler.sendEmptyMessageDelayed(1, time);
    }

    //自定義畫筆,初始化蛇的位置
    private void init() {
        paint.setColor(0x40000000);  //灰
        paint.setAntiAlias(true); //抗鋸齒
        paint.setDither(true);   //防抖動
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(2);

        mSnakeArray.clear();
        mSnakeArray.add(new Point(MAX_LINE-2, 1));
        mSnakeArray.add(new Point(MAX_LINE-2, 2));
        mSnakeArray.add(new Point(MAX_LINE-2, 3));

        SnakeBody_rirht = BitmapFactory.decodeResource(getResources(), R.drawable.shi1);
        SnakeBody_down = BitmapFactory.decodeResource(getResources(), R.drawable.shi2);
        SnakeBody_up = BitmapFactory.decodeResource(getResources(), R.drawable.shi3);
        SnakeBody_left = BitmapFactory.decodeResource(getResources(), R.drawable.shi4);
        SnakeBody = SnakeBody_down;
        SnakeHead = SnakeBody_down;
        Snakefood = BitmapFactory.decodeResource(getResources(), R.drawable.food);
    }

    //設置自定義控件的高度和寬度,這裏設置爲全屏
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        setMeasuredDimension(widthSize,heightSize);

    }


    //設置棋盤的寬度和格子寬度,以及Bitmap的size
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        panWidth = w;
        panHidth = h;
        panLineWidth = (panWidth * 1.0f) / MAX_LINE;
        panLineHeight=(panHidth*1.0f)/MAXLONG_LINE;
        creatfood();   //遊戲開始時,出現第一個食物

        SnakeBody = Bitmap.createScaledBitmap(SnakeBody, (int)(panLineWidth*rare*1.0f), (int)(panLineHeight*rare*1.0f), false);
        SnakeBody_left = Bitmap.createScaledBitmap(SnakeBody_left, (int)(panLineWidth*rare*1.0f), (int)(panLineHeight*rare*1.0f),false);
        SnakeBody_rirht = Bitmap.createScaledBitmap(SnakeBody_rirht,(int)(panLineWidth*rare*1.0f), (int)(panLineHeight*rare*1.0f),false);
        SnakeBody_up = Bitmap.createScaledBitmap(SnakeBody_up,(int)(panLineWidth*rare*1.0f), (int)(panLineHeight*rare*1.0f),false);
        SnakeBody_down = Bitmap.createScaledBitmap(SnakeBody_down,(int)(panLineWidth*rare*1.0f), (int)(panLineHeight*rare*1.0f),false);
        SnakeHead = Bitmap.createScaledBitmap(SnakeHead,(int)(panLineWidth), (int)(panLineHeight),false);
        Snakefood = Bitmap.createScaledBitmap(Snakefood,(int)(panLineWidth*rare*1.0f), (int)(panLineHeight*rare*1.0f),false);
    }

    //touch事件,通過滑動實現上下左右轉彎
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mIsGameover) return false;
        int action = event.getAction();
        if (action == MotionEvent.ACTION_DOWN) {
            x1 = (int) event.getX();
            y1 = (int) event.getY();
        } else if (action == MotionEvent.ACTION_UP) {
            x2 = (int) event.getX();
            y2 = (int) event.getY();

            if (Director == RIGHT || Director == LEFT) {
                if (y2 - y1 >= MoveLength) {
                    Director = DOWN;
                    SnakeHead = SnakeBody_down;
                    SnakeHead = Bitmap.createScaledBitmap(SnakeHead,(int)(panLineWidth), (int)(panLineHeight),false);
                    SnakeMove();
                } else if (y1 - y2 >= MoveLength) {
                    Director = UP;
                    SnakeHead = SnakeBody_up;
                    SnakeHead = Bitmap.createScaledBitmap(SnakeHead,(int)(panLineWidth), (int)(panLineHeight),false);
                    SnakeMove();
                }
            } else if (Director == UP || Director == DOWN) {
                if (x2 - x1 >= MoveLength) {
                    Director = RIGHT;
                    SnakeHead = SnakeBody_rirht;
                    SnakeHead = Bitmap.createScaledBitmap(SnakeHead,(int)(panLineWidth), (int)(panLineHeight),false);
                    SnakeMove();
                } else if (x1 - x2 >= MoveLength) {
                    Director = LEFT;
                    SnakeHead = SnakeBody_left;
                    SnakeHead = Bitmap.createScaledBitmap(SnakeHead,(int)(panLineWidth), (int)(panLineHeight),false);
                    SnakeMove();
                }
            }
            invalidate();
        }
        return true;
    }

    //繪圖
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //drawBoard(canvas);
        drawSnake(canvas);
    }

    //重新開局
    public   void  GameAgain()
    {
        mIsGameover=false;
        mSnakeArray.clear();
        mSnakeArray.add(new Point(MAX_LINE-2, 1));
        mSnakeArray.add(new Point(MAX_LINE-2, 2));
        mSnakeArray.add(new Point(MAX_LINE-2, 3));
        Director=DOWN;
        time=300;
        SnakeHead=SnakeBody_down;
        SnakeHead = Bitmap.createScaledBitmap(SnakeHead,(int)(panLineWidth), (int)(panLineHeight),false);
        handler.sendEmptyMessageDelayed(1, time);
        invalidate();
        Toast.makeText(getContext(),"重新開局",Toast.LENGTH_SHORT).show();
    }


    //設計遊戲初期時用到
    private void drawBoard(Canvas canvas)
    {
        int w=panWidth;
        int h=panHidth;
        float lineheight=panLineHeight;
        float linewidth=panLineWidth;
        for(int i=0;i<MAXLONG_LINE;i++)
        {
            int startx = 0;
            int endx=w;
            int y=(int)(i*lineheight);
            canvas.drawLine(startx,y,endx,y,paint);
        }
        for(int i=0;i<MAXLONG_LINE;i++)
        {
            int starty = 0;
            int endy=h;
            int y=(int)(i*linewidth);
            canvas.drawLine(y,starty,y,endy,paint);
        }
    }


    //畫食物,畫蛇身,畫蛇頭
    private void drawSnake(Canvas canvas)
    {
        canvas.drawBitmap(Snakefood,food.x*panLineWidth+(1-rare)/2*panLineWidth,food.y*panLineHeight+(1-rare)/2*panLineWidth,null);
        for(int i=0,n=mSnakeArray.size();i<n-1;i++)
        {
            Point snakepoint=mSnakeArray.get(i);
            Point next=mSnakeArray.get(i+1);
            if(snakepoint.x==next.x)
            {
                if((snakepoint.y+1)%MAXLONG_LINE==next.y) SnakeBody=SnakeBody_down;
                else SnakeBody=SnakeBody_up;
            }
            else if(snakepoint.y==next.y)
            {
                if((snakepoint.x+1)%MAX_LINE==next.x) SnakeBody=SnakeBody_rirht;
                else SnakeBody=SnakeBody_left;
            }
            canvas.drawBitmap(SnakeBody,snakepoint.x*panLineWidth+(1-rare)/2*panLineWidth,snakepoint.y*panLineHeight+(1-rare)/2*panLineHeight,null);
        }
        Point snakepoint=mSnakeArray.get(mSnakeArray.size()-1);
        canvas.drawBitmap(SnakeHead,snakepoint.x*panLineWidth,snakepoint.y*panLineHeight,null);
    }


    //隨機產生一個食物,且食物不能出現在蛇的身上
    private void creatfood()
    {
        food=new Point(new Random().nextInt(MAX_LINE),new Random().nextInt(MAXLONG_LINE));
        while (mSnakeArray.contains(food))
        {
            food=new Point(new Random().nextInt(MAX_LINE),new Random().nextInt(MAXLONG_LINE));
        }
    }

}


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