Python Arcade Player Movement and Postgres

Have a Database Problem? Speak with an Expert for Free
Get Started >>

Introduction

Welcome to part 4 of a multi-part set of articles on building a retro style video game. In this part 4 we study how to use Python Arcade for Player Movement and Postgres for retrieving Sprite location-on-screen data.

In this part, we recap how to get input from the keyboard and move the player’s Sprite around the screen. We’ll back track over a few relevant parts from 1 through 3 and add some more to your knowledge and work toward the eventual creation of a fully functional and even fun arcade game.

Prerequisites

  • Be sure to study part 1 through part 3 where we learned the basics and more that will help you understand what we are about to go over in this article.

  • IMPORTANT: The full source code, images, and mp3 files are available here for download. For each part, we copy only parts of that full source code that apply to the lesson and study it.

  • Use PIP to install the arcade, datetime, flask, math, os, psycopg2, pyautogui, and random libraries. As we move through each lesson, we’ll use more functions dependent upon these frameworks.

  • Python Arcade library docs. We use the Python Arcade library for quite a bit of the purely game-related functionality of this game. Arcade is based on Pyglet.

Before we get into reading the keyboard and moving the player’s Sprite around the screen, we will briefly review creating a game screen or window and placing the player’s Sprite on that window.

Python Arcade create a screen

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Open a screen/window as the foundation of the game.
# Everything will be drawn on/in this window.
arcade.open_window(screen_width, screen_height, screen_title)

# Set the screen color to white for the game background.
# Be sure your contrast is appropriate to game theme, as well
#   as the icons you will be placing on this screen because
#   we want the player/user to easily be able to see all the
#   game elements.
arcade.set_background_color(arcade.color.WHITE)

# Initialize an image and assign it to the player Sprite.
myPlayerSprite = arcade.Sprite("sprites/penguin.png")

# Set up variables to store/track the player Sprite's x and y coordinates.
#   Divide the screen width by 2 in order to calculate the horizontal center of the window.
x = int(screen_width / 2)
#   Divide the screen height by 2 in order to calculate the vertical center of the window.
y = int(screen_height / 2)

# Initialize the Player Sprite's position in 2d space.
myPlayerSprite.set_position(x, y)

# Draw the Player's Sprite on the window.
myPlayerSprite.draw()

Analysis of the above code:

  • arcade.open_window: The open_window function uses 3 parameters; width, height, and caption/title. Width and height must be integer. Caption/title must be a text string encapsulated in quotes or semi-quotes.

  • arcade.set_background_color: The set_background_color function needs one parameter, which is color. The color can be set using arcade constants as you see above or as an RGBA value.

  • arcade.Sprite: This line of code creates a Sprite, names it “myPlayerSprite”, and gives it an image.

  • x = int(screen_width / 2): Initialize a variable to handle the distance from the left side of the screen.

  • y = int(screen_height / 2): Initialize a variable to store the distance from the bottom of the screen. So zero would be the very bottom and 900 would be the very top. I want to emphasize that this is “from the bottom” because some other game screen systems start from the top.

  • myPlayerSprite.set_position: Sets the Player Sprite’s coordinate position to be at the x and y coordinates we had set to be in the center of the screen.

  • myPlayerSprite.draw: Makes the Player’s Sprite visible on the game window.

Now that we have reviewed how to set up the environment, we will study reading the keyboard and moving the player’s Sprite around the screen.

Keyboard player control

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# When a key is clicked (pressed down), this function is called:
def on_key_press(self, symbol, modifiers):
    # PLAYER ANGLE CHANGE
    # If the user pressed the left cursor key or the "A" key,
    # change player angle by 3 degrees; counter clockwise.
    if symbol == arcade.key.LEFT or symbol == arcade.key.A:
        self.player_sprite.change_angle = 2
    # If the user pressed the right cursor key or the "D" key,
    # change player angle by 3 degrees; clockwise.
    elif symbol == arcade.key.RIGHT or symbol == arcade.key.D:
        self.player_sprite.change_angle = -2
    # If the user pressed the up cursor key or the "W"
    # key, increase "thrust".
    elif symbol == arcade.key.UP or symbol == arcade.key.W:
        self.player_sprite.thrust = 0.15
    # If the user pressed the down cursor or the "S"
    # key, decrease thrust toward the opposite direction
    # using negative for opposite:
    elif symbol == arcade.key.DOWN or symbol == arcade.key.S:
        self.player_sprite.thrust = -.2
    # Increase game difficulty.
    #   We chose "equals" key instead of "plus" key here, so the
    #   Player does not have to use the SHIFT key combined with
    #   the equals key in order to get a "+".
    elif symbol == arcade.key.EQUAL:
        self.player_sprite.difficulty += 1
        if self.player_sprite.difficulty > 15:
            self.player_sprite.difficulty = 15
    # Decrease difficulty of the game. Note: we will
    #   do an entire part in this series on game difficulty,
    #   which includes speed.
    elif symbol == arcade.key.MINUS:
        self.player_sprite.difficulty -= 1
        if self.player_sprite.difficulty < 1:
            self.player_sprite.difficulty = 1

# When the player RELEASES movement keys.
def on_key_release(self, symbol, modifiers):
    # When the LEFT cursor or "A" are released:
    #   Set change angle to zero
    if symbol == arcade.key.LEFT or symbol == arcade.key.A:
        self.player_sprite.change_angle = 0
    # When the RIGHT cursor or "D" are released:
    #   Set change angle to zero
    elif symbol == arcade.key.RIGHT or symbol == arcade.key.D:
        self.player_sprite.change_angle = 0
    # When the UP cursor or "W" are released:
    #   Set thrust to zero
    elif symbol == arcade.key.UP or symbol == arcade.key.W:
        self.player_sprite.thrust = 0
    # When the DOWN cursor or "S" are released:
    #   Set thrust to zero
    elif symbol == arcade.key.DOWN or symbol == arcade.key.S:
        self.player_sprite.thrust = 0

The above is a review of how to read the keyboard, along with some player movement. Below, we are going to add and explain some more code that relates to the player Sprite so it can be moved around. You might call the following code “prequel” and “sequel” to the keyboard-reading routines.

Player Sprite initialization

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# Creating a class for...
# Sprite that represents the player.
# derives from arcade.Sprite.
class PlayerSprite(arcade.Sprite):
    # Set up the player.
    def __init__(self, filename, scale):
        # Call the parent Sprite constructor
        super().__init__(filename, scale)
        # Initialize player movement variables.
        # Angle comes in automatically from the parent class.
        self.thrust = 0
        # Initialize player movement speed to begin
        #   with being still.
        self.speed = 0
        # Set the maximum speed the player can move.
        #   Note: This will not be influenced by changes in difficulty.
        self.max_speed = 5
        # This variable determines how much gravity and
        #    wind resistance slows down your penguin.
        self.drag = 0.045
        # Initialize a respawning variable
        self.respawning = 0
        # Initialize a global difficulty variable
        #   using a constant we created in an earlier part
        #   in this series and will address more deeply
        #   in a future part of this series.
        self.difficulty = DIFFICULTY
        # Set the player to respawn.
        self.respawn()

    # This function is called when Player dies so can make a new player
    #    and set the player to "invulnerable" for a brief time.
    def respawn(self):
        # self.respawning is a timer for invulnerability.
        # If we are in the middle of respawning, this is non-zero.
        self.respawning = 1
        # Place respawning player in center of the screen.
        self.center_x = SCREEN_WIDTH / 2
        self.center_y = SCREEN_HEIGHT / 2
        # Player Sprite is pointing straight up.
        self.angle = 0

    # Update player position, speed, and opacity.
    def update(self):
        # Update respawning counter.
        if self.respawning:
            self.respawning += 1
            # Use respawn counter to set player opacity (alpha property).
            self.alpha = self.respawning
            # When respawn counter reaches past 250,
            # set player to be fully visible.
            if self.respawning > 250:
                self.respawning = 0
                # Alpha of 255 means 100% visible.
                self.alpha = 255

        # If the player is moving, add gravity-like "drag".
        if self.speed > 0:
            self.speed -= self.drag
            # Make sure player speed is not negative
            # after it was reduced by drag:
            if self.speed < 0:
                self.speed = 0
        if self.speed < 0:
            self.speed += self.drag
            if self.speed > 0:
                self.speed = 0
        # Change speed based on the value in the "global" thrust variable.
        #   Check to be sure speed
        self.speed += self.thrust
        if self.speed > self.max_speed:
            self.speed = self.max_speed
        if self.speed < -self.max_speed:
            self.speed = -self.max_speed
        # Change Player direction based on angle and speed.
        self.change_x = -math.sin(math.radians(self.angle)) * self.speed
        self.change_y = math.cos(math.radians(self.angle)) * self.speed
        self.center_x += self.change_x
        self.center_y += self.change_y
        # If the player goes off-screen, teleport
        # them to the other side of the window
        if self.right < 0:
            self.left = SCREEN_WIDTH
        if self.left > SCREEN_WIDTH:
            self.right = 0
        if self.bottom < 0:
            self.top = SCREEN_HEIGHT
        if self.top > SCREEN_HEIGHT:
            self.bottom = 0
        # Call the parent class.
        super().update()

CONCLUSION

In this part 4 of our multi-part set of tutorials for building a 2D top-down perspective game, we learned to use the Python Arcade framework to move the player around the screen and reviewed how to get inputs from the keyboard and use that input to make changes to the player’s Sprite’s vector.

In the next part 5, we will explore the movement of enemy Sprites. After that, we’ll work on bullet firing, collision detection, sound effects, keeping player score, and the ways game difficulty changes various game dynamics.

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.