You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用一系列圆连接波动点实现Pygame平滑水面曲线?

解决Pygame水面平滑曲线与填充问题

核心思路

  1. 平滑曲线实现:放弃直接连接两个波动点的生硬线段,改用线性插值在相邻点之间生成大量过渡点,每个过渡点绘制小圆,模拟连续平滑的曲线;
  2. 水面填充:将所有波动点与屏幕底部的两个端点组合成闭合多边形,用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 19:01:13