Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

개발이 취미인 개발자

플랫포머게임 알고리즘 - 캐릭터의 이동 본문

플랫포머게임 알고리즘(pygame)

플랫포머게임 알고리즘 - 캐릭터의 이동

도그풋79 2023. 8. 14. 17:18

먼저, 메인 캐릭터(주인공)의 움직임을 처리하는 것부터 시작해보자.

메인 캐릭터를 좌우로 움직이게 하는 부분은 이전의 슛팅 게임에서 처리한 로직과 동일하다.

좌우 키를 입력할 때마다 메인 캐릭터의 x축의 값을 빼거나 더하여 이미지를 위치를 바꿔주면 된다.

하지만 슈팅게임과 다른 부분이 하나 있는데 그것이 바로 애니메이션 효과이다.

 

슈팅게임의 경우에는 메인 캐릭터가 비행기이기 때문에 한장의 이미지로만 화면에 표시하고

키 입력에 따라 좌우 위치만 변경해도 큰 무리가 없다.

하지만 플랫포머 게임의 경우 메인 캐릭터가 사물이 아닌 인간이나 생물인 경우가 많다.

따라서 움직임에 조금 더 디테일한 효과를 주어야 움직임이 자연스러워 보인다.

 위와 같이 오른쪽 방향으로 움직이는 이미지 4장을 간단하게 만들어 보았다. 한번 걸을 때마다 총 4장이 이미지가 화면에 차례대로 출력을 시키면 된다. 걷는 모습에 조금 더 정교한 움직임을 처리하고 싶다면 이미지의 장수를 늘리면 된다.

 

 

여기서 조금 더 생각해야할 부분이 있다. 바로 프레임이다.

초당 60프레임의 게임을 개발한다고 가정해 보자. (보통 60프레임을 많이 설정한다.)

나는 우측으로 걷는 이미지를 4장으로 처리 했으니깐 4프레임을 사용하게 된다.

1장당 0.016초가 화면에 표시되는데 4장을 연속으로 보여주면 0.06초만에 위의 4장의 이미지가 출력되는 것이다.

거의 움직임을 인지할 수 없을 만큼 빠르게 흘러가 버린다.

이것을 방지하기 위해 이미지 한장이 출력되는 시간을 살짝 조정하는 것이 필요하다.

class Player(pygame.sprite.Sprite):
    def __init__(self, x, y, speed):
        pygame.sprite.Sprite.__init__(self)
        self.l_images = [pygame.image.load(img_dir + "/img/player_l0.png"),
                         pygame.image.load(img_dir + "/img/player_l1.png"),
                         pygame.image.load(img_dir + "/img/player_l2.png"),
                         pygame.image.load(img_dir + "/img/player_l3.png")]
        self.r_images = [pygame.image.load(img_dir + "/img/player_r0.png"),
                         pygame.image.load(img_dir + "/img/player_r1.png"),
                         pygame.image.load(img_dir + "/img/player_r2.png"),
                         pygame.image.load(img_dir + "/img/player_r3.png")]
        self.left_direction = True
        self.image = self.l_images[0]
        self.rect = self.image.get_rect()
        self.rect.center = [x, y]
        self.speed = 1      
        self.move_left = False
        self.move_right = False
        self.animation_frame = 0
        self.animation_interval = 4
        self.left_images_idx = 0
        self.right_images_idx = 0

Player class 를 구현할 때 animation_frame 과 animation_interval을 선언한다.

여기서는 interval을 4정도로 설정했는데 본인이 구현할 캐릭터의 스프라이트의 이미지가 많거나 캐릭터의 움직임을 유연하게 만들고 싶다면 그에 맞춰서 speed와 interval 값을 변경하면 된다.

iterval을 4로 설정했다면 장당 0.06초의 간격이 생기게 된다. 캐릭터의 움직임이 자연스러워 보일때까지 해당 수치를 계속 바꿔보자.

 

 그리고 실제 걷는 동작과 캐릭터의 위치 이동을 완벽하게 일치하고 싶다면 특정 스프라이트의 위치에서만 이동하도록 처리하는 해야한다. 위의 스프라이트로 예를 들면 0번째 스프라이트는 x축을 이동시키지 않고 첫번째부터 이동시키는 것이다. 0번째 스프라이트는 두 발이 땅에 닿은 상태임으로 움직임을 처리하는 것이 맞지 않다. 실제로 정교한 플랫포머 게임을 만들 계획이라면 동작에 따른 위치 이동을 세분화하는 것도 필요하다.

    def update(self):
        key = pygame.key.get_pressed()
        self.move_left = False
        self.move_right = False

        if key[pygame.K_LEFT] and self.rect.left > 0:            
            self.right_images_idx = 0
            self.move_left = True            
            self.animation_frame += 1
            if self.left_images_idx > 0:
                self.rect.x -= self.speed

            if self.animation_interval <= self.animation_frame:
                self.left_images_idx += 1
                self.animation_frame = 0

            if self.left_images_idx > 3:
                self.left_images_idx = 1

 위의 코드를 보면 두 발이 착지 되어 있는 0번 스프라이트의 경우에는 x 좌표의 값의 변화를 주지 않도록 처리했다.

그리고 걷는 동작이 연속적으로 처리되는 경우에는 0번 스프라이트를 표시하지 않고 1번으로 바로 건너 뛰도록 처리했다.

 

 위의 코드에 조금 더 살을 보태면 아래와 같이 키 입력이 없는 상태인 경우에도 주인공이 움직임을 넣을 수가 있다.

보통 이런 메인 캐릭터의 상태를 idle(휴면) 상태라고 하는데 idle 상태값을 추가한 캐릭터 움직임과 관련된 소스코드를 아래 첨부한다. 예제를 실행하는 방법은 슈팅게임과 동일하게 main.py를 실행하면 된다.

 

02_main_character.zip
0.02MB