스푸79 기록 보관소

타자 연습 게임, 타이핑 몬스터(3) - 애니메이션 본문

게임공작소

타자 연습 게임, 타이핑 몬스터(3) - 애니메이션

스푸79 2025. 1. 12. 16:10

 

지난 포스트에서 개발된 프로토타입을 기반으로 이미지와 애니메이션 효과를 넣어 작업을 해봤습니다.

 

기획 단계에서 작업한 이미지는 계속 마음에 안 들어서 작업 과정에서 손을 보게 되네요.

가장 기본적인 몬스터인 좀비의 애니메이션 작업을 진행했습니다.

걷는 동작은 총 7 장의 그림으로 그렸습니다.

 

초당 60프레임 게임으로 가정하면 60 ÷ 7 = 8.57...정도가 나옵니다.

즉, 이미지 하나가 9~10프레임정도 유지하고 다음 프레임으로 넘어가도록 처리하면

1초에 7개의 동작을 모두 처리할 수 있습니다.

 

죽는 동작은 총 8 장의 그림으로 그렸습니다.

머리 위에 글자와 동일한 글자가 타이핑이 되면 걷는 동작을 멈추고

그 자리에서 고개를 숙이고 쓰러지는 애니메이션을 넣었습니다.

걷는 동작과 짝이 맞지 않아 걷는 동작을 하나 더 추가할까 고민 중입니다.ㅎ

 

 

완성을 다 하고 나니 새배하는 것 같기도 하네요. 의도는 무릎을 꿇는 거였는데

도트로 그림 그리는게 쉽지가 않네요.

 

위의 이미지는 한개의 png 파일에 모든 동작을 다 담았습니다.

각각 이미지의 크기는 너비 51px, 높이 84px, 이미지 간 간격은 1px 입니다.

아래 render_sheet라는 코드를 하나 만들어서

파일명을 입력받으면 png의 이미지를 사이즈별로 짤라서 담을 수 있도록 처리했습니다.

    def render_sheet(self, sheet_name, width, height, count, spacing):
        sprite_sheet = pygame.image.load(cfg.GAME_IMG_DIR + sheet_name)
        frame_width = width
        frame_height = height
        frame_count = count
        frame_spacing = spacing
        images = []
        for i in range(frame_count):
            x = i * (frame_width + frame_spacing)
            frame = pygame.Surface((frame_width, frame_height), pygame.SRCALPHA)
            frame.blit(sprite_sheet, (0, 0), (x, 0, frame_width, frame_height))
            images.append(frame)
        return images

 

몬스터의 상태는 걷는 동작(WALK)와 죽는 동작(DIE)를 구분했습니다.

매 프레임 갱신 과정에서 상태가 변경되면 애니메이션 효과를 변경하도록 아래 코드처럼 처리했습니다.

    def update(self):
        if self.monster_status == cfg.WALK:
            self.pos += self.speed
            self.rect.topleft = self.pos
            if self.rect.top > cfg.SCREEN_HEIGHT:
                self.kill()
            self.animation("LOOP")
               
        elif self.monster_status == cfg.DIE:
            if self.animation_index == len(self.images) - 1:
                self.animation("ONETIME")
                self.opacity -= 1
                self.image.set_alpha(self.opacity)
                if self.opacity < 0:
                    self.kill()
            else:
                self.animation("LOOP")

 

아래 코드는 애니메이션 처리하는 부분입니다.

반복(LOOP)와 한번동작(ONETIME)으로 구분했는데요.

죽는 경우 마지막 무릎을 꿇는 상태에서 반복되지 않고 투명도를 조절해서 화면에서 사라지도록 처리했습니다.

    def animation(self, type):            
        self.animation_frame_count += self.animation_speed
        if type == "LOOP":
            if self.animation_frame_count >= self.animation_interval:
                self.animation_frame_count = 0
                self.animation_index = (self.animation_index + 1) % len(self.images)
                self.image = self.images[self.animation_index]
        elif type == "ONETIME":
            self.image = self.images[self.animation_index]

 

 

그리고 폰트는 HBIOS-SYS라는 옛날 16bit 컴퓨터 운영체제였던 DOS의 폰트를 가져와봤습니다.

도트 감성에 어울리는 폰트를 사용했습니다.

https://github.com/quiple/hbios-sys

 

GitHub - quiple/hbios-sys: 마이크로소프트 한글 MS-DOS 시스템 한글 폰트

마이크로소프트 한글 MS-DOS 시스템 한글 폰트. Contribute to quiple/hbios-sys development by creating an account on GitHub.

github.com

 

예제 코드를 첨부합니다.

실행 방법은 main.py가 있는 폴더에서 python main.py로 실행하면 됩니다.

02. zombie.zip
0.88MB