Python

[python/Game] 파이썬으로 게임만들기(3) - 인트로&아웃트로 추가하기

wonhwa 2023. 2. 13. 16:45
반응형

안녕하세요.

이번에는 저번 pygame포스팅에 이어서 인트로와 아웃트로를 추가해 주도록 하겠습니다.

- 인트로: 게임 설명 및 시작, 종료 버튼 추가

- 아웃트로: 게임 스코어 안내 및 다시시작, 종료 버튼 추가

저번에는 따로 함수를 만들지 않았는데 이번에는

intro, game, outro 함수를 각각 만들어 연결해 보도록 하겠습니다.

이번 게시물의 결과물을 아래에서 미리 확인해 보세요:)

Preview

 

게임 기본 설정
import pygame, sys
from pygame.locals import *
import random, time

pygame.init()

# 초당 프레임 설정
FPS = 60
FramePerSec = pygame.time.Clock()

# 색상 세팅(RGB코드)
RED = (255, 0, 0)
ORANGE = (255, 153, 51)
YELLOW = (255, 255, 0)
GREEN = (0, 255, 0)
SEAGREEN = (60, 179, 113)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
VIOLET = (204, 153, 255)
PINK = (255, 153, 153)

GREY = (213,213,213)
LIGHT_GREY = (246,246,246)
LIGHT_BLACK = (76,76,76)
# 게임 진행에 필요한 변수들 설정
SPEED = 5  # 게임 진행 속도
SCORE = 0  # 플레이어 점수

# 폰트 설정
font = pygame.font.SysFont('Tahoma', 60)  # 기본 폰트 및 사이즈 설정(폰트1)
small_font = pygame.font.SysFont('Malgun Gothic', 20,bold=True)  # 작은 사이즈 폰트(폰트2)
middle_font = pygame.font.SysFont('Malgun Gothic', 40) # 중간 사이즈 폰트(폰트3)
game_over = font.render("GG", True, BLACK)  # 게임 종료시 문구

# 게임 배경화면
background = pygame.image.load('resources/background1.jpg')  # 배경화면 사진 로드

# 게임 화면 생성 및 설정
display_width = 640
display_height = 440
GameDisplay = pygame.display.set_mode((display_width,display_height))
GameDisplay.fill(PINK)
pygame.display.set_caption("Mini Game")

#점수 reset함수
def reset():
    global SCORE
    SCORE = 0
    return SCORE

 

Button 함수 만들기

Intro,outro에 사용할 버튼을 간단하게 만들기 위해 버튼을 만드는 함수를 하나 추가해 줍니다.

이 버튼 함수는 버튼 영역 안에 마우스 포인터가 들어가면 색이 바뀌고 클릭 시 True값을 return 합니다.

더 자세히 설명하자면 아래와 같습니다.

button(버튼안에 들어갈 메세지, x좌표,y좌표, 도형의가로길이,도형의세로길이,도형색, 포인터가 도형위에 위치시 변하는 색, action=True(클릭했을 때 이벤트 활성화), 버튼글씨색 설정 )

#버튼 생성 함수
def button(msg,x,y,w,h,ic,ac,action=None,fcolor=BLACK):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    #print(click)
    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.ellipse(GameDisplay, ac,(x,y,w,h))

        if click[0] == 1 and action != None:
            return True
    else:
        pygame.draw.ellipse(GameDisplay, ic,(x,y,w,h))

    textSurf = middle_font.render(msg,True,fcolor)
    textRect = textSurf.get_rect()
    textRect.center = ( (x+(w/2)), (y+(h/2)) )
    GameDisplay.blit(textSurf, textRect)

 

Intro 만들기

게임 설명 텍스트를 위치시켜주고,

start, quit 버튼을 만들어서

start를 누를 시 게임을 시작하고, quit을 누르면 창이 닫히도록 game_intro 함수를 만들어 주었습니다.

# 시작(intro) 화면
def game_intro():
    intro = True

    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        # 배경화면 사진 게임창에 불러오기(사진, 위치)
        GameDisplay.blit(background, (0, 0)) #TODO
        # 텍스트 생성 및 배치하기
        large_Text = pygame.font.SysFont('Tahoma', 100)
        Text1,Text1Rect = text_objects("How to Play",large_Text)
        Text2,Text2Rect = text_objects("Use ← , → to avoid bombs!",middle_font)
        Text3,Text3Rect = text_objects("방향키 ← , →를 사용하여 폭탄을 피하세요!",small_font)
        Text1Rect.center = ((display_width/2),(display_height/4.5))
        Text2Rect.center = ((display_width/2),(display_height/2.5))
        Text3Rect.center = ((display_width/2),(display_height/2))
        GameDisplay.blit(Text1, Text1Rect)
        GameDisplay.blit(Text2,Text2Rect)
        GameDisplay.blit(Text3,Text3Rect)
        #start,quit버튼
        introBtn1 = button("START",display_width/6,display_height/1.7,200,100,BLACK,BLUE,action=True,fcolor=YELLOW)
        introBtn2 = button("QUIT",display_width/2,display_height/1.7,200,100,BLACK,RED,action=True,fcolor=YELLOW) 
        #버튼을 눌렀을 때
        if introBtn1 == True:
            return game()
        if introBtn2 ==True:
            pygame.quit()
            quit()
        pygame.display.update()
        FramePerSec.tick(FPS)

 

게임에서 동작할 class 만들기

게임에서 사용할 플레이어 및 적 개체 class를 저번 처럼만들어 줍니다.

## 게임 내에서 동작할 클래스 설정 ##

## 플레이어에게 적용할 클래스
class Player(pygame.sprite.Sprite):
    # 플레이어 이미지 로딩 및 설정 함수
    def __init__(self):
        super().__init__()
        # 플레이어 사진 불러오기
        self.image = pygame.image.load('resources/chick.png')
        # 이미지 크기의 직사각형 모양 불러오기
        self.rect = self.image.get_rect()
        # rec 크기 축소(충돌판정 이미지에 맞추기 위함)
        self.rect = self.rect.inflate(-20,-20)
        # 이미지 시작 위치 설정
        self.rect.center = (540, 390)

    # 플레이어 키보드움직임 설정 함수
    def move(self):
        prssdKeys = pygame.key.get_pressed()
        # 왼쪽 방향키를 누르면 5만큼 왼쪽 이동
        if self.rect.left > 0:
            if prssdKeys[K_LEFT]:
                self.rect.move_ip(-5, 0)
                position_p = self.rect.center
                return position_p
        # 오른쪽을 누르면 5만큼 오른쪽으로 이동
        if self.rect.right < 640:
            if prssdKeys[K_RIGHT]:
                self.rect.move_ip(5, 0)
                position_p = self.rect.center
                return position_p


## 적에게 적용할 클래스
class Enemy(pygame.sprite.Sprite):

    # 적의 이미지 로딩 및 설정 함수
    def __init__(self):
        super().__init__()
        # 적 사진 불러오기
        self.image = pygame.image.load('resources/boom2.png')
        # 이미지 크기의 직사각형 모양 불러오기
        self.rect = self.image.get_rect()
        # rec 크기 축소(충돌판정 이미지에 맞추기 위함)
        self.rect = self.rect.inflate(-20,-20)
        # 이미지 시작 위치 설정
        self.rect.center = (random.randint(40, 600), 0)

    # 적의 움직임 설정 함수+ 플레이어 점수 측정
    def move(self):
        global SCORE

        # 적을 10픽셀크기만큼 위에서 아래로 떨어지도록 설정
        self.rect.move_ip(0, SPEED)  # x,y좌표 설정
        # 이미지 가 화면 끝에 있으면(플레이어가 물체를 피하면) 다시 이미지 위치 세팅 + 1점 추가
        if (self.rect.bottom > 440):
            SCORE += 1
            self.rect.top = 0
            self.rect.center = (random.randint(30, 610), 0)
        return self.rect.center
게임 만들기

이제 위의 클래스를 사용하여 폭탄 피하기 게임을 만들어 줍니다.

게임 종료 시 outro화면으로 넘어갈 수 있도록 설정하는 것도 잊지 말고 넣어 줍니다.

###### 게임 설정 ########
# 플레이어 및 적 개체 생성
def game(speed = SPEED):

    P1 = Player()

    E1 = Enemy()

    # Sprites Groups 생성하기
    # 게임 물체들을 그룹화 하여 그룹별로 접근하여 설정 시 용이하게 만들기
    # 적(enemy) 객체 그룹화하기
    Enemies = pygame.sprite.Group()
    Enemies.add(E1)
    # 전체 그룹을 묶기
    All_groups = pygame.sprite.Group()
    All_groups.add(P1)
    All_groups.add(E1)

    # 적 개체 1초(1000ms)마다 새로 생기는 이벤트 생성
    increaseSpeed = pygame.USEREVENT + 1
    pygame.time.set_timer(increaseSpeed, 1000)

    # 게임 BGM 설정
    bgm = pygame.mixer.Sound('resources/backgroundMusic.mp3')
    bgm.play()
    ## 게임 루프 설정 ##
    # 게임 종료되기 전까지 실행되는 루프(이벤트) 설정
    while True:
        for event in pygame.event.get():
            # type increaseSpeed이면 속도 증가하여 어렵게 만듬(적 물체 이벤트)
            if event.type == increaseSpeed:
                speed += 0.5
            # 이벤트가 종료되면 게임도 종료시킴
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

        # 배경화면 사진 게임창에 불러오기(사진, 위치)
        GameDisplay.blit(background, (0, 0))
        # 하단부에 위치할 스코어 점수(적을 피할때마다 +1점 증가)
        scores = small_font.render("Score: " + str(SCORE), True, BLACK)
        GameDisplay.blit(scores, (10, 400))

        # group1 = '<Player Sprite(in 1 groups)>'
        # group2 = '<Enemy Sprite(in 2 groups)>'

        # 게임 내 물체 움직임 생성
        for i in All_groups:
            GameDisplay.blit(i.image, i.rect)
            i.move()
            if str(i) == '<Player Sprite(in 1 groups)>':
                player_pos = i
            else:
                enemy_pos = i

        # <Player Sprite(in 1 groups)>
        # 플레이어 충돌 판정(게임종료)시
        if pygame.sprite.spritecollideany(P1, Enemies):
            for i in All_groups:
                i.kill()
            # 물체 이미지 변경(충돌후 변경되는 이미지)
            # 플레이어
            GameDisplay.blit(background, (0, 0))
            image0 = pygame.image.load('resources/chickbommed.png')
            image0.get_rect()
            GameDisplay.blit(image0, player_pos)

            # 폭탄
            image1 = pygame.image.load('resources/boomm.png')
            image1.get_rect()
            GameDisplay.blit(image1, enemy_pos)
            pygame.display.update()

            # 배경음악 멈춤
            bgm.stop()
            # 적과 충돌시 효과음 추가
            pygame.mixer.Sound('resources/BOOM.WAV').play()
            time.sleep(0.5)
            # 게임오버화면 설정
            pygame.mixer.Sound('resources/gameover.mp3').play()
            pygame.display.update()
            game_outro()

        pygame.display.update()
        # 초당 프레임 설정
        FramePerSec.tick(FPS)

 

Outro 만들기

게임 종료 화면을 만들어 줍니다.

게임 점수를 배치하고 버튼을 배치하여,

다시 플레이하고 싶은 사람은 score 리셋 후 retry를, 종료하고 싶은 사람은 quit을 눌러 창을 닫을 수 있도록 설정합니다.

## 게임오버 페이지
def game_outro():
    outro = True

    while outro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        GameDisplay.blit(background, (0, 0))
        final_scores = font.render("Your Score: " + str(SCORE), True, BLACK)
        Music = small_font.render("Music: www.bensound.com",True,BLACK)
        Photos = small_font.render("Photos: pixabay, pngwing",True,BLACK)
        Madeby = small_font.render("Made by wonhwa.tistory.com",True,BLACK)
        GameDisplay.blit(final_scores, (150, 100))
        GameDisplay.blit(game_over, (280, 200))
        GameDisplay.blit(Music,(10,400))
        GameDisplay.blit(Photos,(10,380))
        GameDisplay.blit(Madeby,(350,400))
        #retry,quit버튼
        outroBtn1 = button("RETRY",display_width/6,display_height/1.7,200,100,BLACK,BLUE,action=True,fcolor=YELLOW)
        outroBtn2 = button("QUIT",display_width/2,display_height/1.7,200,100,BLACK,RED,action=True,fcolor=YELLOW)
        #time.sleep(1)
        #pygame.display.update()
        #time.sleep(5) 
        #TODO: 버튼 누르면 동작
        if outroBtn1 == True:
            reset()
            game()
        if outroBtn2 ==True:
            pygame.quit()
            sys.exit()
        pygame.display.update()
        FramePerSec.tick(FPS)

 

게임 시작!

이제 만들어둔 함수를 호출하여 게임을 시작할 수 있습니다.

#####게임 시작#####
game_intro()

 

게임 파일

게임 파이썬 파일을 .exe파일로 만들어 보았습니다.(용량이 259MB로 꽤 큽니다..)

해보고 싶은 분들은 다운받아 실행해보시길 바랍니다 :)

https://drive.google.com/file/d/1fZGR-vbcTgAvsYqhsIh5lmnWSORJ0I0a/view?usp=sharing 

 

minigame.exe

 

drive.google.com

.py를 .exe로 만드는 방법은 아래의 링크를 참고해 주세요.

https://wonhwa.tistory.com/66

 

[python] pyinstaller로 이미지,소리파일이 포함된 .exe파일 만들기(feat.pygame)

안녕하세요. 그동안 python으로 여러 프로그램을 만들어 보았는데, 그걸 다른 사람에게도 보여주고 싶을 때는 1. python 설치 2. .py 파일 실행 이렇게 번거로운 과정이 필요할 것입니다. 하지만 그동

wonhwa.tistory.com

 

전체 코드

https://github.com/ElenaLim/Pygame/blob/main/minigame_ver1.1.py

 

GitHub - ElenaLim/Pygame: Minigame using Pygame

Minigame using Pygame. Contribute to ElenaLim/Pygame development by creating an account on GitHub.

github.com

참고자료

https://wonhwa.tistory.com/45

 

[python/Game] 파이썬으로 게임만들기(2) - 미니게임

이번 포스팅에서는 미니 게임을 pygame을 사용하여 만들어 보도록 하겠습니다. preview 이 게임은 병아리가 폭탄을 피하고 부딪히면 게임이 종료되는 미니게임 입니다. 게임 구성 1. 게임 화면 설정

wonhwa.tistory.com

https://pythonprogramming.net/pygame-button-function/

 

Python Programming Tutorials

PyGame Progress: 0% --> PyGame Buttons, part 4, creating a general PyGame button function Now that we've got some fancy code coming along, it's time to move all of this to a function, so that we can use this dynamically to create other buttons, rather than

pythonprogramming.net

 

마무리

그동안 저번에 만든 미니게임에 인트로,아웃트로를 넣고 싶었는데 드디어 완성할 수 있었네요.

exe파일도 올려두었으니 한번 씩 심심할 때 해보시면 좋을 것 같습니다 ㅎㅎ

반응형