자바 스크립트에서 분기 대화를 어떻게 구현합니까? “# ~”와 같은 태그가있는

JavaScript 로 매우 기본적인 비주얼 노벨 유형의 게임을 만들고 있습니다. 나는 초보자이기 때문에 재미와 학습을 위해이 일을하고 있으며 나쁜 계획으로 인해 대화의 지점에 갈 때 약간의 문제가 발생했습니다.

현재 게임에 대한 스크립트를 문자열 변수로 유지하고 “# ~”와 같은 태그가있는 각 장면을 작은 배열로 분할하여 게임 스크립트가 다음과 같이 표시되도록합니다.

var script = "Hello World!#~How are you today?"
var gameText = script.split("#~");
//gameText[0]= Hello World!

이것은 선형 작업에 효과적이지만 대화 트리에서 분기를 어떻게 처리해야합니까? 이 방법은 각 경로의 길이를 정확히 알고 있어야하며 변경해야 할 경우 두통이 될 수 있으므로 매우 복잡해 보입니다.

더 간단한 방법으로 어떻게 할 수 있습니까? 게임이 Web Run Time과 작동하도록 바닐라 JavaScript를 고수하려고합니다.



답변

빌립의 대답은 이미 올바른 방향을 보여줍니다. 데이터 구조가 불필요하게 장황하다고 생각합니다. 짧은 텍스트는 읽고 쓰기가 더 쉽습니다.

텍스트가 짧을수록 알고리즘이 조금 더 복잡 해지더라도 알고리즘을 한 번만 작성하지만 대부분의 시간은 스토리를 작성하고 유지하는 데 소비되므로 많은 가치가 있습니다. 따라서 대부분의 시간을 할애하는 부분을 쉽게 만들 수 있도록 최적화하십시오.

var story = [
  { m: "Hi!" },
  { m: "This is my new game." },
  { question: "Do you like it?", answers: [
    { m: "yes", next: "like_yes" },
    { m: "no", next: "like_no" },
  ] },
  { label: "like_yes", m: "I am happy you like my game!", next: "like_end" },
  { label: "like_no", m: "You made me sad!", next: "like_end" },
  { label: "like_end" },
  { m: "OK, let's change the topic" }
];

이 디자인에 대한 몇 가지 설명 :

전체 이야기는 하나의 배열로 작성됩니다. 숫자를 제공 할 필요는 없으며 배열 구문에 의해 자동으로 제공됩니다. 첫 번째 항목에는 색인 0이 있고 다음 항목에는 색인 1이 있습니다.

대부분의 경우 다음 단계의 번호를 쓸 필요는 없습니다. 나는 대부분의 텍스트 줄이 가지 가 아니라고 가정합니다 . “다음 단계는 다음 항목입니다”를 기본 가정으로 설정하고 그렇지 않은 경우에만 메모를 작성하겠습니다.

점프하려면 숫자가 아닌 레이블을 사용하십시오 . 그런 다음 나중에 몇 줄을 추가하거나 제거하면 스토리의 논리가 유지되므로 숫자를 조정할 필요가 없습니다.

선명도와 부족함 사이의 합리적인 타협점을 찾으십시오. 예를 들어, “message”대신 “m”을 쓰는 것이 좋습니다. 왜냐하면 가장 많이 사용되는 명령이므로 짧게 만들면 텍스트를보다 읽기 쉽게 만들 수 있기 때문입니다. 그러나 나머지 키워드를 줄일 필요는 없습니다. (단, 당신이 원하는대로 할. 중요한 것은 그것이 가장 명료하게하는 것입니다 당신을 위해 . 다른 방법으로는 유효한 키워드로 모두 “M”과 “메시지”를 지원할 수 있습니다.)

게임 알고리즘은 다음과 같아야합니다.

function execute_game() {
  var current_line = 0;
  while (current_line < story.length) {
    var current_step = story[current_line];
    if (undefined !== current_step.m) {

      display_message(current_step.m);
      if (undefined !== current_step.next) {
        current_line = find_label(current_step.next);
      } else {
        current_line = current_line + 1;
      }

    } else if (undefined !== current_step.question) {

      // display the question: current_step.question
      // display the answers: current_step.answers
      // choose an answer
      // and change current_line accordingly

    }
  }
}

그건 그렇고, 이러한 아이디어는 Ren’Py 에서 영감을 얻었습니다. Ren’Py 는 웹이 아닌 JavaScript가 아닌 원하는 것이 아니지만 멋진 아이디어를 줄 수 있습니다.


답변

대화 이벤트 배열을 만드는 것이 좋습니다. 각 이벤트는 NPC가 말한 텍스트와 가능한 플레이어 응답 배열을 포함하는 개체이며,이 텍스트는 응답 텍스트와이 응답에 뒤 따르는 이벤트 색인이있는 개체입니다.

var event = []; // create empty array

// create event objects and store them in the array
event[0] = { text: "Hello, how are you?",
             options: [    { response: "Bad", next: 1 },
                           { response: "Good", next: 2 }
                      ]
           };
event[1] = { text: "Why, what's wrong?",
             options: [    { response: "My dog ran away", next: 3},
                           { response: "I broke up with my girlfriend", next: 4}
                      ]
           };
event[2] = { text: "That's nice",

...

답변

다른 접근 방식을 사용해야합니다. JavaScript는 배열과 객체를 지원하므로 항목 당 하나를 사용하지 않아도 모든 분할을 저장하고 실제 텍스트를보다 쉽게 ​​편집 / 읽을 수 있습니까?

원하는 경우 # 1gam에 대해 몇 시간 동안 만든 프로토 타입을 살펴볼 수 있습니다 . 소스는 GPLv3에서 무료로 사용할 수 있습니다. GPL을 고수하지 않고 영감을 얻기 위해 사용하는 경우 완벽하게 좋습니다. 그러나 게임이 끝나면 알려주십시오. 멋진 글쓰기 나 그와 비슷한 것을 기대하지 마십시오. 😉

CSS 애니메이션과 그와 같은 것들을 무시하고 코드 작동 방식에 대한 간단한 설명을 제공합니다.

  • var data 본질적으로 가능한 모든 선택 등을 포함한 전체 이야기가 포함됩니다.
  • 모든 “위치”(또는 페이지 / 항목)는 ID로 식별됩니다. 목록의 첫 번째 ID는 start, 두 번째 cwait등입니다.
  • 모든 위치에는 캡션과 실제 텍스트라는 두 가지 필수 요소가 있습니다. 의사 결정에 대한 링크는 양식을 취하는 간단한 마크 업으로 작성 [target location:display text]됩니다.
  • “매직”전체가 내부에서 발생합니다 navigate().이 기능은 마크 업 링크를 클릭하게 만듭니다. 또한 Dead Ends에 대한 정적 텍스트도 처리하기 때문에 조금 더 깁니다. 중요한 부분은에 대한 첫 두 번의 호출 replace()입니다.
  • 선택적인 마지막 항목은 혼합 할 새로운 배경색을 정의하여 게임의 전반적인 분위기를 지원합니다.
  • 이 색상을 정의하는 대신 다른 위치를 가리키는 링크를 추가 할 수도 있습니다 (이 코드는 내 코드로 처리 되지 않습니다 .이를 보여주는 아이디어 일뿐입니다).

    'start': ['Waking up', 'You wake...', 'cwait:yell for help', 'cwait: wait a bit', 'clook: look around']