1. 程式人生 > >Android快樂貪吃蛇遊戲實戰專案開發教程-05虛擬方向鍵(四)四個三角形按鈕

Android快樂貪吃蛇遊戲實戰專案開發教程-05虛擬方向鍵(四)四個三角形按鈕

package net.chengyujia.happysnake;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * 螢幕上的虛擬方向鍵
 * Created by ChengYuJia on 2016/8/19.
 
*/ public class DirectionKeys extends View { //左三角形按壓時的顏色(較亮) private int leftPressedColor = 0xFFFF0000; //左三角形正常顯示的顏色(較暗) private int leftNormalColor = 0xFFAA0000; //上三角形按壓時的顏色(較亮) private int upPressedColor = 0xFF00FF00; //上三角形正常顯示的顏色(較暗) private int upNormalColor = 0xFF00AA00; //右三角形按壓時的顏色(較亮)
private int rightPressedColor = 0xFF0000FF; //右三角形正常顯示的顏色(較暗) private int rightNormalColor = 0xFF0000AA; //下三角形按壓時的顏色(較亮) private int downPressedColor = 0xFFFFFF00; //下三角形正常顯示的顏色(較暗) private int downNormalColor = 0xFFAAAA00; //畫筆 private Paint paint = new Paint(); //畫左三角形的路徑
private Path pathLeft = new Path(); //畫上三角形的路徑 private Path pathUp = new Path(); //畫右三角形的路徑 private Path pathRight = new Path(); //畫下三角形的路徑 private Path pathDown = new Path(); //畫布的寬 private int width; //畫布的高 private int height; //初始化方法是否執行過,確保初始化方法只執行一次。 private boolean initDone = false; //記錄當前哪個方向鍵被按下 private Direction currentDirection = Direction.none; //只有一個引數的構造方法是我們在程式中通過“new”關鍵字建立例項時呼叫。 public DirectionKeys(Context context) { super(context); } //有兩個引數的構造方法是系統在XML佈局檔案中建立例項時呼叫。 public DirectionKeys(Context context, AttributeSet attrs) { super(context, attrs); } //初始化方法 private void init(Canvas canvas) { /*獲取畫布的長和寬*/ width = canvas.getWidth(); height = canvas.getHeight(); /* (小提示:在計算機中一般都是將左上角作為座標原點的) 畫布上四個頂點和中心點的座標如下: 左上點 0,0 左下點 0,height 右上點 width,0 右下點 width,height 中心點 width/2,height/2 */ /*設定左三角形的路徑資料*/ //從畫布左上點開始 pathLeft.moveTo(0, 0); //畫直線到畫布中心點 pathLeft.lineTo(width / 2, height / 2); //再畫直線到畫布左下點 pathLeft.lineTo(0, height); //自動閉合圖形。從最後一個點(左下點)畫直線到第一個點(左上點)。 pathLeft.close(); /*同理設定上三角形的路徑資料*/ pathUp.moveTo(0, 0); pathUp.lineTo(width / 2, height / 2); pathUp.lineTo(width, 0); pathUp.close(); /*同理設定右三角形的路徑資料*/ pathRight.moveTo(width, 0); pathRight.lineTo(width / 2, height / 2); pathRight.lineTo(width, height); pathRight.close(); /*同理設定下三角形的路徑資料*/ pathDown.moveTo(width, height); pathDown.lineTo(width / 2, height / 2); pathDown.lineTo(0, height); pathDown.close(); } //畫路徑的共用方法 private void drawPath(Path path, int color, Canvas canvas) { //設定畫筆顏色 paint.setColor(color); //用畫筆在畫布上按照路徑資料畫出圖形 canvas.drawPath(path, paint); } //畫左三角正常顏色 private void drawLeftNormal(Canvas canvas) { drawPath(pathLeft, leftNormalColor, canvas); } //畫左三角按壓顏色(高亮) private void drawLeftPressed(Canvas canvas) { drawPath(pathLeft, leftPressedColor, canvas); } //畫上三角正常顏色 private void drawUpNormal(Canvas canvas) { drawPath(pathUp, upNormalColor, canvas); } //畫上三角按壓顏色(高亮) private void drawUpPressed(Canvas canvas) { drawPath(pathUp, upPressedColor, canvas); } //畫右三角正常顏色 private void drawRightNormal(Canvas canvas) { drawPath(pathRight, rightNormalColor, canvas); } //畫右三角按壓顏色(高亮) private void drawRightPressed(Canvas canvas) { drawPath(pathRight, rightPressedColor, canvas); } //畫下三角正常顏色 private void drawDownNormal(Canvas canvas) { drawPath(pathDown, downNormalColor, canvas); } //畫下三角按壓顏色(高亮) private void drawDownPressed(Canvas canvas) { drawPath(pathDown, downPressedColor, canvas); } //所有按鈕恢復正常顏色 private void reset(Canvas canvas) { drawLeftNormal(canvas); drawUpNormal(canvas); drawRightNormal(canvas); drawDownNormal(canvas); } //當按左三角時,左三角高亮,其它正常。 private void drawWhenLeftPressed(Canvas canvas) { drawLeftPressed(canvas); drawUpNormal(canvas); drawRightNormal(canvas); drawDownNormal(canvas); } //當按上三角時,上三角高亮,其它正常。 private void drawWhenUpPressed(Canvas canvas) { drawLeftNormal(canvas); drawUpPressed(canvas); drawRightNormal(canvas); drawDownNormal(canvas); } //當按右三角時,右三角高亮,其它正常。 private void drawWhenRightPressed(Canvas canvas) { drawLeftNormal(canvas); drawUpNormal(canvas); drawRightPressed(canvas); drawDownNormal(canvas); } //當按下三角時,下三角高亮,其它正常。 private void drawWhenDownPressed(Canvas canvas) { drawLeftNormal(canvas); drawUpNormal(canvas); drawRightNormal(canvas); drawDownPressed(canvas); } /** * 通過重寫父類的onDraw方法來繪製我們需要的圖形 * 該方法會在控制元件第一次顯示時被系統呼叫,並在之後每次呼叫invalidate方法後被系統呼叫。 * * @param canvas 這裡的canvas是系統提供的一塊矩形畫布,我們要做的就是在這塊畫布上畫我們想要的東西。 */ @Override protected void onDraw(Canvas canvas) { if (!initDone) { init(canvas); //確保初始化方法只執行一次 initDone = true; } //按下不同的方向鍵,繪製不同的介面效果。 switch (currentDirection) { case left://按下左鍵時 drawWhenLeftPressed(canvas); break; case up://按下上鍵時 drawWhenUpPressed(canvas); break; case right://按下右鍵時 drawWhenRightPressed(canvas); break; case down://按下下鍵時 drawWhenDownPressed(canvas); break; default://其它情況 reset(canvas); } } /** * 當用戶觸控到該控制元件時,系統通過該方法告訴控制元件“你被摸了,要不要有反應啊?有反應返回true,沒反應返回false。” * 控制元件說“那要看是怎麼摸的了。如果是按下,我就將對應的三角形按鍵高亮顯示;如果是擡起,我就將所有的三角形按鍵恢復成正常的顏色。其它情況我就不反應了,摸就摸吧。” * * @param event 系統給我們傳遞的觸控事件引數 * @return 如果該觸控事件被我們處理了返回true,反之返回false。 */ @Override public boolean onTouchEvent(MotionEvent event) { //獲取當前的觸控動作 int action = event.getAction(); if (action == MotionEvent.ACTION_DOWN) {//按下 //獲取觸控點的座標 float x = event.getX(); float y = event.getY(); currentDirection = getDirection(x, y); invalidate();//重繪 return true; } else if (action == MotionEvent.ACTION_UP) {//擡起 currentDirection = Direction.none; invalidate();//重繪 return true; } else {//其它不處理 return false; } } //根據座標判斷哪個三角形方向鍵被按下 private Direction getDirection(float x, float y) { //經過座標轉換,統一成邊長為1的正方形處理。對角線分割形成的4個區域,分別代表4個方向。 float relativeX = x / width;//0<=relativeX<=1 float relativeY = y / height;//0<=relativeY<=1 /* 注意:原點是左上角。 左上角到右下角對角線方程為y=x; 則: y>x的區域包含左和下三角形 y<x的區域包含右和上三角形 左下角到右上角對角線方程為y=-x+1; 則: y>1-x的區域包含右和下三角形 y<1-x的區域包含左和上三角形 綜上可得: y>x 且 y<1-x 表示左三角 y<x 且 y<1-x 表示上三角 y<x 且 y>1-x 表示右三角 y>x 且 y>1-x 表示下三角 */ if (relativeY > relativeX) {//左和下 if (relativeY < 1 - relativeX) {// return Direction.left; } else {// return Direction.down; } } else {//上和右 if (relativeY < 1 - relativeX) {// return Direction.up; } else {// return Direction.right; } } } }