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

使用Turtle开发的Pong游戏出现随机卡顿与音频延迟求助

Pong游戏随机卡顿与音频延迟问题分析

问题描述

我首次尝试用Turtle库开发经典Pong游戏,靠网络搜索、已有知识和Stack Overflow内容完成开发,游戏整体能正常运行,但过程中偶尔会随机卡顿——游戏速度骤降近50%后又突然升到150%,同时还有轻微音频延迟。我的笔记本配置不算差,这种小型游戏不该出现这类问题,求分析原因。

游戏代码

# My attempt at pong (atari game)

import turtle
import winsound

wn = turtle.Screen()
wn.title("Pong")
wn.bgcolor("black")
wn.setup(width = 800, height = 600)
wn.tracer(0)

# Score
player_1_score = 0
player_2_score = 0

# Paddle A
paddle_a = turtle.Turtle()
paddle_a.speed(0)
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.shapesize(stretch_wid = 5, stretch_len = 1)
paddle_a.penup()
paddle_a.goto(-350, 0)

# Paddle B
paddle_b = turtle.Turtle()
paddle_b.speed(0)
paddle_b.shape("square")
paddle_b.color("white")
paddle_b.shapesize(stretch_wid = 5, stretch_len = 1)
paddle_b.penup()
paddle_b.goto(350, 0)

# Ball
ball = turtle.Turtle()
ball.speed(0)
ball.shape("square")
ball.color("white")
ball.penup()
ball.goto(0, 0)
ball.dx = 0.1
ball.dy = 0.1

# Pen
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("PLAYER 1: 0  PLAYER 2: 0", align = "center", font = ("EightBit Atari", 24, "normal"))

# Finish game
finish = turtle.Turtle()
finish.speed(0)
finish.color("white")
finish.penup()
finish.hideturtle()
finish.goto(0, 240)
finish.write("FINISH GAME: SHIFT + Q", align = "center", font = ("EightBit Atari", 10, "normal"))


# Functions
def paddle_a_up():
    y = paddle_a.ycor()
    y += 20
    paddle_a.sety(y)

def paddle_a_down():
    y = paddle_a.ycor()
    y -= 20
    paddle_a.sety(y)

def paddle_b_up():
    y = paddle_b.ycor()
    y += 20
    paddle_b.sety(y)

def paddle_b_down():
    y = paddle_b.ycor()
    y -= 20
    paddle_b.sety(y)

def exit_game():
    turtle.bye()
    
# Keyboard binding
wn.listen()
wn.onkeypress(paddle_a_up, "w")
wn.onkeypress(paddle_a_down, "s")
wn.onkeypress(paddle_b_up, "Up")
wn.onkeypress(paddle_b_down, "Down")
wn.onkeypress(exit_game, "Q")

# Main game loop
while True:
    wn.update()

    # Move the ball
    ball.setx(ball.xcor() + ball.dx)
    ball.sety(ball.ycor() + ball.dy)

    # Border checking
    if ball.ycor() > 290:
        ball.sety(290)
        ball.dy *= -1
        winsound.PlaySound("wall.wav", winsound.SND_ASYNC)

    if ball.ycor() < -290:
        ball.sety(- 290)
        ball.dy *= -1
        winsound.PlaySound("wall.wav", winsound.SND_ASYNC)

    if ball.xcor() > 390:
        ball.goto(0, 0)
        ball.dx *= -1
        player_1_score += 1
        pen.clear()
        pen.write(f"PLAYER 1: {player_1_score}  PLAYER 2: {player_2_score}", align = "center", font = ("EightBit Atari", 24, "normal"))
        winsound.PlaySound("score.wav", winsound.SND_ASYNC)
        
    if ball.xcor() < -390:
        ball.goto(0, 0)
        ball.dx *= -1
        player_2_score += 1
        pen.clear()
        pen.write(f"PLAYER 1: {player_1_score}  PLAYER 2: {player_2_score}", align = "center", font = ("EightBit Atari", 24, "normal"))
        winsound.PlaySound("score.wav", winsound.SND_ASYNC)

    # Paddle and ball collisions
    if (ball.xcor() > 340 and ball.xcor() < 350) and (ball.ycor() < paddle_b.ycor() + 40 and ball.ycor() > paddle_b.ycor() - 40):
        ball.setx(340)
        ball.dx *= -1
        winsound.PlaySound("paddle.wav", winsound.SND_ASYNC)

    if (ball.xcor() < -340 and ball.xcor() > -350) and (ball.ycor() < paddle_a.ycor() + 40 and ball.ycor() > paddle_a.ycor() - 40):
        ball.setx(-340)
        ball.dx *= -1
        winsound.PlaySound("paddle.wav", winsound.SND_ASYNC)

原因分析

  • 音频播放的资源竞争:winsound.PlaySound的SND_ASYNC标记虽说是异步播放,但Windows底层的音频处理在频繁触发时,会和游戏主线程抢占CPU资源,导致帧更新速度波动,出现卡顿和音频延迟。
  • 无帧率控制的循环:主循环用while True无限制运行,会让CPU占用率拉满,一旦系统有后台任务(如杀毒、系统更新)抢占资源,游戏循环的执行速度就会骤变,表现为卡顿和速度异常。
  • 频繁的文本重绘开销:每次得分都调用pen.clear()和pen.write()重绘分数,自定义字体EightBit Atari的渲染比系统字体更耗性能,短时间内的重复绘制会瞬间增加CPU负载,引发短暂卡顿。
  • Turtle库的局限性:Turtle基于Tkinter开发,本身不是为高性能游戏设计的,其图形渲染和事件处理机制在高频更新场景下容易出现性能波动,尤其是无帧率锁的情况下。

优化建议

  • 添加帧率控制:用time.sleep()锁定帧率,比如限制在60帧/秒,避免循环无限制运行:
import time
# 主循环内添加
while True:
    wn.update()
    time.sleep(1/60)
  • 替换音频库:改用pygame.mixer替代winsound,它的异步播放机制更稳定,能避免资源竞争:
import pygame
pygame.mixer.init()
wall_sound = pygame.mixer.Sound("wall.wav")
# 播放时调用
wall_sound.play()
  • 优化分数渲染:仅在得分变化时更新分数文本,减少不必要的重绘操作。
  • 限制 paddle 移动范围:给paddle添加上下边界检查,防止其移出屏幕,减少无用的图形计算:
def paddle_a_up():
    y = paddle_a.ycor()
    if y < 250:
        y += 20
        paddle_a.sety(y)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 09:45:25