別踩白塊新鮮出爐,使用的還是SurfaceView。
package com.example.administrator.whitegrid; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.util.TypedValue; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * Created by Administrator on 2017/6/8. */ public class GridGameView extends SurfaceView implements SurfaceHolder.Callback, Runnable { private boolean isDrawing; private Paint mPaint; /** * 被點擊 */ private boolean isTouch; /** * surface持有者 */ private SurfaceHolder mHolder; /** * 當前畫布 */ private Canvas mCanvas; /** * view的寬度 */ private int mWidth; /** * View的高度 */ private int mHeight; /** * 每格寬度 */ private int gridWidth; /** * 每格高度 */ private int gridHeight; /** * 每行格子個數 */ private int gridNumX = 5; /** * 每列格子個數 */ private int gridNumY = 5; /** * 偏移量 */ private int mOffSet; /** * 格子集合 */ private List<Integer> grids; /** * 生成隨機位置的格子 */ private Random random; /** * 點擊位置橫座標 */ private float pointX; /** * 點擊位置縱座標 */ private float pointY; /** * 被點擊方塊的下標 */ private int touchPosition; /** * 默認寬度設置爲300dp */ private static final int DEFAULT_WIDTH = 300; /** * 默認高度設置爲400dp */ private static final int DEFAULT_HEIGHT = 400; public GridGameView(Context context) { this(context, null); } public GridGameView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public GridGameView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mHolder = getHolder(); mHolder.addCallback(this); // 設置可以獲取焦點 setFocusable(true); // 進入觸摸輸入模式後,該控件是否還有獲得焦點的能力 setFocusableInTouchMode(true); // 是否保持屏幕常亮 setKeepScreenOn(true); random = new Random(); grids = new ArrayList<>(); //初始化一組方塊,屏幕外的上方下方個加一個方塊 for (int i = 0; i < gridNumY + 2; i++) { grids.add(random.nextInt(gridNumX)); } mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.FILL); } /** * 設置一些變量的尺寸 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode == MeasureSpec.AT_MOST) { mWidth = dp2px(DEFAULT_WIDTH); } else { mWidth = Math.max(widthSize, dp2px(DEFAULT_WIDTH)); } if (heightMode == MeasureSpec.AT_MOST) { mHeight = dp2px(DEFAULT_HEIGHT); } else { mHeight = Math.max(heightSize, dp2px(DEFAULT_HEIGHT)); } gridWidth = mWidth / gridNumX; gridHeight = mHeight / gridNumY; setMeasuredDimension(mWidth, mHeight); } @Override public void surfaceCreated(SurfaceHolder holder) { // 開始繪畫 isDrawing = true; // 啓動繪畫線程 new Thread(this).start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { isDrawing = false; } @Override public void run() { while (isDrawing) { try { mOffSet++; Thread.sleep(10); draw(); if (mOffSet == gridHeight) { if (grids.get(0) == gridNumX) { //移出屏幕外的黑塊到達最大偏移量,遊戲繼續 mOffSet = 0; grids.remove(0); grids.add(random.nextInt(gridNumX)); } else { //屏幕內的黑塊到達最大偏移量,遊戲結束 isDrawing = false; } } } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 繪圖 */ private void draw() { mCanvas = mHolder.lockCanvas(); if (mCanvas != null) { // 設置畫布背景爲白色 mCanvas.drawColor(0xffffffff); //繪製豎線 drawLineY(); //繪製橫線 drawLineX(); //點擊事件 eventTouchDown(); //畫黑白塊 drawGrid(); // 保證每次都將繪製的內容提交到服務器 mHolder.unlockCanvasAndPost(mCanvas); } } /** * 繪製縱向線 */ private void drawLineY() { mCanvas.save(); for (int i = 0; i < gridNumX + 1; i++) { mCanvas.drawLine(gridWidth * i, 0, gridWidth * i, mHeight, mPaint); } } /** * 繪製橫向線 */ private void drawLineX() { mCanvas.save(); for (int i = 0; i < gridNumY + 1; i++) { mCanvas.drawLine(0, gridHeight * i + mOffSet, mWidth, gridHeight * i + mOffSet, mPaint); } } /** * 繪製格子 */ private void drawGrid() { mCanvas.save(); mPaint.setColor(Color.BLACK); for (int i = 0; i < grids.size(); i++) { mCanvas.drawRect(grids.get(i) * gridWidth, mHeight - gridHeight * (i + 1) + mOffSet, grids.get(i) * gridWidth + gridWidth, mHeight - gridHeight * i + mOffSet, mPaint); } } /** * 處理點擊事件 */ private void eventTouchDown() { if (isTouch) { touchPosition = (int) (mHeight + mOffSet - pointY) / gridHeight; if (pointX - grids.get(touchPosition) * gridWidth > 0 && pointX - grids.get(touchPosition) * gridWidth < gridWidth) { //被點擊的方塊移出屏幕外 grids.set(touchPosition, gridNumX); } else { //點擊白塊遊戲結束 isDrawing = false; } isTouch = false; } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: pointX = event.getX(); pointY = event.getY(); isTouch = true; break; } return true; } /** * dp轉化爲px工具 */ private int dp2px(int dp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics()); } }Activity中,和佈局文件直接引用自定義的view,跟上一篇小鳥過柱子的遊戲一樣,就不貼代碼了。
view中的屬性都可以通過get、set方法在activity中設置遊戲的開始,暫停,方塊移動速度,橫向縱向方塊的數量等。
另外可以加回調接口,監測遊戲結束