Cách tốt nhất để quản lý các sự kiện trong trò chơi?


13

Tôi đang làm việc trong một trò chơi mà thỉnh thoảng một số sự kiện trong trò chơi cần phải xảy ra. Một ví dụ đẹp sẽ là một hướng dẫn. Bạn bắt đầu trò chơi và tại một số điểm trong trò chơi sẽ xảy ra một sự kiện:

  • Bạn gặp kẻ thù đầu tiên của mình, trò chơi tạm dừng và bạn nhận được lời giải thích về cách tiêu diệt nó.
  • Bạn đã giết kẻ thù đầu tiên, bạn nhận được một tin nhắn "công việc tốt".
  • Bạn có được một mục mới, một menu với cửa sổ bật lên thống kê các mục.
  • Vân vân.

Trò chơi tôi đang làm là một trò chơi giải đố trong đó các quy tắc trong trò chơi khá giống nhau, do đó có vẻ không hiệu quả khi mã hóa tất cả các sự kiện này ở các cấp độ riêng biệt.

Tôi có nên xác định bằng cách nào đó các sự kiện này trong một nguồn bên ngoài, như XML không? Sau đó viết một trình thông dịch đọc ra XML và đặt các yêu cầu sự kiện cho cấp độ? Tôi không chắc làm thế nào tôi có thể xác định một sự kiện sẽ xảy ra khi bạn giết hai kẻ thù chẳng hạn.

Nói rõ hơn, tôi không tìm kiếm ngôn ngữ lập trình hay ngôn ngữ kịch bản tốt nhất để làm việc này, mà hơn thế nữa là phương pháp tốt nhất để xử lý việc này.

Cảm ơn!


Chỉnh sửa: Một ví dụ thứ hai vì câu hỏi của tôi khá khó hiểu:

Vấn đề tôi gặp phải là đặt một số hành động bổ sung trong trò chơi vào một quy trình luôn luôn giống nhau. Giống như một trận chiến RPG, mọi người đều có một lượt, chọn một kỹ năng, v.v. - nó luôn giống nhau. Nhưng chuyện gì sẽ xảy ra nếu tôi muốn hiển thị một đoạn cắt cảnh ở đâu đó ở giữa. Modyfing toàn bộ cấu trúc trò chơi để vượt qua trong một lớp chiến đấu bị thay đổi với đoạn cắt cảnh bao gồm có vẻ rất không hiệu quả. Tôi đang tự hỏi làm thế nào điều này thường được thực hiện.


8
Đừng cố gắng tăng cường quá mức mọi thứ, ví dụ hướng dẫn rất cụ thể và đi kèm với rất nhiều kích hoạt / sự kiện khác nhau. Không có gì sai với mã hóa / kịch bản.
Maik

1
@Maik Nếu bạn đặt nó vào câu trả lời Id +1 thì đơn giản và giải quyết tốt hơn bất kỳ ngày nào.
James

Ví dụ thứ hai của bạn làm cho rõ ràng hơn nhiều rằng một hệ thống nhắn tin trừu tượng sẽ là một chiến thắng lớn. Đối với một hướng dẫn, bạn chỉ có thể mã hóa những thứ khó khăn vì chúng chỉ xảy ra một lần ngay từ đầu, nhưng đối với các sự kiện đang diễn ra có thể xảy ra bất cứ lúc nào trong toàn bộ thời lượng của trò chơi, thì điều đó khác.
jhocking

Vẫn còn một chút mơ hồ, vui lòng liệt kê ít nhất 3 kích hoạt cho 3 đoạn cắt cảnh khác nhau. nói chung rất khó trả lời. Về cơ bản, bạn phải tìm một mô hình chung để hiểu cách thực hiện nó tốt nhất.
Maik

Bạn muốn gì? Bạn muốn tạm dừng các hành động và làm thêm, sau đó bỏ tạm dừng các hành động?
dùng712092

Câu trả lời:


7

Điều này phụ thuộc rất nhiều vào cách các sự kiện được truyền đạt thực sự giữa các đối tượng trong trò chơi của bạn. Ví dụ: nếu bạn đang sử dụng một hệ thống nhắn tin trung tâm thì bạn có thể có một mô-đun hướng dẫn lắng nghe một số tin nhắn nhất định và tạo cửa sổ bật lên hướng dẫn bất cứ khi nào nghe thấy một số tin nhắn nhất định. Sau đó, bạn có thể đặt thông báo nào để nghe, cùng với cửa sổ bật lên sẽ hiển thị, trong tệp XML hoặc nội dung nào đó được phân tích cú pháp bởi mô-đun hướng dẫn. Bằng cách có một đối tượng hướng dẫn riêng biệt theo dõi trạng thái trò chơi và hiển thị cửa sổ bật lên hướng dẫn khi thông báo nội dung trong trò chơi, bạn có thể thay đổi đối tượng hướng dẫn theo ý muốn mà không cần thay đổi bất kỳ điều gì khác về trò chơi của mình. (Đây có phải là mẫu Observer không? Tôi không quen thuộc với tất cả các mẫu thiết kế.)

Nhìn chung, mặc dù nó phụ thuộc vào sự phức tạp của hướng dẫn của bạn nếu nó đáng để lo lắng về điều này. Mã hóa cứng các sự kiện trong mã và / hoặc cấp độ của bạn dường như không phải là vấn đề lớn đối với tôi chỉ với một số ít quảng cáo hướng dẫn. Tôi tò mò chính xác những gì bạn có trong đầu khiến bạn nghĩ nó sẽ không hiệu quả, vì tất cả những gì bạn nên làm mỗi lần kích hoạt chỉ là gửi một thông điệp đến mô-đun hướng dẫn, một cái gì đó như TutorialModule.show ("1st_kill");


Tôi nghĩ vì đây là một trò chơi giải đố, logic của anh ta nằm ở một vị trí cho nhiều cấp độ và do đó, việc kiểm tra xem chúng ta có nên làm một hướng dẫn cho việc này là một cái gì đó tồn tại lâu không. Thành thật mà nói, nếu đó là một trò chơi giải đố, tôi không nghĩ rằng điều này sẽ gây ra một cú hích lớn cho nó ngay cả khi nó không phải là mã đẹp nhất, và vào cuối ngày mã hoạt động trong một trò chơi luôn luôn xuất hiện- Tốt hơn 100% so với mã đẹp mà không bao giờ nhìn thấy ánh sáng trong ngày;)
James

Không bao giờ nghĩ về một cái gì đó giống như mô hình quan sát, âm thanh như một giải pháp tốt đẹp. Tôi sẽ dùng thử, cảm ơn :)
omgnoseat

7

Đây là những hạn chế thiết kế khi tôi hiểu chúng:

  1. Mã trò chơi cốt lõi không quan tâm đến các yêu cầu cấp độ và không nên được kết hợp với mã liên quan đến chúng.

  2. Đồng thời, đó là mã trò chơi cốt lõi để biết khi nào các sự kiện cụ thể đáp ứng các yêu cầu đó xảy ra (nhận một vật phẩm, tiêu diệt kẻ thù, v.v.)

  3. Các cấp độ khác nhau có các bộ yêu cầu khác nhau và những yêu cầu cần được mô tả ở đâu đó.

Với những điều đó, tôi có khả năng sẽ làm một cái gì đó như thế này: Đầu tiên, tạo một lớp đại diện cho cấp độ trò chơi. Nó sẽ gói gọn các yêu cầu cụ thể mà một cấp độ có. Nó có các phương thức có thể được gọi khi các sự kiện trò chơi xảy ra.

Cung cấp mã trò chơi cốt lõi tham chiếu đến đối tượng cấp độ hiện tại. Khi sự kiện gameplay xảy ra, nó sẽ cho mức độ bằng cách gọi phương pháp trên nó: enemyKilled, itemPickedUpvv

Trong nội bộ, Levelcần một vài điều:

  • Nhà nước để theo dõi những sự kiện đã xảy ra. Bằng cách này, nó có thể phân biệt kẻ thù đầu tiên bị giết khỏi những người khác và biết lần đầu tiên bạn nhặt được một vật phẩm nhất định.
  • Một danh sách các LevelRequirementđối tượng mô tả các mục tiêu cụ thể mà bạn cần cho cấp độ đó.

Khi bạn nhập một cấp độ, bạn sẽ tạo một cấp độ Levelphù hợp LevelRequirement, thiết lập mã trò chơi và cung cấp cho cấp độ đó.

Mỗi khi một sự kiện trò chơi xảy ra, trò chơi sẽ chuyển nó đến Level. Đến lượt nó tính toán dữ liệu tổng hợp (tổng số kẻ thù bị giết, kẻ thù thuộc loại đó bị giết, v.v.) Sau đó, nó đi qua các đối tượng yêu cầu của nó, cung cấp cho mỗi người một dữ liệu tổng hợp. Một yêu cầu kiểm tra để xem liệu nó có đáp ứng hay không và nếu có thì sinh ra bất kỳ hành vi kết quả nào là phù hợp (hiển thị văn bản hướng dẫn, v.v.)

LevelRequirement về cơ bản cần hai điều:

  1. Một mô tả của một bài kiểm tra để cho biết nếu yêu cầu đã được đáp ứng. Đây chỉ có thể là một chức năng nếu ngôn ngữ của bạn làm cho điều đó trở nên dễ dàng, nếu không bạn có thể mô hình hóa nó trong dữ liệu. (Tức là có một RequirementTypeenum với những thứ như FIRST_KILLvà sau đó là một người lớn switchbiết cách kiểm tra từng loại.)
  2. Một hành động để thực hiện khi yêu cầu được đáp ứng.

Vẫn còn câu hỏi về những bộ yêu cầu đó được mô tả ở đâu. Bạn có thể làm một cái gì đó như XML hoặc định dạng tệp văn bản khác. Điều đó hữu ích nếu:

  1. Không lập trình viên sẽ được cấp độ tác giả.
  2. Bạn muốn có thể thay đổi yêu cầu mà không cần biên dịch lại và / hoặc khởi động lại.

Nếu không có trường hợp nào xảy ra, có lẽ tôi chỉ cần xây dựng chúng trực tiếp bằng mã. Đơn giản hơn luôn luôn tốt hơn.


3 điểm đầu tiên là một mô tả rất gần về phương pháp tôi đang sử dụng, thật ấn tượng! Vâng, điều tôi đang vật lộn với hầu hết là nơi để mô tả yêu cầu và cách dịch nó sang trò chơi (vì rất có thể nó sẽ là thứ gì đó bên ngoài). Cảm ơn đã giải thích sâu sắc :)
omgnoseat

5

Tôi nghĩ Bạn cần biết cách tạo ra những sự kiện này và phần còn lại của bài viết là về nó, Nếu bạn chỉ muốn lưu trữ những sự kiện này thì hãy sử dụng một số cơ sở dữ liệu quan hệ hoặc giải mã chúng bằng văn bản và sử dụng ngôn ngữ kịch bản (anh ấy sẽ phân tích và đánh giá Bạn). :)

Điều bạn muốn là nhận ra các sự kiện đã xảy ra (1) và sau đó thực hiện một số hành động được yêu cầu bởi các sự kiện này (in thông báo, kiểm tra nhấn phím ...) (2). Bạn cũng muốn làm cho những sự kiện này chỉ xảy ra một lần (3).

Về cơ bản Bạn muốn kiểm tra các điều kiện và sau đó lên lịch một số hành vi.

Cách nhận biết sự kiện (1)

  • Bạn muốn nhận ra các sự kiện như "kẻ thù đầu tiên gặp phải", "vật phẩm mới đạt được"
  • nếu phần chung xảy ra, " kẻ thù gặp phải ", " mục đã đạt được " Bạn kiểm tra phần cụ thể " đầu tiên ...", " mục mới đạt được"

Sự kiện được làm từ gì

Trong cái nhìn tổng quát hơn, mỗi sự kiện như vậy được tạo thành từ:

  • điều kiện tiên quyết , bạn kiểm tra chúng
  • các hành động sẽ được thực hiện khi điều kiện tiên quyết được đáp ứng (nói "" Bạn đã giết kẻ thù đầu tiên! ", nói" "tạo combo bằng cách nhấn nút A và B", nói "nhấn 'enter' để tiếp tục", yêu cầu "nhập")

Làm thế nào để lưu trữ những sự kiện này

Trong một số cấu trúc dữ liệu:

  • có danh sách các điều kiện tiên quyết (chuỗi hoặc mã nếu bạn đang viết nó bằng một số ngôn ngữ cấp cao)
  • có danh sách các hành động (chúng có thể là chuỗi, công cụ Quake sử dụng chuỗi cho các sự kiện)

Bạn cũng có thể lưu trữ nó trong cơ sở dữ liệu quan hệ, mặc dù có vẻ như không cần thiết, nếu bạn muốn làm cho trò chơi này lớn, bạn có thể cần phải tạo một trò chơi.

Sau đó, bạn phải phân tích các chuỗi / điều. Hoặc Bạn có thể sử dụng một số ngôn ngữ kịch bản như Python hoặc LUA hoặc ngôn ngữ như LISP, tất cả chúng đều có thể phân tích cú pháp và thực thi nó cho Bạn. :)

Cách sử dụng các sự kiện này trong vòng lặp trò chơi (2)

Bạn sẽ cần hai cấu trúc dữ liệu này:

  • hàng đợi các sự kiện (các sự kiện dự kiến ​​sẽ được chạy ở đây)
  • hàng đợi hành động (hành động theo lịch trình, sự kiện ngụ ý hành động nào được thực hiện)

Thuật toán:

  • Nếu bạn nhận ra một số sự kiện của điều kiện tiên quyết được đáp ứng Bạn đưa anh ta vào hàng đợi sự kiện
  • (3) Sau đó, bạn nên đảm bảo sự kiện này chỉ xảy ra một lần nếu bạn muốn :) (ví dụ với mảng boolean has_this_event_happened ["kẻ thù đầu tiên gặp phải"])
  • (nếu hàng đợi hành động trống, sau đó) Nếu có sự kiện trong hàng đợi sự kiện Bạn đặt hành động của anh ấy vào hàng đợi hành động và xóa anh ta khỏi hàng đợi sự kiện
  • Nếu có hành động trong hàng đợi hành động Bạn bắt đầu thực hiện những gì được yêu cầu bởi nó
  • Nếu hành động đó được thực hiện Bạn xóa nó khỏi hàng đợi hành động

Cách thực hiện những hành động này (2)

Bạn lập danh sách các đối tượng có chức năng "cập nhật". Chúng đôi khi được gọi là các thực thể (trong công cụ Quake) hoặc các tác nhân (trong công cụ Unreal).

  1. Bạn bắt đầu những đối tượng này khi chúng được yêu cầu bắt đầu trong hàng đợi hành động.
  2. những đối tượng này có thể được sử dụng cho những thứ khác như một số bộ định thời khác. Trong Quake, các thực thể này được sử dụng cho toàn bộ logic trò chơi, tôi khuyên bạn nên đọc một số tài liệu về nó .

Hành động "nói gì đó"

  1. Bạn in một cái gì đó trên màn hình
  2. Bạn muốn thông báo này xuất hiện trong vài giây
  3. trong "cập nhật":
    • thực hiện biến remove_me_after và giảm nó theo thời gian đã qua
    • khi biến là 0 Bạn xóa hành động này khỏi hàng đợi hành động
    • Bạn cũng xóa đối tượng này (hoặc lên lịch để xóa nó ...)

Hành động "yêu cầu khóa"

  1. Nó phụ thuộc vào cách bạn muốn thực hiện nó, nhưng tôi nghĩ rằng Bạn tạo một tin nhắn
  2. trong "cập nhật" ":
    • Bạn chỉ cần kiểm tra sự kiện nhấn phím mong muốn
    • Bạn có thể cần một số mảng / hàng đợi để tổ chức các sự kiện nhấn phím
    • sau đó Bạn có thể xóa nó khỏi hàng đợi hành động và xóa đối tượng

Phương pháp nào để học


-1 đúng, hoặc anh ta chỉ gọi một chức năng, nghiêm túc, OP chỉ muốn một hộp thông báo khi một điều kiện nhất định được đáp ứng
Maik Semder

Đó là một bài viết rất hay, nhưng không chính xác những gì tôi đang tìm kiếm. Tôi đã có một thời gian khó khăn để giải thích những gì tôi muốn. Tôi đã thêm một lời giải thích thứ hai: Vấn đề tôi gặp phải là đưa một số hành động bổ sung vào trò chơi theo một quy trình luôn luôn khá giống nhau. Giống như một trận chiến RPG, mọi người đều có một lượt, chọn một kỹ năng, v.v. - nó luôn giống nhau. Nhưng chuyện gì sẽ xảy ra nếu tôi có thể hiển thị một đoạn cắt cảnh ở đâu đó ở giữa. Modyfing toàn bộ cấu trúc trò chơi để vượt qua trong một lớp chiến đấu thay đổi với cutene bao gồm có vẻ rất không hiệu quả. Tôi đang tự hỏi làm thế nào điều này thường được thực hiện?
omgnoseat
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.