본문 바로가기
개발 일지

파이게임으로 RPG 만들기 #02. 플레이어 이동

by PrintedLove 2021. 4. 12.

 

바닥과 플레이어

 

안녕하세요. Printed 입니다!

파이게임으로 RPG 만들기 제 2회차 일지 입니다.

 

저번에 예고 했던데로 플레이어 이동을 구현해 보았습니다.

덤으로 바닥 자동 이미지 생성 함수도 만들어 보았는데... 이쪽이 더 힘들었다는게 함정...

 

# 바닥과 충돌 검사 함수
def collision_floor(rect):
    hit_list = []
    col = 0
    for row in floor_map:
        if row != -1:
            floor_rect = pygame.rect.Rect((col * TILE_SIZE, row * TILE_SIZE), (TILE_SIZE, TILE_SIZE * 5))
            if rect.colliderect(floor_rect):
                hit_list.append(floor_rect)
        col += 1

    return hit_list

# 오브젝트 이동 함수
def move(rect, movement):
    collision_types = {'top' : False, 'bottom' : False, 'right' : False, 'left' : False}
    rect.x += movement[0]
    hit_list = collision_floor(rect)

    for tile in hit_list:
        if movement[0] > 0:
            rect.right = tile.left
            collision_types['right'] = True
        elif movement[0] < 0:
            rect.left = tile.right
            collision_types['left'] = True

    rect.y += movement[1]
    hit_list = collision_floor(rect)

    for tile in hit_list:
        if movement[1] > 0:
            rect.bottom = tile.top
            collision_types['bottom'] = True
        elif movement[1] < 0:
            rect.top = tile.bottom
            collision_types['top'] = True

    return rect, collision_types

 

플레이어 이동을 담당하는 함수들입니다!

실질적인 움직임은 플레이어의 Rec를 조작하여 구현하지만, 이 두 함수들은 충돌판정이라는 더 중요한 일을 합니다.

발판에서 쓕 가라앉지 않고 위에 서있을 수 있게 만드는 함수들이죠.

 

DaFluffyPotato님의 강좌를 참고하여, 제 바닥 리스트의 조건에 맞게 조금 변형시켰습니다!

저는 바닥을 Rec의 2차원 배열으로 된 타일이 아닌 1차원 높이 데이터 만으로 구현시켜 보았습니다.

때문에, 바닥 위에 바닥이 존재하진 못하지만, 리소스 소모를 많이 줄일 수 있었습니다.

 

# 바닥 타일 이미지 생성 함수
def createMapImage(tileSpr):
    image = pygame.Surface((WINDOW_SIZE[0], WINDOW_SIZE[1]))
    empty = True                        # 빈칸
    case = 0                            # 타일 타입
    spr_index, spr_index2 = 0, []       # 타일 스프라이트 인덱스
    back_height = 0
    pattern_back = 0
    pattern_0 = 0

    for col in range(len(floor_map)):
        if floor_map[col] == -1:     # 비었을 경우
            empty = True
        else:                        # 타일이 존재할 경우
            if floor_map[col + 1] == -1:     # 앞 공간이 비었을 경우
                case = 2
                spr_index, spr_index2 = 4 + random.choice([0, 2]), [15, 16, 10]
            else:                           # 앞 공간에 타일이 존재할 경우
                if empty == True:                   # 이전 공간이 비었을 경우
                    case = 1
                    back_height = floor_map[col]
                    spr_index, spr_index2 = 3 + random.choice([0, 2]), [12, 13, 9]
                else:                               # 이전 공간에 타일이 존재할 경우
                    if floor_map[col - 1] > floor_map[col]:
                        case = 3
                        spr_index, spr_index2 = 3 + random.choice([0, 2]), [7]
                    else:
                        if floor_map[col + 1] == floor_map[col]:
                            case = 0
                            spr_index = pattern_0
                            pattern_0 += 1

                            if pattern_0 > 2:
                                pattern_0 = 0
                        else:
                            case = 4
                            spr_index, spr_index2 = 4 + random.choice([0, 2]), [8]
            empty = False

            for backtile in range(5 + back_height - floor_map[col]):        # 타일 뒷부분 채우기
                if backtile < 5:
                    image.blit(tileSpr.spr[29 - 3 * backtile + pattern_back], (col * TILE_SIZE
                        , (floor_map[col] - backtile + back_height - floor_map[col] + 4) * TILE_SIZE))
                else:
                    image.blit(tileSpr.spr[17 + pattern_back], (col * TILE_SIZE
                        , floor_map[col] * TILE_SIZE))
            pattern_back += 1

            if pattern_back > 2:
                pattern_back = 0

            image.blit(tileSpr.spr[spr_index], (col * TILE_SIZE, floor_map[col] * TILE_SIZE))   # 타일 앞부분 채우기

            if case != 0:
                i = 0
                for spr_indexs in spr_index2:
                    i += 1
                    image.blit(tileSpr.spr[spr_indexs], (col * TILE_SIZE, (floor_map[col] + i) * TILE_SIZE))
    return image

 

고작 1차원 높이 데이터에 불과한 맵 데이터를 자연스러운 바닥 이미지로 만들어주는 함수입니다.

상수를 많이 사용해 다른 게임에서는 사용하지 못하고 참고만 가능합니다..

하지만 이 함수덕에 게임 시작시 한번의 로딩만으로 바닥 이미지를 한 장의 큰 이미지로 불러올 수 있습니다.

 

야매가 많이 섞인 게임이 되어버렸네요 ㅋㅋ

여러명이서 작업하는 프로젝트면 힘들었을 극한의 성능추구 였습니다 ㅋㅋ

 

아래는 영상입니다!

 

 

다음 일지에는 아마 플레이어 추적 카메라를 구현할 것 같네요.

 

 

깃허브에서 소스코드를 확인하실 수 있습니다!

 

PrintedLove/Python-pygame-RPG-tutorial

파이게임 라이브러리로 만드는 RPG 프로젝트. 블로그에서 개발일지를 확인하실 수 있습니다. - PrintedLove/Python-pygame-RPG-tutorial

github.com

 

댓글