0
\$\begingroup\$

I am very new to Python I started to make a pong game, but can't get it to let me hold down the buttons for the paddle to move. I'm using the turtle, not Pygame

 def paddle_a_up():
   y = paddle_a.ycor()
   y += 15
   paddle_a.sety(y)


def paddle_a_down():
    y = paddle_a.ycor()
    y -= 15
    paddle_a.sety(y)


def paddle_b_up():
    y = paddle_b.ycor()
    y += 15
    paddle_b.sety(y)

def paddle_b_down():
    y = paddle_b.ycor()
    y -= 15
    paddle_b.sety(y)

# binds
wn.listen()
wn.onkey(paddle_a_up, "w")
wn.onkey(paddle_a_down, "s")
wn.onkey(paddle_b_up, "o")
wn.onkey(paddle_b_down, "i")

I can't seem to get my arrow up and down to work with the binds so that's why I'm using "o" and "i". If you have a solution for that too, I'd be very grateful.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

System sends to programs information about pressed key ("events") only when key changes state from not-pressed to pressed or from pressed to not-pressed (released). It doesn't send events when you hold down key.

You have to use onkeypressed() to set arrow_up_pressed = True and onkeyreleased() to reset arrow_up_pressed = False and ontimer() to run repeatedly code which checks if arrow_up_pressed is True and move object up. The same you should do with arrow_down_pressed, etc.

Or you can use variable speed instead of arrow_up_pressed and arrow_down_pressed so you can assing +15 or -15 to the same variable (or 0 when keys are released). And again you need ontimer to run repeatedly code which add speed to position.

In example I use second method.


Minimal working code

import turtle

def paddle_a_up():
    global a_speed_y

    a_speed_y = +15

def paddle_a_down():
    global a_speed_y
    
    a_speed_y = -15

def paddle_a_left():
    global a_speed_x

    a_speed_x = -15

def paddle_a_right():
    global a_speed_x
    
    a_speed_x = +15

def paddle_a_stop_y():
    global a_speed_y

    a_speed_y = 0

def paddle_a_stop_x():
    global a_speed_x

    a_speed_x = 0

def update_frame():
    x, y = paddle_a.position()
    
    y += a_speed_y
    x += a_speed_x

    paddle_a.goto(x, y)

    # here update position for other objects - ie. move ball

    # run again after 50ms
    wn.ontimer(update_frame, 50)  # 50ms means ~20 FPS (Frames Per Second) (1000/50 = 20)

# --- main ---

# default values at start
a_speed_x = 0
a_speed_y = 0

wn = turtle.Screen()
paddle_a = turtle.Turtle()

# run first time after 50ms
wn.ontimer(update_frame, 50)  # 50ms means ~20 FPS (Frames Per Second) (1000ms / 50ms = 20)

# binds
wn.onkeypress(paddle_a_up, "Up")
wn.onkeypress(paddle_a_down, "Down")
wn.onkeypress(paddle_a_left, "Left")
wn.onkeypress(paddle_a_right, "Right")

wn.onkeyrelease(paddle_a_stop_y, "Up")
wn.onkeyrelease(paddle_a_stop_y, "Down")
wn.onkeyrelease(paddle_a_stop_x, "Left")
wn.onkeyrelease(paddle_a_stop_x, "Right")

wn.listen()
wn.mainloop()

BTW: The same way you would have to do this in PyGame or Pyglet.


EDIT:

You get better result if you add/substract value to speed instead of assigning - because when you press left and right at the same time then it will stop move (because speed +15 and -15 will gives 0), and when you release only one - ie. left - then it will again move right. In previous version when you release one but you still keep pressed other then it doesn't move again.

import turtle

def paddle_a_up_pressed():
    global a_speed_y

    a_speed_y += 15

def paddle_a_down_pressed():
    global a_speed_y
    
    a_speed_y -= 15

def paddle_a_left_pressed():
    global a_speed_x

    a_speed_x -= 15

def paddle_a_right_pressed():
    global a_speed_x
    
    a_speed_x += 15

def paddle_a_up_released():
    global a_speed_y

    a_speed_y -= 15

def paddle_a_down_released():
    global a_speed_y

    a_speed_y += 15

def paddle_a_left_released():
    global a_speed_x

    a_speed_x += 15

def paddle_a_right_released():
    global a_speed_x

    a_speed_x -= 15


def update_frame():
    x, y = paddle_a.position()
    
    x += a_speed_x
    y += a_speed_y

    paddle_a.goto(x, y)

    # run again after 50ms
    wn.ontimer(update_frame, 50)  # 50ms means ~20 FPS (Frames Per Second) (1000/50 = 20)

# --- main ---

# default values at start
a_speed_x = 0
a_speed_y = 0

wn = turtle.Screen()
paddle_a = turtle.Turtle()

# run first time after 50ms
wn.ontimer(update_frame, 50)  # 50ms means ~20 FPS (Frames Per Second) (1000/50 = 20)

# binds
wn.onkeypress(paddle_a_up_pressed, "Up")
wn.onkeypress(paddle_a_down_pressed, "Down")
wn.onkeypress(paddle_a_left_pressed, "Left")
wn.onkeypress(paddle_a_right_pressed, "Right")

wn.onkeyrelease(paddle_a_up_released, "Up")
wn.onkeyrelease(paddle_a_down_released, "Down")
wn.onkeyrelease(paddle_a_left_released, "Left")
wn.onkeyrelease(paddle_a_right_released, "Right")

wn.listen()
wn.mainloop()
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .