2. 2D图形绘制:使用Python的Pygame库绘制基本图形
好,咱们正式开始动手了。这一章我带你用Pygame画点东西。你想想看,一个桌面应用如果连个图形都画不出来,那跟记事本有什么区别?图形绘制是多媒体开发的基石,说白了就是给屏幕上的像素点「下命令」。
我个人习惯把Pygame当作一个快速验证想法的工具。它不像OpenGL那样底层,也不像Qt那样臃肿。对于2D图形,Pygame的API设计得相当直觉。嗯,咱们先从最基础的开始——点、线、矩形、圆。
2.1 初始化与基本设置
在画任何东西之前,你得先有个画布。Pygame里这个画布叫Surface,而显示在屏幕上的那个叫display Surface。我刚开始学的时候总搞混这两个概念,后来发现其实很简单:display就是最终你看到的那个窗口。
import pygame
import sys
# 初始化Pygame
pygame.init()
# 设置窗口大小,单位是像素
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("2D图形绘制 - 第2章")
# 定义颜色常量(RGB元组)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# 主循环
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 填充背景色
screen.fill(WHITE)
# 在这里绘制图形...
pygame.display.flip()
pygame.quit()
sys.exit()
2.2 绘制点与线
点是最基本的图形元素。在Pygame里,画一个点其实就是画一个1像素宽的线段。我在项目中遇到过一个问题:用画点的方式去绘制大量粒子效果,性能会急剧下降。后来改用画矩形替代,效率提升了好几倍。
# 画一个点(实际上是画一条长度为1的线)
pygame.draw.line(screen, BLACK, (100, 100), (101, 100), 1)
# 画一条直线
pygame.draw.line(screen, RED, (50, 50), (200, 50), 3)
# 画多条连续线(折线)
points = [(300, 100), (400, 200), (500, 100), (600, 200)]
pygame.draw.lines(screen, BLUE, False, points, 2)
2.3 绘制矩形与圆
矩形和圆是UI开发中最常用的图形。按钮、面板、头像,几乎都离不开它们。Pygame的矩形绘制支持圆角,但要注意——圆角矩形在旧版本里是不支持的,升级到2.0以上才有。
# 绘制矩形(无填充)
pygame.draw.rect(screen, GREEN, (100, 100, 200, 150), 2)
# 绘制填充矩形
pygame.draw.rect(screen, RED, (350, 100, 200, 150))
# 绘制圆角矩形(Pygame 2.0+)
pygame.draw.rect(screen, BLUE, (600, 100, 150, 150), 0, 20)
# 绘制圆(无填充)
pygame.draw.circle(screen, BLACK, (200, 350), 50, 3)
# 绘制填充圆
pygame.draw.circle(screen, RED, (400, 350), 60)
# 绘制椭圆
pygame.draw.ellipse(screen, GREEN, (550, 300, 200, 100), 2)
| 函数 | 参数说明 | width=0时 |
|---|---|---|
| pygame.draw.rect | surface, color, rect, width=0 | 完全填充 |
| pygame.draw.circle | surface, color, center, radius, width=0 | 完全填充 |
| pygame.draw.ellipse | surface, color, rect, width=0 | 完全填充 |
| pygame.draw.polygon | surface, color, points, width=0 | 完全填充 |
2.4 颜色与填充
颜色在Pygame里用RGB元组表示,每个分量0-255。但你知道吗?Pygame还支持带透明度的RGBA。alpha通道从0(完全透明)到255(完全不透明)。
我建议你在项目里定义一个颜色常量文件,而不是到处写(255, 0, 0)。为什么?因为后期改主题色的时候,你会感谢我的。
# 带透明度的颜色
TRANSPARENT_RED = (255, 0, 0, 128)
# 创建带透明度的Surface
alpha_surface = pygame.Surface((200, 200), pygame.SRCALPHA)
alpha_surface.fill((0, 0, 255, 100)) # 半透明蓝色
# 渐变填充(手动实现)
for i in range(256):
color = (i, 0, 255 - i) # 从蓝色渐变到红色
pygame.draw.line(screen, color, (i, 450), (i, 500))
2.5 抗锯齿技术
好,接下来聊点进阶的。你仔细看看上面画的圆,是不是边缘有锯齿?这就是所谓的「走样」现象。抗锯齿(Anti-Aliasing)就是通过边缘像素的渐变过渡,让图形看起来更平滑。
Pygame提供了gfxdraw模块来处理抗锯齿。不过要注意,gfxdraw不是默认安装的,需要额外安装pygame.gfxdraw库。我个人习惯用这个库来画高质量的图形。
# 需要安装:pip install pygame-gfxdraw
import pygame.gfxdraw
# 抗锯齿画圆
pygame.gfxdraw.aacircle(screen, 200, 550, 50, BLACK)
# 抗锯齿画线
pygame.gfxdraw.line(screen, 300, 500, 500, 600, RED)
# 抗锯齿填充圆
pygame.gfxdraw.filled_circle(screen, 400, 550, 50, BLUE)
# 手动实现抗锯齿(简单版)
# 原理:在边缘绘制半透明像素
def draw_aa_line(screen, color, start, end, width):
# 实际项目中会用更复杂的算法
# 这里展示思路
pygame.draw.line(screen, color, start, end, width)
# 在端点处画半透明圆来柔化边缘
pygame.draw.circle(screen, (*color, 128), start, width//2)
pygame.draw.circle(screen, (*color, 128), end, width//2)
2.6 综合示例:绘制一个简单的仪表盘
理论说完了,咱们来点实战。下面这个例子画了一个简单的仪表盘,用到了本章所有知识点。
import pygame
import math
pygame.init()
screen = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (200, 200, 200)
RED = (255, 50, 50)
BLUE = (50, 50, 255)
running = True
angle = 0
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(WHITE)
# 画表盘外框(抗锯齿圆)
pygame.gfxdraw.aacircle(screen, 200, 200, 150, BLACK)
pygame.gfxdraw.aacircle(screen, 200, 200, 148, GRAY)
# 画刻度线
for i in range(12):
rad = math.radians(i * 30 - 90)
x1 = 200 + int(130 * math.cos(rad))
y1 = 200 + int(130 * math.sin(rad))
x2 = 200 + int(140 * math.cos(rad))
y2 = 200 + int(140 * math.sin(rad))
pygame.draw.line(screen, BLACK, (x1, y1), (x2, y2), 2)
# 画指针(动态旋转)
rad = math.radians(angle - 90)
end_x = 200 + int(100 * math.cos(rad))
end_y = 200 + int(100 * math.sin(rad))
pygame.draw.line(screen, RED, (200, 200), (end_x, end_y), 4)
# 画中心圆
pygame.draw.circle(screen, BLUE, (200, 200), 10)
angle = (angle + 1) % 360
pygame.display.flip()
clock.tick(60)
pygame.quit()
嗯,这一章的内容就到这儿。记住,图形绘制的核心就三件事:位置、颜色、样式。Pygame把这些封装得足够简单,但真正用好它,需要你在项目中不断积累经验。下一章咱们聊图像加载与处理,到时候你会看到,这些基础图形知识会派上大用场。