Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android游戲 >> Android游戲開發 >> Android游戲開發24:Android觸屏方向導航

Android游戲開發24:Android觸屏方向導航

編輯:Android游戲開發

       很多Android手機都沒有實體的上下左右導航鍵,那麼怎麼控制游戲方向呢?Android游戲開發者想到了利用Android手機的觸屏特性,制作360度搖桿來取代游戲方向鍵,最終使得界面UI變得美觀,用戶操作也方便。

       先貼上效果圖:

Android游戲開發24:Android觸屏方向導航--360度游戲搖桿

       下面開始實現:

       首先,肯定是繪制兩個圓形,無可置疑;圓心點重合,為了區分 ,所以設置了不同顏色;

       灰色:固定不動的搖桿背景(也意味著搖桿的活動范圍);

       紅色:搖桿;

       然後考慮:紅色搖桿肯定跟隨手指觸屏的位置而移動,那麼這個很easy啦,只要在觸屏事件中處理,將獲取的觸屏XY坐標賦值與搖桿XY坐標即可;這個沒問題;但是緊接著在思考一個問題:

       一般情況下,我們不可能希望搖桿一直跟隨手指位置,所以需要一個搖桿的活動區域,也就如同上圖中的灰色區域,在灰色區域內搖桿可以隨著用戶的觸屏位置移動,但是一旦用戶觸屏位置在活動區域之外,搖桿就不應該跑出灰色區域;所以具體實現步驟如下:

       1)得到通過搖桿的坐標與觸屏點的坐標得到所形成的角度Angle。

       2)根據Angle,以及已知所在圓的半徑,算出搖桿所在灰色圓形上做圓周運動的當前X,Y坐標。

       首先第一步: 算出搖桿坐標與觸屏坐標形成的角度。

       我們肯定已知搖桿當前坐標,並且當用戶觸屏時的坐標也可以在觸屏按鍵中得到,那麼獲取的方法就可以寫成一個方法,方法如下:

Java代碼
  1. /***  
  2.  * 得到兩點之間的弧度  
  3.  */  
  4. public double getRad(float px1, float py1, float px2, float py2) {   
  5.     //得到兩點X的距離   
  6.     float x = px2 - px1;   
  7.     //得到兩點Y的距離   
  8.     float y = py1 - py2;   
  9.     //算出斜邊長   
  10.     float xie = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));   
  11.     //得到這個角度的余弦值(通過三角函數中的定理 :鄰邊/斜邊=角度余弦值)   
  12.     float cosAngle = x / xie;   
  13.     //通過反余弦定理獲取到其角度的弧度   
  14.     float rad = (float) Math.acos(cosAngle);   
  15.     //注意:當觸屏的位置Y坐標<搖桿的Y坐標我們要取反值-0~-180   
  16.     if (py2 < py1) {   
  17.         rad = -rad;   
  18.     }   
  19.     return rad;   
  20. }  

       在Java中,Math類中的反余弦函數返回的不是角度是弧度,這一點要格外注意。

       另外一點就是,因為三角函數角度范圍是0~180度,所以反之應該是-0~-180度;

       通過此函數獲取到搖桿與用戶觸屏位置所形成的角度之後,我們就可以通過圓周公式來得到其搖桿的XY坐標了;方法如下:

Java代碼
  1. /**  
  2.  *  
  3.  * @param R  
  4.  *            圓周運動的旋轉點  
  5.  * @param centerX  
  6.  *            旋轉點X  
  7.  * @param centerY  
  8.  *            旋轉點Y  
  9.  * @param rad  
  10.  *            旋轉的弧度  
  11.  */  
  12. public void getXY(float centerX, float centerY, float R, double rad) {   
  13.     //獲取圓周運動的X坐標   
  14.     SmallRockerCircleX = (float) (R * Math.cos(rad)) + centerX;   
  15.     //獲取圓周運動的Y坐標   
  16.     SmallRockerCircleY = (float) (R * Math.sin(rad)) + centerY;   
  17. }  

       圓周運動公式:通過三角函數定理得出:

       X坐標:所在圓的半徑*角度的余弦值

       Y坐標:所在圓形半徑*角度的正弦值

       圓周的大小,由所在圓的半徑R的大小來決定。

       通過以上的公式我們就可以讓搖桿在灰色圓形上做圓周運動,當然除此之外我們還要注意三點:

       1、做圓周運動的大小,應該跟灰色區域的半徑相同;

       2、觸屏事件中應該首先判定用戶觸屏的位置是否在灰色區域中,如果不在,我們就應該獲取搖桿與觸屏點的角度然後獲取搖桿應該在圓周運動上的XY坐標;如果在,就沒有處理了,只要將搖桿位置隨著用戶點擊位置就好了;

       3、在觸屏事件中,當用戶手指離開屏幕後,應該讓搖桿的位置恢復到初始的位置狀態。

       下面是整個項目的MySurfaceView中全部代碼:

Java代碼
  1. package com.rp;   
  2. import android.content.Context;   
  3. import android.graphics.Canvas;   
  4. import android.graphics.Color;   
  5. import android.graphics.Paint;   
  6. import android.util.Log;   
  7. import android.view.MotionEvent;   
  8. import android.view.SurfaceHolder;   
  9. import android.view.SurfaceView;   
  10. import android.view.SurfaceHolder.Callback;   
  11. public class MySurfaceView extends SurfaceView implements Callback, Runnable {   
  12.     private Thread th;   
  13.     private SurfaceHolder sfh;   
  14.     private Canvas canvas;   
  15.     private Paint paint;   
  16.     private boolean flag;   
  17.     //固定搖桿背景圓形的X,Y坐標以及半徑   
  18.     private int RockerCircleX = 100;   
  19.     private int RockerCircleY = 100;   
  20.     private int RockerCircleR = 50;   
  21.     //搖桿的X,Y坐標以及搖桿的半徑   
  22.     private float SmallRockerCircleX = 100;   
  23.     private float SmallRockerCircleY = 100;   
  24.     private float SmallRockerCircleR = 20;   
  25.     public MySurfaceView(Context context) {   
  26.         super(context);   
  27.         Log.v("Himi", "MySurfaceView");   
  28.         this.setKeepScreenOn(true);   
  29.         sfh = this.getHolder();   
  30.         sfh.addCallback(this);   
  31.         paint = new Paint();   
  32.         paint.setAntiAlias(true);   
  33.         setFocusable(true);   
  34.         setFocusableInTouchMode(true);   
  35.     }   
  36.     public void surfaceCreated(SurfaceHolder holder) {   
  37.         th = new Thread(this);   
  38.         flag = true;   
  39.         th.start();   
  40.     }   
  41.     /***  
  42.      * 得到兩點之間的弧度  
  43.      */  
  44.     public double getRad(float px1, float py1, float px2, float py2) {   
  45.         //得到兩點X的距離   
  46.         float x = px2 - px1;   
  47.         //得到兩點Y的距離   
  48.         float y = py1 - py2;   
  49.         //算出斜邊長   
  50.         float xie = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));   
  51.         //得到這個角度的余弦值(通過三角函數中的定理 :鄰邊/斜邊=角度余弦值)   
  52.         float cosAngle = x / xie;   
  53.         //通過反余弦定理獲取到其角度的弧度   
  54.         float rad = (float) Math.acos(cosAngle);   
  55.         //注意:當觸屏的位置Y坐標<搖桿的Y坐標我們要取反值-0~-180   
  56.         if (py2 < py1) {   
  57.             rad = -rad;   
  58.         }   
  59.         return rad;   
  60.     }   
  61.     @Override  
  62.     public boolean onTouchEvent(MotionEvent event) {   
  63.         if (event.getAction() == MotionEvent.ACTION_DOWN ||   
  64.                     event.getAction() == MotionEvent.ACTION_MOVE) {   
  65.             // 當觸屏區域不在活動范圍內   
  66.             if (Math.sqrt(Math.pow((RockerCircleX - (int) event.getX()), 2)   
  67.                     + Math.pow((RockerCircleY - (int) event.getY()), 2)) >= RockerCircleR) {   
  68.                 //得到搖桿與觸屏點所形成的角度   
  69.                 double tempRad = getRad(RockerCircleX, RockerCircleY, event.getX(), event.getY());   
  70.                 //保證內部小圓運動的長度限制   
  71.                 getXY(RockerCircleX, RockerCircleY, RockerCircleR, tempRad);   
  72.             } else {//如果小球中心點小於活動區域則隨著用戶觸屏點移動即可   
  73.                 SmallRockerCircleX = (int) event.getX();   
  74.                 SmallRockerCircleY = (int) event.getY();   
  75.             }   
  76.         } else if (event.getAction() == MotionEvent.ACTION_UP) {   
  77.             //當釋放按鍵時搖桿要恢復搖桿的位置為初始位置   
  78.             SmallRockerCircleX = 100;   
  79.             SmallRockerCircleY = 100;   
  80.         }   
  81.         return true;   
  82.     }   
  83.     /**  
  84.      *  
  85.      * @param R  
  86.      *            圓周運動的旋轉點  
  87.      * @param centerX  
  88.      *            旋轉點X  
  89.      * @param centerY  
  90.      *            旋轉點Y  
  91.      * @param rad  
  92.      *            旋轉的弧度  
  93.      */  
  94.     public void getXY(float centerX, float centerY, float R, double rad) {   
  95.         //獲取圓周運動的X坐標   
  96.         SmallRockerCircleX = (float) (R * Math.cos(rad)) + centerX;   
  97.         //獲取圓周運動的Y坐標   
  98.         SmallRockerCircleY = (float) (R * Math.sin(rad)) + centerY;   
  99.     }   
  100.     public void draw() {   
  101.         try {   
  102.             canvas = sfh.lockCanvas();   
  103.             canvas.drawColor(Color.WHITE);   
  104.             //設置透明度   
  105.             paint.setColor(0x70000000);   
  106.             //繪制搖桿背景   
  107.             canvas.drawCircle(RockerCircleX, RockerCircleY, RockerCircleR, paint);   
  108.             paint.setColor(0x70ff0000);   
  109.             //繪制搖桿   
  110.             canvas.drawCircle(SmallRockerCircleX, SmallRockerCircleY,   
  111.                     SmallRockerCircleR, paint);   
  112.         } catch (Exception e) {   
  113.             // TODO: handle exception   
  114.         } finally {   
  115.             try {   
  116.                 if (canvas != null)   
  117.                     sfh.unlockCanvasAndPost(canvas);   
  118.             } catch (Exception e2) {   
  119.             }   
  120.         }   
  121.     }   
  122.     public void run() {   
  123.         // TODO Auto-generated method stub   
  124.         while (flag) {   
  125.             draw();   
  126.             try {   
  127.                 Thread.sleep(50);   
  128.             } catch (Exception ex) {   
  129.             }   
  130.         }   
  131.     }   
  132.     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {   
  133.         Log.v("Himi", "surfaceChanged");   
  134.     }   
  135.     public void surfaceDestroyed(SurfaceHolder holder) {   
  136.         flag = false;   
  137.         Log.v("Himi", "surfaceDestroyed");   
  138.     }   
  139. }  

       如果大家想美化搖桿,那就讓你們的美工給出兩張圓形圖吧。

       還在等什麼?立刻為你的游戲加上搖桿吧!

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