在Android上的使用《貝賽爾曲線》!

轉載自【黑米GameDev街區】 原文鏈接: http://www.himigame.com/android-game/386.html

          ☞ 點擊訂閱 ☜
 本博客最新動態!及時將最新博文通知您!

首先對於《賽貝爾曲線》不是很瞭解的童鞋,請自覺白度百科、google等等…

爲了方便偷懶的童鞋,這裏給個《貝賽爾曲線》百科地址,以及一段話簡述《貝賽爾曲線》:

《貝賽爾曲線》白度百科快速地址:http://baike.baidu.com/view/4019466.htm

貝塞爾曲線又稱貝茲曲線或貝濟埃曲線,一般的矢量圖形軟件通過它來精確畫出曲線,貝茲曲線由線段與節點組成,節點是可拖動的支點,線段像可伸縮的皮筋;

上面這一段話其實就“線段像可伸縮的皮筋”這一句比較重要,也很容易理解;

至於貝賽爾曲線的實現,在Android中極其的簡單,因爲它是Android封裝的一個方法,這個能不簡單麼。。。。。。只不過它隱藏的比較深,它隱藏於Path類中,方法如下:

android.graphics.Path.quadTo(float x1, float y1, float x2, float y2)

Since: API Level 1

此方參數解釋:

第一個參數:操作點的x座標

第二個參數:操作點的y座標

第三個參數:結束點的x座標

第四個參數:結束點的y座標

從API中看出,賽貝爾曲線從API-1就開始支持了;

熟悉方法後,下面就來實現:

SurfaceView框架不多講,看過我博客的都應該知道的;

直接看MySurfaceView類,此類繼承SurfaceView ,是遊戲的主視圖

這裏爲了更清晰的講解:這裏部分代碼先不貼出來了,最後會整體貼出,當然源碼也是免費在最後提供~

首先是定義相關的成員變量:

1
2
3
4
5
6
7
8
// 貝賽爾曲線成員變量(起始點,控制(操作點),終止點,3點座標)
private int startX, startY, controlX, controlY, endX, endY;
// Path
private Path path;
// 爲了不影響主畫筆,這裏繪製貝賽爾曲線單獨用一個新畫筆
private Paint paintQ;
// 隨機庫(讓貝賽爾曲線更明顯)
private Random random;

本類構造函數:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 * SurfaceView初始化函數
 */
public MySurfaceView(Context context) {
    super(context);
    ...
        //貝賽爾曲線相關初始化
        path = new Path();
        paintQ = new Paint();
        paintQ.setAntiAlias(true);
        paintQ.setStyle(Style.STROKE);
        paintQ.setStrokeWidth(5);
        paintQ.setColor(Color.WHITE);
        random = new Random();
    ...
}

接着我把繪製貝賽爾曲線封裝一個方法了,函數如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * 繪製貝賽爾曲線
 *
 * @param canvas 主畫布
 */
public void drawQpath(Canvas canvas) {
    path.reset();// 重置path
    // 貝賽爾曲線的起始點
    path.moveTo(startX, startY);
    // 設置貝賽爾曲線的操作點以及終止點
    path.quadTo(controlX, controlY, endX, endY);
    // 繪製貝賽爾曲線(Path)
    canvas.drawPath(path, paintQ);
}

最後是用戶觸屏監聽函數以及邏輯函數:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 * 觸屏事件監聽
 */
@Override
public boolean onTouchEvent(MotionEvent event) {
    endX = (int) event.getX();
    endY = (int) event.getY();
    return true;
}
/**
 * 遊戲邏輯
 */
private void logic() {
    if (endX != 0 && endY != 0) {
        // 設置操作點爲線段x/y的一半
        controlX = random.nextInt((endX - startX) / 2);
        controlY = random.nextInt((endY - startY) / 2);
    }
}

整個代碼很easy~主要是貝賽爾函數的參數,尤其是操作點,操作點的各種不同可以實現不同的效果,這裏我簡單的統一的講操作點設置成用戶觸屏點的x,y的一半,呵呵偷懶了~嘻嘻~

我把貝賽爾的操作點寫在了邏輯logic()函數中,不斷的執行,並且每次利用nextInt函數得到隨機的操作點,主要爲了讓其曲線不斷的變化從而形成一個震動的曲線運動軌跡;

ok,效果接圖如下:

這裏可能由於圖片是靜止的效果看起來不是很明顯,大家可以運行源碼來觀察 ,好了~本節就這樣吧;下面貼出整個MySurfaceView的源碼:(最後有本項目的源碼下載地址)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package com.qpath;
import java.util.Random;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
/**
 * 賽貝爾曲線
 * @author Himi
 *
 */
public class MySurfaceView extends SurfaceView implements Callback, Runnable {
    private SurfaceHolder sfh;
    private Paint paint;
    private Thread th;
    private boolean flag;
    private Canvas canvas;
    public static int screenW, screenH;
    // -----------以上是SurfaceView遊戲框架
    // 貝賽爾曲線成員變量(起始點,控制(操作點),終止點,3點座標)
    private int startX, startY, controlX, controlY, endX, endY;
    // Path
    private Path path;
    // 爲了不影響主畫筆,這裏繪製貝賽爾曲線單獨用一個新畫筆
    private Paint paintQ;
    // 隨機庫(讓貝賽爾曲線更明顯)
    private Random random;
    /**
     * SurfaceView初始化函數
     */
    public MySurfaceView(Context context) {
        super(context);
        sfh = this.getHolder();
        sfh.addCallback(this);
        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setAntiAlias(true);
        setFocusable(true);
        // -----------以上是SurfaceView遊戲框架
        //貝賽爾曲線相關初始化
        path = new Path();
        paintQ = new Paint();
        paintQ.setAntiAlias(true);
        paintQ.setStyle(Style.STROKE);
        paintQ.setStrokeWidth(5);
        paintQ.setColor(Color.WHITE);
        random = new Random();
    }
    /**
     * SurfaceView視圖創建,響應此函數
     */
    public void surfaceCreated(SurfaceHolder holder) {
        screenW = this.getWidth();
        screenH = this.getHeight();
        flag = true;
        // 實例線程
        th = new Thread(this);
        // 啓動線程
        th.start();
        // -----------以上是SurfaceView遊戲框架
    }
    /**
     * 遊戲繪圖
     */
    public void myDraw() {
        try {
            canvas = sfh.lockCanvas();
            if (canvas != null) {
                canvas.drawColor(Color.BLACK);
                // -----------以上是SurfaceView遊戲框架
                drawQpath(canvas);
            }
        } catch (Exception e) {
            // TODO: handle exception
        } finally {
            if (canvas != null)
                sfh.unlockCanvasAndPost(canvas);
        }
    }
    /**
     * 繪製貝賽爾曲線
     *
     * @param canvas 主畫布
     */
    public void drawQpath(Canvas canvas) {
        path.reset();// 重置path
        // 貝賽爾曲線的起始點
        path.moveTo(startX, startY);
        // 設置貝賽爾曲線的操作點以及終止點
        path.quadTo(controlX, controlY, endX, endY);
        // 繪製貝賽爾曲線(Path)
        canvas.drawPath(path, paintQ);
    }
    /**
     * 觸屏事件監聽
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        endX = (int) event.getX();
        endY = (int) event.getY();
        return true;
    }
    /**
     * 遊戲邏輯
     */
    private void logic() {
        if (endX != 0 && endY != 0) {
            // 設置操作點爲線段x/y的一半
            controlX = random.nextInt((endX - startX) / 2);
            controlY = random.nextInt((endY - startY) / 2);
        }
    }
    /**
     * 按鍵事件監聽
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        return super.onKeyDown(keyCode, event);
    }
    public void run() {
        while (flag) {
            long start = System.currentTimeMillis();
            myDraw();
            logic();
            long end = System.currentTimeMillis();
            try {
                if (end - start < 50) {
                    Thread.sleep(50 - (end - start));
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * SurfaceView視圖狀態發生改變,響應此函數
     */
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
    }
    /**
     * SurfaceView視圖消亡時,響應此函數
     */
    public void surfaceDestroyed(SurfaceHolder holder) {
        flag = false;
    }
}

本章源碼下載: ”貝賽爾曲線.zip”           下載地址:  http://vdisk.weibo.com/s/hq3e9

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章