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()
\$\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.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.