在上一章的學習中我們已經知道如何處理游戲中的觸摸事件,這一章將向同學們介紹繪制游戲觸摸軌跡的曲線圖,在onTouchEvent方法中我們可以拿到手指在屏幕中觸摸點 X Y時時的坐標,這章我們研究的課題就是如何把這些點變成一種無規則軌跡並且將這條無規則曲線顯示在屏幕中。
Android提供了一個Path類 , 顧名思義這個類可以設置曲線路徑軌跡。任何無規則的曲線實際上都是由若干條線段組成,而線段的定義為兩點之間最短的一條線。path類就 可以記錄這兩點之間的軌跡,那麼若干個Path 就是我們須要繪制的無規則曲線。
下面介紹一下API 中path類設置軌跡路徑的方法
public class
Path
extends Object
java.lang.Object
android.graphics.Path
quadTo(float x1, float y1, float x2, float y2)
Add a quadratic bezier from the last point, approaching control point (x1,y1), and ending at (x2,y2).
解釋:
參數1 軌跡起始點X坐標
參數2 軌跡起始點Y坐標
參數3 軌跡結束點X坐標
參數4 軌跡結束點Y坐標
所以根據這個參數就可以設置一條線段軌跡。
同學們,我們先看一張效果圖。 為了設置一條比較圓滑好看的曲線我們需要對游戲畫筆進行一些設置。注釋已經在代碼中寫的很清楚了,在這裡我詳細說一下 設置畫筆風格 mPaint.setStyle(Paint.Style.STROKE); 意思是設置畫筆的風格 android 畫筆一共提供了三種風格Paint.Style.STROKE 、Paint.Style.FILL、Paint.Style.FILL_AND_STROKE 意思分別為 空心 、實心、實心與空心 。如果不設置的話默認為 Paint.Style.FILL,在這裡必需設置成空心 因為如果一旦設置成實心或者實心與空心那麼畫筆會把path路徑中間包住這樣就不是曲線線段了,所以同學們注意一下這裡。
Java代碼
- /** 創建曲線畫筆 **/
- mPaint = new Paint();
- mPaint.setColor(Color.BLACK);
- /**設置畫筆抗鋸齒**/
- mPaint.setAntiAlias(true);
- /**畫筆的類型**/
- mPaint.setStyle(Paint.Style.STROKE);
- /**設置畫筆變為圓滑狀**/
- mPaint.setStrokeCap(Paint.Cap.ROUND);
- /**設置線的寬度**/
- mPaint.setStrokeWidth(5);
在觸摸按下事件中 通過moveTo() 方法設置觸摸屏幕點為軌跡的起始點,這樣在觸摸移動事件中設置曲線的軌跡 起始點為上次觸摸點 結束點為本次觸摸點。使用quadTo方法記錄每次移動產生的一個曲線線段 然後將所有的曲線線段繪制在屏幕中,如果觸摸抬起將調用reset()方法重置曲線軌跡。
Java代碼
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- /** 拿到觸摸的狀態 **/
- int action = event.getAction();
- float x = event.getX();
- float y = event.getY();
- switch (action) {
- // 觸摸按下的事件
- case MotionEvent.ACTION_DOWN:
- /**設置曲線軌跡起點 X Y坐標**/
- mPath.moveTo(x, y);
- break;
- // 觸摸移動的事件
- case MotionEvent.ACTION_MOVE:
- /**設置曲線軌跡**/
- //參數1 起始點X坐標
- //參數2 起始點Y坐標
- //參數3 結束點X坐標
- //參數4 結束點Y坐標
- mPath.quadTo(mposX, mposY, x, y);
- break;
- // 觸摸抬起的事件
- case MotionEvent.ACTION_UP:
- /**按鍵抬起後清空路徑軌跡**/
- mPath.reset();
- break;
- }
- //記錄當前觸摸X Y坐標
- mposX = x;
- mposY = y;
- return true;
- }
游戲繪制中調用drawPath方法將onTouchEvent中記錄的路徑曲線繪制在屏幕當中。
Java代碼
- private void Draw() {
- /**清空畫布**/
- mCanvas.drawColor(Color.WHITE);
- /**繪制曲線**/
- mCanvas.drawPath(mPath, mPaint);
-
- /**記錄當前觸點位置**/
- mCanvas.drawText("當前觸筆 X:" + mposX, 0, 20,mTextPaint);
- mCanvas.drawText("當前觸筆 Y:" + mposY, 0, 40,mTextPaint);
- }
給出整體代碼的實現
詳細的注釋已經在代碼中寫出 歡迎大家閱讀喔 哇咔咔~~~~
Java代碼
- import android.app.Activity;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Path;
- import android.os.Bundle;
- import android.view.MotionEvent;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- import android.view.Window;
- import android.view.WindowManager;
- import android.view.SurfaceHolder.Callback;
-
- public class SurfaceViewAcitvity extends Activity {
-
- MyView mAnimView = null;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // 全屏顯示窗口
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- // 顯示自定義的游戲View
- mAnimView = new MyView(this);
- setContentView(mAnimView);
- }
-
- public class MyView extends SurfaceView implements Callback,Runnable {
-
- /**每50幀刷新一次屏幕**/
- public static final int TIME_IN_FRAME = 50;
-
- /** 游戲畫筆 **/
- Paint mPaint = null;
- Paint mTextPaint = null;
- SurfaceHolder mSurfaceHolder = null;
-
- /** 控制游戲更新循環 **/
- boolean mRunning = false;
-
- /** 游戲畫布 **/
- Canvas mCanvas = null;
-
- /**控制游戲循環**/
- boolean mIsRunning = false;
-
- /**曲線方向**/
- private Path mPath;
-
- private float mposX, mposY;
-
- public MyView(Context context) {
- super(context);
- /** 設置當前View擁有控制焦點 **/
- this.setFocusable(true);
- /** 設置當前View擁有觸摸事件 **/
- this.setFocusableInTouchMode(true);
- /** 拿到SurfaceHolder對象 **/
- mSurfaceHolder = this.getHolder();
- /** 將mSurfaceHolder添加到Callback回調函數中 **/
- mSurfaceHolder.addCallback(this);
- /** 創建畫布 **/
- mCanvas = new Canvas();
- /** 創建曲線畫筆 **/
- mPaint = new Paint();
- mPaint.setColor(Color.BLACK);
- /**設置畫筆抗鋸齒**/
- mPaint.setAntiAlias(true);
- /**畫筆的類型**/
- mPaint.setStyle(Paint.Style.STROKE);
- /**設置畫筆變為圓滑狀**/
- mPaint.setStrokeCap(Paint.Cap.ROUND);
- /**設置線的寬度**/
- mPaint.setStrokeWidth(5);
- /**創建路徑對象**/
- mPath = new Path();
- /** 創建文字畫筆 **/
- mTextPaint = new Paint();
- /**設置顏色**/
- mTextPaint.setColor(Color.BLACK);
- /**設置文字大小**/
- mTextPaint.setTextSize(15);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- /** 拿到觸摸的狀態 **/
- int action = event.getAction();
- float x = event.getX();
- float y = event.getY();
- switch (action) {
- // 觸摸按下的事件
- case MotionEvent.ACTION_DOWN:
- /**設置曲線軌跡起點 X Y坐標**/
- mPath.moveTo(x, y);
- break;
- // 觸摸移動的事件
- case MotionEvent.ACTION_MOVE:
- /**設置曲線軌跡**/
- //參數1 起始點X坐標
- //參數2 起始點Y坐標
- //參數3 結束點X坐標
- //參數4 結束點Y坐標
- mPath.quadTo(mposX, mposY, x, y);
- break;
- // 觸摸抬起的事件
- case MotionEvent.ACTION_UP:
- /**按鍵抬起後清空路徑軌跡**/
- mPath.reset();
- break;
- }
- //記錄當前觸摸X Y坐標
- mposX = x;
- mposY = y;
- return true;
- }
-
- private void Draw() {
- /**清空畫布**/
- mCanvas.drawColor(Color.WHITE);
- /**繪制曲線**/
- mCanvas.drawPath(mPath, mPaint);
-
- /**記錄當前觸點位置**/
- mCanvas.drawText("當前觸筆 X:" + mposX, 0, 20,mTextPaint);
- mCanvas.drawText("當前觸筆 Y:" + mposY, 0, 40,mTextPaint);
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {
-
- }
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- /**開始游戲主循環線程**/
- mIsRunning = true;
- new Thread(this).start();
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- mIsRunning = false;
- }
-
- @Override
- public void run() {
- while (mIsRunning) {
-
- /** 取得更新游戲之前的時間 **/
- long startTime = System.currentTimeMillis();
-
- /** 在這裡加上線程安全鎖 **/
- synchronized (mSurfaceHolder) {
- /** 拿到當前畫布 然後鎖定 **/
- mCanvas = mSurfaceHolder.lockCanvas();
- Draw();
- /** 繪制結束後解鎖顯示在屏幕上 **/
- mSurfaceHolder.unlockCanvasAndPost(mCanvas);
- }
-
- /** 取得更新游戲結束的時間 **/
- long endTime = System.currentTimeMillis();
-
- /** 計算出游戲一次更新的毫秒數 **/
- int diffTime = (int) (endTime - startTime);
-
- /** 確保每次更新時間為50幀 **/
- while (diffTime <= TIME_IN_FRAME) {
- diffTime = (int) (System.currentTimeMillis() - startTime);
- /** 線程等待 **/
- Thread.yield();
- }
-
- }
-
- }
- }
- }
源碼下載地址:http://vdisk.weibo.com/s/aajeJ