본문 바로가기
개발 일지

파이썬 tkinter 그래픽으로 슈팅 게임 만들기 3

by PrintedLove 2019. 11. 22.

안녕하세요 PrintedLove입니다.

이번 글에서는 물리엔진을 추가해 볼 건데요

 

이번에도 쉬운 이해를 위해 소스코드를 먼저 올리겠습니다.

 

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
from tkinter import *
import time
 
window = Tk()
window.title("nemoRPG")   # 게임 이름
window.resizable(0,0)
canvas = Canvas(window, width = 640, height = 640, bg ="white")   # 창 생성
canvas.pack()
 
class Game:   # 게임 클래스
    global objects
    objects = set()   # 오브젝트 세트 생성
    def __init__(self):
        self.keys = set()   # 버튼 세트 생성
        window.bind("<KeyPress>", self.keyPressHandler)
        window.bind("<KeyRelease>", self.keyReleaseHandler)
 
        obj_main = element(3103102020"black")
 
        while(1):  # 메인 루프
            for key in self.keys:   # 버튼 체킹    
                if obj_main in objects:
                    if key == ord('A'and obj_main.x_accel > -10:   # A 버튼
                        obj_main.x_accel -= 1
                    if key == ord('D'and obj_main.x_accel < 10:   # D 버튼
                        obj_main.x_accel += 1
                    if key == ord('W'and obj_main.y_accel > -10:   # W 버튼
                        obj_main.y_accel -= 1
                    if key == ord('S'and obj_main.y_accel < 10:   # S 버튼
                        obj_main.y_accel += 1
 
            for obj in objects.copy():   # 오브젝트 스텝
                obj.step()
                    
            window.update()   # 업데이트
            time.sleep(0.01)   # 0.01초 만큼 sleep
                        
    def keyPressHandler(self, event):   # 버튼 세트에 버튼추가
        self.keys.add(event.keycode)
 
    def keyReleaseHandler(self, event):   # 버튼 세트에 버튼 제거
        if event.keycode in self.keys:
            self.keys.remove(event.keycode)
 
class element:   # 오브젝트 원형
    def __init__(self, x, y, size_x, size_y, color):
        self.x, self.y = x, y   # 생성 위치
        self.size_x, self.size_y = size_x, size_y   # 크기
        self.color = color   # 색
        self.x_accel, self.y_accel = 00   # 가속도
        objects.add(self)   # 오브젝트 세트에 자신 등록
        self.id = canvas.create_rectangle(x, y, x + self.size_x, y + self.size_y, fill = self.color, width =0)   # 캠버스 추가
 
    def destroy(self):   # 제거 함수
        objects.discard(self)   # 오브젝트 세트에서 자신 제거
        canvas.delete(self.id)   # 캠버스 제거
        del self
 
    def move(self):   # 움직임 계산(이동, 가속도, 중력) 함수
        x_value, y_value = self.x_accel, self.y_accel
        if x_value != 0 or y_value != 0:   # 좌표 갱신
            if canvas.coords(self.id)[0+ x_value < 0:
                x_value = -canvas.coords(self.id)[0]   # 창나감 방지
                self.x_accel = -self.x_accel   # 튕김
            if canvas.coords(self.id)[1+ y_value < 0:
                y_value = -canvas.coords(self.id)[1]
                self.y_accel = -self.y_accel
            if canvas.coords(self.id)[2+ x_value > 640:
                x_value = 640 - canvas.coords(self.id)[2]
                self.x_accel = -self.x_accel
            if canvas.coords(self.id)[3+ y_value > 640:
                y_value = 640 - canvas.coords(self.id)[3]
                self.y_accel = -self.y_accel
            canvas.move(self.id, x_value,  y_value)   # 수치만큼 이동
            self.mx, self.my = 00   # 이동값 초기화
            self.x_accel -= self.x_accel/100   # 가속도 감소
            self.y_accel -= self.y_accel/100
 
    def step(self):
        self.move()
 
Game()   # 게임 실행
cs

 

전체 코드입니다.

달라진 점을 하나하나 살펴보죠.

 

먼저, canvas객체의 틀인 element 클래스에 x_accel 과 y_accel이라는 변수를 추가했습니다.

이 변수는 0 이 아닌 값 (ex. -15, 12)이 입력될 시 객체를 수치만큼 해당 좌표로 이동하게 하는 가속도의 역할을 합니다.

 

여기까진 구현은 쉽습니다. 그냥 해당 값을 canvas.move()함수에 집어넣으면 되니까요.

하지만가속도가 천천히 감소하는 마찰력 효과와 canvas가 창을 나가지 못하게 하기 위해서는 조금 복잡한 식이 필요합니다.

 

때문에 element 클래스에 move라는, 이동 전용 함수를 선언했습니다. 이제 이 함수로 canvas객체의 이동에 관한 모든것을 관리할 것입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def move(self):   # 움직임 계산(이동, 가속도, 중력) 함수
    x_value, y_value = self.x_accel, self.y_accel
    if x_value != 0 or y_value != 0:   # 좌표 갱신
        if canvas.coords(self.id)[0+ x_value < 0:
            x_value = -canvas.coords(self.id)[0]   # 창나감 방지
           self.x_accel = -self.x_accel   # 튕김
        if canvas.coords(self.id)[1+ y_value < 0:
            y_value = -canvas.coords(self.id)[1]
            self.y_accel = -self.y_accel
        if canvas.coords(self.id)[2+ x_value > 640:
            x_value = 640 - canvas.coords(self.id)[2]
            self.x_accel = -self.x_accel
        if canvas.coords(self.id)[3+ y_value > 640:
            y_value = 640 - canvas.coords(self.id)[3]
            self.y_accel = -self.y_accel
        canvas.move(self.id, x_value,  y_value)   # 수치만큼 이동
        self.mx, self.my = 00   # 이동값 초기화
        self.x_accel -= self.x_accel/100   # 가속도 감소
        self.y_accel -= self.y_accel/100
cs

 

위의 코드를 한글로 풀어 써 보면 아래와 같습니다.

 

 

x, y가속도 값을 이동 좌표x, y(지역변수)에 대입

canvas 좌표가 갱신 됬을 시:

   x1 좌표 + x이동 좌표 < 0 일시:

      이동 좌표 - x1 좌표

      x 가속도 반전

   y1 좌표 + y이동 좌표 < 0 일시:

      이동 좌표 - y1 좌표

      y 가속도 반전

   x21 좌표 + x이동 좌표 < 640 일시:

      이동 좌표 - x2 좌표

      x 가속도 반전

   y2 좌표 + y이동 좌표 < 640 일시:

      이동 좌표 - y2 좌표

      y 가속도 반전

이동좌표 값만큼 canvas 이동

x, y가속도 감소

 

 

요지는, 창나감 방지를 위해 오버된 수치만큼만 이동하고 가속도를 반전시켜준다는 것입니다.

 

 

다음에는 공격 오브젝트를 구현해 보도록 하겠습니다.

댓글