4
\$\begingroup\$

I am a new Python programmer, and I am learning how to use the turtle import. I am making some projects, and now I am trying to do a Pong game using turtle.

It is working but not really well; the hitbox and the collisions can be improved. Can you please look at my code and tell me how I can improve it?

Code:

import turtle
import os
import random
import math
#screen
wn = turtle.Screen()
wn.title("PingPangPong")
wn.bgcolor("black")
wn.setup(width = 1.0, height = 1.0)
#Shapes
turtle.register_shape("pong.gif")
#bordure
bordure = turtle.Turtle()
bordure.penup()
bordure.color("white")
bordure.pensize(3)
bordure.ht()
bordure.setposition(-500, 300)
bordure.speed(5)
def bordure1():
 bordure.pendown()
 bordure.fd(1000)
 bordure.pu()
 bordure.setposition(-500,-300)
 bordure.pd()
 bordure.fd(1000)
def filet():
 bordure.pensize(1)
 bordure.setposition(0, -300)
 bordure.setheading(90)
 for i in range (12):
 bordure.fd(26)
 bordure.penup()
 bordure.fd(26)
 bordure.pendown()
bordure1()
filet()
#Ball
ball = turtle.Turtle()
ball.shape("circle")
ball.color("white")
ballspeed = 8
ballheading = random.randint(1,360)
ball.penup()
ball.setheading(ballheading)
ball.speed(0)
#Player 1
player1 = turtle.Turtle()
player1.shape("pong.gif")
player1.turtlesize(2,2)
player1.color("white")
player1.penup()
player1.setposition(-520, 0)
player1.speed(0)
playerspeed = 50
#Player 2
player2 = turtle.Turtle()
player2.shape("pong.gif")
player2.shapesize(5,5)
player2.color("white")
player2.penup()
player2.setposition(520, 0)
player2.speed(0)
playerspeed = 50
#Player 1 Movement
def up():
 y = player1.ycor()
 y += playerspeed
 if y < 270:
 player1.sety(y)
def down():
 y = player1.ycor()
 y -= playerspeed
 if y > -270:
 player1.sety(y) 
#Player 2 movement
def up1():
 y = player2.ycor()
 y += playerspeed
 if y < 280:
 player2.sety(y)
def down1():
 y = player2.ycor()
 y -= playerspeed
 if y > -280:
 player2.sety(y)
#Speed hack
def hack():
 global ballspeed
 if ballspeed == 8:
 ballspeed = 20
 elif ballspeed == 20:
 ballspeed = 8
def start():
 ballheading = random.randint(1,360)
 ball.setposition(0, 0)
 ball.setheading(ballheading)
def distance(t1,t2):
 distance = math.sqrt(math.pow(t1.xcor()-t2.xcor(),2)+math.pow(t1.ycor()-t2.ycor(),2))
 if distance < 45:
 t2.right(91)
def angle():
 print(ball.heading())
#We assign z/s to move the player 1
turtle.listen()
turtle.onkey(up, "z")
turtle.onkey(down,"s")
#We assign up and down arrow to move the player 2
turtle.onkey(up1, "Up")
turtle.onkey(down1,"Down")
#SpeedHack
turtle.onkey(hack, "m")
#Restart
turtle.onkey(start,"p")
#Print the Ball heading
turtle.onkey(angle, "l")
#Player 2 score's
Score1 = 0
s1 = turtle.Turtle()
s1.speed(0)
s1.ht()
s1.color("white")
s1.pu()
s1.setposition(-250, 250)
s1.write(Score1, font=("Arial", 44, "normal"))
#Player 2 score's
Score2 = 0
s2 = turtle.Turtle()
s2.speed(0)
s2.ht()
s2.color("white")
s2.pu()
s2.setposition(250, 250)
s2.write(Score1, font=("Arial", 44, "normal"))
#Mainloop
while True:
 ball.fd(ballspeed)
 degree = ball.heading()
 y = ball.ycor()
 x = ball.xcor()
#We define the border colision 
 if y > 279 or y < -279:
 ball.right(91)
#We define Loose 
 if x > 520:
 ballheading = random.randint(1,360)
 Score1 += 1
 s1.clear()
 s1.write(Score1, font=("Arial", 44, "normal"))
 start()
 if x < -520:
 ballheading = random.randint(1,360)
 Score2 += 1
 s2.clear()
 s2.write(Score2, font=("Arial", 44, "normal"))
 start()
#Colision beetween players and ball 
 distance(player1,ball)
 distance(player2,ball)
turtle.mainloop()
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Mar 10, 2018 at 19:34
\$\endgroup\$
0

1 Answer 1

3
\$\begingroup\$

The major issues I see with your code are:

  • Use of while True: in an event driven environment. We need to put the ball on a timer event instead.

  • The angle of bounce off the sides of the court is unrealistic. You can't simply ball.right(91) as which way you turns depends on your original direction. We can reflect the heading instead.

  • Ditto for the bouncing off the players. Also, the initial ball angle is too broad and leads to unplayable scenarios.

My rework of your code attempts to address these issues as well as clean up the code style-wise:

from turtle import Turtle, Screen
from random import randint, choice
ballspeed = 8
playerspeed = 50
cursor_size = 20
player_height = 60
player_width = 20
court_width = 1000
court_height = 600
FONT = ("Arial", 44, "normal")
def draw_border():
 border.pensize(3)
 border.penup()
 border.setposition(-court_width/2, court_height/2)
 border.pendown()
 border.forward(court_width)
 border.penup()
 border.sety(-court_height/2)
 border.pendown()
 border.backward(court_width)
def filet():
 border.penup()
 border.pensize(1)
 border.setposition(0, -court_height/2)
 border.setheading(90)
 border.pendown()
 for _ in range(court_height // 50):
 border.forward(50 / 2 + 1)
 border.penup()
 border.forward(50 / 2 + 1)
 border.pendown()
# Player 1 Movement
def up1():
 y = player1.ycor()
 y += playerspeed
 if y < court_height/2 - player_height/2:
 player1.sety(y)
def down1():
 y = player1.ycor()
 y -= playerspeed
 if y > player_height/2 - court_height/2:
 player1.sety(y)
# Player 2 movement
def up2():
 y = player2.ycor()
 y += playerspeed
 if y < court_height/2 - player_height/2:
 player2.sety(y)
def down2():
 y = player2.ycor()
 y -= playerspeed
 if y > player_height/2 - court_height/2:
 player2.sety(y)
def reset_ball():
 ball.setposition(0, 0)
 ball.setheading(choice([0, 180]) + randint(-60, 60))
def distance(t1, t2):
 my_distance = t1.distance(t2)
 if my_distance < player_height/2:
 t2.setheading(180 - t2.heading())
 t2.forward(ballspeed)
# Mainloop
def move():
 global score1, score2
 ball.forward(ballspeed)
 x, y = ball.position()
 if x > court_width/2 + cursor_size: # We define scoring
 score1 += 1
 s1.undo()
 s1.write(score1, font=FONT)
 reset_ball()
 elif x < cursor_size - court_width/2:
 score2 += 1
 s2.undo()
 s2.write(score2, font=FONT)
 reset_ball()
 elif y > court_height/2 - cursor_size or y < cursor_size - court_height/2:
 # We define the border collision
 ball.setheading(-ball.heading())
 else:
 # Check collision between players and ball
 distance(player1, ball)
 distance(player2, ball)
 screen.ontimer(move, 20)
# screen
screen = Screen()
screen.title("Pong")
screen.bgcolor("black")
screen.setup(width=1.0, height=1.0)
# border
border = Turtle(visible=False)
border.speed('fastest')
border.color("white")
draw_border()
filet()
# Ball
ball = Turtle("circle")
ball.color("white")
ball.penup()
ball.speed("fastest")
reset_ball()
# Player 1
player1 = Turtle("square")
player1.turtlesize(player_height / cursor_size, player_width / cursor_size)
player1.color("white")
player1.penup()
player1.setx(cursor_size - court_width/2)
player1.speed("fastest")
# Player 2
player2 = Turtle("square")
player2.shapesize(player_height / cursor_size, player_width / cursor_size)
player2.color("white")
player2.penup()
player2.setx(court_width/2 + cursor_size)
player2.speed("fastest")
# Player 1 score
score1 = 0
s1 = Turtle(visible=False)
s1.speed("fastest")
s1.color("white")
s1.penup()
s1.setposition(-court_width/4, court_height/3)
s1.write(score1, font=FONT)
# Player 2 score"s
score2 = 0
s2 = Turtle(visible=False)
s2.speed("fastest")
s2.color("white")
s2.penup()
s2.setposition(court_width/4, court_height/3)
s2.write(score2, font=FONT)
# We assign s/z to move the player 1
screen.onkey(up1, "s")
screen.onkey(down1, "z")
# We assign up and down arrow to move the player 2
screen.onkey(up2, "Up")
screen.onkey(down2, "Down")
# Restart
screen.onkey(reset_ball, "p")
screen.listen()
move()
screen.mainloop()

Not perfect, but playable. I've tossed some of your original details to simplify my example. You should be able to add them back as desired.

answered Mar 11, 2018 at 7:36
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.