Android上怎樣使用《貝賽爾曲線》

來源:互聯網
上載者:User

首先對於《賽貝爾曲線》不是很瞭解的童鞋,請自覺白度百科、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 ,是遊戲的主視圖

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

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

// 貝賽爾曲線成員變數(起始點,控制(操作點),終止點,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);
    ...
        //貝賽爾曲線相關初始化
        path = new Path();
        paintQ = new Paint();
        paintQ.setAntiAlias(true);
        paintQ.setStyle(Style.STROKE);
        paintQ.setStrokeWidth(5);
        paintQ.setColor(Color.WHITE);
        random = new Random();
    ...
}

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

/**
 * 繪製貝賽爾曲線
 * 
 * @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);
    }
}

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

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

ok,效果接圖如下:

 

 

 

 

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

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.