티스토리 뷰

클래스 내에서 정의되는 함수인 메소드(method)를 공부해보겠습니다. 클래스에는 여러 개의 메소드를 정의할 수 있는데 일반 함수와 다른 점이라면 메소드는 전달값을 정의하는 부분 처음에 self 를 적어준다는 점, 그리고 메소드 내에서 self. 을 통해 클래스 멤버변수에 접근 가능하다는 점입니다.

 

스타크래프트에는 공격을 할 수 있는 유닛이 대부분이지만 공격을 할 수 없는 유닛도 있습니다. 예를 들면 유닛들의 수송을 담당하는 드랍쉽이나 부상당한 유닛을 치료해주는 메딕처럼 말이죠. 그래서 이번에는 공격을 할 수 있는 유닛만을 위한 새로운 클래스를 정의하고 이름은 AttackUnit 이라고 하겠습니다. AttackUnit 은 Unit 클래스와 동일하게 __init__() 생성자에서 name, hp, damage 멤버 변수를 정의하는데 print() 를 통한 출력문은 따로 적지 않겠습니다.

class AttackUnit: # 공격 유닛
    def __init__(self, name, hp, damage):
        self.name = name
        self.hp = hp
        self.damage = damage

 

공격 유닛인 만큼 공격 명령을 내리면 공격을 하는 동작, 그리고 적군으로부터 공격을 받으면 피해를 입는 동작을 정의해야겠지요. 우선 공격을 하는 동작을 위한 메소드를 만들겠습니다. 메소드 이름은 attack 으로 하고 전달값에는 기본적으로 적어줘야하는 self 다음에 공격 방향을 의미하는 location 을 정의하겠습니다.

 


스타크래프트는 넓은 땅에서 전쟁을 하는 만큼 적군의 위치를 1시 방향, 9시 방향과 같이
시계 기준으로 표현합니다. 공격 명령을 받아서 공격을 갈 때는 해당 유닛 이름과 전달받은 공격 방향 정보, 그리고 공격력을 출력해줍니다. 이 때 유닛 이름과 공격력은 이미 클래스 객체의 멤버 변수로 정의되어 있기 때문에 자기 자신을 의미하는 self. 을 쓰고, 공격 방향은 명령을 받을 때마다 달라질 수 있으므로 멤버 변수가 아닌 전달값을 사용하기 위해 self. 없이 쓴다는 점 주의해주셔야 합니다.

class AttackUnit:
    ... # __init__() 생략
        
    def attack(self, location): # 전달 받은 방향으로 공격
        print("{0} : {1} 방향으로 적군을 공격 합니다. [공격력 {2}]" \
            .format(self.name, location, self.damage)) # 공간이 좁아서 2줄에 걸쳐 출력

참고로 하나의 문장이 너무 길어서 한 줄에 표현하기 어렵거나 보기 좋게 두 줄 이상으로 나누고자 할 때는 문장 끝에 역슬래시(\) 를 넣음으로써 다음 줄에서 계속하여 문장을 이어갈 수 있습니다.

 

이번에는 공격을 받아서 피해를 입는 동작도 정의해보겠습니다. 적군의 공격 유닛은 종류별로 다른 공격력을 가지며 상황에 따라 피해 데미지도 달라질 수 있으므로 damage 를 전달값으로 받겠습니다. 그리고 유닛이 현재 가지고 있는 체력 정보에서 데미지만큼 값을 빼줘야겠지요. 그런데 만약 공격을 받은 후 남은 체력이 0 이하라면 아쉽지만 유닛은 파괴처리를 해야할 것입니다. 예제에서는 편의상 파괴되었다는 문장 정도만 출력하겠습니다.

class AttackUnit:
    ... # __init__() 생략
    
    ... # attack() 생략
    
    def damaged(self, damage): # damage 만큼 유닛 피해
        print("{0} : {1} 데미지를 입었습니다.".format(self.name, damage)) # 데미지 정보 출력
        self.hp -= damage # 유닛의 체력에서 전달받은 damage 만큼 감소
        print("{0} : 현재 체력은 {1} 입니다.".format(self.name, self.hp)) # 남은 체력 출력
        if self.hp <= 0: # 남은 체력이 0 이하이면?
            print("{0} : 파괴되었습니다.".format(self.name)) # 유닛 파괴 처리

 

지금까지 만든 AttackUnit 의 객체를 만들고 메소드를 사용해보겠습니다.

새로운 유닛인 파이어뱃을 만들어볼까요? 파이어뱃은 마린과 비슷한 크기의 공격 유닛인데, 화염방사기를 다룹니다. 마린의 총에 비해서 사정거리는 짧지만 바로 근처에 있는 적들에게는 가공할 만한 위력을 갖추고 있지요.

 

 

파이어뱃을 하나 만들고 5시 방향으로 공격 명령을 내려보겠습니다.

# 파이어뱃 : 공격 유닛, 화염방사기. 
firebat1 = AttackUnit("파이어뱃", 50, 16) # 체력 50, 공격력 16
firebat1.attack("5시") # 5시 방향으로 공격 명령

실행을 시켜보니 명령대로 공격을 하는 것을 확인할 수 있습니다.

파이어뱃 : 5시 방향으로 적군을 공격 합니다. [공격력 16]

 

공격을 하는 와중에 적군으로부터 피해를 입는다고 가정하고 25 만큼의 데미지로 2 번 공격 받도록 해보겠습니다.

# 공격 2번 받는다고 가정
firebat1.damaged(25) # 남은 체력 25
firebat1.damaged(25) # 남은 채력 0

실행해보니 2번의 공격을 받고 각각 25씩 데미지를 입은 파이어뱃은 원래 체력 50 에서 0 이 되었고 아쉽게도 파괴되었다는 전갈을 받게 됩니다.

파이어뱃 : 25 데미지를 입었습니다. # 1차 공격 받음
파이어뱃 : 현재 체력은 25 입니다.
파이어뱃 : 25 데미지를 입었습니다. # 2차 공격 받음
파이어뱃 : 현재 체력은 0 입니다.
파이어뱃 : 파괴되었습니다.

 

이번 장에서는 새로운 클래스를 정의하고 __init__() 생성자를 제외한 2개의 메소드를 추가로 정의한 후 각각 호출해보는 부분까지 다뤄보았습니다.

 

잠깐!
self 는 자기 자신을 의미합니다. 생성자 또는 메소드에서 self 를 전달받는 것은 결국 자기 자신을 받는다는 의미이며 메소드 내에서 self. 를 쓰는 것은 자기 자신의 멤버 변수 또는 메소드에 접근하겠다는 의미가 됩니다.
firebat1 은 AttackUnit 클래스의 인스턴스이며 코드상에서 객체를 생성할 때는 name, hp, damage 정보만 전달하지만 자동으로 호출되는 __init__() 생성자의 처음 위치에 있는 self 에 자기 자신을 전달하는 것과 같습니다.
그래서 생성자 내에서 self.name = name 이라고 하는 것은 마치 firebat1.name = name 과 같은 동작이 되는 것입니다.

머리가 아파지려고 한다면, 그냥 클래스 메소드의 처음 위치에는 self 를 적어야 하며 클래스 내에서는 self.name 또는 self.attack(...) 과 같이 self. 과 함께 멤버 변수 또는 메소드 이름을 적어서 접근할 수 있다는 것만 기억하시면 됩니다.

 


지금까지 작성한 전체 코드입니다.

class AttackUnit: # 공격 유닛
    def __init__(self, name, hp, damage):
        self.name = name
        self.hp = hp
        self.damage = damage

    def attack(self, location): # 공격 방향
        print("{0} : {1} 방향으로 적군을 공격 합니다. [공격력 {2}]" \
            .format(self.name, location, self.damage)) # 공간이 좁아서 2줄에 걸쳐 출력

    def damaged(self, damage): # damage 만큼 유닛 피해
        print("{0} : {1} 데미지를 입었습니다.".format(self.name, damage)) # 데미지 정보 출력
        self.hp -= damage # 유닛의 체력에서 전달받은 damage 만큼 감소
        print("{0} : 현재 체력은 {1} 입니다.".format(self.name, self.hp)) # 남은 체력 출력
        if self.hp <= 0: # 남은 체력이 0 이하이면?
            print("{0} : 파괴되었습니다.".format(self.name)) # 유닛 파괴 처리

# 파이어뱃 : 공격 유닛, 화염방사기. 
firebat1 = AttackUnit("파이어뱃", 50, 16) # 체력 50, 공격력 16
firebat1.attack("5시") # 5시 방향으로 공격 명령

# 공격 2번 받는다고 가정
firebat1.damaged(25) # 남은 체력 25
firebat1.damaged(25) # 남은 채력 0

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함