Tôi nên xem xét gì khi thiết kế Hệ thống quản lý sự kiện?


9

Tôi đã làm quen với các nguyên tắc cơ bản của một công cụ trò chơi Java và tôi đã đạt đến điểm mà tôi đã sẵn sàng để thêm vào một hệ thống Trình quản lý sự kiện.

Về lý thuyết , tôi biết, Trình quản lý sự kiện nên làm gì: cho phép các đối tượng "đăng ký" cho một số sự kiện nhất định và bất cứ khi nào Trình quản lý sự kiện được thông báo về một sự kiện, hãy phát sự kiện đến người nghe "đã đăng ký". Những gì tôi đang bối rối là làm thế nào để bắt đầu thực hiện nó.

Tôi chưa thể tìm thấy bất cứ điều gì, trực tuyến, về việc triển khai một hệ thống sự kiện từ đầu, vì vậy tôi đang tìm kiếm đầu vào về những thực tiễn tốt nhất trong trường hợp này - những gì tôi nênkhông nên làm.

Chẳng hạn, có thực sự cần thiết cho mỗi đối tượng trò chơi của tôi để có một EventManagertrường không? Vì tất cả các đối tượng trò chơi của tôi thừa hưởng từ một lớp cha duy nhất, trừu tượng, tôi nghĩ rằng tôi có thể sử dụng một tham chiếu tĩnh để chỉ có một phiên bản của Trình quản lý sự kiện, được chia sẻ giữa tất cả các đối tượng trò chơi. Tôi làm một cái gì đó tương tự, với Applet, mà tôi sử dụng để kết xuất từng đối tượng.

Tôi cho rằng tôi phải duy trì một bộ sưu tập nào đó cho mỗi sự kiện được đăng ký có thể - thêm và xóa các đối tượng trò chơi khỏi danh sách, nếu cần. Tôi nghĩ rằng có thể tạo một hàng các sự kiện cần được phát, trong trường hợp đó tôi chỉ cần thêm "EventManager.Update ()" vào vòng lặp trò chơi chính và có Update()phương thức phát các sự kiện xảy ra ở cuối của từng khung. Cuối cùng, mỗi đối tượng sẽ có một HandleEvent(Event e)phương thức, sau đó họ có thể phân tích cú pháp và trả lời một cách thích hợp.


Điều này nghe có vẻ là hướng thích hợp để thực hiện một hệ thống như vậy, hay tôi đang lạc lối và / hoặc thiếu một cái gì đó khá rõ ràng?


2
gamedev.stackexchange.com/questions/7718/ Khăn Đây là một Q / AI được đưa ra trước đây có thể giúp bạn bắt đầu.
James

@James Ah - có vẻ như một liên kết tốt. Cảm ơn! Tôi nghĩ rằng tôi đã bỏ lỡ điều đó, sớm hơn.
Raven Dreamer

4
Một số gợi ý bổ sung: quyết định liệu một số sự kiện có thực sự có hiệu lực ngay lập tức thay vì ở cuối khung hay không, đặc biệt nếu một trình xử lý sự kiện kích hoạt các sự kiện bổ sung; nghĩ những gì xảy ra khi bạn nhận được các vòng lặp sự kiện; nếu bạn đi với hàng đợi, có thể bạn sẽ cần một hệ thống ưu tiên hoặc một cách để bỏ qua hàng đợi.
sam hocevar

Câu trả lời:


6

Điều này có thể đơn giản như bạn muốn.

for each object in the subscriber list:
    object.notify(this event) // (or 'HandleEvent' if you prefer)

Đừng cố gắng và tìm ra những gì một người quản lý sự kiện 'nên' làm - hãy tìm ra những gì bạn cần nó để làm. Phần còn lại nên làm theo từ đó, hoặc ít nhất, nên đề xuất một số câu hỏi cụ thể hơn.


3
+1 cho "Đừng thử và tìm ra những gì X 'nên' làm - hãy tìm ra những gì bạn cần nó để làm." Trên thực tế, đừng thêm một trình quản lý sự kiện nào cho đến khi bạn cảm thấy như bạn cần một số cách tách biệt nhưng chưa tập trung để gọi các chức năng.

@JoeWreschnig Trời ơi có =) "hãy tìm ra những gì bạn cần làm" Đây là một trong 3 lời khuyên hàng đầu mà bất kỳ nhà phát triển nào cũng nên thuộc nằm lòng.
Patrick Hughes

Lúc đầu, tôi muốn không đồng ý với câu thứ hai của bạn về việc không thêm trình quản lý sự kiện bởi vì hầu hết các trò chơi có thể được hưởng lợi từ cách gọi chức năng tách rời nhưng tập trung, nhưng sau đó tôi nghĩ có bao nhiêu trò chơi nhỏ mà tôi đã làm mà không làm có bất kỳ loại quản lý sự kiện. vì vậy, yeah
jhocking

3

Ba phương thức thiết yếu mà hệ thống sự kiện cần là phương thức addListener (), phương thức removeListener () và phương thức để pháiEvent (). Đó là, một đối tượng phương thức sử dụng để đăng ký một sự kiện, một đối tượng phương thức sử dụng để hủy đăng ký và một phương thức để thực sự phát một sự kiện tới tất cả người nghe. Mọi thứ khác đều hấp dẫn.

Như bạn lưu ý, chắc chắn bạn sẽ cần một số loại cấu trúc dữ liệu để theo dõi những người nghe đã đăng ký. Cách tiếp cận đơn giản nhất sẽ là một mảng kết hợp (Từ điển hoặc Đối tượng trong JavaScript) liên kết một vectơ (hoặc đơn giản là một mảng tùy thuộc vào ngôn ngữ) với một sự kiện. Vector đó là một danh sách của tất cả các thính giả đã đăng ký; thêm người nghe vào danh sách hoặc loại bỏ chúng trong các phương thức add / removeListener ().

Để phát một sự kiện trong ClarkEvent (), nó có thể đơn giản như lặp qua vectơ. Bạn có thể thêm sự phức tạp hơn vào việc gửi đi bằng cách sắp xếp mức độ ưu tiên của các sự kiện hoặc bất cứ điều gì, nhưng đừng lo lắng về điều đó cho đến khi bạn cần nó. Trong nhiều trường hợp bạn sẽ không cần nó.

Có một chút sắc thái để gửiEvent () khi bạn xem xét dữ liệu nào sẽ truyền cùng với sự kiện. Ở cấp độ cơ bản nhất, bạn có thể không vượt qua bất kỳ dữ liệu bổ sung nào; tất cả người nghe phải biết là một sự kiện đã xảy ra. Tuy nhiên, hầu hết các sự kiện đều có dữ liệu bổ sung đi kèm với chúng (ví dụ: nơi sự kiện đã xảy ra) để bạn muốn có ClarkEvent () chấp nhận và chuyển qua một số tham số.

Chẳng hạn, có thực sự cần thiết cho mỗi GameObject của tôi để có trường "EventManagner" không? Vì tất cả các GameObject của tôi thừa hưởng từ một lớp cha duy nhất, trừu tượng, tôi nghĩ rằng tôi có thể sử dụng một tham chiếu tĩnh để chỉ có một phiên bản của Trình quản lý sự kiện, được chia sẻ giữa tất cả các đối tượng trò chơi.

Có nhiều cách để cung cấp cho tất cả các đối tượng trò chơi của bạn tham chiếu đến lớp EventManager. Một tài liệu tham khảo tĩnh chắc chắn là một cách; khác là với một Singleton. Tuy nhiên, cả hai cách tiếp cận này đều không linh hoạt, do đó, hầu hết mọi người ở đây đều khuyên bạn nên sử dụng công cụ định vị dịch vụ hoặc tiêm phụ thuộc. Tôi đã thực hiện tiêm phụ thuộc; điều đó có nghĩa là một trường EventManager riêng cho từng đối tượng, đó là điều bạn dường như muốn tránh, nhưng tôi không chắc tại sao đó lại là một vấn đề. Nó không giống như có rất nhiều chi phí từ việc lưu trữ một loạt các con trỏ.


yeah, lần đầu tiên tôi thực sự nắm bắt và thực hiện tiêm phụ thuộc là cho một đối tượng EventDispatcher. Khi tôi đã có được điều đó dưới vành đai của mình, tôi đã rất muốn tái cấu trúc nhiều thứ với mô hình đó.
jhocking

0

TUYÊN BỐ TỪ CHỐI

Tôi không phải là lập trình viên Java nhưng tôi đã viết một bài viết giải thích cách tạo một hệ thống sự kiện trong C89, một trong những ngôn ngữ dễ nhất (IMHO), hãy kiểm tra nó

https://prdeving.wordpress.com/2017/04/03/event-driven-programming-with-c-89/

Những điều cơ bản của xử lý sự kiện là khá đơn giản.

  • đăng ký một sự kiện với một cuộc gọi lại
  • sự kiện kích hoạt
  • vòng qua người nghe để xem có khớp không
  • xử lý lửa nếu tìm thấy
  • nói lại

Biết điều này (nhưng không biết cách triển khai nó trong Java), thật dễ hiểu khi bạn cần một số trình xử lý (các hàm để xử lý các sự kiện) và thêm chúng vào một mảng (với các con trỏ, trong C) được ghép với một tên sự kiện. Khi bạn kích hoạt một sự kiện, bạn lưu trữ tên sự kiện được kích hoạt và nó là đối số trong một ngăn xếp, đây được gọi là nhóm sự kiện.

Sau đó, bạn có một thông báo sự kiện (một vòng lặp đơn giản), người sẽ đưa ra sự kiện đầu tiên trong ngăn xếp đó, cố gắng tìm một trình xử lý cho nó và nếu có, hãy chạy nó với các thông số.

Tất nhiên, thông báo sự kiện này có thể được kích hoạt bất cứ khi nào bạn muốn, ví dụ một lần trên mỗi khung sau khi bạn gọi Update()hàm của mình .


-2

Đối với trường EventManager, sử dụng biến tĩnh. Một Singleton cho EventManager cũng là một ý tưởng tuyệt vời.

Cách tiếp cận của bạn nghe có vẻ tốt, nhưng đừng quên làm cho nó an toàn.

Thật tốt khi thực hiện các Sự kiện IO trước hoặc sau "GameEvent", vì vậy trong một khung hình, mọi "GameEvent" đều có cùng một dữ liệu.


"Lưu chủ đề"? Hmmm
U62

-1 cho đề xuất singleton hoàn toàn không cần thiết và không chính đáng.
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.