프로그램언어+/Python

파이썬 게임만들기(공피하기)

logthink 2018. 12. 11. 12:41

처음으로 파이썬으로 GUI환경에 입문한다.

그동안 콘솔에만 찍거나 앱 어플리케이션, 웹 어플리케이션 작업을 했었기에 조금 신세계(?)였다. 무튼 시작하자.

이 프로젝트는 외주 프로젝트였으며, legacy.py를 받고, 이 게임에 이미지 리소스를 추가하고 싶다는 것이였다.

그래서 기존에 turtle 모듈사용했던것을, 이미지 사용이 가능한 pygame모듈을 사용했고, 게임진행을 조금 업그레이드 했다.
해당 소스코드 밑에 이미지를 참조!!!


프로젝트 변경(전)



○ 기존 게임 방식

-흰색 turtle이 (turtle모듈의 클래스를 객체화한것) 초록색 turtle을 닿는다.

-스코어가 오른다.

-빨간색 turtle과 부딪히면 게임이 종료되고, 스코어가 나오는방식.


legacy.py

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
import pygame
import turtle as t
import random
 
score = 0 # 점수 저장
playing = False #현재 게임이 플레이 중인지 확인하는 함수
te = t.Turtle()
#te.shape("turtle")
te.color("red")
te.speed(150)
te.up()
te.goto(0,200)
 
ts = t.Turtle()
#ts.shape("circle")
ts.color("green")
ts.speed(20)
ts.up()
ts.goto(0,-200)
 
def turn_right():
    t.setheading(0)
def turn_up():
    t.setheading(90)
def turn_left():
    t.setheading(180)
def turn_down():
    t.setheading(270)
def start(): #게임을 시작하는 함수
    global playing
    if playing ==False:
        playing =True
        t.clear() #메시지를 지움
        play()
def play():
    global score #
    global playing #
    t.fd(20) #w
    if random.randint(1,5) == 3: #1에서 5까지 임의수를 뽑는건데 임의수=3이면의 가정(20%확률)
        ang = te.towards(t.pos()) #position
        te.setheading(ang)
    speed = score + 25 #점수가 올라가면 빨라짐
    if speed > 115: #속도가 15를 넘지 않게함
        speed = 15
    te.forward(speed)
    if t.distance(te) < 12: #주인공과 거리가 12보다 작으면 게임을 종료함
        text = "Score:" +str(score)
        message("Game Over", text)
        playing = False
        score = 0
    if t.distance(ts) < 12: #주인공과 거리가 12보다 작으면
        score = score + 1 #점수를 올림
        t.write(score)#점수를 화면에 표시
        star_x = random.randint (-230, 230)
        star_y = random.randint (-230, 230)
        ts.goto(star_x, star_y) #먹이를 옮김
    if playing:
        t.ontimer(play, 100)
 
def message(m1,m2): #메세지를 화면에 표시
    t.clear()
    t.goto(0,100)
    t.write(m1, False, "center", ("", 20))
    t.goto(0, -100)
    t.write(m2, False, "center", ("", 15))
    t.home()
 
t.title("Turtle Run") #제목
t.setup(500,500)
t.bgcolor("orange")
#t.shape("turtle")
t.speed(0)
t.up()
t.color("white")
t.onkeypress(turn_right, "Right") #방향키 오른쪽 화살표
t.onkeypress(turn_up, "Up")
t.onkeypress(turn_left, "Left")
t.onkeypress(turn_down, "Down")
t.onkeypress(start, "space") #시작
t.listen()
message("Turtle Run", "[space]") #첨가
 
cs

이와 같다. 실행화면은 캡쳐했다.

프로젝트 변경(후)



○ 게임 방식
-이미지로 만든 플레이어를 상하좌우 대각선으로 이동
-돌아다니는 쥐를 피할 수록 스코어 오름
-부딪히는 순간 게임끝(스코어 계산)

avoid.py


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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
import  pygame, time, random
'''
기본 
1. 파이게임 모듈 불러오기
2. 초기화 시킨다.
3. 이미지를 가져온다.
4. 계속 화면이 보이도록 한다.
    #####(반복문 시작)#######
   5. 화면을 깨끗하게 한다
   6. 모든 요소들을 다시 그린다
   7. 화면을 다시 그린다
   8. (종료조건시 ESC)게임 종료
www.pygame.org/docs/ref/time.html
ref : https://www.youtube.com/watch?v=EswYaZH4ZAQ
'''
#초기화 작업
pygame.init()
#디스플레이 크기
display_width=800
display_height=600
#폰트, 이미지 변수 선언
font_style="C:/Users/namki/Desktop/mosproject-master/Source/MineSweeper/Assets/ExternalPlugin/Effect/Shared/Fonts/Roboto-Thin.ttf"
p1="C:\\Users\\namki\\Desktop\\외주디렉터리\\hwang\\game-project\\resources\\images\\dude.png".replace('\\\\','/')
p2="C:\\Users\\namki\\Desktop\\외주디렉터리\\hwang\\game-project\\resources\\images\\badguy.png".replace('\\\\','/')
#디스플레이 모드
gameDisplay = pygame.display.set_mode((display_width, display_height))
#FPS
clock = pygame.time.Clock()
#이미지 로드
playerImg = pygame.image.load(p1)
attackerImg = pygame.image.load(p2)
#주인공 class선언
class Player(object):
    x=0
    y=0
    x_speed=0
    y_speed=0
    speed_bouns = 0
    width=40
    height=40
    
    def __init__(self, x, y): #이동좌표
        self.x=x
        self.y=y
    def update(self):  #공 속도 조절
        #방향키 누를때 위치 값
        if self.x_speed > 0:
            self.x_speed += self.speed_bouns
        elif self.x_speed < 0:
            self.x_speed -= self.speed_bouns
 
        if self.y_speed > 0:
            self.y_speed += self.speed_bouns
        elif self.y_speed < 0:
            self.y_speed -= self.speed_bouns
           
        self.x += self.x_speed# + self.speed_factor
        self.y += self.y_speed# + self.speed_factor        
        gameDisplay.blit(playerImg, (self.x, self.y))
    #전체적인 속도
    def left_bound(self):
        if self.x <=0:
            self.x_speed = self.x_speed * -1
    def right_bound(self):
        if self.x >= display_width - self.width:
            self.x_speed = self.x_speed * -1
    def top_bound(self):
        if self.y <=0:
            self.y_speed = self.y_speed * -1
    def bottom_bound(self):
        if self.y >=display_height - self.height:
            self.y_speed = self.y_speed * -1
    def bound(self):
        self.left_bound()
        self.right_bound()
        self.top_bound()
        self.bottom_bound()
    
    def rectangle(self): #플레이어랑 부딪히는 포인트
        return  pygame.Rect(self.x, self.y, self.width, self.height)
#방해물 클래스
class Attacker(object):
    x=0
    y=0
    x_speed=0
    y_speed=0
    width=40
    height=40
    has_reached_limit = False
    side=0
    
    def __init__(self):
        #총 4개의 keytype
        self.side = random.randint(1,4) #self.side =4   
        if self.side == 1: #왼쪽
            self.x = -60
            self.y = random.randint(0, display_height-self.height)
            self.x_speed = 10
        elif self.side == 2:#위
            self.x = random.randint(0, display_width-self.width)
            self.y=-60
            self.y_speed=10
        elif self.side == 3:#오른쪽
            self.x = display_width + 60
            self.y=random.randint(0, display_height-self.height)
            self.x_speed=-10
        elif self.side == 4:#아래
            self.x = random.randint(0, display_width-self.width)
            self.y=display_height+60
            self.y_speed=-10
    def update(self):
        self.x +=  self.x_speed
        self.y +=  self.y_speed
        gameDisplay.blit(attackerImg, (self.x, self.y))
        #떠다니는 공에 대한 산술식
        if self.side == 1 and self.x > display_width:
            self.has_reached_limit = True
        if self.side == 2 and self.y > display_height:
            self.has_reached_limit = True
        if self.side == 3 and self.x < -40:
            self.has_reached_limit = True
        if self.side == 4 and self.y < -40:
            self.has_reached_limit = True
        
    def rectangle(self): #닿는 좌표포인트
        return  pygame.Rect(self.x, self.y, self.width, self.height)
    
    def left_bound(self):
        if self.x <=0:
            self.x_speed = self.x_speed * -1
    def right_bound(self):
        if self.x >= display_width - self.width:
            self.x_speed = self.x_speed * -1
    def top_bound(self):
        if self.y <=0:
            self.y_speed = self.y_speed * -1
    def bottom_bound(self):
        if self.y >=display_height - self.height:
            self.y_speed = self.y_speed * -1
    def bound(self):
        self.left_bound()
        self.right_bound()
        self.top_bound()
        self.bottom_bound()
 
def game_loop(): #게임 무한 루프
    player = Player(display_width/2, display_height/2)
    attackers = []
    difficulty = 1.0
    score=0
    gameDisplay.fill((255,255,255))
    player.update() 
    pygame.display.update() 
    #gameDisplay.blit(playerImg, (player.x, player.y))
    alive = True
    while alive:        
        for event in pygame.event.get():
            if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and (event.key == pygame.K_ESCAPE)):
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    player.x_speed = 2
                if event.key == pygame.K_LEFT:
                    player.x_speed = -2
                if event.key == pygame.K_DOWN:
                    player.y_speed = 2
                if event.key == pygame.K_UP:
                    player.y_speed = -2
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT:
                    player.x_speed = 0                                    
                if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                    player.y_speed = 0
                
        gameDisplay.fill((255, 255, 255))
        player.bound()
        player.update()
        if len(attackers) < difficulty:
            attackers.append(Attacker())            
        ball_index = 0 #볼 기준점
        for ball in attackers: #볼을 계속해서 생성
            ball.update()  #볼을 다시 화면에 그리기
            if ball.rectangle().colliderect(player.rectangle()): #볼이랑 부딪혔을때
                death_screen(score) #게임끝
                
            if ball.has_reached_limit:   #볼 제한걸기             
                attackers.pop(ball_index ) #볼 하나씩 뺌
                ball_index -= 1
                player.speed_bouns += 0.01 
                score += 1  #점수
                difficulty += 0.1  #난이도
                #print("score : {},  difficulty: {}, player.speed_bouns : {}".format(score, difficulty,player.speed_bouns )
        pygame.display.update() #화면에 전체 다시 그리기 flip()도 가능
        clock.tick(160) #FPS
        
def main_screen():  #게임시작 전 첫 화면(스코어 화면)
    gameDisplay.fill((0, 0, 0))
    text = pygame.font.Font(font_style, 60)
    text_on_screen = text.render("공 피하기 게임 \n let's go \n (게임종료는 ESC)", True, (255, 255, 255))
    text_rect = text_on_screen.get_rect()
    text_rect.center = ((display_width/2), (display_height/2))
    gameDisplay.blit(text_on_screen, text_rect)
    pygame.display.update()    
    time.sleep(2) #게임 시작 딜레이
    game_loop()
def death_screen(score):  #죽었을때 첫 화면(스코어 화면)
    gameDisplay.fill((0, 0, 0))
    text = pygame.font.Font(font_style, 60)
    msg="gameover !! \n score : {}".format(int(score))
    text_on_screen = text.render(msg, True, (255, 255, 255))
    text_rect = text_on_screen.get_rect()
    text_rect.center = ((display_width/2), (display_height/2))
    gameDisplay.blit(text_on_screen, text_rect)
    pygame.display.update()
    time.sleep(2)
    main_screen()
    
main_screen()
 
 
cs