본문 바로가기
개발 일지

파이게임으로 RPG 만들기 #05. 몬스터, 구조물 추가

by PrintedLove 2021. 6. 4.

이주가 넘는 시간만에 돌아온.. Printed 입니다!

 

시간이 도저히 안나더군요.. ㅠㅜ

그래도 진도는 많이 나갔습니다. 영상 먼저 보시죠!

 

 

몬스터와 구조물들이 추가되었습니다!

훵~ 했던 게임이 훨씬 다채로워졌어요.

 

여기서 이제 플레이어 공격과, UI, 점수 시스템만 추가하면 프로젝트가 마무리 됩니다!

다음 프로젝트로 우주하마님 팬게임을 다시 만들어 보려고 해서

조금 급하게 끝낼수도 있겠네요!

 

아래는 주요 코드들입니다.

# 기본 오브젝트 클래스
class BaseObject:
    def __init__(self, spr, coord, kinds):
        self.spr = spr
        self.spr_index = 0
        self.width = spr[0].get_width()
        self.height = spr[0].get_height()
        self.direction = True
        self.vspeed = 0
        self.kinds = kinds
        self.rect = pygame.rect.Rect(coord[0], coord[1], self.width, self.height)
        self.destroy = False

    def draw(self, screen, scroll):
        screen.blit(pygame.transform.flip(self.spr[self.spr_index], self.direction, False)
                    , (self.rect.x - scroll[0], self.rect.y - scroll[1]))
        
    def destroy(self):
        objects.remove(self)
        del(self)

# 적 오브젝트 클래스
class EnemyObject(BaseObject):
    def __init__(self, spr, coord, kinds, types):
        super().__init__(spr, coord, kinds)
        self.types = types
        self.frameSpeed = 0
        self.frameTimer = 0
        self.actSpeed = 0
        self.actTimer = 0
        self.hpm = 0
        self.hp = 0

    def events(self, player_rect):
        movement = [0, 0]
        movement[1] += self.vspeed
        self.frameTimer += 1

        self.vspeed += 0.2
        if self.vspeed > 3:
            self.vspeed = 3

        if self.types == 'snake':       # 뱀일 경우
            if self.frameTimer >= self.frameSpeed:
                self.frameTimer = 0
                if self.spr_index < len(self.spr) - 1:
                    self.spr_index += 1
                else:
                    self.spr_index = 0

            if self.direction == False:
                if floor_map[self.rect.right // TILE_SIZE] != -1:
                    movement[0] += 1
                else:
                    self.direction = True
            else:
                if floor_map[self.rect.right // TILE_SIZE - 1] != -1:
                    movement[0] -= 1
                else:
                    self.direction = False
        elif self.types == 'slime':       # 슬라임일 경우
            self.actTimer += 1

            if self.vspeed >= 0:
                if self.frameTimer >= self.frameSpeed:
                    self.frameTimer = 0
                    if self.spr_index == 0:
                        self.spr_index = 1
                    else:
                        self.spr_index = 0
            else:
                self.spr_index = 2

            if self.actTimer == self.actSpeed - 35:
                self.vspeed = -3
            elif self.actTimer > self.actSpeed:
                self.actTimer = 0
            elif self.actTimer > self.actSpeed - 35:
                if player_rect.x - self.rect.x > 0:
                    if floor_map[self.rect.right // TILE_SIZE] != -1:
                        self.direction = False
                        movement[0] += 1
                else:
                    if floor_map[self.rect.right // TILE_SIZE - 1] != -1:
                        self.direction = True
                        movement[0] -= 1
            
        self.rect, collision = move(self.rect, movement)       # 적 움직임

        if collision['bottom']:
            self.vspeed = 0

        if collision['right'] or collision['left']:
            self.vspeed = -2

# 오브젝트 생성 함수
def createObject(spr, coord,  types):
    if types == 'snake':
        obj = EnemyObject(spr, coord, 'enemy', types)
        obj.hpm = 100
        obj.hp = obj.hpm
        obj.frameSpeed = 4
    if types == 'slime':
        obj = EnemyObject(spr, coord, 'slime', types)
        obj.hpm = 200
        obj.hp = obj.hpm
        obj.frameSpeed = 12
        obj.actSpeed = 120
        obj.actTimer = random.randrange(0, 120)

    objects.append(obj)

    return obj

 

부모 오브젝트와 자식인 에너미 오브젝트입니다.

에너미 오브젝트 내에서 인수로 받아온 types 변수를 통해 몬스터 움직임을 통제하고 있음을 확인하실 수 있습니다.

 

오브젝트 생성함수는 기초적인 적의 스텟들을 설정해주는데요, 후에 투사체 오브젝트가 추가되어도 저 함수로

기초값들을 설정할 예정입니다.

 

# 구조물 채우기
            if random.randrange(0, 100) <= 4 and case == 0:
                if random.choice([True, False]):
                    image.blit(tileSpr.spr[32], ((col) * TILE_SIZE, (floor_map[col] - 1) * TILE_SIZE))
                else:
                    image.blit(tileSpr.spr[35], ((col - 1) * TILE_SIZE, (floor_map[col] - 2) * TILE_SIZE))
                    image.blit(tileSpr.spr[36], ((col) * TILE_SIZE, (floor_map[col] - 2) * TILE_SIZE))
                    image.blit(tileSpr.spr[37], ((col - 1) * TILE_SIZE, (floor_map[col] - 1) * TILE_SIZE))
                    image.blit(tileSpr.spr[38], ((col) * TILE_SIZE, (floor_map[col] - 1) * TILE_SIZE))

            if random.randrange(0, 100) <= 14:
                struct_types = random.choice(['leaf', 'flower', 'obj', 'sign', 'gravestone', 'skull'])
                struct_index = random.randrange(structSpr[struct_types][0], structSpr[struct_types][1])
                front_image.blit( tileSpr.spr[struct_index], (col * TILE_SIZE, (floor_map[col] - 1) * TILE_SIZE))

            if random.choice([True, False]):
                struct_index = random.randrange(47, 55)
                front_image.blit(tileSpr.spr[struct_index], (col * TILE_SIZE, (floor_map[col] - 1) * TILE_SIZE)) 

 

 맵 이미지 생성 함수 createMapImage에 추가된 부분입니다.

구조물 이미지들을 두가지 레이어에 추가합니다.

캐릭터 위쪽으로 수풀이나 잔디가 나올 수 있도록 새롭게 mapImage_front라는 레이어를 추가했습니다.

 

 

다음 일지에서는 캐릭터의 공격과 적 처치부분을 만들어볼 예정입니다!

이제 한두편만 더 쓰면 완성이네요!

 

7월 초에 훈련이 예정되어 있어 그전까지 팬게임을 완성시키려면 빠듯할듯 합니다...

중간에 기말고사까지.. 휴우.

일단 이 프로젝트부터 빨리 완성시켜야 겠습니다!

 

 

 

PrintedLove/Python-pygame-RPG-tutorial

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

github.com

 

댓글