Up to date

This page is up to date for Godot `4.2`. If you still find outdated information, please open an issue.

# 贝塞尔、曲线和路径¶

## 二次贝塞尔曲线¶

```func _quadratic_bezier(p0: Vector2, p1: Vector2, p2: Vector2, t: float):
var q0 = p0.lerp(p1, t)
var q1 = p1.lerp(p2, t)
```

```var r = q0.lerp(q1, t)
return r
```

(图像来源: 维基百科)

## 三次贝塞尔曲线¶

```func _cubic_bezier(p0: Vector2, p1: Vector2, p2: Vector2, p3: Vector2, t: float):
```

```var q0 = p0.lerp(p1, t)
var q1 = p1.lerp(p2, t)
var q2 = p2.lerp(p3, t)
```

```var r0 = q0.lerp(q1, t)
var r1 = q1.lerp(q2, t)
```

```var s = r0.lerp(r1, t)
return s
```

```func _cubic_bezier(p0: Vector2, p1: Vector2, p2: Vector2, p3: Vector2, t: float):
var q0 = p0.lerp(p1, t)
var q1 = p1.lerp(p2, t)
var q2 = p2.lerp(p3, t)

var r0 = q0.lerp(q1, t)
var r1 = q1.lerp(q2, t)

var s = r0.lerp(r1, t)
return s
```

(图像来源: 维基百科)

## 添加控制点¶

• `point0 = p0`：是第一个点，即源

• `control0 = p1 - p0`：是相对于第一个控制点的向量

• `control1 = p3 - p2`：是相对于第二个控制点的向量

• `point1 = p3`：是第二个点，即终点

## Curve2D、Curve3D、Path 以及 Path2D¶

They can contain several points, allowing for longer paths. It is also possible to set them to nodes: Path3D and Path2D (also for 3D and 2D respectively):

## 估值¶

Only evaluating them may be an option, but in most cases it's not very useful. The big drawback with Bezier curves is that if you traverse them at constant speed, from `t = 0` to `t = 1`, the actual interpolation will not move at constant speed. The speed is also an interpolation between the distances between points `p0`, `p1`, `p2` and `p3` and there is not a mathematically simple way to traverse the curve at constant speed.

Let's do an example with the following pseudocode:

```var t = 0.0

func _process(delta):
t += delta
position = _cubic_bezier(p0, p1, p2, p3, t)
```

## 绘制¶

Curve 类通过 Curve2D.tessellate() 函数来提供该功能(函数接收可选的 `stages` 递归和角度 `tolerance` 参数). 这样一来, 基于曲线画东西就比较容易了.

## 遍历¶

To make this easier, the curves need to be baked into equidistant points. This way, they can be approximated with regular interpolation (which can be improved further with a cubic option). To do this, just use the Curve3D.sample_baked() method together with Curve2D.get_baked_length(). The first call to either of them will bake the curve internally.

```var t = 0.0

func _process(delta):
t += delta
position = curve.sample_baked(t * curve.get_baked_length(), true)
```