วิธีที่ถูกต้องในการทำให้นามธรรมเป็นตัวควบคุม XBox


12

ฉันมีตัวควบคุม XBox360 ซึ่งฉันต้องการใช้เป็นอินพุตสำหรับแอปพลิเคชัน

สิ่งที่ฉันไม่สามารถทำได้คือวิธีที่ดีที่สุดในการเปิดเผยสิ่งนี้ผ่านทางอินเทอร์เฟซ

ด้านหลังของฉากคลาสที่จัดการกับคอนโทรลเลอร์นั้นขึ้นอยู่กับสถานะของปุ่มสำรวจ

ฉันเริ่มลองลิงค์แล้ว:

Event ButtonPressed() as ButtonEnum

ที่ButtonEnumเป็นButtonRed, ButtonStartฯลฯ ...

ข้อ จำกัด เล็ก ๆ น้อย ๆ ที่สนับสนุนเฉพาะการกดปุ่มไม่ถือ / รูปแบบ (กดสองครั้งเป็นต้น)

แนวคิดต่อไปคือการเปิดเผยสถานะปุ่มให้กับแอพเช่น

Property RedPressed as Boolean
Property StartPressed as Boolean
Property Thumb1XAxis as Double

นี่ยืดหยุ่นมาก แต่จริงๆแล้วมันบังคับให้ทำงานมากเกินไปในแอพและต้องการให้แอพโพล - ฉันต้องการให้มีการขับเคลื่อนกิจกรรมหากเป็นไปได้

ฉันพิจารณาเพิ่มกิจกรรมหลายรายการเช่น:

Event ButtonPressed(Button as ButtonEnum)
Event ButtonPressedTwice(Button as ButtonEnum)
Event ButtonHeldStart(Button as ButtonEnum)
Event ButtonHeldEnd(Button as ButtonEnum)

แต่สิ่งนี้ดูเหมือนจะเป็นเรื่องเล็กน้อยและเป็นความเจ็บปวดที่แท้จริงบนหน้าจอ "ปุ่มผูก"

ใครบางคนช่วยชี้ฉันที่วิธี "ถูกต้อง" เพื่อจัดการอินพุตจากคอนโทรลเลอร์

NB: ฉันกำลังใช้ SlimDX ในคลาสซึ่งใช้อินเทอร์เฟซ ทำให้ฉันอ่านสถานะได้ง่ายมาก ทางเลือกใดที่จะแก้ปัญหาของฉันก็ชื่นชมเช่นกัน

คำตอบ:


21

ไม่มีการแมปที่สมบูรณ์แบบที่ให้คุณเป็นนามธรรมเฉพาะแพลตฟอร์มเพราะเห็นได้ชัดว่าตัวระบุส่วนใหญ่ที่เหมาะสมสำหรับ 360 คอนโทรลเลอร์ผิดสำหรับคอนโทรลเลอร์ PlayStation (A แทน X, B แทน Circle) และแน่นอนว่าคอนโทรลเลอร์ Wii เป็นอีกสิ่งหนึ่งโดยสิ้นเชิง

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

เลเยอร์กลางคือการแมปการควบคุมจริงจากปุ่มจริงไปยังแนวคิดเกม (เช่น A -> Jump) เราเรียกมันว่าแรงกระตุ้นแทนที่จะเป็นปุ่มเพราะมันไม่ได้ถูกผูกไว้กับตัวควบคุมชนิดใดอีกต่อไป อยู่ที่เลเยอร์นี้คุณสามารถทำการแมปตัวควบคุม (ระหว่างการพัฒนาหรือขณะรันไทม์ตามคำสั่งของผู้ใช้) แต่ละแพลตฟอร์มมีการทำแผนที่ของตัวเองของตัวควบคุมแรงกระตุ้นเสมือน คุณทำไม่ได้และไม่ควรพยายามหลีกหนีจากสิ่งนี้ คอนโทรลเลอร์ทุกตัวมีเอกลักษณ์และต้องการการแมปของมันเอง ปุ่มอาจแมปกับแรงกระตุ้นมากกว่าหนึ่ง (ขึ้นอยู่กับโหมดเกม) และมากกว่าหนึ่งปุ่มอาจแมปไปที่แรงกระตุ้นเดียวกัน (เช่น A และ X ทั้งเร่ง, B และ Y ทั้งสองชะลอตัวลง) การทำแผนที่กำหนดทั้งหมดนั้น

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

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


ดูเหมือนว่าวิธีการที่สะอาดและสง่างามมาก ขอบคุณ!
พื้นฐาน

1
ดีมาก. ดีกว่าของฉันมาก: P
Jordaan Mylonas

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

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

@ รวมใจขอบคุณทั้งคู่ - ฉันไม่ได้คิดอย่างนั้น
พื้นฐาน

1

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

ชั้นล่างอาจถูกพิจารณาว่าเป็นระดับ "แบบโพล" และแสดงสถานะปัจจุบันของปุ่ม หนึ่งในอินเตอร์เฟซที่ดังกล่าวก็อาจมี 2 ฟังก์ชั่นGetAnalogState(InputIdentifier)และGetDigitalState(InputIdentifier)ที่InputIdentifierเป็นค่าแจกแจงเป็นตัวแทนที่ปุ่มทริกเกอร์หรือติดคุณตรวจสอบกำลังต่อต้าน (การเรียกใช้ GetAnalogState สำหรับปุ่มจะส่งคืนค่า 1.0 หรือ 0.0 และการเรียกใช้ GetDigitalState สำหรับอะนาล็อกสติ๊กจะกลับเป็นจริงถ้าเกินขีด จำกัด ที่กำหนดไว้ล่วงหน้าหรือเป็นอย่างอื่น)

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

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

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