Sprite(스프라이트) Frame 시간에 관계없이 일정하게 Image 보여주기
페이지정보
내용
Sprite(스프라이트)
Frame 시간에 관계없이 일정하게 Image 보여주기
pygame화면을 나타내는 주기를 FPS(frame per second)라고 하고 1초에 변경되는 화면의 갯수를 의미한다.
만약 어떤 동작(가만히 서있는 동작)에서 사용하는 이미지가 10개인데, FPS가 60이라면, 이 동작은 실제로 1초에 6번을 반복 실행하게 된다.
앞선 강좌에서 실행해 본 결과, 가만히 서서 숨을 고르는 공룡이 자연스럽지 못하고 숨을 헐떡헐떡이는 것처럼 보였다.
예) FPS = 60 일때
이것을 좀 더 자연스럽게 숨쉬고 있는 것 처럼 보이려면, FPS를 10으로 변경하면 된다.
예) FPS = 10 일때
하지만 FPS를 변경하면 게임 전체의 속도를 변화시키는 것이기 때문에 다른 캐릭터나 배경의 움직임까지 같이 영향을 받게 된다.
따라서 이럴 경우는 하나의 Sprite내의 이미지수를 계산하여 그에 맞게 반복하도록 조정해주도록 한다.
본 강좌에서 사용되는 소스코드는 이전 강좌의 소스에서 이어진다.
https://www.jbmpa.com/pygame/20
1. clock.tick를 이용하여 한번 loop를 도는 시간을 얻는다.
clock.tick()은 한번 loop를 도는 시간을 밀리초로 반환한다.
만약 FPS가 60이라면 1000 / 60 = 1.6666666... 을 반환한다.
따라서 아래와 같은 코드를 사용하여 밀리초를 초로 변경하면,
FPS = 60일때, mt = 0.017 , FPS = 10일때 mt = 0.100 을 반환한다.
mt = clock.tick(60) / 1000 |
2. 한번 loop도는 시간을 update() 메서드에 전달
all_sprites.update(mt) |
3. Sprite 클래스의 update() 메서드에서 mt 값 받음
class AnimatedSprite(pygame.sprite.Sprite): ...... ...... def update(self, mt): ...... ...... |
4. 초당 보여줄 이미지의 숫자를 계산
10장의 이미지를 1초안에 보여주려고 한다면 아래와 같이 계산을 하면 된다.
( 100 / 이미지 수) / 100 = (100 / 이미지 수 * 100) = 100 / 10 * 100 = 0.1 => 0.1초에 이미지 한장씩 보여준다.
만약 3장의 그림이라면 ( 100 / 3 * 100) = 0.33 이 된다. => 0.33초에 이미지 한장씩 보여준다.
class AnimatedSprite(pygame.sprite.Sprite):
def __init__(self, position): ...... ...... # 1초에 보여줄 1장의 이미지 시간을 계산, 소수점 3자리까지 반올림 |
이와같이 이미지 수에 맞춰 움직임을 제어하면, 한 동작은 모두 같은 시간안에 끝나지만, 이미지가 많을 수록 좀 더 부드러운 동작으로 이어지게 된다.
이것은 1초당 20 Frame인 애니메이션과 60 Frame의 애니메이션에서 캐릭터가 움직일때 부드러움의 차이와 같다.
5. update() 수정
class AnimatedSprite(pygame.sprite.Sprite): ...... ......
def update(self, mt): # loop 시간 더하기
|
6. 전체 코드
import pygame
SCREEN_WIDTH = 1020
# pygame 초기화 pygame.init()
# 스크린 객체 저장
# FPS를 위한 Clock 생성 FPS = 60
BACKGROUND_COLOR = pygame.Color('white')
class AnimatedSprite(pygame.sprite.Sprite):
def __init__(self, position): super(AnimatedSprite, self).__init__()
# 이미지를 Rect안에 넣기 위해 Rect의 크기 지정
# 여러장의 이미지를 리스트로 저장한다. 이미지 경로는 자신들의 경로를 사용한다.
# rect 만들기
# 캐릭터의 첫번째 이미지
# 1초에 보여줄 1장의 이미지 시간을 계산, 소수점 3자리까지 반올림
def update(self, mt): # loop 시간 더하기
self.image = self.images[self.index]
def main(): # player 생성
running = True
# 각 loop를 도는 시간. clock.tick()은 밀리초를 반환하므로 mt = clock.tick(60) / 1000
# all_sprites 그룹안에 든 모든 Sprite update
if __name__ == '__main__': |
7. 실행 결과
FPS와 이미지의 숫자(가운데 이미지들을 주석처리)를 다르게 하여 실행하여 본다.
FPS에 관계없이 숨을 쉬는 동작은 일정하다. 다만 이미지의 수가 적어지면 동작과 동작사이에 연결되는 이미지가 줄어드므로, 동작이 자연스럽지 못하게 된다.
1) FPS = 60, Image 10개
2) FPS = 100, Image 10개
3) FPS = 60, Image 2개