Sprite(스프라이트) 앞 뒤로 움직이기 > Pygame - python GUI module

본문 바로가기

사이트 내 전체검색

이전으로Pygame - python GUI module

Sprite(스프라이트) 앞 뒤로 움직이기

페이지정보

글쓴이 관리자 조회 22,839 조회 날짜 20-04-05 18:19 / U:20-04-05 19:24
댓글 0댓글

SNS 공유

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

내용

Sprite(스프라이트) 앞 뒤로 움직이기

 

 

Sprite를 움직이게 하는 것은 앞서 했던 자동차 게임에서 자동차들이 움직이는 원리와 같다.

다만, 캐릭터들이 좌우로 움직이는 이미지가 달라져야 한다.

왼쪽과 오른쪽을 모두 표현하는 이미지들이 있다면 그것을 그대로 사용해도 되지만, 한쪽 방향만 바라보는 이미지만 있다면, 그 이미지의 방향을 좌우로 변경하여 사용할 수 있다.

 

Sprite가 방향을 바꾸어서 움직이는 것을 구현해본다.

 

 

 

1. 걸어가는 image들 추가

 

다운 받은 샘플 파일 안에는 Sprite를 위한 여러가지 이미지들이 있다. 이 중에 걸음걸이를 표현한 이미지들을 추가한다.

class AnimatedSprite(pygame.sprite.Sprite):

 

    def __init__(self, position):

       ......

       ......


        # 걷기 11 ~ 20
        images.append(pygame.image.load('freedinosprite/png/Walk_01.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_02.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_03.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_04.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_05.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_06.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_07.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_08.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_09.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_10.png'))

 

 

 

2. 좌우 모습을 보여줘야 하므로, 이미지 좌우로 변경하여 저장

 

걷기 이미지들은 오른쪽을 향한 이미지들이다. 이것들을 왼쪽으로 바라보게 하기 위해서는 세로를 기준으로 좌우를 뒤집어준다.

class AnimatedSprite(pygame.sprite.Sprite):

 

    def __init__(self, position):

       ......

       ......

 

        # 원본 캐릭터 이미지들
        self.images_right = images
        # 캐릭터 이미지가 오른쪽을 보고 있는데, 왼쪽으로 보도록 하기 위해서는
        # 이미지를 세로 기준으로 좌우로 뒤집이 준다. pygame.transform.flip 메서드 사용

        self.images_left = [pygame.transform.flip(image, True, False) for image in images]

 

 

 

3. 플레이어 방향과 속도 설정

 

플레이어는 가만히 서있기와 걷기 두 가지 상태를 가지며, 서있기와 걷기는 왼쪽 오른쪽 방향이 필요하다.

또한 걷을 때 움직이는 거리, 즉 속도를 지정해준다.

class AnimatedSprite(pygame.sprite.Sprite):

 

    def __init__(self, position):

       ......

       ......

 

        # 캐릭터의 현재 상태
        # 0 - idle 상태, 1 - 걷고 있는 상태

        self.state = 0
        # 방향
        self.direction = 'right'
        # 속도
        self.velocity_x = 0

 

 

 

4. update() 수정

 

상태와 방향에 따라 이미지들을 변경시켜주며 움직임을 재생한다.

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

       

        # 현재 상태에 따라 반복해줄 이미지의 index 설정과 속도
        if self.state == 0:
            count = 10
            start_Index = 0
            self.velocity_x = 0
        elif self.state == 1:
            count = 10
            start_Index = 10
            self.velocity_x = 4

 

        # 방향이 오른쪽이면, 오른쪽 이미지 선택
        if self.direction == 'right':
            self.images = self.images_right
        # 방향이 왼쪽이면 왼쪽 이미지 선택, 진행방향 x축으로 -
        elif self.direction == 'left':
            self.images = self.images_left
            self.velocity_x = abs(self.velocity_x) * -1

 

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


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


            # 상태에 따라 이미지 index 범위를 다르게 설정한다.

            # idle 상태는 0 ~ 9, 걷기 상태는 10 ~ 19
            self.index = (self.index % count) + start_Index

           

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


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

           

        # 좌우 위치값 변경, 이동
        self.rect.x += self.velocity_x

 

 

 

5. key event 수정

 

키보크 화살표 키 이벤트에 따라 설정값들을 변경해준다.

def main():

    ......

    ......

 

    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()

            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    player.direction = "right"
                    player.state = 1
                elif event.key == pygame.K_LEFT:
                    player.direction = "left"
                    player.state = 1
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT:
                    player.velocity_x = 0
                    player.state = 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 = []

        # 서있는 상태 0 ~ 10
        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'))


        # 걷기 11 ~ 20
        images.append(pygame.image.load('freedinosprite/png/Walk_01.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_02.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_03.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_04.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_05.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_06.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_07.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_08.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_09.png'))
        images.append(pygame.image.load('freedinosprite/png/Walk_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.images_right = images
        # 캐릭터 이미지가 오른쪽을 보고 있는데, 왼쪽으로 보도록 하기 위해서는
        # 이미지를 세로 기준으로 좌우로 뒤집이 준다. pygame.transform.flip 메서드 사용

        self.images_left = [pygame.transform.flip(image, True, False) for image in images]

       

        # 캐릭터의 현재 상태
        # 0 - idle 상태, 1 - 걷고 있는 상태

        self.state = 0
        # 방향
        self.direction = 'right'
        # 속도
        self.velocity_x = 0

 

        # 캐릭터의 첫번째 이미지
        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를 통해 캐릭터의 이미지가 계속 반복해서 나타나도록 한다.

       

        # 현재 상태에 따라 반복해줄 이미지의 index 설정과 속도
        if self.state == 0:
            count = 10
            start_Index = 0
            self.velocity_x = 0
        elif self.state == 1:
            count = 10
            start_Index = 10
            self.velocity_x = 4

 

        # 방향이 오른쪽이면, 오른쪽 이미지 선택
        if self.direction == 'right':
            self.images = self.images_right
        # 방향이 왼쪽이면 왼쪽 이미지 선택, 진행방향 x축으로 -
        elif self.direction == 'left':
            self.images = self.images_left
            self.velocity_x = abs(self.velocity_x) * -1

 

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


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


            # 상태에 따라 이미지 index 범위를 다르게 설정한다.

            # idle 상태는 0 ~ 9, 걷기 상태는 10 ~ 19
            self.index = (self.index % count) + start_Index

           

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


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

           

        # 좌우 위치값 변경, 이동
        self.rect.x += self.velocity_x

 

 

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()

            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    player.direction = "right"
                    player.state = 1
                elif event.key == pygame.K_LEFT:
                    player.direction = "left"
                    player.state = 1
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT:
                    player.velocity_x = 0
                    player.state = 0

       

        # 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. 실행 결과

 

좌우로 방향 전환할 때, 위치가 변하는 것은 이미지 자체에 앞쪽 흰 공백 때문이다.

좀 더 정밀하게 좌우 방향 전환을 하려면, 이미지의 공백 부분을 제거하고 캐릭터의 중심을 이미지 전체에 똑같이 유지시켜야 한다.

 

2921044682_1586136104.2293.gif

 

댓글목록

댓글이 없습니다

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