Làm thế nào tôi có thể thực hiện cây hộp thoại vào trò chơi của tôi?


51

Cách tốt nhất để thực hiện một hệ thống cây hộp thoại trong trò chơi của tôi là gì? Tôi muốn một NPC cung cấp cho người chơi các bộ phản hồi khác nhau, một số phản hồi chỉ có thể xuất hiện khi Người chơi có một vật phẩm hoặc một sự kiện trước đó đã xảy ra.


2
BOUNTY đặc biệt dành cho những ý tưởng hay về cách xử lý các bản dịch của cụm từ kích hoạt và văn bản NPC. Vì vậy, NPC có thể hiểu và nói các ngôn ngữ khác nhau tùy thuộc vào người chơi bắt đầu cuộc trò chuyện. Ngay cả với cách tiếp cận khối xây dựng trong gamedev.stackexchange.com/questions/31/, nó dường như không phải là một ý tưởng tốt để có logic trong kho văn bản. Nhưng việc tách chúng làm cho việc hiểu mã trở nên khó khăn hơn rất nhiều.
Hendrik Brummermann

Câu trả lời:


17

Cây đối thoại nên được thực hiện bằng cách sử dụng XML. Bạn lưu trữ các điều kiện cho các phản hồi và phản hồi trong các cây lồng nhau với một tham chiếu đến tệp tập lệnh nếu bạn cần làm một cái gì đó phức tạp hơn.

Bạn nên giữ các tập lệnh và hộp thoại riêng biệt, đặc biệt nếu bạn kết hợp một game nhập vai có số lượng cuộc trò chuyện đáng giá. Sau đó, bạn có thể sử dụng một thư viện như SimpleXML để đọc tệp XML.

Có một câu hỏi tương tự trên SO với một ví dụ: https://stackoverflow.com/questions/372915/game-logic-in-xml-files


+1 cho XML. Tốt hơn nhiều so với việc tự nhúng mã, cho phép thay đổi mà không cần biên dịch lại mã và là định dạng chuẩn có thể được đọc bởi một số biên tập viên mạnh mẽ.
Tấn

34
XML chỉ là một định dạng (và, IMO, một định dạng xấu). Thực sự những gì câu trả lời này nói là "Tạo một ngôn ngữ miền nhỏ chứa logic và luồng cơ bản, nhưng chủ yếu bao gồm đoạn hội thoại của bạn và phân tích nó." Theo cách chung đó, tôi đồng ý với câu trả lời này.
Ipsquiggle

5
Chính xác, XML chỉ là một thùng chứa, bạn cũng có thể (và chắc chắn là dễ đọc hơn và có thể chỉnh sửa được con người) thực hiện điều này bằng cách sử dụng Lua hoặc các ngôn ngữ kịch bản lệnh khác.
LearnCocos2D

4
XML rất tốn kém để phân tích cú pháp và chiếm rất nhiều bộ nhớ. Sử dụng nó như một định dạng lưu trữ là tốt, nhưng tôi sẽ viết tiện ích chuyển đổi các cây hộp thoại thành định dạng nhị phân được sử dụng trong thời gian chạy. Nếu trên PC của bạn và không quan tâm đến việc sử dụng bộ nhớ của bạn thì có thể sẽ ổn, nhưng trên bất kỳ nền tảng nào khác, chi phí bộ nhớ sẽ khiến bạn thất vọng.
BigSandwich

1
-1 cho XML. Tôi đồng ý với @Ipsquiggle và @BigSandwich
o0 '.

20

Tôi sẽ xem xét việc nhúng một ngôn ngữ kịch bản như lua hoặc ruby ​​và tương tác hộp thoại mã hóa trong đó.

Do đó, một kịch bản hộp thoại có thể trông giống như:

switch showDialog "Why don't you just leave me along!", "Okay", "But I found your dog!"
    case 1:
        showDialog "And stay gone!"
    case 2:
        if playerHasObject "dog"
            showDialog "Thank you!"
        else
            showDialog "Liar!"

Điều này cũng hoạt động tốt để mã hóa AI và những thứ đơn giản khác hữu ích để điều chỉnh trong thời gian chạy. Bạn thậm chí có thể thêm một trình soạn thảo được tích hợp vào ứng dụng của mình để có thể được gọi khi chạy trong gỡ lỗi (hoặc dưới dạng Easter Egg).


1
Tôi thích điều này với XML thẳng vì bạn có thể thêm logic. Nhưng tôi muốn nói rằng bản thân văn bản có lẽ phải bằng XML chứ không phải trong mã. (dễ dàng hơn để chỉnh sửa, bản địa hóa sang các ngôn ngữ khác, v.v.).
Iain

nếu bạn cần bản địa hóa / chỉnh sửa dễ dàng hơn, bạn có thể bọc văn bản trong một hàm ghi văn bản kèm theo vào một tệp riêng như hàm / macro tr (QString) trong Qt. pepper.troll.no/s60prereleases/doc/linguist-hellotr.html
thợ làm đinh

Điều gì ngăn bạn sử dụng các thuộc tính hoặc thẻ phụ trong xml để mô phỏng logic ở đây?
lathomas64

16

Trong trò chơi Stendhal, chúng tôi sử dụng một máy trạng thái hữu hạn để thực hiện các NPC.

Sơ đồ sau đây cho thấy một ví dụ nhỏ từ cách viết hướng dẫn nhiệm vụ .

FSM với các trạng thái IDLE, ATTENDING và QUEST_OFFERED

Lúc đầu, NPC ở trạng thái IDLE và có thể đang đi bộ xung quanh. Một người chơi có thể bắt đầu một cuộc trò chuyện bằng cách nói "hi" và NPC sẽ chuyển sang trạng thái ATTENDING. Ở trạng thái này, nó trả lời các câu hỏi về "công việc" của anh ấy và cung cấp một số "trợ giúp" trò chơi. Người chơi có thể yêu cầu một nhiệm vụ và NPC sẽ chuyển sang trạng thái QUEST_OFFERED chờ người chơi chấp nhận ("có") hoặc từ chối ("không").

Chúng tôi đã xác định một tập hợp các điều kiện có thể được gắn vào chuyển tiếp. Ví dụ: hoàn thành một nhiệm vụ chỉ có thể được thực hiện nếu PlayerHasItemWithHimCondition được đáp ứng.

Sau khi quá trình chuyển đổi được thực hiện, NPC có thể nói một số văn bản và / hoặc thực hiện một hành động. Tương tự như các điều kiện chúng tôi đã xác định một tập hợp các hành động có thể sử dụng lại như EquipItemAction , được sử dụng để trao phần thưởng nhiệm vụ cho người chơi.

Nhiều điều kiện có thể được kết hợp bằng cách sử dụng AndCondition , OrConditionNotCondition . Thông thường có một số hành động được thực hiện trên hoàn thành nhiệm vụ, vì vậy có một MultipleActions lớp là tốt.

Mặc dù việc triển khai thực tế ở Stendhal bị ảnh hưởng bởi việc không thể dịch được bằng các ngôn ngữ (con người) khác một cách dễ dàng, tôi nghĩ rằng khái niệm chung là tốt.


5

Bạn có thể xem công cụ Dlgedit của công cụ RPG nguồn mở Adonthell . Nó rất tiên tiến và nên chứa mọi thứ bạn cần (bao gồm cả nguồn;))


5

Tôi nghĩ rằng để thêm vào các bản dịch, bạn vẫn có thể sử dụng XML cho logic như đã nêu ở trên . Khi bạn rơi vào loại phức tạp đó, bạn nên viết công cụ đối thoại của riêng mình. Văn bản hội thoại của bạn sẽ được lưu trữ dưới dạng khóa cho cơ sở dữ liệu mà bạn có thể trao đổi tùy theo ngôn ngữ bạn muốn hiển thị.

Ví dụ: bạn có thể có:

<dialogue id="101" condition="!npc.carsFixed">
  <message>Localize.FixMyCar</message>
  <choices>
    <choice condition="hero.carFixingSkill > 5" priority="7" id="Localize.Sure">
      <command>hero.carFixingSkills += 1</command>
      <command>npc.carFixed = true</command>
      <command>hero.playSmokeAnimation()</command>
      <command>nextDialogue = 104</command>
    </choice>
    <choice condition="hero.carFixingSkill <= 5" id="Localize.CantFix">
      <command>nextDialogue = 105</command>
    </choice>
    <choice id="Localize.FixYourself">
      <command>npc.likesHero -= 1</command>
    </choice>
  </choices>
</dialogue>

Sau đó, bạn sẽ có trình kết xuất văn bản tìm kiếm thay thế "Localize.FixMyCar" bằng văn bản được dịch phù hợp.

Công cụ của bạn sẽ hiển thị những gì người chơi sẽ thấy bằng ngôn ngữ có thể chọn cùng với XML thô có thể chỉnh sửa.

Tương tự như vậy, bạn có thể sử dụng một cái gì đó như thế này từ ví dụ bạn đã tham chiếu :

npc.add(ConversationStates.ATTENDING,
        ConversationPhrases.QUEST_MESSAGES, 
        null,
        ConversationStates.QUEST_OFFERED, 
        Localization[ "BringMeABeer" ],
        null);

Nếu các khóa của bạn đủ mô tả không có văn bản hoàn chỉnh thì đó không phải là vấn đề.

Một cái gì đó như thế này cũng có thể hữu ích:

Localization[ "<Location>.<NPC_name>.<Dialogue_text_key>" ];

4

Dữ liệu điều khiển các ký tự của bạn bằng các tập lệnh LUA hoặc thậm chí các tệp XML. Khi bạn tương tác với NPC, hãy lấy tệp được đính kèm, đọc nó, điều chỉnh cho bất kỳ biến trò chơi nào có thể đã được kích hoạt và tạo ra phản hồi hợp lệ.

Lợi ích lớn nhất khi thực hiện theo cách này là bạn có thể dễ dàng truy cập và thao tác hộp thoại, thêm ký tự mới, v.v. Bạn cũng tránh làm hỏng cơ sở mã của mình bằng logic đặc biệt trong việc xử lý từng trường hợp.


1
Đó là Lua, không phải LUA. :)
RCIX

2
Tôi đã làm nó chỉ cho bạn, người đàn ông. ;)
David McGraw

4

Nếu bạn sử dụng XML, hãy đảm bảo bạn xây dựng một công cụ nhỏ để chỉnh sửa tệp XML. Bạn sẽ phát điên nếu không.


Nếu đã không có một công cụ để chỉnh sửa nó, thì việc sử dụng nó ở nơi đầu tiên là vô nghĩa: cũng tạo định dạng của riêng bạn!
o0 '.

3

Nếu bạn có một tập hợp các cây hộp thoại khá sâu, hãy sử dụng ChatMapper . Chúng có phiên bản miễn phí đầy đủ tính năng và công cụ cho phép bạn xuất các cây hộp thoại của mình sang XML. Tôi đã sử dụng nó và đó là một cách tuyệt vời để hình dung và sắp xếp các cây thoại phức tạp.


1

Nếu các hộp thoại của bạn có bất kỳ sự phức tạp nào, điều quan trọng nhất bạn sẽ cần để thực hiện hộp thoại là một cách để hiểu được sự phức tạp của sự tương tác của bạn. Tôi khuyên dùng một trình soạn thảo Node nào đó để hình dung điều này, mặc dù tôi không có hệ thống mở tốt nào để giới thiệu.


1

Tôi nghĩ rằng, bạn sử dụng ngôn ngữ kịch bản của riêng mình để chỉ đạo các loại trò chơi này (nếu không, Bạn nên). Sau đó, hãy mở rộng tập lệnh của bạn để xử lý các hộp thoại.
Bạn có thể làm việc với các biến trò chơi khác trong quá trình tạo logic hộp thoại. Công cụ trò chơi giống như Lego. Bạn chỉ lập trình gạch và script sử dụng chúng. Không thành vấn đề nếu bạn tạo một số trình thông dịch hoặc trình biên dịch tập lệnh. Nhưng kịch bản luôn hữu ích.


0

Máy tự động đơn giản có thể làm:

(dialogueline_id, condition) -> (next_id, response)

Nó có thể trông giống như thế này:

(1, troll is hungry?) -> (2, say "troll be hungry")
(2, player has bananas?) -> (3, say "hey, you have bananas!")
(3, ) -> (-1, (say "i like bananas, i take them and eat, you may pass, bye", remove bananas, feed the troll))
(2, player does not have bananas?) -> (-1, say "go away!!!")

Trong trò chơi Bạn tìm id và cố gắng khớp id và điều kiện.

Bạn cần mô hình hóa các điều kiện và hành động. Theo đối tượng, con trỏ hàm, XML ...

Trình soạn thảo hội thoại tốt cũng sẽ có ích.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.