Pygame
파이게임 설치
pip install pygame
행맨 게임
- 컴퓨터가 단어를 하나 생각함
- 밑줄로 표시
- 유저가 단어에 포함될 거 같은 글자를 하나씩 입력
- 포함이 되면 그 위치에 글자를 표시
- 포함이 안되면 사람을 하나씩 그림
- 사람이 먼저 완성이 되면 컴퓨터 승
- 단어가 먼저 완성이 되면 유저 승
게임 구성 요소
- 프로그래밍
- 시나리오
- 디자인
프로그래밍
- 단어를 하나 생각
word = "man"
word = word.upper() #대문자만 가정
- 유저는 이 글자를 몰라야 함
word_show = "_" * len(word)
- 게임이 끝날 때 까지 알고리즘 반복
- 보통 while문 사용
try_num = 0
ok_list = []
no_list = []
while True:
ans = input().upper() #유저 입력 저장 변수
print(ans)
result = word.find(ans)
if result == -1: #없음
print("X")
try_num += 1
no_list.append(ans)
else:
print("O")
ok_list.append(ans)
for i in range(len(word)):
if word[i] == ans:
word_show = word_show[:i] + ans + word_show[i+1:]
print(word_show)
if try_num == 7: break
if word_show.find("_") == -1: break
- 이 코드는 행맨 게임의 기본적인 알고리즘
- 유저의 입력을 받는다
- 단어에서 그 글자가 있는지 찾는다
- 글자가 단어에 없으면 실패, 있으면 성공 카운트
- 성공하면 word_show밑줄이 그 글자로 바뀜
단어 랜덤으로 불러오기
import random
f = open("voca.txt", "r", encoding = 'UTF-8')
raw_data = f.read()
f.close
data_list = raw_data.split("\n") #voca.txt에 있는 한글 뜻은 필요없음. 전처리
data_list = data_list[:-1]
print(data_list[:-1])
while True:
random_index = random.randrange(0, len(data_list))
word = data_list[random_idx].replace(u"\xa0", u" ").split(" ")[1]
if len(word) <= 6:
break
word = word.upper()
word_show = "_" * len(word)
quit()#이 코드를 쓰면 밑에 줄은 실행X
게임창 띄우기
import pygame
pygame.init()
size = [500, 900]
screen = pygame.display.set_mode(size)
title = "hangman"
clock = pygame.time.Clock()
black = (0,0,0)
white = (255,255,255)
#실수를 정수로 만들어줌
def tup_r(tup):
temp_list = []
for a in tup:
temp_list.append(round(a))
return tuple(temp_list)
exit = False
# 4. 메인 이벤트
while not exit:
# 4-1. FPS 설정
clock.tick(60)
# 4-2. 각종 입력 감지
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit = True
# 4-3. 입력, 시간에 따른 변화
# 4-4. 그리기
screen.fill(black)
A = tup_r((0, size[1]*2/3))
B = (size[0], A[1])
C = tup_r((size[0]/6 , A[1]))
D = (C[0], C[0])
E = tup_r((size[0]/2, D[1]))
pygame.draw.line(screen, white, A, B, 3)
pygame.draw.line(screen, white, C, D, 3)
pygame.draw.line(screen, white, D, E, 3)
# 4-5. 업데이트
pygame.display.flip()
# 5. 게임 종료
pygame.quit()
- 파이게임에서 게임창은 픽셀 단위
- 게임창에 무언가를 그리려면 픽셀 단위로 입력(좌표 활용)
- 좌표 계산을 잘해야함
- 원은 원의 중심 좌표와 반지름 길이를 이용하여 그림
- 꺾이는 부분은 분기점에서 각도 계산
새로운 이벤트 추가(시간이지나면서 빨간선 그려지고 다 그려지면 사람 떨어짐)
import pygame, math
# 1. 게임 초기화
pygame.init()
# 2. 게임창 옵션 설정
size = [500,900]
screen = pygame.display.set_mode(size)
title = "HANGMAN"
pygame.display.set_caption(title)
# 3. 게임 내 필요한 설정
clock = pygame.time.Clock()
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
def tup_r(tup):
temp_list = []
for a in tup:
temp_list.append(round(a))
return tuple(temp_list)
drop = False
exit = False
k = 0
# 4. 메인 이벤트
while not exit:
# 4-1. FPS 설정
clock.tick(60)
# 4-2. 각종 입력 감지
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit = True
# 4-3. 입력, 시간에 따른 변화
k += 1
# 4-4. 그리기
screen.fill(black)
A = tup_r((0, size[1]*2/3))
B = (size[0], A[1])
C = tup_r((size[0]/6 , A[1]))
D = (C[0], C[0])
E = tup_r((size[0]/2, D[1]))
pygame.draw.line(screen, white, A, B, 3)
pygame.draw.line(screen, white, C, D, 3)
pygame.draw.line(screen, white, D, E, 3)
F = tup_r((E[0], E[1]+size[0]/6))
if drop == False:
pygame.draw.line(screen, white, E, F, 3)
r_head = round(size[0]/12)
if drop == True : G = (F[0],F[1]+r_head+k*10)
else : G = (F[0],F[1]+r_head)
pygame.draw.circle(screen, white, G, r_head, 3)
H = (G[0], G[1]+r_head)
I = (H[0], H[1]+r_head)
pygame.draw.line(screen, white, H, I, 3)
l_arm = r_head*2
J = (I[0]-l_arm*math.cos(30*math.pi/180),
I[1]+l_arm*math.sin(30*math.pi/180))
K = (I[0]+l_arm*math.cos(30*math.pi/180),
I[1]+l_arm*math.sin(30*math.pi/180))
J = tup_r(J)
K = tup_r(K)
pygame.draw.line(screen, white, I, J, 3)
pygame.draw.line(screen, white, I, K, 3)
L = (I[0], I[1]+l_arm)
pygame.draw.line(screen, white, I, L, 3)
l_leg = round(l_arm * 1.5)
M = (L[0]-l_leg*math.cos(60*math.pi/180),
L[1]+l_leg*math.sin(60*math.pi/180))
N = (L[0]+l_leg*math.cos(60*math.pi/180),
L[1]+l_leg*math.sin(60*math.pi/180))
M = tup_r(M)
N = tup_r(N)
pygame.draw.line(screen, white, L, M, 3)
pygame.draw.line(screen, white, L, N, 3)
if drop == False:
O = tup_r((size[0]/2-size[0]/6, E[1]/2+F[1]/2))
P = (O[0]+k*2, O[1])
if P[0] > size[0]/2+size[0]/6 :
P = tup_r((size[0]/2+size[0]/6, O[1]))
drop = True
k = 0
pygame.draw.line(screen, red, O, P, 3)
# 4-5. 업데이트
pygame.display.flip()
# 5. 게임 종료
pygame.quit()
- 시간이 지나면서 k가 1 증가
- drop을 False로 초기화
- drop이 false면 선을 그림(O부터 P까지)
- O는 고정, P는 계속 증가(k값 이용)
- 만약 P가 일정 길이까지 도달하면
- drop이 True가 됨, k는 다시 0으로 됨
사용자의 입력 받음
import pygame, math
# 1. 게임 초기화
pygame.init()
# 2. 게임창 옵션 설정
size = [500,900]
screen = pygame.display.set_mode(size)
title = "HANGMAN"
pygame.display.set_caption(title)
# 3. 게임 내 필요한 설정
clock = pygame.time.Clock()
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
hint_font = pygame.font.Font("C:/Windows/Fonts/arial.ttf", 80)
entry_font = pygame.font.Font("C:/Windows/Fonts/arial.ttf", 60)
def tup_r(tup):
temp_list = []
for a in tup:
temp_list.append(round(a))
return tuple(temp_list)
entry_text = ""
try_num = 0
drop = False
exit = False
k = 0
# 4. 메인 이벤트
while not exit:
# 4-1. FPS 설정
clock.tick(60)
# 4-2. 각종 입력 감지
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit = True
if event.type == pygame.KEYDOWN:
key_name = pygame.key.name(event.key)
if len(key_name) == 1:
if (ord(key_name) >= 65 and ord(key_name) <= 90) or (ord(key_name) >= 97 and ord(key_name) <= 122):
entry_text = key_name.upper()
else : entry_text = ""
else : entry_text = ""
print(key_name)
# 4-3. 입력, 시간에 따른 변화
k += 1
# 4-4. 그리기
screen.fill(black)
A = tup_r((0, size[1]*2/3))
B = (size[0], A[1])
C = tup_r((size[0]/6 , A[1]))
D = (C[0], C[0])
E = tup_r((size[0]/2, D[1]))
pygame.draw.line(screen, white, A, B, 3)
pygame.draw.line(screen, white, C, D, 3)
pygame.draw.line(screen, white, D, E, 3)
F = tup_r((E[0], E[1]+size[0]/6))
if drop == False:
pygame.draw.line(screen, white, E, F, 3)
r_head = round(size[0]/12)
if drop == True : G = (F[0],F[1]+r_head+k*10)
else : G = (F[0],F[1]+r_head)
pygame.draw.circle(screen, white, G, r_head, 3)
H = (G[0], G[1]+r_head)
I = (H[0], H[1]+r_head)
pygame.draw.line(screen, white, H, I, 3)
l_arm = r_head*2
J = (I[0]-l_arm*math.cos(30*math.pi/180),
I[1]+l_arm*math.sin(30*math.pi/180))
K = (I[0]+l_arm*math.cos(30*math.pi/180),
I[1]+l_arm*math.sin(30*math.pi/180))
J = tup_r(J)
K = tup_r(K)
pygame.draw.line(screen, white, I, J, 3)
pygame.draw.line(screen, white, I, K, 3)
L = (I[0], I[1]+l_arm)
pygame.draw.line(screen, white, I, L, 3)
l_leg = round(l_arm * 1.5)
M = (L[0]-l_leg*math.cos(60*math.pi/180),
L[1]+l_leg*math.sin(60*math.pi/180))
N = (L[0]+l_leg*math.cos(60*math.pi/180),
L[1]+l_leg*math.sin(60*math.pi/180))
M = tup_r(M)
N = tup_r(N)
pygame.draw.line(screen, white, L, M, 3)
pygame.draw.line(screen, white, L, N, 3)
if drop == False and try_num == 8:
O = tup_r((size[0]/2-size[0]/6, E[1]/2+F[1]/2))
P = (O[0]+k*2, O[1])
if P[0] > size[0]/2+size[0]/6 :
P = tup_r((size[0]/2+size[0]/6, O[1]))
drop = True
k = 0
pygame.draw.line(screen, red, O, P, 3)
# 힌트 표시하기
word_show = "___"
hint = hint_font.render(word_show, True, white)
hint_size = hint.get_size()
hint_pos = tup_r((size[0]/2-hint_size[0]/2, size[1]*5/6-hint_size[1]/2))
screen.blit(hint, hint_pos)
# 입력창 표시하기
entry = entry_font.render(entry_text, True, black)
entry_size = entry.get_size()
entry_pos = tup_r((size[0]/2-entry_size[0]/2, size[1]*17/18-entry_size[1]/2))
entry_bg_size = 80
pygame.draw.rect(screen, white, tup_r((size[0]/2-entry_bg_size/2, size[1]*17/18-entry_bg_size/2
,entry_bg_size ,entry_bg_size)))
screen.blit(entry, entry_pos)
# 4-5. 업데이트
pygame.display.flip()
# 5. 게임 종료
pygame.quit()
- KEYDOWN(키가 눌러짐)이 이벤트의 조건
- key, upper를 활용해 소문자를 대문자로 바꿈
- key를 입력할 때 마다 key_name출력
- 힌트 표시, 입력창 표시
- 입력창 안에 입력한 값을 띄움
- entry_text를 entry_font로 렌더링(entry변수에 저장)
- 입력창 안에 entry 띄움
로직 코드 결합
import pygame, math, random
# 1. 게임 초기화
pygame.init()
# 2. 게임창 옵션 설정
size = [500,900]
screen = pygame.display.set_mode(size)
title = "HANGMAN"
pygame.display.set_caption(title)
# 3. 게임 내 필요한 설정
clock = pygame.time.Clock()
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
hint_font = pygame.font.Font("C:/Windows/Fonts/Arial.ttf", 80)
entry_font = pygame.font.Font("C:/Windows/Fonts/Arial.ttf", 60)
no_font = pygame.font.Font("C:/Windows/Fonts/Arial.ttf", 40)
def tup_r(tup):
temp_list = []
for a in tup:
temp_list.append(round(a))
return tuple(temp_list)
entry_text = ""
drop = False
enter_go = False
exit = False
# A가 영어 단어를 1개 생각한다.
f = open("voca.txt","r",encoding='UTF-8')
raw_data = f.read()
f.close()
data_list = raw_data.split("\n")
data_list = data_list[:-1]
while True:
r_index = random.randrange(0,len(data_list))
word = data_list[r_index].replace(u"\xa0", u" ").split(" ")[1]
if len(word) <= 6 :break
word = word.upper()
# 단어의 글자 수만큼 밑줄을 긋는다.
word_show = "_"*len(word)
try_num = 0
ok_list = []
no_list = []
k = 0
# 4. 메인 이벤트
while not exit:
# 4-1. FPS 설정
clock.tick(60)
# 4-2. 각종 입력 감지
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit = True
if event.type == pygame.KEYDOWN:
key_name = pygame.key.name(event.key)
if (key_name == "return" or key_name == "enter"):
if entry_text != "" and (ok_list+no_list).count(entry_text) == 0 :
enter_go = True
elif len(key_name) == 1:
if (ord(key_name) >= 65 and ord(key_name) <= 90) or (ord(key_name) >= 97 and ord(key_name) <= 122):
entry_text = key_name.upper()
else : entry_text = ""
else : entry_text = ""
# 4-3. 입력, 시간에 따른 변화
if try_num == 8 : k += 1
if enter_go == True:
ans = entry_text
result = word.find(ans)
if result == -1 : #없음
try_num += 1
no_list.append(ans)
else : #있음
ok_list.append(ans)
for i in range(len(word)):
if word[i] == ans:
word_show = word_show[:i] + ans + word_show[i+1:]
enter_go = False
entry_text = ""
# 4-4. 그리기
screen.fill(black)
A = tup_r((0, size[1]*2/3))
B = (size[0], A[1])
C = tup_r((size[0]/6 , A[1]))
D = (C[0], C[0])
E = tup_r((size[0]/2, D[1]))
pygame.draw.line(screen, white, A, B, 3)
pygame.draw.line(screen, white, C, D, 3)
pygame.draw.line(screen, white, D, E, 3)
F = tup_r((E[0], E[1]+size[0]/6))
if drop == False:
pygame.draw.line(screen, white, E, F, 3)
r_head = round(size[0]/12)
if drop == True : G = (F[0],F[1]+r_head+k*10)
else : G = (F[0],F[1]+r_head)
if try_num >= 1 : pygame.draw.circle(screen, white, G, r_head, 3)
H = (G[0], G[1]+r_head)
I = (H[0], H[1]+r_head)
if try_num >= 2 :pygame.draw.line(screen, white, H, I, 3)
l_arm = r_head*2
J = (I[0]-l_arm*math.cos(30*math.pi/180),
I[1]+l_arm*math.sin(30*math.pi/180))
K = (I[0]+l_arm*math.cos(30*math.pi/180),
I[1]+l_arm*math.sin(30*math.pi/180))
J = tup_r(J)
K = tup_r(K)
if try_num >= 3 :pygame.draw.line(screen, white, I, J, 3)
if try_num >= 4 :pygame.draw.line(screen, white, I, K, 3)
L = (I[0], I[1]+l_arm)
if try_num >= 5 :pygame.draw.line(screen, white, I, L, 3)
l_leg = round(l_arm * 1.5)
M = (L[0]-l_leg*math.cos(60*math.pi/180),
L[1]+l_leg*math.sin(60*math.pi/180))
N = (L[0]+l_leg*math.cos(60*math.pi/180),
L[1]+l_leg*math.sin(60*math.pi/180))
M = tup_r(M)
N = tup_r(N)
if try_num >= 6 :pygame.draw.line(screen, white, L, M, 3)
if try_num >= 7 :pygame.draw.line(screen, white, L, N, 3)
if drop == False and try_num == 8:
O = tup_r((size[0]/2-size[0]/6, E[1]/2+F[1]/2))
P = (O[0]+k*2, O[1])
if P[0] > size[0]/2+size[0]/6 :
P = tup_r((size[0]/2+size[0]/6, O[1]))
drop = True
k = 0
pygame.draw.line(screen, red, O, P, 3)
# 힌트 표시하기
hint = hint_font.render(word_show, True, white)
hint_size = hint.get_size()
hint_pos = tup_r((size[0]/2-hint_size[0]/2, size[1]*5/6-hint_size[1]/2))
screen.blit(hint, hint_pos)
# 입력창 표시하기
entry = entry_font.render(entry_text, True, black)
entry_size = entry.get_size()
entry_pos = tup_r((size[0]/2-entry_size[0]/2, size[1]*17/18-entry_size[1]/2))
entry_bg_size = 80
pygame.draw.rect(screen, white, tup_r((size[0]/2-entry_bg_size/2, size[1]*17/18-entry_bg_size/2
,entry_bg_size ,entry_bg_size)))
screen.blit(entry, entry_pos)
# 오답 표시하기
no_text = " ".join(no_list)
no = no_font.render(no_text, True, red)
no_pos = tup_r((20, size[1]*2/3+20))
screen.blit(no, no_pos)
# 4-5. 업데이트
pygame.display.flip()
# 5. 게임 종료
pygame.quit()
- 게임의 로직(시나리오, 텍스트 파일에서 단어를 랜덤으로 가져옴. 한글자씩 입력해서 맞는지 틀렸는지 판단)을 결합
- 오답 표시
- no_text변수에 저장
- 승리 판단(종료)은 그림 그리기 전에 구현
- set_alpha = 투명도
- 시작화면은 while문 시작하기 전에 구현