Sprite(스프라이트) Frame 시간에 관계없이 일정하게 Image 보여주기 > Pygame - python GUI module

본문 바로가기

사이트 내 전체검색

이전으로Pygame - python GUI module

Sprite(스프라이트) Frame 시간에 관계없이 일정하게 Image 보여주기

페이지정보

글쓴이 관리자 조회 34,570 조회 날짜 20-04-05 17:42 / U:20-04-05 19:24
댓글 0댓글

SNS 공유

  • 트위터로 보내기
  • 페이스북으로 보내기
  • 구글플러스로 보내기
  • 카카오톡으로 보내기

내용

Sprite(스프라이트)

Frame 시간에 관계없이 일정하게 Image 보여주기

 

 

pygame화면을 나타내는 주기를 FPS(frame per second)라고 하고 1초에 변경되는 화면의 갯수를 의미한다.

만약 어떤 동작(가만히 서있는 동작)에서 사용하는 이미지가 10개인데, FPS가 60이라면, 이 동작은 실제로 1초에 6번을 반복 실행하게 된다. 

 

앞선 강좌에서 실행해 본 결과, 가만히 서서 숨을 고르는 공룡이 자연스럽지 못하고 숨을 헐떡헐떡이는 것처럼 보였다.

 

예) FPS = 60 일때

2921044682_1586126066.8008.gif

 

 

이것을 좀 더 자연스럽게 숨쉬고 있는 것 처럼 보이려면, FPS를 10으로 변경하면 된다.

 

예) FPS = 10 일때

2921044682_1586126072.642.gif

 

 

하지만 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자리까지 반올림
        self.animation_time = round(100 / len(self.images * 100), 2)

        # mt와 결합하여 animation_time을 계산할 시간 초기화
        self.current_time = 0

 

이와같이 이미지 수에 맞춰 움직임을 제어하면, 한 동작은 모두 같은 시간안에 끝나지만, 이미지가 많을 수록 좀 더 부드러운 동작으로 이어지게 된다.

이것은 1초당 20 Frame인 애니메이션과 60 Frame의 애니메이션에서 캐릭터가 움직일때 부드러움의 차이와 같다.

 

 

5. update() 수정

 

class AnimatedSprite(pygame.sprite.Sprite):

    ......

    ......

   

    def update(self, mt):
        # update를 통해 캐릭터의 이미지가 계속 반복해서 나타나도록 한다.

        # loop 시간 더하기
        self.current_time += mt


        # loop time 경과가 animation_time을 넘어서면 새로운 이미지 출력 
        if self.current_time >= self.animation_time:
            self.current_time = 0
            self.image = self.images[self.index]


            self.index += 1
            if self.index >= len(self.images):
                self.index = 0

 

 

 

6. 전체 코드

 

import pygame


# 스크린 전체 크기 지정

SCREEN_WIDTH = 1020
SCREEN_HEIGHT = 480

 

# pygame 초기화

pygame.init()

 

# 스크린 객체 저장
SCREEN = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("pygame Sprite")

 

# FPS를 위한 Clock 생성
clock = pygame.time.Clock()

FPS = 60

 

BACKGROUND_COLOR = pygame.Color('white')

 

class AnimatedSprite(pygame.sprite.Sprite):

 

    def __init__(self, position):

        super(AnimatedSprite, self).__init__()

 

        # 이미지를 Rect안에 넣기 위해 Rect의 크기 지정
        # 이미지의 크기와 같게 하거나, 크기를 다르게 한다면 pygame.transform.scale을 사용하여 rect 안에
        # 이미지를 맞추도록 한다.

        size = (680, 472)

 

        # 여러장의 이미지를 리스트로 저장한다. 이미지 경로는 자신들의 경로를 사용한다.
        images = []
        images.append(pygame.image.load('freedinosprite/png/Idle_01.png'))
        images.append(pygame.image.load('freedinosprite/png/Idle_02.png'))
        images.append(pygame.image.load('freedinosprite/png/Idle_03.png'))
        images.append(pygame.image.load('freedinosprite/png/Idle_04.png'))
        images.append(pygame.image.load('freedinosprite/png/Idle_05.png'))
        images.append(pygame.image.load('freedinosprite/png/Idle_06.png'))
        images.append(pygame.image.load('freedinosprite/png/Idle_07.png'))
        images.append(pygame.image.load('freedinosprite/png/Idle_08.png'))
        images.append(pygame.image.load('freedinosprite/png/Idle_09.png'))
        images.append(pygame.image.load('freedinosprite/png/Idle_10.png'))

 

        # rect 만들기
        self.rect = pygame.Rect(position, size)


        # Rect 크기와 Image 크기 맞추기. pygame.transform.scale
        self.images = [pygame.transform.scale(image, size) for image in images]

 

        # 캐릭터의 첫번째 이미지
        self.index = 0
        self.image = images[self.index]

 

        # 1초에 보여줄 1장의 이미지 시간을 계산, 소수점 3자리까지 반올림
        self.animation_time = round(100 / len(self.images * 100), 2)

        # mt와 결합하여 animation_time을 계산할 시간 초기화
        self.current_time = 0

 

 

    def update(self, mt):
        # update를 통해 캐릭터의 이미지가 계속 반복해서 나타나도록 한다.

        # loop 시간 더하기
        self.current_time += mt


        # loop time 경과가 animation_time을 넘어서면 새로운 이미지 출력 
        if self.current_time >= self.animation_time:
            self.current_time = 0
           
            self.index += 1
            if self.index >= len(self.images):
                self.index = 0

            self.image = self.images[self.index]

 

 

def main():

    # player 생성
    player = AnimatedSprite(position=(100, 8))
    # 생성된 player를 그룹에 넣기
    all_sprites = pygame.sprite.Group(player)  

 

    running = True
    while running:

 

        # 각 loop를 도는 시간. clock.tick()은 밀리초를 반환하므로
        # 1000을 나누어줘서 초단위로 변경한다.

        mt = clock.tick(60) / 1000


        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

       

        # all_sprites 그룹안에 든 모든 Sprite update
        all_sprites.update(mt)
        # 배경색
        SCREEN.fill(BACKGROUND_COLOR)
        # 모든 sprite 화면에 그려주기
        all_sprites.draw(SCREEN)
        pygame.display.update()

 

 

if __name__ == '__main__':
    main()

 

 

 

7. 실행 결과

 

FPS와 이미지의 숫자(가운데 이미지들을 주석처리)를 다르게 하여 실행하여 본다.

FPS에 관계없이 숨을 쉬는 동작은 일정하다. 다만 이미지의 수가 적어지면 동작과 동작사이에 연결되는 이미지가 줄어드므로, 동작이 자연스럽지 못하게 된다. 

 

1) FPS = 60, Image 10개

 

2921044682_1586131438.3084.gif

 

 

2) FPS = 100, Image 10개

 

2921044682_1586131442.8576.gif

 

 

3) FPS = 60, Image 2개

 

2921044682_1586131448.5637.gif

댓글목록

댓글이 없습니다

게시물 검색
총 22 건 , 1 페이지
올서베이넷
무료 온라인 설문 사이트
OVITII
웹 프레젠테이션 도구
Copyright © JBMPA.com All rights reserved.
사이트 언어 선택
PC 보기