# 턴제 전투
import pygame
import sys
import random
from pygame.locals import * # 이벤트 종류와 키보드 상수 등을 pygame.을 생략할 수 있음
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
imgBtlBG = pygame.image.load('Python_workspace\mini_game\image_dir\\btlbg.png') # 전투 배경 이미지 로딩
imgEffect = pygame.image.load('Python_workspace\mini_game\image_dir\effect_a.png') # 공격 효과 이미지 로딩
imgEnemy = pygame.image.load('Python_workspace\mini_game\image_dir\enemy4.png') # 적 이미지 로딩
emy_x = 440 - imgEnemy.get_width() / 2 # 이미지 폭으로부터 표시 위치(X 좌표) 계산
emy_y = 560 - imgEnemy.get_height() # 이미지 높이로부터 표시 위치(Y 좌표) 계산
emy_step = 0 # 적 이동 관리 변수
emy_blink = 0 # 적 깜빡임 효과 관리 변수
dmg_eff = 0 # 화면 흔들림 효과 관리 변수
COMMAND = ['[A]ttack', '[P]otion', '[B]laze gem', '[R]un'] # 전투 명령어 리스트
message = [''] * 10 # 전투 메시지 입력 리스트
def init_message(): # 메시지 초기화 함수
for i in range(10):
message[i] = '' # 리스트에 빈 문자열 대입
def set_message(msg): # 메시지 설정 함수
for i in range(10):
if message[i] == '': # 문자열이 설정되어 있지 않다면
message[i] = msg # 새로운 문자열 대입
return # 함수 처리 종료
for i in range(9):
message[i] = message[i + 1] # 메시지를 한 문자씩 슬라이스
message[9] = msg # 마지막 행에 새로운 문자열 대입
def draw_text(bg, txt, x, y, fnt, col): # 문자열 그림자 처리 함수
sur = fnt.render(txt, True, BLACK) # 검은 색으로 문자열을 표시할 Surface
bg.blit(sur, [x + 1, y + 2]) # 지정 좌표의 약간 오른쪽 아래에 문자열 전송
sur = fnt.render(txt, True, col) # 지정한 색으로 문자열을 표시할 Surface
bg.blit(sur, [x, y]) # 지정 좌표에 문자열 전송
def draw_battle(bg, fnt): # 전투 화면 표시 함수
global emy_blink, dmg_eff
bx = 0 # 배경 표시 위치 X 좌표
by = 0 # 배경 표시 위치 Y 좌표
if dmg_eff > 0: # 화면 흔들림 효과 변수가 설정되어 있다면
dmg_eff -= 1 # 해당 변수값 1 감소
bx = random.randint(-20, 20) # 난수로 X 좌표 결정
by = random.randint(-10, 10) # 난수로 Y 좌표 결정
bg.blit(imgBtlBG, [bx, by]) # (bx, by) 위치에 배경 표시
if emy_blink % 2 == 0: # 적을 깜빡이기 위한 if 구문
bg.blit(imgEnemy, [emy_x, emy_y + emy_step]) # 적 캐릭터 표시
if emy_blink > 0: # 적을 깜빡이기 위한 변수가 설정되어 있다면
emy_blink -= 1 # 해당 변수값 1 감소
for i in range(10):
draw_text(bg, message[i], 600, 100 + i * 50, fnt, WHITE) # 전투 메시지 표시
def battle_command(bg, fnt): # 전투 명령어 표시 함수
for i in range(4):
draw_text(bg, COMMAND[i], 20, 360 + 60 * i, fnt, WHITE) # 전투 명령어 표시
def main():
global emy_step, emy_blink, dmg_eff
idx = 10 # 게임 진행 관리 인덱스
tmr = 0 # 게임 진행 관리 타이머 변수
pygame.init()
pygame.display.set_caption('Battle Turn')
screen = pygame.display.set_mode((880, 720))
clock = pygame.time.Clock()
font = pygame.font.Font(None, 30)
init_message()
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
draw_battle(screen, font)
tmr += 1 # tmr 값 1 증가
key = pygame.key.get_pressed()
if idx == 10: # 전투 개시
if tmr == 1: set_message('Encounter!') # tmr 값이 1이면 메시지 설정
if tmr == 6: # tmr 값이 6이면
idx = 11 # 플레이어 입력 대기로 이동
tmr = 0
elif idx == 11: # 플레이어 입력 대기
if tmr == 1: set_message('Your turn.')
battle_command(screen, font) # 전투 명령어 표시
if key[K_a] == 1 or key[K_SPACE] == 1: # [A]키 또는 [SPACE]키를 눌렀으면
idx = 12 # 플레이어 공격으로 이동
tmr = 0
elif idx == 12: # 플레이어 공격
if tmr == 1: set_message('You attack!')
if 2 <= tmr and tmr <= 4: # tmr 값이 2에서 4 사이이면
screen.blit(imgEffect, [700 - tmr * 120, -100 + tmr * 120]) # 공격 효과 표시
if tmr == 5: # tmr 값이 5이면
emy_blink = 5 # 적 깜빡임 효과 변수 설정
set_message('***pts of damage!')
if tmr == 16: # tmr 값이 16이면
idx = 13 # 적 턴으로 이동
tmr = 0
elif idx == 13: # 적 턴, 적 공격
if tmr == 1: set_message('Enemy turn.')
if tmr == 5:
set_message('Enemy attack!')
emy_step = 30 # 적 이동 변수 설정
if tmr == 9:
set_message('***pts of damage!')
dmg_eff = 5 # 화면 흔들림 변수 값 설정
emy_step = 0 # 적을 원래 위치로 이동
if tmr == 20:
idx = 11 # 플레이어 입력 대기로 이동
tmr = 0
pygame.display.update()
clock.tick(5)
if __name__ == '__main__':
main()
이전에는 PyQt로 구현하느라 해보지 않았던 인덱스에 따른 구현을 해봤다.
# 게임 화면 연출
import pygame
import sys
import random
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
def main():
pygame.init()
pygame.display.set_caption('반투명과 스크롤')
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
surface_a = pygame.Surface((800, 600)) # 가로 800px, 세로 600px Surface 준비
surface_a.fill(BLACK) # 해당 Surface를 검정색으로 채움
surface_a.set_alpha(32) # 투명도 설정
CHIP_MAX = 50 # 탄막 수
cx = [0] * CHIP_MAX # 탄막 X 좌표
cy = [0] * CHIP_MAX # 탄막 Y 좌표
xp = [0] * CHIP_MAX # 탄막 X 방향 이동량
yp = [0] * CHIP_MAX # 탄막 Y 방향 이동량
for i in range(CHIP_MAX):
cx[i] = random.randint(0, 800) # 난수로 탄막 x 좌표 결정
cy[i] = random.randint(0, 600) # 난수로 탄막 y 좌표 결정
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.scroll(1, 4) # 화면에 그린 이미지 이동(스크롤)
screen.blit(surface_a, [0, 0]) # 화면에 검은 반투명 Surface 겹침
mx, my = pygame.mouse.get_pos() # 변수에 마우스 포인터 좌표 대입
pygame.draw.rect(screen, WHITE, [mx - 4, my - 4, 8, 8]) # 마우스 포인터 좌표에 사각형 표시
# 탄막의 이동량과 좌표 계산
for i in range(CHIP_MAX): # 반복에서 탄막을 이동
# 마우스 포인터 좌표와 탄막 좌표를 비교하고 X 방향과 Y 방향 이동량을 변경
if mx < cx[i] and xp[i] > -20: xp[i] = xp[i] - 1
if mx > cx[i] and xp[i] < 20: xp[i] = xp[i] + 1
if my < cy[i] and yp[i] > -16: yp[i] = yp[i] - 1
if my > cy[i] and yp[i] < 16: yp[i] = yp[i] + 1
cx[i] = cx[i] + xp[i] # X 좌표 변경
cy[i] = cy[i] + yp[i] # Y 좌표 변경
pygame.draw.circle(screen, (0, 64, 192), [cx[i], cy[i]], 12) # 탄막 표시
pygame.draw.circle(screen, (0, 128, 224), [cx[i], cy[i]], 9) # 탄막 표시
pygame.draw.circle(screen, (192, 224, 244), [cx[i], cy[i]], 6) # 탄막 표시
pygame.display.update()
clock.tick(30)
if __name__ == '__main__':
main()
탄막이 마우스 포인터를 쫓아가며 윈도우 안을 날아다닌다.
탄막은 좌표를 관리하는 cx, cy와 이동량을 관리하는 xp, yp 리스트를 사용해 관성의 영향을 받는 움직임으로 표시한다. 탄막의 이동량과 좌표를 계산할 때 좌표에 이동량을 더하는 것이 포인트이다.
반투명 Surface를 만드는데 set_alpha() 명령은 인수로 Surface 전체의 투명도를 지정한다. 인수값이 0이면 완전 투명, 255이면 완전 불투명이다.
scroll 명령은 윈도우 내에 그린 이미지를 스크롤한다. 인수는 이미지를 이동할 X 방향 픽셀 수, Y 방향 픽셀 수이다.
blit 명령으로 검은 반투명 Surface를 윈도우 전체에 겹쳤는데 이것을 통해 이전에 그려진 것들은 점점 반투명한 검은 막에 덮이다가 사라지는 것처럼 연출이 된다.