pygame으로 게임 만들기, 상담 내용

JoonQpa·2022년 4월 25일
3

개인프로젝트

목록 보기
1/6
post-thumbnail

오늘은 pygame을 사용하여 게임을 만들어 보는 개인프로젝트를 진행했다.

물론 초보이기 때문에 처음에는 허접한 결과물이 나올테지만, 그냥 프로젝트용이 아닌 정말 재밌어서 가끔 하고싶게 만드는 게임을 만들고 싶었다.

선택한 게임은...!

Barji의 buckshot !

어서 클론코딩 해봐야지 !


나중에 다시 만나기로 했다.


내가 만들 게임은 마리오 슈팅게임! 기본적으로 유투브 영상을 보면서 따라가며 만들었다.

게임 규칙과 이미지를 한땀한땀 만드는 과정이 꽤 재밌다.

대부분 영상을 보며 만들어갈때 큰 어려움없이 만들 수 있었다.

하지만 문제는 영상에 포함되지 않는 사운드 이펙트를 삽입하는 과정.

그 중에서도 게임오버되었을때 재생되는 사운드가 프레임만큼 겹치는 문제를 해결하는데 가장 오랜 시간이 걸렸다.

스텍오버플로우를 뒤적이던 중 내 코드에 적용할 수 있는 해결방안을 찾았다.

반복되는 게임 오버 사운드를 한번만 재생되게 하는 법

while GO == 1:
        clock.tick(60)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                GO = 0

        if not playgameover:  ##게임오버시 사운드 한번만 재생되게 하는법.
            bgm.stop()
            gs = pygame.mixer.Sound("C:\pygame\mygame\data\sound\Mario Bros Die.mp3")
            gs.play(loops=0)
            playgameover = True

game main loop상태일때 playgameover = False를 설정해준다.


bgm.stop()
gs.play(loops=0)
playgameover = True 설정해주며

게임오버시 playgameover 값이 바뀌면서 게임오버사운드를 한번만 재생하게 된다.


별 것도 아닌 것 같아보이지만, 해결하는데 정말 많은 시간이 걸렸다.



완성!

import pygame
import random
import time
from datetime import datetime

## 게임 초기화
pygame.init()
playgameover = False  #게임오버사운드 한번만 재생하기 위한 메인루프에 playgameover값 True설정

clock = pygame.time.Clock()
while pygame.mixer.get_busy():
    clock.tick(10)
    pygame.event.poll()


## 게임 창 옵션 설정
size = [900, 500]
screen = pygame.display.set_mode(size)   # 게임 스크린 크기


## 게임 이름 설정
title = "Burning Boo"
pygame.display.set_caption(title)     # 게임 이름


## 게임 내 필요한 설정
clock = pygame.time.Clock()    # 시간 변수 생성


class obj:
    def __init__(self):
        self.x = 0
        self.y = 0
        self.move = 0
    def put_img(self, address):
        if address[-3:] == "png":   #address 값의 마지막 3글자가 png일 경우. [-3:]으로표현
            self.img = pygame.image.load(address).convert_alpha() #png파일을 convert해주기
        else :
            self.img = pygame.image.load(address)
            self.sx, self.sy = self.img.get_size()
    def change_size(self, sx, sy):
        self.img = pygame.transform.scale(self.img, (sx, sy)) #이미지 크기 받아오는 함수
        self.sx, self.sy = self.img.get_size()
    def show(self):
        screen.blit(self.img, (self.x, self.y))

def crash(a,b) :           #충돌 개념 부과, 각 4개의 모서리가 일치할때 crash
    if (a.x-b.sx <= b.x) and (b.x <= a.x+a.sx):
        if (a.y-b.sy <= b.y) and (b.y <= a.y+a.sy):
            return True
        else:
            return False
    else:
        return False




me = obj()
me.put_img("data/images/1111.png")
me.change_size(50, 50)
me.x = round(size[0]/2 - me.sx/2)
me.y = round(size[1] - me.sy - 15)
me.move = 10

left_go = False
right_go = False
space_go = False

kill = 0
loss = 0

shots_list = []  # 미사일이 화면 밖으로 나갔을때 데이터를 지워주기
b_list = []

m_list = []
a_list = []


black = (0, 0, 0)
white = (255, 255, 255)
k = 0
GO = 0

# 사운드
bgm = pygame.mixer.Sound("C:\pygame\mygame\data\sound\Mario World 1.mp3")
bgm.play(-1)



## 게임 시작 대기 화면
SB = 0
while SB == 0:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                SB = 1                        #눌러진 키가 스페이스 일떄 SB=1
    screen.fill(white)
    font = pygame.font.Font("C:/Windows/Fonts/AGENCYB.TTF", 30)
    text = font.render("PRESS SPACE KEY TO START THE GAME", True, (0, 0, 0))
    screen.blit(text, (size[0]/2-200, round(size[1]/2-50)))
    pygame.display.flip()




## 메인 이벤트
start_time = datetime.now()
SB = 0
while SB == 0:

    # FPS 설정
    clock.tick(60) # 1초에 while문이 60번 실행된다

    # 각종 입력 감지
    for event in pygame.event.get(): # 게임에서 행해지는 이벤트
        if event.type == pygame.QUIT:
            SB = 1
        if event.type == pygame.KEYDOWN:  # 키가 눌렸을떄
            if event.key == pygame.K_LEFT: # 눌렸을때 그 눌린키가 왼쪽일때
                left_go = True
            elif event.key == pygame.K_RIGHT: # 눌렸을떄 그 눌린키가 오른쪽일때
                right_go = True
            elif event.key == pygame.K_SPACE:
                space_go = True
                k = 0                         # 스페이스를 눌렀을때마다 k를 0으로 만들어서 누를때마다 나가게 만들기(프레임이 6으로 안나누어져도)
        elif event.type == pygame.KEYUP:  # 키를 뗏을떄
            if event.key == pygame.K_LEFT:
                left_go = False
            elif event.key == pygame.K_RIGHT:
                right_go = False
            elif event.key == pygame.K_SPACE:
                space_go = False





    ## 입력, 시간에 따른 변화
    now_time = datetime.now()                             #시간정보
    delta_time = round((now_time - start_time).total_seconds())


    if left_go == True:
        me.x -= me.move # 이동속도만큼 왼쪽 이동
        if me.x <= 0: # 맵 끝의 crash개념을 추가, 위치가 0일떄 0에 고정
            me.x = 0

    elif right_go == True:
        me.x += me.move
        if me.x >= size[0] - me.sx: # 맵 끝의 crash개념 추가, 위치가 우측 끝(screen x축값에 me size를 빼준것
            me.x = size[0] - me.sx




    if space_go == True and k % 10 == 0:  # 총알이 나가는 게 너무 빨라서 fps/6 의 속도로 나가게 함
        shot = obj()
        shot.put_img("data/images/fire.png")
        shot.change_size(20, 20)
        shot.x = round(me.x + me.sx/2 - shot.sx/2)
        shot.y = me.y - shot.sy - 10
        shot.move = 5
        shots_list.append(shot)

    k += 1

    d_list=[]
    for i in range(len(shots_list)):        # 미사일이 발생하는 것
        shots = shots_list[i]
        shots.y -= shots.move        # 미사일 속도만큼 위로
        if shots.y <= - shots.sy:       # 화면 밖으로나갔을떄
            d_list.append(i)          # d_list에 추가해라
    for d in d_list:
        del shots_list[d]                  # d_list 삭제


    # boo 생성함수

    if random.random() > 0.98:
        boo = obj()
        boo.put_img("data/images/boo.png")
        boo.change_size(40, 40)
        boo.x = random.randrange(0, size[0] - boo.sx - round(me.sx)/2)
        boo.y = 10
        boo.move = 2
        b_list.append(boo)


    d_list = []
    for i in range(len(b_list)):   #boo가 화면 밖으로 나갔을때 없애주는 코드
        b = b_list[i]
        b.y += b.move
        if b.y >= size[1]:
            d_list.append(i)
    for d in d_list:
            del b_list[d]
            loss +=1

    # 충돌개념
    dm_list = []
    da_list = []
    for i in range(len(shots_list)):
        for j in range(len(b_list)):
            shots = shots_list[i]
            b = b_list[j]
            if crash(shots,b) == True:
                dm_list.append(i)
                da_list.append(j)
    dm_list = list(set(dm_list)) # dm_list의 중복을 제거한다. 제거됐을땐 set자료형이기 때문에 list로 다시 바꿔준다.
    da_list = list(set(da_list))

    for dm in dm_list:
        del shots_list[dm]
    for da in da_list:
        del b_list[da]
        kill += 1


    for i in range(len(b_list)):
        b = b_list[i]
        if crash(b, me) == True:
            SB = 1
            GO = 1



    ## 그리기
    screen.fill(white)
    me.show()
    for s in shots_list:
        s.show()
    for b in b_list:
        b.show()

    # 문자
    font = pygame.font.Font("C:/Windows/Fonts/AGENCYB.TTF", 20)            ##kill, loss 나타내기
    text_kill = font.render("killed : {} loss: {}".format(kill, loss), True, (255, 0, 0))
    screen.blit(text_kill, (10,5))

    text_time = font.render("time : {}".format(delta_time), True, (0, 0, 0))  ##time나타내기기
    screen.blit(text_time, (size[0]-100,5))

    ## 업데이트
    pygame.display.flip()


##게임종료



while GO == 1:
        clock.tick(60)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                GO = 0

        if not playgameover:  ##게임오버시 사운드 한번만 재생되게 하는법.
            bgm.stop()
            gs = pygame.mixer.Sound("C:\pygame\mygame\data\sound\Mario Bros Die.mp3")
            gs.play(loops=0)
            playgameover = True


        font = pygame.font.Font("C:/Windows/Fonts/AGENCYB.TTF", 70)
        text = font.render("GAME OVER", True, (255, 0, 0))
        screen.blit(text, (size[0] / 2 - 130, round(size[1] / 2 - 50)))
        pygame.display.flip()



pygame.quit()


이와 별개로, 실제로 데이터 분석가로써 경력이 있으신 튜터님께 현재 듣고 있는 프로그램과 내가 가고자 하는 길의 연관성, 전망 및 공부 방법 등에 대해 여쭤보았다.

내가 면접관님들께 받은 피드백까지 세세하게 읽어주시고, 피드백의 의미와 내가 공부해야 할 것들, 가져야할 마음가짐, 추천해주시는 공부 방법 등 나에게 꼭 필요한 것들을 말씀해주셨다.

전반적으로 튜터님의 반응은 꽤 회의적이셨다..

쉽지 않은 길, 인기 직종이 되면서 점점 더 많아지는 경쟁자, 프로그램을 소화하는 동시에 개인 공부를 하는 것이 필수라 많이 힘들 것이라는 말씀을 하셨다.

처음에는 조금 힘이 빠지기도 했지만,

하지만 애초에 이 길이 쉬워서, 인기가 많아서, 연봉이 높아서 택한 것이 아니다. 난 정말 진심으로 즐겁고 내가 잘 할 수 있는 일이라고 느꼈기 때문에 이 길을 선택했다. 내가 확신을 가지고 무언가에 몰두했을때, 결과가 나쁜 적은 없었다. 이미 시작됐으니 내가 할 수 있는 일에 집중하고, 나를 의심하지 말자.



데이터 분석가가 되기 위해 공부 해야 할 것들

1. 백엔드
2. 머신러닝(선택이 아닌 필수)
3. 데이터 분석



추천해주신 방법

1. API에서 데이터 직접 가져오기
2. 데이터 전처리
3. 모델 만들기
4. 결과 비교하기
5. 모델이 유의미한지
6. 어떤 리스크가 있는지
7. 데이터의 신뢰성을 어떻게 볼것인지

내 결과물의 의미에 대해 상대방에게 설명할 수 있고 설득할 수 있어야 한다.

profile
Intuition factory: from noob to pro

0개의 댓글