지난 시간에 파이게임 사용법을 살펴 보았습니다.
https://wondangcom.tistory.com/2597
오늘은 파이게임에서 객체를 생성하고 키보드를 이용하여 이동하는 방법을 살펴 보도록 하겠습니다.
객체를 만들기 위한 이미지는 파이게임 튜토리얼(https://github.com/formazione/pygame_tutorial)에 있는 이미지를 사용하겠습니다.
이미지를 보면 각 행동에 대한 이미지가 여러개 있는 것을 확인 할 수 있습니다.
여기서 Dead 를 선택한다면 Dead(1) ~ Dead(15) 까지 적당한 시간을 두고 이미지를 변경 한다면 마치 쓰러지는 사람처럼 보일것입니다.
객체생성
1. 파이썬 객체 생성
- 플레이어를 관리할 수 있는 객체를 생성하고 객체를 이용해서 인스턴스를 만드는 방법을 살펴 보자.
- 클래스 생성 : pygme의 sprite를 상속받아서 객체를 생성한다
class Player(pygame.sprite.Sprite):
def __init__(self,location=(0, 0),imgsize=(100,100)):
self.action = 'Idle' #최초 생성될때 상태
self.index = 0
self.imgsize=imgsize
# if you use more istance with the same image
# if MySprite.image is None
self.list_surfaces = self.ordered_list_of_surfaces()
self.image = self.list_surfaces[0]
self.image = pygame.transform.scale(self.image,self.imgsize)
self.rect = self.image.get_rect()
self.rect.topleft = location
def ordered_list_of_surfaces(self):
self.los = [
pygame.image.load(img)
for img in glob.glob(f"png\\{self.action}*.png")
]
return self.los
Player 의 최초 상태는 대기 상태로 생성을 한다.
ordered_list_of_surfaces 메서드를 이용해서 png 디렉토리에 있는 Idle*.png 이미지 파일을 모두 읽어서 리스트로 반환한다.
이미지를 읽어온 첫번째 이미지를 이용하여 생성한다.
클래스를 만들었다면 이 클래스를 이용하여 인스턴스를 생성해 보자.
- 인스턴스 생성
player1 = Player()
이렇게 생성된 player1이 처음 대기 상태로 화면에 출력 되기 위해서는 앞에서 살펴 보았던 파이게임을 이용한 화면 출력이 필요하다.
2. 화면에 객체 띄우기
다음과 같이 화면에 출력하는 프로그램을 작성하자.
import pygame,sys,glob
#파이게임 초기화하기
pygame.init()
# 게임 화면 초기화 하기
screen = pygame.display.set_mode((1024,768))
#제목 표시줄 설정하기
pygame.display.set_caption("pygame test")
#프레임 매니저 초기화하기
clock = pygame.time.Clock()
#프레임 레이트 설정하기
clock.tick(60)
#배경색상 설정하기
screen.fill((255,255,255))
player1 = Player()
while True:
screen.fill((255, 255, 255))
screen.blit(player1.image, player1.rect)
#이벤트 확인하기
for event in pygame.event.get():
#닫기 버튼을 눌렀는지
if event.type == pygame.QUIT:
#게임 끝내기
pygame.quit()
sys.exit()
#화면 업데이트하기
pygame.display.update()
#프레임 레이트 설정하기
clock.tick(60)
화면에 Idle 첫번째 이미지만 고정적으로 출력된다. 동적으로 움직이는 것처럼 만들어 보자.
클래스에 다음과 같이 메서드를 추가한다.
class Player(pygame.sprite.Sprite):
...
def update(self):
self.index += 0.2
if self.index >= len(self.list_surfaces):
self.index = 0
self.image = self.list_surfaces[int(self.index)]
self.image = pygame.transform.scale(self.image, self.imgsize) #이미지 크기변경
player의 update를 실행하면 5번 호출 될때 마다 다음 이미지로 이미지를 변경한다.
그 다음 파이게임이 호출되는 무한반복 안에서 update를 호출한다.
while True:
screen.fill((255, 255, 255))
player1.update() #추가
screen.blit(player1.image, player1.rect)
...
쉬고 있는 이미지가 반복해서 출력 되는 것을 확인할 수 있다.
플레이어를 R 키를 눌렀을때는 Run 이미지로, J키를 눌렀을 때는 Jump, D 키를 눌렀을 때는 Dead, W키를 눌렀을 때는 Walk,I를 눌렀을 때 Idle 상태로 동작 상태를 변경하도록 하자.
클래스에 다음과 같이 action_change를 추가하자.
class Player(pygame.sprite.Sprite):
...
def action_change(self,action):
self.action =action
self.index = 0
# if you use more istance with the same image
# if MySprite.image is None
self.list_surfaces = self.ordered_list_of_surfaces()
self.image = self.list_surfaces[0]
self.image = pygame.transform.scale(self.image, self.imgsize) #이미지 크기 변경
self.rect = self.image.get_rect()
action_change 에 action을 호출하면 이미지 리스트를 action에 맞는 이미지로 변경한다.
파이게임에서 호출되는 위치에서 이벤트를 입력 받아 각각의 키값에 따라 액션을 바꿔 보자.
while True:
#이벤트 확인하기
for event in pygame.event.get():
#닫기 버튼을 눌렀는지
if event.type == pygame.QUIT:
#게임 끝내기
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_r : #r키가 눌렸을때
player1.action_change('Run')
elif event.key == pygame.K_j : #j키가 눌렸을때
player1.action_change('Jump')
elif event.key == pygame.K_d : #d키가 눌렸을때
player1.action_change('Dead')
elif event.key == pygame.K_w : #d키가 눌렸을때
player1.action_change('Walk')
elif event.key == pygame.K_i : #i키가 눌렸을때
player1.action_change('Idle')
screen.fill((255, 255, 255))
player1.update()
screen.blit(player1.image, player1.rect)
#화면 업데이트하기
pygame.display.update()
#프레임 레이트 설정하기
clock.tick(60)
키보드가 눌렸는지를 판단해서 각각의 키값에 따라 action 값을 변경해 주면 해당 action에 맞는 이미지를 리스트에 로딩하기 때문에 아래와 같이 변경이 되는 것을 확인할 수 있다.
이제 키값이 들어 왔을때 플레이어를 이동시켜 보자.
객체이동
1. 이동 방향에 따라 이미지를 반전시키자.
왼쪽 오른쪽 방향키에 따라 이동하고 이동하는 동안은 걷는 모양, 서 있을 때는 Idle 모양으로 변경 해 보자
단 왼쪽 방향키를 눌렀을때 이미지의 방향을 반전시켜야 한다. 반전시키기 위해 다음과 같이 프로그램을 수정하자.
class Player(pygame.sprite.Sprite):
def __init__(self,location=(0, 0),imgsize=(100,100)):
...
self.flipped = False #False 일때는 반전하지 않는다.
...
self.list_surfaces = self.ordered_list_of_surfaces(self.flipped)
...
def ordered_list_of_surfaces(self,flipped=False):
if flipped :
self.los = [
pygame.transform.flip(pygame.image.load(img), True, False)
for img in glob.glob(f"png\\{self.action}*.png")
]
else :
self.los = [
pygame.image.load(img)
for img in glob.glob(f"png\\{self.action}*.png")
]
return self.los
...
def action_change(self,action,flipped=False):
...
self.list_surfaces = self.ordered_list_of_surfaces(flipped)
...
flipped= True 일때 이미지를 로딩할 때 반전 이미지를 로딩한다.
2. 방향키에 따라 이동하도록 만들자.
moveSpeed = 2
direct = False
while True:
# 키보드 눌렀을때 True
keys = pygame.key.get_pressed()
# 왼쪽 화살표를 눌렀다면
if keys[pygame.K_LEFT] and player1.rect.left - moveSpeed > 0:
direct = True
player1.move(-moveSpeed, 0)
player1.action_change('Walk', direct)
# 오른쪽 화살표를 눌렀다면
elif keys[pygame.K_RIGHT] and player1.rect.right + moveSpeed < SCREEN_WIDTH:
direct = False
player1.move(moveSpeed, 0)
player1.action_change('Walk', direct)
else:
#print(direct)
player1.action_change('Idle', direct)
#이벤트 확인하기
for event in pygame.event.get():
#닫기 버튼을 눌렀는지
if event.type == pygame.QUIT:
#게임 끝내기
pygame.quit()
sys.exit()
screen.fill((255, 255, 255))
player1.update() #다음 이미지로 처리 하기 위해 처리
screen.blit(player1.image, player1.rect)
#화면 업데이트하기
pygame.display.update()
#프레임 레이트 설정하기
clock.tick(60)
moveSpeed 의 값을 설정하고 왼쪽 키를 눌렀을때 화면 밖으로 나가지 않는 동안 왼쪽으로 이동한다. 이때는 방향을 변경해 주기 위해 direct = True 로 변경해서 방향을 변경해서 이미지를 읽어 왔다.
이 때 키를 누르고 있으면 이미지가 다음 이미지로 이동하지 않고 처음이미지만 나오는 현상이 발생한다.
또한 이동하지 않는다.
이것은 action_change를 호출 할 때마다 index가 0으로 설정 되기 때문이다.
이때 기존의 index를 유지하는 형태로 처리해 보자.
class Player(pygame.sprite.Sprite):
...
def action_change(self,action,flipped=False):
self.action =action
#self.index = 0
self.list_surfaces = self.ordered_list_of_surfaces(flipped)
if self.index >= len(self.list_surfaces):
self.index = 0
self.image = self.list_surfaces[int(self.index)]
self.image = pygame.transform.scale(self.image, self.imgsize)
#self.rect = self.image.get_rect()
self.index = 0 을 주석 처리하고 새로 읽어온 이미지의 길이보다 더 크다면 0으로 변경 후에 해당 이미지를 처리했다.
self.rect 에 이미지의 get_rect()를 가져 오므로 move 를 해도 처음 위치로 되돌아 가기 때문에 self.rect 를 설정하는 부분을 주석 처리 했다.
이상으로 파이게임 객체를 생성해서 이동하는 것을 살펴 보았습니다.
다음시간에는 동물 객체를 만들어서 사람과 고양이가 서로 상속 받아서 움직이는 방법을 살펴 보도록 하겠습니다.
'강의자료 > 텍스트기반SW' 카테고리의 다른 글
[파이썬] 파이게임 객체 임의의 위치로 이동하기 (10) | 2023.08.17 |
---|---|
[파이썬] 파이게임 객체 상속 (27) | 2023.08.10 |
[파이썬] 파이게임 사용법 (18) | 2023.07.21 |
파이썬으로 JSON 파일 다루기 및 실행파일 만들기 (16) | 2023.07.13 |
파이썬으로 웹 크롤링 하고 바드에게 묻고 답하기 (2) | 2023.07.05 |