ฉันจะบ้าไปกับ Event Handlers ได้ไหม? ฉันกำลังจะ“ ผิดไป” กับการออกแบบของฉันหรือไม่?


12

ฉันเดาฉันตัดสินใจว่าฉันชอบตัวจัดการเหตุการณ์ ฉันอาจกำลังทุกข์ทรมานเล็กน้อยจากการวิเคราะห์อัมพาต แต่ฉันกังวลเกี่ยวกับการทำให้การออกแบบของฉันยุ่งเหยิงหรือวิ่งไปสู่ผลลัพธ์ที่ไม่คาดฝันอื่น ๆ ต่อการตัดสินใจออกแบบของฉัน

เอ็นจิ้นเกมของฉันทำการเรนเดอร์พื้นฐานโดยใช้กล้องส่ายกล้อง การออกแบบของฉันมีลักษณะเช่นนี้:

SceneHandler

มีรายการคลาสที่ใช้อินเตอร์เฟส SceneListener (ปัจจุบันเป็น Sprites เท่านั้น) โทร render () หนึ่งครั้งต่อหนึ่งขีดและส่ง onCameraUpdate (); ข้อความถึง SceneListeners

InputHandler

โพลอินพุตหนึ่งครั้งต่อหนึ่งขีดและส่งข้อความ "onKeyPressed" ธรรมดาไปยัง InputListeners ฉันมี Camera InputListener ซึ่งเก็บอินสแตนซ์ของ SceneHandler และทริกเกอร์ updateCamera (); เหตุการณ์ขึ้นอยู่กับสิ่งที่ป้อนเข้า

AgentHandler

เรียกการกระทำเริ่มต้นใน Agent (AI) หนึ่งครั้งต่อหนึ่งขีดและจะตรวจสอบสแต็กสำหรับเหตุการณ์ใหม่ใด ๆ ที่ลงทะเบียนโดยส่งไปยังตัวแทนที่เฉพาะเจาะจงตามความจำเป็น

ดังนั้นฉันจึงมีวัตถุสไปรต์ขั้นพื้นฐานที่สามารถเคลื่อนที่ไปรอบ ๆ ฉากและใช้พฤติกรรมการขับขี่แบบพื้นฐานเพื่อเดินทาง ฉันได้รับการตรวจจับการชนกันและนี่คือที่ฉันไม่แน่ใจว่าทิศทางการออกแบบของฉันเป็นไปได้ดี เป็นการดีหรือไม่ที่จะมีตัวจัดการเหตุการณ์ขนาดเล็กจำนวนมาก? ฉันคิดว่าจะเป็นอย่างที่ฉันจะต้องใช้ CollisionHandler บางประเภท

ฉันจะดีกว่านี้ด้วย EntityHandler ที่รวมมากขึ้นซึ่งจัดการ AI อัพเดตการชนกันและการโต้ตอบเอนทิตีอื่น ๆ ในชั้นเดียวหรือไม่ หรือฉันจะต้องใช้ระบบย่อยการจัดการเหตุการณ์ที่แตกต่างกันหลายอย่างซึ่งส่งข้อความถึงกันโดยขึ้นอยู่กับประเภทของเหตุการณ์ ฉันควรเขียน EntityHandler ซึ่งมีหน้าที่รับผิดชอบในการประสานงานตัวจัดการเหตุการณ์ย่อยเหล่านี้ทั้งหมดหรือไม่?

ฉันตระหนักในบางกรณีเช่น InputHandler และ SceneHandler ของฉันนั่นเป็นประเภทเหตุการณ์ที่เฉพาะเจาะจงมาก รหัสเกมส่วนใหญ่ของฉันจะไม่สนใจอินพุตและส่วนใหญ่จะไม่สนใจเกี่ยวกับการอัปเดตที่เกิดขึ้นอย่างแท้จริงในการแสดงผลของฉาก ดังนั้นฉันจึงรู้สึกว่าการแยกระบบเหล่านั้นออกมานั้นมีเหตุผล อย่างไรก็ตามฉันถามคำถามนี้โดยเฉพาะเหตุการณ์ประเภทเกมตรรกะ

คำตอบ:


21

การออกแบบโดยใช้เหตุการณ์เป็นส่วนใหญ่เกี่ยวข้องกับการนำรูปแบบการออกแบบเครื่องปฏิกรณ์ไปใช้

ก่อนที่จะเริ่มออกแบบส่วนประกอบคุณควรพิจารณาถึงข้อ จำกัด ของรูปแบบดังกล่าว (คุณอาจพบข้อมูลมากมายเกี่ยวกับสิ่งนี้)

สิ่งแรกที่สำคัญที่สุดของปัญหาก็คือตัวจัดการต้องส่งคืนอย่างรวดเร็วเนื่องจากทุกอย่างที่ serius บางตัวทำงานบนกรอบงานที่อิงกับ GUI และแอพพลิเคชั่นพื้นฐานจาวาสคริปต์ก็รู้ดี

เมื่อคุณพัฒนาแอพลิเคชันที่มีทุกความซับซ้อนที่ดีที่คุณจะไม่ช้าก็เร็วต้องเผชิญกับบางจัดการที่จะได้งานที่ซับซ้อนที่ต้องใช้เวลา

ในกรณีเหล่านี้คุณสามารถแยกความแตกต่างได้สองสถานการณ์ (ไม่จำเป็นต้องเกิดร่วมกัน):

คอมเพล็กซ์เหตุการณ์ที่เกี่ยวข้องกับความรับผิดชอบและความซับซ้อนของเหตุการณ์ที่ไม่เกี่ยวข้องกับความรับผิดชอบ

ความรับผิดชอบที่เกี่ยวข้องกับเหตุการณ์ที่ซับซ้อน:

ในกรณีแรกคุณรวมความรับผิดชอบมากเกินไปเข้าไปในตัวจัดการส่วนประกอบเดียว : การกระทำมากเกินไปที่จะตอบสนองต่อเหตุการณ์หรือมีการเรียกใช้การซิงโครไนซ์

ในกรณีนี้การแก้ปัญหาคือการแยกตัวจัดการเป็นตัวจัดการที่แตกต่างกัน (ในวัตถุที่แตกต่างกันถ้าจำเป็น) และให้มือจับที่จะยิงเหตุการณ์แทนการโทรโดยตรงรหัสการจัดการ สิ่งนี้จะช่วยให้คุณสามารถจัดการเหตุการณ์ที่มีลำดับความสำคัญสูงกว่าก่อนได้เนื่องจากตัวจัดการหลักของคุณได้ส่งคืนหลังจากผนวกกิจกรรมเข้ากับคิวเหตุการณ์

อีกวิธีหนึ่งคือการให้เอนทิตีภายนอกเริ่มเหตุการณ์และให้ผู้อื่นสมัครหากสนใจ (เหตุการณ์เวลาเป็นตัวอย่างที่น่ารำคาญที่สุดที่คุณสามารถพูดคุยได้)

ความรับผิดชอบที่ไม่เกี่ยวข้องกับเหตุการณ์ที่ซับซ้อน:

กรณีที่สองเกิดขึ้นเมื่อมีความซับซ้อนที่แท้จริงในการดำเนินการหลังจากเหตุการณ์: คุณต้องคำนวณหมายเลขฟีโบนักชีหลังจากเหตุการณ์เช่น

ที่นี่รูปแบบของเครื่องปฏิกรณ์ล้มเหลวโดยทั่วไปคุ้มค่าเพียงเล็กน้อยที่จะแยกอัลกอริธึมการสร้างฟีโบนักชีออกเป็นชิ้นเล็ก ๆ ที่ทำให้เกิดเหตุการณ์เมื่อสิ้นสุดลง

นี่คือวิธีการแก้ปัญหาคือการผสมการออกแบบเกลียวกับเครื่องปฏิกรณ์ข่าวดีก็คือว่าหากความซับซ้อนอยู่ภายใน (ดังนั้นคุณกำลังอ่านส่วนที่ถูกต้อง) มันมีโอกาสมากที่จะเริ่มและด้ายอิสระที่ทำงานและ ที่ต้องการรู้เพียงเล็กน้อยหรือไม่มีเลยเกี่ยวกับส่วนที่เหลือของส่วนประกอบที่เกี่ยวข้องกับเครื่องปฏิกรณ์

เพื่อจัดการกับชนิดของสถานการณ์นี้ผมพบว่าเป็นประโยชน์ที่จะนำมาใช้เป็นคิวงานกว่าสระด้ายที่มีความยืดหยุ่น

เมื่อตัวจัดการต้องเริ่มการดำเนินการที่ยาวนานมันจะสรุปการกระทำนั้นลงในหน่วยงานที่จะใส่ลงในคิวงาน การกระทำที่ห่อหุ้มนี้ต้องมีค่าเฉลี่ยในการทริกเกอร์เหตุการณ์ในเธรดเครื่องปฏิกรณ์ ตัวจัดการคิวงานอาจทำงานในเธรดของตัวเองหรือในเธรดเครื่องปฏิกรณ์และตอบสนองต่อเหตุการณ์ "newJob"

ตัวจัดการคิวงานทำดังต่อไปนี้:

  • มันจัดสรรหน่วยงานให้กับเธรดจากกลุ่มเธรดที่มีความยืดหยุ่นโดยใช้อัลกอริทึม shedule ถ้ากลุ่มสามารถให้หนึ่งเธรด (มีเธรดอิสระหรืออนุญาตการสร้างเธรดใหม่)

  • ฟังพูลตัวเองเพื่อดูว่าหน่วยงานเสร็จสิ้นหรือไม่เพื่อให้สามารถเรียกคืนเธรดเพื่อเรียกใช้งานหน่วยที่ค้างอยู่ได้อีกถ้ามี

การใช้กลไกการยิงเหตุการณ์หน่วยงานอาจทริกเกอร์เหตุการณ์เพื่อแจ้งให้ทราบถึงความสำเร็จสถานะการอัพเดทคำเตือนข้อผิดพลาดหรือเมื่อใดก็ตามที่จำเป็น กลุ่มเธรดที่มีความยืดหยุ่นช่วยให้มั่นใจว่าสามารถใช้ทรัพยากรได้อย่างดีในขณะที่หลีกเลี่ยงเธรดที่ไม่ทำงานเพื่อแขวนระบบทั้งหมด คิวงานให้คุณเลือกประเภทของลำดับความสำคัญที่กำหนดให้กับประเภทของการกระทำที่แตกต่างกันเนื่องจากคุณรู้ว่าพวกเขาจะต้องใช้ทรัพยากรการคำนวณในปริมาณที่สอดคล้องกัน


3
+1 สำหรับความละเอียดถี่ถ้วน ลิงก์เล็กน้อยสำหรับผู้อ่านที่อยากรู้อยากเห็นจะน่ากลัว
sam hocevar

1

ในสถานการณ์ส่วนใหญ่ที่ใช้เหตุการณ์มากกว่าตัวเลือกอื่น ๆ มักจะปรับปรุงความเร็วและการกระจายอำนาจ ฉันคิดว่าถ้าคุณสามารถใช้เหตุการณ์ได้มากมายคุณควรทำ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.