2023.08.10 - [강의자료/텍스트기반SW] - [파이썬] 파이게임 객체 상속
이전 시간에 만든 프로젝트에서 고양이는 임의의 위치로 계속 이동시키고 사람은 키보드로 이동하도록 변경을 해 봅니다.
고양이 임의의 위치로 이동
고양이를 임의의 위치로 계속 이동시키기 위해서는 일정시간마다 동서남북의 방향을 변경해 주고 계속 조금씩 이동하도록 하면 됩니다.
따라서 다음과 같이 Cat 클래스에 dirChange() 메서드를 생성하고 몇프레임마다 바꿀지 설정하는 changeFrame 변수를 init 에서 생성해 줍니다. 또한 자신이 몇프레임이나 호출 되었는지를 확인 할 수 있도록 frameCount 변수를 생성합니다.
전역 변수로 방향을 저장할 수 있는 dirList를 생성하여 W,E,N,S를 저장합니다.
dirList = ['W',"E","N","S"]
class Cat(Animal):
def __init__(self,location=(0, 0),imgsize=(50,50),walkSpeed=3,jumpSpeed = 5,runSpeed = 7,changeFrame=60):
...
self.changeFrame = changeFrame
self.frameCount = 0
def dirChange(self):
self.frameCount += 1 #호출되는 횟수 카운트
if self.frameCount > self.changeFrame :
self.dir = random.choice(dirList)
self.frameCount=0
....
다음으로 다음과 같이 고양이 객체를 각 프레임마다 이동 시키면서 dirChange를 호출하면 임의의 장소로 이동하는 것을 확인할 수 있습니다.
while True:
...
cat.dirChange()
cat.move()
cat.update()
screen.blit(person.image, person.rect)
screen.blit(cat.image, cat.rect)
...
실행화면
실행해 보면 처음에 Idle 상태에서 action 상태로 변경 될때 이미지가 로딩 되지 않는 것을 확인 할 수 있었다.
다음과 같이 Cat과 Person 에 action 이 변경 될 때 이미지를 다시 로딩 하도록 다음과 같이 변경하자.
- Animal 의 클래스에서 action 변수를 _action 으로 변경 및 _preaction 추가
class Animal(pygame.sprite.Sprite):
def __init__(self, location=(0, 0), imgsize=(100, 100), walkSpeed=1, jumpSpeed=2, runSpeed=5):
self._action = 'Idle'
self._preaction =''
...
- Person과 Cat 에서 다음과 같이 메서드 추가
class Person(Animal):
...
def get_action(self): return self._action
def set_action(self,action):
self._action = action
if self._preaction != self.action:
if (self._preaction!=self.action): #action이 서로 달라지면 새로 로딩하자.
self._preaction = self.action
self.list_surfaces = self.ordered_list_of_surfaces()
#print("action change")
...
action = property(get_action, set_action)
class Cat(Animal):
...
def get_action(self): return self._action
def set_action(self,action):
self._action = action
if self._preaction != self.action:
if (self._preaction!=self.action): #action이 서로 달라지면 새로 로딩하자.
self._preaction = self.action
self.list_surfaces = self.ordered_list_of_surfaces()
#print("action change")
...
action = property(get_action, set_action)
이렇게 하면 action이 변경 되면 해당 action에 맞춰서 이미지가 재 로딩 된다.
사람객체 키보드 이동
이번에는 사람 객체를 키보드로 이동하는 방법을 구현해 보자.
이 부분은 지난번( https://wondangcom.tistory.com/2604 )에 살펴 보았기 때문에 전체 코드 를 살펴 보는것으로 마친다.
현재 까지의 전체 코드
import random
import pygame,sys,glob
class Animal(pygame.sprite.Sprite):
def __init__(self, location=(0, 0), imgsize=(100, 100), walkSpeed=1, jumpSpeed=2, runSpeed=5):
self._preaction =''
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_HEIGHT: 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)
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_action(self): return self._action
def set_action(self,action):
self._action = action
if self._preaction != self.action:
if (self._preaction!=self.action): #action이 서로 달라지면 새로 로딩하자.
self._preaction = self.action
self.list_surfaces = self.ordered_list_of_surfaces()
#print("action change")
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()
def get_dir(self):
return self._dir
dir = property(get_dir, set_dir)
action = property(get_action, set_action)
class Cat(Animal):
def __init__(self,location=(0, 0),imgsize=(50,50),walkSpeed=3,jumpSpeed = 5,runSpeed = 7,changeFrame=30):
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
self.changeFrame = changeFrame
self.frameCount = 0
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 dirChange(self):
self.frameCount += 1 #호출되는 횟수 카운트
if self.frameCount > self.changeFrame :
self.dir = random.choice(dirList)
self.frameCount=0
def get_action(self): return self._action
def set_action(self,action):
self._action = action
if self._preaction != self.action:
if (self._preaction!=self.action): #action이 서로 달라지면 새로 로딩하자.
self._preaction = self.action
self.list_surfaces = self.ordered_list_of_surfaces()
#print("action change")
def get_dir(self): return self._dir
def set_dir(self,dir):
self._dir = dir
#print(self._predir,self.dir)
if self._predir != self.dir:
if (self._predir=='' or 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()
print("dir change")
dir = property(get_dir, set_dir)
action = property(get_action, set_action)
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))
dirList = ['W',"E","N","S"]
while True:
screen.fill((255, 255, 255))
person.update()
cat.action = "Walk"
cat.dirChange()
cat.move()
cat.update()
screen.blit(person.image, person.rect)
screen.blit(cat.image, cat.rect)
# 키보드 눌렀을때 True
keys = pygame.key.get_pressed()
# 왼쪽 화살표를 눌렀다면
if keys[pygame.K_LEFT]:
person.dir = "W"
person.action = "Walk"
person.move()
# 오른쪽 화살표를 눌렀다면
elif keys[pygame.K_RIGHT]:
person.dir = "E"
person.action = "Walk"
person.move()
# 위쪽 화살표를 눌렀다면
elif keys[pygame.K_UP]:
person.dir = "N"
person.action = "Walk"
person.move()
# 아래쪽 화살표를 눌렀다면
elif keys[pygame.K_DOWN]:
person.dir = "S"
person.action = "Walk"
person.move()
else:
person.action = "Idle"
#이벤트 확인하기
for event in pygame.event.get():
#닫기 버튼을 눌렀는지
if event.type == pygame.QUIT:
#게임 끝내기
pygame.quit()
sys.exit()
#화면 업데이트하기
pygame.display.update()
#프레임 레이트 설정하기
clock.tick(60)
실행 화면
다음 시간에는 고양이를 여러마리를 임의의 위치에서 생성하여 임의의 위치로 이동하는 것을 만들어 보겠습니다.
'강의자료 > 텍스트기반SW' 카테고리의 다른 글
[파이썬] 파이게임 고양이/강아지 객체 여러마리 생성하기 (36) | 2023.10.20 |
---|---|
[파이썬] 클래스별 파일로 관리하기 (36) | 2023.10.13 |
[파이썬] 파이게임 객체 상속 (27) | 2023.08.10 |
[파이썬] 파이게임 객체 생성 (13) | 2023.07.27 |
[파이썬] 파이게임 사용법 (18) | 2023.07.21 |