Làm thế nào để xử lý nhiều chủ đề câu chuyện trong một game RPG?


26

Tôi đã thiết kế một game RPG có nhiều chủ đề câu chuyện, nghĩa là tùy thuộc vào sự lựa chọn của người dùng, một số điều có thể xảy ra hoặc không, bạn có thể đạt được điều tương tự theo nhiều cách, kết thúc có thể khác nhau, v.v.

Tôi đã triển khai một công cụ quyết định đơn giản, hoạt động tốt nhưng có một lỗ hổng lớn, ngay khi bạn đưa ra quyết định, câu chuyện bị ảnh hưởng ngay lập tức bởi quyết định của bạn, điều đó có nghĩa là bạn không thể đưa ra quyết định sẽ ảnh hưởng đến bạn trong tương lai xa . Điều này là do câu chuyện mở ra giống như một nhánh trong cấu trúc cây và nó luôn cần biết nút nào tiếp theo. Trong phần giới hạn, các quyết định được triển khai bằng cách sử dụng hàng đợi: mỗi nút biết về nút trước đó và nút tiếp theo (hoặc nếu đó là nút quyết định, nó sẽ đợi đầu vào của người dùng để đặt nút tiếp theo)

Tôi đã thấy rất nhiều game có công cụ quyết định phức tạp và tôi tự hỏi, chúng được tạo ra như thế nào? Có một thiết kế đặc biệt làm cho mọi thứ thực sự dễ dàng? Có ai đã làm một cái gì đó tương tự và có thể cho tôi một gợi ý về cách giải quyết vấn đề này?

CẬP NHẬT 1:

Một khía cạnh quan trọng là quản lý để bằng cách nào đó giữ mã câu chuyện độc lập, để nó có thể được thao tác từ một tệp bên ngoài. Tôi dự định sử dụng nó như một công cụ để thậm chí các lựa chọn có thể phải đến từ một tệp bên ngoài. Các mã phải hoàn toàn trừu tượng.

Ngoài ra, tôi quan tâm đến một giải pháp thiết kế, một cách hay để làm điều đó, cách người khác làm nó hoặc làm nó.


1
Khi các quyết định quan trọng được đưa ra, chỉ cần theo dõi chúng trong một biến có thể truy cập toàn cầu (một mảng các biến này sẽ dễ quản lý hơn). Các biến này sau đó có thể được tham chiếu bởi các phần sau của chương trình trò chơi của bạn để hành động hoặc hiển thị mọi thứ khi thích hợp. Ví dụ, người chơi quyết định trồng một cây nhỏ, và sau đó cây đó xuất hiện rất lớn - nếu họ không trồng cây, thì cây đó sẽ không ở đó vào lúc đó trong trò chơi.
Randolf Richardson

Vâng, đó là những gì tôi ban đầu mặc dù, tuy nhiên, tôi cần điều này là độc lập mã. Điều đó có nghĩa là, câu chuyện có thể được xử lý hoàn toàn từ một tệp bên ngoài. Vì vậy, tôi phải tìm cách khái quát hóa những gì bạn vừa nói và thực hiện nó theo cách sao cho tôi không mất kiểm soát dự án (có khá nhiều quyết định). Sẽ cập nhật câu hỏi. Cảm ơn!
Valentin Radu

Vì vậy, để cụ thể hơn, tôi không thể kiểm tra if (isTree)hoặc giữ một isTreevar toàn cầu vì câu chuyện có thể có hoặc không có lựa chọn đó trong đó. Biết ý tôi không? Nó giống như một công cụ lựa chọn sẽ phục vụ nhiều câu chuyện.
Valentin Radu

Ngoài ra, điều này còn có một vấn đề khác, giả sử rằng nếu người dùng quyết định trồng một cây mà chúng ta đặt isTree=true, tuy nhiên, sau đó, anh ta sẽ làm một việc khác, như chiến đấu với một người bạn cùng trường, người quay lại đi và chặt cây của anh ta khi cây vẫn còn trẻ bởi vì anh ấy bị đá đít. Bây giờ, chúng ta có 2 biến ảnh hưởng đến sự tồn tại của cây isTree==true' and didFightBrat == false`. Biết ý tôi không? Và chuỗi có thể đi mãi mãi, sự tồn tại của cây có thể bị ảnh hưởng bởi một số yếu tố không xác định. Biết ý tôi không?
Valentin Radu

Sau đó lưu trữ dữ liệu đó trong một tệp trên đĩa. Bạn sẽ cần tạo hai chương trình con để tải và lưu thông tin, sau đó sử dụng các thường trình đó từ mỗi phần của mã trên cơ sở khi cần thiết.
Randolf Richardson

Câu trả lời:


18

Bạn cũng có thể khái quát hóa hàng đợi thành một biểu đồ chu kỳ có hướng (DAG). Bạn có thể đọc về những điều này trên Wikipedia. Về cơ bản, mỗi nút có thể có một hoặc nhiều nút cha mà nó "phụ thuộc". Chu kỳ không được phép, tức là nếu A phụ thuộc vào B, B không thể phụ thuộc vào A (trực tiếp hoặc thông qua bất kỳ chuỗi gián tiếp nào của các nút khác).

Mỗi nút ở trạng thái "hoạt động" hoặc "không hoạt động" và chỉ được phép hoạt động nếu tất cả các cha mẹ của nó đã hoạt động. Cấu trúc của biểu đồ (có các nút nào ở đó và chúng được kết nối như thế nào) là một phần của dữ liệu trò chơi, nhưng trạng thái hoạt động / không hoạt động là một phần của dữ liệu lưu của người chơi.

Bằng cách đó, bạn có thể mô hình hóa những thứ như: khi bạn trồng cây, bạn đánh dấu một nhiệm vụ "plantTree" là hoạt động; sau đó, sau đó trong trò chơi, một tác vụ khác "treeGrown" đặt tên cho cả "plantTree" và một số nút khác (một phần của câu chuyện) là cha mẹ của nó. Sau đó, "treeGrown" chỉ hoạt động khi người chơi đến điểm đó trong câu chuyện và "plantTree" cũng hoạt động.

Bạn có thể bao gồm các tính năng khác, chẳng hạn như các nút kích hoạt nếu bất kỳ một trong hai cha mẹ của chúng kích hoạt hoặc các nút được kích hoạt bởi một phụ huynh và bị vô hiệu hóa bởi một người khác, v.v. Đó là một khung chung chung để tạo các câu chuyện với nhiều luồng, phụ thuộc lẫn nhau.


Một câu trả lời rất tốt, cảm ơn bạn. Nó thực sự giải quyết các vấn đề khác mà tôi có, như lưu tiến trình của người dùng. Đây là những gì tôi cần.
Valentin Radu

@NathanReed Tại sao điều này không thể theo chu kỳ? Là chu kỳ thường không phải là một tính năng, mà là sản phẩm phụ của thiết kế đồ thị. Tôi sẽ không tạo ra nó với ý định đó. Ví dụ, hãy tưởng tượng nếu bạn muốn cây của bạn nhận ra các mùa. Bản chất chúng là theo chu kỳ và vòng cung câu chuyện của bạn có thể giống hệt nhau tùy thuộc vào các lựa chọn có sẵn trong một mùa.

Nó phải theo chu kỳ vì nếu có một chu kỳ, bạn sẽ vào một vòng lặp vô hạn khi cố gắng tìm hiểu xem một nút trên chu trình có thể hoạt động hay không, bởi vì bạn kiểm tra đệ quy tất cả tổ tiên của nó, bao gồm chính nút đó. Nếu bạn muốn mô hình hóa một cái gì đó giống như các mùa, tôi sẽ không làm điều đó trong bối cảnh của biểu đồ này.
Nathan Reed

@NathanReed Ah, xin lỗi, tôi đã bỏ lỡ phần đệ quy.

3

Từ những gì tôi hiểu, những gì bạn muốn không chỉ là một công cụ quyết định, mà còn là một công cụ quy tắc. Đối với mỗi quyết định, bạn thực hiện một tập hợp các quy tắc được xác định bởi quyết định đó. Việc thực thi các quy tắc đó thường phụ thuộc vào trạng thái của các thực thể nhất định như ví dụ về cây của bạn.

Về cơ bản, khi người chơi của bạn đưa ra quyết định, bạn sẽ tìm kiếm quyết định đó, thực thi các quy tắc và sau đó cung cấp các quyết định có sẵn tiếp theo như bình thường. Tuy nhiên, các quy tắc của bạn rất năng động ở chỗ một số trong số chúng sẽ chỉ thực thi dựa trên các quy tắc khác đã được thực thi.

Một số chi tiết trên Wikipedia .

Từ khi sử dụng quy tắc Công cụ quy tắc của họ (nhấn mạnh là của tôi):

  • Vấn đề chỉ là quá phức tạp đối với mã truyền thống.
  • Vấn đề có thể không phức tạp, nhưng bạn không thể thấy một cách mạnh mẽ để xây dựng nó.
  • Vấn đề là vượt quá bất kỳ giải pháp dựa trên thuật toán rõ ràng.
  • Đó là một vấn đề phức tạp để giải quyết. Không có giải pháp truyền thống rõ ràng hoặc vấn đề không được hiểu đầy đủ.
  • Logic thay đổi thường xuyên
  • Bản thân logic có thể đơn giản nhưng các quy tắc thay đổi khá thường xuyên. Trong nhiều tổ chức, việc phát hành phần mềm rất hiếm và các quy tắc có thể giúp cung cấp "sự nhanh nhẹn" cần thiết và được mong đợi một cách hợp lý an toàn.
  • Các chuyên gia tên miền và các nhà phân tích kinh doanh có sẵn, nhưng không kỹ thuật.
  • Các chuyên gia tên miền thường rất giàu kiến ​​thức về các quy tắc và quy trình kinh doanh. Chúng thường không khoa học, nhưng có thể rất logic. Các quy tắc có thể cho phép họ thể hiện logic theo cách riêng của họ. Tất nhiên, họ vẫn phải suy nghĩ chín chắn và có khả năng suy nghĩ logic. Nhiều người ở các vị trí phi kỹ thuật không được đào tạo về logic chính thức, vì vậy hãy cẩn thận và làm việc với họ. Bằng cách mã hóa kiến ​​thức kinh doanh trong các quy tắc, bạn sẽ thường tiết lộ các lỗ hổng trong cách hiểu các quy tắc và quy trình kinh doanh hiện tại.

Một điều cần lưu ý là đôi khi một công cụ quy tắc được triển khai tốt nhất bằng cách sử dụng một "ngôn ngữ" cụ thể của miền đơn giản hóa, hoặc một cái gì đó như YAML. Tôi sẽ không đề xuất XML.


1

Bạn phải xem xét rằng một sự kiện không hoàn toàn dựa trên quyết định của người dùng. Như bạn đã lưu ý, một số sự kiện phải nối thêm nếu khi một tập hợp các chuỗi quyết định được thực hiện sau đó một cái gì đó khác sẽ xuất hiện (như hai ngày sau).

Những gì tôi nghĩ bạn cần là một cách để mô hình hóa các sự kiện và cách để kích hoạt nó. Mặc dù trường hợp thứ nhất bị ràng buộc nhiều hơn với trường hợp cụ thể của bạn, trường hợp thứ nhất có thể được mô hình hóa bằng máy trạng thái phân cấp (HSM) trực tiếp hoặc gián tiếp kích hoạt các sự kiện của bạn.

Hãy nhớ rằng một bộ máy trạng thái chịu Lời nguyền về chiều mà chỉ được giảm nhẹ bởi một cấu trúc phân cấp. Bạn sẽ sớm hiểu rằng bạn cần mô hình hóa ý nghĩa phức tạp của trạng thái bằng HMS nhưng cũng cung cấp một cách để truy vấn nó.

Trong kịch bản này, bạn có các sự kiện cơ bản (quyết định của người dùng, thời gian, thay đổi thời tiết, v.v.) được xử lý bởi cả HSM và các cuộc gọi lại sự kiện cơ bản. HSM cung cấp một mô hình cho "bộ nhớ" và các cuộc gọi lại cung cấp một cách để mô tả cách sử dụng bộ nhớ đó để tính toán hậu quả của một chuỗi các quyết định / sự kiện bên ngoài.

Bạn cũng có thể kết thúc bằng cách sử dụng một dictonary (hoặc một số cấu trúc bộ sưu tập khác) của HMS, một cho mỗi "khía cạnh" của trạng thái bạn phải tính toán. Một ví dụ có thể là sử dụng một sự kiện HMS liên quan và một cho các quyết định mà các cuộc gọi lại đưa ra để kích hoạt các sự kiện.

Tất cả các cơ sở hạ tầng này phục vụ mục đích bắt chước hành vi của một Dungeon Master con người: anh ta thường ghi lại một hồ sơ tinh thần về tình hình hiện tại (HMS ["bên ngoài"]) do quyết định của người chơi và điều kiện môi trường; khi một cái gì đó xuất hiện, nó có thể đưa ra quyết định bằng cách sử dụng hồ sơ tinh thần của mình và ghi lại một số trạng thái chiến lược nội bộ (HSM ["nội bộ"]) để tránh phản ứng theo cách tương tự nếu tình huống nào đó xảy ra chẳng hạn.

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.