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 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;iint startx = 0;
            int endx=w;
            int y=(int)(i*lineheight);
            canvas.drawLine(startx,y,endx,y,paint);
        }
        for(int i=0;iint 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();i1;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));
        }
    }

}


你可能感兴趣的:(android学习笔记)