I am a relative new bee in Python coding and exercise myself by coding Pong game. As I had some issues with a stable speed of the ball (by using a win.update() method in a main loop while True: ) I try to use the ontimer function now to get a stable speed of the ball/screen refresh. The issue now is that the screen is shown for a split second and disappears directly. Can anybody help me to overcome that issue ? I hope I programmed the ontimer function correctly. Here is my latest code (I am using VS code as IDE)
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()
I have tried different ways of keeping the screen on, but without luck till now.
Add the following as the last line of your code/file:
win.mainloop()
This turns control over to the turtle event handler. Otherwise, Python falls off the end of the file and returns to the operating system.
My rework of your code including the above fix:
from turtle import Screen, Turtle
PADDLE_MIN_STEP = 30
SCORE_FONT = ('Monaco', 24, 'normal')
SCORE_FORMAT = "Player A: {} Player B: {}"
# Paddle actions
def paddle_left_up():
y = paddle_left.ycor() + PADDLE_MIN_STEP
paddle_left.sety(y)
def paddle_left_down():
y = paddle_left.ycor() - PADDLE_MIN_STEP
paddle_left.sety(y)
def paddle_right_up():
y = paddle_right.ycor() + PADDLE_MIN_STEP
paddle_right.sety(y)
def paddle_right_down():
y = paddle_right.ycor() - PADDLE_MIN_STEP
paddle_right.sety(y)
ball_dx = 1 # variable for speed of ball in x dir
ball_dy = 1 # variable for speed of ball in y dir
# Score variables
player_a = 0
player_b = 0
def check_ballpos_score():
global ball_dx, ball_dy, player_a, player_b
ball.setx(ball.xcor() + ball_dx)
ball.sety(ball.ycor() + ball_dy)
# set 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 *= -1
elif ball.ycor() < -290:
ball.sety(-290)
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.write(SCORE_FORMAT.format(player_a, player_b), align='center', font=SCORE_FONT)
elif ball.xcor() < -390:
ball.goto(0, 0)
player_b += 1
pen.clear()
pen.write(SCORE_FORMAT.format(player_a, player_b), align='center', font=SCORE_FONT)
# handle collision of ball with the paddles
if 340 < ball.xcor() < 360 and paddle_right.ycor() - 50 < ball.ycor() < paddle_right.ycor() + 50:
ball.setx(340)
ball_dx *= -1
elif -340 > ball.xcor() > -360 and paddle_left.ycor() - 50 < ball.ycor() < paddle_left.ycor() + 50:
ball.setx(-340)
ball_dx *= -1
screen.update()
screen.ontimer(check_ballpos_score)
# Pong main screen
screen = Screen()
screen.title('Ping Pong Game')
screen.bgcolor('black')
screen.setup(width=800, height=600)
screen.tracer(0)
# Left paddle
paddle_left = Turtle()
paddle_left.shape('square')
paddle_left.shapesize(stretch_wid=5, stretch_len=1)
paddle_left.color('yellow')
paddle_left.penup()
paddle_left.setx(-350)
# Right paddle
paddle_right = paddle_left.clone()
paddle_right.color('blue')
paddle_right.setx(350)
# Ball
ball = Turtle()
ball.shape('circle')
ball.color('white')
ball.penup()
# Pen for score
pen = Turtle()
pen.hideturtle()
pen.color('skyblue')
pen.penup()
pen.sety(260)
pen.write(SCORE_FORMAT.format(player_a, player_b), align='center', font=SCORE_FONT)
screen.onkeypress(paddle_left_up, 'w')
screen.onkeypress(paddle_left_down, 'x')
screen.onkeypress(paddle_right_up, 'Up')
screen.onkeypress(paddle_right_down, 'Down')
screen.listen()
# Main loop
check_ballpos_score()
screen.mainloop()