Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

User Input

In this lesson, you’ll add user input to control your player sprite. Put this in your game loop right after the event handling loop. Watch for the level of indentation. This returns a dictionary containing the keys pressed at the beginning of every frame:

Python
55# Get the set of keys pressed and check for user input
56pressed_keys = pygame.key.get_pressed()

Next, you write a method in Player to accept that dictionary. This will define the behavior of the sprite based off the keys that are pressed:

Python
29# Move the sprite based on user keypresses
30def update(self, pressed_keys):
31    if pressed_keys[K_UP]:
32        self.rect.move_ip(0, -5)
33    if pressed_keys[K_DOWN]:
34        self.rect.move_ip(0, 5)
35    if pressed_keys[K_LEFT]:
36        self.rect.move_ip(-5, 0)
37    if pressed_keys[K_RIGHT]:
38        self.rect.move_ip(5, 0)

K_UP, K_DOWN, K_LEFT, and K_RIGHT correspond to the arrow keys on the keyboard. If the dictionary entry for that key is True, then that key is down, and you move the player .rect in the proper direction. Here you use .move_ip(), which stands for “move in place,” to move the current Rect.

Then you can call .update() every frame to move the player sprite in response to keypresses. Add this call right after the call to .get_pressed():

Python
53# Main loop
54while running:
55    # for loop through the event queue
56    for event in pygame.event.get():
57        # Check for KEYDOWN event
58        if event.type == KEYDOWN:
59            # If the Esc key is pressed, then exit the main loop
60            if event.key == K_ESCAPE:
61                running = False
62        # Check for QUIT event. If QUIT, then set running to false.
63        elif event.type == QUIT:
64            running = False
65
66    # Get all the keys currently pressed
67    pressed_keys = pygame.key.get_pressed()
68
69    # Update the player sprite based on user keypresses
70    player.update(pressed_keys)
71
72    # Fill the screen with black
73    screen.fill((0, 0, 0))

Now you can move your player rectangle around the screen with the arrow keys. Try it out:

Shell
$ python sky_dodge.py

For more information about .move_ip() and .get_pressed(), check out the following resources from the pygame documentation:

00:00 In this lesson, you’re going to add user input. What type of user input? Well, you’re going to add keyboard controls. Up to now, you’ve been using pygame.event.get() to return a list of the events in the event queue. And you’re currently scanning those for KEYDOWN event types.

00:19 That’s how you can hit Escape and quit. But there’s so much more that you can do with those KEYDOWN event types, and that’s where this comes in. pygame.event.get_pressed() is going to return a dictionary containing all of the KEYDOWN only events in the queue.

00:35 And so what you’re going to do is put this in your game loop right after the event handling loop, and then that way you can return the keys pressed at the beginning of every frame. Now that you have the user input, you need to do something with it to move the player.

00:50 The next step will be to add an .update() method to your Player class, and this is going to define the movement behavior of the sprite based off of the keys that are being pressed.

01:02 It’s going to use the rect rectangle and a new method called .move_ip(), which means move in place. Let me have you add these changes to your code. To start off with, I thought it might be good to look at the types of keys that are being pressed and how you’re going to use a system to identify which are which, and therefore create the movement.

01:25 It all has to do with this getting events, right? So, that’s the event loop, and if the event is of a type KEYDOWNwhich is a general type—you could print it. Like here, you are checking to see if the .key is equal to the constant K_ESCAPE (key Escape). What do those constants look like? Well, if you went here and made a print() statement right as those events are happening—in this case, you’re going to use an f-string—so f, and you could print out the key.

02:01 Right? So each event.key that comes in, it’s going to print it out. I’m going to save, and then down here, I’ve made a little more room with my terminal.

02:09 I’m going to run sky_dodge here. I press Up—this is the constant for Up. Down—this is a constant for Down. Up, Down, Up, Down, holding Up, holding Down.

02:22 Going left, going right. So, those are my keypresses coming in, versus, say, the Spacebar or the A key.

02:31 These are all different numeric values for what’s being pressed—holding a Shift key or the Option key or Command. So, those are what those constants are that it’s looking for.

02:45 And Escape, which is 27, kicks us out of the event loop, because that’s what it was looking for. So those constants that are loaded up here are of these values, and as you can see, they’re kind of cumbersome to remember as a numeric value, so it’s nice that you could just import them and have them ready to go.

03:06 Go ahead and get rid of the print() statement there.

03:14 Now to implement movement. Okay. You’re going to get those pressed keys here at the end of the game loop just before you’re filling in the screen and after that last elif statement, so at line 55.

03:32 Get the set of keys pressed and check for user input, so you’re going to create this new object pressed_keys, and it’ll take into it pygame.key.get_pressed().

03:43 This functions a little differently than what you were looking at before, with a single event. This returns with a huge sequence of Boolean values representing the state of every single key on the keyboard. What state is that key in? 0 meaning not pressed, 1 meaning pressed.

04:00 This helps if you’re pressing both the Up key and the Left key, or holding down something like Shift. Okay, so, lines 55 and 56. Back up into the Player class, you’re going to define a new method. It’s going to be called .update().

04:20 It’s going to be based upon the user keypresses.

04:25 So here’s .update(), and into it you’ll send an argument of the currently pressed keys. And then you’re going to start a list of if statements.

04:35 if pressed_keys for the constant K_UP is currently True1you’re going to take self and use the .rect to move it in place—.move_ip(). And then you put in a tuple, and this is going to be, in this case, up, so you’re going to move nothing left to right, but you’re going to move -5, which will move the rectangle upward—subtracting 5 from its height. These look kind of similar, so it might be useful to copy and paste. Let’s see.

05:02 So, the next one is going to be Down, if the value for pressed_keys[K_DOWN] is currently True. And in that case, you’re going to add 5, moving it downward. Then from there, we need to do Left and Right. If the Left key is held down, then pressed_keys[K_LEFT] would be True. Up and down will be 0, but left will be a -5.

05:24 So you might’ve guessed it—K_RIGHT will be a plus 5. Okay. So here’s the lines. From line 29 to 38, this is a method that can be called on your player. It takes in pressed_keys.

05:37 If K_UP is currently True, then it’s going to move up, -5. If K_DOWN is currently True, it’s going to move down 5, and so forth and so on. K_LEFT moving left and K_RIGHT—right.

05:49 After collecting the pressed_keys,

05:54 I need to do the update and update the player sprite based on those user keypresses. player.update()the one you created—and it takes in, well, your new set of pressed_keys.

06:07 All right, that all looks good! So again, on 69 and 70, you’re going to enter in those two. All right. Next, try it out.

06:18 Now as you move down and up it’s moving the character. Great! Well, that’s a bit of a problem. If you move too high or too far left or too far down, ha, you get lost out there in the black.

06:37 That’s something to fix. And note that if you hold down two keys like Left and Up, it moves diagonally. So, that’s what pressed_keys is doing.

06:46 If I hold Up and Down at the same time, it won’t move, ha. Or Left and Right. So again, pressed_keys is returning the state of all keys as Boolean values,

06:57 so that allows that diagonal movement, which is pretty cool. Awesome! Need to fix this, though. Now that you’ve got all that movement going on, the next lesson is going to help you keep your player on the screen.

Avatar image for Xavier

Xavier on March 28, 2020

I think I entered the code correctly, but I find the player block jumps a large distance for even a single key press. This is perhaps because the loop runs each time the frame is refreshed and what seems a single key press to me may be being registered for multiple frames. Looking ahead, there’s a “Game Speed” lesson. Implementing the clock code from that lesson makes the player behave as seen in this lesson’s demo.

Avatar image for Chris Bailey

Chris Bailey RP Team on March 30, 2020

Hi @Xavier, I’m glad you found that solution. Some hardware will make the block move super fast. You are right that setting the clock will help resolve the issue.

Avatar image for kartik puri

kartik puri on May 18, 2020

# super(Player,self).__init__()

I commented the above line and its still work, I saw the super tutorial on real python, But now I am bit confused again, looking at that piece of line still working.

As per the documentation of super we are calling the init method inside the init of child class to make sure that init of parent gets called when the object(player) is initialized, we have not passed anything inside the init so technically child object(player) can still access all the properties of its parent as per the inheritance rule. So could you please tell me how exactly super is working here as we haven’t passed anything inside the super(Player,self).init(), I might sound stupid i am really stuck at that line and can’t move forward in this course

Avatar image for Chris Bailey

Chris Bailey RP Team on May 19, 2020

Hi @kartik puri, I hope I understand your question. Some of the code used in this course is from an updated article. I did not catch this upon creating the course. In Python 3 vs 2, you do not need to include (Player, self) in the statement. It has now been streamlined, and one can simply use, super().__init__(). The old style format still works, but the new format is much simpler.

You are right that the real inheritance is coming from the initial class Player(pygame.sprite.Sprite): .

Avatar image for simma99

simma99 on June 19, 2023

Hi. I gave all the above commands. The code is working but the rectangle is not working. I tried to check with print statement. When I pressed the keys the print statement is getting updated on the console. But the rectangle is not moving. Please help

Avatar image for Ajeet A R

Ajeet A R on May 30, 2024

Hi @Kartik puri That’s because the Sprite class is not yet used.

Avatar image for the1howie

the1howie on Oct. 31, 2024

Thank you Xavier. I also struggled with the same issue for FPS. As soon as I watched Chris’s video on game speed, all was good again :)

Become a Member to join the conversation.