python - penalty game how to speed up element - python

I've created simple penalty game and all works fine but I want to improve it a bit. Goal moves on sides itself and want I want to do is speeding it up when scored. I understand when dx is negative it must be += 1 and if dx is positive it must be opposite so += -1. I thought about for loop for dx in range(-270, 0, -270) and the second one for prositive variables. I'm beginner in python and programming itself, so I appreciate any advice. I want to speed up SL, SP and P. Those objects create the goal.
import turtle
import time
sd = 0.1
wn = turtle.Screen()
wn.bgcolor("black")
wn.title("karne")
wn.setup(width=800, height=600)
wn.tracer(0)
#pilka
ball = turtle.Turtle()
ball.shape("circle")
ball.color("green")
ball.speed(0)
ball.penup()
ball.goto(0, -275)
ball.direction = "stop"
score = 0
miss = 0
#scoring
pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 0)
#slupek lewy
sl = turtle.Turtle()
sl.shape("square")
sl.color("white")
sl.shapesize(stretch_wid=3, stretch_len=1)
sl.speed(0)
sl.penup()
sl.goto(-80, 270)
sl.dx = sd
#slupek prawy
sp = turtle.Turtle()
sp.shape("square")
sp.color("white")
sp.shapesize(stretch_wid=3, stretch_len=1)
sp.speed(0)
sp.penup()
sp.goto(80, 270)
sp.dx = sd
#poprzeczka
p = turtle.Turtle()
p.shape("square")
p.color("white")
p.shapesize(stretch_wid=7, stretch_len=1)
p.speed(0)
p.seth(90)
p.penup()
p.goto(0, 290)
p.dx = sd
score = 0
miss = 0
#function
def right():
x = ball.xcor()
x +=20
ball.setx(x)
def left():
x = ball.xcor()
x -=20
ball.setx(x)
def shoot():
ball.direction = "up"
def shoot2():
ball.direction = "stop"
def shoot1():
if ball.direction == "up":
y = ball.ycor()
ball.sety(y+0.5)
#binds
wn.listen()
wn.onkeypress(right, "d")
wn.onkeypress(left, "a")
wn.onkeypress(shoot, "space")
while True:
#goal moving
sl.setx(sl.xcor() + sl.dx)
sp.setx(sp.xcor() + sp.dx)
p.setx(p.xcor() + p.dx)
#goal borders check
if sl.xcor() > 250:
sl.setx(250)
sl.dx *= -1
if sl.xcor() < -390:
sl.setx(-390)
sl.dx *= -1
if sp.xcor() > 390:
sp.setx(390)
sp.dx *= -1
if sp.xcor() < -250:
sp.setx(-250)
sp.dx *= -1
if p.xcor() > 320:
p.setx(320)
p.dx *= -1
if p.xcor() < -320:
p.setx(-320)
p.dx *= -1
#ball and goal check
if (ball.ycor() > 270 and ball.ycor() < 280) and (ball.xcor() < p.xcor() + 50 and ball.xcor() > p.xcor() -40):
score += 1
pen.clear()
pen.write("Score:{} Miss:{} ".format(score, miss), align="center", font=("Courier", 24, "normal"))
shoot2()
ball.goto(0, -275)
if ball.ycor() > 295:
miss += 1
ball.goto(0, -275)
score = 0
pen.clear()
pen.write("Score:{} Miss:{} ".format(score, miss), align="center", font=("Courier", 24, "normal"))
shoot2()
shoot1()
wn.update()

With a program like this, the fewer objects you try to move in real time, the better. Your goal is three pieces that have to be be moved in unison. The primary fix below is to define the goal as a turtle shape so the goal is only one piece that needs to be manipulated. The secondary fix below is to replace while True:, which has no place in an event-driven world, with a timed event:
from turtle import Screen, Turtle
sd = 1.0
FONT = ("Courier", 24, "normal")
def right():
ball.forward(20)
def left():
ball.backward(20)
def shoot():
ball.direction = "up"
def shoot2():
ball.direction = "stop"
def shoot1():
if ball.direction == "up":
ball.sety(ball.ycor() + sd * 2)
wn = Screen()
wn.bgcolor("black")
wn.title("karne")
wn.setup(width=800, height=600)
wn.tracer(False)
wn.register_shape("goal", ((-90, 30), (90, 30), (90, -30), (70, -30), (70, 10), (-70, 10), (-70, -30), (-90, -30)))
# pilka
ball = Turtle("circle")
ball.color("green")
ball.speed('fastest')
ball.penup()
ball.sety(-275)
ball.direction = "stop"
# scoring
pen = Turtle(visible=False)
pen.speed('fastest')
pen.color("white")
pen.penup()
# poprzeczka
p = Turtle("goal")
p.color("white")
p.speed('fastest')
p.seth(90)
p.penup()
p.sety(270)
p.dx = sd
score = 0
miss = 0
# binds
wn.onkeypress(right, "d")
wn.onkeypress(left, "a")
wn.onkeypress(shoot, "space")
wn.listen()
def move():
global score, miss
# goal moving
p.setx(p.xcor() + p.dx)
# goal borders check
if p.xcor() > 330:
p.setx(330)
p.dx *= -1
elif p.xcor() < -330:
p.setx(-330)
p.dx *= -1
# ball and goal check
if 270 < ball.ycor() < 280 and ball.distance(p) < 50:
score += 1
pen.clear()
pen.write("Score:{} Miss:{} ".format(score, miss), align="center", font=FONT)
shoot2()
ball.goto(0, -275)
elif ball.ycor() > 295:
miss += 1
score = 0
pen.clear()
pen.write("Score:{} Miss:{} ".format(score, miss), align="center", font=FONT)
shoot2()
ball.goto(0, -275)
shoot1()
wn.update()
wn.ontimer(move, 25)
move()
wn.tracer(True)
wn.mainloop()
Plus lots of other little fixes to streamline the code.

Related

Pong via Python Turtle issues

I've been looking at this for hours and can't figure out why it won't run properly. Any ideas? I've tried messing with different x and y coords to see if that was the problem but nothing works.
The program just runs twitches and ends, when it should be playing through a game of pong until the user exits out.
code: you can ignore the comments
import turtle
# screen
screen = turtle.Screen()
screen.title('Pong')
screen.bgcolor('black')
screen.setup(width=1000, height=500)
# ball
ball = turtle.Turtle()
ball.shape('circle')
ball.color('white')
ball.speed(0)
ball.penup() #solves line issue
ball.goto(0, 0)
ball.dx = 5
ball.dy = -5
# right paddle____add speed___
r_pad = turtle.Turtle()
r_pad.speed(0.5)
r_pad.shape('square')
r_pad.color('white')
r_pad.shapesize(stretch_wid=5, stretch_len=2)
r_pad.penup()
r_pad.goto(450, 0)
# left paddle
l_pad = turtle.Turtle()
l_pad.speed(0.5)
l_pad.shape('square')
l_pad.color('white')
l_pad.shapesize(stretch_wid=5, stretch_len=2)
l_pad.penup()
l_pad.goto(-450, 0)
# Score
score = turtle.Turtle()
score.speed(0)
score.color('white')
score.penup()
score.hideturtle()
score.goto(0, 200)
score.write("Left_player : 0 Right_player: 0",
align="center", font=("arial", 24, "normal"))
#solving that score error
left_player = 0
right_player = 0
# movement
def paddler_up():
y = r_pad.ycor()
y += 20
r_pad.sety(y)
def paddler_down():
y = r_pad.ycor()
y -= 20
r_pad.sety(y)
def paddlel_up():
y = l_pad.ycor()
y += 20
l_pad.sety(y)
def paddlel_down():
y = l_pad.ycor()
y -= 20
l_pad.sety(y)
#main game
screen.listen()
screen.onkeypress(paddler_up, "w")
screen.onkeypress(paddler_down, "s")
screen.onkeypress(paddlel_up, "up")
screen.onkeypress(paddlel_down, "down")
while True:
screen.update()
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Checking borders
if ball.ycor() > 230:
ball.sety(230)
ball.dy *= -1
if ball.ycor() < -230:
ball.sety(-230)
ball.dy *= -1
if ball.xcor() > 600:
ball.goto(0, 0)
ball.dy *= -1
left_player += 1
score.clear()
score.write("Left_player : {} Right_player: {}".format(
left_player, right_player), align="center",
font=("Courier", 24, "normal"))
if ball.xcor() < -600:
ball.goto(0, 0)
ball.dy *= -1
right_player += 1
score.clear()
score.write("Left_player : {} Right_player: {}".format(
left_player, right_player), align="center",
font=("Courier", 24, "normal"))
# Paddle ball collision
if (ball.xcor() > 360 and ball.xcor() < 370) \
and (ball.ycor() < r_pad.ycor() + 40 and ball.ycor() > r_pad.ycor() - 40):
ball.setx(360)
ball.dx *= -1
if (ball.xcor() < -360 and ball.xcor() > -370) \
and (ball.ycor() < l_pad.ycor() + 40 and ball.ycor() > l_pad.ycor() - 40):
ball.setx(-360)
ball.dx *= -1
Your onkeypress calls for up and down keys should be capitalized (Up and Down instead of up and down) for it to work
screen.onkeypress(paddlel_up, "Up")
screen.onkeypress(paddlel_down, "Down")

What does the error "no display name and no $DISPLAY environment variable"

I am a beginner at Python and I tried to repurpose this guy's code on http://christianthompson.com/sites/default/files/Pong/pong.py
but then when I try running it I get the error message
enter image description here
The code is:
import turtle #turtle is a怀library for beginners to understand python and develop games.
import os
space = turtle.Screen()
space.title("Pong - CUHK")
space.bgcolor("black")
space.setup(width=1280, height=720)
space.tracer(0)
# Score
score_c = 0
score_u = 0
#player C #set the basic data about player
player_c = turtle.Turtle()
player_c.speed(0)
player_c.shape('square')
player_c.shapesize(stretch_wid=5, stretch_len=1) #stretches the square into a rectantle
player_c.color('white')
player_c.penup()
player_c.goto(-620, 0)
#player U #set the basic data about player
player_u = turtle.Turtle()
player_u.speed(0)
player_u.shape('square')
player_u.shapesize(stretch_wid=5, stretch_len=1)
player_u.color('white')
player_u.penup()
player_u.goto(620, 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
#Pen
pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("Player C: 0 Player U: 0", align="center", font=("Courier", 24, "normal"))
#Function
def player_c_up():
y = player_c.ycor()
y += 20 #add pixel
player_c.sety(y)
def player_c_down():
y = player_c.ycor()
y -= 20 #minus pixel
player_c.sety(y)
def player_u_up():
y = player_u.ycor()
y += 20
player_u.sety(y)
def player_u_down():
y = player_u.ycor()
y -= 20
player_u.sety(y)
#moving
space.listen()
space.onkeypress(player_c_up,'w')
space.onkeypress(player_c_down,'s')
space.onkeypress(player_u_up,'Up')
space.onkeypress(player_u_down,'Down')
#Game loop
while True:
space.update()
# Move the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
#Border set
if ball.ycor()>350:
ball.sety(350)
ball.dy *= -1 #change the direction
os.system("afplay bounce.wav&")
elif ball.ycor()<-350:
ball.sety(-350)
ball.dy *= -1 #change the direction
os.system("afplay bounce.wav&")
if ball.xcor()>630:
score_c += 1
pen.clear()
pen.write("Player C: {} Player U: {}".format(score_c, score_u), align="center", font=("Courier", 24, "normal"))
ball.goto(0, 0)
ball.dx *= -1 #change the direction
elif ball.xcor()<-630:
score_u += 1
pen.clear()
pen.write("Player C: {} Player U: {}".format(score_c, score_u), align="center", font=("Courier", 24, "normal"))
ball.goto(0,0)
ball.dx *= -1 #change the direction
#paddle and ball collisions
if (ball.xcor()>610 and ball.xcor()<620) and (ball.ycor()<player_u.ycor() + 40 and ball.ycor()> player_u.ycor()-40):
ball.setx(620)
ball.dx *= -1
os.system("afplay bounce.wav&")
if (ball.xcor()<-610 and ball.xcor()>-620) and (ball.ycor()<player_c.ycor() + 40 and ball.ycor()> player_c.ycor()-40):
ball.setx(-610)
ball.dx *= -1
os.system("afplay bounce.wav&")
So what does the error message pertain to, and where is the bit of code I have to change?

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 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