Score in Python and Cockroach

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

Introduction

This is part eleven of a multi-part batch of articles showing how to build a zombie shooter video game. In this part, we learn how to keep score in Python with Cockroach used for saving the score as well as reading and writing Sprite objects to the screen. In this section, we learn how to add score keeping, display to the GUI, and saving.

Prerequisites

  • Please start with part 1 through part ten of this multi-part series of lessons where with each part we build on what we learned in the previous one.

  • IMPORTANT: study part 1 through part 8 where we learned to create and set up a game screen window with Cockroach, how to set up Sprites with images and group the Sprites into Arcade Sprite Lists, how to acknowledge and address when the user presses a key, how to move the Player’s Sprite through game play based on those keypresses, how to move enemies (walruses) with some randomness and intelligence, how to enable the player to fire multiple bullets (snowballs) using the space bar, snowball movement, collisions between Sprite Lists and Sprites, and sound effects.

  • Python Arcade documentation. We use the Arcade framework for most of the functionality in this Python Arcade video game. Some code here was modified from this awesome open source project: Python Arcade Library

In this part eleven, before adding score tracking to our zombie game and even storing that score in CockroachDB, because the full source scripts for this video game are available for you to download above, study, and execute, we’ll copy over only the parts from the full game code that are necessary to THIS lesson about score-keeping and comment them heavily, so you can easily understand and learn in the best way for ease.

Score keeping constants

1
2
3
# Score is based on difficulty,
# as you will see later.
DIFFICULTY = 4

Initialize game score

The following is part of a function we created to handle a new game setup:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Main game class showing only up to
# where we initialize the score.
    def start_new_game(self):
        self.frame_count = 0
        self.game_over = False
        # Set up all the Sprite lists.
        self.list_all_sprites = arcade.SpriteList()
        self.list_enemies = arcade.SpriteList()
        self.list_bullets = arcade.SpriteList()
        self.list_player_lives = arcade.SpriteList()
        self.list_blocks = arcade.SpriteList()
        # Set up title screen sprite image.
        self.title = PlayerSprite("./resources/images/title.png", SCALE * 2.5)
        # Set up the player.
        self.score = 0

Now, we will examine how to draw the score indicator on the game GUI.

Draw game score on screen

1
2
3
4
5
6
7
8
9
10
# Render the game screen.
def on_draw(self):
    # This command must occur before we start drawing
    arcade.start_render()

    output = f"Difficulty: {self.player_sprite.difficulty}"
    arcade.draw_text(output, 10, 60, arcade.color.WHITE, 14)

    output = f"Score: {self.score}"
    arcade.draw_text(output, 10, 40, arcade.color.WHITE, 14)

NOTE: In the above code snippet showing the on_draw(self) function, we left out quite a bit of code not relevant to showing score, so please refer to the zip file containing all the game resources before you try to execute the game.

Now to increment the Player score when their bullet hits an enemy:

Score increase from hitting enemy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Move all visible Sprites:
def on_update(self, x_delta):
    self.frame_count += 1
    fps = x_delta * 3600
    if not self.game_over:
        self.list_all_sprites.update()
        # Cycle through all brains (bullets)
        # currently on the GUI.
        for bullet in self.list_bullets:
            # Check for bullet colliding with an enemy
            enemies = arcade.check_for_collision_with_list(bullet, self.list_enemies)
            # Iterate through all enemies hit by the current bullet.
            i = -1
            for enemy in enemies:
                i += 1
                # Award the Player points for hitting enemy,
                # modified by difficulty level.
                self.score += int(100 * self.player_sprite.difficulty)

OK now that we’ve studied all the parts in the game where we manage score, we will move to using CockroachDB to store player scores.

Cockroach save game

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# First use a SELECT SQL statement to check
# if a saved screen already exists in the db
# for this user. So one save per user.
# We are tracking high score only for a given user.
s = ""
s += "SELECT"
s += " id"
s += ", i_score"
s += " FROM tbl_games_played"
s += " WHERE id_player = " + id_player
crdb_cursor.execute(s)
crdb_row = crdb_cursor.fetchone()
# Check if a row was returned.
if crdb_row == None:
    i_rows = 0
else:
    # Get id and score from that row, so that later
    # we can update that row with a new player high
    # score if the new score is higher.
    i_rows = 1
    id = crdb_row[0]
    i_score = crdb_row[1]

Now that we have asked the database to find out if there are any matching rows for this player and if so, retrieved the id of that record, along with their old high score, we can now either add a new row to CockroachDB or update the existing record, depending on the results.

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
if i_rows == 0:
    # If no rows were returned, this means
    #   we want to add a new record via the INSERT INTO
    #   SQL command.
    s = ""
    s += "INSERT INTO tbl_games_played ("
    s += " id_gui_screen"
    s += ", id_player"
    s += ", i_hitpoints"
    s += ", i_misc"
    s += ", i_lives"
    s += ", i_score"
    s += ") VALUES ("
    s += id_gui_screen
    s += "," + id_player
    s += "," + i_hitpoints
    s += "," + i_misc
    s += "," + i_lives
    s += "," + i_score
    s += ")"
    crdb_cursor.execute(s)
else:
    # If a record was returned earlier, we use
    # the id of that returned row in the WHERE
    # clause below to overwrite that record in
    # the database with a new HIGH score.
    # First make sure the new score is higher
    # than the one stored in the database.
    if self.score > i_score:
        s = ""
        s += "UPDATE tbl_games_played SET"
        s += " id_gui_screen = " + id_gui_screen
        s += ", i_hitpoints = " + i_hitpoints
        s += ", i_misc = " + i_misc
        s += ", i_lives = " + i_lives
        s += ", i_score = " + i_score
        s += " WHERE id = " + id
        crdb_cursor.execute(s)

A different way to handle scores – if you want to track ALL of them for each player, so a player could have their game history remembered – would be to add every single score to a table called something like tbl_scores_all and create queries to produce either all scores for a given player or the highest scores. Here we went with the easy approach and to give you ideas so you can practice your Python and Cockroach coding as well as differentiate your game from others!

Cockroach load game

Now that we put some score data in Cockroach, we can easily retrive it using the query below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
s = ""
s += "SELECT TOP 1"
s += " id_gui_screen"
s += ", i_hitpoints"
s += ", i_misc"
s += ", i_lives"
s += ", i_score"
s += " FROM tbl_games_played"
s += " WHERE id_player = " + id_player
# No "order by" is required here because we
# are tracking highest score per user only.
crdb_cursor.execute(s)
crdb_row = crdb_cursor.fetchone()
# Get data from the row fetched.
id_gui_screen = crdb_row[0]
i_hitpoints = crdb_row[1]
i_misc = crdb_row[2]
i_lives = crdb_row[3]
i_score = crdb_row[4]

Conclusion

In this part eleven of the multi-part batch of articles showing how to build a video game in Python using Arcade, we learned how to use Python with Cockroach database for score tracking, showing the score on the screen, saving score, and retriving score for a given user. Heavily commented and explained code samples provided.

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.