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

如何更新Pygame中绘制的线条?函数切线被覆盖问题求助

问题:函数切线绘制位置异常,无法正确覆盖旧切线

尝试为二次函数 y = -0.001x² 的每个x值绘制函数曲线与对应切线,原本想在绘制新切线前用白色线条覆盖旧切线,但实际切线全部显示在函数图形下方,且覆盖逻辑失效。

原代码

import pygame
import os
from math import *
from time import *

screen = pygame.display.set_mode((600, 600))
screen.fill((255, 255, 255))

os.system('cls')
fun = True
x = -300
y = 0
xl = [0, 0]
yl = [0, 0]
ys = 0
xs = -300
xsl = [0, 0]
ysl = [0, 0]
al = 0
slobe = 0

while True:
    if x <= 600 and fun:
        if x == -1:
            x = 1
        yl[0] = y
        y = 0.001 * x**2
        y = -y
        yl[1] = y

        xl[0] = x
        x += 1
        xl[1] = x
        print((x, y), xl, yl)

        pygame.draw.line(screen, 'red', (xl[0] + 300, yl[0] + 300), (xl[1] + 300, yl[1] + 300))

    if x > 600 and fun:
        fun = False
        x = -300

    if not fun:
        y = 0.001 * x**2
        y = -y

        if x == -1:
            x = 1

        x += 1
        slobe = 0.002 * x
        xs = -300
        for i in range(600):
            point = (x, y)

            xsl[0] = xs
            xs += 1
            xsl[1] = xs

            al = xs + point[0]

            ysl[0] = ys
            ys = slobe * al + y + 3
            ysl[1] = ys

            pygame.draw.line(screen, 'white', (xsl[0] + 300, ysl[0] + 300), (xsl[1] + 300, ysl[1] + 300))
            pygame.draw.line(screen, 'blue', (xsl[0] + 300, ysl[0] + 300), (xsl[1] + 300, ysl[1] + 300))
            pygame.draw.line(screen, 'black', (0, 300), (600, 300))
            pygame.draw.line(screen, 'black', (300, 0), (300, 600))

    pygame.draw.line(screen, 'black', (0, 300), (600, 300))
    pygame.draw.line(screen, 'black', (300, 0), (300, 600))
    pygame.display.update()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()

问题分析与修正方案

  1. 切线公式错误:原代码的切线计算完全偏离点斜式,且斜率符号错误(原函数y=-0.001x²的导数为y’=-0.002x,而非0.002x)。正确的切线方程应为:对于函数上的点(x0, y0),切线在任意x处的y值为 y = k*(x - x0) + y0,其中k=-0.002*x0。
  2. 覆盖逻辑失效:原代码试图用白色线条逐段覆盖旧切线,但未重置背景或切线变量,导致旧切线残留。正确做法是每次绘制新切线前,重绘白色背景和函数曲线,确保旧切线被完全清除。
  3. 变量复用混乱:x变量同时用于函数绘制和切线的x0遍历,导致逻辑混乱,需分离变量。

修正后的代码

import pygame
import os

# 初始化Pygame
pygame.init()
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("函数与切线")

# 坐标系参数
OFFSET = 300  # 屏幕中心对应(0,0)

def draw_function():
    """绘制原函数曲线"""
    x_prev = -300
    y_prev = -0.001 * (x_prev ** 2)
    for x in range(-299, 301):
        y = -0.001 * (x ** 2)
        # 转换为屏幕坐标:x轴+OFFSET,y轴+OFFSET(pygame y轴向下)
        pygame.draw.line(screen, 'red', 
                        (x_prev + OFFSET, y_prev + OFFSET), 
                        (x + OFFSET, y + OFFSET))
        x_prev, y_prev = x, y

def draw_tangent(x0):
    """绘制x0处的切线"""
    y0 = -0.001 * (x0 ** 2)
    k = -0.002 * x0  # 正确的导数(斜率)
    x_prev = -300
    y_prev = k * (x_prev - x0) + y0
    for x in range(-299, 301):
        y = k * (x - x0) + y0
        pygame.draw.line(screen, 'blue', 
                        (x_prev + OFFSET, y_prev + OFFSET), 
                        (x + OFFSET, y + OFFSET))
        x_prev, y_prev = x, y

def draw_axis():
    """绘制坐标轴"""
    pygame.draw.line(screen, 'black', (0, OFFSET), (600, OFFSET))  # x轴
    pygame.draw.line(screen, 'black', (OFFSET, 0), (OFFSET, 600))  # y轴

# 初始绘制函数曲线
screen.fill((255, 255, 255))
draw_function()
draw_axis()
pygame.display.update()

# 遍历每个x0绘制切线
x0 = -300
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    
    if x0 > 300:
        x0 = -300  # 循环遍历
    
    # 清除旧内容,重绘函数和坐标轴
    screen.fill((255, 255, 255))
    draw_function()
    draw_axis()
    # 绘制当前x0的切线
    draw_tangent(x0)
    pygame.display.update()
    
    x0 += 1
    # 控制动画速度
    pygame.time.delay(50)

pygame.quit()

关键修改说明

  • 拆分函数绘制、切线绘制、坐标轴绘制为独立函数,逻辑更清晰
  • 使用正确的导数计算切线斜率,切线方程严格遵循点斜式
  • 每次绘制新切线前用白色背景清除旧内容,确保覆盖效果
  • 分离x0(切线对应的函数点x值)与绘图用的x变量,避免混淆
  • 添加动画延迟,便于观察切线变化

内容的提问来源于stack exchange,提问作者mhnd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 00:23:13