DEV Community

Kajiru
Kajiru

Posted on

Getting Started with 2D Games Using Tkinter (Part 4): Creating Sprites

Creating Sprites

In this article, we will learn about sprites.

In games, objects such as characters are often called sprites.

Here, we will add a new sprite module and define the DemonSprite class.

If needed, it will be helpful to review

Chapter 12: Using Classes beforehand.


Creating the Sprite Module

Create a new file named sprite.py in the same folder as main.py.

working_folder/
 ├ main.py
 ├ sprite.py   <- sprite module
 └ images/
    └ bg_jigoku.png
Enter fullscreen mode Exit fullscreen mode

Defining the DemonSprite Class

Define the DemonSprite class in sprite.py.

(This will be our demon sprite!)

The DemonSprite class is a blueprint that manages the demon’s position and appearance.

It stores:

  • coordinates (x, y)
  • radius (r)

On every screen update, the sprite is redrawn using the update() method.

Using this blueprint, we can mass-produce demon sprites!

In the constructor of DemonSprite, we define the following member variables.

At this stage, it is intentionally simple: position, radius, and a circle object.

# sprite.py (excerpt)
def __init__(self, cvs, x, y, r):
    self.x = x  # x-coordinate
    self.y = y  # y-coordinate
    self.r = r  # sprite radius
    # circle
    self.oval = cvs.create_oval(
        x - r, y - r,
        x + r, y + r,
        fill="white", width=0
    )
Enter fullscreen mode Exit fullscreen mode

The self.oval variable stores the canvas object representing the circle.

The arguments of the cvs.create_oval() method specify:

  • top-left coordinates
  • bottom-right coordinates
  • fill color
  • line width (set to 0 here)

The update() method updates the position of the self.oval object.

# sprite.py
import math
import random
import tkinter

class DemonSprite:

    def __init__(self, cvs, x, y, r):
        self.x = x
        self.y = y
        self.r = r
        self.oval = cvs.create_oval(
            x - r, y - r,
            x + r, y + r,
            fill="white", width=0
        )

    def update(self, cvs):
        # update circle position
        cvs.coords(
            self.oval,
            self.x - self.r, self.y - self.r,
            self.x + self.r, self.y + self.r
        )
Enter fullscreen mode Exit fullscreen mode

Using the DemonSprite Class

By importing the sprite module, we can use the DemonSprite class.

We also import the math and random modules.

# main.py (excerpt)
import math
import random
import sprite
import tkinter
Enter fullscreen mode Exit fullscreen mode

Next, add the following global variables.

# main.py (excerpt)
# number of demons
TOTAL_DEMONS = 10

# demon army
demons = []
Enter fullscreen mode Exit fullscreen mode

In the init() function, we create demon sprites and add them to the demons list.

The demon positions are randomized using the random.random() function.

random.random() returns a floating-point number in the range 0.0 <= x < 1.0.

By multiplying this value by the screen width W, we get a valid x-coordinate.

The same logic applies to the y-coordinate using the screen height H.

# main.py (excerpt)
# demon army
for i in range(TOTAL_DEMONS):
    x = random.random() * W
    y = random.random() * H
    demon = sprite.DemonSprite(cvs, x, y, 20)
    demons.append(demon)
Enter fullscreen mode Exit fullscreen mode

In the update() function, we call the update() method for each demon in the demons list.

# main.py (excerpt)
# demon army
for demon in demons:
    demon.update(cvs)
Enter fullscreen mode Exit fullscreen mode

At this point, running the program will display ten sprites (white circles) on the screen.


Complete Code

Below is the complete implementation up to this point.

# sprite.py
import math
import random
import tkinter

class DemonSprite:

    def __init__(self, cvs, x, y, r):
        self.x = x
        self.y = y
        self.r = r
        self.oval = cvs.create_oval(
            x - r, y - r,
            x + r, y + r,
            fill="white", width=0
        )

    def update(self, cvs):
        cvs.coords(
            self.oval,
            self.x - self.r, self.y - self.r,
            self.x + self.r, self.y + self.r
        )
Enter fullscreen mode Exit fullscreen mode
# main.py
import math
import random
import sprite
import tkinter

W, H = 480, 320

F_RATE = 30
F_INTERVAL = int(1000 / F_RATE)

FONT = ("Arial", 16)

mx, my = 0, 0

bg_photo, bg_image = None, None

TOTAL_DEMONS = 10
demons = []

def init():
    global bg_photo, bg_image

    bg_photo = tkinter.PhotoImage(file="images/bg_jigoku.png")
    bg_image = cvs.create_image(W / 2, H / 2, image=bg_photo)

    for i in range(TOTAL_DEMONS):
        x = random.random() * W
        y = random.random() * H
        demon = sprite.DemonSprite(cvs, x, y, 20)
        demons.append(demon)

def update():
    cvs.delete("hud")

    msg = "x:{}, y:{}".format(mx, my)
    cvs.create_text(
        mx, my,
        text=msg,
        fill="white",
        font=FONT,
        tag="hud"
    )

    for demon in demons:
        demon.update(cvs)

    root.after(F_INTERVAL, update)

def on_mouse_clicked(e):
    print("Clicked:", e.x, e.y)

def on_mouse_moved(e):
    global mx, my
    mx, my = e.x, e.y

root = tkinter.Tk()
root.title("Hello, Tkinter!!")
root.resizable(False, False)
root.bind("<Button>", on_mouse_clicked)
root.bind("<Motion>", on_mouse_moved)

cvs = tkinter.Canvas(width=W, height=H, bg="black")
cvs.pack()

init()
update()
root.mainloop()
Enter fullscreen mode Exit fullscreen mode

What’s Next?

Thank you for reading!

In the next article, we will make the sprites move.

Stay tuned!

Top comments (0)