Game Python Postgres Draw Sprites

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

Introduction

In this tutorial, we will continue creating a game with Python and Postgres with draw sprites as part 2 of a multi-part series of lessons where the final result will be a 2D graphical top-down view game. We’ll use Python’s “Arcade” framework for the graphics-related features it has. We are using PostgreSQL to store and retrieve screen data in the database. In this lesson we will access Postgres to get screen data and draw that data as Sprites. In the next lesson, we’ll learn how to move Arcade’s Sprites and for the player icon to be controlled and moved around the game screen. In later parts (future articles in this series), we will address enemies and collision physics in the game and other pieces of what makes an enjoyable Python graphical game, like scoring points and dying.

Prerequisites

See part 1 where we learned how to draw on a screen, create PostgreSQL tables for storing screen data and screen objects, and pull data from those tables for display on a game screen: Create game with Python and Postgres Part 1. For this lesson we will be using much of what we learned in part 1 but not all. One change will be that instead of using draw commands for objects, we’ll be loading objects in from Postgres and placed into Sprites instead of drawn.

Images built in to Arcade

This is a note about images we could use in this game for Sprites called “resources”. Resources are sounds and images built into Arcade that we can use to build without figuring out how to copy those kind of files into our projects.

Any file load that starts with :resource: will attempt to load that file from the library resources instead of the project directory. [Learn about Arcade Resources here] (http://arcade.academy/resources.html).

That said, we are going to load our objects from our own png image files.

Create a Sprite

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
# Load and position a screen and player sprite

import arcade

# Set up variables for screen dimensions
window_width = 1280
window_height = 720

# Open the screen. Set title and size
arcade.open_window(window_width, window_height, "Drawing with Python")

# Set the background color to black
# For a color list see http://arcade.academy/arcade.color.html
arcade.set_background_color(arcade.color.BLACK)

# Turn the render process on. Required before we use drawing commands
arcade.start_render()

# Create a sprite
arcade.sprite1 = arcade.Sprite("sprites/player.png")

# Find middle of screen
#   Divide window height and width by 2 to get center of window
mid_x = window_width / 2
mid_y = window_height / 2

# Change sprite position
#   Create variables to keep track of player x and y coordinates
player_x = mid_x
Player_y = mid_y

# Use the set_position function to change position of our Sprite
arcade.sprite1.set_position(player_x, player_y)

# Keep the window up until the user clicks close
arcade.run()

Get screen from PostgreSQL

Now we’ll retrieve screen data, which is objects and their locations in 2D space, from two tables. We’ll start by creating the tables. Why two? One table (“tbl_screens”) will have a row per screen, while the second table (“tbl_screens_objects”) will store all the objects and use id_screen to point back to the id field in tbl_screens.

PostgreSQL tables that store screens

Here is tbl_screens with one row of sample data to represent screen 1 of the game:

idt_titlet_colori_widthi_height
1Screen 1BLACK1280720

Here is tbl_screens_objects which contains our Sprites. This table relates to the above table via the id and id_screen fields.

idid_screent_object_namet_object_typet_object_image_URL
11Playerspriteplayer.png
21Wallspritewall.png
31Treespritetree.png
41Powerupspritepowerup.png
51Enemy1spriteenemy1.png
61Enemy2spriteenemy2.png

NOTE: For tbl_screens_objects, for now, we are only showing the relevant fields for setting up the sprites, leaving out our columns that deal with collisions and sounds.

Query PostgreSQL for screen data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# First we get a screen ID and title from tbl_screens from FIRST screen
s = ""
s += "SELECT TOP 1"
s += " id"
s += ", t_title"
s += ", t_color"
s += ", i_width"
s += ", i_height"
s += " FROM tbl_screens"
s += " ORDER BY i_order"
try:
    db_cursor.execute(s)
    id_screen = db_cursor.fetch("id")
    t_title = db_cursor.fetch("t_title")
    i_width = db_cursor.fetch("i_width")
    i_height = db_cursor.fetch("i_height")
    t_color = db_cursor.fetch("t_color")
except psycopg2.Error as e:
    t_message = "Database error: " + e + "/n SQL: " + s
    return render_template("error.html", t_message = t_message)
db_cursor.close

Analysis: Read window/screen data from PostgreSQL, including screen id, title, dimensions, and color.

Query PostgreSQL for objects data

Now that we have the data we need for the screen, we can query tbl_screens_objects to get all the objects associated with that specific 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
26
27
28
29
30
31
32
s = ""
s += "SELECT"
s += " id"
s += ", t_object_name"
s += ", t_object_type"
s += ", t_object_image_URL"
s += ", i_x"
s += ", i_y"
s += ", i_width"
s += ", i_height"
s += ", i_radius"
s += ", t_color_fill"
s += ", t_color_border"
s += ", t_color_collision"
s += ", t_properties"
s += ", t_collision_sound"
s += ", t_collision_action"
s += ", b_collision_possible"
s += ", b_collision_destroys_it"
s += ", b_collision_awards"
s += ", n_collision_awards"
s += ", n_collision_damage"
s += " FROM tbl_screens_objects"
s += " WHERE ("
s += " id_screen = " + id_screen
s += ")"
s += " ORDER BY i_order"
try:
    db_cursor.execute(s)
except psycopg2.Error as e:
    t_message = "Database error: " + e + "/n SQL: " + s
    return render_template("error.html", t_message = t_message)

Analysis: The query above retrieves all object data for a specific screen.

Draw Sprites from recordset

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
import arcade

# First we open a window with arcade
window_width = i_width # from database
window_height = i_height # from database

# Open the window. Set title and screen size
arcade.open_window(window_width, window_height, t_title)

# Set the bkg color to t_color from tbl_screens
arcade.set_background_color(arcade.color.t_color)

player_x = 100
player_y = 200

# Create first sprite, which is our player
Player = arcade.Sprite(t_object_image_URL, center_x=player_x, center_y=player_y)

# initialize sprite list
arcade.sprite_list = arcade.SpriteList()

# Now iterate through each record (row)
# and draw the object to the screen
for each db_row in db_cursor:
    # get data from database
    id_screen = db_row.fetch("id")
    t_object_name = db_row.fetch("t_object_name")
    t_object_type = db_row.fetch("t_object_type")
    t_object_image_URL = db_row.fetch("t_object_image_URL")
    i_x = db_row.fetch("i_x")
    i_y = db_row.fetch("i_y")
    i_width = db_row.fetch("i_width")
    i_height = db_row.fetch("i_height")
    i_radius = db_row.fetch("i_radius")
    t_color_fill = db_row.fetch("t_color_fill")
    t_color_border = db_row.fetch("t_color_border")
    t_color_collision = db_row.fetch("t_color_collision")
    t_properties = db_row.fetch("t_properties")
    t_collision_sound = db_row.fetch("t_collision_sound")
    t_collision_action = db_row.fetch("t_collision_action")
    b_collision_possible = db_row.fetch("b_collision_possible")
    b_collision_destroys_it = db_row.fetch("b_collision_destroys_it")
    b_collision_awards = db_row.fetch("b_collision_awards")
    n_collision_awards = db_row.fetch("n_collision_awards")
    n_collision_damage = db_row.fetch("n_collision_damage")

    # draw each object in db_cursor to screen
    #  ignoring if player because we already created player as sprite1 above.
    #  This assumes we didn't filter out "player" by changing our SQL WHERE clause.
    if t_object_type == "sprite" and t_object_name != "Player":
        self.SpriteObstacle = arcade.Sprite(t_object_image_URL, i_x, i_y)
        self.sprite_list.append(self.SpriteObstacle)
    elif t_object_type == "sprite" and t_object_name == "Player":
        self.SpritePlayer = arcade.Sprite(t_object_image_URL, i_x, i_y)

db_cursor.close
self.sprite_list.update()
self.sprite_list.draw()

# Keep the window alive until the user clicks close
arcade.run()

Conclusion

In this tutorial, we continued building a game with Python and Postgres with draw sprites as part 2 of a multi-part series of lessons where the final result will be a 2D graphical game. We are using Python’s “Arcade” library for the graphics-related functions. We are using PostgreSQL to store and retrieve screen data so we can have potentially infinite screens in our game. In this lesson we used Postgres to get screen data and draw that data as Sprites. In the next lesson, we’ll learn how to move the player around the game screen. In later parts (future articles in this series), we will address enemies and collision physics in the game and other pieces of what makes an enjoyable Python graphical game.

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.