首先对于《赛贝尔曲线》不是很了解的童鞋,请自觉白度百科、google等等...
为了方便偷懒的童鞋,这里给个《贝赛尔曲线》百科地址,以及一段话简述《贝赛尔曲线》:
贝塞尔曲线又称贝兹曲线或贝济埃曲线,一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋;
上面这一段话其实就“线段像可伸缩的皮筋”这一句比较重要,也很容易理解;
至于贝赛尔曲线的实现,在android中极其的简单,因为它是android封装的一个方法,这个能不简单么。。。。。。只不过它隐藏的比较深,它隐藏于path类中,方法如下:
此方参数解释:
第一个参数:操作点的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游戏框架
* surfaceview视图创建,响应此函数
public void surfacecreated(surfaceholder holder) {
screenw = this.getwidth();
screenh = this.getheight();
flag = true;
// 实例线程
th = new thread(this);
// 启动线程
th.start();
* 游戏绘图
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);
* 按键事件监听
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;
}