[PYGAME] Pirate Mario - 7

문승환·2022년 9월 15일
0

[PYGAME]

목록 보기
8/8

프로젝트 개요

  • pygame을 사용하여 Pirate Mario제작
  • Youtube Clear Code의 Platformer in Pygame을 따라하며 진행
  • 주요 과제: 체력바와 코인 점수를 화면에 보여주고 적과 충돌시 발생하는 이벤트를 구현

프로젝트 내용

  • 플레이어가 적의 위로 떨어지면 적을 처치하고 플레이어는 처치와 동시에 자동으로 점프하도록 설정
  • 플레이어가 좌우 측면에서 적과 충돌하면 데미지를 받고 잠시동안 반투명 상태가 되면서 데미지를 받지 않고 만약 체력이 0이 되면 월드맵으로 이동
  • 실버코인은 1점 골드코인은 5점으로 설정
  • 체력바와 코인점수는 화면 좌측 상단에 출력

KEEP

  • 없음

PROBLEM

  • 플레이어가 일부 지형을 갈 수 없을 정도로 레벨이 잘못 디자인되었고 구조물과 적의 배치가 매우 난잡
  • 데미지를 받고 나서 무적시간이 끝나지 않고 지속 (player.py에서 문제가 발생했을 것으로 예상)
import pygame
from support import import_folder
from math import sin

class Player(pygame.sprite.Sprite):
    def __init__(self, pos, surface, create_jump_particles, change_health):
        super().__init__()
        self.import_character_assets()
        self.frame_index = 0
        self.animation_speed = 0.15
        self.image = self.animations['idle'][self.frame_index]
        self.rect = self.image.get_rect(topleft = pos)

        self.import_dust_run_particles()
        self.dust_frame_index = 0
        self.dust_animation_speed = 0.15
        self.display_surface = surface
        self.create_jump_particles = create_jump_particles

        self.direction = pygame.math.Vector2(0, 0)      # a 2-dimensional vector
        self.player_speed = 8
        self.gravity = 0.8
        self.jump_speed = -16

        # default player status
        self.status = 'idle'
        self.facing_right = True
        self.on_ground = False
        self.on_ceiling = False
        self.on_left = False
        self.on_right = False

        # health management
        self.change_health = change_health
        self.invincible = False
        self.invincibility_duration = 450
        self.hurt_time = 0

    def import_character_assets(self):

        # for different animations, different images
        character_path = '../graphics/character/'
        self.animations = {'idle': [], 'run': [], 'jump': [], 'fall': []}

        for animation in self.animations.keys():
            full_path = character_path + animation
            self.animations[animation] = import_folder(full_path)

    def import_dust_run_particles(self):
        self.dust_run_particles = import_folder('../graphics/character/dust_particles/run')

    def animate(self):
        animation = self.animations[self.status]

        # loop over frame index
        self.frame_index += self.animation_speed
        if self.frame_index >= len(animation):
            self.frame_index = 0

        # if player moves to the right, player looks right
        # if player moves to the left, player looks left
        image = animation[int(self.frame_index)]
        if self.facing_right:
            self.image = image
        else:
            flipped_image = pygame.transform.flip(image, True, False)
            self.image = flipped_image

        if self.invincible:
            alpha = self.wave_value()
            self.image.set_alpha(alpha)
        else:
            self.image.set_alpha(255)

        # fix the position of the player by setting the rect of each case
        if self.on_ground and self.on_right:
            self.rect = self.image.get_rect(bottomright = self.rect.bottomright)
        elif self.on_ground and self.on_left:
            self.rect = self.image.get_rect(bottomleft = self.rect.bottomleft)
        elif self.on_ground:
            self.rect = self.image.get_rect(midbottom = self.rect.midbottom)
        elif self.on_ceiling and self.on_right:
            self.rect = self.image.get_rect(topright = self.rect.topright)
        elif self.on_ceiling and self.on_left:
            self.rect = self.image.get_rect(topleft = self.rect.topleft)
        elif self.on_ceiling:
            self.rect = self.image.get_rect(midtop = self.rect.midtop)

    def run_dust_animation(self):

        # if player runs, then dusty
        if self.status == 'run' and self.on_ground:
            self.dust_frame_index += self.dust_animation_speed
            if self.dust_frame_index >= len(self.dust_run_particles):
                self.dust_frame_index = 0

            dust_particle = self.dust_run_particles[int(self.dust_frame_index)]

            # different dust animations for either right or left
            if self.facing_right:
                pos = self.rect.bottomleft - pygame.math.Vector2(6, 10)
                self.display_surface.blit(dust_particle, pos)
            else:
                pos = self.rect.bottomright - pygame.math.Vector2(6, 10)
                flipped_dust_particle = pygame.transform.flip(dust_particle, True, False)
                self.display_surface.blit(flipped_dust_particle, pos)

    def get_input(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_RIGHT]:
            self.direction.x = 1
            self.facing_right = True
        elif keys[pygame.K_LEFT]:
            self.direction.x = -1
            self.facing_right = False
        else: self.direction.x = 0

        if keys[pygame.K_SPACE] and self.on_ground:     # only allow a jump
            self.jump()
            self.create_jump_particles(self.rect.midbottom)

    def get_status(self):
        if self.direction.y < 0:
            self.status = 'jump'
        elif self.direction.y > 1:
            self.status = 'fall'
        else:
            if self.direction.x != 0:
                self.status = 'run'
            else:
                self.status = 'idle'

    def apply_gravity(self):
        self.direction.y += self.gravity
        self.rect.y += self.direction.y

    def jump(self):
        self.direction.y = self.jump_speed

    def get_damage(self):
        if not self.invincible:
            self.change_health(-10)
            self.invincible = True
            self.hurt_time = pygame.time.get_ticks()

    def invincibility_timer(self):
        if self.invincible:
            current_time = pygame.time.get_ticks()
            if current_time - self.hurt_time >= self.invincibility_duration:
                self.invincibility_duration = False

    def wave_value(self):
        value = sin(pygame.time.get_ticks())
        if value >= 0: return 255
        else: return 0

    def update(self):
        self.get_input()
        self.get_status()
        self.animate()
        self.run_dust_animation()
        self.invincibility_timer()
  • 일부 지형에서 비정상적인 움직임이 간헐적으로 발생
  • 적의 움직임이 비정상적인 경우가 간헐적으로 발생
  • 4, 5, 6단계의 레벨이 3단계의 레벨과 동일

TRY

  • 버그 수정을 위해 코드 분석을 진행하는 동시에 게임을 처음부터 다시 작성해보는 것을 시도하고 기존 코드와 다른 부분이 생길 경우 주석처리
  • 레벨 재디자인
profile
아직 모자란 수학과생

0개의 댓글