ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [파이썬/Python] 텍스트 RPG(3): 스텟 분배
    깜빡의 취미/파이썬을 합니다. 2021. 10. 3. 11:30
    728x90

    # 출력 화면은 모두 Pycharm을 이용했습니다.

    반응형

    이 글이 완료될 즈음 여러분은 가장 기초적인 형태의 턴제 RPG를 만들어볼 수 있을 것이다. 물론 가장 기초적인 형태라 실제 그래픽 구현 등은 거의 되어 있지 않다. 그래도 파이썬으로 무언가 해보고 싶은데 무엇부터 해야 할지 모르겠어 막막한 초심자라면, 한 번쯤 도전해볼 만하다.

     

    지난 시간에는 튜토리얼격인 첫 번째 전투에 관한 글을 다루어 보았다.

     

    [파이썬/Python] 텍스트 RPG(2): 튜토리얼(= 첫 전투)

    # 출력 화면은 모두 Pycharm을 이용했습니다. 이 글이 완료될 즈음 여러분은 가장 기초적인 형태의 턴제 RPG를 만들어볼 수 있을 것이다. 물론 가장 기초적인 형태라 실제 그래픽 구현 등은 거의 되

    ccamppak.tistory.com

     

    이번 시간에는 전투에 승리한 주인공(플레이어)을 더욱 강하게 만들어 줄 스텟 배분에 관해 설명해 본다.


    스텟 배분 

    이번에는 한 번에 설명할 수 있을 만큼 분량이 적다. 빠르게 전체 코드를 보여드리고, 바로 설명을 시작하겠다.

    체력 = 체력1
    방어력 = 0
    스킬포인트 = 3
    while 스킬포인트 > 0:
        print('\n하나 고르시오. q: 전투력 (공격력 상승 / 체력 상승) w: 국방력 (방어력 상승 / 스킬 상승) e: 열외력 (도주 확률 증가)')
        N = input('당신의 선택은? ...   ')
        if N == "q":
            전투력1 = 전투력
            체력1 = 체력
            전투력 += random.choice([1,2,3])
            공격력 = 전투력
            체력 += (전투력 - 전투력1)*5
            print(f"\n전투력이 {전투력 - 전투력1} 만큼 올라 {전투력}(이/가) 되었다. 체력이 {체력 - 체력1}만큼 올라 {체력}(이/가) 되었다.")
            스킬포인트 -= 1
        elif N == "w":
            정신력1 = 정신력
            정신력 += random.choice([1,2,3])
            print(f"\n국방력이 {정신력 - 정신력1} 만큼 올라 {정신력}(이/가) 되었다.")
            스킬포인트 -= 1
        elif N == "e":
            운1 = 운
            운 += random.choice([1,2,3])
            print(f"\n열외력이 {운 - 운1} 만큼 올라 {운}(이/가) 되었다.")
            스킬포인트 -= 1

    체력 = 체력1
    방어력 = 0

    앞서 첫 번째 전투가 승리로 끝난 뒤 이어지는 배분창이므로, 전투 중에 바뀌었던 체력과 방어력을 전투 전의 것으로 되돌려야 한다. 방어력의 경우 전투 중에만 활성화되는 개념이므로 0으로 재설정하고, 체력의 경우 앞서 저장해 두었던 체력1을 불러온다는 개념으로 이해하면 좋다.



    스킬포인트 = 3

    이 부분은 스킬포인트의 개수를 정할 수 있는 줄이다. 재량에 따라 정할 수 있겠지만, 올릴 수 있는 스텟의 종류가 3개이므로 예시에서는 3으로 설정해 두었다.


    while 스킬포인트 > 0:

    앞으로 이어질 코드들을 살펴보면, 스텟 배분이 한 차례 끝난 뒤 스킬포인트 개수를 소모하는 방식으로 되어 있다. 따라서 스킬포인트가 0이 되면 while문이 끝날 수 있도록 미리! 조건을 적어 두자.

     

        print('\n하나 고르시오. q: 전투력 (공격력 상승 / 체력 상승) w: 국방력 (방어력 상승 / 스킬 상승) e: 열외력 (도주 확률 증가)')
        N = input('당신의 선택은? ...   ')

    꼭 두 줄로 할 필요는 없다. 다만 입력란의 경우 일정한 문자와 대응해주어야 이후 코드를 진행할 수 있다. 해당 예시에서도 N을 input함수와 대응시킨 것을 확인할 수 있다. print문의 경우, 게임 플레이를 하며 각 스텟이 어떤 역할을 하는지 설명하는 부분이 없었기 때문에 추가하였다.

    int(input())식을 사용하고 싶은 분이 있을 수 있다. 사용해도 큰 차이는 없지만, 다만 이 경우 엔터 키를 잘못 치는 등 숫자가 아닌 것을 입력하면 아예 오류가 뜬다. input 함수만 이용했을 때 엔터 키를 잘못 치면 오류 없이 다시 스텟을 높일 수 있다.


        if N == "q":

    우선, 입력란에 q를 적었을 때 일어나는 일부터 살펴보자.

     

            전투력1 = 전투력

            체력1 = 체력

    전투력과 체력이 얼마나 올랐는지도 설명해 주어야 하기 때문에, 미리 전투력1체력1을 따로 설정하여 기존의 전투력과 체력 값을 지정해 두었다.

     

            전투력 += random.choice([1,2,3])

    random 라이브러리는 앞서 코딩을 진행하였다면 이미 import random을 통해 이용할 수 있게 되었을 것이다. random.choice 함수는 앞서 몇 차례 사용하였으므로 간략하게 설명하자면 위의 코드는 1,2,3 중 임의의 값을 무작위로 선택하여 반영하여 준다.

     

            공격력 = 전투력
            체력 += (전투력 - 전투력1)*5

    공격력은 전투력과 같으므로 동일하게 적어 주고, 체력의 경우 (기존 전투력에서 오른 만큼) * 5를 해주었다.

     

            print(f"\n전투력이 {전투력 - 전투력1} 만큼 올라 {전투력}(이/가) 되었다. 체력이 {체력 - 체력1}만큼 올라 {체력}(이/가) 되었다.")
            스킬포인트 -= 1

    f 포맷팅 기법을 이용하여 전투력과 체력이 얼마나 올랐는지, 그리고 결과로 얼마가 되었는지 보여 준다. 마지막으로 스킬포인트를 하나 소진하였다는 것을 코드를 통해 명시해 주면 된다.


        elif N == "w":

    그렇다면 입력란에 w를 적는다면 어떨까.
     

           정신력1 = 정신력
            정신력 += random.choice([1,2,3])
            print(f"\n국방력이 {정신력 - 정신력1} 만큼 올라 {정신력}(이/가) 되었다.")
            스킬포인트 -= 1

    전부 동일하며, 심지어 정신력은 전투 중 다른 스텟에 영향을 미치는 요소이기 때문에, 스텟 자체가 오르는 건 비교적 간단하게 표현 가능하다. 앞서 정신력을 국방력이라고 표현해 두었던 것을 반영하여 print문을 구성했다. 마찬가지로 스킬포인트를 하나 소진하도록 하는 것을 잊지 말자.

    혹시라도 스킬포인트 -= 1이라는 코드가 스킬포인트 = 스킬포인트 -1과 같다는 것을 몰랐다면, 지금이라도 알아가길.


        elif N == "e":

    마지막으로 입력란에 e를 적는다면 어떻게 될지 살펴보자.

     

            운1 = 운
            운 += random.choice([1,2,3])
            print(f"\n열외력이 {운 - 운1} 만큼 올라 {운}(이/가) 되었다.")
            스킬포인트 -= 1

    전부 동일하며, 위의 식과 동일하다. 앞서 운을 열외력이라고 표현해 두었던 것을 반영하여 print문을 구성했다. 스킬포인트를 하나 소진하도록 하는 것을 꼭 잊지 말자.


    스텟 배분 구현 장면. 아무 것도 입력하지 않으면 다시 선택창으로 돌아간다는 것까지 확인 가능하다.

    글을 나가며

    개인적으로 느끼기에 스텟 배분 시스템은 게임의 흥미를 높이는 데 큰 역할을 하는 요소라고 느낀다. 전투가 진행될수록 캐릭터가 여러 방향으로 강해질 수 있으며, 적에 따라 다양한 전략을 구사할 수 있게 되어 보다 다채로운 플레이가 가능할 것이다. 세세한 수치 등은 각자 원하는 대로 조정 가능하지만, 여러 번 실제 게임을 플레이해보며 적정하다고 생각하는 수치들을 가지고 왔으니, 위의 예시들을 참고해 주시길. 끝으로 기존에 설명했던 코드들을 포함한 지금까지의 최종본을 보여드리며 글 마친다.

    import random
    import time
    print("당신의 이름을 선택하세요.")
    나 = input()
    # 전투 시 실제로 적용되는 요소들
    기초체력 = 75
    방어력 = 0
    공격력 = 0
    # 전투력: 공격력, 체력 상승 / 정신력: 방어력, 스킬 강해짐 / 운: 도주 확률 증가
    전투력 = 0
    정신력 = 0
    운 = 0
    
    # 기: 스킬을 위해 필요 / 도주: 보스를 위한 숨겨진 요소
    기 = 0
    도주 = 0
    
    while 1:
        전투력 = random.randrange(5, 11)
        체력 = 기초체력 + 전투력*1
        공격력 = 전투력
        정신력 = random.randrange(1, 6)
        운 = random.randrange(1, 6)
        print(f"전투력 = {전투력}, 국방력= {정신력}, 열외력={운}")
        print("다시 하겠습니까: a = 네, b = 아니오")
        A = input()
        if A == "a":
            continue
        if A == "b":
            print("\n정말 결정하셨습까?: a = 네, b = 아니오")
            B = input()
            if B == "b":
                continue
            elif B == "a":
                print("\n결정되었습니다.")
                print(f"""
            [스테이터스]
            이름 = {나}
            직업 = 훈련병
            체력=  {체력}
            전투력 = {전투력}
            국방력 = {정신력}
            열외력 = {운}""")
                break
    
    input(f"\n{나}: 뭐야? 왜 이렇게 조용해?")
    input(f"\n거울 속의 {나}: 뭐긴, 시작한 거지. 이번엔 이런 몸인가? 슬슬 나가자 좀.")
    input(f"\n{나}: 거울 속에서 말이? 아니 그럼 훈련병 괴담이 전부 사실이었단 말이야?")
    input(f"\n거울 속의 {나}: 뭐... 그건 잘 모르겠고. 일단 좀 맞자.")
    input(f"\n{나}: ???")
    
    적체력 = 50
    적방어력 = 0
    적공격력 = 7
    적기 = 0
    적정신력 = 0
    print(f"거울 속 {나}의 체력: {적체력}")
    체력1 = 체력
    
    while 1:
        #주인공의 행동 패턴
        print(f"\n{나}의 턴!!!!")
        time.sleep(1)
        N = input("q)공격 w)방어 e)스킬 r)도망간다\n")
        if N == "q":
            print(f"{나}은/는 잽을 두 번 날렸다.")
            공격력1 = 공격력 + random.choice([1, 2, 3, 5, 8])
            if 공격력1 - 적방어력 <= 0:
                print("공격은 완전히 복부로 흡수돼 방어됐다...")
                적방어력 -= 공격력1
            else:
                적체력 -= (공격력1 - 적방어력)
                print(f"상대방의 남은 체력 = {적체력}")
                적방어력 = 0
        elif N == "w":
            방어력 += 5 + 정신력
            print(f'{나}은 덜 아프게 맞을 자세를 취했다 방어도가 {방어력}가 되었다')
        elif N == "e":
            기 += 1
            print("기~")
            if 기 == 2:
                print(f"{나}의 어퍼컷!")
                적체력 -= 정신력 + random.choice([10, 15, 20, 25, 30])
                print(f"상대방의 남은 체력 = {적체력}")
                기 = 0
        elif N == "r":
            escape = random.random()
            if escape < 운/10:
                print(f"{나}는 군인의 본분을 져버리고 도망갔다... \n무언가 업보가 쌓이는 듯한 느낌이 든다...")
                도주 += 1
                break
            else:
                print("도망에 실패했다!!!")
        if 적체력 <= 0:
            print(f"거울 속의 {나}: 쳇, 이번에도 글렀나.")
            break
    
        #적의 행동 패턴
        N = random.randrange(1, 4)
        print("\n상대의 턴!!!")
        time.sleep(1)
        if N == 1:
            적공격력1 = 적공격력 + random.choice([1, 2, 3, 5, 8])
            if 적공격력1 - 방어력 <= 0:
                print("공격은 완전히 복부로 흡수돼 방어됐따 ^^7")
                방어력 -= 적공격력1
            else:
                print("상대는 잽을 두 번 날렸다.")
                체력 -= (적공격력1 - 방어력)
                print(f"{나}의 남은 체력 = {체력}")
                방어력 = 0
        elif N == 2:
            적방어력 += 5 + 적정신력
            print(f'상대는 덜 아프게 맞을 자세를 취했다 방어도가 {적방어력}가 되었다')
        elif N == 3:
            적기 += 1
            print("기~")
            if 적기 == 2:
                print("상대의 어퍼컷!")
                체력 -= 적정신력 + random.choice([10, 15, 20, 25, 30])
                print(f"{나}의 남은 체력 = {체력}")
                적기 = 0
        if 체력 <= 0:
            print("눈앞이 깜깜해졌다")
            print("\ntip: 이걸 지다니... 지나가던 개(발자)가 웃겠다.")
            Count = input("다시 하시겠습니까? q: 다시 한다. w: 다시 한다. e: 다시 한다.\n... ")
            if Count != "이걸맞추면당신은천재":
                t = 4
                while t >= 1:
                    t = t - 1
                    time.sleep(1)
                    print(f"로딩까지 {t}초")
                    체력 = 체력1
                    적체력 = 50
                    적방어력 = 0
                    방어력 = 0
                    continue
    
    체력 = 체력1
    방어력 = 0
    스킬포인트 = 3
    while 스킬포인트 > 0:
        print('\n하나 고르시오. q: 전투력 (공격력 상승 / 체력 상승) w: 국방력 (방어력 상승 / 스킬 상승) e: 열외력 (도주 확률 증가)')
        N = input('당신의 선택은? ...   ')
        if N == "q":
            전투력1 = 전투력
            체력1 = 체력
            전투력 += random.choice([1,2,3])
            공격력 = 전투력
            체력 += (전투력 - 전투력1)*5
            print(f"\n전투력이 {전투력 - 전투력1} 만큼 올라 {전투력}(이/가) 되었다. 체력이 {체력 - 체력1}만큼 올라 {체력}(이/가) 되었다.")
            스킬포인트 -= 1
        elif N == "w":
            정신력1 = 정신력
            정신력 += random.choice([1,2,3])
            print(f"\n국방력이 {정신력 - 정신력1} 만큼 올라 {정신력}(이/가) 되었다.")
            스킬포인트 -= 1
        elif N == "e":
            운1 = 운
            운 += random.choice([1,2,3])
            print(f"\n열외력이 {운 - 운1} 만큼 올라 {운}(이/가) 되었다.")
            스킬포인트 -= 1

    저 포함 두 명이서 식을 짜고 고민하면서 알아낸 사실들, 그리고 그렇게 해서 나온 결과물을 최대한 자세하게 설명드리고 싶었습니다. 이번에도 분량 조절에 실패해 버렸네요...ㅎㅎ 이 글을 통해 조금이나마 기초 개념의 사용 선택지를 늘려 가신다면 좋겠습니다. 방문 감사합니다~ 구독 공감도 감사히 받고 있습니다!(꾸벅) 

     

    벌써 162줄 정도 분량이 되었네요...! 반복적으로 등장하는 개념들은 백준 단계별로 풀어보기나 파이썬 기초에도 많이 사용되는 것들이니, 복습하신다는 마음으로 한번씩 검토해 보시면 좋겠습니다. 다음 주에는 또 다른 양상의 전투를 구현하는 법을 간단하게 소개해 보고자 합니다. 시간이 지나면서 기존에 설명드렸던 내용은 조금씩 빼놓고 글을 써내려갈 수 있는데, 혹시 불친절한 방식이라고 느껴진다면 주저 없이! 댓글 남겨주세요~ 다시 한 번 들러주셔서 감사합니다!

    댓글

Designed by Tistory.