如何用一系列圆连接波动点实现Pygame平滑水面曲线?
解决Pygame水面平滑曲线与填充问题
核心思路
- 平滑曲线实现:放弃直接连接两个波动点的生硬线段,改用线性插值在相邻点之间生成大量过渡点,每个过渡点绘制小圆,模拟连续平滑的曲线;
- 水面填充:将所有波动点与屏幕底部的两个端点组合成闭合多边形,用
pygame.draw.polygon填充颜色,实现水面区域的填充效果。
修改后的完整代码
from random import randint import pygame WIDTH = 700 HEIGHT = 500 win = pygame.display.set_mode((WIDTH, HEIGHT)) WHITE = (255, 255, 255) BLACK = (0, 0, 0) AQUA = (0, 255, 255) # 改用RGB元组,避免字符串兼容性问题 RADIUS = 1 x, y = 0, HEIGHT//2 K = 1 FORCE = 100 VELOCITY = 0.5 run = True class Molecule: def __init__(self, x, y, radius, force, k): self.x = x self.y = y self.radius = radius self.force = force self.k = k self.max_amplitude = y + force/k self.min_amplitude = y - force/k self.up = False self.down = True self.restore = False def oscillate(self): # 修正浮点数精度导致的状态切换问题 if self.down and self.y < self.max_amplitude: self.y += VELOCITY if self.y >= self.max_amplitude: self.y = self.max_amplitude self.down = False self.up = True if self.up and self.y > self.min_amplitude: self.y -= VELOCITY if self.y <= self.min_amplitude: self.y = self.min_amplitude self.up = False self.down = True molecules = [] for i in range(100): FORCE = randint(10, 20) molecules.append(Molecule(x, y, RADIUS, FORCE, K)) x += 10 def draw_smooth_curve(win, points, radius, color): # 在相邻点之间生成插值点,绘制平滑曲线 for i in range(len(points)-1): x1, y1 = points[i] x2, y2 = points[i+1] step = 1 # 按1像素间隔生成过渡点 num_steps = abs(x2 - x1) // step if num_steps == 0: continue # 线性插值计算每个中间点坐标 dx = (x2 - x1) / num_steps dy = (y2 - y1) / num_steps for j in range(num_steps): current_x = int(x1 + dx * j) current_y = int(y1 + dy * j) pygame.draw.circle(win, color, (current_x, current_y), radius) while run: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False win.fill(WHITE) # 更新所有波动点的位置 for molecule in molecules: molecule.oscillate() # 收集所有波动点坐标 water_points = [(mol.x, mol.y) for mol in molecules] # 构建填充多边形的顶点(波动点+屏幕底部两个端点) fill_points = water_points + [(WIDTH, HEIGHT), (0, HEIGHT)] # 填充水面区域 pygame.draw.polygon(win, AQUA, fill_points) # 绘制平滑的水面曲线 draw_smooth_curve(win, water_points, RADIUS, BLACK) pygame.display.flip() pygame.quit()
关键修改说明
- 振动逻辑修正:原代码用
==判断位置容易因浮点数精度失效,改为区间判断+边界值修正,确保振动状态正常切换; - 平滑曲线函数:
draw_smooth_curve通过线性插值生成密集过渡点,用小圆点替代线段,实现平滑曲线效果; - 水面填充实现:通过闭合多边形填充,直接生成水面区域的视觉效果;
- 颜色值优化:将字符串
'aqua'改为RGB元组,避免部分Pygame版本的兼容性问题。
内容的提问来源于stack exchange,提问作者Programmer
相关产品推荐
相关产品推荐

