轉載自【黑米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