turtle graphics goto() not working correctly - python

there are two paddles and a ball in a pong game the ball doesn't go back to 0, 0 after hitting right border in this game the whole script isnt finished yet only a bit I assume it has something to do with the goto() command but i do not know as i am new to python please help me figure this out here is the script of the game:
import turtle
wn = turtle.Screen()
wn.title('Pong by me')
wn.bgcolor('black')
wn.setup(width=800, height=600)
wn.tracer(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 = 2
ball.dy = -2
# Function
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)
# 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')
# 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
if ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
if ball.xcor() > 390:
ball.goto(0, 0)
ball.dx += -1

I guess your border checking should look like this
# Border checking
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
if ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
if ball.xcor() > 390:
ball.goto(0, 0)
ball.dx *= -1
if ball.xcor() < -390:
ball.goto(0, 0)
ball.dx *= -1
Then it works as expected

Related

Move an object based on where your cursor is

I made a basic pong by going through a tutorial and tweaking a few things, currently I'd like the left paddle which is the variable paddle_a to be moved based on where the cursor is while still maintaining its x value. Or, in other words, moving up and down based on the y value of the mouse. I've looked around the internet and couldn't find anything that would help me in this case so help would be appreciated.
import turtle
wn = turtle.Screen()
wn.title("Pong")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(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=0.5)
paddle_a.penup()
paddle_a.goto(-380, 0)
# Ball
ball = turtle.Turtle()
ball.speed(0)
ball.shape("square")
ball.color("white")
ball.shapesize(stretch_len=0.75, stretch_wid=0.75)
ball.penup()
ball.goto(0, 0)
ball.dx = 0.3
ball.dy = 0.3
# Functions
def paddle_a_up():
y = paddle_a.ycor()
y += 10
paddle_a.sety(y)
def paddle_a_down():
y = paddle_a.ycor()
y -= 10
paddle_a.sety(y)
# Keybinding
wn.listen()
wn.onkeypress(paddle_a_up, "w")
wn.onkeypress(paddle_a_down, "s")
# 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
if ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
if ball.xcor() > 390:
ball.goto(0, 0)
ball.dx *= -1
if ball.xcor() < -390:
ball.goto(0, 0)
ball.dx *= -1
Here's a simple approach using the mouse ondrag() event on the paddle instead of key events. Click and hold on the paddle while you move it up and down. The ball will continue to move independently:
from turtle import Screen, Turtle
# Functions
def paddle_move(x, y):
paddle_a.sety(y)
screen = Screen()
screen.title("Pong")
screen.bgcolor("black")
screen.setup(width=800, height=600)
screen.tracer(0)
# Paddle A
paddle_a = Turtle()
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.shapesize(stretch_wid=5, stretch_len=0.5)
paddle_a.penup()
paddle_a.setx(-380)
# Ball
ball = Turtle()
ball.shape("square")
ball.color("white")
ball.shapesize(stretch_len=0.75, stretch_wid=0.75)
ball.penup()
ball.dx = 1.3 # user defined properties
ball.dy = 1.3
# Keybinding
paddle_a.ondrag(paddle_move)
# Main game loop
def play():
# 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
elif ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
if not -390 <= ball.xcor() <= 390:
ball.goto(0, 0)
ball.dx *= -1
screen.update()
screen.ontimer(play)
play()
screen.mainloop()

After taking turtle to other turtle's y coordinate, the program crashes. Any fixes?

Here's the full code
import os
wn = turtle.Screen()
wn.title("Pong")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0)
# Score
score_a = 0
score_b = 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.5
ball.dy = 0.5
# Pen
pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("Player 1: 0 Player 2: 0", align="center", font=("Impact", 24, "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)
# Keyboard bindings
wn.listen()
wn.onkeypress(paddle_a_up, "w")
wn.onkeypress(paddle_a_down, "s")
# Main game loop
while True:
wn.update()
# Computer player
if ball.xcor() > 250:
paddle_b.goto (ball.ycor())
# Move the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Border checking
# Top and bottom
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
os.system("afplay bounce.wav&")
elif ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
os.system("afplay bounce.wav&")
# Left and right
if ball.xcor() > 350:
score_a += 1
pen.clear()
pen.write("Player 1: {} Player 2: {}".format(score_a, score_b), align="center", font=("Impact", 24, "normal"))
ball.goto(0, 0)
ball.dx *= -1
elif ball.xcor() < -350:
score_b += 1
pen.clear()
pen.write("Player 1: {} Player 2: {}".format(score_a, score_b), align="center", font=("Impact", 24, "normal"))
ball.goto(0, 0)
ball.dx *= -1
# Paddle and ball collisions
if ball.xcor() < -340 and ball.ycor() < paddle_a.ycor() + 50 and ball.ycor() > paddle_a.ycor() - 50:
ball.dx *= -1
os.system("afplay bounce.wav&")
elif ball.xcor() > 340 and ball.ycor() < paddle_b.ycor() + 50 and ball.ycor() > paddle_b.ycor() - 50:
ball.dx *= -1
os.system("afplay bounce.wav&")
I'm trying to make a computer player with # Computer player
if ball.xcor() > 250:
paddle_b.goto (ball.ycor())
Each time the ball's xcor gets passed 250, the program crashes. Any fixes?
It wont let me post till I have more text ignore this please
It wont let me post till I have more text ignore this please
It wont let me post till I have more text ignore this please
I always feel like
Somebodys watching meee
And I got no privacy
Oh Oh Oh
So, your main problem is that paddle_b.goto uses an x/y point, not just the y-coordinate which you're inputting from the ball.
This should be giving you the error:
Traceback (most recent call last):
File "<Path>", line 85, in <module>
paddle_b.goto(ball.ycor())
File "<Path>\turtle.py", line 1774, in goto
self._goto(Vec2D(*x))
TypeError: type object argument after * must be an iterable, not float
From the documentation of goto ( https://docs.python.org/3.3/library/turtle.html?highlight=turtle#turtle.goto ):
If y is None, x must be a pair of coordinates or a Vec2D (e.g. as returned by pos()).
You should be able to do: paddle_b.sety(ball.ycor()) instead, which only needs the y-coordinate and you use already. Alternatively, another way to solve this is to keep the X-coordinate of the paddle the same through: paddle_b.goto(paddle_b.xcor(), ball.ycor()).

Python executable (pyinstaller) throws an error when I close it

I created a basic Pong game with Turtle on Windows, which works pretty well, but every time I close it, it throws an error: 'Fatal error detected: Failed to execute script pong'. I have been looking for a solution prior to ask for help, but I couldn't find a proper answer.
In order to create the .exe file I used 'pyinstaller'. This was the exact command I wrote:
pyinstaller --onefile --windowed --add-data "bounce.wav;." --add-data "collision.wav;." --add-data "score.wav;." pong.py
This is my code:
"""
Basic pong game
"""
import turtle
import winsound
import os
import sys
win = turtle.Screen()
win.title("Pong")
win.bgcolor("black")
win.setup(width=800, height=600)
win.tracer(0)
# Score
score_a = 0
score_b = 0
# Paddle A
paddle_a = turtle.Turtle()
name_a = "Verde"
paddle_a.speed(0)
paddle_a.shape("square")
paddle_a.color("green")
paddle_a.shapesize(stretch_wid=5, stretch_len=1)
paddle_a.penup()
paddle_a.goto(-350, 0)
# Paddle B
paddle_b = turtle.Turtle()
name_b = "Amarillo"
paddle_b.speed(0)
paddle_b.shape("square")
paddle_b.color("yellow")
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("circle")
ball.color("white")
ball.penup()
ball.goto(0, 0)
ball.dx = 0.15
ball.dy = -0.15
# Pen
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("{} 0 | 0 {}".format(name_a, name_b), align="center", font=("Courier", 24, "normal"))
# Functions
def resource_path(relative_path):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath('.'), relative_path)
def paddle_a_up():
if paddle_a.ycor() < 240:
y = paddle_a.ycor()
y += 20
paddle_a.sety(y)
def paddle_a_down():
if paddle_a.ycor() > -240:
y = paddle_a.ycor()
y -= 20
paddle_a.sety(y)
def paddle_b_up():
if paddle_b.ycor() < 240:
y = paddle_b.ycor()
y += 20
paddle_b.sety(y)
def paddle_b_down():
if paddle_b.ycor() > -240:
y = paddle_b.ycor()
y -= 20
paddle_b.sety(y)
# Keyboard binding
win.listen()
win.onkeypress(paddle_a_up, "w")
win.onkeypress(paddle_a_down, "s")
win.onkeypress(paddle_b_up, "Up")
win.onkeypress(paddle_b_down, "Down")
# Main game loop
while True:
win.update()
# Move the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Border checking
if ball.ycor() > 290:
winsound.PlaySound(resource_path("bounce.wav"), winsound.SND_ASYNC)
ball.sety(290)
ball.dy *= -1
if ball.ycor() < -290:
winsound.PlaySound(resource_path("bounce.wav"), winsound.SND_ASYNC)
ball.sety(-290)
ball.dy *= -1
if ball.xcor() > 390:
winsound.PlaySound(resource_path("score.wav"), winsound.SND_ASYNC)
ball.goto(0, 0)
ball.dx *= -1
score_a += 1
pen.clear()
pen.write("{} {} | {} {}".format(name_a, score_a, score_b, name_b), align="center", font=("Courier", 24, "normal"))
if ball.xcor() < -390:
winsound.PlaySound(resource_path("score.wav"), winsound.SND_ASYNC)
ball.goto(0, 0)
ball.dx *= -1
score_b += 1
pen.clear()
pen.write("{} {} | {} {}".format(name_a, score_a, score_b, name_b), align="center", font=("Courier", 24, "normal"))
# Paddle and ball collisions
if (ball.xcor() > 340 and ball.xcor() < 350) and (ball.ycor() < paddle_b.ycor() + 50 and ball.ycor() > paddle_b.ycor() - 50):
winsound.PlaySound(resource_path("collision.wav"), winsound.SND_ASYNC)
ball.setx(340)
ball.dx *= -1
if (ball.xcor() < -340 and ball.xcor() > -350) and (ball.ycor() < paddle_a.ycor() + 50 and ball.ycor() > paddle_a.ycor() - 50):
winsound.PlaySound(resource_path("collision.wav"), winsound.SND_ASYNC)
ball.setx(-340)
ball.dx *= -1
"""
End code
"""
I have no clue what may cause that error, since the program runs fine and all the sound effects work correctly.
Thank you all for your answers!
Hey not sure if you still need help on this but line 103 seems to be causing issues:
ball.setx(ball.xcor() + ball.dx)
It only occurs when closing the application, like you said.
I'm not sure if there is a proper solution but a bandaid solution you can use to avoid pyinstaller from throwing errors is to wrap the entire while loop in a try/catch.
# Main game loop
try:
while True:
win.update()
# Move the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Border checking
if ball.ycor() > 290:
winsound.PlaySound(resource_path("bounce.wav"), winsound.SND_ASYNC)
ball.sety(290)
ball.dy *= -1
if ball.ycor() < -290:
winsound.PlaySound(resource_path("bounce.wav"), winsound.SND_ASYNC)
ball.sety(-290)
ball.dy *= -1
if ball.xcor() > 390:
winsound.PlaySound(resource_path("score.wav"), winsound.SND_ASYNC)
ball.goto(0, 0)
ball.dx *= -1
score_a += 1
pen.clear()
pen.write("{} {} | {} {}".format(name_a, score_a, score_b, name_b), align="center", font=("Courier", 24, "normal"))
if ball.xcor() < -390:
winsound.PlaySound(resource_path("score.wav"), winsound.SND_ASYNC)
ball.goto(0, 0)
ball.dx *= -1
score_b += 1
pen.clear()
pen.write("{} {} | {} {}".format(name_a, score_a, score_b, name_b), align="center", font=("Courier", 24, "normal"))
# Paddle and ball collisions
if (ball.xcor() > 340 and ball.xcor() < 350) and (ball.ycor() < paddle_b.ycor() + 50 and ball.ycor() > paddle_b.ycor() - 50):
winsound.PlaySound(resource_path("collision.wav"), winsound.SND_ASYNC)
ball.setx(340)
ball.dx *= -1
if (ball.xcor() < -340 and ball.xcor() > -350) and (ball.ycor() < paddle_a.ycor() + 50 and ball.ycor() > paddle_a.ycor() - 50):
winsound.PlaySound(resource_path("collision.wav"), winsound.SND_ASYNC)
ball.setx(-340)
ball.dx *= -1
except Exception:
sys.exit(0)
It's not the best solution I admit, but I hope this helps!

Python returns an error when i try to quit the application window

I was following a video for this little project but i encountered this error
Traceback (most recent call last):
File "C:/Users/Dell/Desktop/Pygame/games/pong.py", line 92, in <module>
ball.setx(ball.xcor()+ball.dx)
File "C:\Users\Dell\AppData\Local\Programs\Python\Python37-32\lib\turtle.py", line 1808, in setx
self._goto(Vec2D(x, self._position[1]))
File "C:\Users\Dell\AppData\Local\Programs\Python\Python37-32\lib\turtle.py", line 3158, in _goto
screen._pointlist(self.currentLineItem),
File "C:\Users\Dell\AppData\Local\Programs\Python\Python37-32\lib\turtle.py", line 755, in _pointlist
cl = self.cv.coords(item)
File "<string>", line 1, in coords
File "C:\Users\Dell\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 2469, in coords
self.tk.call((self._w, 'coords') + args))]
_tkinter.TclError: invalid command name ".!canvas"
This happens when I press the exit button to close the window.
How to solve this?
Here's the code:
import turtle
wn = turtle.Screen()
wn.title("Pong")
wn.bgcolor('black')
wn.setup(width=800, height=600)
wn.tracer(0)
#Score
score_a = 0
score_b = 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("circle")
ball.color("white")
ball.penup()
ball.goto(0,0)
ball.dx = 0.5
ball.dy = 0.5
#pen
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0,260)
pen.write("Player A: 0 Player B: 0", align="center", font=('Courier', 24, "normal"))
#Function
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)
#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")
running = True
#main game loop
while running:
wn.update()
#move the ball
ball.setx(ball.xcor()+ball.dx)
ball.sety(ball.ycor()+ball.dy)
#border
if ball.ycor() > 280:
ball.sety(280)
ball.dy*=-1
if ball.ycor() < -280:
ball.sety(-280)
ball.dy*=-1
if ball.xcor() > 380:
ball.goto(0,0)
ball.dx*=-1
score_a+=1
pen.clear()
pen.write(f"Player A: {score_a} Player B: {score_b}", align="center", font=('Courier', 24, "normal"))
if ball.xcor() < -380:
ball.goto(0,0)
ball.dx*=-1
score_b += 1
pen.clear()
pen.write(f"Player A: {score_a} Player B: {score_b}", align="center", font=('Courier', 24, "normal"))
#colliosion
if (ball.xcor() > 330 and ball.xcor() < 340) and (ball.ycor() < paddle_b.ycor() + 50 and ball.ycor() > paddle_b.ycor() -50):
ball.setx(330)
ball.dx*=-1
if (ball.xcor() < -330 and ball.xcor() > -340) and (ball.ycor() < paddle_a.ycor() + 50 and ball.ycor() > paddle_a.ycor() -50):
ball.setx(-330)
ball.dx*=-1
i read about putting the .mainloop() method but i couldn't figure out where do i put it. I understand this much that the while loop runs forever and has no condition to stop here so how do i make the loop stop? How do i tell python to stop the loop and quit the window after pressing the exit button?
It looks like turtle uses tkinter. In Tk there's a method named protocol which you can use to control what happens when certain events happen, one of those being hitting the red 'X'.
In order to invoke that we need to get the root level window.
Placing
canvas = wn.getcanvas()
root = canvas.winfo_toplevel()
will set root as your root window.
From here you can use root.protocol("WM_DELETE_WINDOW", on_close) to invoke a function named on_close or whatever you want to name it.
Your function will probably look something like this.
def on_close():
global running
running = False
This will break you out of your loop and close your program.
Full Code.
import turtle
wn = turtle.Screen()
canvas = wn.getcanvas()
root = canvas.winfo_toplevel()
wn.title("Pong")
wn.bgcolor('black')
wn.setup(width=800, height=600)
wn.tracer(0)
#Score
score_a = 0
score_b = 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("circle")
ball.color("white")
ball.penup()
ball.goto(0,0)
ball.dx = 0.5
ball.dy = 0.5
#pen
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0,260)
pen.write("Player A: 0 Player B: 0", align="center", font=('Courier', 24, "normal"))
#Function
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)
#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")
def on_close():
global running
running = False
root.protocol("WM_DELETE_WINDOW", on_close)
running = True
#main game loop
while running:
wn.update()
#move the ball
ball.setx(ball.xcor()+ball.dx)
ball.sety(ball.ycor()+ball.dy)
#border
if ball.ycor() > 280:
ball.sety(280)
ball.dy*=-1
if ball.ycor() < -280:
ball.sety(-280)
ball.dy*=-1
if ball.xcor() > 380:
ball.goto(0,0)
ball.dx*=-1
score_a+=1
pen.clear()
pen.write(f"Player A: {score_a} Player B: {score_b}", align="center", font=('Courier', 24, "normal"))
if ball.xcor() < -380:
ball.goto(0,0)
ball.dx*=-1
score_b += 1
pen.clear()
pen.write(f"Player A: {score_a} Player B: {score_b}", align="center", font=('Courier', 24, "normal"))
#colliosion
if (ball.xcor() > 330 and ball.xcor() < 340) and (ball.ycor() < paddle_b.ycor() + 50 and ball.ycor() > paddle_b.ycor() -50):
ball.setx(330)
ball.dx*=-1
if (ball.xcor() < -330 and ball.xcor() > -340) and (ball.ycor() < paddle_a.ycor() + 50 and ball.ycor() > paddle_a.ycor() -50):
ball.setx(-330)
ball.dx*=-1
We can solve this problem from within turtle, no need to drop down to tkinter underpinnings. Generally, you need to play by the rules. Specifically, no while running: aka while True:. Turtle is an event-based environment and you're not letting events get handled properly and thus the error messages.
Instead of the while loop, we need an ontimer() event:
from turtle import Screen, Turtle
FONT = ('Courier', 24, 'normal')
# Score
score_a = 0
score_b = 0
# Function
def paddle_a_up():
paddle_a.sety(paddle_a.ycor() + 20)
def paddle_a_down():
paddle_a.sety(paddle_a.ycor() - 20)
def paddle_b_up():
paddle_b.sety(paddle_b.ycor() + 20)
def paddle_b_down():
paddle_b.sety(paddle_b.ycor() - 20)
def single_step():
global score_a, score_b
# move the ball
ball.setposition(ball.xcor() + ball.dx, ball.ycor() + ball.dy)
# border
if ball.ycor() > 280:
ball.sety(280)
ball.dy *= -1
elif ball.ycor() < -280:
ball.sety(-280)
ball.dy *= -1
if ball.xcor() > 380:
ball.goto(0, 0)
ball.dx *= -1
score_a += 1
pen.clear()
pen.write(f"Player A: {score_a} Player B: {score_b}", align='center', font=FONT)
if ball.xcor() < -380:
ball.goto(0, 0)
ball.dx *= -1
score_b += 1
pen.clear()
pen.write(f"Player A: {score_a} Player B: {score_b}", align='center', font=FONT)
# collision
if 330 < ball.xcor() < 340 and paddle_b.ycor() - 50 < ball.ycor() < paddle_b.ycor() + 50:
ball.setx(330)
ball.dx *= -1
elif -340 < ball.xcor() < -330 and paddle_a.ycor() - 50 < ball.ycor() < paddle_a.ycor() + 50:
ball.setx(-330)
ball.dx *= -1
screen.update()
screen.ontimer(single_step)
screen = Screen()
screen.title('Pong')
screen.bgcolor('black')
screen.setup(width=800, height=600)
screen.tracer(0)
# paddle A
paddle_a = Turtle()
paddle_a.shape('square')
paddle_a.color('white')
paddle_a.shapesize(stretch_wid=5, stretch_len=1)
paddle_a.penup()
paddle_a.setx(-350)
# paddle B
paddle_b = Turtle()
paddle_b.shape('square')
paddle_b.color('white')
paddle_b.shapesize(stretch_wid=5, stretch_len=1)
paddle_b.penup()
paddle_b.setx(350)
# Ball
ball = Turtle()
ball.shape('circle')
ball.color('white')
ball.penup()
ball.dx = 1
ball.dy = 1
# pen
pen = Turtle()
pen.hideturtle()
pen.color('white')
pen.penup()
pen.sety(260)
pen.write("Player A: 0 Player B: 0", align='center', font=FONT)
# Keyboard binding
screen.onkeypress(paddle_a_up, 'w')
screen.onkeypress(paddle_a_down, 's')
screen.onkeypress(paddle_b_up, 'Up')
screen.onkeypress(paddle_b_down, 'Down')
screen.listen()
single_step()
screen.mainloop()
Now when you close the window, that event will be handled by the same mainloop event handler that's running your game.

Looking to add an AI player in Python Pong using Turtle

I can't seem to get my AI pong paddle to work in Python 3.7.1. I'll admit that I'm new to this so the fix may be easier than I'm making it.
I've tried various forms of adjusting the loops but i think i'm missing something small that plays a big role in the code's processing.
import turtle
# build window
win = turtle.Screen()
# window title/color/size
win.title("csc2280 Project")
win.bgcolor("black")
win.setup(width=800, height=800)
win.tracer(0)
# user paddle
user_paddle = turtle.Turtle()
# user paddle build
user_paddle.shape('square')
user_paddle.shapesize(stretch_wid=5, stretch_len=1)
user_paddle.speed('fastest')
user_paddle.color("white")
# user paddle position
user_paddle.penup()
user_paddle.goto(-350, 0)
# ai paddle
AI_paddle = turtle.Turtle()
# ai paddle build
AI_paddle.shape('square')
AI_paddle.shapesize(stretch_wid=5, stretch_len=1)
AI_paddle.speed('fastest')
AI_paddle.color('white')
#ai paddle position
AI_paddle.penup()
AI_paddle.goto(350, 0)
AI_paddle.speed = 15
# ball
ball = turtle.Turtle()
ball.speed(0)
# ball shape
ball.shape('circle')
ball.color('white')
# ball position
ball.penup()
ball.goto(0, 0)
# ball movement
ball.dx = 2
ball.dy = 2
# Pen
pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("Player A: 0 Player B: 0", align = "center", font = ("Calibri", 24, "normal"))
# Keeping Score
score_p1 = 0
score_p2 = 0
# move user paddle up and down
# user paddle up
def user_paddle_up():
y = user_paddle.ycor()
y += 20
user_paddle.sety(y)
# user paddle down
def user_paddle_down():
y = user_paddle.ycor()
y -= 20
user_paddle.sety(y)
# actually moving the paddle
win.listen()
win.onkeypress(user_paddle_up, "Up")
win.onkeypress(user_paddle_down, "Down")
AI_paddle.forward(AI_paddle.speed)
y = AI_paddle.ycor()
if y < -300 or y > 300:
AI_paddle.speed *= -1
I think the issue is right in here somewhere.
# game loop
while True:
win.update()
# moving the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# create border
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
if ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
if ball.xcor() > 390:
ball.goto(0,0)
ball.dx *= -1
# updating score
score_p1 += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_p1, score_p2), align = "center", font = ("Calibri", 24, "normal"))
if ball.xcor() < -400:
ball.goto(0,0)
ball.dx *= -1
# updating score
score_p2 += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_p1, score_p2), align = "center", font = ("Calibri", 24, "normal"))
# paddle/ball interaction
if (ball.xcor() > 340 and ball.xcor() < 350) and (ball.ycor() < AI_paddle.ycor() + 40 and ball.ycor() > AI_paddle.ycor() -40):
ball.setx(340)
ball.dx *= -1
if (ball.xcor() < -340 and ball.xcor() > -350) and (ball.ycor() < user_paddle.ycor() + 40 and ball.ycor() > user_paddle.ycor() -40):
ball.setx(-340)
ball.dx *= -1
Any help would be super appreciated as this is my final project for the semester and this is literally the only thing holding me up.
The problem I found with your AI player is that this code is in the wrong place:
AI_paddle.forward(AI_paddle.speed)
y = AI_paddle.ycor()
if y < -300 or y > 300:
AI_paddle.speed *= -1
It's just before the main loop so it only gets executed once. It should be inside the main loop, e.g. as the last item.
I found your game difficult to play so I've tweaked some things below to make it more playable and I've made the fix I described above:
from turtle import Screen, Turtle
FONT = ("Calibri", 24, "normal")
# move user paddle up and down
# user paddle up
def user_paddle_up():
y = user_paddle.ycor() + 20
user_paddle.sety(y)
# user paddle down
def user_paddle_down():
y = user_paddle.ycor() - 20
user_paddle.sety(y)
# build window
win = Screen()
# window title/color/size
win.title("csc2280 Project")
win.bgcolor("black")
win.setup(width=800, height=800)
win.tracer(0)
# user paddle
user_paddle = Turtle('square')
# user paddle build
user_paddle.shapesize(stretch_wid=5, stretch_len=1)
user_paddle.color("white")
# user paddle position
user_paddle.penup()
user_paddle.setx(-350)
# AI paddle
AI_paddle = Turtle('square')
# AI paddle build
AI_paddle.shapesize(stretch_wid=5, stretch_len=1)
AI_paddle.color('white')
# AI paddle position
AI_paddle.penup()
AI_paddle.setx(350)
AI_paddle.speed = 10
# ball
ball = Turtle('circle')
# ball shape
ball.color('white')
# ball position
ball.penup()
# ball movement
ball.dx = 2
ball.dy = 2
# Court
court = Turtle(visible=False)
court.color("white")
court.penup()
court.goto(-400, -300)
court.pendown()
court.forward(800)
court.penup()
court.goto(-400, 300)
court.pendown()
court.forward(800)
court.penup()
# Pen
pen = Turtle(visible=False)
pen.color("white")
pen.penup()
pen.sety(325)
pen.write("Player A: 0 Player B: 0", align="center", font=("Calibri", 24, "normal"))
# Keeping Score
score_p1 = 0
score_p2 = 0
# actually moving the paddle
win.onkeypress(user_paddle_up, "Up")
win.onkeypress(user_paddle_down, "Down")
win.listen()
# game loop
while True:
win.update()
# moving the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# enforce boundaries
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
elif ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
if ball.xcor() > 390:
ball.goto(0, 0)
ball.dx *= -1
# updating score
score_p1 += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_p1, score_p2), align="center", font=FONT)
elif ball.xcor() < -390:
ball.goto(0, 0)
ball.dx *= -1
# updating score
score_p2 += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_p1, score_p2), align="center", font=FONT)
# paddle/ball interaction
if (330 < ball.xcor() < 370) and (AI_paddle.ycor() - 60 < ball.ycor() < AI_paddle.ycor() + 60):
ball.setx(330)
ball.dx = - abs(ball.dx)
if (-370 < ball.xcor() < -330) and (user_paddle.ycor() - 60 < ball.ycor() < user_paddle.ycor() + 60):
ball.setx(-330)
ball.dx = abs(ball.dx)
y = AI_paddle.ycor() + AI_paddle.speed
if y < -240 or y > 240:
AI_paddle.speed *= -1
AI_paddle.sety(y)
Good luck with making your AI player smarter!

Categories

Resources