2023.07.27 - [강의자료/텍스트기반SW] - [파이썬] 파이게임 객체 생성
지난 시간 Player의 객체를 생성해서 이동하는 것 까지 만들어 보았습니다.
이번 시간에는 고양이 객체를 생성해서 Player의 주변을 따라 다니도록 프로그램을 구현해 보겠습니다.
객체를 만들기 위한 이미지는 파이게임 튜토리얼(https://github.com/formazione/pygame_tutorial)에 있는 이미지를 사용하겠습니다.
그런데 여기서 고양이와 Player의 속성이 많이 비슷한 것을 알 수 있습니다.
가령 Player도 Walk,Idle,Dead,Jump 등의 행동을 할 수 있고, 생명도 있습니다.
현재 구현하는 것에서 다른것은 그때 그때마다 서로 다른 이미지를 사용하는 것 밖에 없겠네요.
그렇다면 두개의 속성을 같이 갖는 Animal 이라는 객체를 생성하고 그 객체를 상속 받아서 Player 과 Cat 을 별도로 만들어 보는 프로그램을 만들어 보겠습니다.
Animal 객체생성
프로퍼티 정의
- 상태 : Idle(가만히 있기),Walk(걷기),Jump(점프),Run(달리기),Dead(사망)
- 이동속도 : walkSpeed,jumpSpeed,runSpeed
- 현재방향 : East,Weast,North,South
- 현재위치 : x,y
- 객체크기 : size
일단 위의 정보를 이용하여 객체를 생성해 보자.
class Animal(pygame.sprite.Sprite):
def __init__(self, location=(0, 0), imgsize=(100, 100), walkSpeed=1, jumpSpeed=2, runSpeed=5):
self.action = 'Idle'
self._predir = '' # 방향이 변경 되면 방향에 맞게 이미지를 새로 로딩하자.
self._dir = 'W' # 기본으로 동쪽을 바라보도록 처리하자.
self.index = 0
self.size = imgsize
self.location = location
self.walkSpeed = walkSpeed
self.jumpSpeed = jumpSpeed
self.runSpeed = runSpeed
self.list_surfaces = [] # 해당 객체의 이미지를 로딩해서 적재하는 리스트
self.image = None # 현재 이미지 적재 위치
def get_walkSpeed(self): return self._walkSpeed
def set_walkSpeed(self, speed):
if speed < 0: return # 음수 속도는 받을 수 없다.
self._walkSpeed = speed
def get_jumpSpeed(self): return self._jumpSpeed
def set_jumpSpeed(self, speed):
if speed < 0 : return #음수 속도는 받을 수 없다.
self._jumpSpeed = speed
def get_runSpeed(self): return self._runSpeed
def set_runSpeed(self, speed):
if speed < 0: return # 음수 속도는 받을 수 없다.
self._runSpeed = speed
walkSpeed = property(get_walkSpeed, set_walkSpeed)
jumpSpeed = property(get_jumpSpeed, set_jumpSpeed)
runSpeed = property(get_runSpeed, set_runSpeed)
Animal 의 속성 정보를 프로퍼티로 사용하기 위해 위와 같이 각각의 속성을 프로퍼티로 정의 하였다.
프로퍼티로 정의 하면 animal.action = 'Walk' 와 같이 값을 대입하면 set_action 의 메서드를 사용하기 때문에 각각의 메서드에서 추가로 데이터의 오류를 보정할 수 있게 된다.
Animal 에 이미지의 동작을 표현할 수 있도록 update 메서드를 통해서 다음 이미지로 바꿀 수 있도록 만들어 보자.
def update(self):
if len(self.list_surfaces) == 0 :
return #이미지가 적재 되기 전에는 빠져 나가자.
self.index += 0.5
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.size)
한 프레임이 동작할때마다 _index를 0.5 씩 증가 시켜서 두 프레임이 동작할 때 다음 이미지를 출력하도록 바꾸었다.
여기서 Animal에 움직일 수 있도록 move() 메서드를 생성한다. 이때 상태에 따라 해당 속도 만큼 이동시켜 주자.
def move(self):
if self.image == None: return
speed = 0
if self.action == 'Idle':
speed = 0
elif self.action == 'Walk':
speed = self.walkSpeed
elif self.action == 'Jump':
speed = self.jumpSpeed
elif self.action == 'Run':
speed = self.runSpeed
x = 0
y = 0
if self.dir == 'W': # 서쪽 방향이면
x = -speed
elif self.dir == 'E': # 동쪽이면
x = speed
elif self.dir == 'N': # 북쪽이면
y = -speed
elif self.dir == 'S': # 서쪽이면
y = speed
if self.rect.left + x < 0: return
if self.rect.top + y < 0: return
if self.rect.right + x > SCREEN_WIDTH: return
if self.rect.bottom + y > SCREEN_HEIGH: return
self.rect.move_ip(x, y)
현재 상태에 따라 속도를 정해 주고 방향에 따라 x,y 축에 속도만큼의 크기를 설정 후에 범위를 넘어 가지 않는다면 해당 위치로 이동시켜 주자.
Animal 객체 전체 코드
class Animal(pygame.sprite.Sprite):
def __init__(self, location=(0, 0), imgsize=(100, 100), walkSpeed=1, jumpSpeed=2, runSpeed=5):
self.action = 'Idle'
self._predir = '' # 방향이 변경 되면 방향에 맞게 이미지를 새로 로딩하자.
self._dir = 'W' # 기본으로 동쪽을 바라보도록 처리하자.
self.index = 0
self.size = imgsize
self.location = location
self.walkSpeed = walkSpeed
self.jumpSpeed = jumpSpeed
self.runSpeed = runSpeed
self.list_surfaces = [] # 해당 객체의 이미지를 로딩해서 적재하는 리스트
self.image = None # 현재 이미지 적재 위치
def update(self):
if len(self.list_surfaces) == 0 :
return #이미지가 적재 되기 전에는 빠져 나가자.
self.index += 0.5
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.size)
def move(self):
if self.image == None: return
speed = 0
if self.action == 'Idle':
speed = 0
elif self.action == 'Walk':
speed = self.walkSpeed
elif self.action == 'Jump':
speed = self.jumpSpeed
elif self.action == 'Run':
speed = self.runSpeed
x = 0
y = 0
if self.dir == 'W': # 서쪽 방향이면
x = -speed
elif self.dir == 'E': # 동쪽이면
x = speed
elif self.dir == 'N': # 북쪽이면
y = -speed
elif self.dir == 'S': # 서쪽이면
y = speed
if self.rect.left + x < 0: return
if self.rect.top + y < 0: return
if self.rect.right + x > SCREEN_WIDTH: return
if self.rect.bottom + y > SCREEN_HEIGH: return
self.rect.move_ip(x, y)
def get_walkSpeed(self): return self._walkSpeed
def set_walkSpeed(self, speed):
if speed < 0: return # 음수 속도는 받을 수 없다.
self._walkSpeed = speed
def get_jumpSpeed(self): return self._jumpSpeed
def set_jumpSpeed(self, speed):
if speed < 0 : return #음수 속도는 받을 수 없다.
self._jumpSpeed = speed
def get_runSpeed(self): return self._runSpeed
def set_runSpeed(self, speed):
if speed < 0: return # 음수 속도는 받을 수 없다.
self._runSpeed = speed
walkSpeed = property(get_walkSpeed, set_walkSpeed)
jumpSpeed = property(get_jumpSpeed, set_jumpSpeed)
runSpeed = property(get_runSpeed, set_runSpeed)
Person 객체생성
Person객체는 Animal 객체를 상속 받아 놓은 후 이미지 디렉토리 중 사람에 해당하는 이미지 디렉토리의 이미지를 적재해 놓는다.
class Person(Animal):
def __init__(self,location=(0, 0),imgsize=(100,100),walkSpeed=1,jumpSpeed = 2,runSpeed = 3):
super().__init__(location,imgsize,walkSpeed,jumpSpeed,runSpeed) #상속정보를 설정해 주자.
self.action = 'Idle' # 최초 생성 될 때 상태
self.flipped = True
self.list_surfaces = self.ordered_list_of_surfaces()
self.image = self.list_surfaces[0]
self.image = pygame.transform.scale(self.image, self.size)
self.rect = self.image.get_rect()
self.rect.center = location
def ordered_list_of_surfaces(self):
if self.dir == 'W' : self.flipped=True
elif self.dir == 'E' : self.flipped = False
self.los =[]
if self.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")
]
print('image Loading')
return self.los
def get_dir(self): return self._dir
def set_dir(self,dir):
self._dir = dir
if self._predir != self.dir:
if (self._predir=='W' or self._predir=='E') and (self.dir=='W' or self.dir=='E'): #동,서로 변경이 되는 경우에 이미지를 다시 로딩하자.
self._predir = self.dir
self.list_surfaces = self.ordered_list_of_surfaces()
dir = property(get_dir, set_dir)
ordered_list_of_surfaces 에서 동쪽과 서쪽에 한해서 이미지를 반전으로 로딩 할 것인지 아닌지 판단하고 또한 방향을 바꿀때(dir 변경시) predir 에 동/서 만 기록한 다음 동/서의 방향이 바뀌는 경우에만 이미지를 다시 로딩하도록 처리하였다.
Person 이미지는 자신의 png 디렉토리에 있는 이미지를 로딩 하였다.
Cat 객체생성
Cat객체는 Person 객체와 동일한데 이미지 로딩 부분만 서로 다른 디렉토리에서 읽어 오도록 처리 했다.
class Cat(Animal):
def __init__(self,location=(0, 0),imgsize=(50,50),walkSpeed=3,jumpSpeed = 5,runSpeed = 7):
super().__init__(location,imgsize,walkSpeed,jumpSpeed,runSpeed) #상속정보를 설정해 주자.
self.action = 'Idle' # 최초 생성 될 때 상태
self.flipped = True
self.list_surfaces = self.ordered_list_of_surfaces()
self.image = self.list_surfaces[0]
self.image = pygame.transform.scale(self.image, self.size)
self.rect = self.image.get_rect()
self.rect.topleft = location
def ordered_list_of_surfaces(self):
if self.dir == 'W':self.flipped=True
elif self.dir == 'E': self.flipped = False
self.los =[]
if self.flipped :
self.los = [
pygame.transform.flip(pygame.image.load(img), True, False)
for img in glob.glob(f"cat\\{self.action}*.png")
]
else :
self.los = [
pygame.image.load(img)
for img in glob.glob(f"cat\\{self.action}*.png")
]
print('image Loading')
return self.los
def get_dir(self): return self._dir
def set_dir(self,dir):
self._dir = dir
if self._predir != self.dir:
if (self._predir=='W' or self._predir=='E') and (self.dir=='W' or self.dir=='E'): #동,서로 변경이 되는 경우에 이미지를 다시 로딩하자.
self._predir = self.dir
self.list_surfaces = self.ordered_list_of_surfaces()
dir = property(get_dir, set_dir)
이렇게 생성한 두개의 객체를 이용하여 사람과 동물을 화면에 띄워 보자.
Pygame 에서 두 객체의 인스턴스를 화면에 띄우기
SCREEN_WIDTH = 1024
SCREEN_HEIGHT = 768
#파이게임 초기화하기
pygame.init()
# 게임 화면 초기화 하기
screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
#제목 표시줄 설정하기
pygame.display.set_caption("pygame test")
#프레임 매니저 초기화하기
clock = pygame.time.Clock()
#프레임 레이트 설정하기
clock.tick(60)
#배경색상 설정하기
screen.fill((255,255,255))
personX = SCREEN_WIDTH // 2 # 스크린 중앙 위치
personY = SCREEN_HEIGHT // 2
person = Person( (personX,personY) )
cat = Cat((personX - 100,personY))
while True:
screen.fill((255, 255, 255))
person.update()
cat.update()
screen.blit(person.image, person.rect)
screen.blit(cat.image, cat.rect)
#이벤트 확인하기
for event in pygame.event.get():
#닫기 버튼을 눌렀는지
if event.type == pygame.QUIT:
#게임 끝내기
pygame.quit()
sys.exit()
#화면 업데이트하기
pygame.display.update()
#프레임 레이트 설정하기
clock.tick(60)
마지막으로 두 객체의 인스턴스를 pygame에 띄워 보았다.
객체가 생성하는 위치는 사람은 스크린의 중앙, 고양이는 사람의 왼쪽에서 100 떨어진 위치에 생성을 했다.
실행결과
'강의자료 > 텍스트기반SW' 카테고리의 다른 글
[파이썬] 클래스별 파일로 관리하기 (36) | 2023.10.13 |
---|---|
[파이썬] 파이게임 객체 임의의 위치로 이동하기 (10) | 2023.08.17 |
[파이썬] 파이게임 객체 생성 (13) | 2023.07.27 |
[파이썬] 파이게임 사용법 (18) | 2023.07.21 |
파이썬으로 JSON 파일 다루기 및 실행파일 만들기 (16) | 2023.07.13 |