# 사운드 출력
import pygame
import sys
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
CYAN = (0, 255, 255)
def main():
pygame.init()
pygame.display.set_caption('Sound')
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
font = pygame.font.Font(None, 40)
try: # 예외 처리
pygame.mixer.music.load('Python_workspace\mini_game\sound_dir\pygame_bgm.ogg') # BGM 로딩
se = pygame.mixer.Sound('Python_workspace\mini_game\sound_dir\pygame_se.ogg') # SE 로딩
except: # 예외 발생시
print('Wrong ogg file or No Audio Found') # 메세지 출력
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
key = pygame.key.get_pressed()
if key[pygame.K_p] == 1: # P 키를 눌렀을 때
if pygame.mixer.music.get_busy() == False: # BGM이 정지 중이라면
pygame.mixer.music.play(-1) # BGM 재생
if key[pygame.K_s] == 1: # S 키를 눌렀을 때
if pygame.mixer.music.get_busy() == True: # BGM이 재생 중이라면
pygame.mixer.music.stop() # BGM 정지
if key[pygame.K_SPACE] == 1: # SPACE 키를 눌렀으면
se.play() # SE 재생
pos = pygame.mixer.music.get_pos() # 변수에 BGM 재생 시간 대입
txt1 = font.render('BGM pos' + str(pos), True, WHITE) # 재생 시간을 표시할 Surface
txt2 = font.render('[P]lay bgm : [S]top bgm : [SPACE] se', True, CYAN) # 조작 방법을 표시할 Surface
screen.fill(BLACK)
screen.blit(txt1, [100, 100])
screen.blit(txt2, [100, 200])
pygame.display.update()
clock.tick(10)
if __name__ == '__main__':
main()
사운드를 재생하는 방법에 대한 부분이다.
명령 | 코드 | 비고 |
---|---|---|
파일 로딩 | pygame.mixer.music.load(파일명) | |
재생 | pygame.mixer.music.play(인수) | 인수에 -1을 입력하면 반복 재생되고, 0을 입력하면 1회 재생되며, 5를 입력하면 6회 반복 재생된다. |
정지 | pygame.mixer.music.stop() | |
재생 시간 얻기 | pygame.mixer.music.get_pos() | 밀리초 값 |
재생 상태 확인 | pygame.mixer.music.get_busy() | 재생 중이면 True, 그렇지 않으면 False |
pygame에서 한국어를 쓰려면 별도로 처리해줘야 한다.
font = pygame.font.SysFont('malgungothic', 80) # 시스템 폰트 사용시
font = pygame.font.Font('{font_path}/{font_name}.ttf', 80) # 별도의 폰트 사용시
미로 생성 알고리즘 중에 기둥 쓰러뜨리기 법이라는 것이 있다고 한다.
- 테두리를 벽으로 둘러 싼다.
- 내부에 1칸씩 기둥을 놓는다.
- 각 기둥에서 상하좌우 중 하나의 방향(무작위)으로 벽을 만들면 미로가 완성된다.
- 가장 왼쪽 열의 기둥에서부터 4방향 중 하나에 벽을 만들고 그다음 열에서부터는 상, 하, 우 3방향 중 하나에 벽을 만든다.
이 방법의 주의점은 무작위로 4개 방향으로 벽을 만들면 들어갈 수 없는 칸이 생길 가능성이 있다는 것이다. 이는 4번으로 해결할 수 있다.
import pygame
import sys
import random
CYAN = (0, 255, 255)
GRAY = (96, 96, 96)
MAZE_W = 11 # 미로 가로 칸 수
MAZE_H = 9 # 미로 세로 칸 수
maze = [] # 미로 데이터 관리 리스트
for y in range(MAZE_H): # 리스트 초기화
maze.append([0] * MAZE_W)
def make_maze():
XP = [0, 1, 0, -1] # 기둥에서 벽을 그리기 위한 값 정의
YP = [-1, 0, 1, 0] # "
# 미로 생성 알고리즘 1번
# 주변 벽
for x in range(MAZE_W):
maze[0][x] = 1
maze[MAZE_H - 1][x] = 1
for y in range(1, MAZE_H - 1):
maze[y][0] = 1
maze[y][MAZE_W - 1] = 1
# 안을 아무것도 없는 상태로
for y in range(1, MAZE_H - 1):
for x in range(1, MAZE_W - 1):
maze[y][x] = 0
# 미로 생성 알고리즘 2번
# 기둥
for y in range(2, MAZE_H - 2, 2):
for x in range(2, MAZE_W - 2, 2):
maze[y][x] = 1
# 미로생성 알고리즘 3번
# 기둥에서 상하좌우로 벽 생성
for y in range(2, MAZE_H - 2, 2):
for x in range(2, MAZE_W - 2, 2):
d = random.randint(0, 3)
# 미로 생성 알고리즘 4번
if x > 2: # 2번째 열부터 왼쪽으로는 벽을 만들지 않음
d = random.randint(0, 2)
maze[y + YP[d]][x + XP[d]] = 1
def main():
pygame.init()
pygame.display.set_caption('Maze making')
screen = pygame.display.set_mode((528, 432))
clock = pygame.time.Clock()
make_maze()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE: # 스페이스 키를 누르면
make_maze() # 미로 생성 함수 호출
for y in range(MAZE_H):
for x in range(MAZE_W):
W = 48 # 1칸의 폭
H = 48 # 1칸의 높이
X = x * W # 표시할 X 좌표 계산
Y = y * H # 표시할 Y 좌표 계산
if maze[y][x] == 0: # 미로
pygame.draw.rect(screen, CYAN, [X, Y, W, H]) # 길이라면 하늘색으로 칸을 채움
if maze[y][x] == 1: # 벽
pygame.draw.rect(screen, GRAY, [X, Y, W, H]) # 벽이라면 회색으로 칸을 채움
pygame.display.update()
clock.tick(2)
if __name__ == '__main__':
main()
위에서 설명한 미로 생성 알고리즘을 이용하여 자동으로 미로를 생성해서 보여준다.
미로에서 던전으로 데이터 변환을 수행해야 한다.
- 던전을 정의하기 위한 2차원 리스트 dungeon을 준비한다.
- maze의 칸 상태를 조사하면서 dungeon에 값을 설정한다.
- dungeon의 내용을 먼저 모두 벽으로 바꾼다.
- maze[y][x] 값을 확인한 수가 0(길)이면 무작위로 던전에 방을 만든다.
- 방을 만들지 않는 경우 maze[y][x]의 상하좌우 칸을 확인하고 0이면 그 방향으로 던전에 통로를 만든다.
# 던전 생성
import pygame
import sys
import random
BLACK = (0, 0, 0)
CYAN = (0, 255, 255)
GRAY = (96, 96, 96)
MAZE_W = 11 # 미로 가로 칸 수
MAZE_H = 9 # 미로 세로 칸 수
maze = [] # 미로 데이터 관리 리스트
for y in range(MAZE_H): # 리스트 초기화
maze.append([0] * MAZE_W)
DUNGEON_W = MAZE_W * 3
DUNGEON_H = MAZE_H * 3
dungeon = []
for y in range(DUNGEON_H):
dungeon.append([0] * DUNGEON_W)
imgWall = pygame.image.load('Python_workspace\mini_game\image_dir\wall.png')
imgFloor = pygame.image.load('Python_workspace\mini_game\image_dir\\floor.png')
def make_dungeon(): # 던전 자동 생성
# 26 ~ 58번 줄까지는 미로 생성
XP = [0, 1, 0, -1] # 기둥에서 벽을 그리기 위한 값 정의
YP = [-1, 0, 1, 0] # "
# 미로 생성 알고리즘 1번
# 주변 벽
for x in range(MAZE_W):
maze[0][x] = 1
maze[MAZE_H - 1][x] = 1
for y in range(1, MAZE_H - 1):
maze[y][0] = 1
maze[y][MAZE_W - 1] = 1
# 안을 아무것도 없는 상태로
for y in range(1, MAZE_H - 1):
for x in range(1, MAZE_W - 1):
maze[y][x] = 0
# 미로 생성 알고리즘 2번
# 기둥
for y in range(2, MAZE_H - 2, 2):
for x in range(2, MAZE_W - 2, 2):
maze[y][x] = 1
# 미로생성 알고리즘 3번
# 기둥에서 상하좌우로 벽 생성
for y in range(2, MAZE_H - 2, 2):
for x in range(2, MAZE_W - 2, 2):
d = random.randint(0, 3)
# 미로 생성 알고리즘 4번
if x > 2: # 2번째 열부터 왼쪽으로는 벽을 만들지 않음
d = random.randint(0, 2)
maze[y + YP[d]][x + XP[d]] = 1
# 60 ~ 85번 줄까지는 미로를 던전 데이터로 변환
# 미로에서 던전 생성
# 전체를 벽으로 만듬
for y in range(DUNGEON_H):
for x in range(DUNGEON_W):
dungeon[y][x] = 9 # dungeon 값을 모두 9(벽)으로 설정
# 방과 미로 배치
for y in range(1, MAZE_H - 1):
for x in range(1, MAZE_W - 1):
dx = x * 3 + 1
dy = y * 3 + 1
if maze[y][x] == 0: # 미로 데이터 확인, 칸이 길이라면
if random.randint(0, 99) < 20: # 방 생성 여부를 무작위로 결정
for ry in range(-1, 2):
for rx in range(-1, 2):
dungeon[dy + ry][dx + rx] = 0 # 3 x 3 칸의 방으로 만듬
else: # 방을 만들지 않는 경우 통로 생성
dungeon[dy][dx] = 0 # 3 x 3 칸 중앙을 통로로
if maze[y - 1][x] == 0: # 미로의 위 칸이 길이라면 통로를 위로 연징
dungeon[dy - 1][dx] = 0
if maze[y + 1][x] == 0: # 미로의 아래 칸이 길이라면 통로를 아래로 연장
dungeon[dy + 1][dx] = 0
if maze[y][x - 1] == 0: # 미로의 왼쪽 칸이 길이라면 통로를 왼쪽으로 연장
dungeon[dy][dx - 1] = 0
if maze[y][x + 1] == 0: # 미로 오른쪽 칸이 길이라면 통로를 오른쪽으로 연장
dungeon[dy][dx + 1] = 0
def main():
pygame.init()
pygame.display.set_caption('Maze making')
screen = pygame.display.set_mode((1056, 432))
clock = pygame.time.Clock()
make_dungeon()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE: # 스페이스 키를 누르면
make_dungeon() # 미로 생성 함수 호출
# 확인용 미로 표시
for y in range(MAZE_H):
for x in range(MAZE_W):
W = 48 # 1칸의 폭
H = 48 # 1칸의 높이
X = x * W # 표시할 X 좌표 계산
Y = y * H # 표시할 Y 좌표 계산
if maze[y][x] == 0: # 미로
pygame.draw.rect(screen, CYAN, [X, Y, W, H]) # 길이라면 하늘색으로 칸을 채움
if maze[y][x] == 1: # 벽
pygame.draw.rect(screen, GRAY, [X, Y, W, H]) # 벽이라면 회색으로 칸을 채움
# 던전 그리기
for y in range(DUNGEON_H):
for x in range(DUNGEON_W):
X = x * 16 + 528
Y = y * 16
if dungeon[y][x] == 0:
screen.blit(imgFloor, [X, Y])
if dungeon[y][x] == 9:
screen.blit(imgWall, [X, Y])
pygame.display.update()
clock.tick(2)
if __name__ == '__main__':
main()
여기서 벽을 9로 표현한 이유는 추후에 보물상자와 같은 다른 것들을 배치하기 위해서이다.
던전 생성에서 미로 1칸은 던전에서 3 x 3 칸에 해당한다. 그래서 'dx = x * 3 +1', 'dy = y * 3 + 1'로 변수를 준비한 것이고, 각 변수에 +1을 한 건 dx, dy를 3 x 3칸의 중앙 좌표 값으로 하기 위해서이다.