[pygame]시뮬레이트(Simulate) - 2

서희찬·2021년 4월 15일


그럼 이제 이어서 메인함수에서 활용하는 함수들을 구현하자 !

화면에 게임판 그리기

def terminate():
    pygame.quit()
    sys.exit()
 
 def checkForQuit():
    for event in pygame.event.get(QUIT): # 모든 QUIT 이벤트 가져온다.
        terminate() # QUIT 발생시 종료
    for event in pygame.event.get(KEYUP): #모든 키업 이벤트 가져온다.
        if event.key == K_ESCAPE:
            terminate()
        pygame.event.post(event) #다른 KEYUP EVENT 객체는 이벤트 큐에 돌려놓는다.
  

앞선 게임에서 본 함수들이니 설명은 주석으로 대체하겠다.

상수 재활용하기

def flashButtonAnimation(color, animationSpeed=50):
    if color == YELLOW:
        sound = BEEP1
        flashColor = BRIGHTYELLOW
        rectangle = YELLOWRECT
    elif color == BLUE:
        sound = BEEP2
        flashColor = BRIGHTBLUE
        rectangle = BLUERECT
    elif color == RED:
        sound = BEEP3
        flashColor = BRIGHTRED
        rectangle = REDRECT
    elif color == GREEN:
        sound = BEEP4
        flashColor = BRIGHTGREEN
        rectangle = GREENRECT
        

Color 파라미터로 어떤 값을 전달 했느지에 따라 소리,색 등등이 달라진다.

깜박이는 버튼 애니메이션

   origSurf =DISPLAYSURF.copy()
   flashSurf = pygame.surface((BUTTONSIZE,BUTTONSIZE))
   flashSurf = flashSurf.convert_alpha()
   r, g, b = flashColor
   sound.play()

애니메이션의 각 프레임에서 보통의 게임판을 그린 다음 밝은색의 버튼을 이전의 버튼 위에 덮어쓰기해서 그린다.
애니메이션 시작에는 버튼의 알파 값(투명도)를 0으로 하고 매 프레임마다 알파값을 증가 시킨다.
이렇게 해서 255가 되면 완전 밝은색이 되어 그 버튼이 기존의 버튼을 완전히 가리게 된다.
이렇게 하면 깜박거리는 것처럼 보인다!

이동작을 수행하기 위해 Surface 객체의 복사본을 orignSurf에 앞서 저장했다.
버튼 하나 크기의 Surface 객체를 새로 만들어서 flashSurf 변수에 저장했다.
flashSurf 의 conver_alpha() 메소드를 호출하여 flashSurf 객체 위에 투명한 색을 그릴 수 있도록한다.
(이렇게 하지 않으면 color alpha 의 값은 디폴트로 255가 된다.)

r,g,b
신태틱 슈가이다!
flashColor tuple의 RGB 값을 각각 r,g,b라는 지역변수에 저장한다.

Sound 를 실행 먼저시키는 이유는
소리가 실행되는동안 다음 코드들이 진행하여 애니메이션을 진행하기때문에 애니메이션의 실행 코드 직전 소리먼저 실행해주는것이 좋다.

for start, end, step in((0,255,1),(255,0,-1)): #애니메이션 루프
       for alpha in range(start,end,animationSpeed*step):
           checkForQuit()
           DISPLAYSURF.blit(origSurf,(0,0))
           flashSurf.fill((r,g,b,alpha))
           DISPLAYSURF.blit(flashSurf,rectangle.topleft)
           pygame.display.update()
           FPSCLOCK.tick(FPS)
   DISPLAYSURF.blit(origSurf,(0,0))

애니메이션을 수행하기위해서 알파 값을 0부터 255로 증가시키고 0으로 내려주면서 flashSurf를 그린다.

    for start, end, step in((0,255,1),(255,0,-1)): #애니메이션 루프
        for alpha in range(start,end,animationSpeed*step):

이 for문은 대박이다..
대박의 효율,,,
위에 말한 0>255,255->0의 두개의 for문을 하나의 for문으로 줄여줬다!!!
첫번째 for문의 반복은
start = 0
end = 255
step = 1 이다.
그리고 for문의 두번째 반복은
start = 255
end = 0
step = -1 이다.

이렇게 해서 일부러 똑같은 내용의 for문을 두 번 작성할 필요가 없다!
컴퓨터가 너무 빨리 애니메이션을 수행하고
끝내지 않도록 tick() 메소드를 써서 잠깐씩 멈춘다 !

버튼 그리기

def drawButtons():
    pygame.draw.rect(DISPLAYSURF,YELLOW,YELLOWRECT)
    pygame.draw.rect(DISPLAYSURF, BLUE,   BLUERECT)
    pygame.draw.rect(DISPLAYSURF, RED,    REDRECT)
    pygame.draw.rect(DISPLAYSURF, GREEN,  GREENRECT)

각 버튼은 특정한 영역에 서로 다른 색을 가지고 있기에 ! 각각 그려준다 !

배경이 바뀌는 애니메이션

def changeBackgroundAnimation(animationSpeed=40):
    global bgColor
    newBgColor = (random.randint(0,255),random.randint(0,255),random.randint(0,255))

    newBgSurf = pygame.Surface((WINDOWWIDTH,WINDOWHEIGHT))
    newBgSurf = newBgSurf.convert_alpha()
    r, g, b = newBgColor
    for alpha in range(0,255,animationSpeed): # animation loop
        checkForQuit()
        DISPLAYSURF.fill(bgColor)

        newBgSurf.fill((r,g,b,alpha))
        DISPLAYSURF.blit(newBgSurf,(0,0))

        drawButtons() #색 위에 버튼은ㄹ 다시 그린다.

        pygame.display.update()
        FPSCLOCK.tick(FPS)
    bgColor = newBgColor

플레이어가 패턴을 정확히 따라했다면 배경이 바뀌는 애니메이션을 보여준다.
for문에서 매 반복마다 전체 디스플레이 Surface를 다시 그려야 한다.

루프문의 스탭은 이렇다.

  • 전체 디스플레이를 이전 배경색으로 채운다.
  • 다른 Surface object를 새로운 배경색의 RGB값으로 채운다.
  • 그리고 newbgSurf 를 그린다.
  • 버튼 을 그린다.
  • 그리고 잠시 멈춘다.

게임종료 애니메이션

    #모든 비프음을 한꺼번에 플레이 하며 배경색을 깜박거리게 한다.
    origSurf = DISPLAYSURF.copy()
    flashSurf = pygame.Surface(DISPLAYSURF.get_size())
    flashSurf = flashSurf.convert_alpha()
    BEEP1.play()
    BEEP2.play()
    BEEP3.play()
    BEEP4.play()
    r, g, b = color 
    for i in range(3): #3번 깜박인ㄷ.
        for start, end, step in ((0,255,1),(255,0,-1)):
            for alpha in range(start,end,animationSpeed*step)
            checkForQuit()
            flashSurf.fill((r,g,b,alpha))
            DISPLAYSURF.blit(origSurf,(0,0))
            DISPLAYSURF.blit(flashSurf,(0,0))
            drawButtons()
            pygame.display.update()
            FPSCLOCK.tick(FPS)

모든 소리를 재생시키고 3번깜박이게 시키면된다
이때의 애니메이션 작동방식은 앞서 작동한 방식과 동일하다.

픽젤 좌표계를 버튼으로 변환하기

def getButtonClicked(x,y):
 if YELLOWRECT.collidepoint((x,y)):
     return YELLOW
 elif BLUERECT.collidepoint( (x, y) ):
     return BLUE
 elif REDRECT.collidepoint( (x, y) ):
     return RED
 elif GREENRECT.collidepoint( (x, y) ):
     return GREEN
 return None

if __name__ == "__main__":
 main()

어느 카드를 선택했는지 확인하고
다른 쪽을 선택했다면 None 을 반환한다.

암묵적인 것보다 명시적인것이 낫다.

모든 함수는 따로 return 문이 없다면 None 을 반환하지만 위의 getButtonClicked함수에서는 따로 반환해주었다.
그렇지만 ! 어떤 버튼 위도 클릭하지 않았다는것을 명확하게 하기 위해서 return None 을 썻다.

이제 다음 포스트에서 전체 코드를 보여주고 게임실행을 해보겠다.

profile
Carnegie Mellon University Robotics Institute | Research Associate | Developing For Our Lives, 세상에 기여하는 삶을 살고자 개발하고 있습니다

0개의 댓글