从数学曲线到萌系角色的编程之旅
在计算机图形学的世界里,一只毛茸茸的皮卡丘竟然可以通过严谨的数学函数和坐标计算诞生。本文将带你走进这段奇妙的编程之旅,通过 Python 的 turtle 模块,结合贝塞尔曲线等数学工具,一步步还原这只电气鼠的经典形象。这段代码不仅是一次绘图实践,更是数学与艺术在代码中碰撞的完美体现。
import turtle as tur
from math import sin, cos, pi
DRAW_SPEED = 3 # 绘图速度
PEN_SIZE = 6 # 画笔粗细
WIDTH = 600 # 画布宽度
HEIGHT = 600 # 画布高度
这段代码首先导入了绘图所需的 turtle 模块和数学函数,接着设置了画布尺寸、画笔粗细和绘制速度。这些参数决定了最终图像的大小和绘制效率,其中 600×600 像素的画布为皮卡丘的细节呈现提供了足够空间。
DRAW_SPEED参数可以控制绘图速度,设置为0可以立即完成绘制,适合快速查看最终效果。
贝塞尔曲线是计算机图形学中描述曲线的重要工具,通过控制点可以灵活调整曲线形状。代码中实现了从一阶到三阶的贝塞尔曲线计算:
def linear_interp(p1, p2, t):
return p1 * (1 - t) + p2 * t
def bezier1(p1, p2, t):
return (
linear_interp(p1[0], p2[0], t),
linear_interp(p1[1], p2[1], t)
)
def bezier2(p1, p2, p3, t):
return bezier1(
bezier1(p1, p2, t),
bezier1(p2, p3, t),
t
)
def bezier3(p1, p2, p3, p4, t):
return bezier1(
bezier2(p1, p2, p3, t),
bezier2(p2, p3, p4, t),
t
)
t 在两点之间进行线性过渡,是贝塞尔曲线的基础由于 turtle 模块的坐标系统与常见的 SVG 坐标不同,需要通过 p() 和 transform() 函数进行转换:
def p(c): # 将 SVG 坐标 c 转换为 tur 坐标
return complex(
+ c.real - WIDTH / 2,
- c.imag + HEIGHT / 2
)
def transform(p, matrix=(1, 0, 0, 1, 0, 0)):
a, b, c = matrix[0], matrix[1], matrix[2],
d, e, f = matrix[3], matrix[4], matrix[5],
return complex(
a * p.real + c * p.imag + e,
b * p.real + d * p.imag + f
)
turtle 坐标以屏幕中心为原点,x 轴向右,y 轴向上complex 复数类型处理坐标,使计算更简洁高效为了简化绘图代码,封装了一系列绘图指令函数,这些函数相当于绘图的"单词",组合成皮卡丘的"轮廓句子":
def M(c): # 移动到 SVG 坐标 c
tur.goto(p(c).real, p(c).imag)
def L(start, end):
M(start)
M(end)
def C(start, control1, control2, end):
M(start)
bezier_3(
(p(start).real, p(start).imag),
(p(control1).real, p(control1).imag),
(p(control2).real, p(control2).imag),
(p(end).real, p(end).imag))
M(c):移动画笔到指定坐标,不绘制线条L(start, end):从起点到终点绘制直线C(start, control1, control2, end):使用三阶贝塞尔曲线,从起点经两个控制点到终点皮卡丘的颜色搭配是其标志性特征,代码中通过 f() 和 pd() 函数实现颜色控制:
def f(sp=0j, rgb='red'):
tur.fillcolor(rgb)
M(sp)
tur.begin_fill()
def pd(sp, rgb="#E4007F", bold=PEN_SIZE):
tur.color(rgb)
tur.pensize(bold)
M(sp)
tur.pendown()
皮卡丘的身体轮廓是最复杂的部分,通过一系列贝塞尔曲线和直线段构成:
## pikachu_身体
pd(420.5+130.5j, rgb="#816124", bold=6) # 身体 pd
f(420.5+130.5j, "#FFFC9D")
C(420.5+130.5j, 406.87+122.22j, 376.07+106.14j, 334.5+106.5j)
# 中间省略大量曲线指令...
L(409.5+124.5j, 420.5+130.5j)
nf()
面部是表达皮卡丘表情的关键,代码中通过精确的坐标计算实现:
## 右眼
pd(252.7+228.84j, rgb="#29ABE2", bold=6)
f(252.7+228.84j, "#29ABE2")
C(252.7+228.84j, 261.37+225.51j, 270.03+222.17j, 278.7+218.84j)
# 右眼轮廓曲线...
nf()
## 嘴
Mv(374.61+224.7j)
C(374.61+224.7j, 373.87+226.96j, 373.41+229.28j, 372.72+231.54j)
# 嘴巴曲线指令...
E() 函数绘制椭圆,#FB8D8C 的粉红色增添可爱感皮卡丘的四肢和花纹是其辨识度的关键:
## 左脚
pd(268.5+467.5j, rgb="#816124", bold=6)
C(268.5+467.5j, 299.04+420.77j, 308.38+413.95j, 311.5+415.5j)
# 左脚轮廓...
## 左耳_花纹
f(63.5+172.5j, "#816124")
C(63.5+172.5j, 76.29+179.74j, 95.99+188.89j, 121.5+193.5j)
# 耳朵花纹曲线...
代码中使用复数类型 complex 处理坐标,将 x 和 y 坐标分别作为实部和虚部,使坐标计算更简洁:
# 坐标表示示例
420.5+130.5j # 等价于(x=420.5, y=130.5)
这种表示方法允许直接使用复数运算进行坐标变换,如平移、旋转等操作。
虽然代码中注释了 turtle.tracer(2),但实际绘制中可以通过调整追踪参数提高效率:
tur.tracer(0) # 关闭绘图追踪
# 绘制过程...
tur.update() # 一次性更新画面
这种方法能避免逐帧刷新的性能损耗,尤其适合复杂图形的绘制。
在皮卡丘的绘制中,每个曲线段的控制点设置都经过精心调整:
这种数学计算与艺术感知的结合,是实现角色还原的关键。
"在计算机图形学中,艺术是数学的视觉表达,数学是艺术的精确语言。" — 计算机图形学格言
当这段代码在 Python 解释器中运行时,海龟绘图模块会按照以下步骤呈现皮卡丘:
整个过程如同一位数字艺术家,用代码作为画笔,在屏幕上勾勒出这只经典角色的每一个细节。贝塞尔曲线如同艺术家的手腕,通过控制点的微妙调整,让数学函数呈现出艺术的柔美。
这段绘制皮卡丘的代码,不仅是 turtle 模块的应用示例,更是数学与艺术在编程世界的完美融合。从线性插值到三阶贝塞尔曲线,从坐标转换到颜色填充,每一行代码都承载着对角色的理解和对图形的认知。
通过这段代码,我们看到:计算机图形学不仅是严谨的算法和公式,更是创意表达的媒介。当数学函数遇上萌系角色,当代码指令化作像素色彩,编程便成为了一种独特的数字艺术形式。皮卡丘的每一个曲线段,都是代码与创意碰撞的火花,在屏幕上绽放出迷人的光彩。