이제 세번째 게임 시뮬레이트 게임을 만들어보자.
이름만 보면 뭔게임이지?
하는 생각이 들것인데 이것도 마찬가지로 플레이해보면 아하! 아니 설명만들어도 아하 ! 할것이다.
시뮬레이트는 플레이어가 화면에 무작위로 나타난 색이 다른 네 버튼의 순서를 기억하고 있다가 맞히는 게임이다!
즉! 버튼의 순서를 기억하고 그냥 따라 누르면 되는 기억력게임이다!!
플레이어는 불이 들어온 순서대로 버튼을 눌러서 방금 본 패턴을 그대로 반복하면 된다.
이를 위해서는 4개의 사운드 파일이 필요하다.
4개의 타일이라고 했으니
각 사운드별로 클릭하였을때 소리가 나게 만들어주기위함이다.
invpy.com/beep1.ogg
~ beep4 까지 다운받으면된다.
그럼 시작해보자 !
# Simulate (a Simon clone)
# By Al Sweigart al@inventwithpython.com
# http://inventwithpython.com/pygame
# Released under a "Simplified BSD" license
import random, sys, time, pygame
from pygame.locals import *
FPS = 30
WINDOWWIDTH = 640
WINDOWHEIGHT = 480
FLASHSPEED = 500 # in milliseconds
FLASHDELAY = 200 # in milliseconds
BUTTONSIZE = 200
BUTTONGAPSIZE = 20
TIMEOUT = 4 #버튼을 누르지 않으면 4초후 게임 종료
# R G B
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
BRIGHTRED = (255, 0, 0)
RED = (155, 0, 0)
BRIGHTGREEN = ( 0, 255, 0)
GREEN = ( 0, 155, 0)
BRIGHTBLUE = ( 0, 0, 255)
BLUE = ( 0, 0, 155)
BRIGHTYELLOW = (255, 255, 0)
YELLOW = (155, 155, 0)
DARKGRAY = ( 40, 40, 40)
bgColor = BLACK
XMARGIN = int((WINDOWWIDTH - (2 * BUTTONSIZE) - BUTTONGAPSIZE) / 2)
YMARGIN = int((WINDOWHEIGHT - (2 * BUTTONSIZE) - BUTTONGAPSIZE) / 2)
# 4개의 버튼에 대한 Rect 객체
YELLOWRECT = pygame.Rect(XMARGIN, YMARGIN, BUTTONSIZE, BUTTONSIZE)
BLUERECT = pygame.Rect(XMARGIN + BUTTONSIZE + BUTTONGAPSIZE, YMARGIN, BUTTONSIZE, BUTTONSIZE)
REDRECT = pygame.Rect(XMARGIN, YMARGIN + BUTTONSIZE + BUTTONGAPSIZE, BUTTONSIZE, BUTTONSIZE)
GREENRECT = pygame.Rect(XMARGIN + BUTTONSIZE + BUTTONGAPSIZE, YMARGIN + BUTTONSIZE + BUTTONGAPSIZE, BUTTONSIZE, BUTTONSIZE)
앞선 슬라이드 퍼즐 처럼 버튼이 있다.
이 시뮬레이트 게임은 4개의 버튼 난 영역이 있고 플레이어가 클릭 하였을 때 어떤 동작을 해야하는지 처리해야하는 코드가 있어야 할것이다!
그렇다면 ! 당연빠따로 colidepoint() method 를 써서 사용자가 해당 영역을 클릭했는지 알아낸다!
def main():
global FPSCLOCK, DISPLAYSURF, BASICFONT, BEEP1, BEEP2, BEEP3, BEEP4
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT))
pygame.display.set_caption("Chans Simulate")
BASICFONT = pygame.font.Font("freesansbold.ttf",16)
infoSurf = BASICFONT.render("Match the Patter by Clicking on the button or using the Q,W,A,S keys.",1,DARKGRAY)
infoRect = infoSurf.get_rect()
infoRect.topleft = (10,WINDOWHEIGHT - 25)
#사운드파일 업로드
BEEP1 = pygame.mixer.Sound('beep1.ogg')
BEEP2 = pygame.mixer.Sound('beep2.ogg')
BEEP3 = pygame.mixer.Sound('beep3.ogg')
BEEP4 = pygame.mixer.Sound('beep4.ogg')
main() 함수는 프로그램의 일부만 구현하고 필요한 함수를 호출한다.
일반적인 pygame 셋업을 진행하고 전역변수를 설정하여 다른 함수들에서도 이 변수들을 사용할 수 있게 하는것이다.
하지만 이 변수들을 기본적으로 변강하는 일이 없으므로 상수나 마찬가지이다.
그리고 사운드 효과까지 !
#새게임에서 사용할 변수를 초기화한다.
pattern =[] #색깔 패턴을 저장한다.
currentStep = 0 #플레이어가 다음에 눌러야 하는 색깔
lastClickTime = 0 # 플레이어가 이전 버튼을 누른 시간
score = 0
#이 밑에 값이 False면 현재 시뮬레이트가 패턴을 보여주고 있는 상태이다.
#True 면 버튼 클릭 기다리고 있다.
waitingForInput = False
pattern 은 색의 리스트이며 플레이어는 패턴을 기억해야한다 !
플레이어가 하나의 턴을 마치면 또 하나의 무작위 색이 이 리스트 뒤에 추가된다.
CurrentStep 변수는 플레이어가 다음에 어떤 색을 클릭해야하는지 기록 한다 !
만약 값이 0 이고 patter=[Green.RED]라면 플레이어는 초록색을 선택해야한다!
만약 다른 버튼을 눌렀다면 게임은 종료된다.
lastClickTime은 시간제한을 위해 플레이어가 마지막버튼을 누른후 지난 시간을 기록한다 !
WaitingForInput을 통해서 트루/폴스 를 통해 두가지 모드로 진행된다.
while True :
clickedButton= None
DISPLAYSURF.fill(bgColor)
drawButtons()
scoreSurf = BASICFONT.render("Socre : "+str(score),1,WHITE)
scoreRect = scoreSurf.get_rect()
scoreRect.topleft = (WINDOWWIDTH- 100,10)
DISPLAYSURF.blit(scoreSurf,scoreRect)
DISPLAYSURF.blit(infoSurf,infoRect)
매 시작마다 clickedButton None 리셋으로 시작하고 버튼을 클릭했다면 그 값으로 바뀐다.
그리고 버튼과 글자들을 그린다!
점수값은 계속 바뀌기 떄문에 Surface객체를 계속 새로 만들어야 한다.
checkForQuit()
for event in pygame.event.get(): # event loop
if event.type == MOUSEBUTTONUP:
mousex, mousey = event.pos
clickedButton = getButtonClicked(mousex,mousey)
chekcforQuit 를 통해 QUIT 이벤트를 검사한다.
GetButtonClicked 함수는 어떤 버튼을 클릭했는지 Color 객체를 반환해준다 !
만약 색을 클릭하지 않았다면 None !
elif event.type == KEYDOWN :
if event.key == K_q:
clickedButton == YELLOW
elif event.key == K_w:
clickedButton = BLUE
elif event.key == K_a:
clickedButton = RED
elif event.key == K_s:
clickedButton = GREEN
KEYDOWN event가 발생했는지 확인하고 clickedButton을 바꿔준다 !
if not waitingForInput: #False 일때
#패턴을 자동으로 보여준다.
pygame.display.update()
pygame.time.wait(1000)
pattern.append(random.choice((YELLOW,BLUE,RED,GREEN)))
for button in pattern:
flashButtonAnimation(button)
pygame.time.wait(FLASHDELAY)
waitingForInput = True
waitingForInput : True/False에 따라 모드가 나뉜다.
False 면 패턴의 애니메이션을 보여준다.
True 면 플레이어가 버튼을 누르기를 기다린다.
pattern에 랜덤의 색을 추가하고 flashButtonAnimation을 통해서 순서대로 밝게 보여준다.
True 로 변경 후 그 후 사용자의 입력을 기다린다.
else :
#wait for the player to enter button
if clickedButton and clickedButton == pattern[currentStep]:
#맞는 버튼을 클릭(버튼클릭 && 옳은 버튼 클릭 )
flashButtonAnimation(clickedButton)
#클릭한 버튼 색 반쨕~
currentStep += 1
lastClickTime = time.time() # 시간 초기화(현재 시간 기록 가능)
이번껀 쉬우니 주석으로 대체하겠다.
if currentStep == len(pattern):
#패턴의 마지막 버튼을 클릭하였다.
changeBackgroundAnimation()
score += 1
waitingForInput = False
currentStep = 0 #게임 턴이 종료되고 맨 처음으로 리셋한다.
연장된 부분이다.
currentStep이 마지막 패턴의 길이와 동일해졌다는 것은 마지막 버튼을 클릭하였다는 것이고 이는 더이상 따라할 패턴이 없다는것이므로 다음 모드로 넘어가야한다.
그렇기에 점수를 올리고 모드변경과 초기화를 진행해준다.
색변경도 해준다 !
elif (clickedButton and clickedButton != pattern[currentStep]) or (currentStep!=0 and time.time()-TIMEOUT > lastClickTime):
만약 플레이어가 맞는 버튼을 누르지 않았고 시간을 초과했다면 이 elif문을 실행한다.
"시간초과"의 조건은 처음으로 버튼을 누른 것이 아니어야 한다.
즉, 버튼을 한 번 누르기 시작했으면 계속해서 시간안에 버튼을 눌러야한다.
cureentStep != 0 이 True 라면 플레이어가 이미 버튼을 누르기 시작했다는 말이다!
"시간 초과"가 되려면 time.time()에서 TIMEOUT을 뺀 시간이 직전에 버튼을 클릭한 시간 보다 커야한다.
time.time()-TIMEOUT >lastClickedTime 을 이해하기위해서 기준 시간에 대해 알아야한다
기준 시간은(epoch time) 1970년 1월 1일(유닉스 기원) 부터 얼마나 많은 초가 지났는지 나타내는 숫자이다.
7:30PM - 7:31 PM 같은 문자열 가지고 19초가 지났는지 확인 하기는 까다롭지만 epoch time을 사용하면 그저 뺄셈만해서되서 간단하다.
gameOverAnimation()
#reset for new game
pattern=[]
currentStep= 0
waitingForInput = False
score = 0
pygame.time.wait(1000)
changeBackgroundAnimation()
그저 끝내고 초기화닷!
pygame.display.update()
FPSCLOCK.tick(FPS)
길고도 긴 Main함수를 다 짰다.
그렇다면 Main 완성체를 보여주고
다음 글에서 나머지 함수들을 구현해보자 .
def main():
global FPSCLOCK, DISPLAYSURF, BASICFONT, BEEP1, BEEP2, BEEP3, BEEP4
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT))
pygame.display.set_caption("Chans Simulate")
BASICFONT = pygame.font.Font("freesansbold.ttf",16)
infoSurf = BASICFONT.render("Match the Patter by Clicking on the button or using the Q,W,A,S keys.",1,DARKGRAY)
infoRect = infoSurf.get_rect()
infoRect.topleft = (10,WINDOWHEIGHT - 25)
#사운드파일 업로드
BEEP1 = pygame.mixer.Sound('beep1.ogg')
BEEP2 = pygame.mixer.Sound('beep2.ogg')
BEEP3 = pygame.mixer.Sound('beep3.ogg')
BEEP4 = pygame.mixer.Sound('beep4.ogg')
#새게임에서 사용할 변수를 초기화한다.
pattern =[] #색깔 패턴을 저장한다.
currentStep = 0 #플레이어가 다음에 눌러야 하는 색깔
lastClickTime = 0 # 플레이어가 이전 버튼을 누른 시간
score = 0
#이 밑에 값이 False면 현재 시뮬레이트가 패턴을 보여주고 있는 상태이다.
#True 면 버튼 클릭 기다리고 있다.
waitingForInput = False
while True :
clickedButton= None
DISPLAYSURF.fill(bgColor)
drawButtons()
scoreSurf = BASICFONT.render("Socre : "+str(score),1,WHITE)
scoreRect = scoreSurf.get_rect()
scoreRect.topleft = (WINDOWWIDTH- 100,10)
DISPLAYSURF.blit(scoreSurf,scoreRect)
DISPLAYSURF.blit(infoSurf,infoRect)
checkForQuit()
for event in pygame.event.get(): # event loop
if event.type == MOUSEBUTTONUP:
mousex, mousey = event.pos
clickedButton = getButtonClicked(mousex,mousey)
elif event.type == KEYDOWN :
if event.key == K_q:
clickedButton == YELLOW
elif event.key == K_w:
clickedButton = BLUE
elif event.key == K_a:
clickedButton = RED
elif event.key == K_s:
clickedButton = GREEN
if not waitingForInput: #False 일때
#패턴을 자동으로 보여준다.
pygame.display.update()
pygame.time.wait(1000)
pattern.append(random.choice((YELLOW,BLUE,RED,GREEN)))
for button in pattern:
flashButtonAnimation(button)
pygame.time.wait(FLASHDELAY)
waitingForInput = True
else :
#wait for the player to enter button
if clickedButton and clickedButton == pattern[currentStep]:
#맞는 버튼을 클릭(버튼클릭 && 옳은 버튼 클릭 )
flashButtonAnimation(clickedButton)
#클릭한 버튼 색 반쨕~
currentStep += 1
lastClickTime = time.time() # 시간 초기화
if currentStep == len(pattern):
#패턴의 마지막 버튼을 클릭하였다.
changeBackgroundAnimation()
score += 1
waitingForInput = False
currentStep = 0 #게임 턴이 종료되고 맨 처음으로 리셋한다
elif (clickedButton and clickedButton != pattern[currentStep]) or (currentStep!=0 and time.time()-TIMEOUT > lastClickTime):
#버튼을 잘못눌렀거나 시간 초과
gameOverAnimation()
#reset for new game
pattern=[]
currentStep= 0
waitingForInput = False
score = 0
pygame.time.wait(1000)
changeBackgroundAnimation()
pygame.display.update()
FPSCLOCK.tick(FPS)