Move Sprite in Python and Cockroach

Introduction

Welcome to the fourth part of a multi-article set of tutorials for building an 80s style video game. In this part we study how to use Move a Sprite in Python and Cockroach for retrieving location of GUI-building Sprites.

In this part, we review some of how to get input from key presses and move the player around the GUI. We’ll back track over some relevant parts from one through three and add some more to your knowledge while working toward the goal of a fully functional arcade game called Zombie Feeder.

Prerequisites

  • Be sure to study part one through part three where you learn the basics to help understand what we are about to go over in this tutorial.

  • IMPORTANT: Full source code, mp3s, and images are available here for download. For each section, we copy only parts of that full source code that apply to the current lesson.

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

Before we get into reviewing listening for key-presses and moving the player’s Sprite around the GUI, we will briefly recap how to create the game GUI and placing the player’s Sprite on that window.

Create a GUI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Open a screen/window as the
# foundation of the game.
# All objects will be drawn in this GUI.
arcade.open_window(screen_width, screen_height, screen_title)
# Set the color to black for the GUI background color.
# Make sure your contrast is appropriate to game theme,
# as well as the images you will be drawing on this
# screen because we want the player to easily
# be able to distinguish all the game elements from each other.
arcade.set_background_color(arcade.color.BLACK)
# Initialize and assign an image to the new Sprite.
myPlayerSprite = arcade.Sprite("./resources/images/monkey.png")
# Set up variables to manage the Sprite's x and y coordinates.
# Calculate the horizontal center of the window.
x = int(screen_width / 2)
# 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 in the GUI.
myPlayerSprite.draw()

Analysis of the above code:

  • arcade.open_window: This function uses three params; width, height, and title. Width and height must be an integer, where title must be text.

  • arcade.set_background_color: The set_background_color function needs one parameter; color. The color can be set using arcade constants as you see above with “arcade.color.BLACK” or as an RGBA value.

  • arcade.Sprite: This line of code is used to create a Sprite, name it “myPlayerSprite”, and provide it with a PNG image.

  • x = int(screen_width / 2): Handle the distance from the left side of the GUI.

  • y = int(screen_height / 2): Store the distance from the bottom of the GUI. So zero would be the bottom and 900 would be the top.

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

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

Now that we have reviewed how to set up the visual environment, we will study listening for key presses and moving the player’s Sprite on the GUI.

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# When a key is clicked (pressed down), this function is called:
def on_key_press(self, symbol, modifiers):
    # symbol is the key being pressed.
    # If the player hit the space bar and
    # not in respawning mode, shoot a bullet.
    if symbol == arcade.key.SPACE and not self.player_sprite.respawning:
        # Assign an image to the new sprite.
        bullet_sprite = bulletSprite("./resources/images/bullet.png", SCALE)
        # Name the sprite.
        bullet_sprite.guid = "bullet"
        # Assign a speed to the sprite.
        bullet_speed = 8
        # Set direction.
        bullet_sprite.change_y = \
            math.cos(math.radians(self.player_sprite.angle)) * bullet_speed
        bullet_sprite.change_x = \
            -math.sin(math.radians(self.player_sprite.angle)) \
            * bullet_speed
        # Set location.
        bullet_sprite.center_x = self.player_sprite.center_x
        bullet_sprite.center_y = self.player_sprite.center_y
        # Update the sprite in memory.
        bullet_sprite.update()
        # Add new sprite to the two relevant sprite lists.
        self.list_all_sprites.append(bullet_sprite)
        self.list_bullets.append(bullet_sprite)
        # Play a throwing sound.
        arcade.play_sound(self.sound_throw)
    # If they pressed the left cursor control key or the "A" key,
    # change player facing angle 2 degrees counter clockwise.
    if symbol == arcade.key.LEFT or symbol == arcade.key.A:
        self.player_sprite.change_angle = 2
    # If they pressed the right cursor control key or the "D" key,
    # change player facing angle 2 degrees counter counter-clockwise.
    elif symbol == arcade.key.RIGHT or symbol == arcade.key.D:
        self.player_sprite.change_angle = -2
    # If they pressed the up cursor or the "W" key,
    # increase thrust.
    elif symbol == arcade.key.UP or symbol == arcade.key.W:
        self.player_sprite.thrust = 0.15
    # If they pressed the down cursor or the "S" key,
    # decrease thrust toward opposite direction.
    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 Player does not have to use the SHIFT key.
    elif symbol == arcade.key.EQUAL:
        self.player_sprite.difficulty += 1
        self.player_sprite.update()
        if self.player_sprite.difficulty > 15:
            self.player_sprite.difficulty = 15
    # Decrease game difficulty.
    elif symbol == arcade.key.MINUS:
        self.player_sprite.difficulty -= 1
        self.player_sprite.update()
        if self.player_sprite.difficulty < 1:
            self.player_sprite.difficulty = 1
# When any movement key is released.
def on_key_release(self, symbol, modifiers):
    # If LEFT cursor or "A" UNpressed: Set change angle to zero
    if symbol == arcade.key.LEFT or symbol == arcade.key.A:
        self.player_sprite.change_angle = 0
    # If RIGHT cursor or "D" UNpressed: Set change angle to zero
    elif symbol == arcade.key.RIGHT or symbol == arcade.key.D:
        self.player_sprite.change_angle = 0
    # If UP cursor or "W" UNpressed: Set thrust to zero
    elif symbol == arcade.key.UP or symbol == arcade.key.W:
        self.player_sprite.thrust = 0
    # If DOWN cursor or "S" UNpressed: 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 listen for key presses, along with some player movement and added in checking for keys to manage game difficulty and speed, which we’ll cover in more depth in a future part of this series. 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.

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
# Creating a class for the
# ------------------------
# Player Sprite.
# ------------------------
# Derived 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
        self.speed = 0
        self.max_speed = 5
        self.drag = 0.045
        # Initialize respawning variables
        self.respawning = 0
        # Initialize difficulty variable
        self.difficulty = DIFFICULTY
        # Set the player to respawn.
        self.respawn()

    # Called when Player dies so need to make a new player.
    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 player in center of the screen.
        self.center_x = SCREEN_WIDTH / 2
        self.center_y = SCREEN_HEIGHT / 2
        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
        self.speed += self.thrust
        # Make sure player speed does
        # not get out of hand.
        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 fourth part of our multi-part-tutorial for building a 2D top-down game called “Zombie Feeder”, we learned to use Arcade to move the player Sprite around the GUI and reviewed how to receive input from key presses and use the input to change the player’s vector.

In part five, we will explore path-finding for enemy Sprites. After that, we’ll study bullets, collisions, making sounds, keeping the player’s score, and game difficulty and speed changes.

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.