0

Whenever I try to run my code and press the "w", "s", "Up" or "Down" keys on the keyboard, the objects don't move (onkeypress() function doesn't work). I tried to replace it with the onkey() function but to no avail. Below is my code:

import turtle
wn = turtle.Screen()
wn.title("Pong")
wn.setup(width=800, height=600)
wn.bgcolor("black")
wn.tracer(0)

#paddle_a
paddle_a = turtle.Turtle()
paddle_a.shape("square")
paddle_a.goto(-350, 0)
paddle_a.speed(0)
paddle_a.color("blue")
paddle_a.penup()
paddle_a.shapesize(stretch_wid=5, stretch_len=1)

#paddle_b
paddle_b = turtle.Turtle()
paddle_b.shape("square")
paddle_b.goto(350, 0)
paddle_b.speed(0)
paddle_b.color("red")
paddle_b.penup()
paddle_b.shapesize(stretch_wid=5, stretch_len=1)

#ball
ball = turtle.Turtle()
ball.shape("square")
ball.goto(0, 0)
ball.speed(0)
ball.color("white")
ball.penup()


wn.listen()
wn.onkeypress(paddle_a.sety(paddle_a.ycor() + 20), "w")
wn.onkeypress(paddle_a.sety(paddle_a.ycor() - 20), "s")
wn.onkeypress(paddle_b.sety(paddle_b.ycor() + 20), "Up")
wn.onkeypress(paddle_b.sety(paddle_b.ycor() - 20), "Down")

while True:
    wn.update()
ggorlen
  • 44,755
  • 7
  • 76
  • 106

1 Answers1

2

The problem is here:

wn.onkeypress(paddle_a.sety(paddle_a.ycor() + 20), "w")
wn.onkeypress(paddle_a.sety(paddle_a.ycor() - 20), "s")
wn.onkeypress(paddle_b.sety(paddle_b.ycor() + 20), "Up")
wn.onkeypress(paddle_b.sety(paddle_b.ycor() - 20), "Down")

onkey() and onkeypress() want a function to call as their first argument, you instead called a function that returned None. Instead, try something like:

wn.onkeypress(lambda: paddle_a.sety(paddle_a.ycor() + 20), "w")
wn.onkeypress(lambda: paddle_a.sety(paddle_a.ycor() - 20), "s")
wn.onkeypress(lambda: paddle_b.sety(paddle_b.ycor() + 20), "Up")
wn.onkeypress(lambda: paddle_b.sety(paddle_b.ycor() - 20), "Down")

However, if you want your program to work well, we need to make a couple of adjustments. First, your while True: has no business being in an event-based environment like turtle. Second, if we rotate your paddle headings and shapes, we can get away with just using forward and backward move them. A rework of your code:

from turtle import Screen, Turtle

def a_go_up():
    paddle_a.forward(20)
    screen.update()

def a_go_down():
    paddle_a.backward(20)
    screen.update()

def b_go_up():
    paddle_b.forward(20)
    screen.update()

def b_go_down():
    paddle_b.backward(20)
    screen.update()

screen = Screen()
screen.title("Pong")
screen.setup(width=800, height=600)
screen.bgcolor('black')
screen.tracer(False)

# paddle_a
paddle_a = Turtle()
paddle_a.shape('square')
paddle_a.shapesize(stretch_len=5)
paddle_a.setheading(90)
paddle_a.penup()
paddle_a.color('blue')
paddle_a.setx(-350)

# paddle_b
paddle_b = paddle_a.clone()
paddle_b.color('red')
paddle_b.setx(350)

# ball
ball = Turtle()
ball.shape('square')
ball.color('white')
ball.penup()

screen.onkeypress(a_go_up, 'w')
screen.onkeypress(a_go_down, 's')
screen.onkeypress(b_go_up, 'Up')
screen.onkeypress(b_go_down, 'Down')

screen.listen()
screen.update()
screen.mainloop()
cdlane
  • 40,441
  • 5
  • 32
  • 81
  • Thanks for explaining, but I still a little bit confused. In your code above, If we were just to put parentheses next to the go up function for example, we'll end up with error. Can you explain why? – Alhamzah Omar Aug 31 '21 at 15:07
  • @AlhamzahOmar, when we put parentheses after the function, we call it. But *now* is not the time to call, we want to call it *later*, when the user presses a key. By just passing the name of the function, we're allowing `onkey()` to call it later, when appropriate. Think of functions as just another type of data, which we can pass as arguments, store in lists or dictionaries, etc. Only when we're ready to invoke them do we use the parentheses notation. – cdlane Aug 31 '21 at 16:07