Tkinter를 사용한 2D 게임 시작하기 (파트 8): 스프라이트에 데몬 이미지 추가

발행: (2025년 12월 24일 오후 02:54 GMT+9)
5 min read
원문: Dev.to

Source: Dev.to

위에 제공된 소스 링크 외에 번역할 텍스트를 알려주시면, 해당 내용을 한국어로 번역해 드리겠습니다.

1. 악마 이미지 준비

게임에 다음 악마 이미지를 복사하여 사용하십시오.

유형생존 이미지파일 이름 (생존)죽은 이미지파일 이름 (죽음)
파란 악마Blue demon alivedmn_alive_b.pngBlue demon deaddmn_dead_b.png
초록 악마Green demon alivedmn_alive_g.pngGreen demon deaddmn_dead_g.png
빨간 악마Red demon alivedmn_alive_r.pngRed demon deaddmn_dead_r.png

images 폴더 안에 모든 이미지 파일을 넣으세요.

# 폴더 구조
project_folder/
├─ main.py
├─ sprite.py
└─ images/
   ├─ bg_jigoku.png
   ├─ dmn_alive_b.png   # 파란 악마 (생존)
   ├─ dmn_alive_g.png   # 초록 악마 (생존)
   ├─ dmn_alive_r.png   # 빨간 악마 (생존)
   ├─ dmn_dead_b.png    # 파란 악마 (죽음)
   ├─ dmn_dead_g.png    # 초록 악마 (죽음)
   └─ dmn_dead_r.png    # 빨간 악마 (죽음)

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

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

die() 메서드 안에서 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)

이렇게 구현하면 스프라이트를 클릭했을 때 움직임이 멈추고 이미지가 살아있는 상태에서 죽은 상태로 전환됩니다.

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

관련 글

더 보기 »