유치한 게임

[파이썬 간단한 게임 만들기] 6. 날아가는 벌레잡기

ai-creator 2021. 4. 3. 10:55
반응형

유치한 게임에 오신 것을 환영합니다.

이번에는 벌레잡기 게임을 만들어 보겠습니다.

아래와 같은 순서로 배워보겠습니다.

 

1. 목표

2. 사전 준비

3. 소스 코드 (전체)

4. 사전 지식

5. 구현 순서

6. 정리

 

 


1. 목표

이번 장에서는 벌레잡기 게임을 만들어 보도록 하겠습니다.

 

이번에 만들 게임은 벌레잡기 게임입니다. 벌레잡기 게임은 다음과 같습니다.

랜덤한 위치에서 벌레가 생성되며 이 벌레는 자동으로 특정한 방향으로 날아 움직입니다. 이 때, 이 벌레를 마우스로 잡게되면 점수가 쌓이게 되고 제한시간 내에 많은 벌레를 잡는 게임입니다.

 

 

[그림 6-1] 벌레잡기 게임

 

이번 장에서는 이 벌레잡기 게임을 구현하고, 이전 장에서 활용한 x,y축 모두를 활용한 자동 이동을 이용 해보도록 하겠습니다.

날아가는 벌레 표현하기

 

 

2. 연습장

프로젝트를 들어가기 앞서 작은 단위로 연습을 해보아요.

 

1) collidepoint()

- 파란색 사각형을 그리고, 사각형 안을 클릭하면 "catch!" 라는 글자를 출력하게 만드세요.

 

더보기
import pygame # 1. pygame 선언
import random
import time

pygame.init() # 2. pygame 초기화

# 3. pygame에 사용되는 전역변수 선언
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
large_font = pygame.font.SysFont(None, 72)
small_font = pygame.font.SysFont(None, 36)
screen_width = 400
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height)) 

done = False
clock = pygame.time.Clock()

# 4. pygame 무한루프
def runGame():
    global done
    while not done:
        clock.tick(10)
        screen.fill(BLACK)

        for event in pygame.event.get():
            if event.type == pygame.QUIT: # [X] 종료키가 누르면, 게임 종료
                done=True
            elif event.type == pygame.MOUSEBUTTONDOWN:
                 if blue_rect.collidepoint(event.pos) == True:
                    print("catch!!")
                
        blue_rect = pygame.draw.rect(screen, (0, 0, 255), (0, 0, 200, 100))

        pygame.display.update() #모든 화면 그리기 업데이트

runGame()
pygame.quit()

- 이미지를 그리고, 이미지를 클릭하면 "catch!" 라는 글자를 출력하게 만드세요.

 

- 이미지를 그리고, 이미지를 클릭하면 사라진 후 다른 위치에 이미지를 그려보세요.

 

2) time 라이브러리 사용

- 참고) dojang.io/mod/page/view.php?id=2463

- 흘러가는 시간을 출력해보자. (초시계 만들기)

더보기
import pygame # 1. pygame 선언
import random
import time

pygame.init() # 2. pygame 초기화

# 3. pygame에 사용되는 전역변수 선언
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
large_font = pygame.font.SysFont(None, 72)
small_font = pygame.font.SysFont(None, 36)
screen_width = 400
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height)) 

done = False
clock = pygame.time.Clock()

# 4. pygame 무한루프
def runGame():
    global done

    ## 시작시간설정
    start_time = time.time()
    while not done:
        clock.tick(10)
        screen.fill(BLACK)

        for event in pygame.event.get():
            if event.type == pygame.QUIT: # [X] 종료키가 누르면, 게임 종료
                done=True
        
        cur_time = time.time()-start_time
        text = small_font.render("time : " + str(int(cur_time)), True, RED)
        screen.blit(text, (100, 100))
        pygame.display.update() #모든 화면 그리기 업데이트

runGame()
pygame.quit()

 

3. 게임 설계

1) 게임은 어떤 고려사항이 있을까?

3-1) 제한된 시간 설정

3-2) 잡는 벌레 수 카운트

3-3) 랜덤하게 생성되는 벌레

- 생성되는 수

- 이동하는 방법

3-5) 마우스 이벤트 처리 방법

3-6) 글자 출력 방법

 

참고) 설계를 해보자!

 

4. 소스 코드

4-1) 기본 게임판 구성

import pygame # 1. pygame 선언
import random
import time

pygame.init() # 2. pygame 초기화

# 3. pygame에 사용되는 전역변수 선언
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
large_font = pygame.font.SysFont(None, 72)
small_font = pygame.font.SysFont(None, 36)
screen_width = 400
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height)) 

done = False
clock = pygame.time.Clock()

# 4. pygame 무한루프
def runGame():
    global done
    while not done:
        clock.tick(10)
        screen.fill(BLACK)

        for event in pygame.event.get():
            if event.type == pygame.QUIT: # [X] 종료키가 누르면, 게임 종료
                done=True
        
        pygame.display.update() #모든 화면 그리기 업데이트

runGame()
pygame.quit()

 

 

게임을 진행할 화면과 변수를 다음과 같이 설정하도록 하겠습니다.

8번 라인(화면 색) :  black(RGB - 0,0,0)

9번 라인(글자 색 - 게임 오버) :  black(RGB - 0,0,0)

10번 라인(글자 색 - 게임 포인트) :  black(RGB - 0,0,0)

11번 라인(큰 폰트) : fontSize - 72

12번 라인(작은 폰트) : fontSize - 36

15번 라인(화면 크기) : 넓이(width) - 400, 높이(height) - 600/ 400x600

 

4-2) 전체 코드

파일명 : catchBug.py

 

drive.google.com/drive/folders/1P7-ibtlJKUEet1lbqkSAg7N8RyxOza_o?usp=sharing

 

ai-creator 공유폴더(유치한게임) - Google Drive

이 폴더에 파일이 없습니다.이 폴더에 파일을 추가하려면 로그인하세요.

drive.google.com

 

 

 

 

5. 사전 지식

1) 벌레잡기 게임에 필요한 요소 정의

벌레잡기 게임은 게임판 안에서 지속적으로 생성되는 벌레를 잡는 게임입니다. 벌레를 잡는 도구는 마우스를 이용해 진행하기에 저희는 벌레만 생성하면 됩니다.

 

벌레는 이전 장에서 배운 바와 동일하게 벌레 이미지 사이즈에 맞는 사각형을 생성하여 벌레의 위치와 x, y축 이동 속도를 담아 하나 씩 생성하게 됩니다. 모든 벌레의 위치와 이동 속도가 동일 하게 되면 게임이 지루 할 수 있기 때문에, 저희는 벌레의 생성 위치와 이동방향, 속도를 모두 random으로 생성하여 게임 진행을 조금 더 재밌게 하도록 가미 해보겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def runGame():
    score = 0
    start_time = int(time.time())
    remain_time = 0
    game_over = 0
 
    bug_image = pygame.image.load('bug.png')
    bug_image = pygame.transform.scale(bug_image, (6080))
    bugs = []
    for i in range(3):
        bug = pygame.Rect(bug_image.get_rect())
        bug.left = random.randint(0, screen_width)
        bug.top = random.randint(0, screen_height)
        dx = random.randint(-99)
        dy = random.randint(-99)
        bugs.append((bug, dx, dy))
cs

 

벌레와 함께 게임 진행에 필요한 변수를 설정해보도록 하겠습니다.

2번 라인은 벌레를 잡을 때 쌓이게 되는 점수 변수입니다.

3번 라인은 time 라이브러리의 time() 함수를 통해 시작 시간을 입력해줍니다.

4번 라인은 게임 진행 시 남은 시간을 담을 변수 입니다.

5번 라인에서는 게임이 끝나는 플래그를 저장할 변수입니다.

 

7번 라인은 pygame.image.load() 함수를 이용하여 벌레 이미지 파일을 불러오는 코드입니다.

8번 라인은 앞서 불러온 이미지를 게임판 내부에 알맞은 규격으로 재설정 해줍니다. scale() 함수를 통해서 bug_image의 크기를 60x80으로 조절해보겠습니다.

9번 라인은 이후 Rect()로 생성할 벌레들을 담을 리스트를 선언해주는 코드입니다.

10번 라인부터는 총 3개의 벌레을 생성하기 위해 for문을 통해 반복문을 실행해줍니다.

11번 라인은 Rect() 함수를 통해서 벌레 이미지의 사각형 크기를 가져와 네모난 사격형 안에 폭탄 이미지를 넣어주는 코드입니다.

12,13번 라인은 앞서 가져온 사각형의 좌표를 설정해주는데 먼저, left라는 변수를 random 값을 넣어 스크린의 width(size[0]) 안에 속하는 랜덤 x 좌표를 설정해주고, top이라는 변수에는 벌레의 시작점을 설정해줍니다.

14,15번 라인에서는 벌레의 속도를 정해주는 dx, dy 변수를 선언해주는데 각 벌레의 이동 속도를 다르게 하기위해 random.randint() 함수를 통해 랜덤값을 넣어줍니다.

16번 라인은 앞서 생성한 객체와 변수를 벌레 리스트 안에 삽입하는 코드입니다.

 

 

[그림 6-2] 벌레

 

 

2) PyGame 마우스 클릭 처리

벌레잡기 게임에서 score를 쌓는 방법은 벌레를 잡는 것 입니다. 벌레를 잡는 방법은 움직이는 벌레를 마우스로 클릭하면 잡을 수 있게 되는데 이때, 벌레의 현재 좌표와 마우스로 클릭한 좌표가 일치해야 합니다.

 

pygame에서는 이전 장에서 배운 colliderect() 함수와 비슷한, collidepoint()라는 함수를 제공합니다. collidepoint의 차이는 이전앞의 함수는 사각형이 곂치는 검증을 하지만, 이번에 사용할 함수는 point 즉 좌표를 검증합니다.

따라서 마우스 클릭 이벤트가 발생했을 때 좌표를 잡을 수 있는 event.pos를 활용해보도록 하겠습니다.

 

1
2
3
for (bug, dx, dy) in bugs:
    if bug.collidepoint(event.pos):
        bugs.remove((bug, dx, dy))
cs

 

1번 라인에서 앞서 선언한 bugs리스트 안의 요소들을 돌면서 반복문을 실행하도록 합니다.

2,3번 라인에서 bug의 사각형을 이용하여 collidepoint() 함수에 마우스 클릭 좌표를 인자로 넣어 접촉을 판단합니다. 접촉이 되면(True 가 리턴) 벌레를 리스트 안에서 지워주도록 합니다.

 

 

6. 구현 순서

구현 순서는 다음과 같습니다.

Step1 마우스 이벤트 처리를 통한 벌레 잡기
Step2 벌레 출력하기
Step3 스코어 출력하기

 

Step1) 마우스 이벤트 처리를 통한 벌레 잡기

 

먼저 마우스 클릭을 통해서 벌레를 잡아 보도록 하겠습니다. 마우스 클릭 이벤트 처리는 MOUSEBUTTONDOWN 이벤트를 활용합니다. 마우스 버튼 이벤트가 발생하면 위에서 학습한 collidepoint() 함수를 활용하여 벌레를 정확히 클릭하게 되면 해당 벌레를 없애고 score를 쌓도록 합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for event in pygame.event.get():
    if event.type == pygame.QUIT:
        break
    elif event.type == pygame.MOUSEBUTTONDOWN and game_over == 0:
        print(event.pos[0], event.pos[1])
        for (bug, dx, dy) in bugs:
            if bug.collidepoint(event.pos):
                print(bug)
                bugs.remove((bug, dx, dy))
                bug = pygame.Rect(bug_image.get_rect())
                bug.left = random.randint(0, screen_width)
                bug.top = random.randint(0, screen_height)
                dx = random.randint(-99)
                dy = random.randint(-99)
                bugs.append((bug, dx, dy))
                score += 1
cs

 

 

먼저 MOUSEBUTTONDOWN 이벤트를 통해 마우스 버튼이 눌러진 이벤트를 캐치하고, game_over의 플래그를 확인해줍니다.

6~9번 라인은 앞서 작성한 bugs 리스트의 각각 벌레의 좌표를 확인하며 해당하는 벌레가 있으면 리스트에서 벌레를 삭제 해줍니다.

10~15번 라인은 벌레가 사라짐과 동시에 앞서 생성한 것 처럼 새로운 벌레를 랜덤한 좌표, x y축 이동속도를 적용하여 새롭게 리스트에 추가해주도록 합니다.

16번 라인은 벌레를 한마리 잡았을 때, score에 1을 더해 점수를 높히도록 합니다.

 

 

Step2) 벌레 출력하기

 

이번에는 앞서 작성한 코드를 기반으로 벌레를 게임판에 출력해보도록 하겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if game_over == 0:
    for (bug, dx, dy) in bugs:
        bug.left += dx
        bug.top += dy
 
    remain_time = 60 - (int(time.time()) - start_time)
 
    if remain_time <= 0:
        game_over = 1
 
for (bug, dx, dy) in bugs:
    screen.blit(bug_image, bug)
 
for (bug, dx, dy) in bugs:
    if not bug.colliderect(screen.get_rect()):
        bugs.remove((bug, dx, dy))
        bug = pygame.Rect(bug_image.get_rect())
        bug.left = random.randint(0, screen_width)
        bug.top = random.randint(0, screen_height)
        dx = random.randint(-99)
        dy = random.randint(-99)
        bugs.append((bug, dx, dy))
cs

 

1번 라인에서 먼저 game_over의 플래그를 체크해줍니다.

2~4번 라인은 벌레 리스트 안의 벌레들의 위치 값에 이동 속도를 적용하여 각 x y 좌표로 이동하게 해줍니다.

6번 라인은 게임 내부에서 진행시간에 맞추어 각 시간초를 설정합니다. 게임당 진행 시간인 60초에 현재 시간에(time.time())에 게임을 시작할 때 시간을 빼 진행시간을 체크하게 됩니다.

8,9번 라인은 남은 시간이 0이 되면 game_over 플래그를 1로 설정하여 게임을 끝내도록 해줍니다.

11,12번 라인은 blit()함수를 이용하여 bug_image를 통해 화면에 벌레를 출력하도록 합니다.

 

 

[그림 6-3] 벌레의 이동방향

 

 

14~22번 라인은 게임판 내부에서 벌레의 위치가 벗어나게 되면 벌레를 없애고 새롭게 생성하는 코드입니다.

이전에는 게임판의 상하좌우 처리를 모두 다르게 했지만 이번에는 게임판 어디로든 벗어나게 되면 처리를 해주면 되기에, colliderect() 함수를 사용하여 조금 더 간단하게 구현할 수 있습니다. screen의 사각형 안에 bug가 속하지 않으면 벌레를 삭제하고 새롭게 생성해주도록 합니다.

 

 

 

[그림 6-4] 벌레의 게임판 out

 

 

Step3) 스코어 출력하기

마지막으로 작성된 스코어 처리와 game_over 플래그를 통해 게임 종료 메세지를 출력하고, 시간까지 출력하도록 해보겠습니다.  

 

1
2
3
4
5
6
7
8
9
score_image = small_font.render('Point {}'.format(score), True, YELLOW)
screen.blit(score_image, (1010)
 
remain_time_image = small_font.render('Time {}'.format(remain_time), True, YELLOW)
screen.blit(remain_time_image, (screen_width - 10 - remain_time_image.get_width(), 10)
 
if game_over == 1:
    game_over_image = large_font.render('GameOver'True, RED)
    screen.blit(game_over_image, (screen_width // 2 - game_over_image.get_width() // 2, screen_height // 2 - game_over_image.get_height() // 2))
cs

 

1,2번 라인은 점수(score)를 출력해줍니다. 앞서 선언한 small_font를 이용해서 score를 출력하도록 하고 blit() 함수를 통해 게임판에 출력합니다.

4,5번 라인은 점수와 동일하게 남은 시간을 화면에 출력하도록 합니다.

7~9번 라인은 game_over 플래그가 1이 됐을 때, large_font를 이용해 게임 화면 정 가운데(screen_width // 2 - game_over_image.get_width() // 2, screen_height // 2 - game_over_image.get_height() // 2)에 출력하도록 합니다.

 

 

[그림 6-5] 게임화면 글자 출력

 

 

 

6. 정리

이번 장에서는 앞서 배운 pygame의 기본 구조와 게임 루프, 이벤트 처리를 기반으로 마우스 클릭 처리와 좌표(event.pos)를 통해 벌레잡기 게임을 구현해 보았습니다.

 

먼저, 게임에 필요한 요소 정의를 하고 마우스 클릭 처리를 통해 게임 흐름을 진행할 수 있도록 사전학습을 한 뒤 진행을 했으며,

Step 1) 마우스 이벤트 처리를 통한 벌레 잡기 -> 마우스 클릭 이벤트와 collidepoint()를 활용한 좌표 처리

Step 2) 벌레 출력하기 -> 이동속도 dx, dy를 설정하여 벌레 이동값을 통한 출력

Step 3) 스코어 출력하기 -> 플래그를 이용한 게임 종료 처리 및 time.time()을 활용한 시간 처리

를 배웠습니다.

 

이번 장에는 pygame과 마우스 이벤트 처리 및 collidepoint() 함수를 사용하며 여러 상황에 맞는 이벤트 처리를 주로 다뤘습니다. 이번 게임에서도 더 많은 벌레를 출력하고 다양한 크기의 벌레를 출력하도록 하여 게임의 요소를 더 할 수 있습니다. 이번 장의 학습을 기반으로 더 재밌게 게임을 구성해보는 것도 좋은 학습이 됩니다^^

 

ㅁ 참고

토닥토닥 파이썬

 

 


도움이 되셨다면, 좋아요 / 구독 버튼 눌러주세요~

 

저작물의 저작권은 작성자에게 있습니다.
공유는 자유롭게 하시되 댓글 남겨주세요~
상업적 용도로는 무단 사용을 금지합니다.
끝까지 읽어주셔서 감사합니다^^

 

반응형