자바 스크립트에서 분기 대화를 어떻게 구현합니까?


11

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

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

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

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

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


이 비디오는 몇 가지 아이디어를 줄 수 있습니다. youtube.com/watch?v=XM2t5H7kY6Y
JCM

나는 최근에 Node를 사용하여 이것을 위해 무언가를 개발해야했으며 매우 기본적인 텍스트 파일 구조를 선택했습니다. github.com/scottbw/dialoguejs 에서 결과 코드와 텍스트 형식을 볼 수 있습니다 . 코드는 GPL이므로 언제든지 사용하십시오. 노드가 아닌 JS 게임에 적응하는 것이 어렵지 않을 것이라고 확신합니다. "fs.load ()"부분을 Ajax로 바꾸십시오.
Scott Wilson

Inkle Studio가 개발 한 분기 스토리 스크립트 언어 인 Ink를 확인하십시오 . 다양한 프로그래밍 방식의 잉크 통합 (Java, Javascript, C #) 및 많은 타사 리소스가 있습니다. 많은 상용 게임에서도 잉크가 사용되었습니다. 마지막으로, 분기 대화를 구문 검사하고 '재생'할 수 있는 데스크탑 편집기 인 Inky 가 있습니다.
빅 리치

답변:


8

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

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

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가 아닌 원하는 것이 아니지만 멋진 아이디어를 줄 수 있습니다.


깊이있는 설명에 감사드립니다. 배열이 당신과 필립이 보여준 방식으로 작동 할 수 있다는 것을 알지 못했습니다. 문자열이나 숫자 만 가질 수 있다고 생각했습니다.
침묵하는 제작자

1
나는 당신의 솔루션을 구현하려고 노력했지만 꽤 잘 작동하지만 어떤 곳 ({ label: "like_yes"; m: "I am happy you like my game!"; next: "like_end" },)에서는 ';'이 아닌 ';' 가 있어야 한다고 생각 합니다. 또한 중괄호 안의 것은 정확히 무엇입니까? 배열 내의 객체입니까? 이것을 사용하는 방법에 대한 자세한 정보를 원한다면 무엇을 검색합니까?
침묵의 제작자

예, {...}대상입니다. JavaScript에서 object는 PHP의 array 또는 Java의 Map과 유사한 키-값 연관 배열 (이 예제에서는 사용하지 않는 추가 기능이있는)입니다. 자세한 내용은 JavaScript 및 ECMAScript에 대한 Wikipedia 기사와 관련 공식 문서, 특히 공식 ECMAScript 문서를 참조하십시오.
Viliam Búr

1
btw가 여기에서 권장하는 데이터 구조는 기본적으로 JSON입니다. 개인적으로 JSON으로 (가장 괄호와 "트리"를 추가하는 것이 좋습니다. { "tree": [etc]}와 같이 전체 것 주위에) 대화 상자 트리를 외부 파일에 저장할 수 있습니다. 게임이로드하는 외부 파일에 데이터를 넣는 것이 훨씬 유연하고 모듈화됩니다 (따라서이 방법이 최선의 방법 임).
jhocking

5

대화 이벤트 배열을 만드는 것이 좋습니다. 각 이벤트는 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",

...

2

다른 접근 방식을 사용해야합니다. 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']

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.