Mo Halley
Mo Halley

Reputation: 13

Binding Key Press Events Using Turtle

I'm new to Python and am trying a bunch of different projects to learn. I want to use Turtle to create a game and I found this guy on YouTube who walks through re-creating Space Invaders.

I'm using IDLE and Python 3. The screen and player are created, but nothing happens when I press a key. I have looked up this issue and tried a number of things, but I'm not sure what I'm doing wrong.

The other unusual thing is that each function is run once. I included a print statement in each function to discover this. Why is it running each key press event once, but not binding to my actual keyboard?

import turtle

#Screen setup
screen = turtle.Screen()
screen.bgcolor('black')
screen.title("Space Invaders")

#Create player
player = turtle.Turtle()
player.color('blue')
player.shape('triangle')
player.penup()
player.speed(0)
player.setposition(0, -250)
player.setheading(90)

playerspeed = 15

#Move the player left and right
def move_left():
    x = player.xcor()
    x -= playerspeed
    player.setx(x)
    screen.listen()
    print("Move left.") #for debugging

def move_right():
    x = player.xcor()
    x += playerspeed
    player.setx(x)
    screen.listen()
    print("Move right.") #for debugging

#Create keyboard binding
screen.onkey(move_left(), 'Left')
screen.onkey(move_right(), 'Right')
screen.listen()

#Play game
screen.mainloop()

Upvotes: 1

Views: 778

Answers (2)

Lilwen
Lilwen

Reputation: 70

I think the guy you found on YouTube might have been using python 2.7 rather than python 3 which would change the keypress commands.

Instead of

screen.onkey(move_left(), 'Left')
screen.onkey(move_right(), 'Right')
screen.listen()

You should use

screen.listen()
screen.onkeypress(move_left, 'Left')
screen.onkeypress(move_right, 'Right')

Upvotes: 0

cdlane
cdlane

Reputation: 41905

The problem is with these two lines of code:

screen.onkey(move_left(), 'Left')
screen.onkey(move_right(), 'Right')

You don't want to call move_left(), you want to pass move_left to be called by the event handler when the key is pressed:

screen.onkey(move_left, 'Left')
screen.onkey(move_right, 'Right')

By including the parentheses, you pass the return value of move_left() which is None, effectively disabling the event instead of enabling it!

Here's a rework of your code with the above fix plus another trick: space invader type games are perfect for taking advantage of the rarely used turtle.settiltangle() method. This method allows us to make the turtle appear to point vertically, while actually oriented horizontally. So we can simply used forward() and backward() to move it across the screen:

from turtle import Screen, Turtle

PLAYER_SPEED = 15

# Move the player left and right
def move_left():
    player.backward(PLAYER_SPEED)

def move_right():
    player.forward(PLAYER_SPEED)

# Screen setup
screen = Screen()
screen.bgcolor('black')
screen.title("Space Invaders")

# Create player
player = Turtle('triangle')
player.speed('fastest')
player.color('blue')
player.penup()
player.sety(-250)
player.settiltangle(90)

# Create keyboard binding
screen.onkey(move_left, 'Left')
screen.onkey(move_right, 'Right')
screen.listen()

# Play game
screen.mainloop()

Of course, you have to remember when you fire a projectile that your turtle is pointing right and redirect it accordingly!

Upvotes: 1

Related Questions