Getting Started with 2D Games Using Tkinter (Part 8): Add Demon Images to Sprites
Source: Dev.to
1. Prepare Demon Images
Please copy and use the following demon images in your game.
| Type | Alive Image | File Name (alive) | Dead Image | File Name (dead) |
|---|---|---|---|---|
| Blue Demon | ![]() | dmn_alive_b.png | ![]() | dmn_dead_b.png |
| Green Demon | ![]() | dmn_alive_g.png | ![]() | dmn_dead_g.png |
| Red Demon | ![]() | dmn_alive_r.png | ![]() | dmn_dead_r.png |
Place all image files inside the images folder.
# Folder structure
project_folder/
├─ main.py
├─ sprite.py
└─ images/
├─ bg_jigoku.png
├─ dmn_alive_b.png # Blue demon (alive)
├─ dmn_alive_g.png # Green demon (alive)
├─ dmn_alive_r.png # Red demon (alive)
├─ dmn_dead_b.png # Blue demon (dead)
├─ dmn_dead_g.png # Green demon (dead)
└─ dmn_dead_r.png # Red demon (dead)
2. Improve the DemonSprite Class
Add image‑loading logic inside the constructor of the DemonSprite class.
- Image objects are created with
tkinter.PhotoImage()and displayed usingcanvas.create_image(). - A random demon colour (
"r","g"or"b") is chosen. - The alive image is stored in
self.photo_alive. - The dead image is stored in
self.photo_dead. - The currently displayed image is stored in
self.image.
# sprite.py (excerpt)
def __init__(self, cvs, x, y, r):
self.x = x
self.y = y
self.r = r
self.vx = 0
self.vy = 0
self.dead = False
# Circle (collision reference)
self.oval = cvs.create_oval(
x - r, y - r, x + r, y + r,
fill="white", width=0
)
# Randomly choose demon type: r, g, or b
self.type = random.choice(("r", "g", "b"))
file_alive = f"images/dmn_alive_{self.type}.png"
self.photo_alive = tkinter.PhotoImage(file=file_alive)
file_dead = f"images/dmn_dead_{self.type}.png"
self.photo_dead = tkinter.PhotoImage(file=file_dead)
# Start with the alive image
self.image = cvs.create_image(x, y, image=self.photo_alive)
Update the image inside the die() method using canvas.itemconfig():
# sprite.py (excerpt)
def die(self, cvs):
self.dead = True
self.stop()
# Change the collision circle colour
cvs.itemconfig(self.oval, fill="red")
# Switch to the dead sprite image
cvs.itemconfig(self.image, image=self.photo_dead)
After implementing this, clicking a sprite will stop it and switch its image.

Complete Code
Below is the full implementation with all features applied.
# sprite.py (complete code)
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.vx = 0
self.vy = 0
self.dead = False
# Circle for collision detection
self.oval = cvs.create_oval(
x - r, y - r, x + r, y + r,
fill="white", width=0
)
# Random demon type
self.type = random.choice(("r", "g", "b"))
file_alive = f"images/dmn_alive_{self.type}.png"
self.photo_alive = tkinter.PhotoImage(file=file_alive)
file_dead = f"images/dmn_dead_{self.type}.png"
self.photo_dead = tkinter.PhotoImage(file=file_dead)
# Start with the alive image
self.image = cvs.create_image(x, y, image=self.photo_alive)
def update(self, cvs):
self.x += self.vx
self.y += self.vy
# Update circle position
cvs.coords(
self.oval,
self.x - self.r, self.y - self.r,
self.x + self.r, self.y + self.r
)
# Update image position
cvs.coords(self.image, self.x, self.y)
def set_x(self, x):
self.x = x
def set_y(self, y):
self.y = y
# Additional methods (e.g., stop, die) would go here
Feel free to integrate this class into your main game loop and enjoy the animated demons!
Additional Helper Functions
def move(self, spd, deg):
rad = deg * math.pi / 180
self.vx = spd * math.cos(rad)
self.vy = spd * math.sin(rad)
def stop(self):
self.move(0, 0)
def die(self, cvs):
self.dead = True
self.stop()
cvs.itemconfig(self.oval, fill="red")
cvs.itemconfig(self.image, image=self.photo_dead)
def is_dead(self):
return self.dead
def is_inside(self, x, y):
dx = (self.x - x) ** 2
dy = (self.y - y) ** 2
dist = (dx + dy) ** 0.5
return dist
def on_mouse_clicked(e):
for demon in demons:
if demon.is_inside(e.x, e.y) and not demon.is_dead():
demon.die(cvs)
break
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-1>", on_mouse_clicked)
root.bind("<Motion>", on_mouse_moved)
cvs = tkinter.Canvas(width=W, height=H, bg="black")
cvs.pack()
init()
update()
root.mainloop()
What’s Next?
Thank you for reading!
In the next article, we will display a counter on the screen.
Stay tuned!





