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

Python Pong游戏使用ontimer函数时屏幕闪瞬消失问题求助

Turtle Pong游戏窗口一闪即灭的问题解决

我是Python编程新手,练习写Pong游戏时,为了获得稳定的球速和刷新率,用ontimer替代了while True循环里的win.update(),但现在窗口只显示一瞬间就消失了。以下是我的代码:

import turtle as t
import time
import os

#Score variables
player_a = 0
player_b = 0

paddle_min_step=15

#create Pong main screen
win = t.Screen()
win.title('Ping Pong Game')
win.bgcolor('black')
win.setup(width=800,height=600)
win.tracer(0)

#create left paddle
paddle_left=t.Turtle()
paddle_left.speed(0)
paddle_left.shape('square')
paddle_left.shapesize(stretch_wid=5,stretch_len=1)
paddle_left.color('yellow')
paddle_left.penup()
paddle_left.goto(-350,0)

#create right paddle
paddle_right=t.Turtle()
paddle_right.speed(0)
paddle_right.shape('square')
paddle_right.shapesize(stretch_wid=5,stretch_len=1)
paddle_right.color('blue')
paddle_right.penup()
paddle_right.goto(350,0)

#create ball
ball=t.Turtle()
ball.speed(0)
ball.shape('circle')
ball.color('white')
ball.penup()
ball.goto(0,0)
ball_dx=1    #variabel for speed of ball in x dir
ball_dy=1     #variabel for speed of ball in y dir

#create pen for score
pen=t.Turtle()
pen.speed(0)
pen.color('skyblue')
pen.penup()
pen.hideturtle()
pen.goto(0,260)
pen.write("Player A: 0                  Player B: 0 ",align="center",font=('Monaco',24,"normal"))

#create paddle actions
def paddle_left_up():
    y=paddle_left.ycor()
    y=y+paddle_min_step
    paddle_left.sety(y)

def paddle_left_down():
    y=paddle_left.ycor()
    y=y-paddle_min_step
    paddle_left.sety(y)

def paddle_right_up():
    y=paddle_right.ycor()
    y=y+paddle_min_step
    paddle_right.sety(y)

def paddle_right_down():
    y=paddle_right.ycor()
    y=y-paddle_min_step
    paddle_right.sety(y)


win.listen()
win.onkeypress(paddle_left_up,"w")
win.onkeypress(paddle_left_down,'x')
win.onkeypress(paddle_right_up,'Up')
win.onkeypress(paddle_right_down,'Down')


def check_ballpos_score():
    global ball_dx, ball_dy

    win.update()
    ball.setx(ball.xcor()+ball_dx)
    ball.sety(ball.ycor()+ball_dy)

    #setting the borders for the ball
    #for y dir avoid ball is out of screen
    #for x dir check ball out of screen -> score
    if ball.ycor()>290:
        ball.sety(290)
        ball_dy=ball_dy * -1

    if ball.ycor()<-290:
        ball.sety(-290)
        ball_dy=ball_dy * -1

    #ball out of screen left/right check + change score 
    if ball.xcor()>390:
        ball.goto(0,0)
        player_a+=1
        pen.clear()
        pen.goto(0,260)
        pen.write("Player A: {}                  Player B: {} ".format(player_a,player_b),align="center",font=('Monaco',24,"normal"))
        
    if ball.xcor()<-390:
        ball.goto(0,0)
        player_b+=1
        pen.clear()
        pen.goto(0,260)
        pen.write("Player A: {}                  Player B: {} ".format(player_a,player_b),align="center",font=('Monaco',24,"normal"))
         

    #handling collision ball with the paddles
    if(ball.xcor() > 340) and (ball.xcor() < 350) and (ball.ycor() < paddle_right.ycor() + 40 and ball.ycor() > paddle_right.ycor() - 40):
        ball.setx(340)
        ball_dx = ball_dx * -1
       

    if(ball.xcor() < -340) and (ball.xcor() > -350) and (ball.ycor() < paddle_left.ycor() + 40 and ball.ycor() > paddle_left.ycor() - 40):
        ball.setx(-340)
        ball_dx = ball_dx * -1
    win.ontimer(check_ballpos_score, 40)

  
# Main loop 

check_ballpos_score()

我已尝试多种方法保留屏幕,但至今未成功。


问题分析与解决方案

问题核心有两个:

  1. 缺少turtle主事件循环:turtle依赖mainloop()维持窗口运行、处理按键和定时任务,你的代码只触发了一次定时函数就直接退出,导致窗口关闭。
  2. 分数变量未声明全局:修改player_a和player_b时没有声明全局,会导致分数无法正确累加。

修改后的完整代码:

import turtle as t
import time
import os

#Score variables
player_a = 0
player_b = 0

paddle_min_step=15

#create Pong main screen
win = t.Screen()
win.title('Ping Pong Game')
win.bgcolor('black')
win.setup(width=800,height=600)
win.tracer(0)

#create left paddle
paddle_left=t.Turtle()
paddle_left.speed(0)
paddle_left.shape('square')
paddle_left.shapesize(stretch_wid=5,stretch_len=1)
paddle_left.color('yellow')
paddle_left.penup()
paddle_left.goto(-350,0)

#create right paddle
paddle_right=t.Turtle()
paddle_right.speed(0)
paddle_right.shape('square')
paddle_right.shapesize(stretch_wid=5,stretch_len=1)
paddle_right.color('blue')
paddle_right.penup()
paddle_right.goto(350,0)

#create ball
ball=t.Turtle()
ball.speed(0)
ball.shape('circle')
ball.color('white')
ball.penup()
ball.goto(0,0)
ball_dx=1    #variabel for speed of ball in x dir
ball_dy=1     #variabel for speed of ball in y dir

#create pen for score
pen=t.Turtle()
pen.speed(0)
pen.color('skyblue')
pen.penup()
pen.hideturtle()
pen.goto(0,260)
pen.write("Player A: 0                  Player B: 0 ",align="center",font=('Monaco',24,"normal"))

#create paddle actions
def paddle_left_up():
    y=paddle_left.ycor()
    y=y+paddle_min_step
    paddle_left.sety(y)

def paddle_left_down():
    y=paddle_left.ycor()
    y=y-paddle_min_step
    paddle_left.sety(y)

def paddle_right_up():
    y=paddle_right.ycor()
    y=y+paddle_min_step
    paddle_right.sety(y)

def paddle_right_down():
    y=paddle_right.ycor()
    y=y-paddle_min_step
    paddle_right.sety(y)


win.listen()
win.onkeypress(paddle_left_up,"w")
win.onkeypress(paddle_left_down,'x')
win.onkeypress(paddle_right_up,'Up')
win.onkeypress(paddle_right_down,'Down')


def check_ballpos_score():
    global ball_dx, ball_dy, player_a, player_b  # 新增分数变量的全局声明

    win.update()
    ball.setx(ball.xcor()+ball_dx)
    ball.sety(ball.ycor()+ball_dy)

    #setting the borders for the ball
    #for y dir avoid ball is out of screen
    #for x dir check ball out of screen -> score
    if ball.ycor()>290:
        ball.sety(290)
        ball_dy=ball_dy * -1

    if ball.ycor()<-290:
        ball.sety(-290)
        ball_dy=ball_dy * -1

    #ball out of screen left/right check + change score 
    if ball.xcor()>390:
        ball.goto(0,0)
        player_a+=1
        pen.clear()
        pen.goto(0,260)
        pen.write("Player A: {}                  Player B: {} ".format(player_a,player_b),align="center",font=('Monaco',24,"normal"))
        
    if ball.xcor()<-390:
        ball.goto(0,0)
        player_b+=1
        pen.clear()
        pen.goto(0,260)
        pen.write("Player A: {}                  Player B: {} ".format(player_a,player_b),align="center",font=('Monaco',24,"normal"))
         

    #handling collision ball with the paddles
    if(ball.xcor() > 340) and (ball.xcor() < 350) and (ball.ycor() < paddle_right.ycor() + 40 and ball.ycor() > paddle_right.ycor() - 40):
        ball.setx(340)
        ball_dx = ball_dx * -1
       

    if(ball.xcor() < -340) and (ball.xcor() > -350) and (ball.ycor() < paddle_left.ycor() + 40 and ball.ycor() > paddle_left.ycor() - 40):
        ball.setx(-340)
        ball_dx = ball_dx * -1
    win.ontimer(check_ballpos_score, 40)

  
# Main loop 
check_ballpos_score()
win.mainloop()  # 启动turtle主事件循环

关键修改说明

  1. 添加win.mainloop():这是turtle程序的核心,负责维持窗口运行、处理所有交互事件(按键、定时任务),没有它程序会直接执行完毕退出。
  2. 补充全局变量声明:在check_ballpos_score()的global语句中加入player_a和player_b,确保函数内对分数的修改能同步到全局变量,解决分数不更新的问题。

修改后窗口会持续显示,球的运动、碰撞检测、分数更新和按键控制都能正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:37:41