使用 Tkinter 入门 2D 游戏(第 8 部分):向精灵添加恶魔图像

发布: (2025年12月24日 GMT+8 13:54)
4 min read
原文: Dev.to

Source: Dev.to

请提供您希望翻译的完整文本内容,我将按照要求保留源链接并翻译正文部分。

1. 准备恶魔图片

请复制并在你的游戏中使用以下恶魔图片。

类型活动图片文件名(活动)死亡图片文件名(死亡)
Blue DemonBlue demon alivedmn_alive_b.pngBlue demon deaddmn_dead_b.png
Green DemonGreen demon alivedmn_alive_g.pngGreen demon deaddmn_dead_g.png
Red DemonRed demon alivedmn_alive_r.pngRed demon deaddmn_dead_r.png

将所有图片文件放入 images 文件夹。

# 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. 改进 DemonSprite

DemonSprite 类的构造函数中加入图像加载逻辑。

  • 图像对象使用 tkinter.PhotoImage() 创建,并通过 canvas.create_image() 显示。
  • 随机选择恶魔颜色("r""g""b")。
  • 活着的图像保存在 self.photo_alive 中。
  • 死亡的图像保存在 self.photo_dead 中。
  • 当前显示的图像保存在 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

    # 圆形(碰撞参考)
    self.oval = cvs.create_oval(
        x - r, y - r, x + r, y + r,
        fill="white", width=0
    )

    # 随机选择恶魔类型:r、g 或 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)

    # 初始使用活着的图像
    self.image = cvs.create_image(x, y, image=self.photo_alive)

die() 方法中使用 canvas.itemconfig() 更新图像:

# sprite.py (excerpt)
def die(self, cvs):
    self.dead = True
    self.stop()

    # 更改碰撞圆的颜色
    cvs.itemconfig(self.oval, fill="red")

    # 切换为死亡的精灵图像
    cvs.itemconfig(self.image, image=self.photo_dead)

实现上述功能后,点击精灵会使其停止并切换图像。

Demo GIF

完整代码

下面是包含所有功能的完整实现。

# 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

随意将此类集成到你的主游戏循环中,享受动画恶魔吧!

其他辅助函数

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()

接下来是什么?

感谢阅读!

在下一篇文章中,我们将在屏幕上显示计数器

敬请期待!

Back to Blog

相关文章

阅读更多 »