Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android快樂貪吃蛇游戲實戰項目開發教程-05虛擬方向鍵(四)四個三角形按鈕,android-05

Android快樂貪吃蛇游戲實戰項目開發教程-05虛擬方向鍵(四)四個三角形按鈕,android-05

編輯:關於android開發

Android快樂貪吃蛇游戲實戰項目開發教程-05虛擬方向鍵(四)四個三角形按鈕,android-05


該系列教程概述與目錄:http://www.cnblogs.com/chengyujia/p/5787111.html

一、如何判斷點擊的是哪個方向鍵按鈕

在上篇教程中我們實現了左邊的三角形按鈕效果,本篇教程我們將左、上、右、下四個三角形按鈕都一起實現了。
能做出一個來,另外三個應該不難了吧?但實際並非怎麼簡單哦。
首先我們來解決一下上節課遺留的一個問題,如何判斷當前手指點擊的是哪個三角形按鈕?


這個需要用解析幾何大法來解決。
假設我們的控件是邊長為1的正方形,建立平面直角坐標系(注意:計算機中坐標系原點在左上角哦),如下圖:

正方形的對角線將控件分成了4個三角形區域,也就是我們的4個方向鍵按鈕。

據上圖可知:
左上角到右下角對角線的方程為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 表示下三角

以上是按照邊長為1的正方形得到的結論,但實際中,我們的控件不一定是正方形,邊長也不是1,而是一個不確定的矩形,這該怎麼辦呢?
這就需要經過一定的轉換,將普通的矩形轉換為邊長為1的正方形。
這個轉變也簡單,如下:
設畫布上被觸摸到的點的坐標為(x,y),則:

    float relativeX = x / width;//0<=relativeX<=1
    float relativeY = y / height;//0<=relativeY<=1

我們將畫布上被觸摸的點的橫縱坐標分別除以畫布的寬和高,這樣就得到了一個相對坐標,而這個相對坐標的取值一定在0到1之間。這樣就相當於把一個不確定的矩形簡化成了一個邊長為1的正方形處理。

二、程序代碼

有了上面的了解,下面就可以寫代碼了。由於有4個三角形按鈕,而每個按鈕又有兩種狀態,代碼會稍微長點。但每個按鈕的邏輯都是一樣的,都是按哪個那個高亮,不按時都恢復正常狀態。代碼中的注釋比較詳細,相信大家如果看了前面的教程內容,看這個應該問題不大。唯一需要注意的是每次調用invalidate方法重繪界面時,是需要對整個畫布都重繪的,而不能只重繪一個三角形。

這裡我們需要先引入一個表示方向的枚舉:Direction

package net.chengyujia.happysnake;

/**
 * 用來表示方向的枚舉
 * Created by ChengYuJia on 2016/8/21.
 */
public enum Direction {
    //none表示沒有方向鍵按下
    none,
    //左
    left,
    //上
    up,
    //右
    right,
    //下
    down;
}

 
下面是當前DirectionKeys的完整代碼:

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;
            }
        }
    }
}

 

三、運行效果

沒有點擊時的效果:

 

點擊左鍵時的效果:

 

點擊上建時的效果:

 

點擊右鍵時的效果:

 

點擊下鍵時的效果:

 

到這裡,我們的自定義方向鍵的4個背景三角形已經做好了,而且實現了點擊變色的按鈕效果。

後面我們會在這4個三角形上都畫上相應的箭頭,同樣也有點擊變色的效果哦。敬請期待o(^▽^)o

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved